[Python-checkins] r70617 - python/trunk/Lib/test/test_descr.py

benjamin.peterson python-checkins at python.org
Thu Mar 26 21:17:27 CET 2009


Author: benjamin.peterson
Date: Thu Mar 26 21:17:27 2009
New Revision: 70617

Log:
apply the second part of #4242's patch; classify all the implementation details in test_descr

Modified:
   python/trunk/Lib/test/test_descr.py

Modified: python/trunk/Lib/test/test_descr.py
==============================================================================
--- python/trunk/Lib/test/test_descr.py	(original)
+++ python/trunk/Lib/test/test_descr.py	Thu Mar 26 21:17:27 2009
@@ -75,8 +75,9 @@
         # Find method in parent class
         while meth not in t.__dict__:
             t = t.__bases__[0]
-
-        self.assertEqual(m, t.__dict__[meth])
+        # in some implementations (e.g. PyPy), 'm' can be a regular unbound
+        # method object; the getattr() below obtains its underlying function.
+        self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth])
         self.assertEqual(m(a), res)
         bm = getattr(a, meth)
         self.assertEqual(bm(), res)
@@ -95,7 +96,9 @@
         m = getattr(t, meth)
         while meth not in t.__dict__:
             t = t.__bases__[0]
-        self.assertEqual(m, t.__dict__[meth])
+        # in some implementations (e.g. PyPy), 'm' can be a regular unbound
+        # method object; the getattr() below obtains its underlying function.
+        self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth])
         self.assertEqual(m(a, b), res)
         bm = getattr(a, meth)
         self.assertEqual(bm(b), res)
@@ -107,7 +110,9 @@
         m = getattr(t, meth)
         while meth not in t.__dict__:
             t = t.__bases__[0]
-        self.assertEqual(m, t.__dict__[meth])
+        # in some implementations (e.g. PyPy), 'm' can be a regular unbound
+        # method object; the getattr() below obtains its underlying function.
+        self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth])
         self.assertEqual(m(a, b, c), res)
         bm = getattr(a, meth)
         self.assertEqual(bm(b, c), res)
@@ -120,7 +125,9 @@
         m = getattr(t, meth)
         while meth not in t.__dict__:
             t = t.__bases__[0]
-        self.assertEqual(m, t.__dict__[meth])
+        # in some implementations (e.g. PyPy), 'm' can be a regular unbound
+        # method object; the getattr() below obtains its underlying function.
+        self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth])
         d['a'] = deepcopy(a)
         m(d['a'], b)
         self.assertEqual(d['a'], res)
@@ -137,7 +144,9 @@
         m = getattr(t, meth)
         while meth not in t.__dict__:
             t = t.__bases__[0]
-        self.assertEqual(m, t.__dict__[meth])
+        # in some implementations (e.g. PyPy), 'm' can be a regular unbound
+        # method object; the getattr() below obtains its underlying function.
+        self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth])
         d['a'] = deepcopy(a)
         m(d['a'], b, c)
         self.assertEqual(d['a'], res)
@@ -154,7 +163,9 @@
         while meth not in t.__dict__:
             t = t.__bases__[0]
         m = getattr(t, meth)
-        self.assertEqual(m, t.__dict__[meth])
+        # in some implementations (e.g. PyPy), 'm' can be a regular unbound
+        # method object; the getattr() below obtains its underlying function.
+        self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth])
         dictionary['a'] = deepcopy(a)
         m(dictionary['a'], b, c, d)
         self.assertEqual(dictionary['a'], res)
@@ -182,7 +193,10 @@
 
     def test_dicts(self):
         # Testing dict operations...
-        self.binop_test({1:2}, {2:1}, -1, "cmp(a,b)", "__cmp__")
+        if hasattr(dict, '__cmp__'):   # PyPy has only rich comparison on dicts
+            self.binop_test({1:2}, {2:1}, -1, "cmp(a,b)", "__cmp__")
+        else:
+            self.binop_test({1:2}, {2:1}, True, "a < b", "__lt__")
         self.binop_test({1:2,3:4}, 1, 1, "b in a", "__contains__")
         self.binop_test({1:2,3:4}, 2, 0, "b in a", "__contains__")
         self.binop_test({1:2,3:4}, 1, 2, "a[b]", "__getitem__")
