From 782256837879ece72a89c9343813b5b78898e099 Mon Sep 17 00:00:00 2001 From: Alex Oleshkevich Date: Mon, 23 Jan 2023 00:24:35 +0300 Subject: [PATCH] Add Config.env_prefix option (#1990) * add Config.env_prefix option * fix variable name in docs * simplify test case * rollback markdown formatting * Update docs/config.md Co-authored-by: Marcelo Trylesinski Co-authored-by: Marcelo Trylesinski --- docs/config.md | 17 +++++++++++++++++ starlette/config.py | 3 +++ tests/test_config.py | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/docs/config.md b/docs/config.md index a879374dc..853dff3d4 100644 --- a/docs/config.md +++ b/docs/config.md @@ -113,6 +113,23 @@ from starlette.config import environ environ['TESTING'] = 'TRUE' ``` +## Reading prefixed environment variables + +You can namespace the environment variables by setting `env_prefix` argument. + +```python title="myproject/settings.py" +import os +from starlette.config import Config + +os.environ['APP_DEBUG'] = 'yes' +os.environ['ENVIRONMENT'] = 'dev' + +config = Config(env_prefix='APP_') + +DEBUG = config('DEBUG') # lookups APP_DEBUG, returns "yes" +ENVIRONMENT = config('ENVIRONMENT') # lookups APP_ENVIRONMENT, raises KeyError as variable is not defined +``` + ## A full example Structuring large applications can be complex. You need proper separation of diff --git a/starlette/config.py b/starlette/config.py index 8c58b2738..795232cf6 100644 --- a/starlette/config.py +++ b/starlette/config.py @@ -54,8 +54,10 @@ def __init__( self, env_file: typing.Optional[typing.Union[str, Path]] = None, environ: typing.Mapping[str, str] = environ, + env_prefix: str = "", ) -> None: self.environ = environ + self.env_prefix = env_prefix self.file_values: typing.Dict[str, str] = {} if env_file is not None and os.path.isfile(env_file): self.file_values = self._read_file(env_file) @@ -103,6 +105,7 @@ def get( cast: typing.Optional[typing.Callable] = None, default: typing.Any = undefined, ) -> typing.Any: + key = self.env_prefix + key if key in self.environ: value = self.environ[key] return self._perform_cast(key, value, cast) diff --git a/tests/test_config.py b/tests/test_config.py index d33000389..70b0a4812 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -127,3 +127,13 @@ def test_environ(): environ = Environ() assert list(iter(environ)) == list(iter(os.environ)) assert len(environ) == len(os.environ) + + +def test_config_with_env_prefix(tmpdir, monkeypatch): + config = Config( + environ={"APP_DEBUG": "value", "ENVIRONMENT": "dev"}, env_prefix="APP_" + ) + assert config.get("DEBUG") == "value" + + with pytest.raises(KeyError): + config.get("ENVIRONMENT")