diff options
Diffstat (limited to 'Objects/object.c')
-rw-r--r-- | Objects/object.c | 229 |
1 files changed, 26 insertions, 203 deletions
diff --git a/Objects/object.c b/Objects/object.c index a91c46a..05c52f1 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1,5 +1,5 @@ -/* Generic object operations; and implementation of None (NoObject) */ +/* Generic object operations; and implementation of None */ #include "Python.h" #include "frameobject.h" @@ -29,8 +29,6 @@ _Py_GetRefTotal(void) } #endif /* Py_REF_DEBUG */ -int Py_DivisionWarningFlag; - /* Object allocation routines used by NEWOBJ and NEWVAROBJ macros. These are used by the individual routines for object creation. Do not call them otherwise, they do not initialize the object! */ @@ -1184,66 +1182,6 @@ PyCallable_Check(PyObject *x) return x->ob_type->tp_call != NULL; } -/* ------------------------- PyObject_Dir() helpers ------------------------- */ - -/* Helper for PyObject_Dir. - Merge the __dict__ of aclass into dict, and recursively also all - the __dict__s of aclass's base classes. The order of merging isn't - defined, as it's expected that only the final set of dict keys is - interesting. - Return 0 on success, -1 on error. -*/ - -static int -merge_class_dict(PyObject* dict, PyObject* aclass) -{ - PyObject *classdict; - PyObject *bases; - - assert(PyDict_Check(dict)); - assert(aclass); - - /* Merge in the type's dict (if any). */ - classdict = PyObject_GetAttrString(aclass, "__dict__"); - if (classdict == NULL) - PyErr_Clear(); - else { - int status = PyDict_Update(dict, classdict); - Py_DECREF(classdict); - if (status < 0) - return -1; - } - - /* Recursively merge in the base types' (if any) dicts. */ - bases = PyObject_GetAttrString(aclass, "__bases__"); - if (bases == NULL) - PyErr_Clear(); - else { - /* We have no guarantee that bases is a real tuple */ - Py_ssize_t i, n; - n = PySequence_Size(bases); /* This better be right */ - if (n < 0) - PyErr_Clear(); - else { - for (i = 0; i < n; i++) { - int status; - PyObject *base = PySequence_GetItem(bases, i); - if (base == NULL) { - Py_DECREF(bases); - return -1; - } - status = merge_class_dict(dict, base); - Py_DECREF(base); - if (status < 0) { - Py_DECREF(bases); - return -1; - } - } - } - Py_DECREF(bases); - } - return 0; -} /* Helper for PyObject_Dir without arguments: returns the local scope. */ static PyObject * @@ -1267,140 +1205,43 @@ _dir_locals(void) Py_DECREF(names); return NULL; } + if (PyList_Sort(names)) { + Py_DECREF(names); + return NULL; + } /* the locals don't need to be DECREF'd */ return names; } -/* Helper for PyObject_Dir of type objects: returns __dict__ and __bases__. - We deliberately don't suck up its __class__, as methods belonging to the - metaclass would probably be more confusing than helpful. -*/ -static PyObject * -_specialized_dir_type(PyObject *obj) -{ - PyObject *result = NULL; - PyObject *dict = PyDict_New(); - - if (dict != NULL && merge_class_dict(dict, obj) == 0) - result = PyDict_Keys(dict); - - Py_XDECREF(dict); - return result; -} - -/* Helper for PyObject_Dir of module objects: returns the module's __dict__. */ -static PyObject * -_specialized_dir_module(PyObject *obj) -{ - PyObject *result = NULL; - PyObject *dict = PyObject_GetAttrString(obj, "__dict__"); - - if (dict != NULL) { - if (PyDict_Check(dict)) - result = PyDict_Keys(dict); - else { - const char *name = PyModule_GetName(obj); - if (name) - PyErr_Format(PyExc_TypeError, - "%.200s.__dict__ is not a dictionary", - name); - } - } - - Py_XDECREF(dict); - return result; -} - -/* Helper for PyObject_Dir of generic objects: returns __dict__, __class__, - and recursively up the __class__.__bases__ chain. -*/ -static PyObject * -_generic_dir(PyObject *obj) -{ - PyObject *result = NULL; - PyObject *dict = NULL; - PyObject *itsclass = NULL; - - /* Get __dict__ (which may or may not be a real dict...) */ - dict = PyObject_GetAttrString(obj, "__dict__"); - if (dict == NULL) { - PyErr_Clear(); - dict = PyDict_New(); - } - else if (!PyDict_Check(dict)) { - Py_DECREF(dict); - dict = PyDict_New(); - } - else { - /* Copy __dict__ to avoid mutating it. */ - PyObject *temp = PyDict_Copy(dict); - Py_DECREF(dict); - dict = temp; - } - - if (dict == NULL) - goto error; - - /* Merge in attrs reachable from its class. */ - itsclass = PyObject_GetAttrString(obj, "__class__"); - if (itsclass == NULL) - /* XXX(tomer): Perhaps fall back to obj->ob_type if no - __class__ exists? */ - PyErr_Clear(); - else { - if (merge_class_dict(dict, itsclass) != 0) - goto error; - } - - result = PyDict_Keys(dict); - /* fall through */ -error: - Py_XDECREF(itsclass); - Py_XDECREF(dict); - return result; -} - -/* Helper for PyObject_Dir: object introspection. - This calls one of the above specialized versions if no __dir__ method - exists. */ +/* Helper for PyObject_Dir: object introspection. */ static PyObject * _dir_object(PyObject *obj) { - PyObject *result = NULL; + PyObject *result, *sorted; static PyObject *dir_str = NULL; PyObject *dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str); assert(obj); if (dirfunc == NULL) { - if (PyErr_Occurred()) - return NULL; - /* use default implementation */ - if (PyModule_Check(obj)) - result = _specialized_dir_module(obj); - else if (PyType_Check(obj)) - result = _specialized_dir_type(obj); - else - result = _generic_dir(obj); + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_TypeError, "object does not provide __dir__"); + return NULL; } - else { - /* use __dir__ */ - result = PyObject_CallFunctionObjArgs(dirfunc, NULL); - Py_DECREF(dirfunc); - if (result == NULL) - return NULL; - - /* result must be a list */ - /* XXX(gbrandl): could also check if all items are strings */ - if (!PyList_Check(result)) { - PyErr_Format(PyExc_TypeError, - "__dir__() must return a list, not %.200s", - Py_TYPE(result)->tp_name); - Py_DECREF(result); - result = NULL; - } + /* use __dir__ */ + result = PyObject_CallFunctionObjArgs(dirfunc, NULL); + Py_DECREF(dirfunc); + if (result == NULL) + return NULL; + /* return sorted(result) */ + sorted = PySequence_List(result); + Py_DECREF(result); + if (sorted == NULL) + return NULL; + if (PyList_Sort(sorted)) { + Py_DECREF(sorted); + return NULL; } - - return result; + return sorted; } /* Implementation of dir() -- if obj is NULL, returns the names in the current @@ -1410,31 +1251,13 @@ _dir_object(PyObject *obj) PyObject * PyObject_Dir(PyObject *obj) { - PyObject * result; - - if (obj == NULL) - /* no object -- introspect the locals */ - result = _dir_locals(); - else - /* object -- introspect the object */ - result = _dir_object(obj); - - assert(result == NULL || PyList_Check(result)); - - if (result != NULL && PyList_Sort(result) != 0) { - /* sorting the list failed */ - Py_DECREF(result); - result = NULL; - } - - return result; + return (obj == NULL) ? _dir_locals() : _dir_object(obj); } /* -NoObject is usable as a non-NULL undefined value, used by the macro None. +None is as a non-NULL undefined value. There is (and should be!) no way to create other objects of this type, so there is exactly one (which is indestructible, by the way). -(XXX This type and the type of NotImplemented below should be unified.) */ /* ARGSUSED */ |