@@ -293,6 +307,7 @@
         self.assertEqual(repr(a), "234.5")
         self.assertEqual(a.prec, 12)
 
+    @test_support.impl_detail("the module 'xxsubtype' is internal")
     def test_spam_lists(self):
         # Testing spamlist operations...
         import copy, xxsubtype as spam
@@ -336,6 +351,7 @@
         a.setstate(42)
         self.assertEqual(a.getstate(), 42)
 
+    @test_support.impl_detail("the module 'xxsubtype' is internal")
     def test_spam_dicts(self):
         # Testing spamdict operations...
         import copy, xxsubtype as spam
@@ -891,8 +907,11 @@
             try:
                 callable(*args)
             except exc, msg:
-                if not str(msg).startswith(expected):
-                    self.fail("Message %r, expected %r" % (str(msg), expected))
+                # the exact msg is generally considered an impl detail
+                if test_support.check_impl_detail():
+                    if not str(msg).startswith(expected):
+                        self.fail("Message %r, expected %r" %
+                                  (str(msg), expected))
             else:
                 self.fail("Expected %s" % exc)
 
@@ -1085,6 +1104,7 @@
         x.c = Counted()
         self.assertEqual(Counted.counter, 3)
         del x
+        test_support.gc_collect()
         self.assertEqual(Counted.counter, 0)
         class D(C):
             pass
@@ -1093,6 +1113,7 @@
         x.z = Counted()
         self.assertEqual(Counted.counter, 2)
         del x
+        test_support.gc_collect()
         self.assertEqual(Counted.counter, 0)
         class E(D):
             __slots__ = ['e']
@@ -1102,6 +1123,7 @@
         x.e = Counted()
         self.assertEqual(Counted.counter, 3)
         del x
+        test_support.gc_collect()
         self.assertEqual(Counted.counter, 0)
 
         # Test cyclical leaks [SF bug 519621]
@@ -1112,22 +1134,23 @@
         s.a = [Counted(), s]
         self.assertEqual(Counted.counter, 1)
         s = None
-        import gc
-        gc.collect()
+        test_support.gc_collect()
         self.assertEqual(Counted.counter, 0)
 
         # Test lookup leaks [SF bug 572567]
         import sys,gc
-        class G(object):
-            def __cmp__(self, other):
-                return 0
-            __hash__ = None # Silence Py3k warning
-        g = G()
-        orig_objects = len(gc.get_objects())
-        for i in xrange(10):
-            g==g
-        new_objects = len(gc.get_objects())
-        self.assertEqual(orig_objects, new_objects)
+        if hasattr(gc, 'get_objects'):
+            class G(object):
+                def __cmp__(self, other):
+                    return 0
+                __hash__ = None # Silence Py3k warning
+            g = G()
+            orig_objects = len(gc.get_objects())
+            for i in xrange(10):
+                g==g
+            new_objects = len(gc.get_objects())
+            self.assertEqual(orig_objects, new_objects)
+
         class H(object):
             __slots__ = ['a', 'b']
             def __init__(self):
@@ -1382,6 +1405,7 @@
         else:
             self.fail("classmethod shouldn't accept keyword args")
 
+    @test_support.impl_detail("the module 'xxsubtype' is internal")
     def test_classmethods_in_c(self):
         # Testing C-based class methods...
         import xxsubtype as spam
@@ -1413,6 +1437,7 @@
         self.assertEqual(d.foo(1), (d, 1))
         self.assertEqual(D.foo(d, 1), (d, 1))
 
+    @test_support.impl_detail("the module 'xxsubtype' is internal")
     def test_staticmethods_in_c(self):
         # Testing C-based static methods...
         import xxsubtype as spam
@@ -1529,6 +1554,14 @@
                 class __metaclass__(type):
                     def mro(self):
                         return [self, dict, object]
