diff options
Diffstat (limited to 'Python/bltinmodule.c')
-rw-r--r-- | Python/bltinmodule.c | 70 |
1 files changed, 48 insertions, 22 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index fd8dc80..2461904 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -384,39 +384,65 @@ builtin_dir(self, args) PyObject *self; PyObject *args; { - PyObject *v = NULL; - PyObject *d; + static char *attrlist[] = {"__members__", "__methods__", NULL}; + PyObject *v = NULL, *l = NULL, *m = NULL; + PyObject *d, *x; + int i; + char **s; if (!PyArg_ParseTuple(args, "|O:dir", &v)) return NULL; if (v == NULL) { - d = PyEval_GetLocals(); - Py_INCREF(d); + x = PyEval_GetLocals(); + if (x == NULL) + goto error; + l = PyMapping_Keys(x); + if (l == NULL) + goto error; } else { d = PyObject_GetAttrString(v, "__dict__"); - if (d == NULL) { - PyErr_SetString(PyExc_TypeError, - "dir() argument must have __dict__ attribute"); - return NULL; + if (d == NULL) + PyErr_Clear(); + else { + l = PyMapping_Keys(d); + if (l == NULL) + PyErr_Clear(); + Py_DECREF(d); } - } - if (PyDict_Check(d)) { - v = PyDict_Keys(d); - if (PyList_Sort(v) != 0) { - Py_DECREF(v); - v = NULL; + if (l == NULL) { + l = PyList_New(0); + if (l == NULL) + goto error; } - } - else { - v = PyObject_CallMethod(d, "keys", NULL); - if (v == NULL) { - PyErr_Clear(); - v = PyList_New(0); + for (s = attrlist; *s != NULL; s++) { + m = PyObject_GetAttrString(v, *s); + if (m == NULL) { + PyErr_Clear(); + continue; + } + for (i = 0; ; i++) { + x = PySequence_GetItem(m, i); + if (x == NULL) { + PyErr_Clear(); + break; + } + if (PyList_Append(l, x) != 0) { + Py_DECREF(x); + Py_DECREF(m); + goto error; + } + Py_DECREF(x); + } + Py_DECREF(m); } } - Py_DECREF(d); - return v; + if (PyList_Sort(l) != 0) + goto error; + return l; + error: + Py_XDECREF(l); + return NULL; } static PyObject * |