From df0d689d8172a3c097a8545f377599b96c5a2cfa Mon Sep 17 00:00:00 2001 From: Justin Hiemstra Date: Mon, 8 Jun 2026 16:38:43 -0500 Subject: [PATCH] Propagate enable_profiling through ProcessedContainerSettings ProcessedContainerSettings.from_container_settings() rebuilds the processed container settings from the raw ContainerSettings, but it never copied the enable_profiling field, so the processed settings always used the dataclass default of False. run_container_singularity() reads the flag off the processed settings (config.enable_profiling), so the profiling branch never ran: no peer cgroup was created, cgroup_wrapper.sh never executed, and no usage-profile.tsv was written, regardless of the user's containers.enable_profiling config value. This regressed in #390, which moved enable_profiling from a top-level config field to the nested container settings and added the field to both ContainerSettings and ProcessedContainerSettings, but missed wiring it through the conversion in from_container_settings(). Add the missing assignment, plus a regression test in test_config.py asserting that enable_profiling survives the full config-parsing path. --- spras/config/container_schema.py | 1 + test/test_config.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/spras/config/container_schema.py b/spras/config/container_schema.py index 70276f63..5112198b 100644 --- a/spras/config/container_schema.py +++ b/spras/config/container_schema.py @@ -95,6 +95,7 @@ def from_container_settings(settings: ContainerSettings, hash_length: int) -> "P unpack_singularity=unpack_singularity, base_url=container_base_url, prefix=container_prefix, + enable_profiling=settings.enable_profiling, hash_length=hash_length, images=dict(settings.images), ) diff --git a/test/test_config.py b/test/test_config.py index cf4cdf0f..f20f0e64 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -251,6 +251,22 @@ def test_config_container_images_invalid_algorithm(self): with pytest.raises(ValueError, match="Unknown algorithm name 'typo_algo'"): config.init_global(test_config) + def test_config_container_enable_profiling(self): + # enable_profiling must survive the ContainerSettings -> ProcessedContainerSettings + # conversion in from_container_settings(). containers.py reads it off the processed + # settings at runtime, so if it isn't propagated the profiling code path never runs. + # Regression test for the field being silently dropped during that conversion. + test_config = get_test_config() + + # Default: absent from config --> False + config.init_global(test_config) + assert config.config.container_settings.enable_profiling is False + + # Explicitly enabled --> must propagate to the processed settings as True + test_config["containers"]["enable_profiling"] = True + config.init_global(test_config) + assert config.config.container_settings.enable_profiling is True + def test_error_dataset_label(self): test_config = get_test_config() error_test_dicts = [{"label": "test$"}, {"label": "@test'"}, {"label": "[test]"}, {"label": "test-test"},