test_extcall.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. """Doctest for method/function calls.
  2. We're going the use these types for extra testing
  3. >>> from collections import UserList
  4. >>> from collections import UserDict
  5. We're defining four helper functions
  6. >>> def e(a,b):
  7. ... print(a, b)
  8. >>> def f(*a, **k):
  9. ... print(a, support.sortdict(k))
  10. >>> def g(x, *y, **z):
  11. ... print(x, y, support.sortdict(z))
  12. >>> def h(j=1, a=2, h=3):
  13. ... print(j, a, h)
  14. Argument list examples
  15. >>> f()
  16. () {}
  17. >>> f(1)
  18. (1,) {}
  19. >>> f(1, 2)
  20. (1, 2) {}
  21. >>> f(1, 2, 3)
  22. (1, 2, 3) {}
  23. >>> f(1, 2, 3, *(4, 5))
  24. (1, 2, 3, 4, 5) {}
  25. >>> f(1, 2, 3, *[4, 5])
  26. (1, 2, 3, 4, 5) {}
  27. >>> f(*[1, 2, 3], 4, 5)
  28. (1, 2, 3, 4, 5) {}
  29. >>> f(1, 2, 3, *UserList([4, 5]))
  30. (1, 2, 3, 4, 5) {}
  31. >>> f(1, 2, 3, *[4, 5], *[6, 7])
  32. (1, 2, 3, 4, 5, 6, 7) {}
  33. >>> f(1, *[2, 3], 4, *[5, 6], 7)
  34. (1, 2, 3, 4, 5, 6, 7) {}
  35. >>> f(*UserList([1, 2]), *UserList([3, 4]), 5, *UserList([6, 7]))
  36. (1, 2, 3, 4, 5, 6, 7) {}
  37. Here we add keyword arguments
  38. >>> f(1, 2, 3, **{'a':4, 'b':5})
  39. (1, 2, 3) {'a': 4, 'b': 5}
  40. >>> f(1, 2, **{'a': -1, 'b': 5}, **{'a': 4, 'c': 6})
  41. Traceback (most recent call last):
  42. ...
  43. TypeError: test.test_extcall.f() got multiple values for keyword argument 'a'
  44. >>> f(1, 2, **{'a': -1, 'b': 5}, a=4, c=6)
  45. Traceback (most recent call last):
  46. ...
  47. TypeError: test.test_extcall.f() got multiple values for keyword argument 'a'
  48. >>> f(1, 2, a=3, **{'a': 4}, **{'a': 5})
  49. Traceback (most recent call last):
  50. ...
  51. TypeError: test.test_extcall.f() got multiple values for keyword argument 'a'
  52. >>> f(1, 2, 3, *[4, 5], **{'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), **{'a':8, 'b': 9})
  55. (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
  56. >>> f(1, 2, 3, *[4, 5], **{'c': 8}, **{'a':6, 'b':7})
  57. (1, 2, 3, 4, 5) {'a': 6, 'b': 7, 'c': 8}
  58. >>> f(1, 2, 3, *(4, 5), x=6, y=7, **{'a':8, 'b': 9})
  59. (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
  60. >>> f(1, 2, 3, **UserDict(a=4, b=5))
  61. (1, 2, 3) {'a': 4, 'b': 5}
  62. >>> f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7))
  63. (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
  64. >>> f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9))
  65. (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
  66. >>> f(1, 2, 3, *(4, 5), x=6, y=7, **UserDict(a=8, b=9))
  67. (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
  68. Mix keyword arguments and dict unpacking
  69. >>> d1 = {'a':1}
  70. >>> d2 = {'c':3}
  71. >>> f(b=2, **d1, **d2)
  72. () {'a': 1, 'b': 2, 'c': 3}
  73. >>> f(**d1, b=2, **d2)
  74. () {'a': 1, 'b': 2, 'c': 3}
  75. >>> f(**d1, **d2, b=2)
  76. () {'a': 1, 'b': 2, 'c': 3}
  77. >>> f(**d1, b=2, **d2, d=4)
  78. () {'a': 1, 'b': 2, 'c': 3, 'd': 4}
  79. Examples with invalid arguments (TypeErrors). We're also testing the function
  80. names in the exception messages.
  81. Verify clearing of SF bug #733667
  82. >>> e(c=4)
  83. Traceback (most recent call last):
  84. ...
  85. TypeError: e() got an unexpected keyword argument 'c'
  86. >>> g()
  87. Traceback (most recent call last):
  88. ...
  89. TypeError: g() missing 1 required positional argument: 'x'
  90. >>> g(*())
  91. Traceback (most recent call last):
  92. ...
  93. TypeError: g() missing 1 required positional argument: 'x'
  94. >>> g(*(), **{})
  95. Traceback (most recent call last):
  96. ...
  97. TypeError: g() missing 1 required positional argument: 'x'
  98. >>> g(1)
  99. 1 () {}
  100. >>> g(1, 2)
  101. 1 (2,) {}
  102. >>> g(1, 2, 3)
  103. 1 (2, 3) {}
  104. >>> g(1, 2, 3, *(4, 5))
  105. 1 (2, 3, 4, 5) {}
  106. >>> class Nothing: pass
  107. ...
  108. >>> g(*Nothing())
  109. Traceback (most recent call last):
  110. ...
  111. TypeError: test.test_extcall.g() argument after * must be an iterable, not Nothing
  112. >>> class Nothing:
  113. ... def __len__(self): return 5
  114. ...
  115. >>> g(*Nothing())
  116. Traceback (most recent call last):
  117. ...
  118. TypeError: test.test_extcall.g() argument after * must be an iterable, not Nothing
  119. >>> class Nothing():
  120. ... def __len__(self): return 5
  121. ... def __getitem__(self, i):
  122. ... if i<3: return i
  123. ... else: raise IndexError(i)
  124. ...
  125. >>> g(*Nothing())
  126. 0 (1, 2) {}
  127. >>> class Nothing:
  128. ... def __init__(self): self.c = 0
  129. ... def __iter__(self): return self
  130. ... def __next__(self):
  131. ... if self.c == 4:
  132. ... raise StopIteration
  133. ... c = self.c
  134. ... self.c += 1
  135. ... return c
  136. ...
  137. >>> g(*Nothing())
  138. 0 (1, 2, 3) {}
  139. Check for issue #4806: Does a TypeError in a generator get propagated with the
  140. right error message? (Also check with other iterables.)
  141. >>> def broken(): raise TypeError("myerror")
  142. ...
  143. >>> g(*(broken() for i in range(1)))
  144. Traceback (most recent call last):
  145. ...
  146. TypeError: myerror
  147. >>> g(*range(1), *(broken() for i in range(1)))
  148. Traceback (most recent call last):
  149. ...
  150. TypeError: myerror
  151. >>> class BrokenIterable1:
  152. ... def __iter__(self):
  153. ... raise TypeError('myerror')
  154. ...
  155. >>> g(*BrokenIterable1())
  156. Traceback (most recent call last):
  157. ...
  158. TypeError: myerror
  159. >>> g(*range(1), *BrokenIterable1())
  160. Traceback (most recent call last):
  161. ...
  162. TypeError: myerror
  163. >>> class BrokenIterable2:
  164. ... def __iter__(self):
  165. ... yield 0
  166. ... raise TypeError('myerror')
  167. ...
  168. >>> g(*BrokenIterable2())
  169. Traceback (most recent call last):
  170. ...
  171. TypeError: myerror
  172. >>> g(*range(1), *BrokenIterable2())
  173. Traceback (most recent call last):
  174. ...
  175. TypeError: myerror
  176. >>> class BrokenSequence:
  177. ... def __getitem__(self, idx):
  178. ... raise TypeError('myerror')
  179. ...
  180. >>> g(*BrokenSequence())
  181. Traceback (most recent call last):
  182. ...
  183. TypeError: myerror
  184. >>> g(*range(1), *BrokenSequence())
  185. Traceback (most recent call last):
  186. ...
  187. TypeError: myerror
  188. Make sure that the function doesn't stomp the dictionary
  189. >>> d = {'a': 1, 'b': 2, 'c': 3}
  190. >>> d2 = d.copy()
  191. >>> g(1, d=4, **d)
  192. 1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4}
  193. >>> d == d2
  194. True
  195. What about willful misconduct?
  196. >>> def saboteur(**kw):
  197. ... kw['x'] = 'm'
  198. ... return kw
  199. >>> d = {}
  200. >>> kw = saboteur(a=1, **d)
  201. >>> d
  202. {}
  203. >>> g(1, 2, 3, **{'x': 4, 'y': 5})
  204. Traceback (most recent call last):
  205. ...
  206. TypeError: g() got multiple values for argument 'x'
  207. >>> f(**{1:2})
  208. Traceback (most recent call last):
  209. ...
  210. TypeError: keywords must be strings
  211. >>> h(**{'e': 2})
  212. Traceback (most recent call last):
  213. ...
  214. TypeError: h() got an unexpected keyword argument 'e'
  215. >>> h(*h)
  216. Traceback (most recent call last):
  217. ...
  218. TypeError: test.test_extcall.h() argument after * must be an iterable, not function
  219. >>> h(1, *h)
  220. Traceback (most recent call last):
  221. ...
  222. TypeError: Value after * must be an iterable, not function
  223. >>> h(*[1], *h)
  224. Traceback (most recent call last):
  225. ...
  226. TypeError: Value after * must be an iterable, not function
  227. >>> dir(*h)
  228. Traceback (most recent call last):
  229. ...
  230. TypeError: dir() argument after * must be an iterable, not function
  231. >>> nothing = None
  232. >>> nothing(*h)
  233. Traceback (most recent call last):
  234. ...
  235. TypeError: None argument after * must be an iterable, \
  236. not function
  237. >>> h(**h)
  238. Traceback (most recent call last):
  239. ...
  240. TypeError: test.test_extcall.h() argument after ** must be a mapping, not function
  241. >>> h(**[])
  242. Traceback (most recent call last):
  243. ...
  244. TypeError: test.test_extcall.h() argument after ** must be a mapping, not list
  245. >>> h(a=1, **h)
  246. Traceback (most recent call last):
  247. ...
  248. TypeError: test.test_extcall.h() argument after ** must be a mapping, not function
  249. >>> h(a=1, **[])
  250. Traceback (most recent call last):
  251. ...
  252. TypeError: test.test_extcall.h() argument after ** must be a mapping, not list
  253. >>> h(**{'a': 1}, **h)
  254. Traceback (most recent call last):
  255. ...
  256. TypeError: test.test_extcall.h() argument after ** must be a mapping, not function
  257. >>> h(**{'a': 1}, **[])
  258. Traceback (most recent call last):
  259. ...
  260. TypeError: test.test_extcall.h() argument after ** must be a mapping, not list
  261. >>> dir(**h)
  262. Traceback (most recent call last):
  263. ...
  264. TypeError: dir() argument after ** must be a mapping, not function
  265. >>> nothing(**h)
  266. Traceback (most recent call last):
  267. ...
  268. TypeError: None argument after ** must be a mapping, \
  269. not function
  270. >>> dir(b=1, **{'b': 1})
  271. Traceback (most recent call last):
  272. ...
  273. TypeError: dir() got multiple values for keyword argument 'b'
  274. Test a kwargs mapping with duplicated keys.
  275. >>> from collections.abc import Mapping
  276. >>> class MultiDict(Mapping):
  277. ... def __init__(self, items):
  278. ... self._items = items
  279. ...
  280. ... def __iter__(self):
  281. ... return (k for k, v in self._items)
  282. ...
  283. ... def __getitem__(self, key):
  284. ... for k, v in self._items:
  285. ... if k == key:
  286. ... return v
  287. ... raise KeyError(key)
  288. ...
  289. ... def __len__(self):
  290. ... return len(self._items)
  291. ...
  292. ... def keys(self):
  293. ... return [k for k, v in self._items]
  294. ...
  295. ... def values(self):
  296. ... return [v for k, v in self._items]
  297. ...
  298. ... def items(self):
  299. ... return [(k, v) for k, v in self._items]
  300. ...
  301. >>> g(**MultiDict([('x', 1), ('y', 2)]))
  302. 1 () {'y': 2}
  303. >>> g(**MultiDict([('x', 1), ('x', 2)]))
  304. Traceback (most recent call last):
  305. ...
  306. TypeError: test.test_extcall.g() got multiple values for keyword argument 'x'
  307. >>> g(a=3, **MultiDict([('x', 1), ('x', 2)]))
  308. Traceback (most recent call last):
  309. ...
  310. TypeError: test.test_extcall.g() got multiple values for keyword argument 'x'
  311. >>> g(**MultiDict([('a', 3)]), **MultiDict([('x', 1), ('x', 2)]))
  312. Traceback (most recent call last):
  313. ...
  314. TypeError: test.test_extcall.g() got multiple values for keyword argument 'x'
  315. Another helper function
  316. >>> def f2(*a, **b):
  317. ... return a, b
  318. >>> d = {}
  319. >>> for i in range(512):
  320. ... key = 'k%d' % i
  321. ... d[key] = i
  322. >>> a, b = f2(1, *(2,3), **d)
  323. >>> len(a), len(b), b == d
  324. (3, 512, True)
  325. >>> class Foo:
  326. ... def method(self, arg1, arg2):
  327. ... return arg1+arg2
  328. >>> x = Foo()
  329. >>> Foo.method(*(x, 1, 2))
  330. 3
  331. >>> Foo.method(x, *(1, 2))
  332. 3
  333. >>> Foo.method(*(1, 2, 3))
  334. 5
  335. >>> Foo.method(1, *[2, 3])
  336. 5
  337. A PyCFunction that takes only positional parameters should allow an
  338. empty keyword dictionary to pass without a complaint, but raise a
  339. TypeError if te dictionary is not empty
  340. >>> try:
  341. ... silence = id(1, *{})
  342. ... True
  343. ... except:
  344. ... False
  345. True
  346. >>> id(1, **{'foo': 1})
  347. Traceback (most recent call last):
  348. ...
  349. TypeError: id() takes no keyword arguments
  350. A corner case of keyword dictionary items being deleted during
  351. the function call setup. See <http://bugs.python.org/issue2016>.
  352. >>> class Name(str):
  353. ... def __eq__(self, other):
  354. ... try:
  355. ... del x[self]
  356. ... except KeyError:
  357. ... pass
  358. ... return str.__eq__(self, other)
  359. ... def __hash__(self):
  360. ... return str.__hash__(self)
  361. >>> x = {Name("a"):1, Name("b"):2}
  362. >>> def f(a, b):
  363. ... print(a,b)
  364. >>> f(**x)
  365. 1 2
  366. Too many arguments:
  367. >>> def f(): pass
  368. >>> f(1)
  369. Traceback (most recent call last):
  370. ...
  371. TypeError: f() takes 0 positional arguments but 1 was given
  372. >>> def f(a): pass
  373. >>> f(1, 2)
  374. Traceback (most recent call last):
  375. ...
  376. TypeError: f() takes 1 positional argument but 2 were given
  377. >>> def f(a, b=1): pass
  378. >>> f(1, 2, 3)
  379. Traceback (most recent call last):
  380. ...
  381. TypeError: f() takes from 1 to 2 positional arguments but 3 were given
  382. >>> def f(*, kw): pass
  383. >>> f(1, kw=3)
  384. Traceback (most recent call last):
  385. ...
  386. TypeError: f() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
  387. >>> def f(*, kw, b): pass
  388. >>> f(1, 2, 3, b=3, kw=3)
  389. Traceback (most recent call last):
  390. ...
  391. TypeError: f() takes 0 positional arguments but 3 positional arguments (and 2 keyword-only arguments) were given
  392. >>> def f(a, b=2, *, kw): pass
  393. >>> f(2, 3, 4, kw=4)
  394. Traceback (most recent call last):
  395. ...
  396. TypeError: f() takes from 1 to 2 positional arguments but 3 positional arguments (and 1 keyword-only argument) were given
  397. Too few and missing arguments:
  398. >>> def f(a): pass
  399. >>> f()
  400. Traceback (most recent call last):
  401. ...
  402. TypeError: f() missing 1 required positional argument: 'a'
  403. >>> def f(a, b): pass
  404. >>> f()
  405. Traceback (most recent call last):
  406. ...
  407. TypeError: f() missing 2 required positional arguments: 'a' and 'b'
  408. >>> def f(a, b, c): pass
  409. >>> f()
  410. Traceback (most recent call last):
  411. ...
  412. TypeError: f() missing 3 required positional arguments: 'a', 'b', and 'c'
  413. >>> def f(a, b, c, d, e): pass
  414. >>> f()
  415. Traceback (most recent call last):
  416. ...
  417. TypeError: f() missing 5 required positional arguments: 'a', 'b', 'c', 'd', and 'e'
  418. >>> def f(a, b=4, c=5, d=5): pass
  419. >>> f(c=12, b=9)
  420. Traceback (most recent call last):
  421. ...
  422. TypeError: f() missing 1 required positional argument: 'a'
  423. Same with keyword only args:
  424. >>> def f(*, w): pass
  425. >>> f()
  426. Traceback (most recent call last):
  427. ...
  428. TypeError: f() missing 1 required keyword-only argument: 'w'
  429. >>> def f(*, a, b, c, d, e): pass
  430. >>> f()
  431. Traceback (most recent call last):
  432. ...
  433. TypeError: f() missing 5 required keyword-only arguments: 'a', 'b', 'c', 'd', and 'e'
  434. """
  435. import doctest
  436. import unittest
  437. from test import support
  438. def load_tests(loader, tests, pattern):
  439. tests.addTest(doctest.DocTestSuite())
  440. return tests
  441. if __name__ == '__main__':
  442. unittest.main()