allow __dir__ to return any sequence
This commit is contained in:
parent
703f7c4bf5
commit
3bbb722654
|
@ -1343,7 +1343,8 @@ access (use of, assignment to, or deletion of ``x.name``) for class instances.
|
|||
|
||||
.. method:: object.__dir__(self)
|
||||
|
||||
Called when :func:`dir` is called on the object. A list must be returned.
|
||||
Called when :func:`dir` is called on the object. A sequence must be
|
||||
returned. :func:`dir` converts the returned sequence to a list and sorts it.
|
||||
|
||||
|
||||
.. _descriptors:
|
||||
|
|
|
@ -372,7 +372,15 @@ class BuiltinTest(unittest.TestCase):
|
|||
f = Foo()
|
||||
self.assertTrue(dir(f) == ["ga", "kan", "roo"])
|
||||
|
||||
# dir(obj__dir__not_list)
|
||||
# dir(obj__dir__tuple)
|
||||
class Foo(object):
|
||||
def __dir__(self):
|
||||
return ("b", "c", "a")
|
||||
res = dir(Foo())
|
||||
self.assertIsInstance(res, list)
|
||||
self.assertTrue(res == ["a", "b", "c"])
|
||||
|
||||
# dir(obj__dir__not_sequence)
|
||||
class Foo(object):
|
||||
def __dir__(self):
|
||||
return 7
|
||||
|
|
|
@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1?
|
|||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- Loosen type restrictions on the __dir__ method. __dir__ can now return any
|
||||
sequence, which will be converted to a list and sorted by dir().
|
||||
|
||||
- Issue #12265: Make error messages produced by passing an invalid set of
|
||||
arguments to a function more informative.
|
||||
|
||||
|
|
|
@ -1205,6 +1205,10 @@ _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;
|
||||
}
|
||||
|
@ -1213,7 +1217,7 @@ _dir_locals(void)
|
|||
static PyObject *
|
||||
_dir_object(PyObject *obj)
|
||||
{
|
||||
PyObject *result;
|
||||
PyObject *result, *sorted;
|
||||
static PyObject *dir_str = NULL;
|
||||
PyObject *dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str);
|
||||
|
||||
|
@ -1228,18 +1232,16 @@ _dir_object(PyObject *obj)
|
|||
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;
|
||||
/* 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
|
||||
|
@ -1249,24 +1251,7 @@ _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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue