Skip to content

Commit 590873f

Browse files
authored
Merge branch 'master' into tutorials-docker
2 parents aa31af9 + 8a9ceed commit 590873f

25 files changed

+246
-216
lines changed

cscs-checks/prgenv/hip/build_hip.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class BuildHip(rfm.RegressionTest):
2121
valid_prog_environs = ['PrgEnv-gnu']
2222
sourcesdir = 'https://github.com/ROCm-Developer-Tools/HIP.git'
2323
build_system = 'CMake'
24+
prebuild_cmds = ['git checkout main']
2425
postbuild_cmds = ['make install']
2526
executable = f'{hip_path}/bin/hipcc'
2627
executable_opts = ['--version']
@@ -38,9 +39,9 @@ def set_compile_options(self):
3839
f'-DHIP_PLATFORM={self.hip_platform}',
3940
]
4041

41-
@run_before('sanity')
42+
@sanity_function
4243
def set_sanity_patterns(self):
43-
self.sanity_patterns = sn.assert_found(r'nvcc:\s+NVIDIA', self.stdout)
44+
return sn.assert_found(r'nvcc:\s+NVIDIA', self.stdout)
4445

4546

4647
@rfm.simple_test
@@ -75,6 +76,6 @@ def set_env(self):
7576
self.variables = {'HIP_PATH': f'{self.hip_path}'}
7677
self.build_system.cxx = os.path.join(self.hip_path, 'bin', 'hipcc')
7778

78-
@run_before('sanity')
79+
@sanity_function
7980
def set_sanity(self):
80-
self.sanity_patterns = sn.assert_found(r'HelloWorld', self.stdout)
81+
return sn.assert_found(r'HelloWorld', self.stdout)

docs/config_reference.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,6 +1280,10 @@ General Configuration
12801280

12811281
Ignore test name conflicts when loading tests.
12821282

1283+
.. deprecated:: 3.8.0
1284+
This option will be removed in a future version.
1285+
1286+
12831287

12841288
.. js:attribute:: .general[].trap_job_errors
12851289

docs/manpage.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ This is something that writers of regression tests should bear in mind.
5353

5454
This option can also be set using the :envvar:`RFM_IGNORE_CHECK_CONFLICTS` environment variable or the :js:attr:`ignore_check_conflicts` general configuration parameter.
5555

56+
.. deprecated:: 3.8.0
57+
This option will be removed in a future version.
58+
5659

5760
--------------
5861
Test filtering
@@ -790,6 +793,9 @@ Here is an alphabetical list of the environment variables recognized by ReFrame:
790793
Associated configuration parameter :js:attr:`ignore_check_conflicts` general configuration parameter
791794
================================== ==================
792795

796+
.. deprecated:: 3.8.0
797+
This environment variable will be removed in a future version.
798+
793799

794800
.. envvar:: RFM_TRAP_JOB_ERRORS
795801

docs/tutorial_tips_tricks.rst

Lines changed: 36 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ Debugging
1111
---------
1212

1313
ReFrame tests are Python classes inside Python source files, so the usual debugging techniques for Python apply, but the ReFrame frontend will filter some errors and stack traces by default in order to keep the output clean.
14-
ReFrame test files are imported, so any error that appears during import time will cause the test loading process to fail and print a stack trace pointing to the offending line.
14+
Generally, ReFrame will not print the full stack trace for user programming errors and will not block the test loading process.
15+
If a test has errors and cannot be loaded, an error message will be printed and the loading of the remaining tests will continue.
1516
In the following, we have inserted a small typo in the ``hello2.py`` tutorial example:
1617

