[Python-checkins] CVS: python/dist/src/Objects object.c,2.143,2.144
Tim Peters
tim_one@users.sourceforge.net
Tue, 04 Sep 2001 15:08:58 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv11322/python/Objects
Modified Files:
object.c
Log Message:
At Guido's suggestion, here's a new C API function, PyObject_Dir(), like
__builtin__.dir(). Moved the guts from bltinmodule.c to object.c.
Index: object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.143
retrieving revision 2.144
diff -C2 -d -r2.143 -r2.144
*** object.c 2001/08/31 17:40:15 2.143
--- object.c 2001/09/04 22:08:56 2.144
***************
*** 1358,1361 ****
--- 1358,1506 ----
}
+ /* 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) {
+ int i, n;
+ assert(PyTuple_Check(bases));
+ n = PyTuple_GET_SIZE(bases);
+ for (i = 0; i < n; i++) {
+ PyObject *base = PyTuple_GET_ITEM(bases, i);
+ if (merge_class_dict(dict, base) < 0) {
+ Py_DECREF(bases);
+ return -1;
+ }
+ }
+ Py_DECREF(bases);
+ }
+ return 0;
+ }
+
+ /* Like __builtin__.dir(arg). See bltinmodule.c's builtin_dir for the
+ docstring, which should be kept in synch with this implementation. */
+
+ PyObject *
+ PyObject_Dir(PyObject *arg)
+ {
+ /* Set exactly one of these non-NULL before the end. */
+ PyObject *result = NULL; /* result list */
+ PyObject *masterdict = NULL; /* result is masterdict.keys() */
+
+ /* If NULL arg, return the locals. */
+ if (arg == NULL) {
+ PyObject *locals = PyEval_GetLocals();
+ if (locals == NULL)
+ goto error;
+ result = PyDict_Keys(locals);
+ if (result == NULL)
+ goto error;
+ }
+
+ /* Elif this is some form of module, we only want its dict. */
+ else if (PyObject_TypeCheck(arg, &PyModule_Type)) {
+ masterdict = PyObject_GetAttrString(arg, "__dict__");
+ if (masterdict == NULL)
+ goto error;
+ assert(PyDict_Check(masterdict));
+ }
+
+ /* Elif some form of type or class, grab its dict and its bases.
+ We deliberately don't suck up its __class__, as methods belonging
+ to the metaclass would probably be more confusing than helpful. */
+ else if (PyType_Check(arg) || PyClass_Check(arg)) {
+ masterdict = PyDict_New();
+ if (masterdict == NULL)
+ goto error;
+ if (merge_class_dict(masterdict, arg) < 0)
+ goto error;
+ }
+
+ /* Else look at its dict, and the attrs reachable from its class. */
+ else {
+ PyObject *itsclass;
+ /* Create a dict to start with. CAUTION: Not everything
+ responding to __dict__ returns a dict! */
+ masterdict = PyObject_GetAttrString(arg, "__dict__");
+ if (masterdict == NULL) {
+ PyErr_Clear();
+ masterdict = PyDict_New();
+ }
+ else if (!PyDict_Check(masterdict)) {
+ Py_DECREF(masterdict);
+ masterdict = PyDict_New();
+ }
+ else {
+ /* The object may have returned a reference to its
+ dict, so copy it to avoid mutating it. */
+ PyObject *temp = PyDict_Copy(masterdict);
+ Py_DECREF(masterdict);
+ masterdict = temp;
+ }
+ if (masterdict == NULL)
+ goto error;
+
+ /* Merge in attrs reachable from its class.
+ CAUTION: Not all objects have a __class__ attr. */
+ itsclass = PyObject_GetAttrString(arg, "__class__");
+ if (itsclass == NULL)
+ PyErr_Clear();
+ else {
+ int status = merge_class_dict(masterdict, itsclass);
+ Py_DECREF(itsclass);
+ if (status < 0)
+ goto error;
+ }
+ }
+
+ assert((result == NULL) ^ (masterdict == NULL));
+ if (masterdict != NULL) {
+ /* The result comes from its keys. */
+ assert(result == NULL);
+ result = PyDict_Keys(masterdict);
+ if (result == NULL)
+ goto error;
+ }
+
+ assert(result);
+ if (PyList_Sort(result) != 0)
+ goto error;
+ else
+ goto normal_return;
+
+ error:
+ Py_XDECREF(result);
+ result = NULL;
+ /* fall through */
+ normal_return:
+ Py_XDECREF(masterdict);
+ return result;
+ }
/*