+            # In CPython, the class creation above already raises
+            # TypeError, as a protection against the fact that
+            # instances of X would segfault it.  In other Python
+            # implementations it would be ok to let the class X
+            # be created, but instead get a clean TypeError on the
+            # __setitem__ below.
+            x = object.__new__(X)
+            x[5] = 6
         except TypeError:
             pass
         else:
@@ -1766,6 +1799,10 @@
 
         # Safety test for __cmp__
         def unsafecmp(a, b):
+            if not hasattr(a, '__cmp__'):
+                return   # some types don't have a __cmp__ any more (so the
+                         # test doesn't make sense any more), or maybe they
+                         # never had a __cmp__ at all, e.g. in PyPy
             try:
                 a.__class__.__cmp__(a, b)
             except TypeError:
@@ -1781,7 +1818,8 @@
         unsafecmp(1, 1L)
         unsafecmp(1L, 1)
 
-    def test_recursions(self):
+    @test_support.impl_detail("custom logic for printing to real file objects")
+    def test_recursions_1(self):
         # Testing recursion checks ...
         class Letter(str):
             def __new__(cls, letter):
@@ -1806,6 +1844,7 @@
         finally:
             sys.stdout = test_stdout
 
+    def test_recursions_2(self):
         # Bug #1202533.
         class A(object):
             pass
@@ -1826,6 +1865,7 @@
         r = weakref.ref(c)
         self.assertEqual(r(), c)
         del c
+        test_support.gc_collect()
         self.assertEqual(r(), None)
         del r
         class NoWeak(object):
@@ -1843,6 +1883,7 @@
         r = weakref.ref(yes)
         self.assertEqual(r(), yes)
         del yes
+        test_support.gc_collect()
         self.assertEqual(r(), None)
         del r
 
@@ -2179,7 +2220,10 @@
 
         # Two essentially featureless objects, just inheriting stuff from
         # object.
-        self.assertEqual(dir(None), dir(Ellipsis))
+        self.assertEqual(dir(NotImplemented), dir(Ellipsis))
+        if test_support.check_impl_detail():
+            # None differs in PyPy: it has a __nonzero__
+            self.assertEqual(dir(None), dir(Ellipsis))
 
         # Nasty test case for proxied objects
         class Wrapper(object):
@@ -2893,7 +2937,7 @@
                 self.fail("shouldn't allow %r.__class__ = %r" % (x, C))
             try:
                 delattr(x, "__class__")
-            except TypeError:
+            except (TypeError, AttributeError):
                 pass
             else:
                 self.fail("shouldn't allow del %r.__class__" % x)
@@ -3027,6 +3071,16 @@
             mod.__dict__["spam"] = "eggs"
 
         # Exception's __dict__ can be replaced, but not deleted
+        # (at least not any more than regular exception's __dict__ can
+        # be deleted; on CPython it is not the case, whereas on PyPy they
+        # can, just like any other new-style instance's __dict__.)
+        def can_delete_dict(e):
+            try:
+                del e.__dict__
+            except (TypeError, AttributeError):
+                return False
+            else:
+                return True
         class Exception1(Exception, Base):
             pass
         class Exception2(Base, Exception):
@@ -3035,12 +3089,7 @@
             e = ExceptionType()
             e.__dict__ = {"a": 1}
             self.assertEqual(e.a, 1)
-            try:
-                del e.__dict__
-            except (TypeError, AttributeError):
-                pass
-            else:
-                self.fail("%r's __dict__ can be deleted" % e)
+            self.assertEqual(can_delete_dict(e), can_delete_dict(ValueError()))
 
     def test_pickles(self):
         # Testing pickling and copying new-style classes and objects...
@@ -3339,7 +3388,7 @@
         class B(A):
             pass
         del B
-        gc.collect()
+        test_support.gc_collect()
         A.__setitem__ = lambda *a: None # crash
 
     def test_buffer_inheritance(self):
@@ -3431,6 +3480,7 @@
         c = C()
         self.assertEqual(log, [])
         del c