1718
.. code:: bash
@@ -20,41 +21,24 @@ In the following, we have inserted a small typo in the ``hello2.py`` tutorial ex
2021
2122
.. code-block:: none
2223
23-
./bin/reframe: name error: name 'rm' is not defined
24-
./bin/reframe: Traceback (most recent call last):
25-
File "/Users/karakasv/Repositories/reframe/reframe/frontend/cli.py", line 668, in main
26-
checks_found = loader.load_all()
27-
File "/Users/karakasv/Repositories/reframe/reframe/frontend/loader.py", line 204, in load_all
28-
checks.extend(self.load_from_dir(d, self._recurse))
29-
File "/Users/karakasv/Repositories/reframe/reframe/frontend/loader.py", line 189, in load_from_dir
30-
checks.extend(self.load_from_file(entry.path))
31-
File "/Users/karakasv/Repositories/reframe/reframe/frontend/loader.py", line 174, in load_from_file
32-
return self.load_from_module(util.import_module_from_file(filename))
33-
File "/Users/karakasv/Repositories/reframe/reframe/utility/__init__.py", line 96, in import_module_from_file
34-
return importlib.import_module(module_name)
35-
File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/__init__.py", line 127, in import_module
36-
return _bootstrap._gcd_import(name[level:], package, level)
37-
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
38-
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
39-
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
40-
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
41-
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
42-
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
43-
File "/Users/karakasv/Repositories/reframe/tutorials/basics/hello/hello2.py", line 10, in <module>
44-
@rm.parameterized_test(['c'], ['cpp'])
45-
NameError: name 'rm' is not defined
46-
24+
./bin/reframe: skipping test file '/Users/user/Repositories/reframe/tutorials/basics/hello/hello2.py': name error: tutorials/basics/hello/hello2.py:17: name 's' is not defined
25+
sanity_patterns = s.assert_found(r'Hello, World\!', 'hello.out')
26+
(rerun with '-v' for more information)
27+
[List of matched checks]
28+
- HelloTest (found in '/Users/user/Repositories/reframe/tutorials/basics/hello/hello1.py')
29+
Found 1 check(s)
4730
48-
However, if there is a Python error inside your test's constructor, ReFrame will issue a warning and keep on loading and initializing the rest of the tests.
31+
Notice how ReFrame prints also the source code line that caused the error.
32+
This is not always the case, however.
33+
ReFrame cannot always track a user error back to its source and this is particularly true for the ReFrame-specific syntactic elements, such as the class `builtins <regression_test_api.html#builtins>`__.
34+
In such cases, ReFrame will just print the error message but not the source code context.
35+
In the following example, we introduce a typo in the argument of the :obj:`@run_before` decorator:
4936

5037
.. code-block:: none
5138
52-
./bin/reframe: skipping test due to errors: HelloMultiLangTest: use `-v' for more information
53-
FILE: /Users/karakasv/Repositories/reframe/tutorials/basics/hello/hello2.py:13
54-
./bin/reframe: skipping test due to errors: HelloMultiLangTest: use `-v' for more information
55-
FILE: /Users/karakasv/Repositories/reframe/tutorials/basics/hello/hello2.py:13
39+
./bin/reframe: skipping test file '/Users/user/Repositories/reframe/tutorials/basics/hello/hello2.py': reframe syntax error: invalid pipeline stage specified: 'compil' (rerun with '-v' for more information)
5640
[List of matched checks]
57-
- HelloTest (found in '/Users/karakasv/Repositories/reframe/tutorials/basics/hello/hello1.py')
41+
- HelloTest (found in '/Users/user/Repositories/reframe/tutorials/basics/hello/hello1.py')
5842
Found 1 check(s)
5943
6044
@@ -66,27 +50,27 @@ As suggested by the warning message, passing :option:`-v` will give you the stac
6650
6751
.. code-block:: none
6852
69-
./bin/reframe: skipping test due to errors: HelloMultiLangTest: use `-v' for more information
70-
FILE: /Users/karakasv/Repositories/reframe/tutorials/basics/hello/hello2.py:13
71-
Traceback (most recent call last):
72-
File "/Users/karakasv/Repositories/reframe/reframe/core/decorators.py", line 49, in _instantiate_all
73-
ret.append(_instantiate(cls, args))
74-
File "/Users/karakasv/Repositories/reframe/reframe/core/decorators.py", line 32, in _instantiate
75-
return cls(*args)
76-
File "/Users/karakasv/Repositories/reframe/tutorials/basics/hello/hello2.py", line 13, in __init__
77-
foo
78-
NameError: name 'foo' is not defined
79-
80-
./bin/reframe: skipping test due to errors: HelloMultiLangTest: use `-v' for more information
81-
FILE: /Users/karakasv/Repositories/reframe/tutorials/basics/hello/hello2.py:13
53+
./bin/reframe: skipping test file '/Users/user/Repositories/reframe/tutorials/basics/hello/hello2.py': name error: tutorials/basics/hello/hello2.py:17: name 's' is not defined
54+
sanity_patterns = s.assert_found(r'Hello, World\!', 'hello.out')
55+
(rerun with '-v' for more information)
8256
Traceback (most recent call last):
83-
File "/Users/karakasv/Repositories/reframe/reframe/core/decorators.py", line 49, in _instantiate_all
84-
ret.append(_instantiate(cls, args))
85-
File "/Users/karakasv/Repositories/reframe/reframe/core/decorators.py", line 32, in _instantiate
86-
return cls(*args)
87-
File "/Users/karakasv/Repositories/reframe/tutorials/basics/hello/hello2.py", line 13, in __init__
88-
foo
89-
NameError: name 'foo' is not defined
57+
File "/Users/user/Repositories/reframe/reframe/frontend/loader.py", line 172, in load_from_file
58+
util.import_module_from_file(filename, force)
59+
File "/Users/user/Repositories/reframe/reframe/utility/__init__.py", line 101, in import_module_from_file
60+
return importlib.import_module(module_name)
61+
File "/usr/local/Cellar/[email protected]/3.9.1_6/Frameworks/Python.framework/Versions/3.9/lib/python3.9/importlib/__init__.py", line 127, in import_module
62+
return _bootstrap._gcd_import(name[level:], package, level)
63+
File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
64+
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
65+
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
66+
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
67+
File "<frozen importlib._bootstrap_external>", line 790, in exec_module
68+
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
69+
File "/Users/user/Repositories/reframe/tutorials/basics/hello/hello2.py", line 11, in <module>
70+
class HelloMultiLangTest(rfm.RegressionTest):
71+
File "/Users/user/Repositories/reframe/tutorials/basics/hello/hello2.py", line 17, in HelloMultiLangTest
72+
sanity_patterns = s.assert_found(r'Hello, World\!', 'hello.out')
73+
NameError: name 's' is not defined
9074
9175
Loaded 1 test(s)
9276
Generated 1 test case(s)
@@ -95,9 +79,8 @@ As suggested by the warning message, passing :option:`-v` will give you the stac
9579
Filtering test cases(s) by other attributes: 1 remaining
9680
Final number of test cases: 1
9781
[List of matched checks]
98-
- HelloTest (found in '/Users/karakasv/Repositories/reframe/tutorials/basics/hello/hello1.py')
82+
- HelloTest (found in '/Users/user/Repositories/reframe/tutorials/basics/hello/hello1.py')
9983
Found 1 check(s)
100-
Log file(s) saved in: '/var/folders/h7/k7cgrdl13r996m4dmsvjq7v80000gp/T/rfm-ckymcl44.log'
10184
10285
10386
.. tip::

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.8.0-dev.1'
9+
VERSION = '3.8.0-dev.2'
1010
INSTALL_PREFIX = os.path.normpath(
1111
os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
1212
)

