Skip to content

Commit 095dd68

Browse files
author
Vasileios Karakasis
authored
Merge branch 'master' into doc/update-readme
2 parents 5641595 + b33ba87 commit 095dd68

File tree

6 files changed

+68
-120
lines changed

6 files changed

+68
-120
lines changed

reframe/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import os
77
import sys
88

9-
VERSION = '3.9.0'
9+
VERSION = '3.10.0-dev.0'
1010
INSTALL_PREFIX = os.path.normpath(
1111
os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
1212
)

reframe/core/fixtures.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -527,16 +527,10 @@ class FixtureSpace(namespaces.Namespace):
527527
into the target instance under the ``_rfm_fixture_registry`` attribute.
528528
'''
529529

530-
@property
531-
def local_namespace_name(self):
532-
return '_rfm_local_fixture_space'
533-
534-
@property
535-
def namespace_name(self):
536-
return '_rfm_fixture_space'
537-
538-
def __init__(self, target_cls=None, target_namespace=None):
539-
super().__init__(target_cls, target_namespace)
530+
def __init__(self, target_cls=None, illegal_names=None):
531+
super().__init__(target_cls, illegal_names,
532+
ns_name='_rfm_fixture_space',
533+
ns_local_name='_rfm_local_fixture_space')
540534

541535
# Store all fixture variant combinations to allow random access.
542536
self.__variant_combinations = tuple(
@@ -563,7 +557,7 @@ def join(self, other, cls):
563557

564558
def extend(self, cls):
565559
'''Extend the inherited fixture space with the local fixture space.'''
566-
local_fixture_space = getattr(cls, self.local_namespace_name)
560+
local_fixture_space = getattr(cls, self.local_namespace_name, False)
567561
while local_fixture_space:
568562
name, fixture = local_fixture_space.popitem()
569563
self.fixtures[name] = fixture

reframe/core/meta.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -393,18 +393,18 @@ def __init__(cls, name, bases, namespace, **kwargs):
393393
for base in (b for b in bases if hasattr(b, '_rfm_dir')):
394394
cls._rfm_dir.update(base._rfm_dir)
395395

396-
used_attribute_names = set(cls._rfm_dir)
397-
398-
# Build the var space and extend the target namespace
399-
variables.VarSpace(cls, used_attribute_names)
400-
used_attribute_names.update(cls._rfm_var_space.vars)
401-
402-
# Build the parameter space
403-
parameters.ParamSpace(cls, used_attribute_names)
404-
used_attribute_names.update(cls._rfm_param_space.params)
396+
used_attribute_names = set(cls._rfm_dir).union(
397+
{h.__name__ for h in cls._rfm_hook_registry}
398+
)
405399

406-
# Build the fixture space
407-
fixtures.FixtureSpace(cls, used_attribute_names)
400+
# Build the different global class namespaces
401+
namespace_types = (variables.VarSpace,
402+
parameters.ParamSpace,
403+
fixtures.FixtureSpace)
404+
for ns_type in namespace_types:
405+
ns = ns_type(cls, used_attribute_names)
406+
setattr(cls, ns.namespace_name, ns)
407+
used_attribute_names.update(ns.data())
408408

409409
# Update used names set with the local __dict__
410410
cls._rfm_dir.update(cls.__dict__)

reframe/core/namespaces.py

Lines changed: 28 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -68,22 +68,23 @@ def _raise_namespace_clash(self, name):
6868
def clear(self):
6969
self._namespace = {}
7070

71+
def data(self):
72+
'''Give access to the underlying namespace'''
73+
return self._namespace
74+
7175

7276
class Namespace(LocalNamespace, metaclass=abc.ABCMeta):
7377
'''Namespace of a regression test.
7478
75-
The final namespace may be built by inheriting namespaces from
76-
the base classes, and extended with the information stored in the local
77-
namespace of the target class. In this context, the target class is
78-
simply the regression test class where the namespace is to be built.
79-
80-
To allow for this inheritance and extension of the namespace, this
81-
class must define the names under which the local and final namespaces
82-
are inserted in the target classes.
79+
The final namespace may be built by inheriting namespaces from the base
80+
classes, and extending this one with the information stored in the local
81+
namespace of the target class. In this context, the target class is simply
82+
the regression test class where the namespace is to be built.
8383
84-
If a target class is provided, the constructor will attach the Namespace
85-
instance into the target class with the class attribute name as defined
86-
in ``namespace_name``.
84+
If a target class is provided, the constructor will build a Namespace
85+
instance by inheriting the namespaces found in the base classes, and
86+
extending this with the information from the local namespace of the
87+
target class.
8788
8889
Eventually, the items from a Namespace are injected as attributes of
8990
the target class instance by the :func:`inject` method, which must be
@@ -95,32 +96,15 @@ class may use more that one Namespace, which raises the need for name
9596
target class. Then, after the Namespace is built, if ``illegal_names`` is
9697
provided, a sanity check is performed, ensuring that no name clashing
9798
will occur during the target class instantiation process.
98-
'''
9999
100-
@property
101-
@abc.abstractmethod
102-
def local_namespace_name(self):
103-
'''Name of the local namespace in the target class.
104-
105-
Name under which the local namespace is stored in the
106-
:class:`reframe.core.pipeline.RegressionTest` class.
107-
'''
108-
109-
@property
110-
@abc.abstractmethod
111-
def namespace_name(self):
112-
'''Name of the namespace in the target class.
113-
114-
Name under which the namespace is stored in the
115-
:class:`reframe.core.pipeline.RegressionTest` class.
116-
'''
100+
'''
117101

