diff --git a/reframe/core/logging.py b/reframe/core/logging.py index bf68067157..ec1273602a 100644 --- a/reframe/core/logging.py +++ b/reframe/core/logging.py @@ -484,8 +484,15 @@ def _update_check_extras(self): self.extra['check_system'] = self.check.current_system.name if self.check.current_partition: + cp = self.check.current_partition.fullname self.extra['check_partition'] = self.check.current_partition.name + # When logging performance references, we need only those of the + # current system + self.extra['check_reference'] = jsonext.dumps( + self.check.reference.scope(cp) + ) + if self.check.current_environ: self.extra['check_environ'] = self.check.current_environ.name diff --git a/reframe/utility/__init__.py b/reframe/utility/__init__.py index 62c5352a4e..df8eb20d9c 100644 --- a/reframe/utility/__init__.py +++ b/reframe/utility/__init__.py @@ -672,6 +672,7 @@ class ScopedDict(UserDict): ``d['*:k1']`` are all equivalent. If you try to retrieve a whole scope, e.g., ``d['a:b']``, :class:`KeyError` will be raised. + For retrieving scopes, you should use the :func:`scope` function. Key deletion follows the same resolution mechanism as key retrieval, except that you are allowed to delete whole scopes. For example, ``del @@ -727,6 +728,29 @@ def update(self, other): for k, v in scope_dict.items(): self.data[scope][k] = v + def scope(self, name): + '''Retrieve a whole scope. + + :arg scope: The name of the scope to retrieve. + :returns: A dictionary with the keys that are within the requested + scope. + ''' + + ret = {} + curr_scope = name + while curr_scope is not None: + if curr_scope in self.data: + for k, v in self.data[curr_scope].items(): + if k not in ret: + ret[k] = v + + if curr_scope == self._global_scope: + curr_scope = None + else: + curr_scope = self._parent_scope(curr_scope) + + return ret + def __str__(self): # just return the internal dictionary return str(self.data) diff --git a/unittests/test_utility.py b/unittests/test_utility.py index 86388d1d3f..2350ad1762 100644 --- a/unittests/test_utility.py +++ b/unittests/test_utility.py @@ -952,6 +952,16 @@ def test_scoped_dict_key_resolution(): with pytest.raises(KeyError): scoped_dict[''] + # Scopes must be requested with scope() + assert scoped_dict.scope('a') == {'k1': 1, 'k2': 2, 'k3': 9, 'k4': 10} + assert scoped_dict.scope('a:b') == {'k1': 3, 'k2': 2, 'k3': 4, 'k4': 10} + assert scoped_dict.scope('a:b:c') == {'k1': 3, 'k2': 5, 'k3': 6, 'k4': 10} + assert scoped_dict.scope('*') == {'k1': 7, 'k3': 9, 'k4': 10} + + # This is resolved in scope 'a' + assert scoped_dict.scope('a:z') == {'k1': 1, 'k2': 2, 'k3': 9, 'k4': 10} + assert scoped_dict.scope(None) == {} + def test_scoped_dict_setitem(): scoped_dict = reframe.utility.ScopedDict({