mirror of https://github.com/python/cpython
Restore PyObject_IsInstance() comment (GH-18345)
Restore PyObject_IsInstance() comment explaining why only tuples of types are accepted, but not general sequence. Comment written by Guido van Rossum in commit03290ecbf1
which implements isinstance(x, (A, B, ...)). The comment was lost in a PyObject_IsInstance() optimization: commitec569b7947
. Cleanup also the code. recursive_isinstance() is no longer recursive, so rename it to object_isinstance(), whereas object_isinstance() is recursive and so rename it to object_recursive_isinstance().
This commit is contained in:
parent
4590f72259
commit
850a4bd839
|
@ -2423,7 +2423,7 @@ check_class(PyObject *cls, const char *error)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
recursive_isinstance(PyObject *inst, PyObject *cls)
|
object_isinstance(PyObject *inst, PyObject *cls)
|
||||||
{
|
{
|
||||||
PyObject *icls;
|
PyObject *icls;
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -2461,21 +2461,23 @@ recursive_isinstance(PyObject *inst, PyObject *cls)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
object_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls)
|
object_recursive_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls)
|
||||||
{
|
{
|
||||||
_Py_IDENTIFIER(__instancecheck__);
|
_Py_IDENTIFIER(__instancecheck__);
|
||||||
PyObject *checker;
|
|
||||||
|
|
||||||
/* Quick test for an exact match */
|
/* Quick test for an exact match */
|
||||||
if (Py_TYPE(inst) == (PyTypeObject *)cls)
|
if (Py_TYPE(inst) == (PyTypeObject *)cls) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* We know what type's __instancecheck__ does. */
|
/* We know what type's __instancecheck__ does. */
|
||||||
if (PyType_CheckExact(cls)) {
|
if (PyType_CheckExact(cls)) {
|
||||||
return recursive_isinstance(inst, cls);
|
return object_isinstance(inst, cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyTuple_Check(cls)) {
|
if (PyTuple_Check(cls)) {
|
||||||
|
/* Not a general sequence -- that opens up the road to
|
||||||
|
recursion and stack overflow. */
|
||||||
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
|
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2483,37 +2485,41 @@ object_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls)
|
||||||
int r = 0;
|
int r = 0;
|
||||||
for (Py_ssize_t i = 0; i < n; ++i) {
|
for (Py_ssize_t i = 0; i < n; ++i) {
|
||||||
PyObject *item = PyTuple_GET_ITEM(cls, i);
|
PyObject *item = PyTuple_GET_ITEM(cls, i);
|
||||||
r = object_isinstance(tstate, inst, item);
|
r = object_recursive_isinstance(tstate, inst, item);
|
||||||
if (r != 0)
|
if (r != 0) {
|
||||||
/* either found it, or got an error */
|
/* either found it, or got an error */
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_Py_LeaveRecursiveCall(tstate);
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__);
|
PyObject *checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__);
|
||||||
if (checker != NULL) {
|
if (checker != NULL) {
|
||||||
int ok = -1;
|
|
||||||
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
|
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
|
||||||
Py_DECREF(checker);
|
Py_DECREF(checker);
|
||||||
return ok;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *res = _PyObject_CallOneArg(checker, inst);
|
PyObject *res = _PyObject_CallOneArg(checker, inst);
|
||||||
_Py_LeaveRecursiveCall(tstate);
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
Py_DECREF(checker);
|
Py_DECREF(checker);
|
||||||
if (res != NULL) {
|
|
||||||
ok = PyObject_IsTrue(res);
|
if (res == NULL) {
|
||||||
Py_DECREF(res);
|
return -1;
|
||||||
}
|
}
|
||||||
|
int ok = PyObject_IsTrue(res);
|
||||||
|
Py_DECREF(res);
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
else if (_PyErr_Occurred(tstate)) {
|
else if (_PyErr_Occurred(tstate)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Probably never reached anymore. */
|
/* cls has no __instancecheck__() method */
|
||||||
return recursive_isinstance(inst, cls);
|
return object_isinstance(inst, cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2521,7 +2527,7 @@ int
|
||||||
PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
||||||
{
|
{
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
return object_isinstance(tstate, inst, cls);
|
return object_recursive_isinstance(tstate, inst, cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2611,7 +2617,7 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
||||||
int
|
int
|
||||||
_PyObject_RealIsInstance(PyObject *inst, PyObject *cls)
|
_PyObject_RealIsInstance(PyObject *inst, PyObject *cls)
|
||||||
{
|
{
|
||||||
return recursive_isinstance(inst, cls);
|
return object_isinstance(inst, cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
Loading…
Reference in New Issue