|
|
|
@ -1398,29 +1398,23 @@ PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b) |
|
|
|
return type_is_subtype_base_chain(a, b); |
|
|
|
} |
|
|
|
|
|
|
|
/* Internal routines to do a method lookup in the type |
|
|
|
without looking in the instance dictionary |
|
|
|
(so we can't use PyObject_GetAttr) but still binding |
|
|
|
it to the instance. The arguments are the object, |
|
|
|
the method name as a C string, and the address of a |
|
|
|
static variable used to cache the interned Python string. |
|
|
|
/* Routines to do a method lookup in the type without looking in the |
|
|
|
instance dictionary (so we can't use PyObject_GetAttr) but still |
|
|
|
binding it to the instance. |
|
|
|
|
|
|
|
Variants: |
|
|
|
|
|
|
|
- lookup_maybe() returns NULL without raising an exception |
|
|
|
- _PyObject_LookupSpecial() returns NULL without raising an exception |
|
|
|
when the _PyType_Lookup() call fails; |
|
|
|
|
|
|
|
- lookup_maybe_method() and lookup_method() are similar to |
|
|
|
lookup_maybe(), but can return unbound PyFunction |
|
|
|
- lookup_maybe_method() and lookup_method() are internal routines similar |
|
|
|
to _PyObject_LookupSpecial(), but can return unbound PyFunction |
|
|
|
to avoid temporary method object. Pass self as first argument when |
|
|
|
unbound == 1. |
|
|
|
|
|
|
|
- _PyObject_LookupSpecial() expose lookup_maybe for the benefit of |
|
|
|
other places. |
|
|
|
*/ |
|
|
|
|
|
|
|
static PyObject * |
|
|
|
lookup_maybe(PyObject *self, _Py_Identifier *attrid) |
|
|
|
PyObject * |
|
|
|
_PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) |
|
|
|
{ |
|
|
|
PyObject *res; |
|
|
|
|
|
|
|
@ -1471,12 +1465,6 @@ lookup_method(PyObject *self, _Py_Identifier *attrid, int *unbound) |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
PyObject * |
|
|
|
_PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) |
|
|
|
{ |
|
|
|
return lookup_maybe(self, attrid); |
|
|
|
} |
|
|
|
|
|
|
|
static PyObject* |
|
|
|
call_unbound(int unbound, PyObject *func, PyObject *self, |
|
|
|
PyObject **args, Py_ssize_t nargs) |
|
|
|
@ -1501,9 +1489,8 @@ call_unbound_noarg(int unbound, PyObject *func, PyObject *self) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* A variation of PyObject_CallMethodObjArgs that uses lookup_maybe_method() |
|
|
|
instead of PyObject_GetAttrString(). This uses the same convention |
|
|
|
as lookup_maybe_method to cache the interned name string object. */ |
|
|
|
/* A variation of PyObject_CallMethod* that uses lookup_maybe_method() |
|
|
|
instead of PyObject_GetAttrString(). */ |
|
|
|
static PyObject * |
|
|
|
call_method(PyObject *obj, _Py_Identifier *name, |
|
|
|
PyObject **args, Py_ssize_t nargs) |
|
|
|
@ -1511,13 +1498,10 @@ call_method(PyObject *obj, _Py_Identifier *name, |
|
|
|
int unbound; |
|
|
|
PyObject *func, *retval; |
|
|
|
|
|
|
|
func = lookup_maybe_method(obj, name, &unbound); |
|
|
|
func = lookup_method(obj, name, &unbound); |
|
|
|
if (func == NULL) { |
|
|
|
if (!PyErr_Occurred()) |
|
|
|
PyErr_SetObject(PyExc_AttributeError, name->object); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
retval = call_unbound(unbound, func, obj, args, nargs); |
|
|
|
Py_DECREF(func); |
|
|
|
return retval; |
|
|
|
@ -5960,45 +5944,19 @@ slot_sq_length(PyObject *self) |
|
|
|
return len; |
|
|
|
} |
|
|
|
|
|
|
|
/* Super-optimized version of slot_sq_item. |
|
|
|
Other slots could do the same... */ |
|
|
|
static PyObject * |
|
|
|
slot_sq_item(PyObject *self, Py_ssize_t i) |
|
|
|
{ |
|
|
|
PyObject *func, *ival = NULL, *retval = NULL; |
|
|
|
descrgetfunc f; |
|
|
|
|
|
|
|
func = _PyType_LookupId(Py_TYPE(self), &PyId___getitem__); |
|
|
|
if (func == NULL) { |
|
|
|
PyObject *getitem_str = _PyUnicode_FromId(&PyId___getitem__); |
|
|
|
PyErr_SetObject(PyExc_AttributeError, getitem_str); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
f = Py_TYPE(func)->tp_descr_get; |
|
|
|
if (f == NULL) { |
|
|
|
Py_INCREF(func); |
|
|
|
} |
|
|
|
else { |
|
|
|
func = f(func, self, (PyObject *)(Py_TYPE(self))); |
|
|
|
if (func == NULL) { |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ival = PyLong_FromSsize_t(i); |
|
|
|
PyObject *retval; |
|
|
|
PyObject *args[1]; |
|
|
|
PyObject *ival = PyLong_FromSsize_t(i); |
|
|
|
if (ival == NULL) { |
|
|
|
goto error; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
retval = PyObject_CallFunctionObjArgs(func, ival, NULL); |
|
|
|
Py_DECREF(func); |
|
|
|
args[0] = ival; |
|
|
|
retval = call_method(self, &PyId___getitem__, args, 1); |
|
|
|
Py_DECREF(ival); |
|
|
|
return retval; |
|
|
|
|
|
|
|
error: |
|
|
|
Py_DECREF(func); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
static int |
|
|
|
@ -6223,7 +6181,7 @@ slot_tp_repr(PyObject *self) |
|
|
|
_Py_IDENTIFIER(__repr__); |
|
|
|
int unbound; |
|
|
|
|
|
|
|
func = lookup_method(self, &PyId___repr__, &unbound); |
|
|
|
func = lookup_maybe_method(self, &PyId___repr__, &unbound); |
|
|
|
if (func != NULL) { |
|
|
|
res = call_unbound_noarg(unbound, func, self); |
|
|
|
Py_DECREF(func); |
|
|
|
@ -6243,7 +6201,7 @@ slot_tp_hash(PyObject *self) |
|
|
|
Py_ssize_t h; |
|
|
|
int unbound; |
|
|
|
|
|
|
|
func = lookup_method(self, &PyId___hash__, &unbound); |
|
|
|
func = lookup_maybe_method(self, &PyId___hash__, &unbound); |
|
|
|
|
|
|
|
if (func == Py_None) { |
|
|
|
Py_DECREF(func); |
|
|
|
@ -6422,7 +6380,7 @@ slot_tp_richcompare(PyObject *self, PyObject *other, int op) |
|
|
|
int unbound; |
|
|
|
PyObject *func, *res; |
|
|
|
|
|
|
|
func = lookup_method(self, &name_op[op], &unbound); |
|
|
|
func = lookup_maybe_method(self, &name_op[op], &unbound); |
|
|
|
if (func == NULL) { |
|
|
|
PyErr_Clear(); |
|
|
|
Py_RETURN_NOTIMPLEMENTED; |
|
|
|
@ -6441,7 +6399,7 @@ slot_tp_iter(PyObject *self) |
|
|
|
PyObject *func, *res; |
|
|
|
_Py_IDENTIFIER(__iter__); |
|
|
|
|
|
|
|
func = lookup_method(self, &PyId___iter__, &unbound); |
|
|
|
func = lookup_maybe_method(self, &PyId___iter__, &unbound); |
|
|
|
if (func == Py_None) { |
|
|
|
Py_DECREF(func); |
|
|
|
PyErr_Format(PyExc_TypeError, |
|
|
|
@ -6457,7 +6415,7 @@ slot_tp_iter(PyObject *self) |
|
|
|
} |
|
|
|
|
|
|
|
PyErr_Clear(); |
|
|
|
func = lookup_method(self, &PyId___getitem__, &unbound); |
|
|
|
func = lookup_maybe_method(self, &PyId___getitem__, &unbound); |
|
|
|
if (func == NULL) { |
|
|
|
PyErr_Format(PyExc_TypeError, |
|
|
|
"'%.200s' object is not iterable", |
|
|
|
@ -6597,7 +6555,7 @@ slot_am_await(PyObject *self) |
|
|
|
PyObject *func, *res; |
|
|
|
_Py_IDENTIFIER(__await__); |
|
|
|
|
|
|
|
func = lookup_method(self, &PyId___await__, &unbound); |
|
|
|
func = lookup_maybe_method(self, &PyId___await__, &unbound); |
|
|
|
if (func != NULL) { |
|
|
|
res = call_unbound_noarg(unbound, func, self); |
|
|
|
Py_DECREF(func); |
|
|
|
@ -6616,7 +6574,7 @@ slot_am_aiter(PyObject *self) |
|
|
|
PyObject *func, *res; |
|
|
|
_Py_IDENTIFIER(__aiter__); |
|
|
|
|
|
|
|
func = lookup_method(self, &PyId___aiter__, &unbound); |
|
|
|
func = lookup_maybe_method(self, &PyId___aiter__, &unbound); |
|
|
|
if (func != NULL) { |
|
|
|
res = call_unbound_noarg(unbound, func, self); |
|
|
|
Py_DECREF(func); |
|
|
|
@ -6635,7 +6593,7 @@ slot_am_anext(PyObject *self) |
|
|
|
PyObject *func, *res; |
|
|
|
_Py_IDENTIFIER(__anext__); |
|
|
|
|
|
|
|
func = lookup_method(self, &PyId___anext__, &unbound); |
|
|
|
func = lookup_maybe_method(self, &PyId___anext__, &unbound); |
|
|
|
if (func != NULL) { |
|
|
|
res = call_unbound_noarg(unbound, func, self); |
|
|
|
Py_DECREF(func); |
|
|
|
@ -7182,7 +7140,7 @@ set_names(PyTypeObject *type) |
|
|
|
return -1; |
|
|
|
|
|
|
|
while (PyDict_Next(names_to_set, &i, &key, &value)) { |
|
|
|
set_name = lookup_maybe(value, &PyId___set_name__); |
|
|
|
set_name = _PyObject_LookupSpecial(value, &PyId___set_name__); |
|
|
|
if (set_name != NULL) { |
|
|
|
tmp = PyObject_CallFunctionObjArgs(set_name, type, key, NULL); |
|
|
|
Py_DECREF(set_name); |
|
|
|
|