1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
from os import environ
from dynaconf.utils import upperfy
from dynaconf.utils.parse_conf import parse_conf_data
from dynaconf.vendor.dotenv import cli as dotenv_cli
IDENTIFIER = "env"
def load(obj, env=None, silent=True, key=None):
"""Loads envvars with prefixes:
`DYNACONF_` (default global) or `$(ENVVAR_PREFIX_FOR_DYNACONF)_`
"""
global_prefix = obj.get("ENVVAR_PREFIX_FOR_DYNACONF")
if global_prefix is False or global_prefix.upper() != "DYNACONF":
load_from_env(obj, "DYNACONF", key, silent, IDENTIFIER + "_global")
# Load the global env if exists and overwrite everything
load_from_env(obj, global_prefix, key, silent, IDENTIFIER + "_global")
def load_from_env(
obj,
prefix=False,
key=None,
silent=False,
identifier=IDENTIFIER,
env=False, # backwards compatibility bc renamed param
):
if prefix is False and env is not False:
prefix = env
env_ = ""
if prefix is not False:
if not isinstance(prefix, str):
raise TypeError("`prefix/env` must be str or False")
prefix = prefix.upper()
env_ = f"{prefix}_"
# Load a single environment variable explicitly.
if key:
key = upperfy(key)
value = environ.get(f"{env_}{key}")
if value:
try: # obj is a Settings
obj.set(key, value, loader_identifier=identifier, tomlfy=True)
except AttributeError: # obj is a dict
obj[key] = parse_conf_data(
value, tomlfy=True, box_settings=obj
)
# Load environment variables in bulk (when matching).
else:
# Only known variables should be loaded from environment.
ignore_unknown = obj.get("IGNORE_UNKNOWN_ENVVARS_FOR_DYNACONF")
known_keys = set(obj.store)
trim_len = len(env_)
data = {
key[trim_len:]: parse_conf_data(
data, tomlfy=True, box_settings=obj
)
for key, data in environ.items()
if key.startswith(env_)
and not (
# Ignore environment variables that haven't been
# pre-defined in settings space.
ignore_unknown
and key[trim_len:] not in known_keys
)
}
# Update the settings space based on gathered data from environment.
if data:
obj.update(data, loader_identifier=identifier)
def write(settings_path, settings_data, **kwargs):
"""Write data to .env file"""
for key, value in settings_data.items():
quote_mode = (
isinstance(value, str)
and (value.startswith("'") or value.startswith('"'))
) or isinstance(value, (list, dict))
dotenv_cli.set_key(
str(settings_path),
key,
str(value),
quote_mode="always" if quote_mode else "none",
)
|