Statistics
| Branch: | Revision:

root / env / lib / python2.7 / site-packages / django / conf / __init__.py @ 1a305335

History | View | Annotate | Download (7.58 KB)

1
"""
2
Settings and configuration for Django.
3

4
Values will be read from the module specified by the DJANGO_SETTINGS_MODULE environment
5
variable, and then from django.conf.global_settings; see the global settings file for
6
a list of all possible variables.
7
"""
8

    
9
import os
10
import re
11
import time     # Needed for Windows
12
import warnings
13

    
14
from django.conf import global_settings
15
from django.utils.functional import LazyObject, empty
16
from django.utils import importlib
17

    
18
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
19

    
20

    
21
class 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 is not empty:
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
    @property
58
    def configured(self):
59
        """
60
        Returns True if the settings have already been configured.
61
        """
62
        return self._wrapped is not empty
63

    
64

    
65
class BaseSettings(object):
66
    """
67
    Common logic for settings whether set by a module or by the user.
68
    """
69
    def __setattr__(self, name, value):
70
        if name in ("MEDIA_URL", "STATIC_URL") and value and not value.endswith('/'):
71
            warnings.warn("If set, %s must end with a slash" % name,
72
                          DeprecationWarning)
73
        elif name == "ADMIN_MEDIA_PREFIX":
74
            warnings.warn("The ADMIN_MEDIA_PREFIX setting has been removed; "
75
                          "use STATIC_URL instead.", DeprecationWarning)
76
        elif name == "ALLOWED_INCLUDE_ROOTS" and isinstance(value, basestring):
77
            raise ValueError("The ALLOWED_INCLUDE_ROOTS setting must be set "
78
                "to a tuple, not a string.")
79
        object.__setattr__(self, name, value)
80

    
81

    
82
class Settings(BaseSettings):
83
    def __init__(self, settings_module):
84
        # update this dict from global settings (but only for ALL_CAPS settings)
85
        for setting in dir(global_settings):
86
            if setting == setting.upper():
87
                setattr(self, setting, getattr(global_settings, setting))
88

    
89
        # store the settings module in case someone later cares
90
        self.SETTINGS_MODULE = settings_module
91

    
92
        try:
93
            mod = importlib.import_module(self.SETTINGS_MODULE)
94
        except ImportError, e:
95
            raise ImportError("Could not import settings '%s' (Is it on sys.path?): %s" % (self.SETTINGS_MODULE, e))
96

    
97
        # Settings that should be converted into tuples if they're mistakenly entered
98
        # as strings.
99
        tuple_settings = ("INSTALLED_APPS", "TEMPLATE_DIRS")
100

    
101
        for setting in dir(mod):
102
            if setting == setting.upper():
103
                setting_value = getattr(mod, setting)
104
                if setting in tuple_settings and \
105
                        isinstance(setting_value, basestring):
106
                    setting_value = (setting_value,) # In case the user forgot the comma.
107
                setattr(self, setting, setting_value)
108

    
109
        if not self.SECRET_KEY:
110
            warnings.warn("The SECRET_KEY setting must not be empty.", DeprecationWarning)
111

    
112
        if hasattr(time, 'tzset') and self.TIME_ZONE:
113
            # When we can, attempt to validate the timezone. If we can't find
114
            # this file, no check happens and it's harmless.
115
            zoneinfo_root = '/usr/share/zoneinfo'
116
            if (os.path.exists(zoneinfo_root) and not
117
                    os.path.exists(os.path.join(zoneinfo_root, *(self.TIME_ZONE.split('/'))))):
118
                raise ValueError("Incorrect timezone setting: %s" % self.TIME_ZONE)
119
            # Move the time zone info into os.environ. See ticket #2315 for why
120
            # we don't do this unconditionally (breaks Windows).
121
            os.environ['TZ'] = self.TIME_ZONE
122
            time.tzset()
123

    
124
        # Settings are configured, so we can set up the logger if required
125
        if self.LOGGING_CONFIG:
126
            # First find the logging configuration function ...
127
            logging_config_path, logging_config_func_name = self.LOGGING_CONFIG.rsplit('.', 1)
128
            logging_config_module = importlib.import_module(logging_config_path)
129
            logging_config_func = getattr(logging_config_module, logging_config_func_name)
130

    
131
            # Backwards-compatibility shim for #16288 fix
132
            compat_patch_logging_config(self.LOGGING)
133

    
134
            # ... then invoke it with the logging settings
135
            logging_config_func(self.LOGGING)
136

    
137

    
138
class UserSettingsHolder(BaseSettings):
139
    """
140
    Holder for user configured settings.
141
    """
142
    # SETTINGS_MODULE doesn't make much sense in the manually configured
143
    # (standalone) case.
144
    SETTINGS_MODULE = None
145

    
146
    def __init__(self, default_settings):
147
        """
148
        Requests for configuration variables not in this class are satisfied
149
        from the module specified in default_settings (if possible).
150
        """
151
        self.default_settings = default_settings
152

    
153
    def __getattr__(self, name):
154
        return getattr(self.default_settings, name)
155

    
156
    def __dir__(self):
157
        return self.__dict__.keys() + dir(self.default_settings)
158

    
159
    # For Python < 2.6:
160
    __members__ = property(lambda self: self.__dir__())
161

    
162
settings = LazySettings()
163

    
164

    
165

    
166
def compat_patch_logging_config(logging_config):
167
    """
168
    Backwards-compatibility shim for #16288 fix. Takes initial value of
169
    ``LOGGING`` setting and patches it in-place (issuing deprecation warning)
170
    if "mail_admins" logging handler is configured but has no filters.
171

172
    """
173
    #  Shim only if LOGGING["handlers"]["mail_admins"] exists,
174
    #  but has no "filters" key
175
    if "filters" not in logging_config.get(
176
        "handlers", {}).get(
177
        "mail_admins", {"filters": []}):
178

    
179
        warnings.warn(
180
            "You have no filters defined on the 'mail_admins' logging "
181
            "handler: adding implicit debug-false-only filter. "
182
            "See http://docs.djangoproject.com/en/dev/releases/1.4/"
183
            "#request-exceptions-are-now-always-logged",
184
            PendingDeprecationWarning)
185

    
186
        filter_name = "require_debug_false"
187

    
188
        filters = logging_config.setdefault("filters", {})
189
        while filter_name in filters:
190
            filter_name = filter_name + "_"
191

    
192
        filters[filter_name] = {
193
            "()": "django.utils.log.RequireDebugFalse",
194
        }
195

    
196
        logging_config["handlers"]["mail_admins"]["filters"] = [filter_name]