Skip to content

Commit 8d4938f

Browse files
authored
Merge branch 'master' into slurm_cpus_per_task_bugfix
2 parents f780784 + 93de6f4 commit 8d4938f

File tree

32 files changed

+374
-114
lines changed

32 files changed

+374
-114
lines changed

docs/config_reference.rst

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ System Configuration
142142
These modules modify the ReFrame environment.
143143
This is useful in cases where a particular module is needed, for example, to submit jobs on a specific system.
144144

145-
.. js:attribute:: .systems[].variables
145+
.. js:attribute:: .systems[].env_vars
146146

147147
:required: No
148148
:default: ``[]``
@@ -154,6 +154,14 @@ System Configuration
154154
ReFrame will expand its value.
155155
Variables are set after the environment modules are loaded.
156156

157+
.. versionadded:: 4.0.0
158+
159+
.. js:attribute:: .systems[].variables
160+
161+
.. deprecated:: 4.0.0
162+
Please use :js:attr:`env_vars` instead.
163+
If specified in conjunction with :js:attr:`env_vars`, it will be ignored.
164+
157165
.. js:attribute:: .systems[].prefix
158166

159167
:required: No
@@ -374,7 +382,7 @@ System Partition Configuration
374382
When the value is ``null``, no time limit is applied.
375383

376384

377-
.. js:attribute:: .systems[].partitions[].variables
385+
.. js:attribute:: .systems[].partitions[].env_vars
378386

379387
:required: No
380388
:default: ``[]``
@@ -385,6 +393,13 @@ System Partition Configuration
385393
ReFrame will expand its value.
386394
Variables are set after the environment modules are loaded.
387395

396+
.. versionadded:: 4.0.0
397+
398+
.. js:attribute:: .systems[].partitions[].variables
399+
400+
.. deprecated:: 4.0.0
401+
Please use :js:attr:`env_vars` instead.
402+
If specified in conjunction with :js:attr:`env_vars`, it will be ignored.
388403

389404
.. js:attribute:: .systems[].partitions[].max_jobs
390405

@@ -500,7 +515,7 @@ ReFrame can launch containerized applications, but you need to configure properl
500515
A list of `environment module objects <#module-objects>`__ to be loaded when running containerized tests using this container platform.
501516

502517

503-
.. js:attribute:: .systems[].partitions[].container_platforms[].variables
518+
.. js:attribute:: .systems[].partitions[].container_platforms[].env_vars
504519

505520
:required: No
506521
:default: ``[]``
@@ -511,6 +526,14 @@ ReFrame can launch containerized applications, but you need to configure properl
511526
ReFrame will expand its value.
512527
Variables are set after the environment modules are loaded.
513528

529+
.. versionadded:: 4.0.0
530+
531+
.. js:attribute:: .systems[].partitions[].container_platforms[].variables
532+
533+
.. deprecated:: 4.0.0
534+
Please use :js:attr:`env_vars` instead.
535+
If specified in conjunction with :js:attr:`env_vars`, it will be ignored.
536+
514537

515538
Custom Job Scheduler Resources
516539
==============================
@@ -619,7 +642,7 @@ They are associated with `system partitions <#system-partition-configuration>`__
619642
A list of `environment module objects <#module-objects>`__ to be loaded when this environment is loaded.
620643

621644

622-
.. js:attribute:: .environments[].variables
645+
.. js:attribute:: .environments[].env_vars
623646

624647
:required: No
625648
:default: ``[]``
@@ -630,6 +653,14 @@ They are associated with `system partitions <#system-partition-configuration>`__
630653
ReFrame will expand its value.
631654
Variables are set after the environment modules are loaded.
632655

656+
.. versionadded:: 4.0.0
657+
658+
.. js:attribute:: .environments[].variables
659+
660+
.. deprecated:: 4.0.0
661+
Please use :js:attr:`env_vars` instead.
662+
If specified in conjunction with :js:attr:`env_vars`, it will be ignored.
663+
633664

634665
.. js:attribute:: .environments[].features
635666

