blob: 6b6c12de2e9698f6882e7709f0ef0ad2a5b14121 [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) {}
37 >>> f(1, 2, 3, *UserList([4, 5]))
38 (1, 2, 3, 4, 5) {}
39
40Here we add keyword arguments
41
42 >>> f(1, 2, 3, **{'a':4, 'b':5})
43 (1, 2, 3) {'a': 4, 'b': 5}
44 >>> f(1, 2, 3, *[4, 5], **{'a':6, 'b':7})
45 (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
46 >>> f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9})
47 (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
48
49 >>> f(1, 2, 3, **UserDict(a=4, b=5))
50 (1, 2, 3) {'a': 4, 'b': 5}
51 >>> f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7))
52 (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
53 >>> f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9))
54 (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
55
56Examples with invalid arguments (TypeErrors). We're also testing the function
57names in the exception messages.
58
59Verify clearing of SF bug #733667
60
61 >>> e(c=4)
62 Traceback (most recent call last):
63 ...
64 TypeError: e() got an unexpected keyword argument 'c'
65
66 >>> g()
67 Traceback (most recent call last):
68 ...
Benjamin Petersone109c702011-06-24 09:37:26 -050069 TypeError: g() missing 1 required positional argument: 'x'
Christian Heimesb186d002008-03-18 15:15:01 +000070
71 >>> g(*())
72 Traceback (most recent call last):
73 ...
Benjamin Petersone109c702011-06-24 09:37:26 -050074 TypeError: g() missing 1 required positional argument: 'x'
Christian Heimesb186d002008-03-18 15:15:01 +000075
76 >>> g(*(), **{})
77 Traceback (most recent call last):
78 ...
Benjamin Petersone109c702011-06-24 09:37:26 -050079 TypeError: g() missing 1 required positional argument: 'x'
Christian Heimesb186d002008-03-18 15:15:01 +000080
81 >>> g(1)
82 1 () {}
83 >>> g(1, 2)
84 1 (2,) {}
85 >>> g(1, 2, 3)
86 1 (2, 3) {}
87 >>> g(1, 2, 3, *(4, 5))
88 1 (2, 3, 4, 5) {}
89
90 >>> class Nothing: pass
91 ...
92 >>> g(*Nothing())
93 Traceback (most recent call last):
94 ...
Neal Norwitzd79bacc2008-03-18 20:58:39 +000095 TypeError: g() argument after * must be a sequence, not Nothing
Christian Heimesb186d002008-03-18 15:15:01 +000096
97 >>> class Nothing:
98 ... def __len__(self): return 5
99 ...
100
101 >>> g(*Nothing())
102 Traceback (most recent call last):
103 ...
Neal Norwitzd79bacc2008-03-18 20:58:39 +0000104 TypeError: g() argument after * must be a sequence, not Nothing
Christian Heimesb186d002008-03-18 15:15:01 +0000105
106 >>> class Nothing():
107 ... def __len__(self): return 5
108 ... def __getitem__(self, i):
109 ... if i<3: return i
110 ... else: raise IndexError(i)
111 ...
112
113 >>> g(*Nothing())
114 0 (1, 2) {}
115
116 >>> class Nothing:
117 ... def __init__(self): self.c = 0
118 ... def __iter__(self): return self
Neal Norwitzd79bacc2008-03-18 20:58:39 +0000119 ... def __next__(self):
Christian Heimesb186d002008-03-18 15:15:01 +0000120 ... if self.c == 4:
121 ... raise StopIteration
122 ... c = self.c
123 ... self.c += 1
124 ... return c
125 ...
126
127 >>> g(*Nothing())
128 0 (1, 2, 3) {}
129
130Make sure that the function doesn't stomp the dictionary
131
132 >>> d = {'a': 1, 'b': 2, 'c': 3}
133 >>> d2 = d.copy()
134 >>> g(1, d=4, **d)
135 1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4}
136 >>> d == d2
137 True
138
139What about willful misconduct?
140
141 >>> def saboteur(**kw):
142 ... kw['x'] = 'm'
143 ... return kw
144
145 >>> d = {}
146 >>> kw = saboteur(a=1, **d)
147 >>> d
148 {}
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +0000149
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000150
Christian Heimesb186d002008-03-18 15:15:01 +0000151 >>> g(1, 2, 3, **{'x': 4, 'y': 5})
152 Traceback (most recent call last):
153 ...
Benjamin Petersonb204a422011-06-05 22:04:07 -0500154 TypeError: g() got multiple values for argument 'x'
Christian Heimesb186d002008-03-18 15:15:01 +0000155
156 >>> f(**{1:2})
157 Traceback (most recent call last):
158 ...
159 TypeError: f() keywords must be strings
160
161 >>> h(**{'e': 2})
162 Traceback (most recent call last):
163 ...
164 TypeError: h() got an unexpected keyword argument 'e'
165
166 >>> h(*h)
167 Traceback (most recent call last):
168 ...
169 TypeError: h() argument after * must be a sequence, not function
170
171 >>> dir(*h)
172 Traceback (most recent call last):
173 ...
174 TypeError: dir() argument after * must be a sequence, not function
175
176 >>> None(*h)
177 Traceback (most recent call last):
178 ...
179 TypeError: NoneType object argument after * must be a sequence, \
180not function
181
182 >>> h(**h)
183 Traceback (most recent call last):
184 ...
185 TypeError: h() argument after ** must be a mapping, not function
186
187 >>> dir(**h)
188 Traceback (most recent call last):
189 ...
190 TypeError: dir() argument after ** must be a mapping, not function
191
192 >>> None(**h)
193 Traceback (most recent call last):
194 ...
195 TypeError: NoneType object argument after ** must be a mapping, \
196not function
197
198 >>> dir(b=1, **{'b': 1})
199 Traceback (most recent call last):
200 ...
201 TypeError: dir() got multiple values for keyword argument 'b'
202
203Another helper function
204
205 >>> def f2(*a, **b):
206 ... return a, b
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000207
208
Christian Heimesb186d002008-03-18 15:15:01 +0000209 >>> d = {}
Neal Norwitzd79bacc2008-03-18 20:58:39 +0000210 >>> for i in range(512):
Christian Heimesb186d002008-03-18 15:15:01 +0000211 ... key = 'k%d' % i
212 ... d[key] = i
213 >>> a, b = f2(1, *(2,3), **d)
214 >>> len(a), len(b), b == d
215 (3, 512, True)
Raymond Hettinger40174c32003-05-31 07:04:16 +0000216
Christian Heimesb186d002008-03-18 15:15:01 +0000217 >>> class Foo:
218 ... def method(self, arg1, arg2):
219 ... return arg1+arg2
Fred Drake004d5e62000-10-23 17:22:08 +0000220
Christian Heimesb186d002008-03-18 15:15:01 +0000221 >>> x = Foo()
222 >>> Foo.method(*(x, 1, 2))
223 3
224 >>> Foo.method(x, *(1, 2))
225 3
226 >>> Foo.method(*(1, 2, 3))
Neal Norwitzd79bacc2008-03-18 20:58:39 +0000227 5
Christian Heimesb186d002008-03-18 15:15:01 +0000228 >>> Foo.method(1, *[2, 3])
Neal Norwitzd79bacc2008-03-18 20:58:39 +0000229 5
Fred Drake004d5e62000-10-23 17:22:08 +0000230
Ezio Melotti13925002011-03-16 11:05:33 +0200231A PyCFunction that takes only positional parameters should allow an
Christian Heimesb186d002008-03-18 15:15:01 +0000232empty keyword dictionary to pass without a complaint, but raise a
233TypeError if te dictionary is not empty
Jeremy Hylton074c3e62000-03-30 23:55:31 +0000234
Christian Heimesb186d002008-03-18 15:15:01 +0000235 >>> try:
236 ... silence = id(1, *{})
237 ... True
238 ... except:
239 ... False
240 True
Fred Drake004d5e62000-10-23 17:22:08 +0000241
Christian Heimesb186d002008-03-18 15:15:01 +0000242 >>> id(1, **{'foo': 1})
243 Traceback (most recent call last):
244 ...
245 TypeError: id() takes no keyword arguments
Jeremy Hylton074c3e62000-03-30 23:55:31 +0000246
Benjamin Peterson0289b152009-06-28 17:22:03 +0000247A corner case of keyword dictionary items being deleted during
248the function call setup. See <http://bugs.python.org/issue2016>.
249
250 >>> class Name(str):
251 ... def __eq__(self, other):
252 ... try:
253 ... del x[self]
254 ... except KeyError:
255 ... pass
256 ... return str.__eq__(self, other)
257 ... def __hash__(self):
258 ... return str.__hash__(self)
259
260 >>> x = {Name("a"):1, Name("b"):2}
261 >>> def f(a, b):
262 ... print(a,b)
263 >>> f(**x)
264 1 2
Benjamin Petersona567a772010-03-21 21:00:50 +0000265
Benjamin Petersone109c702011-06-24 09:37:26 -0500266Too many arguments:
Benjamin Petersona567a772010-03-21 21:00:50 +0000267
Benjamin Petersone109c702011-06-24 09:37:26 -0500268 >>> def f(): pass
Benjamin Petersonb204a422011-06-05 22:04:07 -0500269 >>> f(1)
270 Traceback (most recent call last):
271 ...
Benjamin Petersone109c702011-06-24 09:37:26 -0500272 TypeError: f() takes 0 positional arguments but 1 was given
273 >>> def f(a): pass
274 >>> f(1, 2)
Benjamin Petersonb204a422011-06-05 22:04:07 -0500275 Traceback (most recent call last):
276 ...
Benjamin Petersone109c702011-06-24 09:37:26 -0500277 TypeError: f() takes 1 positional argument but 2 were given
278 >>> def f(a, b=1): pass
279 >>> f(1, 2, 3)
Benjamin Petersonb204a422011-06-05 22:04:07 -0500280 Traceback (most recent call last):
281 ...
Benjamin Petersone109c702011-06-24 09:37:26 -0500282 TypeError: f() takes from 1 to 2 positional arguments but 3 were given
283 >>> def f(*, kw): pass
284 >>> f(1, kw=3)
Benjamin Petersonb204a422011-06-05 22:04:07 -0500285 Traceback (most recent call last):
286 ...
287 TypeError: f() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
Benjamin Petersone109c702011-06-24 09:37:26 -0500288 >>> def f(*, kw, b): pass
289 >>> f(1, 2, 3, b=3, kw=3)
290 Traceback (most recent call last):
291 ...
292 TypeError: f() takes 0 positional arguments but 3 positional arguments (and 2 keyword-only arguments) were given
293 >>> def f(a, b=2, *, kw): pass
294 >>> f(2, 3, 4, kw=4)
295 Traceback (most recent call last):
296 ...
297 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 -0500298
Benjamin Petersone109c702011-06-24 09:37:26 -0500299Too few and missing arguments:
300
301 >>> def f(a): pass
Benjamin Petersonb204a422011-06-05 22:04:07 -0500302 >>> f()
303 Traceback (most recent call last):
Benjamin Petersone109c702011-06-24 09:37:26 -0500304 ...
305 TypeError: f() missing 1 required positional argument: 'a'
306 >>> def f(a, b): pass
307 >>> f()
Benjamin Petersonb204a422011-06-05 22:04:07 -0500308 Traceback (most recent call last):
Benjamin Petersone109c702011-06-24 09:37:26 -0500309 ...
310 TypeError: f() missing 2 required positional arguments: 'a' and 'b'
311 >>> def f(a, b, c): pass
312 >>> f()
Benjamin Petersonb204a422011-06-05 22:04:07 -0500313 Traceback (most recent call last):
Benjamin Petersone109c702011-06-24 09:37:26 -0500314 ...
315 TypeError: f() missing 3 required positional arguments: 'a', 'b', and 'c'
316 >>> def f(a, b, c, d, e): pass
317 >>> f()
318 Traceback (most recent call last):
319 ...
320 TypeError: f() missing 5 required positional arguments: 'a', 'b', 'c', 'd', and 'e'
321 >>> def f(a, b=4, c=5, d=5): pass
322 >>> f(c=12, b=9)
323 Traceback (most recent call last):
324 ...
325 TypeError: f() missing 1 required positional argument: 'a'
326
327Same with keyword only args:
328
329 >>> def f(*, w): pass
330 >>> f()
331 Traceback (most recent call last):
332 ...
333 TypeError: f() missing 1 required keyword-only argument: 'w'
334 >>> def f(*, a, b, c, d, e): pass
335 >>> f()
336 Traceback (most recent call last):
337 ...
338 TypeError: f() missing 5 required keyword-only arguments: 'a', 'b', 'c', 'd', and 'e'
339
Christian Heimesb186d002008-03-18 15:15:01 +0000340"""
Samuele Pedroni8036c832004-02-21 21:03:30 +0000341
Benjamin Petersona567a772010-03-21 21:00:50 +0000342import sys
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000343from test import support
Samuele Pedroni8036c832004-02-21 21:03:30 +0000344
Christian Heimesb186d002008-03-18 15:15:01 +0000345def test_main():
Benjamin Petersona567a772010-03-21 21:00:50 +0000346 support.run_doctest(sys.modules[__name__], True)
Jeremy Hylton074c3e62000-03-30 23:55:31 +0000347
Christian Heimesb186d002008-03-18 15:15:01 +0000348if __name__ == '__main__':
349 test_main()