Commit 03bc7d3c authored by Guido van Rossum's avatar Guido van Rossum

SF #532767: isinstance(x, X) should work when x is a proxy for an X

instance, as long as x.__class__ is X or a subclass thereof.
Did a little cleanup of PyObject_IsInstance() too.
parent 73019a63
...@@ -3735,7 +3735,8 @@ def dict_type_with_metaclass(): ...@@ -3735,7 +3735,8 @@ def dict_type_with_metaclass():
def meth_class_get(): def meth_class_get():
# Full coverage of descrobject.c::classmethod_get() # Full coverage of descrobject.c::classmethod_get()
if verbose: print "Testing __get__ method of METH_CLASS C methods..." if verbose:
print "Testing __get__ method of METH_CLASS C methods..."
# Baseline # Baseline
arg = [1, 2, 3] arg = [1, 2, 3]
res = {1: None, 2: None, 3: None} res = {1: None, 2: None, 3: None}
...@@ -3772,6 +3773,32 @@ def meth_class_get(): ...@@ -3772,6 +3773,32 @@ def meth_class_get():
else: else:
raise TestFailed, "shouldn't have allowed descr.__get__(None, int)" raise TestFailed, "shouldn't have allowed descr.__get__(None, int)"
def isinst_isclass():
if verbose:
print "Testing proxy isinstance() and isclass()..."
class Proxy(object):
def __init__(self, obj):
self.__obj = obj
def __getattribute__(self, name):
if name.startswith("_Proxy__"):
return object.__getattribute__(self, name)
else:
return getattr(self.__obj, name)
# Test with a classic class
class C:
pass
a = C()
pa = Proxy(a)
verify(isinstance(a, C)) # Baseline
verify(isinstance(pa, C)) # Test
# Test with a new-style class
class C(object):
pass
a = C()
pa = Proxy(a)
verify(isinstance(a, C)) # Baseline
verify(isinstance(pa, C)) # Test
def test_main(): def test_main():
do_this_first() do_this_first()
...@@ -3859,6 +3886,7 @@ def test_main(): ...@@ -3859,6 +3886,7 @@ def test_main():
subclass_right_op() subclass_right_op()
dict_type_with_metaclass() dict_type_with_metaclass()
meth_class_get() meth_class_get()
isinst_isclass()
if verbose: print "All OK" if verbose: print "All OK"
......
...@@ -12,6 +12,11 @@ What's New in Python 2.3 alpha 2? ...@@ -12,6 +12,11 @@ What's New in Python 2.3 alpha 2?
Core and builtins Core and builtins
----------------- -----------------
- isinstance(x, X): if X is a new-style class, this is now equivalent
to issubclass(type(x), X) or issubclass(x.__class__, X). Previously
only type(x) was tested. (For classic classes this was already the
case.)
- compile(), eval() and the exec statement now fully support source code - compile(), eval() and the exec statement now fully support source code
passed as unicode strings. passed as unicode strings.
......
...@@ -2040,6 +2040,12 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls) ...@@ -2040,6 +2040,12 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
static PyObject *__class__ = NULL; static PyObject *__class__ = NULL;
int retval = 0; int retval = 0;
if (__class__ == NULL) {
__class__ = PyString_FromString("__class__");
if (__class__ == NULL)
return -1;
}
if (PyClass_Check(cls) && PyInstance_Check(inst)) { if (PyClass_Check(cls) && PyInstance_Check(inst)) {
PyObject *inclass = PyObject *inclass =
(PyObject*)((PyInstanceObject*)inst)->in_class; (PyObject*)((PyInstanceObject*)inst)->in_class;
...@@ -2047,6 +2053,19 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls) ...@@ -2047,6 +2053,19 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
} }
else if (PyType_Check(cls)) { else if (PyType_Check(cls)) {
retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls); retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);
if (retval == 0) {
PyObject *c = PyObject_GetAttr(inst, __class__);
if (c == NULL) {
PyErr_Clear();
}
else {
if (c != inst->ob_type && PyType_Check(c))
retval = PyType_IsSubtype(
(PyTypeObject *)c,
(PyTypeObject *)cls);
Py_DECREF(c);
}
}
} }
else if (PyTuple_Check(cls)) { else if (PyTuple_Check(cls)) {
/* Not a general sequence -- that opens up the road to /* Not a general sequence -- that opens up the road to
...@@ -2060,18 +2079,12 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls) ...@@ -2060,18 +2079,12 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
if (retval != 0) if (retval != 0)
break; break;
} }
return retval;
} }
else { else {
if (!check_class(cls, if (!check_class(cls,
"isinstance() arg 2 must be a class, type," "isinstance() arg 2 must be a class, type,"
" or tuple of classes and types")) " or tuple of classes and types"))
return -1; return -1;
if (__class__ == NULL) {
__class__ = PyString_FromString("__class__");
if (__class__ == NULL)
return -1;
}
icls = PyObject_GetAttr(inst, __class__); icls = PyObject_GetAttr(inst, __class__);
if (icls == NULL) { if (icls == NULL) {
PyErr_Clear(); PyErr_Clear();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment