[pypy-svn] r75686 - in pypy/branch/fast-forward/pypy: module/__builtin__ module/__builtin__/test objspace objspace/std objspace/test

benjamin at codespeak.net benjamin at codespeak.net
Wed Jun 30 17:13:09 CEST 2010


Author: benjamin
Date: Wed Jun 30 17:13:07 2010
New Revision: 75686

Modified:
   pypy/branch/fast-forward/pypy/module/__builtin__/abstractinst.py
   pypy/branch/fast-forward/pypy/module/__builtin__/test/test_abstractinst.py
   pypy/branch/fast-forward/pypy/objspace/descroperation.py
   pypy/branch/fast-forward/pypy/objspace/std/objspace.py
   pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py
Log:
new plan: disable isinstance() and issubtype() overriding by user classes by default

Modified: pypy/branch/fast-forward/pypy/module/__builtin__/abstractinst.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/__builtin__/abstractinst.py	(original)
+++ pypy/branch/fast-forward/pypy/module/__builtin__/abstractinst.py	Wed Jun 30 17:13:07 2010
@@ -45,12 +45,20 @@
         return space.type(w_obj)
 
 @jit.unroll_safe
-def abstract_isinstance_w(space, w_obj, w_klass_or_tuple):
+def abstract_isinstance_w(space, w_obj, w_klass_or_tuple, allow_override=False):
     """Implementation for the full 'isinstance(obj, klass_or_tuple)'."""
 
+    # -- case (anything, tuple)
+    # XXX it might be risky that the JIT sees this
+    if space.is_true(space.isinstance(w_klass_or_tuple, space.w_tuple)):
+        for w_klass in space.fixedview(w_klass_or_tuple):
+            if abstract_isinstance_w(space, w_obj, w_klass, allow_override):
+                return True
+        return False
+
     # -- case (anything, type)
     try:
-        w_result = space.isinstance(w_obj, w_klass_or_tuple)
+        w_result = space.isinstance(w_obj, w_klass_or_tuple, allow_override)
     except OperationError, e:   # if w_klass_or_tuple was not a type, ignore it
         if not e.match(space, space.w_TypeError):
             raise       # propagate other errors
@@ -64,7 +72,8 @@
             w_pretendtype = space.getattr(w_obj, space.wrap('__class__'))
             if space.is_w(w_pretendtype, space.type(w_obj)):
                 return False     # common case: obj.__class__ is type(obj)
-            w_result = space.issubtype(w_pretendtype, w_klass_or_tuple)
+            w_result = space.issubtype(w_pretendtype, w_klass_or_tuple,
+                                       allow_override)
         except OperationError, e:
             if e.async(space):
                 raise
@@ -78,13 +87,6 @@
         oldstyleinst = space.interpclass_w(w_obj)
         if isinstance(oldstyleinst, W_InstanceObject):
             return oldstyleinst.w_class.is_subclass_of(oldstyleclass)
-    # -- case (anything, tuple)
-    # XXX it might be risky that the JIT sees this
-    if space.is_true(space.isinstance(w_klass_or_tuple, space.w_tuple)):
-        for w_klass in space.fixedview(w_klass_or_tuple):
-            if abstract_isinstance_w(space, w_obj, w_klass):
-                return True
-        return False
     return _abstract_isinstance_w_helper(space, w_obj, w_klass_or_tuple)
 
 @jit.dont_look_inside
@@ -118,12 +120,21 @@
 
 
 @jit.unroll_safe
-def abstract_issubclass_w(space, w_derived, w_klass_or_tuple):
+def abstract_issubclass_w(space, w_derived, w_klass_or_tuple,
+                          allow_override=False):
     """Implementation for the full 'issubclass(derived, klass_or_tuple)'."""
 
+    # -- case (class-like-object, tuple-of-classes)
+    # XXX it might be risky that the JIT sees this
+    if space.is_true(space.isinstance(w_klass_or_tuple, space.w_tuple)):
+        for w_klass in space.fixedview(w_klass_or_tuple):
+            if abstract_issubclass_w(space, w_derived, w_klass, allow_override):
+                return True
+        return False
+
     # -- case (type, type)
     try:
-        w_result = space.issubtype(w_derived, w_klass_or_tuple)
+        w_result = space.issubtype(w_derived, w_klass_or_tuple, allow_override)
     except OperationError, e:   # if one of the args was not a type, ignore it
         if not e.match(space, space.w_TypeError):
             raise       # propagate other errors
@@ -140,14 +151,6 @@
         check_class(space, w_derived, "issubclass() arg 1 must be a class")
     # from here on, we are sure that w_derived is a class-like object
 
