[Python-checkins] cpython: allow __dir__ to return any sequence

benjamin.peterson python-checkins at python.org
Sat Jun 11 23:11:33 CEST 2011


http://hg.python.org/cpython/rev/f74fceebf853
changeset: 70801:f74fceebf853
user: Benjamin Peterson <benjamin at python.org>
date: Sat Jun 11 16:12:08 2011 -0500
summary:
 allow __dir__ to return any sequence
files:
 Doc/reference/datamodel.rst | 3 +-
 Lib/test/test_builtin.py | 10 +++++-
 Misc/NEWS | 3 +
 Objects/object.c | 45 ++++++++----------------
 4 files changed, 29 insertions(+), 32 deletions(-)
diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst
--- a/Doc/reference/datamodel.rst
+++ b/Doc/reference/datamodel.rst
@@ -1343,7 +1343,8 @@
 
 .. 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:
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -372,7 +372,15 @@
 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
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 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.
 
diff --git a/Objects/object.c b/Objects/object.c
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1205,6 +1205,10 @@
 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 @@
 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 @@
 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 @@
 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);
 }
 
 /*
-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /