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;
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)
}
}
-/* 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)
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;
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
_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);
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);
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;
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,
}
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",
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);
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);
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);
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);