@@ -868,7 +899,8 @@ All logging handlers share the following set of common attributes:
868899
``%(check_descr)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.descr` attribute.
869900
``%(check_display_name)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.display_name` attribute.
870901
``%(check_environ)s``, The name of the test's :attr:`~reframe.core.pipeline.RegressionTest.current_environ`.
871-
``%(check_exclusive_access)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.exclusive_access` attribute.
902+
``%(check_env_vars)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.env_vars` attribute.
903+
``%(check_exclusive_access)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.exclusive_access` attribute.
872904
``%(check_executable)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.executable` attribute.
873905
``%(check_executable_opts)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.executable_opts` attribute.
874906
``%(check_extra_resources)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.extra_resources` attribute.
@@ -918,7 +950,7 @@ All logging handlers share the following set of common attributes:
918950
``%(check_use_multithreading)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.use_multithreading` attribute.
919951
``%(check_valid_prog_environs)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.valid_prog_environs` attribute.
920952
``%(check_valid_systems)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.valid_systems` attribute.
921-
``%(check_variables)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.variables` attribute.
953+
``%(check_variables)s``, DEPRECATED: Please use ``%(check_env_vars)s`` instead.
922954
``%(osuser)s``, The name of the OS user running ReFrame.
923955
``%(osgroup)s``, The name of the OS group running ReFrame.
924956
``%(version)s``, The ReFrame version.

