[pypy-svn] r75653 - in pypy/branch/fast-forward/pypy: interpreter objspace objspace/flow objspace/std objspace/test translator
benjamin at codespeak.net
benjamin at codespeak.net
Mon Jun 28 22:12:22 CEST 2010
Author: benjamin
Date: Mon Jun 28 22:12:19 2010
New Revision: 75653
Modified:
pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py
pypy/branch/fast-forward/pypy/objspace/descroperation.py
pypy/branch/fast-forward/pypy/objspace/flow/operation.py
pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py
pypy/branch/fast-forward/pypy/objspace/std/typeobject.py
pypy/branch/fast-forward/pypy/objspace/test/test_descroperation.py
pypy/branch/fast-forward/pypy/translator/geninterplevel.py
Log:
support __subclasscheck__ and __instancecheck__
Modified: pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py Mon Jun 28 22:12:19 2010
@@ -870,10 +870,6 @@
return self.w_True
return self.w_False
- def isinstance(self, w_obj, w_type):
- w_objtype = self.type(w_obj)
- return self.issubtype(w_objtype, w_type)
-
def isinstance_w(self, w_obj, w_type):
return self.is_true(self.isinstance(w_obj, w_type))
@@ -904,7 +900,7 @@
# it with exception_
def exception_is_valid_obj_as_class_w(self, w_obj):
- if not self.is_true(self.isinstance(w_obj, self.w_type)):
+ if not self.isinstance_w(w_obj, self.w_type):
return False
if not self.full_exceptions:
return True
@@ -1201,7 +1197,8 @@
('is_', 'is', 2, []),
('id', 'id', 1, []),
('type', 'type', 1, []),
- ('issubtype', 'issubtype', 2, []), # not for old-style classes
+ ('isinstance', 'isinstance', 2, ['__instancecheck__']),
+ ('issubtype', 'issubtype', 2, ['__subclasscheck__']), # not for old-style classes
('repr', 'repr', 1, ['__repr__']),
('str', 'str', 1, ['__str__']),
('format', 'format', 2, ['__format__']),
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 Mon Jun 28 22:12:19 2010
@@ -464,10 +464,19 @@
raise OperationError(space.w_TypeError,
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)
- # xxx ord
+ 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)
Modified: pypy/branch/fast-forward/pypy/objspace/flow/operation.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/flow/operation.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/flow/operation.py Mon Jun 28 22:12:19 2010
@@ -174,6 +174,7 @@
('id', id),
('type', new_style_type),
('type', type),
+ ('isinstance', isinstance),
('issubtype', issubclass),
('repr', repr),
('str', str),
Modified: pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/builtinshortcut.py Mon Jun 28 22:12:19 2010
@@ -39,6 +39,7 @@
'abs', 'hex', 'oct', # rare stuff?
'pos', 'divmod', 'cmp', # rare stuff?
'float', 'long', 'coerce', # rare stuff?
+ 'isinstance', 'issubtype',
]
# We cannot support {get,set,del}slice right now because
# DescrOperation.{get,set,del}slice do a bit more work than just call
Modified: pypy/branch/fast-forward/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/typeobject.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/typeobject.py Mon Jun 28 22:12:19 2010
@@ -321,7 +321,7 @@
raise operationerrfmt(space.w_TypeError,
"X is not a type object ('%s')",
space.type(w_subtype).getname(space, '?'))
- if not space.is_true(space.issubtype(w_subtype, w_self)):
+ if not w_subtype.issubtype(w_self):
raise operationerrfmt(space.w_TypeError,
"%s.__new__(%s): %s is not a subtype of %s",
w_self.name, w_subtype.name, w_subtype.name, w_self.name)
@@ -358,6 +358,17 @@
def is_cpytype(w_self):
return w_self.__flags__ & _CPYTYPE
+ def issubtype(w_self, w_type):
+ w_self = hint(w_self, promote=True)
+ w_type = hint(w_type, promote=True)
+ if w_self.space.config.objspace.std.withtypeversion and we_are_jitted():
+ version_tag1 = w_self.version_tag()
+ version_tag2 = w_type.version_tag()
+ if version_tag1 is not None and version_tag2 is not None:
+ res = _pure_issubtype(w_self, w_type, version_tag1, version_tag2)
+ return res
+ return _issubtype(w_self, w_type)
+
def get_module(w_self):
space = w_self.space
if w_self.is_heaptype() and '__module__' in w_self.dict_w:
@@ -700,24 +711,18 @@
space.wrap("__init__() should return None"))
return w_newobject
-def _issubtype(w_type1, w_type2):
- return w_type2 in w_type1.mro_w
+def _issubtype(w_sub, w_type):
+ return w_type in w_sub.mro_w
@purefunction_promote()
-def _pure_issubtype(w_type1, w_type2, version_tag1, version_tag2):
- return _issubtype(w_type1, w_type2)
+def _pure_issubtype(w_sub, w_type, version_tag1, version_tag2):
+ return _issubtype(w_sub, w_type)
+
+def issubtype__Type_Type(space, w_type, w_sub):
+ return space.newbool(w_sub.issubtype(w_type))
-def issubtype__Type_Type(space, w_type1, w_type2):
- w_type1 = hint(w_type1, promote=True)
- w_type2 = hint(w_type2, promote=True)
- if space.config.objspace.std.withtypeversion and we_are_jitted():
- version_tag1 = w_type1.version_tag()
- version_tag2 = w_type2.version_tag()
- if version_tag1 is not None and version_tag2 is not None:
- res = _pure_issubtype(w_type1, w_type2, version_tag1, version_tag2)
- return space.newbool(res)
- res = _issubtype(w_type1, w_type2)
- return space.newbool(res)
+def isinstance__Type_ANY(space, w_type, w_inst):
+ return space.newbool(space.type(w_inst).issubtype(w_type))
def repr__Type(space, w_obj):
w_mod = w_obj.get_module()
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 Mon Jun 28 22:12:19 2010
@@ -463,6 +463,33 @@
return self
raises(TypeError, iter, x())
+ def test_isinstance_and_issubclass(self):
+ class Meta(type):
+ def __instancecheck__(cls, instance):
+ if cls is A:
+ return True
+ return False
+ def __subclasscheck__(cls, sub):
+ if cls is B:
+ return True
+ return False
+ class A:
+ __metaclass__ = Meta
+ class B(A):
+ pass
+ a = A()
+ b = B()
+ assert isinstance(a, A)
+ assert not isinstance(a, B)
+ assert isinstance(b, A)
+ assert not isinstance(b, B)
+ assert isinstance(4, A)
+ assert not issubclass(A, A)
+ assert not issubclass(B, A)
+ assert issubclass(A, B)
+ assert issubclass(B, B)
+ assert issubclass(23, B)
+
class AppTestWithBuiltinShortcut(AppTest_Descroperation):
OPTIONS = {'objspace.std.builtinshortcut': True}
Modified: pypy/branch/fast-forward/pypy/translator/geninterplevel.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/geninterplevel.py (original)
+++ pypy/branch/fast-forward/pypy/translator/geninterplevel.py Mon Jun 28 22:12:19 2010
@@ -225,13 +225,14 @@
return ", ".join(res)
def oper(self, op, localscope):
- if op.opname == 'issubtype':
+ if op.opname in ('issubtype', 'isinstance'):
arg = op.args[1]
if (not isinstance(arg, Constant)
or not isinstance(arg.value, (type, types.ClassType))):
- op = SpaceOperation("simple_call",
- [Constant(issubclass)]+op.args,
- op.result)
+ func = issubclass if op.opname == 'issubtype' else isinstance
+ op = SpaceOperation("simple_call",
+ [Constant(func)]+op.args,
+ op.result)
if op.opname == "simple_call":
v = op.args[0]
space_shortcut = self.try_space_shortcut_for_builtin(v, len(op.args)-1,
@@ -703,21 +704,15 @@
arities = self._space_arities = {}
for name, sym, arity, specnames in self.space.MethodTable:
arities[name] = arity
- arities['isinstance'] = 2
+ del arities["isinstance"]
return self._space_arities
def try_space_shortcut_for_builtin(self, v, nargs, args):
if isinstance(v, Constant) and v.value in self.ibuiltin_ids:
name = self.ibuiltin_ids[v.value].__name__
- if hasattr(self.space, name):
- if self.space_arities().get(name, -1) == nargs:
- if name != 'isinstance':
- return "space.%s" % name
- else:
- arg = args[1]
- if (isinstance(arg, Constant)
- and isinstance(arg.value, (type, types.ClassType))):
- return "space.isinstance"
+ if (hasattr(self.space, name) and
+ self.space_arities().get(name, -1) == nargs):
+ return "space.%s" % name
return None
def nameof_builtin_function_or_method(self, func):
More information about the Pypy-commit
mailing list