118-
def __init__(self, target_cls=None, illegal_names=None):
102+
def __init__(self, target_cls=None, illegal_names=None,
103+
*, ns_name, ns_local_name):
119104
super().__init__()
105+
self._ns_name = ns_name
106+
self._ns_local_name = ns_local_name
120107
if target_cls:
121-
# Assert the Namespace can be built for the target_cls
122-
self.assert_target_cls(target_cls)
123-
124108
# Inherit Namespaces from the base clases
125109
self.inherit(target_cls)
126110

@@ -130,23 +114,21 @@ def __init__(self, target_cls=None, illegal_names=None):
130114
# Sanity checkings on the resulting Namespace
131115
self.sanity(target_cls, illegal_names)
132116

133-
# Attach the Namespace to the target class
134-
setattr(target_cls, self.namespace_name, self)
135-
136-
def assert_target_cls(self, cls):
137-
'''Assert the target class has a valid local namespace.'''
117+
@property
118+
def namespace_name(self):
119+
return self._ns_name
138120

139-
assert hasattr(cls, self.local_namespace_name)
140-
assert isinstance(getattr(cls, self.local_namespace_name),
141-
LocalNamespace)
121+
@property
122+
def local_namespace_name(self):
123+
return self._ns_local_name
142124

143125
def inherit(self, cls):
144126
'''Inherit the Namespaces from the bases.'''
145127

146-
for base in filter(lambda x: hasattr(x, self.namespace_name),
147-
cls.__bases__):
148-
assert isinstance(getattr(base, self.namespace_name), type(self))
149-
self.join(getattr(base, self.namespace_name), cls)
128+
for base in cls.__bases__:
129+
other = getattr(base, self.namespace_name, None)
130+
if isinstance(other, type(self)):
131+
self.join(other, cls)
150132

151133
@abc.abstractmethod
152134
def join(self, other, cls):
@@ -156,7 +138,7 @@ def join(self, other, cls):
156138
def extend(self, cls):
157139
'''Extend the namespace with the local namespace.'''
158140

159-
def sanity(self, cls, illegal_names=None):
141+
def sanity(self, cls, illegal_names):
160142
'''Sanity checks post-creation of the namespace.
161143
162144
By default, we make illegal to have any item in the namespace

reframe/core/parameters.py

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -61,43 +61,24 @@ def filter_params(x):
6161

6262

6363
class ParamSpace(namespaces.Namespace):
64-
''' Regression test parameter space
65-
66-
Host class for the parameter space of a regresion test. The parameter
67-
space is stored as a dictionary (self.params), where the keys are the
68-
parameter names and the values are tuples with all the available values
69-
for each parameter. The __init__ method in this class takes an optional
70-
argument (target_class), which is the regression test class where the
71-
parameter space is to e inserted as the ``_rfm_param_space`` class
72-
attribute. If no target class is provided, the parameter space is
73-
initialized as empty. After the parameter space is set, a parameter space
74-
iterator is created under self.__unique_iter, which acts as an internal
75-
control variable that tracks the usage of this parameter space. This
76-
iterator walks through all possible parameter combinations and cannot be
77-
restored after reaching exhaustion. The length of this iterator matches
78-
the value returned by the member function __len__.
79-
80-
:param target_cls: the class where the full parameter space is to be built.
81-
:param target_namespace: a reference namespace to ensure that no name
82-
clashes occur (see :class:`reframe.core.namespaces.Namespace`).
83-
84-
.. note::
85-
The __init__ method is aware of the implementation details of the
86-
regression test metaclass. This is required to retrieve the parameter
87-
spaces from the base classes, and also the local parameter space from
88-
the target class.
64+
'''Regression test parameter space
65+
66+
The parameter space is stored as a dictionary (self.params), where the
67+
keys are the parameter names and the values are tuples with all the
68+
available values for each parameter. The __init__ method in this class
69+
takes the optional argument ``target_cls``, which is the regression test
70+
class that the parameter space is being built for. If no target class is
71+
provided, the parameter space is initialized as empty.
72+
73+
All the parameter combinations are stored under ``__param_combinations``.
74+
This enables random-access to any of the available parameter combinations
75+
through the ``__getitem__`` method.
8976
'''
9077

