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.
This commit is contained in:
parent
73019a6321
commit
03bc7d3c4d
@ -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():
|
|||||||
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():
|
|||||||
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?
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user