From 7fc887a4920f0c56feee0550e35870e4dc1ae45f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Mon, 22 Apr 2024 16:36:39 +0200 Subject: [PATCH] feat: ENV_FILE configuration variable can customize the .env file --- CHANGES.rst | 4 ++++ canaille/app/configuration.py | 9 ++++++-- tests/app/test_configuration.py | 41 +++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 84b1dc82..722bb4ba 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,7 @@ +Added +^^^^^ +- `ENV_FILE` environment variable can customize/disable the .env file + Changed ^^^^^^^ - Locked users cannot be impersonated anymore. diff --git a/canaille/app/configuration.py b/canaille/app/configuration.py index 2111e598..16553fb5 100644 --- a/canaille/app/configuration.py +++ b/canaille/app/configuration.py @@ -13,6 +13,7 @@ from pydantic_settings import SettingsConfigDict from canaille.core.configuration import CoreSettings ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +DEFAULT_ENV_FILE = ".env" class RootSettings(BaseSettings): @@ -30,7 +31,6 @@ class RootSettings(BaseSettings): extra="allow", env_nested_delimiter="__", case_sensitive=True, - env_file=".env", ) SECRET_KEY: str @@ -93,7 +93,12 @@ def settings_factory(config): **attributes, ) - return Settings(**config, _secrets_dir=os.environ.get("SECRETS_DIR")) + env_file = os.getenv("ENV_FILE", config.get("ENV_FILE", DEFAULT_ENV_FILE)) + return Settings( + **config, + _secrets_dir=os.environ.get("SECRETS_DIR"), + _env_file=env_file, + ) class ConfigurationException(Exception): diff --git a/tests/app/test_configuration.py b/tests/app/test_configuration.py index d2af2e97..0b66ba6f 100644 --- a/tests/app/test_configuration.py +++ b/tests/app/test_configuration.py @@ -60,6 +60,47 @@ def test_configuration_from_environment_vars(): del os.environ["CANAILLE_SQL__DATABASE_URI"] +def test_dotenv_file(tmp_path, configuration): + """Canaille should read configuration from .env files.""" + oldcwd = os.getcwd() + os.chdir(tmp_path) + dotenv = tmp_path / ".env" + + with open(dotenv, "w") as fd: + fd.write("FOOBAR=custom-value") + + app = create_app(configuration) + assert app.config["FOOBAR"] == "custom-value" + os.chdir(oldcwd) + + +def test_custom_dotenv_file(tmp_path, configuration): + """Canaille should read configuration from custom .env files if they are + passed with ENV_FILE.""" + dotenv = tmp_path / "custom.env" + with open(dotenv, "w") as fd: + fd.write("FOOBAR=other-custom-value") + + configuration["ENV_FILE"] = dotenv + app = create_app(configuration) + assert app.config["FOOBAR"] == "other-custom-value" + + +def test_disable_dotenv_file(tmp_path, configuration): + """Canaille should ignore .env files if ENV_FILE is None.""" + oldcwd = os.getcwd() + os.chdir(tmp_path) + dotenv = tmp_path / ".env" + + with open(dotenv, "w") as fd: + fd.write("FOOBAR=custom-value") + + configuration["ENV_FILE"] = None + app = create_app(configuration) + assert "FOOBAR" not in app.config + os.chdir(oldcwd) + + def test_smtp_connection_remote_smtp_unreachable(testclient, backend, configuration): configuration["CANAILLE"]["SMTP"]["HOST"] = "smtp://invalid-smtp.com" config_obj = settings_factory(configuration)