PageRenderTime 139ms CodeModel.GetById 101ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 0ms

/django/conf/__init__.py

https://code.google.com/p/mango-py/
Python | 229 lines | 157 code | 28 blank | 44 comment | 23 complexity | 7069b3905488515a832b84ba3e42ab08 MD5 | raw file
  1"""
  2Settings and configuration for Django.
  3
  4Values will be read from the module specified by the DJANGO_SETTINGS_MODULE environment
  5variable, and then from django.conf.global_settings; see the global settings file for
  6a list of all possible variables.
  7"""
  8
  9import os, sys
 10import re
 11import time     # Needed for Windows
 12import warnings
 13
 14from django.conf import global_settings
 15from django.utils.functional import LazyObject
 16from django.utils import importlib
 17
 18ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
 19
 20
 21class LazySettings(LazyObject):
 22    """
 23    A lazy proxy for either global Django settings or a custom settings object.
 24    The user can manually configure settings prior to using them. Otherwise,
 25    Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
 26    """
 27    def _setup(self):
 28        """
 29        Load the settings module pointed to by the environment variable. This
 30        is used the first time we need any settings at all, if the user has not
 31        previously configured the settings manually.
 32        """
 33        try:
 34            settings_module = os.environ[ENVIRONMENT_VARIABLE]
 35            if not settings_module: # If it's set but is an empty string.
 36                raise KeyError
 37        except KeyError:
 38            # NOTE: This is arguably an EnvironmentError, but that causes
 39            # problems with Python's interactive help.
 40            raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE)
 41
 42        self._wrapped = Settings(settings_module)
 43
 44    def configure(self, default_settings=global_settings, **options):
 45        """
 46        Called to manually configure the settings. The 'default_settings'
 47        parameter sets where to retrieve any unspecified values from (its
 48        argument must support attribute access (__getattr__)).
 49        """
 50        if self._wrapped != None:
 51            raise RuntimeError('Settings already configured.')
 52        holder = UserSettingsHolder(default_settings)
 53        for name, value in options.items():
 54            setattr(holder, name, value)
 55        self._wrapped = holder
 56
 57    def configured(self):
 58        """
 59        Returns True if the settings have already been configured.
 60        """
 61        return bool(self._wrapped)
 62    configured = property(configured)
 63
 64def import_settings_module_with_extras(settings_module):
 65    parts = settings_module.split(".")
 66    parts[-1]+=".py"
 67
 68    found = []
 69    for path in ["."]+sys.path:
 70        search = os.path.join(path,*parts)
 71        if os.path.exists(search) and os.path.isfile(search):
 72            found.append(search)
 73
 74    if 'PROJECT_DIRECTORY' not in os.environ:
 75        os.environ['PROJECT_DIRECTORY']=os.path.dirname(os.path.abspath(found[0]))
 76    if 'SCRIPT_NAME' not in os.environ:                                                               # this will be missing if we are running on the internal server
 77        os.environ['SCRIPT_NAME']=''
 78
 79    try:
 80        mod = importlib.import_module(settings_module)
 81    except ImportError, e:
 82        raise ImportError("Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (ENVIRONMENT_VARIABLE, e))
 83
 84    return mod
 85
 86class BaseSettings(object):
 87    """
 88    Common logic for settings whether set by a module or by the user.
 89    """
 90    def __setattr__(self, name, value):
 91        if name in ("MEDIA_URL", "STATIC_URL") and value and not value.endswith('/'):
 92            warnings.warn('If set, %s must end with a slash' % name,
 93                          PendingDeprecationWarning)
 94        object.__setattr__(self, name, value)
 95
 96
 97class Settings(BaseSettings):
 98    def __init__(self, settings_module):
 99        # update this dict from global settings (but only for ALL_CAPS settings)
100        for setting in dir(global_settings):
101            if setting == setting.upper():
102                setattr(self, setting, getattr(global_settings, setting))
103
104        # store the settings module in case someone later cares
105        self.SETTINGS_MODULE = settings_module
106
107        try:
108            mod = importlib.import_module(self.SETTINGS_MODULE)
109        except ImportError, e:
110            raise ImportError("Could not import settings '%s' (Is it on sys.path?): %s" % (self.SETTINGS_MODULE, e))
111
112        # Settings that should be converted into tuples if they're mistakenly entered
113        # as strings.
114        tuple_settings = ("INSTALLED_APPS", "TEMPLATE_DIRS")
115
116        for setting in dir(mod):
117            if setting == setting.upper():
118                setting_value = getattr(mod, setting)
119                if setting in tuple_settings and type(setting_value) == str:
120                    setting_value = (setting_value,) # In case the user forgot the comma.
121                setattr(self, setting, setting_value)
122
123        # Expand entries in INSTALLED_APPS like "django.contrib.*" to a list
124        # of all those apps.
125        new_installed_apps = []
126        for app in self.INSTALLED_APPS:
127            if app.endswith('.*'):
128                app_mod = importlib.import_module(app[:-2])
129                appdir = os.path.dirname(app_mod.__file__)
130                app_subdirs = os.listdir(appdir)
131                app_subdirs.sort()
132                name_pattern = re.compile(r'[a-zA-Z]\w*')
133                for d in app_subdirs:
134                    if name_pattern.match(d) and os.path.isdir(os.path.join(appdir, d)):
135                        new_installed_apps.append('%s.%s' % (app[:-2], d))
136            else:
137                new_installed_apps.append(app)
138        self.INSTALLED_APPS = new_installed_apps
139
140        if hasattr(time, 'tzset') and self.TIME_ZONE:
141            # When we can, attempt to validate the timezone. If we can't find
142            # this file, no check happens and it's harmless.
143            zoneinfo_root = '/usr/share/zoneinfo'
144            if (os.path.exists(zoneinfo_root) and not
145                    os.path.exists(os.path.join(zoneinfo_root, *(self.TIME_ZONE.split('/'))))):
146                raise ValueError("Incorrect timezone setting: %s" % self.TIME_ZONE)
147            # Move the time zone info into os.environ. See ticket #2315 for why
148            # we don't do this unconditionally (breaks Windows).
149            os.environ['TZ'] = self.TIME_ZONE
150            time.tzset()
151
152        # Settings are configured, so we can set up the logger if required
153        if self.LOGGING_CONFIG:
154            # First find the logging configuration function ...
155            logging_config_path, logging_config_func_name = self.LOGGING_CONFIG.rsplit('.', 1)
156            logging_config_module = importlib.import_module(logging_config_path)
157            logging_config_func = getattr(logging_config_module, logging_config_func_name)
158
159            # Backwards-compatibility shim for #16288 fix
160            compat_patch_logging_config(self.LOGGING)
161
162            # ... then invoke it with the logging settings
163            logging_config_func(self.LOGGING)
164
165
166class UserSettingsHolder(BaseSettings):
167    """
168    Holder for user configured settings.
169    """
170    # SETTINGS_MODULE doesn't make much sense in the manually configured
171    # (standalone) case.
172    SETTINGS_MODULE = None
173
174    def __init__(self, default_settings):
175        """
176        Requests for configuration variables not in this class are satisfied
177        from the module specified in default_settings (if possible).
178        """
179        self.default_settings = default_settings
180
181    def __getattr__(self, name):
182        return getattr(self.default_settings, name)
183
184    def __dir__(self):
185        return self.__dict__.keys() + dir(self.default_settings)
186
187    # For Python < 2.6:
188    __members__ = property(lambda self: self.__dir__())
189
190settings = LazySettings()
191
192
193
194def compat_patch_logging_config(logging_config):
195    """
196    Backwards-compatibility shim for #16288 fix. Takes initial value of
197    ``LOGGING`` setting and patches it in-place (issuing deprecation warning)
198    if "mail_admins" logging handler is configured but has no filters.
199
200    """
201    #  Shim only if LOGGING["handlers"]["mail_admins"] exists,
202    #  but has no "filters" key
203    if "filters" not in logging_config.get(
204        "handlers", {}).get(
205        "mail_admins", {"filters": []}):
206
207        warnings.warn(
208            "You have no filters defined on the 'mail_admins' logging "
209            "handler: adding implicit debug-false-only filter. "
210            "See http://docs.djangoproject.com/en/dev/releases/1.4/"
211            "#request-exceptions-are-now-always-logged",
212            PendingDeprecationWarning)
213
214        filter_name = "require_debug_false"
215
216        filters = logging_config.setdefault("filters", {})
217        while filter_name in filters:
218            filter_name = filter_name + "_"
219
220        def _callback(record):
221            from django.conf import settings
222            return not settings.DEBUG
223
224        filters[filter_name] = {
225            "()": "django.utils.log.CallbackFilter",
226            "callback": _callback
227            }
228
229        logging_config["handlers"]["mail_admins"]["filters"] = [filter_name]