Kaydet (Commit) 88fe5f97 authored tarafından Benjamin Peterson's avatar Benjamin Peterson

Merged revisions 72690 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r72690 | benjamin.peterson | 2009-05-16 16:44:25 -0500 (Sat, 16 May 2009) | 1 line

  properly lookup __instancecheck__ and __subclasscheck__
........
üst 188789d8
...@@ -1556,16 +1556,25 @@ order (MRO) for bases """ ...@@ -1556,16 +1556,25 @@ order (MRO) for bases """
return 0 return 0
def stop(self): def stop(self):
raise StopIteration 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 # 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 # only listing the ones I can remember outside of typeobject.c, since it
# does it right. # does it right.
specials = [ specials = [
("__bytes__", bytes, hello, {}), ("__bytes__", bytes, hello, set(), {}),
("__reversed__", reversed, empty_seq, {}), ("__reversed__", reversed, empty_seq, set(), {}),
("__length_hint__", list, zero, ("__length_hint__", list, zero, set(),
{"__iter__" : iden, "__next__" : stop}), {"__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 # 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 # them up. We'd have to add a new opcode to fix this, and it's
# probably not worth it. # probably not worth it.
...@@ -1577,7 +1586,9 @@ order (MRO) for bases """ ...@@ -1577,7 +1586,9 @@ order (MRO) for bases """
def __getattr__(self, attr, test=self): def __getattr__(self, attr, test=self):
test.fail("__getattr__ called with {0}".format(attr)) test.fail("__getattr__ called with {0}".format(attr))
def __getattribute__(self, attr, test=self): 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): class SpecialDescr(object):
def __init__(self, impl): def __init__(self, impl):
self.impl = impl self.impl = impl
...@@ -1586,7 +1597,7 @@ order (MRO) for bases """ ...@@ -1586,7 +1597,7 @@ order (MRO) for bases """
return self.impl.__get__(obj, owner) 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): class X(Checker):
pass pass
for attr, obj in env.items(): for attr, obj in env.items():
......
...@@ -2574,14 +2574,8 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls) ...@@ -2574,14 +2574,8 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
Py_LeaveRecursiveCall(); Py_LeaveRecursiveCall();
return r; return r;
} }
if (name == NULL) {
name = PyUnicode_InternFromString("__instancecheck__"); checker = _PyObject_LookupSpecial(cls, "__instancecheck__", &name);
if (name == NULL)
return -1;
}
checker = PyObject_GetAttr(cls, name);
if (checker == NULL && PyErr_Occurred())
PyErr_Clear();
if (checker != NULL) { if (checker != NULL) {
PyObject *res; PyObject *res;
int ok = -1; int ok = -1;
...@@ -2644,14 +2638,8 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls) ...@@ -2644,14 +2638,8 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
Py_LeaveRecursiveCall(); Py_LeaveRecursiveCall();
return r; return r;
} }
if (name == NULL) {
name = PyUnicode_InternFromString("__subclasscheck__"); checker = _PyObject_LookupSpecial(cls, "__subclasscheck__", &name);
if (name == NULL)
return -1;
}
PyErr_Fetch(&t, &v, &tb);
checker = PyObject_GetAttr(cls, name);
PyErr_Restore(t, v, tb);
if (checker != NULL) { if (checker != NULL) {
PyObject *res; PyObject *res;
int ok = -1; int ok = -1;
......
...@@ -598,14 +598,6 @@ type___instancecheck__(PyObject *type, PyObject *inst) ...@@ -598,14 +598,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 * static PyObject *
type___subclasscheck__(PyObject *type, PyObject *inst) type___subclasscheck__(PyObject *type, PyObject *inst)
{ {
...@@ -619,13 +611,6 @@ type___subclasscheck__(PyObject *type, PyObject *inst) ...@@ -619,13 +611,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[] = { static PyGetSetDef type_getsets[] = {
{"__name__", (getter)type_name, (setter)type_set_name, NULL}, {"__name__", (getter)type_name, (setter)type_set_name, NULL},
...@@ -635,8 +620,6 @@ static PyGetSetDef type_getsets[] = { ...@@ -635,8 +620,6 @@ static PyGetSetDef type_getsets[] = {
(setter)type_set_abstractmethods, NULL}, (setter)type_set_abstractmethods, NULL},
{"__dict__", (getter)type_dict, NULL, NULL}, {"__dict__", (getter)type_dict, NULL, NULL},
{"__doc__", (getter)type_get_doc, NULL, NULL}, {"__doc__", (getter)type_get_doc, NULL, NULL},
{"__instancecheck__", (getter)type_get_instancecheck, NULL, NULL},
{"__subclasscheck__", (getter)type_get_subclasscheck, NULL, NULL},
{0} {0}
}; };
...@@ -2518,6 +2501,10 @@ static PyMethodDef type_methods[] = { ...@@ -2518,6 +2501,10 @@ static PyMethodDef type_methods[] = {
METH_VARARGS | METH_KEYWORDS | METH_CLASS, METH_VARARGS | METH_KEYWORDS | METH_CLASS,
PyDoc_STR("__prepare__() -> dict\n" PyDoc_STR("__prepare__() -> dict\n"
"used to create the namespace for the class statement")}, "used to create the namespace for the class statement")},
{"__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} {0}
}; };
......
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