summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2009-03-02 04:48:22 +0000
committerMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2009-03-02 04:48:22 +0000
commitcf3071242a289e20526ade81021b1f895fde706d (patch)
treeaaf91d5c55097ac9d98050f62e22222e7e7f5ff5
parentec710220dd347ed362a0a535d6a848e906d102e9 (diff)
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
-rw-r--r--django/conf/__init__.py35
-rw-r--r--django/utils/functional.py36
-rw-r--r--tests/regressiontests/comment_tests/tests/app_api_tests.py2
3 files changed, 44 insertions, 29 deletions
diff --git a/django/conf/__init__.py b/django/conf/__init__.py
index fc69bed7c6..81787d63d5 100644
--- a/django/conf/__init__.py
+++ b/django/conf/__init__.py
@@ -8,40 +8,19 @@ a list of all possible variables.
import os
import time # Needed for Windows
+
from django.conf import global_settings
+from django.utils.functional import LazyObject
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
-class LazySettings(object):
+class LazySettings(LazyObject):
"""
A lazy proxy for either global Django settings or a custom settings object.
The user can manually configure settings prior to using them. Otherwise,
Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
"""
- def __init__(self):
- # _target must be either None or something that supports attribute
- # access (getattr, hasattr, etc).
- self._target = None
-
- def __getattr__(self, name):
- if self._target is None:
- self._import_settings()
- if name == '__members__':
- # Used to implement dir(obj), for example.
- return self._target.get_all_members()
- return getattr(self._target, name)
-
- def __setattr__(self, name, value):
- if name == '_target':
- # Assign directly to self.__dict__, because otherwise we'd call
- # __setattr__(), which would be an infinite loop.
- self.__dict__['_target'] = value
- else:
- if self._target is None:
- self._import_settings()
- setattr(self._target, name, value)
-
- def _import_settings(self):
+ def _setup(self):
"""
Load the settings module pointed to by the environment variable. This
is used the first time we need any settings at all, if the user has not
@@ -56,7 +35,7 @@ class LazySettings(object):
# problems with Python's interactive help.
raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE)
- self._target = Settings(settings_module)
+ self._wrapped = Settings(settings_module)
def configure(self, default_settings=global_settings, **options):
"""
@@ -69,13 +48,13 @@ class LazySettings(object):
holder = UserSettingsHolder(default_settings)
for name, value in options.items():
setattr(holder, name, value)
- self._target = holder
+ self._wrapped = holder
def configured(self):
"""
Returns True if the settings have already been configured.
"""
- return bool(self._target)
+ return bool(self._wrapped)
configured = property(configured)
class Settings(object):
diff --git a/django/utils/functional.py b/django/utils/functional.py
index 9a12eda5a1..23614d1712 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -251,3 +251,39 @@ def allow_lazy(func, *resultclasses):
return func(*args, **kwargs)
return lazy(func, *resultclasses)(*args, **kwargs)
return wraps(func)(wrapper)
+
+class LazyObject(object):
+ """
+ A wrapper for another class that can be used to delay instantiation of the
+ wrapped class.
+
+ This is useful, for example, if the wrapped class needs to use Django
+ settings at creation time: we want to permit it to be imported without
+ accessing settings.
+ """
+ def __init__(self):
+ self._wrapped = None
+
+ 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):
+ if name == "_wrapped":
+ # Assign to __dict__ to avoid infinite __setattr__ loops.
+ self.__dict__["_wrapped"] = value
+ else:
+ if self._wrapped is None:
+ self._setup()
+ setattr(self._wrapped, name, value)
+
+ def _setup(self):
+ """
+ Must be implemented by subclasses to initialise the wrapped object.
+ """
+ raise NotImplementedError
+
diff --git a/tests/regressiontests/comment_tests/tests/app_api_tests.py b/tests/regressiontests/comment_tests/tests/app_api_tests.py
index 6a9eb1c637..c4d9ebfef3 100644
--- a/tests/regressiontests/comment_tests/tests/app_api_tests.py
+++ b/tests/regressiontests/comment_tests/tests/app_api_tests.py
@@ -41,7 +41,7 @@ class CustomCommentTest(CommentTestCase):
del settings.INSTALLED_APPS[-1]
settings.COMMENTS_APP = self.old_comments_app
if settings.COMMENTS_APP is None:
- delattr(settings._target, 'COMMENTS_APP')
+ delattr(settings._wrapped, 'COMMENTS_APP')
def testGetCommentApp(self):
from regressiontests.comment_tests import custom_comments