reframe/core/decorators.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@
2121
import reframe.utility.osext as osext
2222
import reframe.core.warnings as warn
2323
import reframe.core.hooks as hooks
24-
from reframe.core.exceptions import (ReframeSyntaxError,
25-
SkipTestError,
26-
user_frame)
24+
from reframe.core.exceptions import ReframeSyntaxError, SkipTestError, what
2725
from reframe.core.logging import getlogger
2826
from reframe.core.pipeline import RegressionTest
2927
from reframe.utility.versioning import VersionValidator
@@ -51,22 +49,18 @@ def _instantiate_all():
5149
try:
5250
if cls in mod.__rfm_skip_tests:
5351
continue
54-
5552
except AttributeError:
5653
mod.__rfm_skip_tests = set()
5754

5855
try:
5956
ret.append(_instantiate(cls, args))
6057
except SkipTestError as e:
61-
getlogger().warning(f'skipping test {cls.__name__!r}: {e}')
58+
getlogger().warning(f'skipping test {cls.__qualname__!r}: {e}')
6259
except Exception:
63-
frame = user_frame(*sys.exc_info())
64-
filename = frame.filename if frame else 'n/a'
65-
lineno = frame.lineno if frame else 'n/a'
60+
exc_info = sys.exc_info()
6661
getlogger().warning(
67-
f"skipping test {cls.__name__!r} due to errors: "
68-
f"use `-v' for more information\n"
69-
f" FILE: {filename}:{lineno}"
62+
f"skipping test {cls.__qualname__!r}: {what(*exc_info)} "
63+
f"(rerun with '-v' for more information)"
7064
)
7165
getlogger().verbose(traceback.format_exc())
7266

@@ -88,8 +82,11 @@ def _validate_test(cls):
8882
'subclass of RegressionTest')
8983

9084
if (cls.is_abstract()):
91-
raise ValueError(f'decorated test ({cls.__qualname__!r}) has one or '
92-
f'more undefined parameters')
85+
getlogger().warning(
86+
f'skipping test {cls.__qualname__!r}: '
87+
f'test has one or more undefined parameters'
88+
)
89+
return False
9390

9491
conditions = [VersionValidator(v) for v in cls._rfm_required_version]
9592
if (cls._rfm_required_version and
@@ -151,7 +148,7 @@ def parameterized_test(*inst):
151148
def _do_register(cls):
152149
if _validate_test(cls):
153150
if not cls.param_space.is_empty():
154-
raise ValueError(
151+
raise ReframeSyntaxError(
155152
f'{cls.__qualname__!r} is already a parameterized test'
156153
)
157154

@@ -204,7 +201,7 @@ def required_version(*versions):
204201
)
205202

206203
if not versions:
207-
raise ValueError('no versions specified')
204+
raise ReframeSyntaxError('no versions specified')
208205

209206
conditions = [VersionValidator(v) for v in versions]
210207

@@ -246,10 +243,11 @@ def run_before(stage):
246243
from_version='3.7.0'
247244
)
248245
if stage not in _USER_PIPELINE_STAGES:
249-
raise ValueError(f'invalid pipeline stage specified: {stage!r}')
246+
raise ReframeSyntaxError(
247+
f'invalid pipeline stage specified: {stage!r}')
250248

