blob: 654258eb240c856a98fa60969c9722f2f77b1d36 [file] [log] [blame]
Benjamin Petersona567a772010-03-21 21:00:50 +00001
Christian Heimesb186d002008-03-18 15:15:01 +00002"""Doctest for method/function calls.
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +00003
Christian Heimesb186d002008-03-18 15:15:01 +00004We're going the use these types for extra testing
Raymond Hettinger40174c32003-05-31 07:04:16 +00005
Neal Norwitzd79bacc2008-03-18 20:58:39 +00006 >>> from collections import UserList
7 >>> from collections import UserDict
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +00008
Christian Heimesb186d002008-03-18 15:15:01 +00009We're defining four helper functions
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +000010
Christian Heimesb186d002008-03-18 15:15:01 +000011 >>> def e(a,b):
Neal Norwitzd79bacc2008-03-18 20:58:39 +000012 ... print(a, b)
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +000013
Christian Heimesb186d002008-03-18 15:15:01 +000014 >>> def f(*a, **k):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000015 ... print(a, support.sortdict(k))
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +000016
Christian Heimesb186d002008-03-18 15:15:01 +000017 >>> def g(x, *y, **z):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000018 ... print(x, y, support.sortdict(z))
Christian Heimesb186d002008-03-18 15:15:01 +000019
20 >>> def h(j=1, a=2, h=3):
Neal Norwitzd79bacc2008-03-18 20:58:39 +000021 ... print(j, a, h)
Christian Heimesb186d002008-03-18 15:15:01 +000022
23Argument list examples
24
25 >>> f()
26 () {}
27 >>> f(1)
28 (1,) {}
29 >>> f(1, 2)
30 (1, 2) {}
31 >>> f(1, 2, 3)
32 (1, 2, 3) {}
33 >>> f(1, 2, 3, *(4, 5))
34 (1, 2, 3, 4, 5) {}
35 >>> f(1, 2, 3, *[4, 5])
36 (1, 2, 3, 4, 5) {}
Benjamin Peterson025e9eb2015-05-05 20:16:41 -040037 >>> f(*[1, 2, 3], 4, 5)
38 (1, 2, 3, 4, 5) {}
Christian Heimesb186d002008-03-18 15:15:01 +000039 >>> f(1, 2, 3, *UserList([4, 5]))
40 (1, 2, 3, 4, 5) {}
Benjamin Peterson025e9eb2015-05-05 20:16:41 -040041 >>> f(1, 2, 3, *[4, 5], *[6, 7])
42 (1, 2, 3, 4, 5, 6, 7) {}
43 >>> f(1, *[2, 3], 4, *[5, 6], 7)
44 (1, 2, 3, 4, 5, 6, 7) {}
45 >>> f(*UserList([1, 2]), *UserList([3, 4]), 5, *UserList([6, 7]))
46 (1, 2, 3, 4, 5, 6, 7) {}
Christian Heimesb186d002008-03-18 15:15:01 +000047
48Here we add keyword arguments
49
50 >>> f(1, 2, 3, **{'a':4, 'b':5})
51 (1, 2, 3) {'a': 4, 'b': 5}
Benjamin Peterson025e9eb2015-05-05 20:16:41 -040052 >>> f(1, 2, **{'a': -1, 'b': 5}, **{'a': 4, 'c': 6})
53 Traceback (most recent call last):
54 ...
55 TypeError: f() got multiple values for keyword argument 'a'
56 >>> f(1, 2, **{'a': -1, 'b': 5}, a=4, c=6)
57 Traceback (most recent call last):
58 ...
59 TypeError: f() got multiple values for keyword argument 'a'
Christian Heimesb186d002008-03-18 15:15:01 +000060 >>> f(1, 2, 3, *[4, 5], **{'a':6, 'b':7})
61 (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
62 >>> f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9})
63 (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
Benjamin Peterson025e9eb2015-05-05 20:16:41 -040064 >>> f(1, 2, 3, *[4, 5], **{'c': 8}, **{'a':6, 'b':7})
65 (1, 2, 3, 4, 5) {'a': 6, 'b': 7, 'c': 8}
66 >>> f(1, 2, 3, *(4, 5), x=6, y=7, **{'a':8, 'b': 9})
67 (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
Christian Heimesb186d002008-03-18 15:15:01 +000068
69 >>> f(1, 2, 3, **UserDict(a=4, b=5))
70 (1, 2, 3) {'a': 4, 'b': 5}
71 >>> f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7))
72 (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
73 >>> f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9))
74 (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
Benjamin Peterson025e9eb2015-05-05 20:16:41 -040075 >>> f(1, 2, 3, *(4, 5), x=6, y=7, **UserDict(a=8, b=9))
76 (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
Christian Heimesb186d002008-03-18 15:15:01 +000077
78Examples with invalid arguments (TypeErrors). We're also testing the function
79names in the exception messages.
80
81Verify clearing of SF bug #733667
82
83 >>> e(c=4)
84 Traceback (most recent call last):
85 ...
86 TypeError: e() got an unexpected keyword argument 'c'
87
88 >>> g()
89 Traceback (most recent call last):
90 ...
Benjamin Petersone109c702011-06-24 09:37:26 -050091 TypeError: g() missing 1 required positional argument: 'x'
Christian Heimesb186d002008-03-18 15:15:01 +000092
93 >>> g(*())
94 Traceback (most recent call last):
95 ...
Benjamin Petersone109c702011-06-24 09:37:26 -050096 TypeError: g() missing 1 required positional argument: 'x'
Christian Heimesb186d002008-03-18 15:15:01 +000097
98 >>> g(*(), **{})
99 Traceback (most recent call last):
100 ...
Benjamin Petersone109c702011-06-24 09:37:26 -0500101 TypeError: g() missing 1 required positional argument: 'x'
Christian Heimesb186d002008-03-18 15:15:01 +0000102
103 >>> g(1)
104 1 () {}
105 >>> g(1, 2)
106 1 (2,) {}
107 >>> g(1, 2, 3)
108 1 (2, 3) {}
109 >>> g(1, 2, 3, *(4, 5))
110 1 (2, 3, 4, 5) {}
111
112 >>> class Nothing: pass
113 ...
114 >>> g(*Nothing())
115 Traceback (most recent call last):
116 ...
Neal Norwitzd79bacc2008-03-18 20:58:39 +0000117 TypeError: g() argument after * must be a sequence, not Nothing
Christian Heimesb186d002008-03-18 15:15:01 +0000118
119 >>> class Nothing:
120 ... def __len__(self): return 5
121 ...
122
123 >>> g(*Nothing())
124 Traceback (most recent call last):
125 ...
Neal Norwitzd79bacc2008-03-18 20:58:39 +0000126 TypeError: g() argument after * must be a sequence, not Nothing
Christian Heimesb186d002008-03-18 15:15:01 +0000127
128 >>> class Nothing():
129 ... def __len__(self): return 5
130 ... def __getitem__(self, i):
131 ... if i<3: return i
132 ... else: raise IndexError(i)
133 ...
134
135 >>> g(*Nothing())
136 0 (1, 2) {}
137
138 >>> class Nothing:
139 ... def __init__(self): self.c = 0
140 ... def __iter__(self): return self
Neal Norwitzd79bacc2008-03-18 20:58:39 +0000141 ... def __next__(self):
Christian Heimesb186d002008-03-18 15:15:01 +0000142 ... if self.c == 4:
143 ... raise StopIteration
144 ... c = self.c
145 ... self.c += 1
146 ... return c
147 ...
148
149 >>> g(*Nothing())
150 0 (1, 2, 3) {}
151
152Make sure that the function doesn't stomp the dictionary
153
154 >>> d = {'a': 1, 'b': 2, 'c': 3}
155 >>> d2 = d.copy()
156 >>> g(1, d=4, **d)
157 1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4}
158 >>> d == d2
159 True
160
161What about willful misconduct?
162
163 >>> def saboteur(**kw):
164 ... kw['x'] = 'm'
165 ... return kw
166
167 >>> d = {}
168 >>> kw = saboteur(a=1, **d)
169 >>> d
170 {}
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +0000171
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000172
Christian Heimesb186d002008-03-18 15:15:01 +0000173 >>> g(1, 2, 3, **{'x': 4, 'y': 5})
174 Traceback (most recent call last):
175 ...
Benjamin Petersonb204a422011-06-05 22:04:07 -0500176 TypeError: g() got multiple values for argument 'x'
Christian Heimesb186d002008-03-18 15:15:01 +0000177
178 >>> f(**{1:2})
179 Traceback (most recent call last):
180 ...
181 TypeError: f() keywords must be strings
182
183 >>> h(**{'e': 2})
184 Traceback (most recent call last):
185 ...
186 TypeError: h() got an unexpected keyword argument 'e'
187
188 >>> h(*h)
189 Traceback (most recent call last):
190 ...
191 TypeError: h() argument after * must be a sequence, not function
192
193 >>> dir(*h)
194 Traceback (most recent call last):
195 ...
196 TypeError: dir() argument after * must be a sequence, not function
197
198 >>> None(*h)
199 Traceback (most recent call last):
200 ...
201 TypeError: NoneType object argument after * must be a sequence, \
202not function
203
204 >>> h(**h)
205 Traceback (most recent call last):
206 ...
207 TypeError: h() argument after ** must be a mapping, not function
208
209 >>> dir(**h)
210 Traceback (most recent call last):
211 ...
212 TypeError: dir() argument after ** must be a mapping, not function
213
214 >>> None(**h)
215 Traceback (most recent call last):
216 ...
217 TypeError: NoneType object argument after ** must be a mapping, \
218not function
219
220 >>> dir(b=1, **{'b': 1})
221 Traceback (most recent call last):
222 ...
223 TypeError: dir() got multiple values for keyword argument 'b'
224
225Another helper function
226
227 >>> def f2(*a, **b):
228 ... return a, b
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000229
230
Christian Heimesb186d002008-03-18 15:15:01 +0000231 >>> d = {}
Neal Norwitzd79bacc2008-03-18 20:58:39 +0000232 >>> for i in range(512):
Christian Heimesb186d002008-03-18 15:15:01 +0000233 ... key = 'k%d' % i
234 ... d[key] = i
235 >>> a, b = f2(1, *(2,3), **d)
236 >>> len(a), len(b), b == d
237 (3, 512, True)
Raymond Hettinger40174c32003-05-31 07:04:16 +0000238
Christian Heimesb186d002008-03-18 15:15:01 +0000239 >>> class Foo:
240 ... def method(self, arg1, arg2):
241 ... return arg1+arg2
Fred Drake004d5e62000-10-23 17:22:08 +0000242
Christian Heimesb186d002008-03-18 15:15:01 +0000243 >>> x = Foo()
244 >>> Foo.method(*(x, 1, 2))
245 3
246 >>> Foo.method(x, *(1, 2))
247 3
248 >>> Foo.method(*(1, 2, 3))
Neal Norwitzd79bacc2008-03-18 20:58:39 +0000249 5
Christian Heimesb186d002008-03-18 15:15:01 +0000250 >>> Foo.method(1, *[2, 3])
Neal Norwitzd79bacc2008-03-18 20:58:39 +0000251 5
Fred Drake004d5e62000-10-23 17:22:08 +0000252
Ezio Melotti13925002011-03-16 11:05:33 +0200253A PyCFunction that takes only positional parameters should allow an
Christian Heimesb186d002008-03-18 15:15:01 +0000254empty keyword dictionary to pass without a complaint, but raise a
255TypeError if te dictionary is not empty
Jeremy Hylton074c3e62000-03-30 23:55:31 +0000256
Christian Heimesb186d002008-03-18 15:15:01 +0000257 >>> try:
258 ... silence = id(1, *{})
259 ... True
260 ... except:
261 ... False
262 True
Fred Drake004d5e62000-10-23 17:22:08 +0000263
Christian Heimesb186d002008-03-18 15:15:01 +0000264 >>> id(1, **{'foo': 1})
265 Traceback (most recent call last):
266 ...
267 TypeError: id() takes no keyword arguments
Jeremy Hylton074c3e62000-03-30 23:55:31 +0000268
Benjamin Peterson0289b152009-06-28 17:22:03 +0000269A corner case of keyword dictionary items being deleted during
270the function call setup. See <http://bugs.python.org/issue2016>.
271
272 >>> class Name(str):
273 ... def __eq__(self, other):
274 ... try:
275 ... del x[self]
276 ... except KeyError:
277 ... pass
278 ... return str.__eq__(self, other)
279 ... def __hash__(self):
280 ... return str.__hash__(self)
281
282 >>> x = {Name("a"):1, Name("b"):2}
283 >>> def f(a, b):
284 ... print(a,b)
285 >>> f(**x)
286 1 2
Benjamin Petersona567a772010-03-21 21:00:50 +0000287
Benjamin Petersone109c702011-06-24 09:37:26 -0500288Too many arguments:
Benjamin Petersona567a772010-03-21 21:00:50 +0000289
Benjamin Petersone109c702011-06-24 09:37:26 -0500290 >>> def f(): pass
Benjamin Petersonb204a422011-06-05 22:04:07 -0500291 >>> f(1)
292 Traceback (most recent call last):
293 ...
Benjamin Petersone109c702011-06-24 09:37:26 -0500294 TypeError: f() takes 0 positional arguments but 1 was given
295 >>> def f(a): pass
296 >>> f(1, 2)
Benjamin Petersonb204a422011-06-05 22:04:07 -0500297 Traceback (most recent call last):
298 ...
Benjamin Petersone109c702011-06-24 09:37:26 -0500299 TypeError: f() takes 1 positional argument but 2 were given
300 >>> def f(a, b=1): pass
301 >>> f(1, 2, 3)
Benjamin Petersonb204a422011-06-05 22:04:07 -0500302 Traceback (most recent call last):
303 ...
Benjamin Petersone109c702011-06-24 09:37:26 -0500304 TypeError: f() takes from 1 to 2 positional arguments but 3 were given
305 >>> def f(*, kw): pass
306 >>> f(1, kw=3)
Benjamin Petersonb204a422011-06-05 22:04:07 -0500307 Traceback (most recent call last):
308 ...
309 TypeError: f() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
Benjamin Petersone109c702011-06-24 09:37:26 -0500310 >>> def f(*, kw, b): pass
311 >>> f(1, 2, 3, b=3, kw=3)
312 Traceback (most recent call last):
313 ...
314 TypeError: f() takes 0 positional arguments but 3 positional arguments (and 2 keyword-only arguments) were given
315 >>> def f(a, b=2, *, kw): pass
316 >>> f(2, 3, 4, kw=4)
317 Traceback (most recent call last):
318 ...
319 TypeError: f() takes from 1 to 2 positional arguments but 3 positional arguments (and 1 keyword-only argument) were given
Benjamin Petersonb204a422011-06-05 22:04:07 -0500320
Benjamin Petersone109c702011-06-24 09:37:26 -0500321Too few and missing arguments:
322
323 >>> def f(a): pass
Benjamin Petersonb204a422011-06-05 22:04:07 -0500324 >>> f()
325 Traceback (most recent call last):
Benjamin Petersone109c702011-06-24 09:37:26 -0500326 ...
327 TypeError: f() missing 1 required positional argument: 'a'
328 >>> def f(a, b): pass
329 >>> f()
Benjamin Petersonb204a422011-06-05 22:04:07 -0500330 Traceback (most recent call last):
Benjamin Petersone109c702011-06-24 09:37:26 -0500331 ...
332 TypeError: f() missing 2 required positional arguments: 'a' and 'b'
333 >>> def f(a, b, c): pass
334 >>> f()
Benjamin Petersonb204a422011-06-05 22:04:07 -0500335 Traceback (most recent call last):
Benjamin Petersone109c702011-06-24 09:37:26 -0500336 ...
337 TypeError: f() missing 3 required positional arguments: 'a', 'b', and 'c'
338 >>> def f(a, b, c, d, e): pass
339 >>> f()
340 Traceback (most recent call last):
341 ...
342 TypeError: f() missing 5 required positional arguments: 'a', 'b', 'c', 'd', and 'e'
343 >>> def f(a, b=4, c=5, d=5): pass
344 >>> f(c=12, b=9)
345 Traceback (most recent call last):
346 ...
347 TypeError: f() missing 1 required positional argument: 'a'
348
349Same with keyword only args:
350
351 >>> def f(*, w): pass
352 >>> f()
353 Traceback (most recent call last):
354 ...
355 TypeError: f() missing 1 required keyword-only argument: 'w'
356 >>> def f(*, a, b, c, d, e): pass
357 >>> f()
358 Traceback (most recent call last):
359 ...
360 TypeError: f() missing 5 required keyword-only arguments: 'a', 'b', 'c', 'd', and 'e'
361
Christian Heimesb186d002008-03-18 15:15:01 +0000362"""
Samuele Pedroni8036c832004-02-21 21:03:30 +0000363
Benjamin Petersona567a772010-03-21 21:00:50 +0000364import sys
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000365from test import support
Samuele Pedroni8036c832004-02-21 21:03:30 +0000366
Christian Heimesb186d002008-03-18 15:15:01 +0000367def test_main():
Benjamin Petersona567a772010-03-21 21:00:50 +0000368 support.run_doctest(sys.modules[__name__], True)
Jeremy Hylton074c3e62000-03-30 23:55:31 +0000369
Christian Heimesb186d002008-03-18 15:15:01 +0000370if __name__ == '__main__':
371 test_main()