test_class.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. "Test the functionality of Python classes implementing operators."
  2. import unittest
  3. testmeths = [
  4. # Binary operations
  5. "add",
  6. "radd",
  7. "sub",
  8. "rsub",
  9. "mul",
  10. "rmul",
  11. "matmul",
  12. "rmatmul",
  13. "truediv",
  14. "rtruediv",
  15. "floordiv",
  16. "rfloordiv",
  17. "mod",
  18. "rmod",
  19. "divmod",
  20. "rdivmod",
  21. "pow",
  22. "rpow",
  23. "rshift",
  24. "rrshift",
  25. "lshift",
  26. "rlshift",
  27. "and",
  28. "rand",
  29. "or",
  30. "ror",
  31. "xor",
  32. "rxor",
  33. # List/dict operations
  34. "contains",
  35. "getitem",
  36. "setitem",
  37. "delitem",
  38. # Unary operations
  39. "neg",
  40. "pos",
  41. "abs",
  42. # generic operations
  43. "init",
  44. ]
  45. # These need to return something other than None
  46. # "hash",
  47. # "str",
  48. # "repr",
  49. # "int",
  50. # "float",
  51. # These are separate because they can influence the test of other methods.
  52. # "getattr",
  53. # "setattr",
  54. # "delattr",
  55. callLst = []
  56. def trackCall(f):
  57. def track(*args, **kwargs):
  58. callLst.append((f.__name__, args))
  59. return f(*args, **kwargs)
  60. return track
  61. statictests = """
  62. @trackCall
  63. def __hash__(self, *args):
  64. return hash(id(self))
  65. @trackCall
  66. def __str__(self, *args):
  67. return "AllTests"
  68. @trackCall
  69. def __repr__(self, *args):
  70. return "AllTests"
  71. @trackCall
  72. def __int__(self, *args):
  73. return 1
  74. @trackCall
  75. def __index__(self, *args):
  76. return 1
  77. @trackCall
  78. def __float__(self, *args):
  79. return 1.0
  80. @trackCall
  81. def __eq__(self, *args):
  82. return True
  83. @trackCall
  84. def __ne__(self, *args):
  85. return False
  86. @trackCall
  87. def __lt__(self, *args):
  88. return False
  89. @trackCall
  90. def __le__(self, *args):
  91. return True
  92. @trackCall
  93. def __gt__(self, *args):
  94. return False
  95. @trackCall
  96. def __ge__(self, *args):
  97. return True
  98. """
  99. # Synthesize all the other AllTests methods from the names in testmeths.
  100. method_template = """\
  101. @trackCall
  102. def __%s__(self, *args):
  103. pass
  104. """
  105. d = {}
  106. exec(statictests, globals(), d)
  107. for method in testmeths:
  108. exec(method_template % method, globals(), d)
  109. AllTests = type("AllTests", (object,), d)
  110. del d, statictests, method, method_template
  111. class ClassTests(unittest.TestCase):
  112. def setUp(self):
  113. callLst[:] = []
  114. def assertCallStack(self, expected_calls):
  115. actualCallList = callLst[:] # need to copy because the comparison below will add
  116. # additional calls to callLst
  117. if expected_calls != actualCallList:
  118. self.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" %
  119. (expected_calls, actualCallList))
  120. def testInit(self):
  121. foo = AllTests()
  122. self.assertCallStack([("__init__", (foo,))])
  123. def testBinaryOps(self):
  124. testme = AllTests()
  125. # Binary operations
  126. callLst[:] = []
  127. testme + 1
  128. self.assertCallStack([("__add__", (testme, 1))])
  129. callLst[:] = []
  130. 1 + testme
  131. self.assertCallStack([("__radd__", (testme, 1))])
  132. callLst[:] = []
  133. testme - 1
  134. self.assertCallStack([("__sub__", (testme, 1))])
  135. callLst[:] = []
  136. 1 - testme
  137. self.assertCallStack([("__rsub__", (testme, 1))])
  138. callLst[:] = []
  139. testme * 1
  140. self.assertCallStack([("__mul__", (testme, 1))])
  141. callLst[:] = []
  142. 1 * testme
  143. self.assertCallStack([("__rmul__", (testme, 1))])
  144. callLst[:] = []
  145. testme @ 1
  146. self.assertCallStack([("__matmul__", (testme, 1))])
  147. callLst[:] = []
  148. 1 @ testme
  149. self.assertCallStack([("__rmatmul__", (testme, 1))])
  150. callLst[:] = []
  151. testme / 1
  152. self.assertCallStack([("__truediv__", (testme, 1))])
  153. callLst[:] = []
  154. 1 / testme
  155. self.assertCallStack([("__rtruediv__", (testme, 1))])
  156. callLst[:] = []
  157. testme // 1
  158. self.assertCallStack([("__floordiv__", (testme, 1))])
  159. callLst[:] = []
  160. 1 // testme
  161. self.assertCallStack([("__rfloordiv__", (testme, 1))])
  162. callLst[:] = []
  163. testme % 1
  164. self.assertCallStack([("__mod__", (testme, 1))])
  165. callLst[:] = []
  166. 1 % testme
  167. self.assertCallStack([("__rmod__", (testme, 1))])
  168. callLst[:] = []
  169. divmod(testme,1)
  170. self.assertCallStack([("__divmod__", (testme, 1))])
  171. callLst[:] = []
  172. divmod(1, testme)
  173. self.assertCallStack([("__rdivmod__", (testme, 1))])
  174. callLst[:] = []
  175. testme ** 1
  176. self.assertCallStack([("__pow__", (testme, 1))])
  177. callLst[:] = []
  178. 1 ** testme
  179. self.assertCallStack([("__rpow__", (testme, 1))])
  180. callLst[:] = []
  181. testme >> 1
  182. self.assertCallStack([("__rshift__", (testme, 1))])
  183. callLst[:] = []
  184. 1 >> testme
  185. self.assertCallStack([("__rrshift__", (testme, 1))])
  186. callLst[:] = []
  187. testme << 1
  188. self.assertCallStack([("__lshift__", (testme, 1))])
  189. callLst[:] = []
  190. 1 << testme
  191. self.assertCallStack([("__rlshift__", (testme, 1))])
  192. callLst[:] = []
  193. testme & 1
  194. self.assertCallStack([("__and__", (testme, 1))])
  195. callLst[:] = []
  196. 1 & testme
  197. self.assertCallStack([("__rand__", (testme, 1))])
  198. callLst[:] = []
  199. testme | 1
  200. self.assertCallStack([("__or__", (testme, 1))])
  201. callLst[:] = []
  202. 1 | testme
  203. self.assertCallStack([("__ror__", (testme, 1))])
  204. callLst[:] = []
  205. testme ^ 1
  206. self.assertCallStack([("__xor__", (testme, 1))])
  207. callLst[:] = []
  208. 1 ^ testme
  209. self.assertCallStack([("__rxor__", (testme, 1))])
  210. def testListAndDictOps(self):
  211. testme = AllTests()
  212. # List/dict operations
  213. class Empty: pass
  214. try:
  215. 1 in Empty()
  216. self.fail('failed, should have raised TypeError')
  217. except TypeError:
  218. pass
  219. callLst[:] = []
  220. 1 in testme
  221. self.assertCallStack([('__contains__', (testme, 1))])
  222. callLst[:] = []
  223. testme[1]
  224. self.assertCallStack([('__getitem__', (testme, 1))])
  225. callLst[:] = []
  226. testme[1] = 1
  227. self.assertCallStack([('__setitem__', (testme, 1, 1))])
  228. callLst[:] = []
  229. del testme[1]
  230. self.assertCallStack([('__delitem__', (testme, 1))])
  231. callLst[:] = []
  232. testme[:42]
  233. self.assertCallStack([('__getitem__', (testme, slice(None, 42)))])
  234. callLst[:] = []
  235. testme[:42] = "The Answer"
  236. self.assertCallStack([('__setitem__', (testme, slice(None, 42),
  237. "The Answer"))])
  238. callLst[:] = []
  239. del testme[:42]
  240. self.assertCallStack([('__delitem__', (testme, slice(None, 42)))])
  241. callLst[:] = []
  242. testme[2:1024:10]
  243. self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
  244. callLst[:] = []
  245. testme[2:1024:10] = "A lot"
  246. self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10),
  247. "A lot"))])
  248. callLst[:] = []
  249. del testme[2:1024:10]
  250. self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))])
  251. callLst[:] = []
  252. testme[:42, ..., :24:, 24, 100]
  253. self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None),
  254. Ellipsis,
  255. slice(None, 24, None),
  256. 24, 100)))])
  257. callLst[:] = []
  258. testme[:42, ..., :24:, 24, 100] = "Strange"
  259. self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None),
  260. Ellipsis,
  261. slice(None, 24, None),
  262. 24, 100), "Strange"))])
  263. callLst[:] = []
  264. del testme[:42, ..., :24:, 24, 100]
  265. self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None),
  266. Ellipsis,
  267. slice(None, 24, None),
  268. 24, 100)))])
  269. def testUnaryOps(self):
  270. testme = AllTests()
  271. callLst[:] = []
  272. -testme
  273. self.assertCallStack([('__neg__', (testme,))])
  274. callLst[:] = []
  275. +testme
  276. self.assertCallStack([('__pos__', (testme,))])
  277. callLst[:] = []
  278. abs(testme)
  279. self.assertCallStack([('__abs__', (testme,))])
  280. callLst[:] = []
  281. int(testme)
  282. self.assertCallStack([('__int__', (testme,))])
  283. callLst[:] = []
  284. float(testme)
  285. self.assertCallStack([('__float__', (testme,))])
  286. callLst[:] = []
  287. oct(testme)
  288. self.assertCallStack([('__index__', (testme,))])
  289. callLst[:] = []
  290. hex(testme)
  291. self.assertCallStack([('__index__', (testme,))])
  292. def testMisc(self):
  293. testme = AllTests()
  294. callLst[:] = []
  295. hash(testme)
  296. self.assertCallStack([('__hash__', (testme,))])
  297. callLst[:] = []
  298. repr(testme)
  299. self.assertCallStack([('__repr__', (testme,))])
  300. callLst[:] = []
  301. str(testme)
  302. self.assertCallStack([('__str__', (testme,))])
  303. callLst[:] = []
  304. testme == 1
  305. self.assertCallStack([('__eq__', (testme, 1))])
  306. callLst[:] = []
  307. testme < 1
  308. self.assertCallStack([('__lt__', (testme, 1))])
  309. callLst[:] = []
  310. testme > 1
  311. self.assertCallStack([('__gt__', (testme, 1))])
  312. callLst[:] = []
  313. testme != 1
  314. self.assertCallStack([('__ne__', (testme, 1))])
  315. callLst[:] = []
  316. 1 == testme
  317. self.assertCallStack([('__eq__', (1, testme))])
  318. callLst[:] = []
  319. 1 < testme
  320. self.assertCallStack([('__gt__', (1, testme))])
  321. callLst[:] = []
  322. 1 > testme
  323. self.assertCallStack([('__lt__', (1, testme))])
  324. callLst[:] = []
  325. 1 != testme
  326. self.assertCallStack([('__ne__', (1, testme))])
  327. def testGetSetAndDel(self):
  328. # Interfering tests
  329. class ExtraTests(AllTests):
  330. @trackCall
  331. def __getattr__(self, *args):
  332. return "SomeVal"
  333. @trackCall
  334. def __setattr__(self, *args):
  335. pass
  336. @trackCall
  337. def __delattr__(self, *args):
  338. pass
  339. testme = ExtraTests()
  340. callLst[:] = []
  341. testme.spam
  342. self.assertCallStack([('__getattr__', (testme, "spam"))])
  343. callLst[:] = []
  344. testme.eggs = "spam, spam, spam and ham"
  345. self.assertCallStack([('__setattr__', (testme, "eggs",
  346. "spam, spam, spam and ham"))])
  347. callLst[:] = []
  348. del testme.cardinal
  349. self.assertCallStack([('__delattr__', (testme, "cardinal"))])
  350. def testDel(self):
  351. x = []
  352. class DelTest:
  353. def __del__(self):
  354. x.append("crab people, crab people")
  355. testme = DelTest()
  356. del testme
  357. import gc
  358. gc.collect()
  359. self.assertEqual(["crab people, crab people"], x)
  360. def testBadTypeReturned(self):
  361. # return values of some method are type-checked
  362. class BadTypeClass:
  363. def __int__(self):
  364. return None
  365. __float__ = __int__
  366. __complex__ = __int__
  367. __str__ = __int__
  368. __repr__ = __int__
  369. __bytes__ = __int__
  370. __bool__ = __int__
  371. __index__ = __int__
  372. def index(x):
  373. return [][x]
  374. for f in [float, complex, str, repr, bytes, bin, oct, hex, bool, index]:
  375. self.assertRaises(TypeError, f, BadTypeClass())
  376. def testHashStuff(self):
  377. # Test correct errors from hash() on objects with comparisons but
  378. # no __hash__
  379. class C0:
  380. pass
  381. hash(C0()) # This should work; the next two should raise TypeError
  382. class C2:
  383. def __eq__(self, other): return 1
  384. self.assertRaises(TypeError, hash, C2())
  385. def testSFBug532646(self):
  386. # Test for SF bug 532646
  387. class A:
  388. pass
  389. A.__call__ = A()
  390. a = A()
  391. try:
  392. a() # This should not segfault
  393. except RecursionError:
  394. pass
  395. else:
  396. self.fail("Failed to raise RecursionError")
  397. def testForExceptionsRaisedInInstanceGetattr2(self):
  398. # Tests for exceptions raised in instance_getattr2().
  399. def booh(self):
  400. raise AttributeError("booh")
  401. class A:
  402. a = property(booh)
  403. try:
  404. A().a # Raised AttributeError: A instance has no attribute 'a'
  405. except AttributeError as x:
  406. if str(x) != "booh":
  407. self.fail("attribute error for A().a got masked: %s" % x)
  408. class E:
  409. __eq__ = property(booh)
  410. E() == E() # In debug mode, caused a C-level assert() to fail
  411. class I:
  412. __init__ = property(booh)
  413. try:
  414. # In debug mode, printed XXX undetected error and
  415. # raises AttributeError
  416. I()
  417. except AttributeError:
  418. pass
  419. else:
  420. self.fail("attribute error for I.__init__ got masked")
  421. def assertNotOrderable(self, a, b):
  422. with self.assertRaises(TypeError):
  423. a < b
  424. with self.assertRaises(TypeError):
  425. a > b
  426. with self.assertRaises(TypeError):
  427. a <= b
  428. with self.assertRaises(TypeError):
  429. a >= b
  430. def testHashComparisonOfMethods(self):
  431. # Test comparison and hash of methods
  432. class A:
  433. def __init__(self, x):
  434. self.x = x
  435. def f(self):
  436. pass
  437. def g(self):
  438. pass
  439. def __eq__(self, other):
  440. return True
  441. def __hash__(self):
  442. raise TypeError
  443. class B(A):
  444. pass
  445. a1 = A(1)
  446. a2 = A(1)
  447. self.assertTrue(a1.f == a1.f)
  448. self.assertFalse(a1.f != a1.f)
  449. self.assertFalse(a1.f == a2.f)
  450. self.assertTrue(a1.f != a2.f)
  451. self.assertFalse(a1.f == a1.g)
  452. self.assertTrue(a1.f != a1.g)
  453. self.assertNotOrderable(a1.f, a1.f)
  454. self.assertEqual(hash(a1.f), hash(a1.f))
  455. self.assertFalse(A.f == a1.f)
  456. self.assertTrue(A.f != a1.f)
  457. self.assertFalse(A.f == A.g)
  458. self.assertTrue(A.f != A.g)
  459. self.assertTrue(B.f == A.f)
  460. self.assertFalse(B.f != A.f)
  461. self.assertNotOrderable(A.f, A.f)
  462. self.assertEqual(hash(B.f), hash(A.f))
  463. # the following triggers a SystemError in 2.4
  464. a = A(hash(A.f)^(-1))
  465. hash(a.f)
  466. def testSetattrWrapperNameIntern(self):
  467. # Issue #25794: __setattr__ should intern the attribute name
  468. class A:
  469. pass
  470. def add(self, other):
  471. return 'summa'
  472. name = str(b'__add__', 'ascii') # shouldn't be optimized
  473. self.assertIsNot(name, '__add__') # not interned
  474. type.__setattr__(A, name, add)
  475. self.assertEqual(A() + 1, 'summa')
  476. name2 = str(b'__add__', 'ascii')
  477. self.assertIsNot(name2, '__add__')
  478. self.assertIsNot(name2, name)
  479. type.__delattr__(A, name2)
  480. with self.assertRaises(TypeError):
  481. A() + 1
  482. def testSetattrNonStringName(self):
  483. class A:
  484. pass
  485. with self.assertRaises(TypeError):
  486. type.__setattr__(A, b'x', None)
  487. def testTypeAttributeAccessErrorMessages(self):
  488. class A:
  489. pass
  490. error_msg = "type object 'A' has no attribute 'x'"
  491. with self.assertRaisesRegex(AttributeError, error_msg):
  492. A.x
  493. with self.assertRaisesRegex(AttributeError, error_msg):
  494. del A.x
  495. def testObjectAttributeAccessErrorMessages(self):
  496. class A:
  497. pass
  498. class B:
  499. y = 0
  500. __slots__ = ('z',)
  501. error_msg = "'A' object has no attribute 'x'"
  502. with self.assertRaisesRegex(AttributeError, error_msg):
  503. A().x
  504. with self.assertRaisesRegex(AttributeError, error_msg):
  505. del A().x
  506. error_msg = "'B' object has no attribute 'x'"
  507. with self.assertRaisesRegex(AttributeError, error_msg):
  508. B().x
  509. with self.assertRaisesRegex(AttributeError, error_msg):
  510. del B().x
  511. with self.assertRaisesRegex(AttributeError, error_msg):
  512. B().x = 0
  513. error_msg = "'B' object attribute 'y' is read-only"
  514. with self.assertRaisesRegex(AttributeError, error_msg):
  515. del B().y
  516. with self.assertRaisesRegex(AttributeError, error_msg):
  517. B().y = 0
  518. error_msg = 'z'
  519. with self.assertRaisesRegex(AttributeError, error_msg):
  520. B().z
  521. with self.assertRaisesRegex(AttributeError, error_msg):
  522. del B().z
  523. def testConstructorErrorMessages(self):
  524. # bpo-31506: Improves the error message logic for object_new & object_init
  525. # Class without any method overrides
  526. class C:
  527. pass
  528. error_msg = r'C.__init__\(\) takes exactly one argument \(the instance to initialize\)'
  529. with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
  530. C(42)
  531. with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
  532. C.__new__(C, 42)
  533. with self.assertRaisesRegex(TypeError, error_msg):
  534. C().__init__(42)
  535. with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
  536. object.__new__(C, 42)
  537. with self.assertRaisesRegex(TypeError, error_msg):
  538. object.__init__(C(), 42)
  539. # Class with both `__init__` & `__new__` method overridden
  540. class D:
  541. def __new__(cls, *args, **kwargs):
  542. super().__new__(cls, *args, **kwargs)
  543. def __init__(self, *args, **kwargs):
  544. super().__init__(*args, **kwargs)
  545. error_msg = r'object.__new__\(\) takes exactly one argument \(the type to instantiate\)'
  546. with self.assertRaisesRegex(TypeError, error_msg):
  547. D(42)
  548. with self.assertRaisesRegex(TypeError, error_msg):
  549. D.__new__(D, 42)
  550. with self.assertRaisesRegex(TypeError, error_msg):
  551. object.__new__(D, 42)
  552. # Class that only overrides __init__
  553. class E:
  554. def __init__(self, *args, **kwargs):
  555. super().__init__(*args, **kwargs)
  556. error_msg = r'object.__init__\(\) takes exactly one argument \(the instance to initialize\)'
  557. with self.assertRaisesRegex(TypeError, error_msg):
  558. E().__init__(42)
  559. with self.assertRaisesRegex(TypeError, error_msg):
  560. object.__init__(E(), 42)
  561. def testClassWithExtCall(self):
  562. class Meta(int):
  563. def __init__(*args, **kwargs):
  564. pass
  565. def __new__(cls, name, bases, attrs, **kwargs):
  566. return bases, kwargs
  567. d = {'metaclass': Meta}
  568. class A(**d): pass
  569. self.assertEqual(A, ((), {}))
  570. class A(0, 1, 2, 3, 4, 5, 6, 7, **d): pass
  571. self.assertEqual(A, (tuple(range(8)), {}))
  572. class A(0, *range(1, 8), **d, foo='bar'): pass
  573. self.assertEqual(A, (tuple(range(8)), {'foo': 'bar'}))
  574. if __name__ == '__main__':
  575. unittest.main()