Skip to content

Commit 64ab7c0

Browse files
authored
Merge pull request #3027 from vkarak/bugfix/nodelist-treat-suffixes
[bugfix] Treat node name suffixes properly in abbreviated node lists
2 parents 7dd781b + 7477204 commit 64ab7c0

File tree

2 files changed

+30
-13
lines changed

2 files changed

+30
-13
lines changed

reframe/utility/__init__.py

+24-13
Original file line numberDiff line numberDiff line change
@@ -829,11 +829,12 @@ def _rl_encode(seq):
829829

830830

831831
def _parse_node(nodename):
832-
m = re.search(r'(.*\D)(\d+)', nodename)
832+
m = re.search(r'(.*\D)(\d+)(\D*)', nodename)
833833
if m is None:
834834
basename = nodename
835835
width = 0
836836
nodeid = None
837+
suffix = None
837838
else:
838839
basename = m.group(1)
839840
_id = m.group(2).lstrip('0')
@@ -843,8 +844,9 @@ def _parse_node(nodename):
843844

844845
nodeid = int(_id)
845846
width = len(m.group(2))
847+
suffix = m.group(3)
846848

847-
return basename, width, nodeid
849+
return basename, width, nodeid, suffix
848850

849851

850852
def count_digits(n):
@@ -873,15 +875,20 @@ def _common_prefix(s1, s2):
873875

874876

875877
class _NodeGroup:
876-
def __init__(self, name, width):
878+
def __init__(self, name, width, suffix):
877879
self.__name = name
880+
self.__suffix = suffix
878881
self.__width = width
879882
self.__nodes = []
880883

881884
@property
882885
def name(self):
883886
return self.__name
884887

888+
@property
889+
def suffix(self):
890+
return self.__suffix
891+
885892
@property
886893
def width(self):
887894
return self.__width
@@ -903,12 +910,12 @@ def __str__(self):
903910
start, delta, size = unit
904911
if size == 1:
905912
s_start = str(start).zfill(self.width)
906-
abbrev.append(f'{self.name}{s_start}')
913+
abbrev.append(f'{self.name}{s_start}{self.suffix}')
907914
elif delta != 1:
908915
# We simply unpack node lists with delta != 1
909916
for i in range(size):
910917
s_start = str(start + i*delta).zfill(self.width)
911-
abbrev.append(f'{self.name}{s_start}')
918+
abbrev.append(f'{self.name}{s_start}{self.suffix}')
912919
else:
913920
last = start + delta*(size-1)
914921
digits_last = count_digits(last)
@@ -921,19 +928,21 @@ def __str__(self):
921928
s_first = str(start).zfill(digits_last)
922929
s_last = str(last)
923930
prefix, s_first, s_last = _common_prefix(s_first, s_last)
924-
nd_range += f'{prefix}[{s_first}-{s_last}]'
931+
nd_range += f'{prefix}[{s_first}-{s_last}]{self.suffix}'
925932
abbrev.append(nd_range)
926933

927934
return ','.join(abbrev)
928935

929936
def __hash__(self):
930-
return hash(self.name) ^ hash(self.width)
937+
return hash(self.name) ^ hash(self.suffix) ^ hash(self.width)
931938

932939
def __eq__(self, other):
933940
if not isinstance(other, _NodeGroup):
934941
return NotImplemented
935942

936-
return self.name == other.name and self.width == other.width
943+
return (self.name == other.name and
944+
self.suffix == other.suffix and
945+
self.width == other.width)
937946

938947

939948
def nodelist_abbrev(nodes):
@@ -978,8 +987,8 @@ def nodelist_abbrev(nodes):
978987

979988
node_groups = {}
980989
for n in sorted(nodes):
981-
basename, width, nid = _parse_node(n)
982-
ng = _NodeGroup(basename, width)
990+
basename, width, nid, suffix = _parse_node(n)
991+
ng = _NodeGroup(basename, width, suffix)
983992
node_groups.setdefault(ng, ng)
984993
if nid is not None:
985994
node_groups[ng].add(nid)
@@ -1004,7 +1013,9 @@ def nodelist_expand(nodespec):
10041013
return []
10051014

10061015
nodespec_parts = nodespec.split(',')
1007-
node_patt = re.compile(r'(?P<prefix>.+)\[(?P<l>\d+)-(?P<u>\d+)\]')
1016+
node_patt = re.compile(
1017+
r'(?P<prefix>.+)\[(?P<l>\d+)-(?P<u>\d+)\](?P<suffix>.*)'
1018+
)
10081019
nodes = []
10091020
for ns in nodespec_parts:
10101021
if '[' not in ns and ']' not in ns:
@@ -1015,11 +1026,11 @@ def nodelist_expand(nodespec):
10151026
if not match:
10161027
raise ValueError(f'invalid nodespec: {nodespec}')
10171028

1018-
prefix = match.group('prefix')
1029+
prefix, suffix = match.group('prefix'), match.group('suffix')
10191030
low, upper = int(match.group('l')), int(match.group('u'))
10201031
width = count_digits(upper)
10211032
for nid in range(low, upper+1):
1022-
nodes.append(f'{prefix}{nid:0{width}}')
1033+
nodes.append(f'{prefix}{nid:0{width}}{suffix}')
10231034

10241035
return nodes
10251036

unittests/test_utility.py

+6
Original file line numberDiff line numberDiff line change
@@ -2052,6 +2052,12 @@ def test_nodelist_utilities():
20522052
# Test the reverse operation
20532053
assert expand('c2-01-[00-99]') == nodes
20542054

2055+
# Test host names with suffixes (see GH #3021)
2056+
nodes = [f'nid{n:03}-x' for n in range(100)]
2057+
nodes.append('nid100-y')
2058+
assert nodelist(nodes) == 'nid0[00-99]-x,nid100-y'
2059+
assert expand('nid0[00-99]-x,nid100-y') == nodes
2060+
20552061
# Test node duplicates
20562062
assert nodelist(['nid001', 'nid001', 'nid002']) == 'nid001,nid00[1-2]'
20572063
assert expand('nid001,nid00[1-2]') == ['nid001', 'nid001', 'nid002']

0 commit comments

Comments
 (0)