home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / test_isinstance.py < prev    next >
Text File  |  2003-12-30  |  9KB  |  260 lines

  1. # Tests some corner cases with isinstance() and issubclass().  While these
  2. # tests use new style classes and properties, they actually do whitebox
  3. # testing of error conditions uncovered when using extension types.
  4.  
  5. import unittest
  6. from test import test_support
  7.  
  8.  
  9.  
  10. class TestIsInstanceExceptions(unittest.TestCase):
  11.     # Test to make sure that an AttributeError when accessing the instance's
  12.     # class's bases is masked.  This was actually a bug in Python 2.2 and
  13.     # 2.2.1 where the exception wasn't caught but it also wasn't being cleared
  14.     # (leading to an "undetected error" in the debug build).  Set up is,
  15.     # isinstance(inst, cls) where:
  16.     #
  17.     # - inst isn't an InstanceType
  18.     # - cls isn't a ClassType, a TypeType, or a TupleType
  19.     # - cls has a __bases__ attribute
  20.     # - inst has a __class__ attribute
  21.     # - inst.__class__ as no __bases__ attribute
  22.     #
  23.     # Sounds complicated, I know, but this mimics a situation where an
  24.     # extension type raises an AttributeError when its __bases__ attribute is
  25.     # gotten.  In that case, isinstance() should return False.
  26.     def test_class_has_no_bases(self):
  27.         class I(object):
  28.             def getclass(self):
  29.                 # This must return an object that has no __bases__ attribute
  30.                 return None
  31.             __class__ = property(getclass)
  32.  
  33.         class C(object):
  34.             def getbases(self):
  35.                 return ()
  36.             __bases__ = property(getbases)
  37.  
  38.         self.assertEqual(False, isinstance(I(), C()))
  39.  
  40.     # Like above except that inst.__class__.__bases__ raises an exception
  41.     # other than AttributeError
  42.     def test_bases_raises_other_than_attribute_error(self):
  43.         class E(object):
  44.             def getbases(self):
  45.                 raise RuntimeError
  46.             __bases__ = property(getbases)
  47.  
  48.         class I(object):
  49.             def getclass(self):
  50.                 return E()
  51.             __class__ = property(getclass)
  52.  
  53.         class C(object):
  54.             def getbases(self):
  55.                 return ()
  56.             __bases__ = property(getbases)
  57.  
  58.         self.assertRaises(RuntimeError, isinstance, I(), C())
  59.  
  60.     # Here's a situation where getattr(cls, '__bases__') raises an exception.
  61.     # If that exception is not AttributeError, it should not get masked
  62.     def test_dont_mask_non_attribute_error(self):
  63.         class I: pass
  64.  
  65.         class C(object):
  66.             def getbases(self):
  67.                 raise RuntimeError
  68.             __bases__ = property(getbases)
  69.  
  70.         self.assertRaises(RuntimeError, isinstance, I(), C())
  71.  
  72.     # Like above, except that getattr(cls, '__bases__') raises an
  73.     # AttributeError, which /should/ get masked as a TypeError
  74.     def test_mask_attribute_error(self):
  75.         class I: pass
  76.  
  77.         class C(object):
  78.             def getbases(self):
  79.                 raise AttributeError
  80.             __bases__ = property(getbases)
  81.  
  82.         self.assertRaises(TypeError, isinstance, I(), C())
  83.  
  84.  
  85.  
  86. # These tests are similar to above, but tickle certain code paths in
  87. # issubclass() instead of isinstance() -- really PyObject_IsSubclass()
  88. # vs. PyObject_IsInstance().
  89. class TestIsSubclassExceptions(unittest.TestCase):
  90.     def test_dont_mask_non_attribute_error(self):
  91.         class C(object):
  92.             def getbases(self):
  93.                 raise RuntimeError
  94.             __bases__ = property(getbases)
  95.  
  96.         class S(C): pass
  97.  
  98.         self.assertRaises(RuntimeError, issubclass, C(), S())
  99.  
  100.     def test_mask_attribute_error(self):
  101.         class C(object):
  102.             def getbases(self):
  103.                 raise AttributeError
  104.             __bases__ = property(getbases)
  105.  
  106.         class S(C): pass
  107.  
  108.         self.assertRaises(TypeError, issubclass, C(), S())
  109.  
  110.     # Like above, but test the second branch, where the __bases__ of the
  111.     # second arg (the cls arg) is tested.  This means the first arg must
  112.     # return a valid __bases__, and it's okay for it to be a normal --
  113.     # unrelated by inheritance -- class.
  114.     def test_dont_mask_non_attribute_error_in_cls_arg(self):
  115.         class B: pass
  116.  
  117.         class C(object):
  118.             def getbases(self):
  119.                 raise RuntimeError
  120.             __bases__ = property(getbases)
  121.  
  122.         self.assertRaises(RuntimeError, issubclass, B, C())
  123.  
  124.     def test_mask_attribute_error_in_cls_arg(self):
  125.         class B: pass
  126.  
  127.         class C(object):
  128.             def getbases(self):
  129.                 raise AttributeError
  130.             __bases__ = property(getbases)
  131.  
  132.         self.assertRaises(TypeError, issubclass, B, C())
  133.  
  134.  
  135.  
  136. # meta classes for creating abstract classes and instances
  137. class AbstractClass(object):
  138.     def __init__(self, bases):
  139.         self.bases = bases
  140.  
  141.     def getbases(self):
  142.         return self.bases
  143.     __bases__ = property(getbases)
  144.  
  145.     def __call__(self):
  146.         return AbstractInstance(self)
  147.  
  148. class AbstractInstance(object):
  149.     def __init__(self, klass):
  150.         self.klass = klass
  151.  
  152.     def getclass(self):
  153.         return self.klass
  154.     __class__ = property(getclass)
  155.  
  156. # abstract classes
  157. AbstractSuper = AbstractClass(bases=())
  158.  
  159. AbstractChild = AbstractClass(bases=(AbstractSuper,))
  160.  
  161. # normal classes
  162. class Super:
  163.     pass
  164.  
  165. class Child(Super):
  166.     pass
  167.  
  168. # new-style classes
  169. class NewSuper(object):
  170.     pass
  171.  
  172. class NewChild(NewSuper):
  173.     pass
  174.  
  175.  
  176.  
  177. class TestIsInstanceIsSubclass(unittest.TestCase):
  178.     # Tests to ensure that isinstance and issubclass work on abstract
  179.     # classes and instances.  Before the 2.2 release, TypeErrors were
  180.     # raised when boolean values should have been returned.  The bug was
  181.     # triggered by mixing 'normal' classes and instances were with
  182.     # 'abstract' classes and instances.  This case tries to test all
  183.     # combinations.
  184.  
  185.     def test_isinstance_normal(self):
  186.         # normal instances
  187.         self.assertEqual(True, isinstance(Super(), Super))
  188.         self.assertEqual(False, isinstance(Super(), Child))
  189.         self.assertEqual(False, isinstance(Super(), AbstractSuper))
  190.         self.assertEqual(False, isinstance(Super(), AbstractChild))
  191.  
  192.         self.assertEqual(True, isinstance(Child(), Super))
  193.         self.assertEqual(False, isinstance(Child(), AbstractSuper))
  194.  
  195.     def test_isinstance_abstract(self):
  196.         # abstract instances
  197.         self.assertEqual(True, isinstance(AbstractSuper(), AbstractSuper))
  198.         self.assertEqual(False, isinstance(AbstractSuper(), AbstractChild))
  199.         self.assertEqual(False, isinstance(AbstractSuper(), Super))
  200.         self.assertEqual(False, isinstance(AbstractSuper(), Child))
  201.  
  202.         self.assertEqual(True, isinstance(AbstractChild(), AbstractChild))
  203.         self.assertEqual(True, isinstance(AbstractChild(), AbstractSuper))
  204.         self.assertEqual(False, isinstance(AbstractChild(), Super))
  205.         self.assertEqual(False, isinstance(AbstractChild(), Child))
  206.  
  207.     def test_subclass_normal(self):
  208.         # normal classes
  209.         self.assertEqual(True, issubclass(Super, Super))
  210.         self.assertEqual(False, issubclass(Super, AbstractSuper))
  211.         self.assertEqual(False, issubclass(Super, Child))
  212.  
  213.         self.assertEqual(True, issubclass(Child, Child))
  214.         self.assertEqual(True, issubclass(Child, Super))
  215.         self.assertEqual(False, issubclass(Child, AbstractSuper))
  216.  
  217.     def test_subclass_abstract(self):
  218.         # abstract classes
  219.         self.assertEqual(True, issubclass(AbstractSuper, AbstractSuper))
  220.         self.assertEqual(False, issubclass(AbstractSuper, AbstractChild))
  221.         self.assertEqual(False, issubclass(AbstractSuper, Child))
  222.  
  223.         self.assertEqual(True, issubclass(AbstractChild, AbstractChild))
  224.         self.assertEqual(True, issubclass(AbstractChild, AbstractSuper))
  225.         self.assertEqual(False, issubclass(AbstractChild, Super))
  226.         self.assertEqual(False, issubclass(AbstractChild, Child))
  227.  
  228.     def test_subclass_tuple(self):
  229.         # test with a tuple as the second argument classes
  230.         self.assertEqual(True, issubclass(Child, (Child,)))
  231.         self.assertEqual(True, issubclass(Child, (Super,)))
  232.         self.assertEqual(False, issubclass(Super, (Child,)))
  233.         self.assertEqual(True, issubclass(Super, (Child, Super)))
  234.         self.assertEqual(False, issubclass(Child, ()))
  235.         self.assertEqual(True, issubclass(Super, (Child, (Super,))))
  236.  
  237.         self.assertEqual(True, issubclass(NewChild, (NewChild,)))
  238.         self.assertEqual(True, issubclass(NewChild, (NewSuper,)))
  239.         self.assertEqual(False, issubclass(NewSuper, (NewChild,)))
  240.         self.assertEqual(True, issubclass(NewSuper, (NewChild, NewSuper)))
  241.         self.assertEqual(False, issubclass(NewChild, ()))
  242.         self.assertEqual(True, issubclass(NewSuper, (NewChild, (NewSuper,))))
  243.  
  244.         self.assertEqual(True, issubclass(int, (long, (float, int))))
  245.         self.assertEqual(True, issubclass(str, (unicode, (Child, NewChild, basestring))))
  246.  
  247.  
  248.  
  249.  
  250. def test_main():
  251.     test_support.run_unittest(
  252.         TestIsInstanceExceptions,
  253.         TestIsSubclassExceptions,
  254.         TestIsInstanceIsSubclass
  255.     )
  256.  
  257.  
  258. if __name__ == '__main__':
  259.     test_main()
  260.