use override feature of dotenv instead of deferring loading of default files

In the previous commit, #5628 was fixed by creating the context
before loading the default environment variables. However, as
pointed out by @davidism, this can cause issues with the load
pipeline. Thus, this commit reverses that approach and uses the
`override` argument provided by `python-dotenv` to give priority
to custom file over default file.

Signed-off-by: Jalaj <96870071+jalaj711@users.noreply.github.com>
This commit is contained in:
Jalaj 2024-11-07 23:33:45 +05:30
parent f60d6c9042
commit d4b54f9c3e
No known key found for this signature in database
GPG key ID: FDC1954BB2CAC91C

View file

@ -495,7 +495,7 @@ def _env_file_callback(
# Don't check FLASK_SKIP_DOTENV, that only disables automatically # Don't check FLASK_SKIP_DOTENV, that only disables automatically
# loading .env and .flaskenv files. # loading .env and .flaskenv files.
load_dotenv(value) load_dotenv(value, override=True)
return value return value
@ -528,10 +528,6 @@ class FlaskGroup(AppGroup):
directory to the directory containing the first file found. directory to the directory containing the first file found.
:param set_debug_flag: Set the app's debug flag. :param set_debug_flag: Set the app's debug flag.
.. versionchanged:: 3.1.0
Environment file specified through -e/--env-file gets
prioity over default .env, .flaskenv files
.. versionchanged:: 2.2 .. versionchanged:: 2.2
Added the ``-A/--app``, ``--debug/--no-debug``, ``-e/--env-file`` options. Added the ``-A/--app``, ``--debug/--no-debug``, ``-e/--env-file`` options.
@ -658,23 +654,17 @@ class FlaskGroup(AppGroup):
# when importing, blocking whatever command is being called. # when importing, blocking whatever command is being called.
os.environ["FLASK_RUN_FROM_CLI"] = "true" os.environ["FLASK_RUN_FROM_CLI"] = "true"
if "obj" not in extra and "obj" not in self.context_settings:
extra["obj"] = ScriptInfo(
create_app=self.create_app, set_debug_flag=self.set_debug_flag
)
# The make_context function goes ahead to parse the arguments
# which also includes the -e option. Since that option gets
# priority over default config files (See #5532), we need to
# call this before attempting to load the default config.
ctx = super().make_context(info_name, args, parent=parent, **extra)
# Attempt to load .env and .flask env files. The --env-file # Attempt to load .env and .flask env files. The --env-file
# option can cause another file to be loaded. # option can cause another file to be loaded.
if get_load_dotenv(self.load_dotenv): if get_load_dotenv(self.load_dotenv):
load_dotenv() load_dotenv()
return ctx if "obj" not in extra and "obj" not in self.context_settings:
extra["obj"] = ScriptInfo(
create_app=self.create_app, set_debug_flag=self.set_debug_flag
)
return super().make_context(info_name, args, parent=parent, **extra)
def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]: def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]:
if not args and self.no_args_is_help: if not args and self.no_args_is_help:
@ -694,7 +684,9 @@ def _path_is_ancestor(path: str, other: str) -> bool:
return os.path.join(path, other[len(path) :].lstrip(os.sep)) == other return os.path.join(path, other[len(path) :].lstrip(os.sep)) == other
def load_dotenv(path: str | os.PathLike[str] | None = None) -> bool: def load_dotenv(
path: str | os.PathLike[str] | None = None, override: bool = False
) -> bool:
"""Load "dotenv" files in order of precedence to set environment variables. """Load "dotenv" files in order of precedence to set environment variables.
If an env var is already set it is not overwritten, so earlier files in the If an env var is already set it is not overwritten, so earlier files in the
@ -707,6 +699,10 @@ def load_dotenv(path: str | os.PathLike[str] | None = None) -> bool:
:param path: Load the file at this location instead of searching. :param path: Load the file at this location instead of searching.
:return: ``True`` if a file was loaded. :return: ``True`` if a file was loaded.
.. versionchanged:: 3.1.0
Added optional parameter 'override' to override existing
variables
.. versionchanged:: 2.0 .. versionchanged:: 2.0
The current directory is not changed to the location of the The current directory is not changed to the location of the
loaded file. loaded file.
@ -737,7 +733,7 @@ def load_dotenv(path: str | os.PathLike[str] | None = None) -> bool:
# the default files. # the default files.
if path is not None: if path is not None:
if os.path.isfile(path): if os.path.isfile(path):
return dotenv.load_dotenv(path, encoding="utf-8") return dotenv.load_dotenv(path, encoding="utf-8", override=override)
return False return False
@ -749,7 +745,7 @@ def load_dotenv(path: str | os.PathLike[str] | None = None) -> bool:
if not path: if not path:
continue continue
dotenv.load_dotenv(path, encoding="utf-8") dotenv.load_dotenv(path, encoding="utf-8", override=override)
loaded = True loaded = True
return loaded # True if at least one file was located and loaded. return loaded # True if at least one file was located and loaded.