diff --git a/ccflow/callable.py b/ccflow/callable.py index 2f79a2d..4cd3ec0 100644 --- a/ccflow/callable.py +++ b/ccflow/callable.py @@ -440,7 +440,7 @@ def get_options(cls, model: CallableModelType, model_options: FlowOptions | None current_options = cls._apply_options(current_options, model_options) # Then apply the model meta-provided options if model.meta.options: - current_options = model.meta.options + current_options = cls._apply_options(current_options, model.meta.options) # Then apply all model-specific overrides for override in overrides: if any(model is m for m in override.models) or isinstance(model, override.model_types): diff --git a/ccflow/tests/test_decorator.py b/ccflow/tests/test_decorator.py index 5bea104..1d64332 100644 --- a/ccflow/tests/test_decorator.py +++ b/ccflow/tests/test_decorator.py @@ -219,6 +219,23 @@ def test_override_precedence(self): self.assertEqual(get_options(model), new_options) self.assertEqual(get_options(model), options) + def test_meta_keeps_unset_global_options(self): + # meta only overrides the fields it sets, so a globally configured evaluator still applies + evaluator = DummyEvaluator() + model = DefaultModel(meta={"options": {"cacheable": False}}) + get_options = DefaultModel.__call__.get_options + with FlowOptionsOverride(options=FlowOptions(evaluator=evaluator, cacheable=True, log_level=logging.WARNING)): + options = get_options(model) + self.assertIs(options.evaluator, evaluator) + self.assertEqual(options.log_level, logging.WARNING) + self.assertFalse(options.cacheable) + + def test_meta_keeps_unset_decorator_options(self): + model = MyModel(meta={"options": {"cacheable": True}}) + options = MyModel.__call__.get_options(model) + self.assertEqual(options.log_level, logging.WARNING) + self.assertTrue(options.cacheable) + class TestFlowOptionsOverride(TestCase): def setUp(self):