Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed non-standard introspection support in LazyObject.

LazyObject called a public method ``get_all_members`` on wrapped objects in
order to allow introspection.  This could easily cause name clashes with
existing methods on wrapped objects, and so has been changed to use the
standard methods.  This could be slightly backwards-incompatible, in obscure
cases, if the undocumented LazyObject has been used externally.



git-svn-id: http://code.djangoproject.com/svn/django/trunk@11636 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit c6e8e5d9f068210d25f501b2aae4192d1c01185c 1 parent 22be3d7
Luke Plant authored October 19, 2009
8  django/conf/__init__.py
@@ -108,9 +108,6 @@ def __init__(self, settings_module):
108 108
             os.environ['TZ'] = self.TIME_ZONE
109 109
             time.tzset()
110 110
 
111  
-    def get_all_members(self):
112  
-        return dir(self)
113  
-
114 111
 class UserSettingsHolder(object):
115 112
     """
116 113
     Holder for user configured settings.
@@ -129,8 +126,11 @@ def __init__(self, default_settings):
129 126
     def __getattr__(self, name):
130 127
         return getattr(self.default_settings, name)
131 128
 
132  
-    def get_all_members(self):
  129
+    def __dir__(self):
133 130
         return dir(self) + dir(self.default_settings)
134 131
 
  132
+    # For Python < 2.6:
  133
+    __members__ = property(lambda self: self.__dir__())
  134
+
135 135
 settings = LazySettings()
136 136
 
4  django/core/files/storage.py
@@ -118,10 +118,6 @@ def url(self, name):
118 118
         """
119 119
         raise NotImplementedError()
120 120
 
121  
-    # Needed by django.utils.functional.LazyObject (via DefaultStorage).
122  
-    def get_all_members(self):
123  
-        return self.__members__
124  
-
125 121
 class FileSystemStorage(Storage):
126 122
     """
127 123
     Standard filesystem storage
10  django/utils/functional.py
@@ -266,9 +266,6 @@ def __init__(self):
266 266
     def __getattr__(self, name):
267 267
         if self._wrapped is None:
268 268
             self._setup()
269  
-        if name == "__members__":
270  
-            # Used to implement dir(obj)
271  
-            return self._wrapped.get_all_members()
272 269
         return getattr(self._wrapped, name)
273 270
 
274 271
     def __setattr__(self, name, value):
@@ -286,6 +283,13 @@ def _setup(self):
286 283
         """
287 284
         raise NotImplementedError
288 285
 
  286
+    # introspection support:
  287
+    __members__ = property(lambda self: self.__dir__())
  288
+
  289
+    def __dir__(self):
  290
+        if self._wrapped is None:
  291
+            self._setup()
  292
+        return  dir(self._wrapped)
289 293
 
290 294
 class SimpleLazyObject(LazyObject):
291 295
     """
28  docs/releases/1.2-alpha.txt
... ...
@@ -0,0 +1,28 @@
  1
+
  2
+Backwards-incompatible changes
  3
+==============================
  4
+
  5
+LazyObject
  6
+----------
  7
+
  8
+``LazyObject`` is an undocumented utility class used for lazily wrapping other
  9
+objects of unknown type.  In Django 1.1 and earlier, it handled introspection in
  10
+a non-standard way, depending on wrapped objects implementing a public method
  11
+``get_all_members()``. Since this could easily lead to name clashes, it has been
  12
+changed to use the standard method, involving ``__members__`` and ``__dir__()``.
  13
+If you used ``LazyObject`` in your own code, and implemented the
  14
+``get_all_members()`` method for wrapped objects, you need to make the following
  15
+changes:
  16
+
  17
+ * If your class does not have special requirements for introspection (i.e. you
  18
+   have not implemented ``__getattr__()`` or other methods that allow for
  19
+   attributes not discoverable by normal mechanisms), you can simply remove the
  20
+   ``get_all_members()`` method.  The default implementation on ``LazyObject``
  21
+   will do the right thing.
  22
+
  23
+ * If you have more complex requirements for introspection, first rename the
  24
+   ``get_all_members()`` method to ``__dir__()``.  This is the standard method,
  25
+   from Python 2.6 onwards, for supporting introspection.  If you are require
  26
+   support for Python < 2.6, add the following code to the class::
  27
+
  28
+       __members__ = property(lambda self: self.__dir__())

0 notes on commit c6e8e5d

Please sign in to comment.
Something went wrong with that request. Please try again.