blob: d9598e7e54a5121573105c2aa0b3d7995490aaeb [file] [log] [blame]
Benjamin Petersone18ef192009-01-20 14:21:16 +00001# -*- coding: utf-8 -*-
Benjamin Petersone39b2ec2010-03-21 17:34:54 +00002
3import sys
4
Brett Cannon0bb79502008-03-18 01:58:56 +00005"""Doctest for method/function calls.
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +00006
Brett Cannon0bb79502008-03-18 01:58:56 +00007We're going the use these types for extra testing
Raymond Hettinger40174c32003-05-31 07:04:16 +00008
Brett Cannon0bb79502008-03-18 01:58:56 +00009 >>> from UserList import UserList
10 >>> from UserDict import UserDict
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +000011
Brett Cannon0bb79502008-03-18 01:58:56 +000012We're defining four helper functions
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +000013
Brett Cannon0bb79502008-03-18 01:58:56 +000014 >>> def e(a,b):
15 ... print a, b
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +000016
Brett Cannon0bb79502008-03-18 01:58:56 +000017 >>> def f(*a, **k):
18 ... print a, test_support.sortdict(k)
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +000019
Brett Cannon0bb79502008-03-18 01:58:56 +000020 >>> def g(x, *y, **z):
21 ... print x, y, test_support.sortdict(z)
22
23 >>> def h(j=1, a=2, h=3):
24 ... print j, a, h
25
26Argument list examples
27
28 >>> f()
29 () {}
30 >>> f(1)
31 (1,) {}
32 >>> f(1, 2)
33 (1, 2) {}
34 >>> f(1, 2, 3)
35 (1, 2, 3) {}
36 >>> f(1, 2, 3, *(4, 5))
37 (1, 2, 3, 4, 5) {}
38 >>> f(1, 2, 3, *[4, 5])
39 (1, 2, 3, 4, 5) {}
40 >>> f(1, 2, 3, *UserList([4, 5]))
41 (1, 2, 3, 4, 5) {}
42
43Here we add keyword arguments
44
45 >>> f(1, 2, 3, **{'a':4, 'b':5})
46 (1, 2, 3) {'a': 4, 'b': 5}
47 >>> f(1, 2, 3, *[4, 5], **{'a':6, 'b':7})
48 (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
49 >>> f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9})
50 (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
51
52 >>> f(1, 2, 3, **UserDict(a=4, b=5))
53 (1, 2, 3) {'a': 4, 'b': 5}
54 >>> f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7))
55 (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
56 >>> f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9))
57 (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
58
59Examples with invalid arguments (TypeErrors). We're also testing the function
60names in the exception messages.
61
62Verify clearing of SF bug #733667
63
64 >>> e(c=4)
65 Traceback (most recent call last):
66 ...
67 TypeError: e() got an unexpected keyword argument 'c'
68
69 >>> g()
70 Traceback (most recent call last):
71 ...
72 TypeError: g() takes at least 1 argument (0 given)
73
74 >>> g(*())
75 Traceback (most recent call last):
76 ...
77 TypeError: g() takes at least 1 argument (0 given)
78
79 >>> g(*(), **{})
80 Traceback (most recent call last):
81 ...
82 TypeError: g() takes at least 1 argument (0 given)
83
84 >>> g(1)
85 1 () {}
86 >>> g(1, 2)
87 1 (2,) {}
88 >>> g(1, 2, 3)
89 1 (2, 3) {}
90 >>> g(1, 2, 3, *(4, 5))
91 1 (2, 3, 4, 5) {}
92
93 >>> class Nothing: pass
94 ...
95 >>> g(*Nothing())
96 Traceback (most recent call last):
97 ...
98 TypeError: g() argument after * must be a sequence, not instance
99
100 >>> class Nothing:
101 ... def __len__(self): return 5
102 ...
103
104 >>> g(*Nothing())
105 Traceback (most recent call last):
106 ...
107 TypeError: g() argument after * must be a sequence, not instance
108
109 >>> class Nothing():
110 ... def __len__(self): return 5
111 ... def __getitem__(self, i):
112 ... if i<3: return i
113 ... else: raise IndexError(i)
114 ...
115
116 >>> g(*Nothing())
117 0 (1, 2) {}
118
119 >>> class Nothing:
120 ... def __init__(self): self.c = 0
121 ... def __iter__(self): return self
122 ... def next(self):
123 ... if self.c == 4:
124 ... raise StopIteration
125 ... c = self.c
126 ... self.c += 1
127 ... return c
128 ...
129
130 >>> g(*Nothing())
131 0 (1, 2, 3) {}
132
133Make sure that the function doesn't stomp the dictionary
134
135 >>> d = {'a': 1, 'b': 2, 'c': 3}
136 >>> d2 = d.copy()
137 >>> g(1, d=4, **d)
138 1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4}
139 >>> d == d2
140 True
141
142What about willful misconduct?
143
144 >>> def saboteur(**kw):
145 ... kw['x'] = 'm'
146 ... return kw
147
148 >>> d = {}
149 >>> kw = saboteur(a=1, **d)
150 >>> d
151 {}
Jeremy Hyltonaed0d8d2000-03-28 23:51:17 +0000152
Georg Brandl2134e752007-05-21 20:34:16 +0000153
Brett Cannon0bb79502008-03-18 01:58:56 +0000154 >>> g(1, 2, 3, **{'x': 4, 'y': 5})
155 Traceback (most recent call last):
156 ...
157 TypeError: g() got multiple values for keyword argument 'x'
158
159 >>> f(**{1:2})
160 Traceback (most recent call last):
161 ...
162 TypeError: f() keywords must be strings
163
164 >>> h(**{'e': 2})
165 Traceback (most recent call last):
166 ...
167 TypeError: h() got an unexpected keyword argument 'e'
168
169 >>> h(*h)
170 Traceback (most recent call last):
171 ...
172 TypeError: h() argument after * must be a sequence, not function
173
174 >>> dir(*h)
175 Traceback (most recent call last):
176 ...
177 TypeError: dir() argument after * must be a sequence, not function
178
179 >>> None(*h)
180 Traceback (most recent call last):
181 ...
182 TypeError: NoneType object argument after * must be a sequence, \
183not function
184
185 >>> h(**h)
186 Traceback (most recent call last):
187 ...
188 TypeError: h() argument after ** must be a mapping, not function
189
190 >>> dir(**h)
191 Traceback (most recent call last):
192 ...
193 TypeError: dir() argument after ** must be a mapping, not function
194
195 >>> None(**h)
196 Traceback (most recent call last):
197 ...
198 TypeError: NoneType object argument after ** must be a mapping, \
199not function
200
201 >>> dir(b=1, **{'b': 1})
202 Traceback (most recent call last):
203 ...
204 TypeError: dir() got multiple values for keyword argument 'b'
205
206Another helper function
207
208 >>> def f2(*a, **b):
209 ... return a, b
Georg Brandl2134e752007-05-21 20:34:16 +0000210
211
Brett Cannon0bb79502008-03-18 01:58:56 +0000212 >>> d = {}
213 >>> for i in xrange(512):
214 ... key = 'k%d' % i
215 ... d[key] = i
216 >>> a, b = f2(1, *(2,3), **d)
217 >>> len(a), len(b), b == d
218 (3, 512, True)
Raymond Hettinger40174c32003-05-31 07:04:16 +0000219
Brett Cannon0bb79502008-03-18 01:58:56 +0000220 >>> class Foo:
221 ... def method(self, arg1, arg2):
222 ... return arg1+arg2
Fred Drake004d5e62000-10-23 17:22:08 +0000223
Brett Cannon0bb79502008-03-18 01:58:56 +0000224 >>> x = Foo()
225 >>> Foo.method(*(x, 1, 2))
226 3
227 >>> Foo.method(x, *(1, 2))
228 3
229 >>> Foo.method(*(1, 2, 3))
230 Traceback (most recent call last):
231 ...
232 TypeError: unbound method method() must be called with Foo instance as \
233first argument (got int instance instead)
Fred Drake004d5e62000-10-23 17:22:08 +0000234
Brett Cannon0bb79502008-03-18 01:58:56 +0000235 >>> Foo.method(1, *[2, 3])
236 Traceback (most recent call last):
237 ...
238 TypeError: unbound method method() must be called with Foo instance as \
239first argument (got int instance instead)
Fred Drake004d5e62000-10-23 17:22:08 +0000240
Brett Cannon0bb79502008-03-18 01:58:56 +0000241A PyCFunction that takes only positional parameters shoud allow an
242empty keyword dictionary to pass without a complaint, but raise a
243TypeError if te dictionary is not empty
Jeremy Hylton074c3e62000-03-30 23:55:31 +0000244
Brett Cannon0bb79502008-03-18 01:58:56 +0000245 >>> try:
246 ... silence = id(1, *{})
247 ... True
248 ... except:
249 ... False
250 True
Fred Drake004d5e62000-10-23 17:22:08 +0000251
Brett Cannon0bb79502008-03-18 01:58:56 +0000252 >>> id(1, **{'foo': 1})
253 Traceback (most recent call last):
254 ...
255 TypeError: id() takes no keyword arguments
Jeremy Hylton074c3e62000-03-30 23:55:31 +0000256
Amaury Forgeot d'Arc595f7a52009-06-25 22:29:29 +0000257A corner case of keyword dictionary items being deleted during
258the function call setup. See <http://bugs.python.org/issue2016>.
259
260 >>> class Name(str):
261 ... def __eq__(self, other):
262 ... try:
263 ... del x[self]
264 ... except KeyError:
265 ... pass
266 ... return str.__eq__(self, other)
267 ... def __hash__(self):
268 ... return str.__hash__(self)
269
270 >>> x = {Name("a"):1, Name("b"):2}
271 >>> def f(a, b):
272 ... print a,b
273 >>> f(**x)
274 1 2
Brett Cannon0bb79502008-03-18 01:58:56 +0000275"""
Samuele Pedroni8036c832004-02-21 21:03:30 +0000276
Benjamin Petersone18ef192009-01-20 14:21:16 +0000277import unittest
Brett Cannon0bb79502008-03-18 01:58:56 +0000278from test import test_support
Samuele Pedroni8036c832004-02-21 21:03:30 +0000279
Benjamin Petersone18ef192009-01-20 14:21:16 +0000280
Benjamin Petersone39b2ec2010-03-21 17:34:54 +0000281class ExtCallTest(unittest.TestCase):
Benjamin Petersone18ef192009-01-20 14:21:16 +0000282
283 def test_unicode_keywords(self):
284 def f(a):
285 return a
286 self.assertEqual(f(**{u'a': 4}), 4)
287 self.assertRaises(TypeError, f, **{u'stören': 4})
288 self.assertRaises(TypeError, f, **{u'someLongString':2})
289 try:
290 f(a=4, **{u'a': 4})
291 except TypeError:
292 pass
293 else:
294 self.fail("duplicate arguments didn't raise")
295
296
Brett Cannon0bb79502008-03-18 01:58:56 +0000297def test_main():
Benjamin Petersone39b2ec2010-03-21 17:34:54 +0000298 test_support.run_doctest(sys.modules[__name__], True)
299 test_support.run_unittest(ExtCallTest)
Jeremy Hylton074c3e62000-03-30 23:55:31 +0000300
Brett Cannon0bb79502008-03-18 01:58:56 +0000301if __name__ == '__main__':
302 test_main()