251249
if stage == 'init':
252-
raise ValueError('pre-init hooks are not allowed')
250+
raise ReframeSyntaxError('pre-init hooks are not allowed')
253251

254252
return hooks.attach_to('pre_' + stage)
255253

@@ -268,7 +266,8 @@ def run_after(stage):
268266
from_version='3.7.0'
269267
)
270268
if stage not in _USER_PIPELINE_STAGES:
271-
raise ValueError(f'invalid pipeline stage specified: {stage!r}')
269+
raise ReframeSyntaxError(
270+
f'invalid pipeline stage specified: {stage!r}')
272271

273272
# Map user stage names to the actual pipeline functions if needed
274273
if stage == 'init':

reframe/core/exceptions.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,22 @@ def is_exit_request(exc_type, exc_value, tb):
320320
FailureLimitError))
321321

322322

323+
def is_user_error(exc_type, exc_value, tb):
324+
'''Check if error is a user programming error.
325+
326+
A user error is any of :py:class:`AttributeError`, :py:class:`NameError`,
327+
:py:class:`TypeError` or :py:class:`ValueError` and the exception is
328+
thrown from user context.
329+
'''
330+
331+
frame = user_frame(exc_type, exc_value, tb)
332+
if frame is None:
333+
return False
334+
335+
return isinstance(exc_value,
336+
(AttributeError, NameError, TypeError, ValueError))
337+
338+
323339
def is_severe(exc_type, exc_value, tb):
324340
'''Check if exception is a severe one.'''
325341

@@ -330,14 +346,8 @@ def is_severe(exc_type, exc_value, tb):
330346
if isinstance(exc_value, soft_errors):
331347
return False
332348

333-
# Treat specially type and value errors
334-
type_error = isinstance(exc_value, TypeError)
335-
value_error = isinstance(exc_value, ValueError)
336-
frame = user_frame(exc_type, exc_value, tb)
337-
if (type_error or value_error) and frame is not None:
338-
return False
339-
340-
return True
349+
# User errors are treated as soft
350+
return not is_user_error(exc_type, exc_value, tb)
341351

342352

343353
def what(exc_type, exc_value, tb):
@@ -349,14 +359,12 @@ def what(exc_type, exc_value, tb):
349359
reason = utility.decamelize(exc_type.__name__, ' ')
350360

351361
# We need frame information for user type and value errors
352-
frame = user_frame(exc_type, exc_value, tb)
353-
user_type_error = isinstance(exc_value, TypeError) and frame
354-
user_value_error = isinstance(exc_value, ValueError) and frame
355362
if isinstance(exc_value, KeyboardInterrupt):
356363
reason = 'cancelled by user'
357364
elif isinstance(exc_value, AbortTaskError):
358365
reason = f'aborted due to {type(exc_value.__cause__).__name__}'
359-
elif user_type_error or user_value_error:
366+
elif is_user_error(exc_type, exc_value, tb):
367+
frame = user_frame(exc_type, exc_value, tb)
360368
relpath = os.path.relpath(frame.filename)
361369
source = ''.join(frame.code_context)
362370
reason += f': {relpath}:{frame.lineno}: {exc_value}\n{source}'

reframe/core/meta.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def __setitem__(self, key, value):
5050
self._namespace.pop(key, None)
5151

5252
elif key in self['_rfm_local_param_space']:
53-
raise ValueError(
53+
raise ReframeSyntaxError(
5454
f'cannot override parameter {key!r}'
5555
)
5656
else:
@@ -76,7 +76,7 @@ def __getitem__(self, key):
7676
except KeyError:
7777
# Handle parameter access
7878
if key in self['_rfm_local_param_space']:
79-
raise ValueError(
79+
raise ReframeSyntaxError(
8080
'accessing a test parameter from the class '
8181
'body is disallowed'
8282
) from None
@@ -426,7 +426,7 @@ class attribute. This behavior does not apply when the assigned value
426426
return
427427
elif not var_space[name].field is value:
428428
desc = '.'.join([cls.__qualname__, name])
429-
raise ValueError(
429+
raise ReframeSyntaxError(
430430
f'cannot override variable descriptor {desc!r}'
431431
)
432432

@@ -437,7 +437,7 @@ class attribute. This behavior does not apply when the assigned value
437437
try:
438438
param_space = super().__getattribute__('_rfm_param_space')
439439
if name in param_space.params:
440-
raise ValueError(f'cannot override parameter {name!r}')
440+
raise ReframeSyntaxError(f'cannot override parameter {name!r}')
441441

442442
except AttributeError:
443443
pass

0 commit comments

Comments
 (0)