Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/conf/__init__.py: 60%
139 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1"""
2Settings and configuration for Django.
4Read values from the module specified by the DJANGO_SETTINGS_MODULE environment
5variable, and then from django.conf.global_settings; see the global_settings.py
6for a list of all possible variables.
7"""
9import importlib
10import os
11import time
12import traceback
13import warnings
14from pathlib import Path
16import django
17from django.conf import global_settings
18from django.core.exceptions import ImproperlyConfigured
19from django.utils.deprecation import RemovedInDjango50Warning
20from django.utils.functional import LazyObject, empty
22ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
24# RemovedInDjango50Warning
25USE_DEPRECATED_PYTZ_DEPRECATED_MSG = (
26 "The USE_DEPRECATED_PYTZ setting, and support for pytz timezones is "
27 "deprecated in favor of the stdlib zoneinfo module. Please update your "
28 "code to use zoneinfo and remove the USE_DEPRECATED_PYTZ setting."
29)
31USE_L10N_DEPRECATED_MSG = (
32 "The USE_L10N setting is deprecated. Starting with Django 5.0, localized "
33 "formatting of data will always be enabled. For example Django will "
34 "display numbers and dates using the format of the current locale."
35)
38class SettingsReference(str):
39 """
40 String subclass which references a current settings value. It's treated as
41 the value in memory but serializes to a settings.NAME attribute reference.
42 """
44 def __new__(self, value, setting_name):
45 return str.__new__(self, value)
47 def __init__(self, value, setting_name):
48 self.setting_name = setting_name
51class LazySettings(LazyObject):
52 """
53 A lazy proxy for either global Django settings or a custom settings object.
54 The user can manually configure settings prior to using them. Otherwise,
55 Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
56 """
58 def _setup(self, name=None):
59 """
60 Load the settings module pointed to by the environment variable. This
61 is used the first time settings are needed, if the user hasn't
62 configured settings manually.
63 """
64 settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
65 if not settings_module: 65 ↛ 66line 65 didn't jump to line 66, because the condition on line 65 was never true
66 desc = ("setting %s" % name) if name else "settings"
67 raise ImproperlyConfigured(
68 "Requested %s, but settings are not configured. "
69 "You must either define the environment variable %s "
70 "or call settings.configure() before accessing settings."
71 % (desc, ENVIRONMENT_VARIABLE)
72 )
74 self._wrapped = Settings(settings_module)
76 def __repr__(self):
77 # Hardcode the class name as otherwise it yields 'Settings'.
78 if self._wrapped is empty:
79 return "<LazySettings [Unevaluated]>"
80 return '<LazySettings "%(settings_module)s">' % {
81 "settings_module": self._wrapped.SETTINGS_MODULE,
82 }
84 def __getattr__(self, name):
85 """Return the value of a setting and cache it in self.__dict__."""
86 if self._wrapped is empty:
87 self._setup(name)
88 val = getattr(self._wrapped, name)
90 # Special case some settings which require further modification.
91 # This is done here for performance reasons so the modified value is cached.
92 if name in {"MEDIA_URL", "STATIC_URL"} and val is not None:
93 val = self._add_script_prefix(val)
94 elif name == "SECRET_KEY" and not val: 94 ↛ 95line 94 didn't jump to line 95, because the condition on line 94 was never true
95 raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")
97 self.__dict__[name] = val
98 return val
100 def __setattr__(self, name, value):
101 """
102 Set the value of setting. Clear all cached values if _wrapped changes
103 (@override_settings does this) or clear single values when set.
104 """
105 if name == "_wrapped":
106 self.__dict__.clear()
107 else:
108 self.__dict__.pop(name, None)
109 super().__setattr__(name, value)
111 def __delattr__(self, name):
112 """Delete a setting and clear it from cache if needed."""
113 super().__delattr__(name)
114 self.__dict__.pop(name, None)
116 def configure(self, default_settings=global_settings, **options):
117 """
118 Called to manually configure the settings. The 'default_settings'
119 parameter sets where to retrieve any unspecified values from (its
120 argument must support attribute access (__getattr__)).
121 """
122 if self._wrapped is not empty:
123 raise RuntimeError("Settings already configured.")
124 holder = UserSettingsHolder(default_settings)
125 for name, value in options.items():
126 if not name.isupper():
127 raise TypeError("Setting %r must be uppercase." % name)
128 setattr(holder, name, value)
129 self._wrapped = holder
131 @staticmethod
132 def _add_script_prefix(value):
133 """
134 Add SCRIPT_NAME prefix to relative paths.
136 Useful when the app is being served at a subpath and manually prefixing
137 subpath to STATIC_URL and MEDIA_URL in settings is inconvenient.
138 """
139 # Don't apply prefix to absolute paths and URLs.
140 if value.startswith(("http://", "https://", "/")): 140 ↛ 142line 140 didn't jump to line 142, because the condition on line 140 was never false
141 return value
142 from django.urls import get_script_prefix
144 return "%s%s" % (get_script_prefix(), value)
146 @property
147 def configured(self):
148 """Return True if the settings have already been configured."""
149 return self._wrapped is not empty
151 @property
152 def USE_L10N(self):
153 stack = traceback.extract_stack()
154 # Show a warning if the setting is used outside of Django.
155 # Stack index: -1 this line, -2 the caller.
156 filename, _, _, _ = stack[-2]
157 if not filename.startswith(os.path.dirname(django.__file__)):
158 warnings.warn(
159 USE_L10N_DEPRECATED_MSG,
160 RemovedInDjango50Warning,
161 stacklevel=2,
162 )
163 return self.__getattr__("USE_L10N")
165 # RemovedInDjango50Warning.
166 @property
167 def _USE_L10N_INTERNAL(self):
168 # Special hook to avoid checking a traceback in internal use on hot
169 # paths.
170 return self.__getattr__("USE_L10N")
173class Settings:
174 def __init__(self, settings_module):
175 # update this dict from global settings (but only for ALL_CAPS settings)
176 for setting in dir(global_settings):
177 if setting.isupper():
178 setattr(self, setting, getattr(global_settings, setting))
180 # store the settings module in case someone later cares
181 self.SETTINGS_MODULE = settings_module
183 mod = importlib.import_module(self.SETTINGS_MODULE)
185 tuple_settings = (
186 "ALLOWED_HOSTS",
187 "INSTALLED_APPS",
188 "TEMPLATE_DIRS",
189 "LOCALE_PATHS",
190 )
191 self._explicit_settings = set()
192 for setting in dir(mod):
193 if setting.isupper():
194 setting_value = getattr(mod, setting)
196 if setting in tuple_settings and not isinstance( 196 ↛ 199line 196 didn't jump to line 199, because the condition on line 196 was never true
197 setting_value, (list, tuple)
198 ):
199 raise ImproperlyConfigured(
200 "The %s setting must be a list or a tuple." % setting
201 )
202 setattr(self, setting, setting_value)
203 self._explicit_settings.add(setting)
205 if self.USE_TZ is False and not self.is_overridden("USE_TZ"): 205 ↛ 206line 205 didn't jump to line 206, because the condition on line 205 was never true
206 warnings.warn(
207 "The default value of USE_TZ will change from False to True "
208 "in Django 5.0. Set USE_TZ to False in your project settings "
209 "if you want to keep the current default behavior.",
210 category=RemovedInDjango50Warning,
211 )
213 if self.is_overridden("USE_DEPRECATED_PYTZ"): 213 ↛ 214line 213 didn't jump to line 214, because the condition on line 213 was never true
214 warnings.warn(USE_DEPRECATED_PYTZ_DEPRECATED_MSG, RemovedInDjango50Warning)
216 if hasattr(time, "tzset") and self.TIME_ZONE: 216 ↛ 228line 216 didn't jump to line 228, because the condition on line 216 was never false
217 # When we can, attempt to validate the timezone. If we can't find
218 # this file, no check happens and it's harmless.
219 zoneinfo_root = Path("/usr/share/zoneinfo")
220 zone_info_file = zoneinfo_root.joinpath(*self.TIME_ZONE.split("/"))
221 if zoneinfo_root.exists() and not zone_info_file.exists(): 221 ↛ 222line 221 didn't jump to line 222, because the condition on line 221 was never true
222 raise ValueError("Incorrect timezone setting: %s" % self.TIME_ZONE)
223 # Move the time zone info into os.environ. See ticket #2315 for why
224 # we don't do this unconditionally (breaks Windows).
225 os.environ["TZ"] = self.TIME_ZONE
226 time.tzset()
228 if self.is_overridden("USE_L10N"): 228 ↛ exitline 228 didn't return from function '__init__', because the condition on line 228 was never false
229 warnings.warn(USE_L10N_DEPRECATED_MSG, RemovedInDjango50Warning)
231 def is_overridden(self, setting):
232 return setting in self._explicit_settings
234 def __repr__(self):
235 return '<%(cls)s "%(settings_module)s">' % {
236 "cls": self.__class__.__name__,
237 "settings_module": self.SETTINGS_MODULE,
238 }
241class UserSettingsHolder:
242 """Holder for user configured settings."""
244 # SETTINGS_MODULE doesn't make much sense in the manually configured
245 # (standalone) case.
246 SETTINGS_MODULE = None
248 def __init__(self, default_settings):
249 """
250 Requests for configuration variables not in this class are satisfied
251 from the module specified in default_settings (if possible).
252 """
253 self.__dict__["_deleted"] = set()
254 self.default_settings = default_settings
256 def __getattr__(self, name):
257 if not name.isupper() or name in self._deleted:
258 raise AttributeError
259 return getattr(self.default_settings, name)
261 def __setattr__(self, name, value):
262 self._deleted.discard(name)
263 if name == "USE_L10N":
264 warnings.warn(USE_L10N_DEPRECATED_MSG, RemovedInDjango50Warning)
265 super().__setattr__(name, value)
266 if name == "USE_DEPRECATED_PYTZ":
267 warnings.warn(USE_DEPRECATED_PYTZ_DEPRECATED_MSG, RemovedInDjango50Warning)
269 def __delattr__(self, name):
270 self._deleted.add(name)
271 if hasattr(self, name):
272 super().__delattr__(name)
274 def __dir__(self):
275 return sorted(
276 s
277 for s in [*self.__dict__, *dir(self.default_settings)]
278 if s not in self._deleted
279 )
281 def is_overridden(self, setting):
282 deleted = setting in self._deleted
283 set_locally = setting in self.__dict__
284 set_on_default = getattr(
285 self.default_settings, "is_overridden", lambda s: False
286 )(setting)
287 return deleted or set_locally or set_on_default
289 def __repr__(self):
290 return "<%(cls)s>" % {
291 "cls": self.__class__.__name__,
292 }
295settings = LazySettings()