Author: Martin Matusiak <[email protected]>
Branch: py3.3
Changeset: r72641:2bdf0e894a85
Date: 2014-07-29 19:44 +0200
http://bitbucket.org/pypy/pypy/changeset/2bdf0e894a85/
Log: factor dir() built-in out into object, type and module methods
This happened in bugs.python.org/issue12166
diff --git a/pypy/interpreter/module.py b/pypy/interpreter/module.py
--- a/pypy/interpreter/module.py
+++ b/pypy/interpreter/module.py
@@ -123,3 +123,15 @@
except OperationError:
__file__ = u'?'
return space.wrap(u"<module %s from %s>" % (name, __file__))
+
+ def descr_module__dir__(self, space):
+ try:
+ w__dict__ = space.getattr(self, space.wrap('__dict__'))
+ result = space.listview(w__dict__)
+ w_result = space.wrap(result)
+ w_result.sort(False)
+ return w_result
+ except OperationError as e:
+ if e.match(space, space.w_AttributeError):
+ return space.wrap([])
+ raise
diff --git a/pypy/interpreter/test/test_module.py
b/pypy/interpreter/test/test_module.py
--- a/pypy/interpreter/test/test_module.py
+++ b/pypy/interpreter/test/test_module.py
@@ -68,6 +68,12 @@
m = type(_pypy_interact).__new__(type(_pypy_interact))
assert repr(m).startswith("<module '?'")
+ def test_dir(self):
+ import sys
+ items = sys.__dir__()
+ assert items == sorted(items)
+ assert items == dir(sys)
+
def test_package(self):
import sys
import os
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -779,6 +779,7 @@
__new__ = interp2app(Module.descr_module__new__.im_func),
__init__ = interp2app(Module.descr_module__init__),
__repr__ = interp2app(Module.descr_module__repr__),
+ __dir__ = interp2app(Module.descr_module__dir__),
__reduce__ = interp2app(Module.descr__reduce__),
__dict__ = GetSetProperty(descr_get_dict, cls=Module), # module
dictionaries are readonly attributes
__doc__ = 'module(name[, doc])\n\nCreate a module object.\nThe name must
be a string; the optional doc argument can have any type.'
diff --git a/pypy/module/__builtin__/app_inspect.py
b/pypy/module/__builtin__/app_inspect.py
--- a/pypy/module/__builtin__/app_inspect.py
+++ b/pypy/module/__builtin__/app_inspect.py
@@ -45,8 +45,6 @@
local_names.sort()
return local_names
- import types
-
obj = args[0]
dir_meth = lookup_special(obj, "__dir__")
@@ -56,58 +54,5 @@
result = list(result) # Will throw TypeError if not iterable
result.sort()
return result
- elif isinstance(obj, types.ModuleType):
- try:
- result = list(obj.__dict__)
- result.sort()
- return result
- except AttributeError:
- return []
- elif isinstance(obj, type):
- #Don't look at __class__, as metaclass methods would be confusing.
- result = list(_classdir(obj).keys())
- result.sort()
- return result
-
- else: #(regular item)
- Dict = {}
- try:
- if isinstance(obj.__dict__, dict):
- Dict.update(obj.__dict__)
- except AttributeError:
- pass
- try:
- Dict.update(_classdir(obj.__class__))
- except AttributeError:
- pass
- result = list(Dict.keys())
- result.sort()
- return result
-
-def _classdir(klass):
- """Return a dict of the accessible attributes of class/type klass.
-
- This includes all attributes of klass and all of the
- base classes recursively.
-
- The values of this dict have no meaning - only the keys have
- meaning.
- """
- Dict = {}
- try:
- Dict.update(klass.__dict__)
- except AttributeError: pass
- try:
- # XXX - Use of .__mro__ would be suggested, if the existance
- # of that attribute could be guarranted.
- bases = klass.__bases__
- except AttributeError: pass
- else:
- try:
- #Note that since we are only interested in the keys,
- # the order we merge classes is unimportant
- for base in bases:
- Dict.update(_classdir(base))
- except TypeError: pass
- return Dict
+ return [] # we should never reach here since object.__dir__ exists
diff --git a/pypy/objspace/std/objecttype.py b/pypy/objspace/std/objecttype.py
--- a/pypy/objspace/std/objecttype.py
+++ b/pypy/objspace/std/objecttype.py
@@ -19,6 +19,43 @@
classname = u'%s.%s' % (modulename, classname)
return w_obj.getrepr(space, u'%s object' % (classname,))
+def descr__dir__(space, w_obj):
+ w_result = space.appexec([w_obj], """(obj):
+ def _classdir(klass):
+ Dict = {}
+ try:
+ Dict.update(klass.__dict__)
+ except AttributeError: pass
+ try:
+ # XXX - Use of .__mro__ would be suggested, if the existance
+ # of that attribute could be guarranted.
+ bases = klass.__bases__
+ except AttributeError: pass
+ else:
+ try:
+ #Note that since we are only interested in the keys,
+ # the order we merge classes is unimportant
+ for base in bases:
+ Dict.update(_classdir(base))
+ except TypeError: pass
+ return Dict
+
+ Dict = {}
+ try:
+ if isinstance(obj.__dict__, dict):
+ Dict.update(obj.__dict__)
+ except AttributeError:
+ pass
+ try:
+ Dict.update(_classdir(obj.__class__))
+ except AttributeError:
+ pass
+ result = list(Dict.keys())
+ result.sort()
+ return result
+ """)
+ return w_result
+
def descr__str__(space, w_obj):
w_type = space.type(w_obj)
w_impl = w_type.lookup("__repr__")
@@ -219,6 +256,7 @@
__delattr__ = gateway.interp2app(Object.descr__delattr__.im_func),
__str__ = gateway.interp2app(descr__str__),
__repr__ = gateway.interp2app(descr__repr__),
+ __dir__ = gateway.interp2app(descr__dir__),
__class__ = GetSetProperty(descr__class__, descr_set___class__),
__doc__ = '''The most base type''',
__new__ = gateway.interp2app(descr__new__),
diff --git a/pypy/objspace/std/test/test_obj.py
b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -105,6 +105,16 @@
return 123456
assert A().__str__() == 123456
+ def test_object_dir(self):
+ class A(object):
+ a_var = None
+
+ assert hasattr(object, '__dir__')
+ obj = A()
+ obj_items = dir(obj)
+ assert obj_items == sorted(obj_items)
+ assert obj_items == dir(obj)
+
def test_is_on_primitives(self):
if self.cpython_apptest:
diff --git a/pypy/objspace/std/test/test_typeobject.py
b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -716,6 +716,26 @@
pass
raises(TypeError, "class D(A, C): pass")
+ def test_dir(self):
+ class A(object):
+ a_var = None
+ def a_meth(self):
+ pass
+
+ class C(A):
+ c_var = None
+ def c_meth(self):
+ pass
+
+ C_items = dir(C)
+ assert C_items == sorted(C_items)
+ assert C_items != C.__dir__(C) # as in cpython
+
+ assert 'a_var' in C_items
+ assert 'c_var' in C_items
+ assert 'a_meth' in C_items
+ assert 'c_meth' in C_items
+
def test_data_descriptor_without_get(self):
"""
class Descr(object):
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -730,6 +730,33 @@
else:
return space.get(w_result, space.w_None, w_type)
+def descr__dir(space, w_type):
+ w_result = space.appexec([w_type], """(obj):
+ def _classdir(klass):
+ Dict = {}
+ try:
+ Dict.update(klass.__dict__)
+ except AttributeError: pass
+ try:
+ # XXX - Use of .__mro__ would be suggested, if the existance
+ # of that attribute could be guarranted.
+ bases = klass.__bases__
+ except AttributeError: pass
+ else:
+ try:
+ #Note that since we are only interested in the keys,
+ # the order we merge classes is unimportant
+ for base in bases:
+ Dict.update(_classdir(base))
+ except TypeError: pass
+ return Dict
+
+ result = list(_classdir(obj).keys())
+ result.sort()
+ return result
+ """)
+ return w_result
+
def descr__flags(space, w_type):
from copy_reg import _HEAPTYPE
_CPYTYPE = 1 # used for non-heap types defined in C
@@ -803,6 +830,7 @@
__mro__ = GetSetProperty(descr_get__mro__),
__dict__ = GetSetProperty(descr_get_dict),
__doc__ = GetSetProperty(descr__doc),
+ __dir__ = gateway.interp2app(descr__dir),
mro = gateway.interp2app(descr_mro),
__flags__ = GetSetProperty(descr__flags),
__module__ = GetSetProperty(descr_get__module, descr_set__module),
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit