These files are a subset of the python-2.7.2.tgz distribution from python.org. Changed files from PyMod-2.7.2 have been copied into the corresponding directories of this tree, replacing the original files in the distribution. Signed-off-by: daryl.mcdaniel@intel.com git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13197 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			278 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			278 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Tests some corner cases with isinstance() and issubclass().  While these
 | ||
| # tests use new style classes and properties, they actually do whitebox
 | ||
| # testing of error conditions uncovered when using extension types.
 | ||
| 
 | ||
| import unittest
 | ||
| from test import test_support
 | ||
| import sys
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| class TestIsInstanceExceptions(unittest.TestCase):
 | ||
|     # Test to make sure that an AttributeError when accessing the instance's
 | ||
|     # class's bases is masked.  This was actually a bug in Python 2.2 and
 | ||
|     # 2.2.1 where the exception wasn't caught but it also wasn't being cleared
 | ||
|     # (leading to an "undetected error" in the debug build).  Set up is,
 | ||
|     # isinstance(inst, cls) where:
 | ||
|     #
 | ||
|     # - inst isn't an InstanceType
 | ||
|     # - cls isn't a ClassType, a TypeType, or a TupleType
 | ||
|     # - cls has a __bases__ attribute
 | ||
|     # - inst has a __class__ attribute
 | ||
|     # - inst.__class__ as no __bases__ attribute
 | ||
|     #
 | ||
|     # Sounds complicated, I know, but this mimics a situation where an
 | ||
|     # extension type raises an AttributeError when its __bases__ attribute is
 | ||
|     # gotten.  In that case, isinstance() should return False.
 | ||
|     def test_class_has_no_bases(self):
 | ||
|         class I(object):
 | ||
|             def getclass(self):
 | ||
|                 # This must return an object that has no __bases__ attribute
 | ||
|                 return None
 | ||
|             __class__ = property(getclass)
 | ||
| 
 | ||
|         class C(object):
 | ||
|             def getbases(self):
 | ||
|                 return ()
 | ||
|             __bases__ = property(getbases)
 | ||
| 
 | ||
|         self.assertEqual(False, isinstance(I(), C()))
 | ||
| 
 | ||
|     # Like above except that inst.__class__.__bases__ raises an exception
 | ||
|     # other than AttributeError
 | ||
|     def test_bases_raises_other_than_attribute_error(self):
 | ||
|         class E(object):
 | ||
|             def getbases(self):
 | ||
|                 raise RuntimeError
 | ||
|             __bases__ = property(getbases)
 | ||
| 
 | ||
|         class I(object):
 | ||
|             def getclass(self):
 | ||
|                 return E()
 | ||
|             __class__ = property(getclass)
 | ||
| 
 | ||
|         class C(object):
 | ||
|             def getbases(self):
 | ||
|                 return ()
 | ||
|             __bases__ = property(getbases)
 | ||
| 
 | ||
|         self.assertRaises(RuntimeError, isinstance, I(), C())
 | ||
| 
 | ||
|     # Here's a situation where getattr(cls, '__bases__') raises an exception.
 | ||
|     # If that exception is not AttributeError, it should not get masked
 | ||
|     def test_dont_mask_non_attribute_error(self):
 | ||
|         class I: pass
 | ||
| 
 | ||
|         class C(object):
 | ||
|             def getbases(self):
 | ||
|                 raise RuntimeError
 | ||
|             __bases__ = property(getbases)
 | ||
| 
 | ||
|         self.assertRaises(RuntimeError, isinstance, I(), C())
 | ||
| 
 | ||
|     # Like above, except that getattr(cls, '__bases__') raises an
 | ||
|     # AttributeError, which /should/ get masked as a TypeError
 | ||
|     def test_mask_attribute_error(self):
 | ||
|         class I: pass
 | ||
| 
 | ||
|         class C(object):
 | ||
|             def getbases(self):
 | ||
|                 raise AttributeError
 | ||
|             __bases__ = property(getbases)
 | ||
| 
 | ||
|         self.assertRaises(TypeError, isinstance, I(), C())
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| # These tests are similar to above, but tickle certain code paths in
 | ||
| # issubclass() instead of isinstance() -- really PyObject_IsSubclass()
 | ||
| # vs. PyObject_IsInstance().
 | ||
| class TestIsSubclassExceptions(unittest.TestCase):
 | ||
|     def test_dont_mask_non_attribute_error(self):
 | ||
|         class C(object):
 | ||
|             def getbases(self):
 | ||
|                 raise RuntimeError
 | ||
|             __bases__ = property(getbases)
 | ||
| 
 | ||
|         class S(C): pass
 | ||
| 
 | ||
|         self.assertRaises(RuntimeError, issubclass, C(), S())
 | ||
| 
 | ||
|     def test_mask_attribute_error(self):
 | ||
|         class C(object):
 | ||
|             def getbases(self):
 | ||
|                 raise AttributeError
 | ||
|             __bases__ = property(getbases)
 | ||
| 
 | ||
|         class S(C): pass
 | ||
| 
 | ||
|         self.assertRaises(TypeError, issubclass, C(), S())
 | ||
| 
 | ||
|     # Like above, but test the second branch, where the __bases__ of the
 | ||
|     # second arg (the cls arg) is tested.  This means the first arg must
 | ||
|     # return a valid __bases__, and it's okay for it to be a normal --
 | ||
|     # unrelated by inheritance -- class.
 | ||
|     def test_dont_mask_non_attribute_error_in_cls_arg(self):
 | ||
|         class B: pass
 | ||
| 
 | ||
|         class C(object):
 | ||
|             def getbases(self):
 | ||
|                 raise RuntimeError
 | ||
|             __bases__ = property(getbases)
 | ||
| 
 | ||
|         self.assertRaises(RuntimeError, issubclass, B, C())
 | ||
| 
 | ||
|     def test_mask_attribute_error_in_cls_arg(self):
 | ||
|         class B: pass
 | ||
| 
 | ||
|         class C(object):
 | ||
|             def getbases(self):
 | ||
|                 raise AttributeError
 | ||
|             __bases__ = property(getbases)
 | ||
| 
 | ||
|         self.assertRaises(TypeError, issubclass, B, C())
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| # meta classes for creating abstract classes and instances
 | ||
| class AbstractClass(object):
 | ||
|     def __init__(self, bases):
 | ||
|         self.bases = bases
 | ||
| 
 | ||
|     def getbases(self):
 | ||
|         return self.bases
 | ||
|     __bases__ = property(getbases)
 | ||
| 
 | ||
|     def __call__(self):
 | ||
|         return AbstractInstance(self)
 | ||
| 
 | ||
| class AbstractInstance(object):
 | ||
|     def __init__(self, klass):
 | ||
|         self.klass = klass
 | ||
| 
 | ||
|     def getclass(self):
 | ||
|         return self.klass
 | ||
|     __class__ = property(getclass)
 | ||
| 
 | ||
| # abstract classes
 | ||
| AbstractSuper = AbstractClass(bases=())
 | ||
| 
 | ||
| AbstractChild = AbstractClass(bases=(AbstractSuper,))
 | ||
| 
 | ||
| # normal classes
 | ||
| class Super:
 | ||
|     pass
 | ||
| 
 | ||
| class Child(Super):
 | ||
|     pass
 | ||
| 
 | ||
| # new-style classes
 | ||
| class NewSuper(object):
 | ||
|     pass
 | ||
| 
 | ||
| class NewChild(NewSuper):
 | ||
|     pass
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| class TestIsInstanceIsSubclass(unittest.TestCase):
 | ||
|     # Tests to ensure that isinstance and issubclass work on abstract
 | ||
|     # classes and instances.  Before the 2.2 release, TypeErrors were
 | ||
|     # raised when boolean values should have been returned.  The bug was
 | ||
|     # triggered by mixing 'normal' classes and instances were with
 | ||
|     # 'abstract' classes and instances.  This case tries to test all
 | ||
|     # combinations.
 | ||
| 
 | ||
|     def test_isinstance_normal(self):
 | ||
|         # normal instances
 | ||
|         self.assertEqual(True, isinstance(Super(), Super))
 | ||
|         self.assertEqual(False, isinstance(Super(), Child))
 | ||
|         self.assertEqual(False, isinstance(Super(), AbstractSuper))
 | ||
|         self.assertEqual(False, isinstance(Super(), AbstractChild))
 | ||
| 
 | ||
|         self.assertEqual(True, isinstance(Child(), Super))
 | ||
|         self.assertEqual(False, isinstance(Child(), AbstractSuper))
 | ||
| 
 | ||
|     def test_isinstance_abstract(self):
 | ||
|         # abstract instances
 | ||
|         self.assertEqual(True, isinstance(AbstractSuper(), AbstractSuper))
 | ||
|         self.assertEqual(False, isinstance(AbstractSuper(), AbstractChild))
 | ||
|         self.assertEqual(False, isinstance(AbstractSuper(), Super))
 | ||
|         self.assertEqual(False, isinstance(AbstractSuper(), Child))
 | ||
| 
 | ||
|         self.assertEqual(True, isinstance(AbstractChild(), AbstractChild))
 | ||
|         self.assertEqual(True, isinstance(AbstractChild(), AbstractSuper))
 | ||
|         self.assertEqual(False, isinstance(AbstractChild(), Super))
 | ||
|         self.assertEqual(False, isinstance(AbstractChild(), Child))
 | ||
| 
 | ||
|     def test_subclass_normal(self):
 | ||
|         # normal classes
 | ||
|         self.assertEqual(True, issubclass(Super, Super))
 | ||
|         self.assertEqual(False, issubclass(Super, AbstractSuper))
 | ||
|         self.assertEqual(False, issubclass(Super, Child))
 | ||
| 
 | ||
|         self.assertEqual(True, issubclass(Child, Child))
 | ||
|         self.assertEqual(True, issubclass(Child, Super))
 | ||
|         self.assertEqual(False, issubclass(Child, AbstractSuper))
 | ||
| 
 | ||
|     def test_subclass_abstract(self):
 | ||
|         # abstract classes
 | ||
|         self.assertEqual(True, issubclass(AbstractSuper, AbstractSuper))
 | ||
|         self.assertEqual(False, issubclass(AbstractSuper, AbstractChild))
 | ||
|         self.assertEqual(False, issubclass(AbstractSuper, Child))
 | ||
| 
 | ||
|         self.assertEqual(True, issubclass(AbstractChild, AbstractChild))
 | ||
|         self.assertEqual(True, issubclass(AbstractChild, AbstractSuper))
 | ||
|         self.assertEqual(False, issubclass(AbstractChild, Super))
 | ||
|         self.assertEqual(False, issubclass(AbstractChild, Child))
 | ||
| 
 | ||
|     def test_subclass_tuple(self):
 | ||
|         # test with a tuple as the second argument classes
 | ||
|         self.assertEqual(True, issubclass(Child, (Child,)))
 | ||
|         self.assertEqual(True, issubclass(Child, (Super,)))
 | ||
|         self.assertEqual(False, issubclass(Super, (Child,)))
 | ||
|         self.assertEqual(True, issubclass(Super, (Child, Super)))
 | ||
|         self.assertEqual(False, issubclass(Child, ()))
 | ||
|         self.assertEqual(True, issubclass(Super, (Child, (Super,))))
 | ||
| 
 | ||
|         self.assertEqual(True, issubclass(NewChild, (NewChild,)))
 | ||
|         self.assertEqual(True, issubclass(NewChild, (NewSuper,)))
 | ||
|         self.assertEqual(False, issubclass(NewSuper, (NewChild,)))
 | ||
|         self.assertEqual(True, issubclass(NewSuper, (NewChild, NewSuper)))
 | ||
|         self.assertEqual(False, issubclass(NewChild, ()))
 | ||
|         self.assertEqual(True, issubclass(NewSuper, (NewChild, (NewSuper,))))
 | ||
| 
 | ||
|         self.assertEqual(True, issubclass(int, (long, (float, int))))
 | ||
|         if test_support.have_unicode:
 | ||
|             self.assertEqual(True, issubclass(str, (unicode, (Child, NewChild, basestring))))
 | ||
| 
 | ||
|     def test_subclass_recursion_limit(self):
 | ||
|         # make sure that issubclass raises RuntimeError before the C stack is
 | ||
|         # blown
 | ||
|         self.assertRaises(RuntimeError, blowstack, issubclass, str, str)
 | ||
| 
 | ||
|     def test_isinstance_recursion_limit(self):
 | ||
|         # make sure that issubclass raises RuntimeError before the C stack is
 | ||
|         # blown
 | ||
|         self.assertRaises(RuntimeError, blowstack, isinstance, '', str)
 | ||
| 
 | ||
| def blowstack(fxn, arg, compare_to):
 | ||
|     # Make sure that calling isinstance with a deeply nested tuple for its
 | ||
|     # argument will raise RuntimeError eventually.
 | ||
|     tuple_arg = (compare_to,)
 | ||
|     for cnt in xrange(sys.getrecursionlimit()+5):
 | ||
|         tuple_arg = (tuple_arg,)
 | ||
|         fxn(arg, tuple_arg)
 | ||
| 
 | ||
| 
 | ||
| def test_main():
 | ||
|     test_support.run_unittest(
 | ||
|         TestIsInstanceExceptions,
 | ||
|         TestIsSubclassExceptions,
 | ||
|         TestIsInstanceIsSubclass
 | ||
|     )
 | ||
| 
 | ||
| 
 | ||
| if __name__ == '__main__':
 | ||
|     test_main()
 |