Ticket #14297: settings_optimization.diff

File settings_optimization.diff, 6.3 KB (added by akaariai, 5 years ago)
  • django/conf/__init__.py

    diff --git a/django/conf/__init__.py b/django/conf/__init__.py
    index bda0ef3..f6ae4e0 100644
    a b from django.utils import importlib 
    1616
    1717ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
    1818
    19 class LazySettings(LazyObject):
    20     """
    21     A lazy proxy for either global Django settings or a custom settings object.
    22     The user can manually configure settings prior to using them. Otherwise,
    23     Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
    24     """
     19
     20class LazySettings(object):
     21    def __init__(self):
     22        self._is_configured = False
     23        # Uqly hack to make the test pass. Should patch
     24        # the tests instead. (Backwards compatibility
     25        # should not be a problem here).
     26        self._wrapped = self
     27        self._has_real_wrapped = False
     28   
     29    def __getattr__(self, name):
     30        if not self._is_configured:
     31            self._setup()
     32            self._is_configured = True
     33            if name in self.__dict__:
     34                return self.__dict__[name]
     35            else:
     36                raise AttributeError
     37        else:
     38            if self._has_real_wrapped:
     39                return getattr(self._wrapped, name)
     40            raise AttributeError
     41     
     42    def __delattr__(self, name):
     43         if name == "_wrapped":
     44             raise TypeError("can't delete _wrapped.")
     45         # Need more checks here for _is_configured etc?
     46         if not self._is_configured:
     47             self._setup()
     48         del self.__dict__[name]
     49   
    2550    def _setup(self):
    26         """
    27         Load the settings module pointed to by the environment variable. This
    28         is used the first time we need any settings at all, if the user has not
    29         previously configured the settings manually.
    30         """
     51        # NOTE: we are working inside __getattr__ here, so be careful to not
     52        # refer to any missing value in self.
     53
     54        # We want to store the actual settings only if the whole _real_init
     55        # is succesfull. This way either the settings will be all set up
     56        # or none at all, just like with LazySettings. So we store all the
     57        # settings in new_dict and copy it to self.__dict__ when
     58        # we are done.
     59       
     60        new_dict = {}
    3161        try:
    3262            settings_module = os.environ[ENVIRONMENT_VARIABLE]
    3363            if not settings_module: # If it's set but is an empty string.
    class LazySettings(LazyObject): 
    3767            # problems with Python's interactive help.
    3868            raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE)
    3969
    40         self._wrapped = Settings(settings_module)
     70        # update this dict from global settings (but only for ALL_CAPS settings)
     71        for setting in dir(global_settings):
     72            if setting == setting.upper():
     73                new_dict[setting] = getattr(global_settings, setting)
     74
     75        # store the settings module in case someone later cares
     76        new_dict["SETTINGS_MODULE"] = settings_module
     77
     78        try:
     79            mod = importlib.import_module(settings_module)
     80        except ImportError, e:
     81            raise ImportError("Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (settings_module, e))
     82
     83        # Settings that should be converted into tuples if they're mistakenly entered
     84        # as strings.
     85        tuple_settings = ("INSTALLED_APPS", "TEMPLATE_DIRS")
     86
     87        for setting in dir(mod):
     88            if setting == setting.upper():
     89                setting_value = getattr(mod, setting)
     90                if setting in tuple_settings and type(setting_value) == str:
     91                    setting_value = (setting_value,) # In case the user forgot the comma.
     92                new_dict[setting] = setting_value
     93
     94        # Expand entries in INSTALLED_APPS like "django.contrib.*" to a list
     95        # of all those apps.
     96        new_installed_apps = []
     97        for app in new_dict['INSTALLED_APPS']:
     98            if app.endswith('.*'):
     99                app_mod = importlib.import_module(app[:-2])
     100                appdir = os.path.dirname(app_mod.__file__)
     101                app_subdirs = os.listdir(appdir)
     102                app_subdirs.sort()
     103                name_pattern = re.compile(r'[a-zA-Z]\w*')
     104                for d in app_subdirs:
     105                    if name_pattern.match(d) and os.path.isdir(os.path.join(appdir, d)):
     106                        new_installed_apps.append('%s.%s' % (app[:-2], d))
     107            else:
     108                new_installed_apps.append(app)
     109        new_dict["INSTALLED_APPS"] = new_installed_apps
     110
     111        if hasattr(time, 'tzset') and new_dict.get('TIME_ZONE'):
     112            # When we can, attempt to validate the timezone. If we can't find
     113            # this file, no check happens and it's harmless.
     114            zoneinfo_root = '/usr/share/zoneinfo'
     115            if (os.path.exists(zoneinfo_root) and not
     116                    os.path.exists(os.path.join(zoneinfo_root, *(new_dict['TIME_ZONE'].split('/'))))):
     117                raise ValueError("Incorrect timezone setting: %s" % new_dict['TIME_ZONE'])
     118            # Move the time zone info into os.environ. See ticket #2315 for why
     119            # we don't do this unconditionally (breaks Windows).
     120            os.environ['TZ'] = new_dict['TIME_ZONE']
     121            time.tzset()
     122        # Everything passed. Now it is safe to make the settings visible.
     123        self.__dict__.update(new_dict)
    41124
    42125    def configure(self, default_settings=global_settings, **options):
    43126        """
    class LazySettings(LazyObject): 
    45128        parameter sets where to retrieve any unspecified values from (its
    46129        argument must support attribute access (__getattr__)).
    47130        """
    48         if self._wrapped != None:
     131        if self._is_configured:
    49132            raise RuntimeError('Settings already configured.')
    50133        holder = UserSettingsHolder(default_settings)
    51134        for name, value in options.items():
    52135            setattr(holder, name, value)
    53136        self._wrapped = holder
     137        self._has_real_wrapped = True
    54138
    55139    def configured(self):
    56140        """
    57141        Returns True if the settings have already been configured.
    58142        """
    59         return bool(self._wrapped)
     143        return self._is_configured
    60144    configured = property(configured)
    61145
    62146class Settings(object):
Back to Top