test_extcall.py revision 1a7aab70d1f56b63ba6798db1cafe0a61cc3da15
1from UserList import UserList
2from test_support import TestFailed
3
4def f(*a, **k):
5    print a, k
6
7def g(x, *y, **z):
8    print x, y, z
9
10def h(j=1, a=2, h=3):
11    print j, a, h
12
13f()
14f(1)
15f(1, 2)
16f(1, 2, 3)
17
18f(1, 2, 3, *(4, 5))
19f(1, 2, 3, *[4, 5])
20f(1, 2, 3, *UserList([4, 5]))
21f(1, 2, 3, **{'a':4, 'b':5})
22f(1, 2, 3, *(4, 5), **{'a':6, 'b':7})
23f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b':9})
24
25try:
26    g()
27except TypeError, err:
28    print "TypeError:", err
29else:
30    print "should raise TypeError: not enough arguments; expected 1, got 0"
31
32try:
33    g(*())
34except TypeError, err:
35    print "TypeError:", err
36else:
37    print "should raise TypeError: not enough arguments; expected 1, got 0"
38
39try:
40    g(*(), **{})
41except TypeError, err:
42    print "TypeError:", err
43else:
44    print "should raise TypeError: not enough arguments; expected 1, got 0"
45
46g(1)
47g(1, 2)
48g(1, 2, 3)
49g(1, 2, 3, *(4, 5))
50class Nothing: pass
51try:
52    g(*Nothing())
53except AttributeError, attr:
54    pass
55else:
56    print "should raise AttributeError: __len__"
57
58class Nothing:
59    def __len__(self):
60        return 5
61try:
62    g(*Nothing())
63except AttributeError, attr:
64    pass
65else:
66    print "should raise AttributeError: __getitem__"
67
68class Nothing:
69    def __len__(self):
70        return 5
71    def __getitem__(self, i):
72        if i < 3:
73            return i
74        else:
75            raise IndexError, i
76g(*Nothing())
77
78# make sure the function call doesn't stomp on the dictionary?
79d = {'a': 1, 'b': 2, 'c': 3}
80d2 = d.copy()
81assert d == d2
82g(1, d=4, **d)
83print d
84print d2
85assert d == d2, "function call modified dictionary"
86
87# what about willful misconduct?
88def saboteur(**kw):
89    kw['x'] = locals() # yields a cyclic kw
90    return kw
91d = {}
92kw = saboteur(a=1, **d)
93assert d == {}
94# break the cycle
95del kw['x']
96
97try:
98    g(1, 2, 3, **{'x':4, 'y':5})
99except TypeError, err:
100    print err
101else:
102    print "should raise TypeError: keyword parameter redefined"
103
104try:
105    g(1, 2, 3, a=4, b=5, *(6, 7), **{'a':8, 'b':9})
106except TypeError, err:
107    print err
108else:
109    print "should raise TypeError: keyword parameter redefined"
110
111try:
112    f(**{1:2})
113except TypeError, err:
114    print err
115else:
116    print "should raise TypeError: keywords must be strings"
117
118try:
119    h(**{'e': 2})
120except TypeError, err:
121    print err
122else:
123    print "should raise TypeError: unexpected keyword argument: e"
124
125try:
126    h(*h)
127except TypeError, err:
128    print err
129else:
130    print "should raise TypeError: * argument must be a tuple"
131
132try:
133    h(**h)
134except TypeError, err:
135    print err
136else:
137    print "should raise TypeError: ** argument must be a dictionary"
138
139def f2(*a, **b):
140    return a, b
141
142d = {}
143for i in range(512):
144    key = 'k%d' % i
145    d[key] = i
146a, b = f2(1, *(2, 3), **d)
147print len(a), len(b), b == d
148
149class Foo:
150    def method(self, arg1, arg2):
151        return arg1 + arg2
152
153x = Foo()
154print Foo.method(*(x, 1, 2))
155print Foo.method(x, *(1, 2))
156try:
157    print Foo.method(*(1, 2, 3))
158except TypeError, err:
159    print err
160try:
161    print Foo.method(1, *(2, 3))
162except TypeError, err:
163    print err
164
165# A PyCFunction that takes only positional parameters should allow an
166# empty keyword dictionary to pass without a complaint, but raise a
167# TypeError if the dictionary is non-empty.
168id(1, **{})
169try:
170    id(1, **{"foo": 1})
171except TypeError:
172    pass
173else:
174    raise TestFailed, 'expected TypeError; no exception raised'
175