test_class.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. "Test the functionality of Python classes implementing operators."
  2. import unittest
  3. from test import test_support
  4. testmeths = [
  5. # Binary operations
  6. "add",
  7. "radd",
  8. "sub",
  9. "rsub",
  10. "mul",
  11. "rmul",
  12. "div",
  13. "rdiv",
  14. "mod",
  15. "rmod",
  16. "divmod",
  17. "rdivmod",
  18. "pow",
  19. "rpow",
  20. "rshift",
  21. "rrshift",
  22. "lshift",
  23. "rlshift",
  24. "and",
  25. "rand",
  26. "or",
  27. "ror",
  28. "xor",
  29. "rxor",
  30. # List/dict operations
  31. "contains",
  32. "getitem",
  33. "getslice",
  34. "setitem",
  35. "setslice",
  36. "delitem",
  37. "delslice",
  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. # "coerce",
  47. # "hash",
  48. # "str",
  49. # "repr",
  50. # "int",
  51. # "long",
  52. # "float",
  53. # "oct",
  54. # "hex",
  55. # These are separate because they can influence the test of other methods.
  56. # "getattr",
  57. # "setattr",
  58. # "delattr",
  59. callLst = []
  60. def trackCall(f):
  61. def track(*args, **kwargs):
  62. callLst.append((f.__name__, args))
  63. return f(*args, **kwargs)
  64. return track
  65. class AllTests:
  66. trackCall = trackCall
  67. @trackCall
  68. def __coerce__(self, *args):
  69. return (self,) + args
  70. @trackCall
  71. def __hash__(self, *args):
  72. return hash(id(self))
  73. @trackCall
  74. def __str__(self, *args):
  75. return "AllTests"
  76. @trackCall
  77. def __repr__(self, *args):
  78. return "AllTests"
  79. @trackCall
  80. def __int__(self, *args):
  81. return 1
  82. @trackCall
  83. def __float__(self, *args):
  84. return 1.0
  85. @trackCall
  86. def __long__(self, *args):
  87. return 1L
  88. @trackCall
  89. def __oct__(self, *args):
  90. return '01'
  91. @trackCall
  92. def __hex__(self, *args):
  93. return '0x1'
  94. @trackCall
  95. def __cmp__(self, *args):
  96. return 0
  97. # Synthesize all the other AllTests methods from the names in testmeths.
  98. method_template = """\
  99. @trackCall
  100. def __%(method)s__(self, *args):
  101. pass
  102. """
  103. for method in testmeths:
  104. exec method_template % locals() in AllTests.__dict__
  105. del method, method_template
  106. class ClassTests(unittest.TestCase):
  107. def setUp(self):
  108. callLst[:] = []
  109. def assertCallStack(self, expected_calls):
  110. actualCallList = callLst[:] # need to copy because the comparison below will add
  111. # additional calls to callLst
  112. if expected_calls != actualCallList:
  113. self.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" %
  114. (expected_calls, actualCallList))
  115. def testInit(self):
  116. foo = AllTests()
  117. self.assertCallStack([("__init__", (foo,))])
  118. def testBinaryOps(self):
  119. testme = AllTests()
  120. # Binary operations
  121. callLst[:] = []
  122. testme + 1
  123. self.assertCallStack([("__coerce__", (testme, 1)), ("__add__", (testme, 1))])
  124. callLst[:] = []
  125. 1 + testme
  126. self.assertCallStack([("__coerce__", (testme, 1)), ("__radd__", (testme, 1))])
  127. callLst[:] = []
  128. testme - 1
  129. self.assertCallStack([("__coerce__", (testme, 1)), ("__sub__", (testme, 1))])
  130. callLst[:] = []
  131. 1 - testme
  132. self.assertCallStack([("__coerce__", (testme, 1)), ("__rsub__", (testme, 1))])
  133. callLst[:] = []
  134. testme * 1
  135. self.assertCallStack([("__coerce__", (testme, 1)), ("__mul__", (testme, 1))])
  136. callLst[:] = []
  137. 1 * testme
  138. self.assertCallStack([("__coerce__", (testme, 1)), ("__rmul__", (testme, 1))])
  139. if 1/2 == 0:
  140. callLst[:] = []
  141. testme / 1
  142. self.assertCallStack([("__coerce__", (testme, 1)), ("__div__", (testme, 1))])
  143. callLst[:] = []
  144. 1 / testme
  145. self.assertCallStack([("__coerce__", (testme, 1)), ("__rdiv__", (testme, 1))])
  146. callLst[:] = []
  147. testme % 1
  148. self.assertCallStack([("__coerce__", (testme, 1)), ("__mod__", (testme, 1))])
  149. callLst[:] = []
  150. 1 % testme
  151. self.assertCallStack([("__coerce__", (testme, 1)), ("__rmod__", (testme, 1))])
  152. callLst[:] = []
  153. divmod(testme,1)
  154. self.assertCallStack([("__coerce__", (testme, 1)), ("__divmod__", (testme, 1))])
  155. callLst[:] = []
  156. divmod(1, testme)
  157. self.assertCallStack([("__coerce__", (testme, 1)), ("__rdivmod__", (testme, 1))])
  158. callLst[:] = []
  159. testme ** 1
  160. self.assertCallStack([("__coerce__", (testme, 1)), ("__pow__", (testme, 1))])
  161. callLst[:] = []
  162. 1 ** testme
  163. self.assertCallStack([("__coerce__", (testme, 1)), ("__rpow__", (testme, 1))])
  164. callLst[:] = []
  165. testme >> 1
  166. self.assertCallStack([("__coerce__", (testme, 1)), ("__rshift__", (testme, 1))])
  167. callLst[:] = []
  168. 1 >> testme
  169. self.assertCallStack([("__coerce__", (testme, 1)), ("__rrshift__", (testme, 1))])
  170. callLst[:] = []
  171. testme << 1
  172. self.assertCallStack([("__coerce__", (testme, 1)), ("__lshift__", (testme, 1))])
  173. callLst[:] = []
  174. 1 << testme
  175. self.assertCallStack([("__coerce__", (testme, 1)), ("__rlshift__", (testme, 1))])
  176. callLst[:] = []
  177. testme & 1
  178. self.assertCallStack([("__coerce__", (testme, 1)), ("__and__", (testme, 1))])
  179. callLst[:] = []
  180. 1 & testme
  181. self.assertCallStack([("__coerce__", (testme, 1)), ("__rand__", (testme, 1))])
  182. callLst[:] = []
  183. testme | 1
  184. self.assertCallStack([("__coerce__", (testme, 1)), ("__or__", (testme, 1))])
  185. callLst[:] = []
  186. 1 | testme
  187. self.assertCallStack([("__coerce__", (testme, 1)), ("__ror__", (testme, 1))])
  188. callLst[:] = []
  189. testme ^ 1
  190. self.assertCallStack([("__coerce__", (testme, 1)), ("__xor__", (testme, 1))])
  191. callLst[:] = []
  192. 1 ^ testme
  193. self.assertCallStack([("__coerce__", (testme, 1)), ("__rxor__", (testme, 1))])
  194. def testListAndDictOps(self):
  195. testme = AllTests()
  196. # List/dict operations
  197. class Empty: pass
  198. try:
  199. 1 in Empty()
  200. self.fail('failed, should have raised TypeError')
  201. except TypeError:
  202. pass
  203. callLst[:] = []
  204. 1 in testme
  205. self.assertCallStack([('__contains__', (testme, 1))])
  206. callLst[:] = []
  207. testme[1]
  208. self.assertCallStack([('__getitem__', (testme, 1))])
  209. callLst[:] = []
  210. testme[1] = 1
  211. self.assertCallStack([('__setitem__', (testme, 1, 1))])
  212. callLst[:] = []
  213. del testme[1]
  214. self.assertCallStack([('__delitem__', (testme, 1))])
  215. callLst[:] = []
  216. testme[:42]
  217. self.assertCallStack([('__getslice__', (testme, 0, 42))])
  218. callLst[:] = []
  219. testme[:42] = "The Answer"
  220. self.assertCallStack([('__setslice__', (testme, 0, 42, "The Answer"))])
  221. callLst[:] = []
  222. del testme[:42]
  223. self.assertCallStack([('__delslice__', (testme, 0, 42))])
  224. callLst[:] = []
  225. testme[2:1024:10]
  226. self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
  227. callLst[:] = []
  228. testme[2:1024:10] = "A lot"
  229. self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10),
  230. "A lot"))])
  231. callLst[:] = []
  232. del testme[2:1024:10]
  233. self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))])
  234. callLst[:] = []
  235. testme[:42, ..., :24:, 24, 100]
  236. self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None),
  237. Ellipsis,
  238. slice(None, 24, None),
  239. 24, 100)))])
  240. callLst[:] = []
  241. testme[:42, ..., :24:, 24, 100] = "Strange"
  242. self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None),
  243. Ellipsis,
  244. slice(None, 24, None),
  245. 24, 100), "Strange"))])
  246. callLst[:] = []
  247. del testme[:42, ..., :24:, 24, 100]
  248. self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None),
  249. Ellipsis,
  250. slice(None, 24, None),
  251. 24, 100)))])
  252. # Now remove the slice hooks to see if converting normal slices to
  253. # slice object works.
  254. getslice = AllTests.__getslice__
  255. del AllTests.__getslice__
  256. setslice = AllTests.__setslice__
  257. del AllTests.__setslice__
  258. delslice = AllTests.__delslice__
  259. del AllTests.__delslice__
  260. # XXX when using new-style classes the slice testme[:42] produces
  261. # slice(None, 42, None) instead of slice(0, 42, None). py3k will have
  262. # to change this test.
  263. callLst[:] = []
  264. testme[:42]
  265. self.assertCallStack([('__getitem__', (testme, slice(0, 42, None)))])
  266. callLst[:] = []
  267. testme[:42] = "The Answer"
  268. self.assertCallStack([('__setitem__', (testme, slice(0, 42, None),
  269. "The Answer"))])
  270. callLst[:] = []
  271. del testme[:42]
  272. self.assertCallStack([('__delitem__', (testme, slice(0, 42, None)))])
  273. # Restore the slice methods, or the tests will fail with regrtest -R.
  274. AllTests.__getslice__ = getslice
  275. AllTests.__setslice__ = setslice
  276. AllTests.__delslice__ = delslice
  277. @test_support.cpython_only
  278. def testDelItem(self):
  279. class A:
  280. ok = False
  281. def __delitem__(self, key):
  282. self.ok = True
  283. a = A()
  284. # Subtle: we need to call PySequence_SetItem, not PyMapping_SetItem.
  285. from _testcapi import sequence_delitem
  286. sequence_delitem(a, 2)
  287. self.assertTrue(a.ok)
  288. def testUnaryOps(self):
  289. testme = AllTests()
  290. callLst[:] = []
  291. -testme
  292. self.assertCallStack([('__neg__', (testme,))])
  293. callLst[:] = []
  294. +testme
  295. self.assertCallStack([('__pos__', (testme,))])
  296. callLst[:] = []
  297. abs(testme)
  298. self.assertCallStack([('__abs__', (testme,))])
  299. callLst[:] = []
  300. int(testme)
  301. self.assertCallStack([('__int__', (testme,))])
  302. callLst[:] = []
  303. long(testme)
  304. self.assertCallStack([('__long__', (testme,))])
  305. callLst[:] = []
  306. float(testme)
  307. self.assertCallStack([('__float__', (testme,))])
  308. callLst[:] = []
  309. oct(testme)
  310. self.assertCallStack([('__oct__', (testme,))])
  311. callLst[:] = []
  312. hex(testme)
  313. self.assertCallStack([('__hex__', (testme,))])
  314. def testMisc(self):
  315. testme = AllTests()
  316. callLst[:] = []
  317. hash(testme)
  318. self.assertCallStack([('__hash__', (testme,))])
  319. callLst[:] = []
  320. repr(testme)
  321. self.assertCallStack([('__repr__', (testme,))])
  322. callLst[:] = []
  323. str(testme)
  324. self.assertCallStack([('__str__', (testme,))])
  325. callLst[:] = []
  326. testme == 1
  327. self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
  328. callLst[:] = []
  329. testme < 1
  330. self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
  331. callLst[:] = []
  332. testme > 1
  333. self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
  334. callLst[:] = []
  335. eval('testme <> 1') # XXX kill this in py3k
  336. self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
  337. callLst[:] = []
  338. testme != 1
  339. self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
  340. callLst[:] = []
  341. 1 == testme
  342. self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
  343. callLst[:] = []
  344. 1 < testme
  345. self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
  346. callLst[:] = []
  347. 1 > testme
  348. self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
  349. callLst[:] = []
  350. eval('1 <> testme')
  351. self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
  352. callLst[:] = []
  353. 1 != testme
  354. self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
  355. def testGetSetAndDel(self):
  356. # Interfering tests
  357. class ExtraTests(AllTests):
  358. @trackCall
  359. def __getattr__(self, *args):
  360. return "SomeVal"
  361. @trackCall
  362. def __setattr__(self, *args):
  363. pass
  364. @trackCall
  365. def __delattr__(self, *args):
  366. pass
  367. testme = ExtraTests()
  368. callLst[:] = []
  369. testme.spam
  370. self.assertCallStack([('__getattr__', (testme, "spam"))])
  371. callLst[:] = []
  372. testme.eggs = "spam, spam, spam and ham"
  373. self.assertCallStack([('__setattr__', (testme, "eggs",
  374. "spam, spam, spam and ham"))])
  375. callLst[:] = []
  376. del testme.cardinal
  377. self.assertCallStack([('__delattr__', (testme, "cardinal"))])
  378. def testDel(self):
  379. x = []
  380. class DelTest:
  381. def __del__(self):
  382. x.append("crab people, crab people")
  383. testme = DelTest()
  384. del testme
  385. import gc
  386. gc.collect()
  387. self.assertEqual(["crab people, crab people"], x)
  388. def testBadTypeReturned(self):
  389. # return values of some method are type-checked
  390. class BadTypeClass:
  391. def __int__(self):
  392. return None
  393. __float__ = __int__
  394. __long__ = __int__
  395. __str__ = __int__
  396. __repr__ = __int__
  397. __oct__ = __int__
  398. __hex__ = __int__
  399. for f in [int, float, long, str, repr, oct, hex]:
  400. self.assertRaises(TypeError, f, BadTypeClass())
  401. def testMixIntsAndLongs(self):
  402. # mixing up ints and longs is okay
  403. class IntLongMixClass:
  404. @trackCall
  405. def __int__(self):
  406. return 42L
  407. @trackCall
  408. def __long__(self):
  409. return 64
  410. mixIntAndLong = IntLongMixClass()
  411. callLst[:] = []
  412. as_int = int(mixIntAndLong)
  413. self.assertEqual(type(as_int), long)
  414. self.assertEqual(as_int, 42L)
  415. self.assertCallStack([('__int__', (mixIntAndLong,))])
  416. callLst[:] = []
  417. as_long = long(mixIntAndLong)
  418. self.assertEqual(type(as_long), long)
  419. self.assertEqual(as_long, 64)
  420. self.assertCallStack([('__long__', (mixIntAndLong,))])
  421. def testHashStuff(self):
  422. # Test correct errors from hash() on objects with comparisons but
  423. # no __hash__
  424. class C0:
  425. pass
  426. hash(C0()) # This should work; the next two should raise TypeError
  427. class C1:
  428. def __cmp__(self, other): return 0
  429. self.assertRaises(TypeError, hash, C1())
  430. class C2:
  431. def __eq__(self, other): return 1
  432. self.assertRaises(TypeError, hash, C2())
  433. def testSFBug532646(self):
  434. # Test for SF bug 532646
  435. class A:
  436. pass
  437. A.__call__ = A()
  438. a = A()
  439. try:
  440. a() # This should not segfault
  441. except RuntimeError:
  442. pass
  443. else:
  444. self.fail("Failed to raise RuntimeError")
  445. def testForExceptionsRaisedInInstanceGetattr2(self):
  446. # Tests for exceptions raised in instance_getattr2().
  447. def booh(self):
  448. raise AttributeError("booh")
  449. class A:
  450. a = property(booh)
  451. try:
  452. A().a # Raised AttributeError: A instance has no attribute 'a'
  453. except AttributeError, x:
  454. if str(x) != "booh":
  455. self.fail("attribute error for A().a got masked: %s" % x)
  456. class E:
  457. __eq__ = property(booh)
  458. E() == E() # In debug mode, caused a C-level assert() to fail
  459. class I:
  460. __init__ = property(booh)
  461. try:
  462. # In debug mode, printed XXX undetected error and
  463. # raises AttributeError
  464. I()
  465. except AttributeError, x:
  466. pass
  467. else:
  468. self.fail("attribute error for I.__init__ got masked")
  469. def testHashComparisonOfMethods(self):
  470. # Test comparison and hash of methods
  471. class A:
  472. def __init__(self, x):
  473. self.x = x
  474. def f(self):
  475. pass
  476. def g(self):
  477. pass
  478. def __eq__(self, other):
  479. return self.x == other.x
  480. def __hash__(self):
  481. return self.x
  482. class B(A):
  483. pass
  484. a1 = A(1)
  485. a2 = A(2)
  486. self.assertEqual(a1.f, a1.f)
  487. self.assertNotEqual(a1.f, a2.f)
  488. self.assertNotEqual(a1.f, a1.g)
  489. self.assertEqual(a1.f, A(1).f)
  490. self.assertEqual(hash(a1.f), hash(a1.f))
  491. self.assertEqual(hash(a1.f), hash(A(1).f))
  492. self.assertNotEqual(A.f, a1.f)
  493. self.assertNotEqual(A.f, A.g)
  494. self.assertEqual(B.f, A.f)
  495. self.assertEqual(hash(B.f), hash(A.f))
  496. # the following triggers a SystemError in 2.4
  497. a = A(hash(A.f.im_func)^(-1))
  498. hash(a.f)
  499. def testAttrSlots(self):
  500. class C:
  501. pass
  502. for c in C, C():
  503. self.assertRaises(TypeError, type(c).__getattribute__, c, [])
  504. self.assertRaises(TypeError, type(c).__setattr__, c, [], [])
  505. def test_main():
  506. with test_support.check_py3k_warnings(
  507. (".+__(get|set|del)slice__ has been removed", DeprecationWarning),
  508. ("classic int division", DeprecationWarning),
  509. ("<> not supported", DeprecationWarning)):
  510. test_support.run_unittest(ClassTests)
  511. if __name__=='__main__':
  512. test_main()