diff --git a/django/conf/__init__.py b/django/conf/__init__.py index 7bc7ae95083..7fbfd265346 100644 --- a/django/conf/__init__.py +++ b/django/conf/__init__.py @@ -108,9 +108,6 @@ class Settings(object): os.environ['TZ'] = self.TIME_ZONE time.tzset() - def get_all_members(self): - return dir(self) - class UserSettingsHolder(object): """ Holder for user configured settings. @@ -129,8 +126,11 @@ class UserSettingsHolder(object): def __getattr__(self, name): return getattr(self.default_settings, name) - def get_all_members(self): + def __dir__(self): return dir(self) + dir(self.default_settings) + # For Python < 2.6: + __members__ = property(lambda self: self.__dir__()) + settings = LazySettings() diff --git a/django/core/files/storage.py b/django/core/files/storage.py index e183c17dd32..96c0b54623e 100644 --- a/django/core/files/storage.py +++ b/django/core/files/storage.py @@ -118,10 +118,6 @@ class Storage(object): """ raise NotImplementedError() - # Needed by django.utils.functional.LazyObject (via DefaultStorage). - def get_all_members(self): - return self.__members__ - class FileSystemStorage(Storage): """ Standard filesystem storage diff --git a/django/utils/functional.py b/django/utils/functional.py index 52969cd43ac..e12ef3b8138 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -266,9 +266,6 @@ class LazyObject(object): def __getattr__(self, name): if self._wrapped is None: self._setup() - if name == "__members__": - # Used to implement dir(obj) - return self._wrapped.get_all_members() return getattr(self._wrapped, name) def __setattr__(self, name, value): @@ -286,6 +283,13 @@ class LazyObject(object): """ raise NotImplementedError + # introspection support: + __members__ = property(lambda self: self.__dir__()) + + def __dir__(self): + if self._wrapped is None: + self._setup() + return dir(self._wrapped) class SimpleLazyObject(LazyObject): """ diff --git a/docs/releases/1.2-alpha.txt b/docs/releases/1.2-alpha.txt new file mode 100644 index 00000000000..0df21034861 --- /dev/null +++ b/docs/releases/1.2-alpha.txt @@ -0,0 +1,28 @@ + +Backwards-incompatible changes +============================== + +LazyObject +---------- + +``LazyObject`` is an undocumented utility class used for lazily wrapping other +objects of unknown type. In Django 1.1 and earlier, it handled introspection in +a non-standard way, depending on wrapped objects implementing a public method +``get_all_members()``. Since this could easily lead to name clashes, it has been +changed to use the standard method, involving ``__members__`` and ``__dir__()``. +If you used ``LazyObject`` in your own code, and implemented the +``get_all_members()`` method for wrapped objects, you need to make the following +changes: + + * If your class does not have special requirements for introspection (i.e. you + have not implemented ``__getattr__()`` or other methods that allow for + attributes not discoverable by normal mechanisms), you can simply remove the + ``get_all_members()`` method. The default implementation on ``LazyObject`` + will do the right thing. + + * If you have more complex requirements for introspection, first rename the + ``get_all_members()`` method to ``__dir__()``. This is the standard method, + from Python 2.6 onwards, for supporting introspection. If you are require + support for Python < 2.6, add the following code to the class:: + + __members__ = property(lambda self: self.__dir__())