bazarr/libs/dynaconf/contrib/django_dynaconf_v2.py

143 lines
4.5 KiB
Python

"""Dynaconf django extension
In the `django_project/settings.py` put at the very bottom of the file:
# HERE STARTS DYNACONF EXTENSION LOAD (Keep at the very bottom of settings.py)
# Read more at https://www.dynaconf.com/django/
import dynaconf # noqa
settings = dynaconf.DjangoDynaconf(__name__) # noqa
# HERE ENDS DYNACONF EXTENSION LOAD (No more code below this line)
Now in the root of your Django project
(the same folder where manage.py is located)
Put your config files `settings.{py|yaml|toml|ini|json}`
and or `.secrets.{py|yaml|toml|ini|json}`
On your projects root folder now you can start as::
DJANGO_DEBUG='false' \
DJANGO_ALLOWED_HOSTS='["localhost"]' \
python manage.py runserver
"""
from __future__ import annotations
import inspect
import os
import sys
import dynaconf
try: # pragma: no cover
from django import conf
from django.conf import settings as django_settings
django_installed = True
except ImportError: # pragma: no cover
django_installed = False
def load(django_settings_module_name=None, **kwargs): # pragma: no cover
if not django_installed:
raise RuntimeError(
"To use this extension django must be installed "
"install it with: pip install django"
)
try:
django_settings_module = sys.modules[django_settings_module_name]
except KeyError:
django_settings_module = sys.modules[
os.environ["DJANGO_SETTINGS_MODULE"]
]
settings_module_name = django_settings_module.__name__
settings_file = os.path.abspath(django_settings_module.__file__)
_root_path = os.path.dirname(settings_file)
# 1) Create the lazy settings object reusing settings_module consts
options = {
k.upper(): v
for k, v in django_settings_module.__dict__.items()
if k.isupper()
}
options.update(kwargs)
options.setdefault(
"SKIP_FILES_FOR_DYNACONF", [settings_file, "dynaconf_merge"]
)
options.setdefault("ROOT_PATH_FOR_DYNACONF", _root_path)
options.setdefault("ENVVAR_PREFIX_FOR_DYNACONF", "DJANGO")
options.setdefault("ENV_SWITCHER_FOR_DYNACONF", "DJANGO_ENV")
options.setdefault("ENVIRONMENTS_FOR_DYNACONF", True)
options.setdefault("load_dotenv", True)
options.setdefault(
"default_settings_paths", dynaconf.DEFAULT_SETTINGS_FILES
)
class UserSettingsHolder(dynaconf.LazySettings):
_django_override = True
lazy_settings = dynaconf.LazySettings(**options)
dynaconf.settings = lazy_settings # rebind the settings
# 2) Set all settings back to django_settings_module for 'django check'
lazy_settings.populate_obj(django_settings_module)
# 3) Bind `settings` and `DYNACONF`
setattr(django_settings_module, "settings", lazy_settings)
setattr(django_settings_module, "DYNACONF", lazy_settings)
# 4) keep django original settings
dj = {}
for key in dir(django_settings):
if (
key.isupper()
and (key != "SETTINGS_MODULE")
and key not in lazy_settings.store
):
dj[key] = getattr(django_settings, key, None)
dj["ORIGINAL_SETTINGS_MODULE"] = django_settings.SETTINGS_MODULE
lazy_settings.update(dj)
# Allow dynaconf_hooks to be in the same folder as the django.settings
dynaconf.loaders.execute_hooks(
"post",
lazy_settings,
lazy_settings.current_env,
modules=[settings_module_name],
files=[settings_file],
)
lazy_settings._loaded_py_modules.insert(0, settings_module_name)
# 5) Patch django.conf.settings
class Wrapper:
# lazy_settings = conf.settings.lazy_settings
def __getattribute__(self, name):
if name == "settings":
return lazy_settings
if name == "UserSettingsHolder":
return UserSettingsHolder
return getattr(conf, name)
# This implementation is recommended by Guido Van Rossum
# https://mail.python.org/pipermail/python-ideas/2012-May/014969.html
sys.modules["django.conf"] = Wrapper()
# 6) Enable standalone scripts to use Dynaconf
# This is for when `django.conf.settings` is imported directly
# on external `scripts` (out of Django's lifetime)
for stack_item in reversed(inspect.stack()):
if isinstance(
stack_item.frame.f_globals.get("settings"), conf.LazySettings
):
stack_item.frame.f_globals["settings"] = lazy_settings
return lazy_settings
# syntax sugar
DjangoDynaconf = load # noqa