diff --git a/docs/regression_test_api.rst b/docs/regression_test_api.rst index 4e62e14c3a..98c4454737 100644 --- a/docs/regression_test_api.rst +++ b/docs/regression_test_api.rst @@ -670,7 +670,6 @@ Therefore, classes that derive from the base :class:`~reframe.core.pipeline.Regr .. automethod:: reframe.core.pipeline.RegressionMixin.variant_name - ------------------------ Environments and Systems ------------------------ diff --git a/reframe/core/meta.py b/reframe/core/meta.py index 642c4dc4e6..e03405579e 100644 --- a/reframe/core/meta.py +++ b/reframe/core/meta.py @@ -832,13 +832,12 @@ def fixture_space(cls): def is_abstract(cls): '''Check if the class is an abstract test. - This is the case when some parameters are undefined, which results in - the length of the parameter space being 0. + A test is considered abstract if any of its direct or indirect + parameters (inherited from a base class or from a fixture) is + undefined. - :return: bool indicating whether the test or any of its fixtures has - undefined parameters. + :returns: :obj:`True` if the test is abstract, :obj:`False` otherwise. - :meta private: ''' return cls.num_variants == 0 @@ -908,6 +907,8 @@ class HelloTest(rfm.RunOnlyRegressionTest): :param kwargs: Any keyword arguments to be passed to the :class:`RegressionTestMeta` metaclass. + .. versionadded:: 3.10.0 + ''' namespace = RegressionTestMeta.__prepare__(name, bases, **kwargs) namespace.update(body) diff --git a/reframe/core/pipeline.py b/reframe/core/pipeline.py index aa8b82deb5..83f3d42cb8 100644 --- a/reframe/core/pipeline.py +++ b/reframe/core/pipeline.py @@ -1166,6 +1166,26 @@ def fixture_variant(self): ''' return getattr(self, '_rfm_fixt_variant', None) + def set_var_default(self, name, value): + '''Set the default value of a variable if variable is undefined. + + A variable is undefined if it is declared and required and no value is + yet assigned to it. + + :param name: The name of the variable. + :param value: The value to set the variable to. + :raises ValueError: If the variable does not exist + + .. versionadded:: 3.10.1 + + ''' + var_space = type(self).var_space + if name not in var_space: + raise ValueError(f'no such variable: {name!r}') + + if not var_space[name].is_defined(): + setattr(self, name, value) + @property def perfvalues(self): return util.MappingView(self._perfvalues) diff --git a/unittests/test_pipeline.py b/unittests/test_pipeline.py index d81f42708f..67c78775bc 100644 --- a/unittests/test_pipeline.py +++ b/unittests/test_pipeline.py @@ -1527,6 +1527,24 @@ def validate(self): _run(hello_cls(), *local_exec_ctx) +def test_set_var_default(): + class _X(rfm.RunOnlyRegressionTest): + foo = variable(int, value=10) + bar = variable(int) + + @run_after('init') + def set_defaults(self): + self.set_var_default('foo', 100) + self.set_var_default('bar', 100) + + with pytest.raises(ValueError): + self.set_var_default('foobar', 10) + + x = _X() + assert x.foo == 10 + assert x.bar == 100 + + def test_set_name_deprecation(): from reframe.core.warnings import ReframeDeprecationWarning