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 an iterable, 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 an iterable, 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 Check for issue #4806: Does a TypeError in a generator get propagated with the 132 right error message? 133 134 >>> def broken(): raise TypeError("myerror") 135 ... 136 137 >>> g(*(broken() for i in range(1))) 138 Traceback (most recent call last): 139 ... 140 TypeError: myerror 141 142 Make sure that the function doesn't stomp the dictionary 143 144 >>> d = {'a': 1, 'b': 2, 'c': 3} 145 >>> d2 = d.copy() 146 >>> g(1, d=4, **d) 147 1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4} 148 >>> d == d2 149 True 150 151 What about willful misconduct? 152 153 >>> def saboteur(**kw): 154 ... kw['x'] = 'm' 155 ... return kw 156 157 >>> d = {} 158 >>> kw = saboteur(a=1, **d) 159 >>> d 160 {} 161 162 163 >>> g(1, 2, 3, **{'x': 4, 'y': 5}) 164 Traceback (most recent call last): 165 ... 166 TypeError: g() got multiple values for keyword argument 'x' 167 168 >>> f(**{1:2}) 169 Traceback (most recent call last): 170 ... 171 TypeError: f() keywords must be strings 172 173 >>> h(**{'e': 2}) 174 Traceback (most recent call last): 175 ... 176 TypeError: h() got an unexpected keyword argument 'e' 177 178 >>> h(*h) 179 Traceback (most recent call last): 180 ... 181 TypeError: h() argument after * must be an iterable, not function 182 183 >>> h(1, *h) 184 Traceback (most recent call last): 185 ... 186 TypeError: h() argument after * must be an iterable, not function 187 188 >>> dir(*h) 189 Traceback (most recent call last): 190 ... 191 TypeError: dir() argument after * must be an iterable, not function 192 193 >>> None(*h) 194 Traceback (most recent call last): 195 ... 196 TypeError: NoneType object argument after * must be an iterable, \ 197 not function 198 199 >>> h(**h) 200 Traceback (most recent call last): 201 ... 202 TypeError: h() argument after ** must be a mapping, not function 203 204 >>> h(**[]) 205 Traceback (most recent call last): 206 ... 207 TypeError: h() argument after ** must be a mapping, not list 208 209 >>> h(a=1, **h) 210 Traceback (most recent call last): 211 ... 212 TypeError: h() argument after ** must be a mapping, not function 213 214 >>> h(a=1, **[]) 215 Traceback (most recent call last): 216 ... 217 TypeError: h() argument after ** must be a mapping, not list 218 219 >>> dir(**h) 220 Traceback (most recent call last): 221 ... 222 TypeError: dir() argument after ** must be a mapping, not function 223 224 >>> None(**h) 225 Traceback (most recent call last): 226 ... 227 TypeError: NoneType object argument after ** must be a mapping, \ 228 not function 229 230 >>> dir(b=1, **{'b': 1}) 231 Traceback (most recent call last): 232 ... 233 TypeError: dir() got multiple values for keyword argument 'b' 234 235 Another helper function 236 237 >>> def f2(*a, **b): 238 ... return a, b 239 240 241 >>> d = {} 242 >>> for i in xrange(512): 243 ... key = 'k%d' % i 244 ... d[key] = i 245 >>> a, b = f2(1, *(2,3), **d) 246 >>> len(a), len(b), b == d 247 (3, 512, True) 248 249 >>> class Foo: 250 ... def method(self, arg1, arg2): 251 ... return arg1+arg2 252 253 >>> x = Foo() 254 >>> Foo.method(*(x, 1, 2)) 255 3 256 >>> Foo.method(x, *(1, 2)) 257 3 258 >>> Foo.method(*(1, 2, 3)) 259 Traceback (most recent call last): 260 ... 261 TypeError: unbound method method() must be called with Foo instance as \ 262 first argument (got int instance instead) 263 264 >>> Foo.method(1, *[2, 3]) 265 Traceback (most recent call last): 266 ... 267 TypeError: unbound method method() must be called with Foo instance as \ 268 first argument (got int instance instead) 269 270 A PyCFunction that takes only positional parameters should allow an 271 empty keyword dictionary to pass without a complaint, but raise a 272 TypeError if te dictionary is not empty 273 274 >>> try: 275 ... silence = id(1, *{}) 276 ... True 277 ... except: 278 ... False 279 True 280 281 >>> id(1, **{'foo': 1}) 282 Traceback (most recent call last): 283 ... 284 TypeError: id() takes no keyword arguments 285 286 A corner case of keyword dictionary items being deleted during 287 the function call setup. See <http://bugs.python.org/issue2016>. 288 289 >>> class Name(str): 290 ... def __eq__(self, other): 291 ... try: 292 ... del x[self] 293 ... except KeyError: 294 ... pass 295 ... return str.__eq__(self, other) 296 ... def __hash__(self): 297 ... return str.__hash__(self) 298 299 >>> x = {Name("a"):1, Name("b"):2} 300 >>> def f(a, b): 301 ... print a,b 302 >>> f(**x) 303 1 2 304 305 An obscure message: 306 307 >>> def f(a, b): 308 ... pass 309 >>> f(b=1) 310 Traceback (most recent call last): 311 ... 312 TypeError: f() takes exactly 2 arguments (1 given) 313 314 The number of arguments passed in includes keywords: 315 316 >>> def f(a): 317 ... pass 318 >>> f(6, a=4, *(1, 2, 3)) 319 Traceback (most recent call last): 320 ... 321 TypeError: f() takes exactly 1 argument (5 given) 322 """ 323 324 import unittest 325 import sys 326 from test import test_support 327 328 329 class ExtCallTest(unittest.TestCase): 330 331 def test_unicode_keywords(self): 332 def f(a): 333 return a 334 self.assertEqual(f(**{u'a': 4}), 4) 335 self.assertRaises(TypeError, f, **{u'stren': 4}) 336 self.assertRaises(TypeError, f, **{u'someLongString':2}) 337 try: 338 f(a=4, **{u'a': 4}) 339 except TypeError: 340 pass 341 else: 342 self.fail("duplicate arguments didn't raise") 343 344 345 def test_main(): 346 test_support.run_doctest(sys.modules[__name__], True) 347 test_support.run_unittest(ExtCallTest) 348 349 if __name__ == '__main__': 350 test_main() 351