test_subclass.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. __author__ = 'mchat'
  2. import unittest
  3. class MySimpleInt(int): pass
  4. class MySimpleFloat(float): pass
  5. class MySimpleLong(long): pass
  6. class MyInt(int):
  7. def __init__(self, value):
  8. self.value = value
  9. def __add__(self, other):
  10. return self.value - other
  11. def __hash__(self):
  12. return 11
  13. class MyFloat(float):
  14. def __sub__(self, other):
  15. return 0
  16. class MyLong(long):
  17. def __lt__(self, other):
  18. return True
  19. class MyList(list):
  20. def __contains__(self, item):
  21. if item == 2:
  22. return True
  23. else:
  24. return False
  25. def __add__(self, item):
  26. return self
  27. def __mul__(self, num):
  28. return self[:1]
  29. def __rmul__(self, num):
  30. return self[1:]
  31. class MySet(set):
  32. def __len__(self):
  33. return 0
  34. class MyDict(dict):
  35. def __getitem__(self, key):
  36. return "hello world"
  37. def __setitem__(self, key, value):
  38. return None
  39. class AnotherInt(MyInt):
  40. def __mul__(self, other):
  41. return 0
  42. foo_radd = "Foo __radd__"
  43. bar_add = "Bar __add__"
  44. baz_radd = "Baz __radd__"
  45. baz_add = "Baz __add__"
  46. class Foo(int):
  47. def __radd__(self, other):
  48. return foo_radd
  49. class Bar(int):
  50. def __add__(self, other):
  51. return bar_add
  52. class Baz(Bar):
  53. def __add__(self, other):
  54. return baz_add
  55. def __radd__(self, other):
  56. return baz_radd
  57. class SubclassTest(unittest.TestCase):
  58. def test_builtin_functions(self):
  59. builtinToSubclass = {5: MySimpleInt(5),
  60. 3L: MySimpleLong(3L),
  61. 1.2: MySimpleFloat(1.2)}
  62. for builtin in builtinToSubclass:
  63. subclass = builtinToSubclass[builtin]
  64. self.assertEqual(repr(subclass), repr(builtin))
  65. self.assertEqual(str(subclass), str(builtin))
  66. self.assertEqual(abs(subclass), abs(builtin))
  67. self.assertEqual(hash(subclass), hash(builtin))
  68. def test_comparions(self):
  69. less = [MySimpleInt(5), MySimpleLong(5L), MySimpleFloat(5.0), 5, 5L, 5.0]
  70. greater = [MySimpleInt(10), MySimpleLong(10L), MySimpleFloat(10.0), 10, 10L, 10.0]
  71. for x in less:
  72. for y in less:
  73. self.assertEqual(x, y)
  74. for l in less:
  75. for g in greater:
  76. self.assertLess(l, g)
  77. self.assertLessEqual(l, g)
  78. self.assertGreater(g, l)
  79. self.assertGreaterEqual(g, l)
  80. self.assertLessEqual(l, l)
  81. self.assertGreaterEqual(g, g)
  82. def test_binop(self):
  83. builtinToSubclass = {5: MySimpleInt(5),
  84. 3L: MySimpleLong(3L),
  85. 1.2: MySimpleFloat(1.2)}
  86. for x_builtin in builtinToSubclass:
  87. x_subclass = builtinToSubclass[x_builtin]
  88. for y_builtin in builtinToSubclass:
  89. y_subclass = builtinToSubclass[y_builtin]
  90. self.assertEqual(x_subclass + y_subclass, x_builtin + y_builtin)
  91. self.assertEqual(y_subclass + x_subclass, y_builtin + x_builtin)
  92. self.assertEqual(x_subclass - y_subclass, x_builtin - y_builtin)
  93. self.assertEqual(y_subclass - x_subclass, y_builtin - x_builtin)
  94. self.assertEqual(x_subclass * y_subclass, x_builtin * y_builtin)
  95. self.assertEqual(y_subclass * x_subclass, y_builtin * x_builtin)
  96. self.assertEqual(x_subclass / y_subclass, x_builtin / y_builtin)
  97. self.assertEqual(y_subclass / x_subclass, y_builtin / x_builtin)
  98. self.assertEqual(x_subclass % y_subclass, x_builtin % y_builtin)
  99. self.assertEqual(y_subclass % x_subclass, y_builtin % x_builtin)
  100. self.assertEqual(x_subclass // y_subclass, x_builtin // y_builtin)
  101. self.assertEqual(y_subclass // x_subclass, y_builtin // x_builtin)
  102. self.assertEqual(x_subclass ** y_subclass, x_builtin ** y_builtin)
  103. self.assertEqual(y_subclass ** x_subclass, y_builtin ** x_builtin)
  104. def test_override_dunder_numbers(self):
  105. i = MyInt(5)
  106. l = MyLong(3L)
  107. f = MyFloat(1.2)
  108. self.assertEqual(i + f, i - f) # MyInt.__add__
  109. self.assertEqual(f - i, 0) # MyFloat.__sub__
  110. self.assertLess(l, i) # MyLong.__lt__
  111. self.assertLess(l, f) # MyLong.__lt__
  112. self.assertEqual(hash(i), 11) # MyInt.__hash__
  113. def test_override_dunder_containers(self):
  114. base_list = [1, 2, 3]
  115. base_dict = {1: 2}
  116. li = MyList(base_list)
  117. self.assertEqual(li, base_list)
  118. self.assertNotIn(1, li) # MyList.__contains__
  119. self.assertIn(2, li) # MyList.__contains__
  120. self.assertNotIn(3, li) # MyList.__contains__
  121. self.assertNotIn(4, li) # MyList.__contains__
  122. self.assertEqual(li + [4], li) # MyList.__add__
  123. self.assertEqual(li * 5, li[:1]) # MyList.__mul__
  124. self.assertEqual(5 * li, li[1:]) # MyList.__rmul__
  125. s = MySet(base_list)
  126. self.assertEqual(s, set(base_list))
  127. self.assertEqual(len(s), 0) # MySet.__len__
  128. d = MyDict(base_dict)
  129. self.assertEqual(d, base_dict)
  130. self.assertEqual(d[1], "hello world") # MyDict.__getitem__
  131. self.assertEqual(d["not a key"], "hello world") # MyDict.__getitem__
  132. d[1] = "should not change"
  133. self.assertEqual(d, base_dict) # MyDict.__setitem__
  134. def test_override_ancestor_operations(self):
  135. foo = Foo(5)
  136. bar = Bar(5)
  137. baz = Baz(5)
  138. self.assertEqual(foo + 2, 7) # int.__add__
  139. self.assertEqual(2 + foo, foo_radd) # Foo.__radd__
  140. self.assertEqual(bar + 2, bar_add) # Bar.__add__
  141. self.assertEqual(2 + bar, 7) # int.__radd__ (from Bar)
  142. self.assertEqual(foo + bar, 10) # int.__add__ (from Foo)
  143. self.assertEqual(bar + foo, bar_add) # Bar.__add__
  144. self.assertEqual(baz + 2, baz_add) # Baz.__add__
  145. self.assertEqual(2 + baz, baz_radd) # Baz.__radd__
  146. self.assertEqual(foo + baz, 10) # int.__add__ (from Foo)
  147. self.assertEqual(baz + foo, baz_add) # Baz.__add__
  148. self.assertEqual(bar + baz, baz_radd) # Baz.__radd__
  149. self.assertEqual(baz + bar, baz_add) # Baz.add
  150. def test_subclass_of_subclass(self):
  151. x = MyInt(5)
  152. self.assertEqual(x * 5, 25)
  153. y = AnotherInt(5)
  154. self.assertEqual(y, 5) # int.__eq__
  155. self.assertEqual(y + 2, 3) # MyInt.__add__
  156. self.assertEqual(hash(y), 11) # MyInt.__hash__
  157. self.assertEqual(y * 5, 0) # AnotherInt.__mul__
  158. def test_multiple_inheritance(self):
  159. class Ancestor:
  160. def __hash__(self):
  161. return 15
  162. def __str__(self):
  163. return "Ancestor"
  164. def test(self):
  165. return "Hello world"
  166. class Foo(Ancestor, int): pass
  167. class Bar(Ancestor, MyInt): pass
  168. class Baz(MyInt, Ancestor): pass
  169. x = Foo(5)
  170. y = Bar(5)
  171. z = Baz(5)
  172. self.assertEqual(str(x), "Ancestor") # Ancestor.__str__
  173. self.assertEqual(hash(x), 15) # Ancestor.__hash__
  174. self.assertEqual(x.test(), "Hello world") # Ancestor.test
  175. self.assertEqual(str(y), "Ancestor") # Ancestor.__str__
  176. self.assertEqual(hash(y), 15) # Ancestor.__str__
  177. self.assertEqual(y.test(), "Hello world") # Ancestor.test
  178. self.assertEqual(str(z), "5") # int.__str__
  179. self.assertEqual(hash(z), 11) # MyInt.__hash__
  180. self.assertEqual(z.test(), "Hello world") # Ancestor.test
  181. def test_bad_multiple_inheritance(self):
  182. # Note: "with self.assertRaises" syntax is not supported by Skulpt
  183. # at this time so must pass a function to "self.assertRaises"
  184. def two_builtins():
  185. class BadClass(int, float): pass
  186. def builtin_and_subclass():
  187. class BadClass(int, MyFloat): pass
  188. def two_subclasses():
  189. class BadClass(MyList, AnotherInt): pass
  190. self.assertRaises(TypeError, two_builtins)
  191. self.assertRaises(TypeError, builtin_and_subclass)
  192. self.assertRaises(TypeError, two_subclasses)
  193. class SameBuiltin(MyInt, int): pass
  194. self.assertEqual(SameBuiltin(5), 5)
  195. def test_exceptions(self):
  196. class TestFailed(Exception):
  197. """Test failed."""
  198. def raiseTestFailed():
  199. raise TestFailed()
  200. self.assertRaises(TestFailed, raiseTestFailed)
  201. try:
  202. raise TestFailed("test")
  203. self.fail("Should never get here")
  204. except TestFailed as e:
  205. self.assertIn("TestFailed: test", str(e))
  206. class MyTypeError(TypeError): pass
  207. def raiseMyTypeError():
  208. raise MyTypeError()
  209. self.assertRaises(MyTypeError, raiseMyTypeError)
  210. self.assertRaises(TypeError, raiseMyTypeError)
  211. self.assertRaises(Exception, raiseMyTypeError)
  212. class MyStandardError(StandardError):
  213. def __str__(self):
  214. return "My Standard Error"
  215. try:
  216. raise MyStandardError("test")
  217. self.fail("Should never get here")
  218. except MyStandardError as e:
  219. self.assertEqual("My Standard Error", str(e))
  220. # Test multiple-class catch
  221. try:
  222. raiseTestFailed()
  223. self.fail("Shouldn't get here")
  224. except (StandardError, TestFailed):
  225. pass
  226. if __name__ == "__main__":
  227. unittest.main()