91-
@property
92-
def local_namespace_name(self):
93-
return '_rfm_local_param_space'
94-
95-
@property
96-
def namespace_name(self):
97-
return '_rfm_param_space'
98-
99-
def __init__(self, target_cls=None, target_namespace=None):
100-
super().__init__(target_cls, target_namespace)
78+
def __init__(self, target_cls=None, illegal_names=None):
79+
super().__init__(target_cls, illegal_names,
80+
ns_name='_rfm_param_space',
81+
ns_local_name='_rfm_local_param_space')
10182

10283
# Store all param combinations to allow random access.
10384
self.__param_combinations = tuple(
@@ -142,7 +123,7 @@ def join(self, other, cls):
142123
def extend(self, cls):
143124
'''Extend the parameter space with the local parameter space.'''
144125

145-
local_param_space = getattr(cls, self.local_namespace_name)
126+
local_param_space = getattr(cls, self.local_namespace_name, dict())
146127
for name, p in local_param_space.items():
147128
try:
148129
filt_vals = p.filter_params(self.params.get(name, ()))

reframe/core/variables.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -425,30 +425,21 @@ def __ceil__(self):
425425
class VarSpace(namespaces.Namespace):
426426
'''Variable space of a regression test.
427427
428-
Store the variables of a regression test. This variable space is stored
429-
in the regression test class under the class attribute ``_rfm_var_space``.
430428
A target class can be provided to the
431429
:func:`__init__` method, which is the regression test where the
432430
VarSpace is to be built. During this call to
433431
:func:`__init__`, the VarSpace inherits all the VarSpace from the base
434432
classes of the target class. After this, the VarSpace is extended with
435-
the information from the local variable space, which is stored under the
436-
target class' attribute ``_rfm_local_var_space``. If no target class is
433+
the information from the local variable space. If no target class is
437434
provided, the VarSpace is simply initialized as empty.
438435
'''
439436

440-
@property
441-
def local_namespace_name(self):
442-
return '_rfm_local_var_space'
443-
444-
@property
445-
def namespace_name(self):
446-
return '_rfm_var_space'
447-
448437
def __init__(self, target_cls=None, illegal_names=None):
449438
# Set to register the variables already injected in the class
450439
self._injected_vars = set()
451-
super().__init__(target_cls, illegal_names)
440+
super().__init__(target_cls, illegal_names,
441+
ns_name='_rfm_var_space',
442+
ns_local_name='_rfm_local_var_space')
452443

453444
def join(self, other, cls):
454445
'''Join an existing VarSpace into the current one.
@@ -482,7 +473,7 @@ def extend(self, cls):
482473
of these actions on the same var for the same local var space
483474
is disallowed.
484475
'''
485-
local_varspace = getattr(cls, self.local_namespace_name)
476+
local_varspace = getattr(cls, self.local_namespace_name, False)
486477
while local_varspace:
487478
key, var = local_varspace.popitem()
488479
if isinstance(var, TestVar):
@@ -513,7 +504,7 @@ def extend(self, cls):
513504
for key in _assigned_vars:
514505
delattr(cls, key)
515506

516-
def sanity(self, cls, illegal_names=None):
507+
def sanity(self, cls, illegal_names):
517508
'''Sanity checks post-creation of the var namespace.
518509
519510
By default, we make illegal to have any item in the namespace

0 commit comments

Comments
 (0)