Author: mtredinnick Date: 2009-03-01 22:57:03 -0600 (Sun, 01 Mar 2009) New Revision: 9947
Modified: django/branches/releases/1.0.X/django/conf/__init__.py django/branches/releases/1.0.X/django/core/files/storage.py django/branches/releases/1.0.X/django/utils/functional.py Log: 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). Modified: django/branches/releases/1.0.X/django/conf/__init__.py =================================================================== --- django/branches/releases/1.0.X/django/conf/__init__.py 2009-03-02 04:48:47 UTC (rev 9946) +++ django/branches/releases/1.0.X/django/conf/__init__.py 2009-03-02 04:57:03 UTC (rev 9947) @@ -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 @@ # 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 @@ 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): Modified: django/branches/releases/1.0.X/django/core/files/storage.py =================================================================== --- django/branches/releases/1.0.X/django/core/files/storage.py 2009-03-02 04:48:47 UTC (rev 9946) +++ django/branches/releases/1.0.X/django/core/files/storage.py 2009-03-02 04:57:03 UTC (rev 9947) @@ -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 @@ # 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 @@ """ 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 @@ 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 @@ 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 @@ 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() Modified: django/branches/releases/1.0.X/django/utils/functional.py =================================================================== --- django/branches/releases/1.0.X/django/utils/functional.py 2009-03-02 04:48:47 UTC (rev 9946) +++ django/branches/releases/1.0.X/django/utils/functional.py 2009-03-02 04:57:03 UTC (rev 9947) @@ -251,3 +251,39 @@ 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 + --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-updates@googlegroups.com To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-updates?hl=en -~----------~----~----~----~------~----~------~--~---