diff --git a/src/experimaestro/core/objects/config.py b/src/experimaestro/core/objects/config.py index 2b495eeb..1c7f7e40 100644 --- a/src/experimaestro/core/objects/config.py +++ b/src/experimaestro/core/objects/config.py @@ -344,6 +344,14 @@ def seal(self, context: ConfigWalkContext): Arguments: - context: the generation context """ + subconfigs = [ + v.__xpm__ + for v in self.values.values() + if isinstance(v, Config) and v.__xpm__.task is None + ] + + if any(v._has_generated_value for v in subconfigs): + raise AttributeError("Cannot seal a configuration with generated values") class Sealer(ConfigWalk): def preprocess(self, config: ConfigMixin): diff --git a/src/experimaestro/tests/test_generators.py b/src/experimaestro/tests/test_generators.py index ac4d799e..7695d23d 100644 --- a/src/experimaestro/tests/test_generators.py +++ b/src/experimaestro/tests/test_generators.py @@ -14,7 +14,7 @@ class Learner(Task): x: Param[int] -def test_generators_reuse(): +def test_generators_reuse_on_submit(): # We have one way to select the best model validation = Validation.C() @@ -31,3 +31,31 @@ def test_generators_reuse(): # Here we have a problem... # the path is still the previous one Learner.C(x=2, validation=validation).submit(workspace=workspace) + + +def test_generators_delayed_submit(): + workspace = Workspace( + Settings(), + WorkspaceSettings("test_generators_simple", path=Path("/tmp")), + run_mode=RunMode.DRY_RUN, + ) + validation = Validation.C() + task1 = Learner.C(x=1, validation=validation) + task2 = Learner.C(x=2, validation=validation) + task1.submit(workspace=workspace) + with pytest.raises((AttributeError)): + task2.submit(workspace=workspace) + + +def test_generators_reuse_on_set(): + workspace = Workspace( + Settings(), + WorkspaceSettings("test_generators_simple", path=Path("/tmp")), + run_mode=RunMode.DRY_RUN, + ) + validation = Validation.C() + Learner.C(x=1, validation=validation).submit(workspace=workspace) + with pytest.raises((AttributeError)): + # We should not be able to *create* a second task with the same validation, + # even without submitting it + Learner.C(x=2, validation=validation)