Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Removed some import-time dependencies on Django's settings.

Now you can import the file storage stuff and still call settings.configure()
afterwards. There is still one import-time usage of settings in
django.contrib.comments, but that's unavoidable.

Backport of r9945 and r9946 from trunk (this is needed in order to fix #8193 in
a clean fashion, which is why it's being backported).

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@9947 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 32be118081fab4ec62412d2dcb97b7d835b8d109 1 parent 9576353
@malcolmt malcolmt authored
View
35 django/conf/__init__.py
@@ -8,40 +8,19 @@
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 @@ def _import_settings(self):
# 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 @@ def configure(self, default_settings=global_settings, **options):
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):
View
30 django/core/files/storage.py
@@ -4,11 +4,12 @@
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
+from django.core.files import locks, File
+from django.core.files.move import file_move_safe
from django.utils.encoding import force_unicode
+from django.utils.functional import LazyObject
from django.utils.text import get_valid_filename
from django.utils._os import safe_join
-from django.core.files import locks, File
-from django.core.files.move import file_move_safe
__all__ = ('Storage', 'FileSystemStorage', 'DefaultStorage', 'default_storage')
@@ -40,7 +41,7 @@ def save(self, name, content):
# Get the proper name for the file, as it will actually be saved.
if name is None:
name = content.name
-
+
name = self.get_available_name(name)
name = self._save(name, content)
@@ -116,12 +117,20 @@ def url(self, name):
"""
raise NotImplementedError()
+ # Needed by django.utils.functional.LazyObject (via DefaultStorage).
+ def get_all_members(self):
+ return self.__members__
+
class FileSystemStorage(Storage):
"""
Standard filesystem storage
"""
- def __init__(self, location=settings.MEDIA_ROOT, base_url=settings.MEDIA_URL):
+ def __init__(self, location=None, base_url=None):
+ if location is None:
+ location = settings.MEDIA_ROOT
+ if base_url is None:
+ base_url = settings.MEDIA_URL
self.location = os.path.abspath(location)
self.base_url = base_url
@@ -172,10 +181,10 @@ def _save(self, name, content):
else:
# OK, the file save worked. Break out of the loop.
break
-
+
if settings.FILE_UPLOAD_PERMISSIONS is not None:
os.chmod(full_path, settings.FILE_UPLOAD_PERMISSIONS)
-
+
return name
def delete(self, name):
@@ -212,7 +221,9 @@ def url(self, name):
raise ValueError("This file is not accessible via a URL.")
return urlparse.urljoin(self.base_url, name).replace('\\', '/')
-def get_storage_class(import_path):
+def get_storage_class(import_path=None):
+ if import_path is None:
+ import_path = settings.DEFAULT_FILE_STORAGE
try:
dot = import_path.rindex('.')
except ValueError:
@@ -227,5 +238,8 @@ def get_storage_class(import_path):
except AttributeError:
raise ImproperlyConfigured('Storage module "%s" does not define a "%s" class.' % (module, classname))
-DefaultStorage = get_storage_class(settings.DEFAULT_FILE_STORAGE)
+class DefaultStorage(LazyObject):
+ def _setup(self):
+ self._wrapped = get_storage_class()()
+
default_storage = DefaultStorage()
View
36 django/utils/functional.py
@@ -251,3 +251,39 @@ def wrapper(*args, **kwargs):
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
+
Please sign in to comment.
Something went wrong with that request. Please try again.