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

1""" 

2Settings and configuration for Django. 

3 

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""" 

8 

9import importlib 

10import os 

11import time 

12import traceback 

13import warnings 

14from pathlib import Path 

15 

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 

21 

22ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" 

23 

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) 

30 

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) 

36 

37 

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 """ 

43 

44 def __new__(self, value, setting_name): 

45 return str.__new__(self, value) 

46 

47 def __init__(self, value, setting_name): 

48 self.setting_name = setting_name 

49 

50 

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 """ 

57 

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 ) 

73 

74 self._wrapped = Settings(settings_module) 

75 

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 } 

83 

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) 

89 

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.") 

96 

97 self.__dict__[name] = val 

98 return val 

99 

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) 

110 

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) 

115 

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 

130 

131 @staticmethod 

132 def _add_script_prefix(value): 

133 """ 

134 Add SCRIPT_NAME prefix to relative paths. 

135 

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 

143 

144 return "%s%s" % (get_script_prefix(), value) 

145 

146 @property 

147 def configured(self): 

148 """Return True if the settings have already been configured.""" 

149 return self._wrapped is not empty 

150 

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") 

164 

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") 

171 

172 

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)) 

179 

180 # store the settings module in case someone later cares 

181 self.SETTINGS_MODULE = settings_module 

182 

183 mod = importlib.import_module(self.SETTINGS_MODULE) 

184 

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) 

195 

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) 

204 

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 ) 

212 

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) 

215 

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() 

227 

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) 

230 

231 def is_overridden(self, setting): 

232 return setting in self._explicit_settings 

233 

234 def __repr__(self): 

235 return '<%(cls)s "%(settings_module)s">' % { 

236 "cls": self.__class__.__name__, 

237 "settings_module": self.SETTINGS_MODULE, 

238 } 

239 

240 

241class UserSettingsHolder: 

242 """Holder for user configured settings.""" 

243 

244 # SETTINGS_MODULE doesn't make much sense in the manually configured 

245 # (standalone) case. 

246 SETTINGS_MODULE = None 

247 

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 

255 

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) 

260 

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) 

268 

269 def __delattr__(self, name): 

270 self._deleted.add(name) 

271 if hasattr(self, name): 

272 super().__delattr__(name) 

273 

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 ) 

280 

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 

288 

289 def __repr__(self): 

290 return "<%(cls)s>" % { 

291 "cls": self.__class__.__name__, 

292 } 

293 

294 

295settings = LazySettings()