From 322803c3fb09f86e49b9a6bb85ea428a53384a75 Mon Sep 17 00:00:00 2001 From: Raoul Schaffranek Date: Tue, 13 Jan 2026 00:25:37 +0100 Subject: [PATCH 1/3] Allow environment variables to override settings from foundry.toml --- src/kontrol/__main__.py | 5 +++-- src/kontrol/foundry.py | 16 +++++++++++++--- src/tests/integration/test_foundry_prove.py | 6 ++---- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/kontrol/__main__.py b/src/kontrol/__main__.py index e65074042..568b802cb 100644 --- a/src/kontrol/__main__.py +++ b/src/kontrol/__main__.py @@ -137,8 +137,9 @@ def main() -> None: def exec_load_state(options: LoadStateOptions) -> None: foundry = _load_foundry(options.foundry_root, add_enum_constraints=options.enum_constraints) if options.output_dir_name is None: - options.output_dir_name = foundry.profile.get('test', '') - output_dir = foundry._root / options.output_dir_name + output_dir = foundry.config('test', '') + else: + output_dir = foundry._root / options.output_dir_name foundry_state_load(options=options, output_dir=output_dir) diff --git a/src/kontrol/foundry.py b/src/kontrol/foundry.py index e870a8709..801192a30 100644 --- a/src/kontrol/foundry.py +++ b/src/kontrol/foundry.py @@ -476,9 +476,19 @@ def profile(self) -> dict[str, Any]: return {**default_profile, **current_profile} + def config(self, key: str, default: Any = None) -> Any: + """ + Get a configuration value from an environment variable or foundry.toml profile. + This mimics Foundry's behavior of allowing environment variables to override + settings in foundry.toml. + """ + env_name = 'FOUNDRY_' + key.upper() + return os.getenv(env_name, self.profile.get(key, default)) + @property def out(self) -> Path: - return self._root / self.profile.get('out', '') + out = self.config('out', '') + return self._root / out @property def proofs_dir(self) -> Path: @@ -502,7 +512,7 @@ def main_file(self) -> Path: @property def build_info(self) -> Path: - build_info_path = self.profile.get('build_info_path') + build_info_path = self.config('build_info_path', '') if build_info_path: return self._root / build_info_path @@ -644,7 +654,7 @@ def load_lemmas(self, lemmas_id: str | None) -> KFlatModule | None: @cached_property def all_tests(self) -> list[str]: - test_dir = os.path.join(self.profile.get('test', 'test'), '') + test_dir = os.path.join(self.config('test', 'test'), '') return [ f'{contract.name_with_path}.{method.signature}' for contract in self.contracts.values() diff --git a/src/tests/integration/test_foundry_prove.py b/src/tests/integration/test_foundry_prove.py index 3520be9f9..9f5b8616d 100644 --- a/src/tests/integration/test_foundry_prove.py +++ b/src/tests/integration/test_foundry_prove.py @@ -784,7 +784,6 @@ def test_load_state_diff( foundry_root_dir = root_tmp_dir / 'foundry' foundry = Foundry(foundry_root=foundry_root_dir) - output_dir = foundry._root / foundry.profile.get('test', '') foundry_state_load( LoadStateOptions( { @@ -794,7 +793,7 @@ def test_load_state_diff( 'from_state_diff': 'True', } ), - output_dir=output_dir, + output_dir=foundry.out, ) generated_main_file = foundry_root_dir / 'src' / 'LoadStateDiff.sol' @@ -828,7 +827,6 @@ def test_load_state_dump( foundry_root_dir = root_tmp_dir / 'foundry' foundry = Foundry(foundry_root=foundry_root_dir) - output_dir = foundry._root / foundry.profile.get('test', '') foundry_state_load( LoadStateOptions( { @@ -837,7 +835,7 @@ def test_load_state_dump( 'output_dir_name': 'src', } ), - output_dir=output_dir, + output_dir=foundry.out, ) generated_main_file = foundry_root_dir / 'src' / 'LoadStateDump.sol' From c79f798b8fb1cea189ef4963d4ce55ebc5690ec5 Mon Sep 17 00:00:00 2001 From: Raoul Schaffranek Date: Tue, 13 Jan 2026 12:15:37 +0100 Subject: [PATCH 2/3] Fix test path --- src/kontrol/foundry.py | 5 +++++ src/tests/integration/test_foundry_prove.py | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/kontrol/foundry.py b/src/kontrol/foundry.py index 801192a30..0c94eabcf 100644 --- a/src/kontrol/foundry.py +++ b/src/kontrol/foundry.py @@ -519,6 +519,11 @@ def build_info(self) -> Path: else: return self.out / 'build-info' + @property + def test_path(self) -> Path: + test_path = self.config('test', '') + return self._root / test_path + @property def ffi(self) -> bool: if os.getenv('FOUNDRY_FFI', '').lower() in ('true', '1'): diff --git a/src/tests/integration/test_foundry_prove.py b/src/tests/integration/test_foundry_prove.py index 9f5b8616d..18c1ffba7 100644 --- a/src/tests/integration/test_foundry_prove.py +++ b/src/tests/integration/test_foundry_prove.py @@ -793,7 +793,7 @@ def test_load_state_diff( 'from_state_diff': 'True', } ), - output_dir=foundry.out, + output_dir=foundry.test_path, ) generated_main_file = foundry_root_dir / 'src' / 'LoadStateDiff.sol' @@ -835,7 +835,7 @@ def test_load_state_dump( 'output_dir_name': 'src', } ), - output_dir=foundry.out, + output_dir=foundry.test_path, ) generated_main_file = foundry_root_dir / 'src' / 'LoadStateDump.sol' From ee78175dfe476447e9bedcc94ad07cd174afa7fc Mon Sep 17 00:00:00 2001 From: Raoul <1412344+RaoulSchaffranek@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:33:08 +0100 Subject: [PATCH 3/3] Use test_path instead of reading config manually Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/kontrol/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kontrol/__main__.py b/src/kontrol/__main__.py index 568b802cb..d4835af12 100644 --- a/src/kontrol/__main__.py +++ b/src/kontrol/__main__.py @@ -137,7 +137,7 @@ def main() -> None: def exec_load_state(options: LoadStateOptions) -> None: foundry = _load_foundry(options.foundry_root, add_enum_constraints=options.enum_constraints) if options.output_dir_name is None: - output_dir = foundry.config('test', '') + output_dir = foundry.test_path else: output_dir = foundry._root / options.output_dir_name foundry_state_load(options=options, output_dir=output_dir)