diff --git a/deepnote_toolkit/set_integrations_env.py b/deepnote_toolkit/set_integrations_env.py index 0edaadd..56c4d2e 100644 --- a/deepnote_toolkit/set_integrations_env.py +++ b/deepnote_toolkit/set_integrations_env.py @@ -2,7 +2,7 @@ from requests.adapters import HTTPAdapter, Retry from . import env as dnenv -from .config import get_config +from .config import clear_config_cache, get_config from .get_webapp_url import get_absolute_userpod_api_url, get_project_auth_headers from .logging import LoggerManager @@ -64,4 +64,8 @@ def set_integration_env(): v["name"] for v in variables if v.get("name") is not None ] + # New env vars may affect config, so drop the cached config to + # force a fresh read on next access. + clear_config_cache() + logger.info("Finish set_integration_env") diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index bd96b53..b070e2d 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -3,6 +3,7 @@ from deepnote_core.config.loader import ConfigurationLoader from deepnote_core.config.models import DeepnoteConfig +from deepnote_toolkit.config import clear_config_cache, get_config def test_port_validation_range(): @@ -26,6 +27,24 @@ def test_runtime_coerce_float_inverted_flag(monkeypatch): assert cfg.runtime.coerce_float is False +def test_coerce_float_picks_up_late_env_after_cache_clear(monkeypatch): + # Setup: start from a clean cache and confirm the default value + clear_config_cache() + monkeypatch.delenv("DEEPNOTE_DO_NOT_COERCE_FLOAT", raising=False) + cfg_default = get_config() + assert cfg_default.runtime.coerce_float is True + + # Inject the env var; the cached config should still return the default + monkeypatch.setenv("DEEPNOTE_DO_NOT_COERCE_FLOAT", "1") + cfg_cached = get_config() + assert cfg_cached.runtime.coerce_float is True + + # After clearing the cache, the config should pick up the injected value + clear_config_cache() + cfg_refreshed = get_config() + assert cfg_refreshed.runtime.coerce_float is False + + def test_loader_precedence_cli_over_env_over_file(tmp_path, monkeypatch): # File value: 7777 config_file = tmp_path / "deepnote-toolkit.toml" diff --git a/tests/unit/test_set_integrations_env.py b/tests/unit/test_set_integrations_env.py index db1b17f..1c26644 100644 --- a/tests/unit/test_set_integrations_env.py +++ b/tests/unit/test_set_integrations_env.py @@ -74,6 +74,38 @@ def get(self, *a, **k): set_integration_env() +@mock.patch( + "deepnote_toolkit.set_integrations_env.get_config", + side_effect=lambda: _mock_cfg(True), +) +def test_set_integration_env_clears_config_cache( + mock_get_config, monkeypatch # noqa: ARG001 +): + class DummyResp: + ok = True + + def json(self): + return [{"name": "DEEPNOTE_DO_NOT_COERCE_FLOAT", "value": "1"}] + + class DummySession: + def mount(self, *a, **k): + pass + + def get(self, *a, **k): + return DummyResp() + + monkeypatch.setattr( + "deepnote_toolkit.set_integrations_env.requests.Session", lambda: DummySession() + ) + monkeypatch.setenv("DEEPNOTE_PROJECT_ID", "pid") + + with mock.patch( + "deepnote_toolkit.set_integrations_env.clear_config_cache" + ) as mock_clear: + set_integration_env() + mock_clear.assert_called_once() + + def test_set_integration_env_disabled_gate(monkeypatch): # get_config returns disabled gate; Session should not be constructed from deepnote_toolkit import set_integrations_env as sie