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