diff --git a/CHANGES.rst b/CHANGES.rst index 118751e9..4ed3c42c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -17,6 +17,8 @@ Unreleased about resource limits to the security page. :issue:`5625` - Add support for the ``Partitioned`` cookie attribute (CHIPS), with the ``SESSION_COOKIE_PARTITIONED`` config. :issue`5472` +- Give priority to file specified through the -e/--env-file option + over default .env & .flaskenv files in CLI. Version 3.0.3 diff --git a/src/flask/cli.py b/src/flask/cli.py index 8e72db5a..1c8cfb21 100644 --- a/src/flask/cli.py +++ b/src/flask/cli.py @@ -528,6 +528,10 @@ class FlaskGroup(AppGroup): directory to the directory containing the first file found. :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 Added the ``-A/--app``, ``--debug/--no-debug``, ``-e/--env-file`` options. @@ -654,17 +658,23 @@ class FlaskGroup(AppGroup): # when importing, blocking whatever command is being called. os.environ["FLASK_RUN_FROM_CLI"] = "true" - # Attempt to load .env and .flask env files. The --env-file - # option can cause another file to be loaded. - if get_load_dotenv(self.load_dotenv): - load_dotenv() - 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) + # 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 + # option can cause another file to be loaded. + if get_load_dotenv(self.load_dotenv): + load_dotenv() + + return ctx def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]: if not args and self.no_args_is_help: diff --git a/tests/test_apps/.customenv b/tests/test_apps/.customenv new file mode 100644 index 00000000..58d7a729 --- /dev/null +++ b/tests/test_apps/.customenv @@ -0,0 +1,4 @@ +FOO=customenv +BAZ=1 +BAR=custombar +EGGS=custom diff --git a/tests/test_cli.py b/tests/test_cli.py index 09995488..2b662233 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -565,6 +565,21 @@ def test_disable_dotenv_from_env(monkeypatch, runner): assert "FOO" not in os.environ +@need_dotenv +def test_custom_dotenv_takes_priority(monkeypatch, runner): + monkeypatch.chdir(test_path) + runner.invoke(FlaskGroup(), "-e .customenv") + + # .customenv is loaded + assert "BAZ" in os.environ + + # .customenv takes priority over .flaskenv + assert os.environ["BAR"] == "custombar" + + # .customenv takes priority over .env + assert os.environ["FOO"] == "customenv" + + def test_run_cert_path(): # no key with pytest.raises(click.BadParameter):