docs/tutorial_basics.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ The next thing to notice is the :attr:`~reframe.core.pipeline.RegressionTest.pre
430430
These commands will be executed from the test's stage directory.
431431
In this case, we just fetch the source code of the benchmark.
432432
For running the benchmark, we need to set the OpenMP number of threads and pin them to the right CPUs through the ``OMP_NUM_THREADS`` and ``OMP_PLACES`` environment variables.
433-
You can set environment variables in a ReFrame test through the :attr:`~reframe.core.pipeline.RegressionTest.variables` dictionary.
433+
You can set environment variables in a ReFrame test through the :attr:`~reframe.core.pipeline.RegressionTest.env_vars` dictionary.
434434

435435
What makes a ReFrame test a performance test is the definition of at least one :ref:`performance function<deferrable-performance-functions>`.
436436
Similarly to a test's :func:`@sanity_function<reframe.core.pipeline.RegressionMixin.sanity_function>`, a performance function is a member function decorated with the :attr:`@performance_function<reframe.core.pipeline.RegressionMixin.performance_function>` decorator, which binds the decorated function to a given unit.

reframe/core/config.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,45 @@ def validate(self):
347347

348348
partition_names.add(partname)
349349

350+
def _warn_variables(config, opt_path):
351+
opt_path = '/'.join(opt_path + ['variables'])
352+
if 'env_vars' in config and 'variables' in config:
353+
getlogger().warning(
354+
f"configuration option {opt_path!r}: "
355+
f"both 'env_vars' and 'variables' are defined; "
356+
f"'variables' will be ignored"
357+
)
358+
elif 'variables' in config:
359+
getlogger().warning(
360+
f"configuration option {opt_path!r}: "
361+
f"'variables' is deprecated; please use 'env_vars' instead"
362+
)
363+
config['env_vars'] = config['variables']
364+
365+
# Warn about the deprecated `variables` and convert them internally to
366+
# `env_vars`
367+
for system in self._site_config['systems']:
368+
sysname = system['name']
369+
opt_path = ['systems', f'@{sysname}']
370+
_warn_variables(system, opt_path)
371+
for part in system['partitions']:
372+
partname = part['name']
373+
opt_path += ['partitions', f'@{partname}']
374+
_warn_variables(part, opt_path)
375+
for i, cp in enumerate(part.get('container_platforms', [])):
376+
opt_path += ['container_platforms', str(i)]
377+
_warn_variables(cp, opt_path)
378+
opt_path.pop()
379+
opt_path.pop()
380+
381+
opt_path.pop()
382+
opt_path.pop()
383+
384+
for env in self._site_config['environments']:
385+
envname = env['name']
386+
opt_path = ['environments', f'@{envname}']
387+
_warn_variables(env, opt_path)
388+
350389
def select_subconfig(self, system_fullname=None,
351390
ignore_resolve_errors=False):
352391
# First look for the current subconfig in the cache; if not found,

reframe/core/environments.py

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import reframe.utility as util
1111
import reframe.utility.jsonext as jsonext
1212
import reframe.utility.typecheck as typ
13+
from reframe.core.warnings import user_deprecation_warning
1314

1415

1516
def normalize_module_list(modules):
@@ -37,14 +38,22 @@ class Environment(jsonext.JSONSerializable):
3738
Users may not create :class:`Environment` objects directly.
3839
'''
3940

40-
def __init__(self, name, modules=None, variables=None,
41+
def __init__(self, name, modules=None, env_vars=None,
4142
extras=None, features=None):
4243
modules = modules or []
43-
variables = variables or []
44+
env_vars = env_vars or []
4445
self._name = name
4546
self._modules = normalize_module_list(modules)
4647
self._module_names = [m['name'] for m in self._modules]
47-
self._variables = collections.OrderedDict(variables)
48+
49+
# Convert values of env_vars to strings before storing
50+
if isinstance(env_vars, dict):
51+
env_vars = env_vars.items()
52+
53+
self._env_vars = collections.OrderedDict()
54+
for k, v in env_vars:
55+
self._env_vars[k] = str(v)
56+
4857
self._extras = extras or {}
4958
self._features = features or []
5059

@@ -85,12 +94,25 @@ def modules_detailed(self):
8594
return util.SequenceView(self._modules)
8695

8796
@property
88-
def variables(self):
97+
def env_vars(self):
8998
'''The environment variables associated with this environment.
9099
91100
:type: :class:`OrderedDict[str, str]`
101+
102+
.. versionadded:: 4.0.0
103+
'''
104+
return util.MappingView(self._env_vars)
105+
106+
@property
107+
def variables(self):
108+
'''The environment variables associated with this environment.
109+
110+
.. deprecated:: 4.0.0
111+
Please :attr:`env_vars` instead.
92112
'''
93-
return util.MappingView(self._variables)
113+
user_deprecation_warning("the 'variables' attribute is deprecated; "
114+
"please use the 'env_vars' instead")
115+
return util.MappingView(self._env_vars)
94116

95117
@property
96118
def extras(self):
@@ -117,9 +139,19 @@ def __eq__(self, other):
117139
if not isinstance(other, type(self)):
118140
return NotImplemented
119141

120-
return (self.name == other.name and
121-
set(self.modules) == set(other.modules) and
122-
self.variables == other.variables)
142+
if (self.name != other.name or
143+
set(self.modules) != set(other.modules)):
144+
return False
145+
146+
# Env. variables are checked against their string representation
147+
for kv0, kv1 in zip(self.env_vars.items(),
148+
other.env_vars.items()):
149+
k0, v0 = kv0
150+
k1, v1 = kv1
151+
if k0 != k1 or str(v0) != str(v1):
152+
return False
153+
154+
return True
123155

124156
def __str__(self):
125157
return self.name
@@ -128,7 +160,7 @@ def __repr__(self):
128160
return (f'{type(self).__name__}('
129161
f'name={self._name!r}, '
130162
f'modules={self._modules!r}, '
131-
f'variables={list(self._variables.items())!r}, '
163+
f'env_vars={list(self._env_vars.items())!r}, '
132164
f'extras={self._extras!r}, features={self._features!r})')
133165

134166

@@ -141,15 +173,15 @@ def __init__(self, name='env_snapshot'):
141173
def restore(self):
142174
'''Restore this environment snapshot.'''
143175
os.environ.clear()
144-
os.environ.update(self._variables)
176+
os.environ.update(self._env_vars)
145177

146178
def __eq__(self, other):
147179
if not isinstance(other, Environment):
148180
return NotImplemented
149181

150-
# Order of variables is not important when comparing snapshots
151-
for k, v in self.variables.items():
152-
if other.variables[k] != v:
182+
# Order of env. variables is not important when comparing snapshots
183+
for k, v in self.env_vars.items():
184+
if other.env_vars[k] != v:
153185
return False
154186

155187
return self.name == other.name
@@ -185,7 +217,7 @@ class ProgEnvironment(Environment):
185217
def __init__(self,
186218
name,
187219
modules=None,
188-
variables=None,
220+
env_vars=None,
189221
extras=None,
190222
features=None,
191223
cc='cc',
@@ -198,7 +230,7 @@ def __init__(self,
198230
fflags=None,
199231
ldflags=None,
200232
**kwargs):
201-
super().__init__(name, modules, variables, extras, features)
233+
super().__init__(name, modules, env_vars, extras, features)
202234
self._cc = cc
203235
self._cxx = cxx
204236
self._ftn = ftn

reframe/core/logging.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import reframe.utility.jsonext as jsonext
2121
import reframe.utility.osext as osext
2222
from reframe.core.exceptions import ConfigError, LoggingError
23+
from reframe.core.warnings import suppress_deprecations
2324
from reframe.utility.profile import TimeProfiler
2425

2526

@@ -396,8 +397,8 @@ def __init__(self, url, extras=None, ignore_keys=None):
396397
def _record_to_json(self, record):
397398
def _can_send(key):
398399
return not (
399-
key.startswith('_') or key in HTTPJSONHandler.LOG_ATTRS
400-
or (self._ignore_keys and key in self._ignore_keys)
400+
key.startswith('_') or key in HTTPJSONHandler.LOG_ATTRS or
401+
(self._ignore_keys and key in self._ignore_keys)
401402
)
402403

403404
json_record = {
@@ -577,9 +578,11 @@ def _update_check_extras(self):
577578
for attr, alt_name in check_type.loggable_attrs():
578579
extra_name = alt_name or attr
579580

580-
# In case of AttributeError, i.e., the variable is undefined, we
581-
# set the value to None
582-
val = getattr(self.check, attr, None)
581+
with suppress_deprecations():
582+
# In case of AttributeError, i.e., the variable is undefined,
583+
# we set the value to None
584+
val = getattr(self.check, attr, None)
585+
583586
if attr in check_type.raw_params:
584587
# Attribute is parameter, so format it
585588
val = check_type.raw_params[attr].format(val)

reframe/core/pipeline.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -781,11 +781,28 @@ def pipeline_hooks(cls):
781781

782782
#: Environment variables to be set before running this test.
783783
#:
784-
#: These variables will be set during the :func:`setup` phase.
784+
#: The value of the environment variables can be of any type. ReFrame will
785+
#: invoke :func:`str` on it whenever it needs to emit it in a script.
785786
#:
786-
#: :type: :class:`Dict[str, str]`
787+
#: :type: :class:`Dict[str, object]`
787788
#: :default: ``{}``
788-
variables = variable(typ.Dict[str, str], value={}, loggable=True)
789+
#:
790+
#: .. versionadded:: 4.0.0
791+
env_vars = variable(typ.Dict[str, str],
792+
typ.Dict[str, object], value={}, loggable=True)
793+
# NOTE: We still keep the original type, just to allow setting this
794+
# variable from the command line, because otherwise, ReFrame will not know
795+
# how to convert a value to an arbitrary object.
796+
797+
#: Environment variables to be set before running this test.
798+
#:
799+
#: This is an alias of :attr:`env_vars`.
800+
#:
801+
#: .. deprecated:: 4.0.0
802+
#: Please use :attr:`env_vars` instead.
803+
variables = deprecate(variable(alias=env_vars, loggable=True),
804+
f"the use of 'variables' is deprecated; "
805+
f"please use 'env_vars' instead")
789806

790807
#: Time limit for this test.
791808
#:
@@ -1746,7 +1763,7 @@ def compile(self):
17461763
self.build_system.executable = self.executable
17471764

17481765
user_environ = Environment(self.unique_name,
1749-
self.modules, self.variables.items())
1766+
self.modules, self.env_vars.items())
17501767
environs = [self._current_partition.local_env, self._current_environ,
17511768
user_environ, self._cdt_environ]
17521769
self._build_job.time_limit = (
@@ -1880,7 +1897,7 @@ def _get_cp_env():
18801897
*self.postrun_cmds
18811898
]
18821899
user_environ = Environment(self.unique_name,
1883-
self.modules, self.variables.items())
1900+
self.modules, self.env_vars.items())
18841901
environs = [
18851902
self._current_partition.local_env,
18861903
self._current_environ,

0 commit comments

Comments
 (0)