summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_descr.py23
-rw-r--r--Objects/abstract.c38
-rw-r--r--Objects/typeobject.c21
3 files changed, 46 insertions, 36 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index e66b550..f3c216a 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1683,16 +1683,25 @@ order (MRO) for bases """
return 0
def stop(self):
raise StopIteration
+ def return_true(self, thing=None):
+ return True
+ def do_isinstance(obj):
+ return isinstance(int, obj)
+ def do_issubclass(obj):
+ return issubclass(int, obj)
# It would be nice to have every special method tested here, but I'm
# only listing the ones I can remember outside of typeobject.c, since it
# does it right.
specials = [
- ("__unicode__", unicode, hello, {}),
- ("__reversed__", reversed, empty_seq, {}),
- ("__length_hint__", list, zero,
+ ("__unicode__", unicode, hello, set(), {}),
+ ("__reversed__", reversed, empty_seq, set(), {}),
+ ("__length_hint__", list, zero, set(),
{"__iter__" : iden, "next" : stop}),
- ("__sizeof__", sys.getsizeof, zero, {}),
+ ("__sizeof__", sys.getsizeof, zero, set(), {}),
+ ("__instancecheck__", do_isinstance, return_true, set(), {}),
+ ("__subclasscheck__", do_issubclass, return_true,
+ set(("__bases__",)), {}),
# These two fail because the compiler generates LOAD_ATTR to look
# them up. We'd have to add a new opcode to fix this, and it's
# probably not worth it.
@@ -1704,7 +1713,9 @@ order (MRO) for bases """
def __getattr__(self, attr, test=self):
test.fail("__getattr__ called with {0}".format(attr))
def __getattribute__(self, attr, test=self):
- test.fail("__getattribute__ called with {0}".format(attr))
+ if attr not in ok:
+ test.fail("__getattribute__ called with {0}".format(attr))
+ return object.__getattribute__(attr)
class SpecialDescr(object):
def __init__(self, impl):
self.impl = impl
@@ -1713,7 +1724,7 @@ order (MRO) for bases """
return self.impl.__get__(obj, owner)
- for name, runner, meth_impl, env in specials:
+ for name, runner, meth_impl, ok, env in specials:
class X(Checker):
pass
for attr, obj in env.iteritems():
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 4da7e00..5fb7bfc 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2926,14 +2926,19 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
Py_LeaveRecursiveCall();
return r;
}
- if (name == NULL) {
- name = PyString_InternFromString("__instancecheck__");
- if (name == NULL)
- return -1;
+
+ if (PyInstance_Check(cls)) {
+ checker = PyObject_GetAttrString(cls, "__instancecheck__");
+ if (checker == NULL) {
+ if (PyErr_ExceptionMatches(PyExc_AttributeError))
+ PyErr_Clear();
+ else
+ return -1;
+ }
+ }
+ else {
+ checker = _PyObject_LookupSpecial(cls, "__instancecheck__", &name);
}
- checker = PyObject_GetAttr(cls, name);
- if (checker == NULL && PyErr_Occurred())
- PyErr_Clear();
if (checker != NULL) {
PyObject *res;
int ok = -1;
@@ -3008,14 +3013,21 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
Py_LeaveRecursiveCall();
return r;
}
- if (name == NULL) {
- name = PyString_InternFromString("__subclasscheck__");
- if (name == NULL)
+ if (PyInstance_Check(cls)) {
+ PyErr_Fetch(&t, &v, &tb);
+ checker = PyObject_GetAttr(cls, name);
+ if (checker == NULL &&
+ !PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ Py_XDECREF(t);
+ Py_XDECREF(v);
+ Py_XDECREF(tb);
return -1;
+ }
+ PyErr_Restore(t, v, tb);
+ }
+ else {
+ checker = _PyObject_LookupSpecial(cls, "__subclasscheck__", &name);
}
- PyErr_Fetch(&t, &v, &tb);
- checker = PyObject_GetAttr(cls, name);
- PyErr_Restore(t, v, tb);
if (checker != NULL) {
PyObject *res;
int ok = -1;
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index fabdd9d..8c49096 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -586,14 +586,6 @@ type___instancecheck__(PyObject *type, PyObject *inst)
static PyObject *
-type_get_instancecheck(PyObject *type, void *context)
-{
- static PyMethodDef ml = {"__instancecheck__",
- type___instancecheck__, METH_O };
- return PyCFunction_New(&ml, type);
-}
-
-static PyObject *
type___subclasscheck__(PyObject *type, PyObject *inst)
{
switch (_PyObject_RealIsSubclass(inst, type)) {
@@ -606,13 +598,6 @@ type___subclasscheck__(PyObject *type, PyObject *inst)
}
}
-static PyObject *
-type_get_subclasscheck(PyObject *type, void *context)
-{
- static PyMethodDef ml = {"__subclasscheck__",
- type___subclasscheck__, METH_O };
- return PyCFunction_New(&ml, type);
-}
static PyGetSetDef type_getsets[] = {
{"__name__", (getter)type_name, (setter)type_set_name, NULL},
@@ -622,8 +607,6 @@ static PyGetSetDef type_getsets[] = {
(setter)type_set_abstractmethods, NULL},
{"__dict__", (getter)type_dict, NULL, NULL},
{"__doc__", (getter)type_get_doc, NULL, NULL},
- {"__instancecheck__", (getter)type_get_instancecheck, NULL, NULL},
- {"__subclasscheck__", (getter)type_get_subclasscheck, NULL, NULL},
{0}
};
@@ -2674,6 +2657,10 @@ static PyMethodDef type_methods[] = {
PyDoc_STR("mro() -> list\nreturn a type's method resolution order")},
{"__subclasses__", (PyCFunction)type_subclasses, METH_NOARGS,
PyDoc_STR("__subclasses__() -> list of immediate subclasses")},
+ {"__instancecheck__", type___instancecheck__, METH_O,
+ PyDoc_STR("__instancecheck__() -> check if an object is an instance")},
+ {"__subclasscheck__", type___subclasscheck__, METH_O,
+ PyDoc_STR("__subclasschck__ -> check if an class is a subclass")},
{0}
};