| """Unit tests for __instancecheck__ and __subclasscheck__.""" |
| |
| import unittest |
| from test import test_support |
| |
| |
| class ABC(type): |
| |
| def __instancecheck__(cls, inst): |
| """Implement isinstance(inst, cls).""" |
| return any(cls.__subclasscheck__(c) |
| for c in set([type(inst), inst.__class__])) |
| |
| def __subclasscheck__(cls, sub): |
| """Implement issubclass(sub, cls).""" |
| candidates = cls.__dict__.get("__subclass__", set()) | set([cls]) |
| return any(c in candidates for c in sub.mro()) |
| |
| |
| class Integer: |
| |
| __metaclass__ = ABC |
| |
| __subclass__ = set([int]) |
| |
| |
| class SubInt(Integer): |
| |
| pass |
| |
| |
| class Evil: |
| def __instancecheck__(self, inst): return False |
| |
| |
| class TypeChecksTest(unittest.TestCase): |
| |
| def testIsSubclassInternal(self): |
| self.assertEqual(Integer.__subclasscheck__(int), True) |
| self.assertEqual(Integer.__subclasscheck__(float), False) |
| |
| def testIsSubclassBuiltin(self): |
| self.assertEqual(issubclass(int, Integer), True) |
| self.assertEqual(issubclass(int, (Integer,)), True) |
| self.assertEqual(issubclass(float, Integer), False) |
| self.assertEqual(issubclass(float, (Integer,)), False) |
| |
| def testIsInstanceBuiltin(self): |
| self.assertEqual(isinstance(42, Integer), True) |
| self.assertEqual(isinstance(42, (Integer,)), True) |
| self.assertEqual(isinstance(3.14, Integer), False) |
| self.assertEqual(isinstance(3.14, (Integer,)), False) |
| |
| def testIsInstanceActual(self): |
| self.assertEqual(isinstance(Integer(), Integer), True) |
| self.assertEqual(isinstance(Integer(), (Integer,)), True) |
| |
| def testIsSubclassActual(self): |
| self.assertEqual(issubclass(Integer, Integer), True) |
| self.assertEqual(issubclass(Integer, (Integer,)), True) |
| |
| def testSubclassBehavior(self): |
| self.assertEqual(issubclass(SubInt, Integer), True) |
| self.assertEqual(issubclass(SubInt, (Integer,)), True) |
| self.assertEqual(issubclass(SubInt, SubInt), True) |
| self.assertEqual(issubclass(SubInt, (SubInt,)), True) |
| self.assertEqual(issubclass(Integer, SubInt), False) |
| self.assertEqual(issubclass(Integer, (SubInt,)), False) |
| self.assertEqual(issubclass(int, SubInt), False) |
| self.assertEqual(issubclass(int, (SubInt,)), False) |
| self.assertEqual(isinstance(SubInt(), Integer), True) |
| self.assertEqual(isinstance(SubInt(), (Integer,)), True) |
| self.assertEqual(isinstance(SubInt(), SubInt), True) |
| self.assertEqual(isinstance(SubInt(), (SubInt,)), True) |
| self.assertEqual(isinstance(42, SubInt), False) |
| self.assertEqual(isinstance(42, (SubInt,)), False) |
| |
| def testInfiniteRecursionCaughtProperly(self): |
| e = Evil() |
| # This invokes isinstance() recursively, until the stack is exhausted. |
| self.assertRaises(RuntimeError, isinstance, e, Evil) |
| # XXX How to check the same situation for issubclass()? |
| |
| |
| def test_main(): |
| test_support.run_unittest(TypeChecksTest) |
| |
| |
| if __name__ == "__main__": |
| unittest.main() |