Skip to content

Commit

Permalink
make DOTENV setting more robust
Browse files Browse the repository at this point in the history
Add additional config options to DOTENV while retaining compatibility with the old way of setting it
  • Loading branch information
P1roks committed Jul 26, 2023
1 parent cad6dcb commit 6e04278
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 2 deletions.
22 changes: 20 additions & 2 deletions configurations/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def OTHER(self):
"""
DOTENV_LOADED = None
DOTENV_RELOAD = False

@classmethod
def load_dotenv(cls):
Expand All @@ -109,6 +110,18 @@ def load_dotenv(cls):
# check if the class has DOTENV set whether with a path or None
dotenv = getattr(cls, 'DOTENV', None)

required = True
overwrite_env = False
# check if the DOTENV is dict, and check all options of it
if isinstance(dotenv, dict):
# whether we want to overwrite previously set envs
overwrite_env = dotenv.get("overwrite", False)
# whether we want to error if the file is not found
required = dotenv.get("required", True)
# whether we want to reload on dotenv, useful if we want to frequently change it
cls.DOTENV_RELOAD = dotenv.get("reload", False)
dotenv = dotenv.get("path", None)

# if DOTENV is falsy we want to disable it
if not dotenv:
return
Expand All @@ -118,6 +131,8 @@ def load_dotenv(cls):
with open(dotenv, 'r') as f:
content = f.read()
except OSError as e:
if not required:
return
raise ImproperlyConfigured("Couldn't read .env file "
"with the path {}. Error: "
"{}".format(dotenv, e)) from e
Expand All @@ -133,13 +148,16 @@ def load_dotenv(cls):
m3 = re.match(r'\A"(.*)"\Z', val)
if m3:
val = re.sub(r'\\(.)', r'\1', m3.group(1))
os.environ.setdefault(key, val)
if overwrite_env:
os.environ[key] = val
else:
os.environ.setdefault(key, val)

cls.DOTENV_LOADED = dotenv

@classmethod
def pre_setup(cls):
if cls.DOTENV_LOADED is None:
if cls.DOTENV_LOADED is None or cls.DOTENV_RELOAD:
cls.load_dotenv()

@classmethod
Expand Down
14 changes: 14 additions & 0 deletions docs/cookbook.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ A ``.env`` file is a ``.ini``-style file. It must contain a list of
API_KEY1=1234
API_KEY2=5678
``DOTENV`` can also be a dictionary, and then its behavior can be configured more:
.. code-block:: python
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
class Dev(Configuration):
DOTENV = {
"path": str(os.path.join(BASE_DIR, '.env')),
# if True, overwrites previously set environmental variables, if False only sets them if they haven't been set before
"overwrite": True,
# if True errors if the DOTENV is not found at path, if False return
"required": False,
# if True, reloads DOTENV dynamically for example on hot reload
"reload": True,
Envdir
------
Expand Down

0 comments on commit 6e04278

Please sign in to comment.