Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Factor out some common pieces of django.conf.LazySettings.

This is in preparation for some reuse elsewhere in the core code.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@9945 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit cf3071242a289e20526ade81021b1f895fde706d 1 parent ec71022
Malcolm Tredinnick authored March 02, 2009
35  django/conf/__init__.py
@@ -8,40 +8,19 @@
8 8
 
9 9
 import os
10 10
 import time     # Needed for Windows
  11
+
11 12
 from django.conf import global_settings
  13
+from django.utils.functional import LazyObject
12 14
 
13 15
 ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
14 16
 
15  
-class LazySettings(object):
  17
+class LazySettings(LazyObject):
16 18
     """
17 19
     A lazy proxy for either global Django settings or a custom settings object.
18 20
     The user can manually configure settings prior to using them. Otherwise,
19 21
     Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
20 22
     """
21  
-    def __init__(self):
22  
-        # _target must be either None or something that supports attribute
23  
-        # access (getattr, hasattr, etc).
24  
-        self._target = None
25  
-
26  
-    def __getattr__(self, name):
27  
-        if self._target is None:
28  
-            self._import_settings()
29  
-        if name == '__members__':
30  
-            # Used to implement dir(obj), for example.
31  
-            return self._target.get_all_members()
32  
-        return getattr(self._target, name)
33  
-
34  
-    def __setattr__(self, name, value):
35  
-        if name == '_target':
36  
-            # Assign directly to self.__dict__, because otherwise we'd call
37  
-            # __setattr__(), which would be an infinite loop.
38  
-            self.__dict__['_target'] = value
39  
-        else:
40  
-            if self._target is None:
41  
-                self._import_settings()
42  
-            setattr(self._target, name, value)
43  
-
44  
-    def _import_settings(self):
  23
+    def _setup(self):
45 24
         """
46 25
         Load the settings module pointed to by the environment variable. This
47 26
         is used the first time we need any settings at all, if the user has not
@@ -56,7 +35,7 @@ def _import_settings(self):
56 35
             # problems with Python's interactive help.
57 36
             raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE)
58 37
 
59  
-        self._target = Settings(settings_module)
  38
+        self._wrapped = Settings(settings_module)
60 39
 
61 40
     def configure(self, default_settings=global_settings, **options):
62 41
         """
@@ -69,13 +48,13 @@ def configure(self, default_settings=global_settings, **options):
69 48
         holder = UserSettingsHolder(default_settings)
70 49
         for name, value in options.items():
71 50
             setattr(holder, name, value)
72  
-        self._target = holder
  51
+        self._wrapped = holder
73 52
 
74 53
     def configured(self):
75 54
         """
76 55
         Returns True if the settings have already been configured.
77 56
         """
78  
-        return bool(self._target)
  57
+        return bool(self._wrapped)
79 58
     configured = property(configured)
80 59
 
81 60
 class Settings(object):
36  django/utils/functional.py
@@ -251,3 +251,39 @@ def wrapper(*args, **kwargs):
251 251
             return func(*args, **kwargs)
252 252
         return lazy(func, *resultclasses)(*args, **kwargs)
253 253
     return wraps(func)(wrapper)
  254
+
  255
+class LazyObject(object):
  256
+    """
  257
+    A wrapper for another class that can be used to delay instantiation of the
  258
+    wrapped class.
  259
+
  260
+    This is useful, for example, if the wrapped class needs to use Django
  261
+    settings at creation time: we want to permit it to be imported without
  262
+    accessing settings.
  263
+    """
  264
+    def __init__(self):
  265
+        self._wrapped = None
  266
+
  267
+    def __getattr__(self, name):
  268
+        if self._wrapped is None:
  269
+            self._setup()
  270
+        if name == "__members__":
  271
+            # Used to implement dir(obj)
  272
+            return self._wrapped.get_all_members()
  273
+        return getattr(self._wrapped, name)
  274
+
  275
+    def __setattr__(self, name, value):
  276
+        if name == "_wrapped":
  277
+            # Assign to __dict__ to avoid infinite __setattr__ loops.
  278
+            self.__dict__["_wrapped"] = value
  279
+        else:
  280
+            if self._wrapped is None:
  281
+                self._setup()
  282
+            setattr(self._wrapped, name, value)
  283
+
  284
+    def _setup(self):
  285
+        """
  286
+        Must be implemented by subclasses to initialise the wrapped object.
  287
+        """
  288
+        raise NotImplementedError
  289
+
2  tests/regressiontests/comment_tests/tests/app_api_tests.py
@@ -41,7 +41,7 @@ def tearDown(self):
41 41
         del settings.INSTALLED_APPS[-1]
42 42
         settings.COMMENTS_APP = self.old_comments_app
43 43
         if settings.COMMENTS_APP is None:
44  
-            delattr(settings._target, 'COMMENTS_APP')
  44
+            delattr(settings._wrapped, 'COMMENTS_APP')
45 45
 
46 46
     def testGetCommentApp(self):
47 47
         from regressiontests.comment_tests import custom_comments

0 notes on commit cf30712

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