1 | # -*- coding: utf-8 -*-
|
---|
2 |
|
---|
3 | """Doctest for method/function calls.
|
---|
4 |
|
---|
5 | We're going the use these types for extra testing
|
---|
6 |
|
---|
7 | >>> from UserList import UserList
|
---|
8 | >>> from UserDict import UserDict
|
---|
9 |
|
---|
10 | We're defining four helper functions
|
---|
11 |
|
---|
12 | >>> def e(a,b):
|
---|
13 | ... print a, b
|
---|
14 |
|
---|
15 | >>> def f(*a, **k):
|
---|
16 | ... print a, test_support.sortdict(k)
|
---|
17 |
|
---|
18 | >>> def g(x, *y, **z):
|
---|
19 | ... print x, y, test_support.sortdict(z)
|
---|
20 |
|
---|
21 | >>> def h(j=1, a=2, h=3):
|
---|
22 | ... print j, a, h
|
---|
23 |
|
---|
24 | Argument list examples
|
---|
25 |
|
---|
26 | >>> f()
|
---|
27 | () {}
|
---|
28 | >>> f(1)
|
---|
29 | (1,) {}
|
---|
30 | >>> f(1, 2)
|
---|
31 | (1, 2) {}
|
---|
32 | >>> f(1, 2, 3)
|
---|
33 | (1, 2, 3) {}
|
---|
34 | >>> f(1, 2, 3, *(4, 5))
|
---|
35 | (1, 2, 3, 4, 5) {}
|
---|
36 | >>> f(1, 2, 3, *[4, 5])
|
---|
37 | (1, 2, 3, 4, 5) {}
|
---|
38 | >>> f(1, 2, 3, *UserList([4, 5]))
|
---|
39 | (1, 2, 3, 4, 5) {}
|
---|
40 |
|
---|
41 | Here we add keyword arguments
|
---|
42 |
|
---|
43 | >>> f(1, 2, 3, **{'a':4, 'b':5})
|
---|
44 | (1, 2, 3) {'a': 4, 'b': 5}
|
---|
45 | >>> f(1, 2, 3, *[4, 5], **{'a':6, 'b':7})
|
---|
46 | (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
|
---|
47 | >>> f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9})
|
---|
48 | (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
|
---|
49 |
|
---|
50 | >>> f(1, 2, 3, **UserDict(a=4, b=5))
|
---|
51 | (1, 2, 3) {'a': 4, 'b': 5}
|
---|
52 | >>> f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7))
|
---|
53 | (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
|
---|
54 | >>> f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9))
|
---|
55 | (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
|
---|
56 |
|
---|
57 | Examples with invalid arguments (TypeErrors). We're also testing the function
|
---|
58 | names in the exception messages.
|
---|
59 |
|
---|
60 | Verify clearing of SF bug #733667
|
---|
61 |
|
---|
62 | >>> e(c=4)
|
---|
63 | Traceback (most recent call last):
|
---|
64 | ...
|
---|
65 | TypeError: e() got an unexpected keyword argument 'c'
|
---|
66 |
|
---|
67 | >>> g()
|
---|
68 | Traceback (most recent call last):
|
---|
69 | ...
|
---|
70 | TypeError: g() takes at least 1 argument (0 given)
|
---|
71 |
|
---|
72 | >>> g(*())
|
---|
73 | Traceback (most recent call last):
|
---|
74 | ...
|
---|
75 | TypeError: g() takes at least 1 argument (0 given)
|
---|
76 |
|
---|
77 | >>> g(*(), **{})
|
---|
78 | Traceback (most recent call last):
|
---|
79 | ...
|
---|
80 | TypeError: g() takes at least 1 argument (0 given)
|
---|
81 |
|
---|
82 | >>> g(1)
|
---|
83 | 1 () {}
|
---|
84 | >>> g(1, 2)
|
---|
85 | 1 (2,) {}
|
---|
86 | >>> g(1, 2, 3)
|
---|
87 | 1 (2, 3) {}
|
---|
88 | >>> g(1, 2, 3, *(4, 5))
|
---|
89 | 1 (2, 3, 4, 5) {}
|
---|
90 |
|
---|
91 | >>> class Nothing: pass
|
---|
92 | ...
|
---|
93 | >>> g(*Nothing())
|
---|
94 | Traceback (most recent call last):
|
---|
95 | ...
|
---|
96 | TypeError: g() argument after * must be a sequence, not instance
|
---|
97 |
|
---|
98 | >>> class Nothing:
|
---|
99 | ... def __len__(self): return 5
|
---|
100 | ...
|
---|
101 |
|
---|
102 | >>> g(*Nothing())
|
---|
103 | Traceback (most recent call last):
|
---|
104 | ...
|
---|
105 | TypeError: g() argument after * must be a sequence, not instance
|
---|
106 |
|
---|
107 | >>> class Nothing():
|
---|
108 | ... def __len__(self): return 5
|
---|
109 | ... def __getitem__(self, i):
|
---|
110 | ... if i<3: return i
|
---|
111 | ... else: raise IndexError(i)
|
---|
112 | ...
|
---|
113 |
|
---|
114 | >>> g(*Nothing())
|
---|
115 | 0 (1, 2) {}
|
---|
116 |
|
---|
117 | >>> class Nothing:
|
---|
118 | ... def __init__(self): self.c = 0
|
---|
119 | ... def __iter__(self): return self
|
---|
120 | ... def next(self):
|
---|
121 | ... if self.c == 4:
|
---|
122 | ... raise StopIteration
|
---|
123 | ... c = self.c
|
---|
124 | ... self.c += 1
|
---|
125 | ... return c
|
---|
126 | ...
|
---|
127 |
|
---|
128 | >>> g(*Nothing())
|
---|
129 | 0 (1, 2, 3) {}
|
---|
130 |
|
---|
131 | Make sure that the function doesn't stomp the dictionary
|
---|
132 |
|
---|
133 | >>> d = {'a': 1, 'b': 2, 'c': 3}
|
---|
134 | >>> d2 = d.copy()
|
---|
135 | >>> g(1, d=4, **d)
|
---|
136 | 1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4}
|
---|
137 | >>> d == d2
|
---|
138 | True
|
---|
139 |
|
---|
140 | What about willful misconduct?
|
---|
141 |
|
---|
142 | >>> def saboteur(**kw):
|
---|
143 | ... kw['x'] = 'm'
|
---|
144 | ... return kw
|
---|
145 |
|
---|
146 | >>> d = {}
|
---|
147 | >>> kw = saboteur(a=1, **d)
|
---|
148 | >>> d
|
---|
149 | {}
|
---|
150 |
|
---|
151 |
|
---|
152 | >>> g(1, 2, 3, **{'x': 4, 'y': 5})
|
---|
153 | Traceback (most recent call last):
|
---|
154 | ...
|
---|
155 | TypeError: g() got multiple values for keyword argument 'x'
|
---|
156 |
|
---|
157 | >>> f(**{1:2})
|
---|
158 | Traceback (most recent call last):
|
---|
159 | ...
|
---|
160 | TypeError: f() keywords must be strings
|
---|
161 |
|
---|
162 | >>> h(**{'e': 2})
|
---|
163 | Traceback (most recent call last):
|
---|
164 | ...
|
---|
165 | TypeError: h() got an unexpected keyword argument 'e'
|
---|
166 |
|
---|
167 | >>> h(*h)
|
---|
168 | Traceback (most recent call last):
|
---|
169 | ...
|
---|
170 | TypeError: h() argument after * must be a sequence, not function
|
---|
171 |
|
---|
172 | >>> dir(*h)
|
---|
173 | Traceback (most recent call last):
|
---|
174 | ...
|
---|
175 | TypeError: dir() argument after * must be a sequence, not function
|
---|
176 |
|
---|
177 | >>> None(*h)
|
---|
178 | Traceback (most recent call last):
|
---|
179 | ...
|
---|
180 | TypeError: NoneType object argument after * must be a sequence, \
|
---|
181 | not function
|
---|
182 |
|
---|
183 | >>> h(**h)
|
---|
184 | Traceback (most recent call last):
|
---|
185 | ...
|
---|
186 | TypeError: h() argument after ** must be a mapping, not function
|
---|
187 |
|
---|
188 | >>> dir(**h)
|
---|
189 | Traceback (most recent call last):
|
---|
190 | ...
|
---|
191 | TypeError: dir() argument after ** must be a mapping, not function
|
---|
192 |
|
---|
193 | >>> None(**h)
|
---|
194 | Traceback (most recent call last):
|
---|
195 | ...
|
---|
196 | TypeError: NoneType object argument after ** must be a mapping, \
|
---|
197 | not function
|
---|
198 |
|
---|
199 | >>> dir(b=1, **{'b': 1})
|
---|
200 | Traceback (most recent call last):
|
---|
201 | ...
|
---|
202 | TypeError: dir() got multiple values for keyword argument 'b'
|
---|
203 |
|
---|
204 | Another helper function
|
---|
205 |
|
---|
206 | >>> def f2(*a, **b):
|
---|
207 | ... return a, b
|
---|
208 |
|
---|
209 |
|
---|
210 | >>> d = {}
|
---|
211 | >>> for i in xrange(512):
|
---|
212 | ... key = 'k%d' % i
|
---|
213 | ... d[key] = i
|
---|
214 | >>> a, b = f2(1, *(2,3), **d)
|
---|
215 | >>> len(a), len(b), b == d
|
---|
216 | (3, 512, True)
|
---|
217 |
|
---|
218 | >>> class Foo:
|
---|
219 | ... def method(self, arg1, arg2):
|
---|
220 | ... return arg1+arg2
|
---|
221 |
|
---|
222 | >>> x = Foo()
|
---|
223 | >>> Foo.method(*(x, 1, 2))
|
---|
224 | 3
|
---|
225 | >>> Foo.method(x, *(1, 2))
|
---|
226 | 3
|
---|
227 | >>> Foo.method(*(1, 2, 3))
|
---|
228 | Traceback (most recent call last):
|
---|
229 | ...
|
---|
230 | TypeError: unbound method method() must be called with Foo instance as \
|
---|
231 | first argument (got int instance instead)
|
---|
232 |
|
---|
233 | >>> Foo.method(1, *[2, 3])
|
---|
234 | Traceback (most recent call last):
|
---|
235 | ...
|
---|
236 | TypeError: unbound method method() must be called with Foo instance as \
|
---|
237 | first argument (got int instance instead)
|
---|
238 |
|
---|
239 | A PyCFunction that takes only positional parameters should allow an
|
---|
240 | empty keyword dictionary to pass without a complaint, but raise a
|
---|
241 | TypeError if te dictionary is not empty
|
---|
242 |
|
---|
243 | >>> try:
|
---|
244 | ... silence = id(1, *{})
|
---|
245 | ... True
|
---|
246 | ... except:
|
---|
247 | ... False
|
---|
248 | True
|
---|
249 |
|
---|
250 | >>> id(1, **{'foo': 1})
|
---|
251 | Traceback (most recent call last):
|
---|
252 | ...
|
---|
253 | TypeError: id() takes no keyword arguments
|
---|
254 |
|
---|
255 | A corner case of keyword dictionary items being deleted during
|
---|
256 | the function call setup. See <http://bugs.python.org/issue2016>.
|
---|
257 |
|
---|
258 | >>> class Name(str):
|
---|
259 | ... def __eq__(self, other):
|
---|
260 | ... try:
|
---|
261 | ... del x[self]
|
---|
262 | ... except KeyError:
|
---|
263 | ... pass
|
---|
264 | ... return str.__eq__(self, other)
|
---|
265 | ... def __hash__(self):
|
---|
266 | ... return str.__hash__(self)
|
---|
267 |
|
---|
268 | >>> x = {Name("a"):1, Name("b"):2}
|
---|
269 | >>> def f(a, b):
|
---|
270 | ... print a,b
|
---|
271 | >>> f(**x)
|
---|
272 | 1 2
|
---|
273 |
|
---|
274 | A obscure message:
|
---|
275 |
|
---|
276 | >>> def f(a, b):
|
---|
277 | ... pass
|
---|
278 | >>> f(b=1)
|
---|
279 | Traceback (most recent call last):
|
---|
280 | ...
|
---|
281 | TypeError: f() takes exactly 2 arguments (1 given)
|
---|
282 |
|
---|
283 | The number of arguments passed in includes keywords:
|
---|
284 |
|
---|
285 | >>> def f(a):
|
---|
286 | ... pass
|
---|
287 | >>> f(6, a=4, *(1, 2, 3))
|
---|
288 | Traceback (most recent call last):
|
---|
289 | ...
|
---|
290 | TypeError: f() takes exactly 1 argument (5 given)
|
---|
291 | """
|
---|
292 |
|
---|
293 | import unittest
|
---|
294 | import sys
|
---|
295 | from test import test_support
|
---|
296 |
|
---|
297 |
|
---|
298 | class ExtCallTest(unittest.TestCase):
|
---|
299 |
|
---|
300 | def test_unicode_keywords(self):
|
---|
301 | def f(a):
|
---|
302 | return a
|
---|
303 | self.assertEqual(f(**{u'a': 4}), 4)
|
---|
304 | self.assertRaises(TypeError, f, **{u'stören': 4})
|
---|
305 | self.assertRaises(TypeError, f, **{u'someLongString':2})
|
---|
306 | try:
|
---|
307 | f(a=4, **{u'a': 4})
|
---|
308 | except TypeError:
|
---|
309 | pass
|
---|
310 | else:
|
---|
311 | self.fail("duplicate arguments didn't raise")
|
---|
312 |
|
---|
313 |
|
---|
314 | def test_main():
|
---|
315 | test_support.run_doctest(sys.modules[__name__], True)
|
---|
316 | test_support.run_unittest(ExtCallTest)
|
---|
317 |
|
---|
318 | if __name__ == '__main__':
|
---|
319 | test_main()
|
---|