1# Copyright 2007 Google, Inc. All Rights Reserved. 2# Licensed to PSF under a Contributor Agreement. 3 4"""Unit tests for abc.py.""" 5 6import unittest, weakref 7from test import test_support 8 9import abc 10from inspect import isabstract 11 12 13class TestABC(unittest.TestCase): 14 15 def test_abstractmethod_basics(self): 16 @abc.abstractmethod 17 def foo(self): pass 18 self.assertTrue(foo.__isabstractmethod__) 19 def bar(self): pass 20 self.assertFalse(hasattr(bar, "__isabstractmethod__")) 21 22 def test_abstractproperty_basics(self): 23 @abc.abstractproperty 24 def foo(self): pass 25 self.assertTrue(foo.__isabstractmethod__) 26 def bar(self): pass 27 self.assertFalse(hasattr(bar, "__isabstractmethod__")) 28 29 class C: 30 __metaclass__ = abc.ABCMeta 31 @abc.abstractproperty 32 def foo(self): return 3 33 class D(C): 34 @property 35 def foo(self): return super(D, self).foo 36 self.assertEqual(D().foo, 3) 37 38 def test_abstractmethod_integration(self): 39 for abstractthing in [abc.abstractmethod, abc.abstractproperty]: 40 class C: 41 __metaclass__ = abc.ABCMeta 42 @abstractthing 43 def foo(self): pass # abstract 44 def bar(self): pass # concrete 45 self.assertEqual(C.__abstractmethods__, set(["foo"])) 46 self.assertRaises(TypeError, C) # because foo is abstract 47 self.assertTrue(isabstract(C)) 48 class D(C): 49 def bar(self): pass # concrete override of concrete 50 self.assertEqual(D.__abstractmethods__, set(["foo"])) 51 self.assertRaises(TypeError, D) # because foo is still abstract 52 self.assertTrue(isabstract(D)) 53 class E(D): 54 def foo(self): pass 55 self.assertEqual(E.__abstractmethods__, set()) 56 E() # now foo is concrete, too 57 self.assertFalse(isabstract(E)) 58 class F(E): 59 @abstractthing 60 def bar(self): pass # abstract override of concrete 61 self.assertEqual(F.__abstractmethods__, set(["bar"])) 62 self.assertRaises(TypeError, F) # because bar is abstract now 63 self.assertTrue(isabstract(F)) 64 65 def test_subclass_oldstyle_class(self): 66 class A: 67 __metaclass__ = abc.ABCMeta 68 class OldstyleClass: 69 pass 70 self.assertFalse(issubclass(OldstyleClass, A)) 71 self.assertFalse(issubclass(A, OldstyleClass)) 72 73 def test_isinstance_class(self): 74 class A: 75 __metaclass__ = abc.ABCMeta 76 class OldstyleClass: 77 pass 78 self.assertFalse(isinstance(OldstyleClass, A)) 79 self.assertTrue(isinstance(OldstyleClass, type(OldstyleClass))) 80 self.assertFalse(isinstance(A, OldstyleClass)) 81 # This raises a recursion depth error, but is low-priority: 82 # self.assertTrue(isinstance(A, abc.ABCMeta)) 83 84 def test_registration_basics(self): 85 class A: 86 __metaclass__ = abc.ABCMeta 87 class B(object): 88 pass 89 b = B() 90 self.assertFalse(issubclass(B, A)) 91 self.assertFalse(issubclass(B, (A,))) 92 self.assertNotIsInstance(b, A) 93 self.assertNotIsInstance(b, (A,)) 94 A.register(B) 95 self.assertTrue(issubclass(B, A)) 96 self.assertTrue(issubclass(B, (A,))) 97 self.assertIsInstance(b, A) 98 self.assertIsInstance(b, (A,)) 99 class C(B): 100 pass 101 c = C() 102 self.assertTrue(issubclass(C, A)) 103 self.assertTrue(issubclass(C, (A,))) 104 self.assertIsInstance(c, A) 105 self.assertIsInstance(c, (A,)) 106 107 def test_isinstance_invalidation(self): 108 class A: 109 __metaclass__ = abc.ABCMeta 110 class B(object): 111 pass 112 b = B() 113 self.assertFalse(isinstance(b, A)) 114 self.assertFalse(isinstance(b, (A,))) 115 A.register(B) 116 self.assertTrue(isinstance(b, A)) 117 self.assertTrue(isinstance(b, (A,))) 118 119 def test_registration_builtins(self): 120 class A: 121 __metaclass__ = abc.ABCMeta 122 A.register(int) 123 self.assertIsInstance(42, A) 124 self.assertIsInstance(42, (A,)) 125 self.assertTrue(issubclass(int, A)) 126 self.assertTrue(issubclass(int, (A,))) 127 class B(A): 128 pass 129 B.register(basestring) 130 self.assertIsInstance("", A) 131 self.assertIsInstance("", (A,)) 132 self.assertTrue(issubclass(str, A)) 133 self.assertTrue(issubclass(str, (A,))) 134 135 def test_registration_edge_cases(self): 136 class A: 137 __metaclass__ = abc.ABCMeta 138 A.register(A) # should pass silently 139 class A1(A): 140 pass 141 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed 142 class B(object): 143 pass 144 A1.register(B) # ok 145 A1.register(B) # should pass silently 146 class C(A): 147 pass 148 A.register(C) # should pass silently 149 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed 150 C.register(B) # ok 151 152 def test_register_non_class(self): 153 class A(object): 154 __metaclass__ = abc.ABCMeta 155 self.assertRaisesRegexp(TypeError, "Can only register classes", 156 A.register, 4) 157 158 def test_registration_transitiveness(self): 159 class A: 160 __metaclass__ = abc.ABCMeta 161 self.assertTrue(issubclass(A, A)) 162 self.assertTrue(issubclass(A, (A,))) 163 class B: 164 __metaclass__ = abc.ABCMeta 165 self.assertFalse(issubclass(A, B)) 166 self.assertFalse(issubclass(A, (B,))) 167 self.assertFalse(issubclass(B, A)) 168 self.assertFalse(issubclass(B, (A,))) 169 class C: 170 __metaclass__ = abc.ABCMeta 171 A.register(B) 172 class B1(B): 173 pass 174 self.assertTrue(issubclass(B1, A)) 175 self.assertTrue(issubclass(B1, (A,))) 176 class C1(C): 177 pass 178 B1.register(C1) 179 self.assertFalse(issubclass(C, B)) 180 self.assertFalse(issubclass(C, (B,))) 181 self.assertFalse(issubclass(C, B1)) 182 self.assertFalse(issubclass(C, (B1,))) 183 self.assertTrue(issubclass(C1, A)) 184 self.assertTrue(issubclass(C1, (A,))) 185 self.assertTrue(issubclass(C1, B)) 186 self.assertTrue(issubclass(C1, (B,))) 187 self.assertTrue(issubclass(C1, B1)) 188 self.assertTrue(issubclass(C1, (B1,))) 189 C1.register(int) 190 class MyInt(int): 191 pass 192 self.assertTrue(issubclass(MyInt, A)) 193 self.assertTrue(issubclass(MyInt, (A,))) 194 self.assertIsInstance(42, A) 195 self.assertIsInstance(42, (A,)) 196 197 def test_all_new_methods_are_called(self): 198 class A: 199 __metaclass__ = abc.ABCMeta 200 class B(object): 201 counter = 0 202 def __new__(cls): 203 B.counter += 1 204 return super(B, cls).__new__(cls) 205 class C(A, B): 206 pass 207 self.assertEqual(B.counter, 0) 208 C() 209 self.assertEqual(B.counter, 1) 210 211 def test_cache_leak(self): 212 # See issue #2521. 213 class A(object): 214 __metaclass__ = abc.ABCMeta 215 @abc.abstractmethod 216 def f(self): 217 pass 218 class C(A): 219 def f(self): 220 A.f(self) 221 r = weakref.ref(C) 222 # Trigger cache. 223 C().f() 224 del C 225 test_support.gc_collect() 226 self.assertEqual(r(), None) 227 228def test_main(): 229 test_support.run_unittest(TestABC) 230 231 232if __name__ == "__main__": 233 unittest.main() 234