def test_require(): """Validate config and raise proper exception if required variables are missing.""" config = Konfig() with pytest.raises( MissingError, match=r"Options \['MISSING', 'YET_ANOTHER_MISSING'\] are required" ): config.require("MISSING", "YET_ANOTHER_MISSING")
def test_no_reinitialization(mocked_import_config_module): """When config instance is accessed second time, the underlying module is not re-imported.""" config = Konfig() for _ in (1, 2): assert config.EXAMPLE == "test" # Py2.7, Py3.5: replace with `assert_called_once` when 2.7/3.5 support will be dropped. assert mocked_import_config_module.called is True assert mocked_import_config_module.call_count == 1
def test_dotenv_override(testdir, monkeypatch, override, expected_value): # If something is already present in env we can decide should it be overridden from .env or not settings = testdir.tmpdir.ensure_dir("settings") settings.ensure(".env").write("FROM_DOTENV=loaded") monkeypatch.setenv("FROM_DOTENV", "loaded_from_env") config = Konfig(dotenv=os.path.join(str(settings), ".env"), dotenv_override=override) assert config.FROM_DOTENV == expected_value
def config(request, vault_prefix): marker = request.node.get_closest_marker("async_vault") if marker: from konfetti.vault import AsyncVaultBackend as vault_backend else: vault_backend = VaultBackend yield Konfig(vault_backend=vault_backend(vault_prefix)) sys.modules.pop("settings.production", None)
def test_asdict(monkeypatch, vault_prefix, vault_addr, vault_token): monkeypatch.setenv("KONFETTI_SETTINGS", "test_app.settings.subset") config = Konfig(vault_backend=VaultBackend(vault_prefix)) assert config.asdict() == { "DEBUG": True, "SECRET": "value", "KEY": "value", "VAULT_ADDR": vault_addr, "VAULT_TOKEN": vault_token, "NESTED_SECRET": "what?", "WHOLE_SECRET": { "DECIMAL": "1.3", "IS_SECRET": True, "SECRET": "value" }, "DICTIONARY": { "static": 1, "env": True, "vault": "value" }, }
def test_dotenv_reloading(testdir, mocker): """The dotenv file shouldn't be reloaded after first time.""" settings = testdir.tmpdir.ensure_dir("settings") settings.ensure(".env").write("FROM_DOTENV=loaded") config = Konfig(dotenv=os.path.join(str(settings), ".env"), dotenv_override=True) load_env = mocker.patch("konfetti.core.load_dotenv", wraps=load_dotenv) assert config.FROM_DOTENV == "loaded" assert load_env.called load_env.reset_mock() assert config.FROM_DOTENV == "loaded" assert not load_env.called
def test_from_object(vault_prefix, vault_addr, vault_token): class Test: VALUE = 42 VAULT_ADDR = env("VAULT_ADDR") VAULT_TOKEN = env("VAULT_TOKEN") SECRET = vault("path/to")["SECRET"] config = Konfig.from_object(Test, vault_backend=VaultBackend(vault_prefix)) assert config.asdict() == { "VALUE": 42, "SECRET": "value", "VAULT_ADDR": vault_addr, "VAULT_TOKEN": vault_token }
def test_vault_override_variables(monkeypatch, vault_prefix): monkeypatch.setenv("KONFETTI_SETTINGS", "test_app.settings.subset") config = Konfig(vault_backend=VaultBackend(vault_prefix)) assert config.vault.get_override_examples() == { "NESTED_SECRET": { "PATH__TO__NESTED": '{"NESTED_SECRET": {"nested": "example_value"}}' }, "SECRET": { "PATH__TO": '{"SECRET": "example_value"}' }, "WHOLE_SECRET": { "PATH__TO": "{}" }, }
def test_from_string(vault_prefix, vault_addr, vault_token): config = Konfig.from_object("test_app.settings.subset", vault_backend=VaultBackend(vault_prefix)) assert config.asdict() == { "DEBUG": True, "SECRET": "value", "KEY": "value", "VAULT_ADDR": vault_addr, "VAULT_TOKEN": vault_token, "NESTED_SECRET": "what?", "WHOLE_SECRET": { "DECIMAL": "1.3", "IS_SECRET": True, "SECRET": "value" }, "DICTIONARY": { "static": 1, "env": True, "vault": "value" }, }
def test_custom_config_variable_name(monkeypatch): # Config variable name is customizable config = Konfig(config_variable_name="APP_CONFIG") monkeypatch.setenv("APP_CONFIG", "test_app.settings.production") assert config.KEY == "value"
def test_vault_override_variables_cache(monkeypatch, vault_prefix): monkeypatch.setenv("KONFETTI_SETTINGS", "test_app.settings.subset") config = Konfig(vault_backend=VaultBackend(vault_prefix)) assert config.vault is config.vault assert config.vault.get_override_examples( ) is config.vault.get_override_examples()
def test_from_json(vault_prefix): path = os.path.join(HERE, "test_app/settings/config.json") config = Konfig.from_json(path, vault_backend=VaultBackend(vault_prefix)) assert config.asdict() == {"VALUE": "from json", "SECRET": 42}
def test_require_nothing(): """Given keys should contain at least one element.""" config = Konfig() with pytest.raises(RuntimeError, match="You need to specify at least one key"): config.require()
def test_dictionary_access(monkeypatch, vault_prefix): monkeypatch.setenv("KONFETTI_SETTINGS", "test_app.settings.subset") config = Konfig(vault_backend=VaultBackend(vault_prefix)) assert config.DICTIONARY == {"static": 1, "env": True, "vault": "value"}
def test_contains_override(): config = Konfig(strict_override=False) with config.override(MISSING="awesome"): with config.override(): assert "MISSING" in config
def test_dotenv(testdir): settings = testdir.tmpdir.ensure_dir("settings") settings.ensure(".env").write("FROM_DOTENV=loaded") config = Konfig(dotenv=os.path.join(str(settings), ".env")) assert config.FROM_DOTENV == "loaded"
def test_require_ok(): config = Konfig() assert config.require("EXAMPLE") is None
def test_from_mapping(): config = Konfig.from_object({"VALUE": 42}) assert config.asdict() == {"VALUE": 42}