+        test_support.gc_collect()
         self.assertEqual(log, [1])
 
         class D(object): pass
@@ -3526,7 +3576,7 @@
         self.assertEqual(hasattr(m, "__name__"), 0)
         self.assertEqual(hasattr(m, "__file__"), 0)
         self.assertEqual(hasattr(m, "foo"), 0)
-        self.assertEqual(m.__dict__, None)
+        self.assertFalse(m.__dict__)   # None or {} are both reasonable answers
         m.foo = 1
         self.assertEqual(m.__dict__, {"foo": 1})
 
@@ -3661,17 +3711,23 @@
         c = C()
         c.attr = 42
 
-        # The most interesting thing here is whether this blows up, due to flawed
-        # GC tracking logic in typeobject.c's call_finalizer() (a 2.2.1 bug).
+        # The most interesting thing here is whether this blows up, due to
+        # flawed GC tracking logic in typeobject.c's call_finalizer() (a 2.2.1
+        # bug).
         del c
 
         # If that didn't blow up, it's also interesting to see whether clearing
-        # the last container slot works:  that will attempt to delete c again,
-        # which will cause c to get appended back to the container again "during"
-        # the del.
-        del C.container[-1]
+        # the last container slot works: that will attempt to delete c again,
+        # which will cause c to get appended back to the container again
+        # "during" the del.  (On non-CPython implementations, however, __del__
+        # is typically not called again.)
+        test_support.gc_collect()
         self.assertEqual(len(C.container), 1)
-        self.assertEqual(C.container[-1].attr, 42)
+        del C.container[-1]
+        if test_support.check_impl_detail():
+            test_support.gc_collect()
+            self.assertEqual(len(C.container), 1)
+            self.assertEqual(C.container[-1].attr, 42)
 
         # Make c mortal again, so that the test framework with -l doesn't report
         # it as a leak.
@@ -3697,7 +3753,8 @@
             pass
         class C(A,B) :
             __slots__=()
-        self.assertEqual(C.__basicsize__, B.__basicsize__)
+        if test_support.check_impl_detail():
+            self.assertEqual(C.__basicsize__, B.__basicsize__)
         self.assert_(hasattr(C, '__dict__'))
         self.assert_(hasattr(C, '__weakref__'))
         C().x = 2
@@ -3780,7 +3837,7 @@
 
         try:
             del D.__bases__
-        except TypeError:
+        except (TypeError, AttributeError):
             pass
         else:
             self.fail("shouldn't be able to delete .__bases__")
@@ -3981,6 +4038,7 @@
         self.assertEqual(E() // C(), "C.__floordiv__")
         self.assertEqual(C() // E(), "C.__floordiv__") # This one would fail
 
+    @test_support.impl_detail("testing an internal kind of method object")
     def test_meth_class_get(self):
         # Testing __get__ method of METH_CLASS C methods...
         # Full coverage of descrobject.c::classmethod_get()
@@ -4166,7 +4224,7 @@
 
         self.assertEqual(c.attr, 1)
         # this makes a crash more likely:
-        import gc; gc.collect()
+        test_support.gc_collect()
         self.assertEqual(hasattr(c, 'attr'), False)
 
     def test_init(self):
@@ -4191,8 +4249,14 @@
         self.assert_(l.__add__ != [5].__add__)
         self.assert_(l.__add__ != l.__mul__)
         self.assert_(l.__add__.__name__ == '__add__')
-        self.assert_(l.__add__.__self__ is l)
-        self.assert_(l.__add__.__objclass__ is list)
+        if hasattr(l.__add__, '__self__'):
+            # CPython
+            self.assert_(l.__add__.__self__ is l)
+            self.assert_(l.__add__.__objclass__ is list)
+        else:
+            # Python implementations where [].__add__ is a normal bound method
+            self.assert_(l.__add__.im_self is l)
+            self.assert_(l.__add__.im_class is list)
         self.assertEqual(l.__add__.__doc__, list.__add__.__doc__)
         try:
             hash(l.__add__)


More information about the Python-checkins mailing list