From 82550d5b8654cee55357cef303038effa4e0448a Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Tue, 8 Apr 2003 19:02:34 +0000 Subject: Added private API function _PyInstance_Lookup(). This is part of backporting fixes so that garbage collection doesn't have to trigger execution of arbitrary Python code just to figure out whether an object has a __del__ method. --- Include/classobject.h | 12 ++++++++++++ Objects/classobject.c | 37 +++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/Include/classobject.h b/Include/classobject.h index c79f4a2..16af37b 100644 --- a/Include/classobject.h +++ b/Include/classobject.h @@ -51,6 +51,18 @@ extern DL_IMPORT(PyObject *) PyMethod_Function(PyObject *); extern DL_IMPORT(PyObject *) PyMethod_Self(PyObject *); extern DL_IMPORT(PyObject *) PyMethod_Class(PyObject *); +/* Look up attribute with name (a string) on instance object pinst, using + * only the instance and base class dicts. If a descriptor is found in + * a class dict, the descriptor is returned without calling it. + * Returns NULL if nothing found, else a borrowed reference to the + * value associated with name in the dict in which name was found. + * The point of this routine is that it never calls arbitrary Python + * code, so is always "safe": all it does is dict lookups. The function + * can't fail, never sets an exception, and NULL is not an error (it just + * means "not found"). + */ +PyAPI_FUNC(PyObject *) _PyInstance_Lookup(PyObject *pinst, PyObject *name); + /* Macros for direct access to these values. Type checks are *not* done, so use with care. */ #define PyMethod_GET_FUNCTION(meth) \ diff --git a/Objects/classobject.c b/Objects/classobject.c index c1c4a3e..90f169e 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -729,6 +729,27 @@ instance_getattr(register PyInstanceObject *inst, PyObject *name) return res; } +/* See classobject.h comments: this only does dict lookups, and is always + * safe to call. + */ +PyObject * +_PyInstance_Lookup(PyObject *pinst, PyObject *name) +{ + PyObject *v; + PyClassObject *class; + PyInstanceObject *inst; /* pinst cast to the right type */ + + assert(PyInstance_Check(pinst)); + inst = (PyInstanceObject *)pinst; + + assert(PyString_Check(name)); + + v = PyDict_GetItem(inst->in_dict, name); + if (v == NULL) + v = class_lookup(inst->in_class, name, &class); + return v; +} + static int instance_setattr1(PyInstanceObject *inst, PyObject *name, PyObject *v) { @@ -1056,7 +1077,7 @@ sliceobj_from_intint(int i, int j) start = PyInt_FromLong((long)i); if (!start) return NULL; - + end = PyInt_FromLong((long)j); if (!end) { Py_DECREF(start); @@ -1088,9 +1109,9 @@ instance_slice(PyInstanceObject *inst, int i, int j) if (func == NULL) return NULL; arg = Py_BuildValue("(N)", sliceobj_from_intint(i, j)); - } else + } else arg = Py_BuildValue("(ii)", i, j); - + if (arg == NULL) { Py_DECREF(func); return NULL; @@ -1219,7 +1240,7 @@ instance_contains(PyInstanceObject *inst, PyObject *member) res = PyEval_CallObject(func, arg); Py_DECREF(func); Py_DECREF(arg); - if(res == NULL) + if(res == NULL) return -1; ret = PyObject_IsTrue(res); Py_DECREF(res); @@ -1292,7 +1313,7 @@ static PyObject *coerce_obj; /* Try one half of a binary operator involving a class instance. */ static PyObject * -half_binop(PyObject *v, PyObject *w, char *opname, binaryfunc thisfunc, +half_binop(PyObject *v, PyObject *w, char *opname, binaryfunc thisfunc, int swapped) { PyObject *args; @@ -1300,7 +1321,7 @@ half_binop(PyObject *v, PyObject *w, char *opname, binaryfunc thisfunc, PyObject *coerced = NULL; PyObject *v1; PyObject *result; - + if (!PyInstance_Check(v)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; @@ -1654,7 +1675,7 @@ bin_power(PyObject *v, PyObject *w) /* This version is for ternary calls only (z != None) */ static PyObject * instance_pow(PyObject *v, PyObject *w, PyObject *z) -{ +{ if (z == Py_None) { return do_binop(v, w, "__pow__", "__rpow__", bin_power); } @@ -1723,7 +1744,7 @@ instance_ipow(PyObject *v, PyObject *w, PyObject *z) #define NAME_OPS 6 static PyObject **name_op = NULL; -static int +static int init_name_op(void) { int i; -- cgit v0.12