Skip to content

Commit

Permalink
Merge branch 'master' into bugfix/slurm-lazy-eval-nodelist
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarak authored Nov 8, 2023
2 parents db60948 + 3e3f4c5 commit 8f22223
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 18 deletions.
6 changes: 5 additions & 1 deletion docs/config_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,7 @@ All logging handlers share the following set of common attributes:
``%(check_prebuild_cmds)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.prebuild_cmds` attribute.
``%(check_prefix)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.prefix` attribute.
``%(check_prerun_cmds)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.prerun_cmds` attribute.
``%(check_result)s``, The result of the test (``pass`` or ``fail``).
``%(check_readonly_files)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.readonly_files` attribute.
``%(check_short_name)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.short_name` attribute.
``%(check_sourcepath)s``, The value of the :attr:`~reframe.core.pipeline.RegressionTest.sourcepath` attribute.
Expand Down Expand Up @@ -1116,6 +1117,9 @@ All logging handlers share the following set of common attributes:
.. versionchanged:: 3.11.0
Limit the number of attributes that can be logged. User attributes or properties must be explicitly marked as "loggable" in order to be selectable for logging.

.. versionadded:: 4.0
The ``%(check_result)s`` specifier is added.

.. versionadded:: 4.3
The ``%(check_#ALL)s`` special specifier is added.

Expand Down Expand Up @@ -1188,7 +1192,7 @@ The additional properties for the ``file`` handler are the following:

.. py:attribute:: logging.handlers..file..append
.. py:attribute:: logging.handlers_perflog..file..ppend
.. py:attribute:: logging.handlers_perflog..file..append
:required: No
:default: ``false``
Expand Down
5 changes: 5 additions & 0 deletions docs/manpage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,11 @@ Options controlling ReFrame execution
the :option:`-P` option can only parameterize the leaf test:
it cannot be used to parameterize a fixture of the test.

.. note::

The :option:`-P` option supports only tests that use fixtures.
Tests that use raw dependencies are not supported.

.. versionadded:: 4.3

.. option:: --repeat=N
Expand Down
4 changes: 0 additions & 4 deletions reframe/core/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -789,13 +789,9 @@ def __init__(self, logger=None, check=None):
'__rfm_check__': check,
'__rfm_loggable_attrs__': [],
'check_name': 'reframe',
'check_jobid': None,
'check_job_completion_time': None,
'check_job_completion_time_unix': None,
'check_info': 'reframe',
'check_system': None,
'check_partition': None,
'check_environ': None,
'check_perf_var': None,
'check_perf_value': None,
'check_perf_ref': None,
Expand Down
1 change: 1 addition & 0 deletions reframe/frontend/autodetect.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ def _emit_script_for_pip(job, env):
commands = [
'python3 -m venv venv.reframe',
'source venv.reframe/bin/activate',
'pip install --upgrade pip',
f'pip install reframe-hpc=={rfm.VERSION}',
'reframe --detect-host-topology=topo.json',
'deactivate'
Expand Down
37 changes: 24 additions & 13 deletions reframe/utility/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -829,11 +829,12 @@ def _rl_encode(seq):


def _parse_node(nodename):
m = re.search(r'(.*\D)(\d+)', nodename)
m = re.search(r'(.*\D)(\d+)(\D*)', nodename)
if m is None:
basename = nodename
width = 0
nodeid = None
suffix = None
else:
basename = m.group(1)
_id = m.group(2).lstrip('0')
Expand All @@ -843,8 +844,9 @@ def _parse_node(nodename):

nodeid = int(_id)
width = len(m.group(2))
suffix = m.group(3)

return basename, width, nodeid
return basename, width, nodeid, suffix


def count_digits(n):
Expand Down Expand Up @@ -873,15 +875,20 @@ def _common_prefix(s1, s2):


class _NodeGroup:
def __init__(self, name, width):
def __init__(self, name, width, suffix):
self.__name = name
self.__suffix = suffix
self.__width = width
self.__nodes = []

@property
def name(self):
return self.__name

@property
def suffix(self):
return self.__suffix

@property
def width(self):
return self.__width
Expand All @@ -903,12 +910,12 @@ def __str__(self):
start, delta, size = unit
if size == 1:
s_start = str(start).zfill(self.width)
abbrev.append(f'{self.name}{s_start}')
abbrev.append(f'{self.name}{s_start}{self.suffix}')
elif delta != 1:
# We simply unpack node lists with delta != 1
for i in range(size):
s_start = str(start + i*delta).zfill(self.width)
abbrev.append(f'{self.name}{s_start}')
abbrev.append(f'{self.name}{s_start}{self.suffix}')
else:
last = start + delta*(size-1)
digits_last = count_digits(last)
Expand All @@ -921,19 +928,21 @@ def __str__(self):
s_first = str(start).zfill(digits_last)
s_last = str(last)
prefix, s_first, s_last = _common_prefix(s_first, s_last)
nd_range += f'{prefix}[{s_first}-{s_last}]'
nd_range += f'{prefix}[{s_first}-{s_last}]{self.suffix}'
abbrev.append(nd_range)

return ','.join(abbrev)

def __hash__(self):
return hash(self.name) ^ hash(self.width)
return hash(self.name) ^ hash(self.suffix) ^ hash(self.width)

def __eq__(self, other):
if not isinstance(other, _NodeGroup):
return NotImplemented

return self.name == other.name and self.width == other.width
return (self.name == other.name and
self.suffix == other.suffix and
self.width == other.width)


def nodelist_abbrev(nodes):
Expand Down Expand Up @@ -978,8 +987,8 @@ def nodelist_abbrev(nodes):

node_groups = {}
for n in sorted(nodes):
basename, width, nid = _parse_node(n)
ng = _NodeGroup(basename, width)
basename, width, nid, suffix = _parse_node(n)
ng = _NodeGroup(basename, width, suffix)
node_groups.setdefault(ng, ng)
if nid is not None:
node_groups[ng].add(nid)
Expand All @@ -1004,7 +1013,9 @@ def nodelist_expand(nodespec):
return []

nodespec_parts = nodespec.split(',')
node_patt = re.compile(r'(?P<prefix>.+)\[(?P<l>\d+)-(?P<u>\d+)\]')
node_patt = re.compile(
r'(?P<prefix>.+)\[(?P<l>\d+)-(?P<u>\d+)\](?P<suffix>.*)'
)
nodes = []
for ns in nodespec_parts:
if '[' not in ns and ']' not in ns:
Expand All @@ -1015,11 +1026,11 @@ def nodelist_expand(nodespec):
if not match:
raise ValueError(f'invalid nodespec: {nodespec}')

prefix = match.group('prefix')
prefix, suffix = match.group('prefix'), match.group('suffix')
low, upper = int(match.group('l')), int(match.group('u'))
width = count_digits(upper)
for nid in range(low, upper+1):
nodes.append(f'{prefix}{nid:0{width}}')
nodes.append(f'{prefix}{nid:0{width}}{suffix}')

return nodes

Expand Down
6 changes: 6 additions & 0 deletions unittests/test_utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -2052,6 +2052,12 @@ def test_nodelist_utilities():
# Test the reverse operation
assert expand('c2-01-[00-99]') == nodes

# Test host names with suffixes (see GH #3021)
nodes = [f'nid{n:03}-x' for n in range(100)]
nodes.append('nid100-y')
assert nodelist(nodes) == 'nid0[00-99]-x,nid100-y'
assert expand('nid0[00-99]-x,nid100-y') == nodes

# Test node duplicates
assert nodelist(['nid001', 'nid001', 'nid002']) == 'nid001,nid00[1-2]'
assert expand('nid001,nid00[1-2]') == ['nid001', 'nid001', 'nid002']
Expand Down

0 comments on commit 8f22223

Please sign in to comment.