-    # -- case (class-like-object, tuple-of-classes)
-    # XXX it might be risky that the JIT sees this
-    if space.is_true(space.isinstance(w_klass_or_tuple, space.w_tuple)):
-        for w_klass in space.fixedview(w_klass_or_tuple):
-            if abstract_issubclass_w(space, w_derived, w_klass):
-                return True
-        return False
-
     # -- case (class-like-object, abstract-class)
     check_class(space, w_klass_or_tuple,
                 "issubclass() arg 2 must be a class, type,"
@@ -193,13 +196,15 @@
     """Check whether a class 'cls' is a subclass (i.e., a derived class) of
 another class.  When using a tuple as the second argument, check whether
 'cls' is a subclass of any of the classes listed in the tuple."""
-    return space.wrap(abstract_issubclass_w(space, w_cls, w_klass_or_tuple))
+    result = abstract_issubclass_w(space, w_cls, w_klass_or_tuple, True)
+    return space.wrap(result)
 
 def isinstance(space, w_obj, w_klass_or_tuple):
     """Check whether an object is an instance of a class (or of a subclass
 thereof).  When using a tuple as the second argument, check whether 'obj'
 is an instance of any of the classes listed in the tuple."""
-    return space.wrap(abstract_isinstance_w(space, w_obj, w_klass_or_tuple))
+    result = abstract_isinstance_w(space, w_obj, w_klass_or_tuple, True)
+    return space.wrap(result)
 
 # avoid namespace pollution
 app_issubclass = issubclass; del issubclass

Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_abstractinst.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_abstractinst.py	(original)
+++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_abstractinst.py	Wed Jun 30 17:13:07 2010
@@ -182,3 +182,23 @@
         assert not issubclass(BSub1, BSub2)
         assert not issubclass(MyInst, BSub1)
         assert not issubclass(BSub1, MyInst)
+
+    def test_overriding(self):
+        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])
+        assert issubclass(int, Integer)
+        assert issubclass(int, (Integer,))

Modified: pypy/branch/fast-forward/pypy/objspace/descroperation.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/descroperation.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/descroperation.py	Wed Jun 30 17:13:07 2010
@@ -465,18 +465,21 @@
                                  space.wrap("coercion should return None or 2-tuple"))
         return w_res
 
-    def issubtype(space, w_sub, w_type):
-        w_check = space.lookup(w_type, "__subclasscheck__")
-        if w_check is None:
-            raise OperationError(space.w_TypeError,
-                                 space.wrap("issubclass not supported here"))
-        return space.get_and_call_function(w_check, w_type, w_sub)
-
-    def isinstance(space, w_inst, w_type):
-        w_check = space.lookup(w_type, "__instancecheck__")
-        if w_check is not None:
-            return space.get_and_call_function(w_check, w_type, w_inst)
-        return space.issubtype(space.type(w_inst), w_type)
+    def issubtype(space, w_sub, w_type, allow_override=False):
+        if allow_override:
+            w_check = space.lookup(w_type, "__subclasscheck__")
+            if w_check is None:
+                raise OperationError(space.w_TypeError,
+                                     space.wrap("issubclass not supported here"))
+            return space.get_and_call_function(w_check, w_type, w_sub)
+        return space._type_issubtype(w_sub, w_type)
+
+    def isinstance(space, w_inst, w_type, allow_override=False):
+        if allow_override:
+            w_check = space.lookup(w_type, "__instancecheck__")
+            if w_check is not None:
+                return space.get_and_call_function(w_check, w_type, w_inst)
+        return space.issubtype(space.type(w_inst), w_type, allow_override)
 
 
 

Modified: pypy/branch/fast-forward/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/objspace.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/std/objspace.py	Wed Jun 30 17:13:07 2010
@@ -508,3 +508,8 @@
     def raise_key_error(self, w_key):
         e = self.call_function(self.w_KeyError, w_key)
         raise OperationError(self.w_KeyError, e)
+
+    def _type_issubtype(self, w_sub, w_type):
+        if isinstance(w_sub, W_TypeObject) and isinstance(w_type, W_TypeObject):
+            return self.wrap(w_sub.issubtype(w_type))
+        raise OperationError(self.w_TypeError, self.wrap("need type objects"))

Modified: pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py	Wed Jun 30 17:13:07 2010
@@ -13,6 +13,22 @@
         space.call_method(l, 'append', space.w_False)
         assert space.nonzero(l) is space.w_True
 
+    def test_isinstance_and_issubtype_ignore_special(self):
+        space = self.space
+        w_tup = space.appexec((), """():
+        class Meta(type):
+            def __subclasscheck__(mcls, cls):
+                return False
+        class Base:
+            __metaclass__ = Meta
+        class Sub(Base):
+            pass
+        return Base, Sub""")
+        w_base, w_sub = space.unpackiterable(w_tup)
+        assert space.is_true(space.issubtype(w_sub, w_base))
+        w_inst = space.call_function(w_sub)
+        assert space.isinstance_w(w_inst, w_base)
+
 
 class AppTest_Descroperation:
     OPTIONS = {}



More information about the Pypy-commit mailing list