test_extcall.py revision 8036c836305f9770d6b242ccd504b543476058ff
1from test.test_support import verify, verbose, TestFailed, sortdict
2from UserList import UserList
3
4def e(a, b):
5    print a, b
6
7def f(*a, **k):
8    print a, sortdict(k)
9
10def g(x, *y, **z):
11    print x, y, sortdict(z)
12
13def h(j=1, a=2, h=3):
14    print j, a, h
15
16f()
17f(1)
18f(1, 2)
19f(1, 2, 3)
20
21f(1, 2, 3, *(4, 5))
22f(1, 2, 3, *[4, 5])
23f(1, 2, 3, *UserList([4, 5]))
24f(1, 2, 3, **{'a':4, 'b':5})
25f(1, 2, 3, *(4, 5), **{'a':6, 'b':7})
26f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b':9})
27
28# Verify clearing of SF bug #733667
29try:
30    e(c=3)
31except TypeError:
32    pass
33else:
34    print "should raise TypeError: e() got an unexpected keyword argument 'c'"
35
36try:
37    g()
38except TypeError, err:
39    print "TypeError:", err
40else:
41    print "should raise TypeError: not enough arguments; expected 1, got 0"
42
43try:
44    g(*())
45except TypeError, err:
46    print "TypeError:", err
47else:
48    print "should raise TypeError: not enough arguments; expected 1, got 0"
49
50try:
51    g(*(), **{})
52except TypeError, err:
53    print "TypeError:", err
54else:
55    print "should raise TypeError: not enough arguments; expected 1, got 0"
56
57g(1)
58g(1, 2)
59g(1, 2, 3)
60g(1, 2, 3, *(4, 5))
61class Nothing: pass
62try:
63    g(*Nothing())
64except TypeError, attr:
65    pass
66else:
67    print "should raise TypeError"
68
69class Nothing:
70    def __len__(self):
71        return 5
72try:
73    g(*Nothing())
74except TypeError, attr:
75    pass
76else:
77    print "should raise TypeError"
78
79class Nothing:
80    def __len__(self):
81        return 5
82    def __getitem__(self, i):
83        if i < 3:
84            return i
85        else:
86            raise IndexError, i
87g(*Nothing())
88
89class Nothing:
90    def __init__(self):
91        self.c = 0
92    def __iter__(self):
93        return self
94try:
95    g(*Nothing())
96except TypeError, attr:
97    pass
98else:
99    print "should raise TypeError"
100
101class Nothing:
102    def __init__(self):
103        self.c = 0
104    def __iter__(self):
105        return self
106    def next(self):
107        if self.c == 4:
108            raise StopIteration
109        c = self.c
110        self.c += 1
111        return c
112g(*Nothing())
113
114# make sure the function call doesn't stomp on the dictionary?
115d = {'a': 1, 'b': 2, 'c': 3}
116d2 = d.copy()
117verify(d == d2)
118g(1, d=4, **d)
119print sortdict(d)
120print sortdict(d2)
121verify(d == d2, "function call modified dictionary")
122
123# what about willful misconduct?
124def saboteur(**kw):
125    kw['x'] = locals() # yields a cyclic kw
126    return kw
127d = {}
128kw = saboteur(a=1, **d)
129verify(d == {})
130# break the cycle
131del kw['x']
132
133try:
134    g(1, 2, 3, **{'x':4, 'y':5})
135except TypeError, err:
136    print err
137else:
138    print "should raise TypeError: keyword parameter redefined"
139
140try:
141    g(1, 2, 3, a=4, b=5, *(6, 7), **{'a':8, 'b':9})
142except TypeError, err:
143    print err
144else:
145    print "should raise TypeError: keyword parameter redefined"
146
147try:
148    f(**{1:2})
149except TypeError, err:
150    print err
151else:
152    print "should raise TypeError: keywords must be strings"
153
154try:
155    h(**{'e': 2})
156except TypeError, err:
157    print err
158else:
159    print "should raise TypeError: unexpected keyword argument: e"
160
161try:
162    h(*h)
163except TypeError, err:
164    print err
165else:
166    print "should raise TypeError: * argument must be a tuple"
167
168try:
169    dir(*h)
170except TypeError, err:
171    print err
172else:
173    print "should raise TypeError: * argument must be a tuple"
174
175try:
176    None(*h)
177except TypeError, err:
178    print err
179else:
180    print "should raise TypeError: * argument must be a tuple"
181
182try:
183    h(**h)
184except TypeError, err:
185    print err
186else:
187    print "should raise TypeError: ** argument must be a dictionary"
188
189try:
190    dir(**h)
191except TypeError, err:
192    print err
193else:
194    print "should raise TypeError: ** argument must be a dictionary"
195
196try:
197    None(**h)
198except TypeError, err:
199    print err
200else:
201    print "should raise TypeError: ** argument must be a dictionary"
202
203try:
204    dir(b=1,**{'b':1})
205except TypeError, err:
206    print err
207else:
208    print "should raise TypeError: dir() got multiple values for keyword argument 'b'"
209
210def f2(*a, **b):
211    return a, b
212
213d = {}
214for i in range(512):
215    key = 'k%d' % i
216    d[key] = i
217a, b = f2(1, *(2, 3), **d)
218print len(a), len(b), b == d
219
220class Foo:
221    def method(self, arg1, arg2):
222        return arg1 + arg2
223
224x = Foo()
225print Foo.method(*(x, 1, 2))
226print Foo.method(x, *(1, 2))
227try:
228    print Foo.method(*(1, 2, 3))
229except TypeError, err:
230    pass
231else:
232    print 'expected a TypeError for unbound method call'
233try:
234    print Foo.method(1, *(2, 3))
235except TypeError, err:
236    pass
237else:
238    print 'expected a TypeError for unbound method call'
239
240# A PyCFunction that takes only positional parameters should allow an
241# empty keyword dictionary to pass without a complaint, but raise a
242# TypeError if the dictionary is non-empty.
243id(1, **{})
244try:
245    id(1, **{"foo": 1})
246except TypeError:
247    pass
248else:
249    raise TestFailed, 'expected TypeError; no exception raised'
250
251a, b, d, e, v, k = 'A', 'B', 'D', 'E', 'V', 'K'
252funcs = []
253maxargs = {}
254for args in ['', 'a', 'ab']:
255    for defargs in ['', 'd', 'de']:
256        for vararg in ['', 'v']:
257            for kwarg in ['', 'k']:
258                name = 'z' + args + defargs + vararg + kwarg
259                arglist = list(args) + map(
260                    lambda x: '%s="%s"' % (x, x), defargs)
261                if vararg: arglist.append('*' + vararg)
262                if kwarg: arglist.append('**' + kwarg)
263                decl = (('def %s(%s): print "ok %s", a, b, d, e, v, ' +
264                         'type(k) is type ("") and k or sortdict(k)')
265                         % (name, ', '.join(arglist), name))
266                exec(decl)
267                func = eval(name)
268                funcs.append(func)
269                maxargs[func] = len(args + defargs)
270
271for name in ['za', 'zade', 'zabk', 'zabdv', 'zabdevk']:
272    func = eval(name)
273    for args in [(), (1, 2), (1, 2, 3, 4, 5)]:
274        for kwargs in ['', 'a', 'd', 'ad', 'abde']:
275            kwdict = {}
276            for k in kwargs: kwdict[k] = k + k
277            print func.func_name, args, sortdict(kwdict), '->',
278            try: func(*args, **kwdict)
279            except TypeError, err: print err
280