From 6f8a3fd273c258b9b41af5f39ef2a934f2e7f641 Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Thu, 14 Nov 2019 21:18:06 +0100 Subject: [PATCH 1/3] Refactor usage of make_deferrable() and evaluate() - `make_deferrable()` is renamed to `defer()` and is moved inside `reframe.utility.sanity`. - `evaluate()` is moved inside `reframe.utility.sanity` - The old functions are deprecated. - Functions are now publicly visible and documentation is updated. - Tests that were making use of them are adapted. --- cscs-checks/cuda/multi_gpu.py | 11 +- docs/deferrables.rst | 22 +- reframe/core/deferrable.py | 13 +- reframe/core/pipeline.py | 21 +- reframe/utility/sanity.py | 26 +- .../resources/checks_unlisted/deps_complex.py | 3 +- unittests/test_deferrable.py | 115 ++++---- unittests/test_pipeline.py | 6 +- unittests/test_policies.py | 2 +- unittests/test_sanity_functions.py | 245 +++++++++--------- 10 files changed, 242 insertions(+), 222 deletions(-) diff --git a/cscs-checks/cuda/multi_gpu.py b/cscs-checks/cuda/multi_gpu.py index 56a775fde4..f1834bf41b 100644 --- a/cscs-checks/cuda/multi_gpu.py +++ b/cscs-checks/cuda/multi_gpu.py @@ -2,7 +2,6 @@ import reframe.utility.sanity as sn import reframe as rfm -from reframe.core.deferrable import evaluate @rfm.required_version('>=2.16-dev0') @@ -90,7 +89,7 @@ def do_sanity_check(self): self.stdout, 1 )) - evaluate(sn.assert_eq( + sn.evaluate(sn.assert_eq( self.job.num_tasks, len(devices_found), msg='requested {0} node(s), got {1} (nodelist: %s)' % ','.join(sorted(devices_found)))) @@ -100,9 +99,11 @@ def do_sanity_check(self): self.stdout, 1 )) - evaluate(sn.assert_eq(devices_found, good_nodes, - msg='check failed on the following node(s): %s' % - ','.join(sorted(devices_found - good_nodes)))) + sn.evaluate(sn.assert_eq( + devices_found, good_nodes, + msg='check failed on the following node(s): %s' % + ','.join(sorted(devices_found - good_nodes))) + ) # Sanity is fine, fill in the perf. patterns based on the exact node id for nodename in devices_found: diff --git a/docs/deferrables.rst b/docs/deferrables.rst index 1f46e4995b..57f3828051 100644 --- a/docs/deferrables.rst +++ b/docs/deferrables.rst @@ -31,15 +31,15 @@ If you try to call ``foo()``, its code will not execute: Instead, a special object is returned that represents the function whose execution is deferred. Notice the more general *deferred expression* name of this object. We shall see later on why this name is used. -In order to explicitly trigger the execution of ``foo()``, you have to call :func:`evaluate ` on it: +In order to explicitly trigger the execution of ``foo()``, you have to call :func:`evaluate ` on it: .. code-block:: pycon - >>> from reframe.core.deferrable import evaluate + >>> from reframe.utility.sanity import evaluate >>> evaluate(foo()) hello -If the argument passed to :func:`evaluate ` is not a deferred expression, it will be simply returned as is. +If the argument passed to :func:`evaluate ` is not a deferred expression, it will be simply returned as is. Deferrable functions may also be combined as we do with normal functions. Let's extend our example with ``foo()`` accepting an argument and printing it: @@ -186,7 +186,7 @@ In summary deferrable functions have the following characteristics: * You can make any function deferrable by preceding it with the :func:`@sanity_function ` or the :func:`@deferrable ` decorator. * When you call a deferrable function, its body is not executed but its arguments are *captured* and an object representing the deferred function is returned. -* You can execute the body of a deferrable function at any later point by calling :func:`evaluate ` on the deferred expression object that it has been returned by the call to the deferred function. +* You can execute the body of a deferrable function at any later point by calling :func:`evaluate ` on the deferred expression object that it has been returned by the call to the deferred function. * Deferred functions can accept other deferred expressions as arguments and may also return a deferred expression. * When you evaluate a deferrable function, any other deferrable function down the call tree will also be evaluated. * You can include a call to a deferrable function in any Python expression and the result will be another deferred expression. @@ -195,7 +195,7 @@ How a Deferred Expression Is Evaluated? --------------------------------------- As discussed before, you can create a new deferred expression by calling a function whose definition is decorated by the ``@sanity_function`` or ``@deferrable`` decorator or by including an already deferred expression in any sort of arithmetic operation. -When you call :func:`evaluate ` on a deferred expression, you trigger the evaluation of the whole subexpression tree. +When you call :func:`evaluate ` on a deferred expression, you trigger the evaluation of the whole subexpression tree. Here is how the evaluation process evolves: A deferred expression object is merely a placeholder of the target function and its arguments at the moment you call it. @@ -244,7 +244,7 @@ The following figure shows how the evaluation evolves for this particular exampl Implicit evaluation of a deferred expression -------------------------------------------- -Although you can trigger the evaluation of a deferred expression at any time by calling :func:`evaluate `, there are some cases where the evaluation is triggered implicitly: +Although you can trigger the evaluation of a deferred expression at any time by calling :func:`evaluate `, there are some cases where the evaluation is triggered implicitly: * When you try to get the truthy value of a deferred expression by calling :func:`bool ` on it. This happens for example when you include a deferred expression in an :keyword:`if` statement or as an argument to the :keyword:`and`, :keyword:`or`, :keyword:`not` and :keyword:`in` (:func:`__contains__ `) operators. @@ -262,8 +262,8 @@ Although you can trigger the evaluation of a deferred expression at any time by .. code-block:: pycon - >>> from reframe.core.deferrable import make_deferrable - >>> l = make_deferrable([1, 2, 3]) + >>> from reframe.utility.sanity import defer + >>> l = defer([1, 2, 3]) >>> l >>> evaluate(l) @@ -273,7 +273,7 @@ Although you can trigger the evaluation of a deferred expression at any time by >>> 3 in l True - The :func:`make_deferrable ` is simply a deferrable version of the identity function (a function that simply returns its argument). + The :func:`defer ` is simply a deferrable version of the identity function (a function that simply returns its argument). As expected, ``l`` is a deferred expression that evaluates to the ``[1, 2, 3]`` list. When we apply the :keyword:`in` operator, the deferred expression is immediately evaluated. .. note:: Python expands this expression into ``bool(l.__contains__(3))``. @@ -328,7 +328,7 @@ You can call other deferrable functions from within a deferrable function. Thanks to the implicit evaluation rules as well as the fact that the return value of a deferrable function is also evaluated if it is a deferred expression, you can write a deferrable function without caring much about whether the functions you call are themselves deferrable or not. However, you should be aware of passing mutable objects to deferrable functions. If these objects happen to change between the actual call and the implicit evaluation of the deferrable function, you might run into surprises. -In any case, if you want the immediate evaluation of a deferrable function or expression, you can always do that by calling :func:`evaluate ` on it. +In any case, if you want the immediate evaluation of a deferrable function or expression, you can always do that by calling :func:`evaluate ` on it. The following example demonstrates two different ways writing a deferrable function that checks the average of the elements of an iterable: @@ -422,7 +422,7 @@ Notice that you cannot include generators in expressions, whereas you can genera * Generators are iterator objects, while deferred expressions are not. As a result, you can trigger the evaluation of a generator expression using the :func:`next ` builtin function. - For a deferred expression you should use :func:`evaluate ` instead. + For a deferred expression you should use :func:`evaluate ` instead. * A generator object is iterable, whereas a deferrable object will be iterable if and only if the result of its evaluation is iterable. diff --git a/reframe/core/deferrable.py b/reframe/core/deferrable.py index edbcb0fefc..eed95f6c1b 100644 --- a/reframe/core/deferrable.py +++ b/reframe/core/deferrable.py @@ -1,8 +1,8 @@ -'''Provides utilities for deferred execution of expressions.''' - import builtins import functools +from reframe.core.exceptions import user_deprecation_warning + def deferrable(func): '''Function decorator for converting a function to a deferred @@ -335,13 +335,10 @@ def __invert__(a): return ~a -# Utility functions - def evaluate(expr): - '''Evaluate a deferred expression. + user_deprecation_warning('evaluate() is deprecated: ' + 'please use reframe.utility.sanity.evaluate') - If `expr` is not a deferred expression, it will returned as is. - ''' if isinstance(expr, _DeferredExpression): return expr.evaluate() else: @@ -350,4 +347,6 @@ def evaluate(expr): @deferrable def make_deferrable(a): + user_deprecation_warning('make_deferrable() is deprecated: ' + 'please use reframe.utility.sanity.defer') return a diff --git a/reframe/core/pipeline.py b/reframe/core/pipeline.py index d6920152b1..4b5eb65037 100644 --- a/reframe/core/pipeline.py +++ b/reframe/core/pipeline.py @@ -19,10 +19,11 @@ import reframe.core.runtime as rt import reframe.utility as util import reframe.utility.os_ext as os_ext +import reframe.utility.sanity as sn import reframe.utility.typecheck as typ from reframe.core.buildsystems import BuildSystemField from reframe.core.containers import ContainerPlatform, ContainerPlatformField -from reframe.core.deferrable import deferrable, _DeferredExpression, evaluate +from reframe.core.deferrable import _DeferredExpression from reframe.core.exceptions import (BuildError, DependencyError, PipelineError, SanityError, PerformanceError) @@ -812,7 +813,7 @@ def outputdir(self): return self._outputdir @property - @deferrable + @sn.sanity_function def stdout(self): '''The name of the file containing the standard output of the test. @@ -826,7 +827,7 @@ def stdout(self): return self._job.stdout @property - @deferrable + @sn.sanity_function def stderr(self): '''The name of the file containing the standard error of the test. @@ -840,12 +841,12 @@ def stderr(self): return self._job.stderr @property - @deferrable + @sn.sanity_function def build_stdout(self): return self._build_job.stdout @property - @deferrable + @sn.sanity_function def build_stderr(self): return self._build_job.stderr @@ -1222,7 +1223,7 @@ def check_sanity(self): raise SanityError('sanity_patterns not set') with os_ext.change_dir(self._stagedir): - success = evaluate(self.sanity_patterns) + success = sn.evaluate(self.sanity_patterns) if not success: raise SanityError() @@ -1273,7 +1274,7 @@ def check_performance(self): # check them against the reference. This way we always log them # even if the don't meet the reference. for tag, expr in self.perf_patterns.items(): - value = evaluate(expr) + value = sn.evaluate(expr) key = '%s:%s' % (self._current_partition.fullname, tag) if key not in self.reference: raise SanityError( @@ -1288,7 +1289,7 @@ def check_performance(self): val, ref, low_thres, high_thres, *_ = values tag = key.split(':')[-1] try: - evaluate( + sn.evaluate( assert_reference( val, ref, low_thres, high_thres, msg=('failed to meet reference: %s={0}, ' @@ -1450,12 +1451,12 @@ def setup(self, partition, environ, **job_opts): self._setup_paths() @property - @deferrable + @sn.sanity_function def stdout(self): return self._build_job.stdout @property - @deferrable + @sn.sanity_function def stderr(self): return self._build_job.stderr diff --git a/reframe/utility/sanity.py b/reframe/utility/sanity.py index 21a7a16498..b7252c95db 100644 --- a/reframe/utility/sanity.py +++ b/reframe/utility/sanity.py @@ -64,7 +64,7 @@ import re import reframe.utility as util -from reframe.core.deferrable import deferrable, evaluate +from reframe.core.deferrable import deferrable, _DeferredExpression from reframe.core.exceptions import SanityError @@ -94,7 +94,7 @@ def myfunc(*args): This decorator is an alias to the :func:`reframe.core.deferrable.deferrable` decorator. -The following function definition is equivalent to the above: +> 3) self.assertEqual(3 >> 8, 3 >> a) def test_and(self): - a = make_deferrable(7) + a = sn.defer(7) self.assertEqual(2, a & 2) self.assertEqual(2, 2 & a) def test_xor(self): - a = make_deferrable(7) + a = sn.defer(7) self.assertEqual(0, a ^ 7) self.assertEqual(0, 7 ^ a) def test_or(self): - a = make_deferrable(2) + a = sn.defer(2) self.assertEqual(7, a | 5) self.assertEqual(7, 5 | a) def test_expr_chaining(self): - a = make_deferrable(2) + a = sn.defer(2) self.assertEqual(64, a**((a + 1) * a)) def test_neg(self): - a = make_deferrable(3) + a = sn.defer(3) self.assertEqual(-3, -a) def test_pos(self): - a = make_deferrable(3) + a = sn.defer(3) self.assertEqual(+3, +a) def test_abs(self): - a = make_deferrable(-3) + a = sn.defer(-3) self.assertEqual(3, abs(a)) def test_invert(self): - a = make_deferrable(3) + a = sn.defer(3) self.assertEqual(~3, ~a) def test_iadd(self): v = V(1) - dv = make_deferrable(v) + dv = sn.defer(v) dv += V(3) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(4, v._value) def test_isub(self): v = V(1) - dv = make_deferrable(v) + dv = sn.defer(v) dv -= V(3) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(-2, v._value) def test_imul(self): v = V(1) - dv = make_deferrable(v) + dv = sn.defer(v) dv *= V(3) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(3, v._value) def test_itruediv(self): v = V(3) - dv = make_deferrable(v) + dv = sn.defer(v) dv /= V(2) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(1.5, v._value) def test_ifloordiv(self): v = V(3) - dv = make_deferrable(v) + dv = sn.defer(v) dv //= V(2) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(1, v._value) def test_imod(self): v = V(3) - dv = make_deferrable(v) + dv = sn.defer(v) dv %= V(2) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(1, v._value) def test_ipow(self): v = V(3) - dv = make_deferrable(v) + dv = sn.defer(v) dv **= V(2) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(9, v._value) def test_ilshift(self): v = V(1) - dv = make_deferrable(v) + dv = sn.defer(v) dv <<= V(2) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(4, v._value) def test_irshift(self): v = V(8) - dv = make_deferrable(v) + dv = sn.defer(v) dv >>= V(3) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(1, v._value) def test_iand(self): v = V(7) - dv = make_deferrable(v) + dv = sn.defer(v) dv &= V(2) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(2, v._value) def test_ixor(self): v = V(7) - dv = make_deferrable(v) + dv = sn.defer(v) dv ^= V(7) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(0, v._value) def test_ior(self): v = V(2) - dv = make_deferrable(v) + dv = sn.defer(v) dv |= V(5) - evaluate(dv) + sn.evaluate(dv) self.assertEqual(7, v._value) diff --git a/unittests/test_pipeline.py b/unittests/test_pipeline.py index 204f5eb9d1..0df500a19b 100644 --- a/unittests/test_pipeline.py +++ b/unittests/test_pipeline.py @@ -72,10 +72,8 @@ def replace_prefix(self, filename, new_prefix): return os.path.join(new_prefix, basename) def keep_files_list(self, test, compile_only=False): - from reframe.core.deferrable import evaluate - - ret = [self.replace_prefix(evaluate(test.stdout), test.outputdir), - self.replace_prefix(evaluate(test.stderr), test.outputdir)] + ret = [self.replace_prefix(sn.evaluate(test.stdout), test.outputdir), + self.replace_prefix(sn.evaluate(test.stderr), test.outputdir)] if not compile_only: ret.append(self.replace_prefix(test.job.script_filename, diff --git a/unittests/test_policies.py b/unittests/test_policies.py index 14a5cb1ced..7c53000832 100644 --- a/unittests/test_policies.py +++ b/unittests/test_policies.py @@ -289,7 +289,7 @@ def set_max_jobs(self, value): def read_timestamps(self, tasks): '''Read the timestamps and sort them to permit simple concurrency tests.''' - from reframe.core.deferrable import evaluate + from reframe.utility.sanity import evaluate self.begin_stamps = [] self.end_stamps = [] diff --git a/unittests/test_sanity_functions.py b/unittests/test_sanity_functions.py index 45a5f89cd3..ab2590dc06 100644 --- a/unittests/test_sanity_functions.py +++ b/unittests/test_sanity_functions.py @@ -4,7 +4,6 @@ from tempfile import NamedTemporaryFile import reframe.utility.sanity as sn -from reframe.core.deferrable import evaluate, make_deferrable from reframe.core.exceptions import SanityError from unittests.fixtures import TEST_RESOURCES_CHECKS @@ -32,7 +31,7 @@ def test_abs(self): self.assertEqual(1.0, sn.abs(1.0)) self.assertEqual(0.0, sn.abs(0.0)) self.assertEqual(1.0, sn.abs(-1.0)) - self.assertEqual(2.0, sn.abs(make_deferrable(-2.0))) + self.assertEqual(2.0, sn.abs(sn.defer(-2.0))) def test_and(self): expr = sn.and_(self.a, self.b) @@ -71,19 +70,19 @@ def test_any(self): self.assertFalse(expr) def test_enumerate(self): - de = sn.enumerate(make_deferrable([1, 2]), start=1) + de = sn.enumerate(sn.defer([1, 2]), start=1) for i, e in de: self.assertEqual(i, e) def test_filter(self): df = sn.filter(lambda x: x if x % 2 else None, - make_deferrable([1, 2, 3, 4, 5])) + sn.defer([1, 2, 3, 4, 5])) for i, x in sn.enumerate(df, start=1): self.assertEqual(2*i - 1, x) # Alternative testing - self.assertEqual([1, 3, 5], list(evaluate(df))) + self.assertEqual([1, 3, 5], list(sn.evaluate(df))) def test_hasattr(self): e = sn.hasattr(self, '_c') @@ -94,7 +93,7 @@ def test_hasattr(self): def test_len(self): l = [1, 2] - dl = make_deferrable(l) + dl = sn.defer(l) self.assertEqual(2, sn.len(dl)) l.append(3) @@ -107,11 +106,11 @@ def test_map(self): self.assertEqual(2*i + 1, x) # Alternative test - self.assertEqual([3, 5, 7], list(evaluate(dm))) + self.assertEqual([3, 5, 7], list(sn.evaluate(dm))) def test_max(self): l = [1, 2] - dl = make_deferrable(l) + dl = sn.defer(l) self.assertEqual(2, sn.max(dl)) l.append(3) @@ -119,7 +118,7 @@ def test_max(self): def test_min(self): l = [1, 2] - dl = make_deferrable(l) + dl = sn.defer(l) self.assertEqual(1, sn.min(dl)) l.append(0) @@ -128,29 +127,29 @@ def test_min(self): def test_reversed(self): l = [1, 2, 3] dr = sn.reversed(l) - self.assertEqual([3, 2, 1], list(evaluate(dr))) + self.assertEqual([3, 2, 1], list(sn.evaluate(dr))) def test_round(self): - self.assertEqual(1.0, sn.round(make_deferrable(1.4))) + self.assertEqual(1.0, sn.round(sn.defer(1.4))) def test_setattr(self): dset = sn.setattr(self, '_a', 5) self.assertEqual(0, self._a) - evaluate(dset) + sn.evaluate(dset) self.assertEqual(5, self._a) def test_sorted(self): l = [2, 3, 1] ds = sn.sorted(l) - self.assertEqual([1, 2, 3], list(evaluate(ds))) + self.assertEqual([1, 2, 3], list(sn.evaluate(ds))) def test_sum(self): self.assertEqual(3, sn.sum([1, 1, 1])) - self.assertEqual(3, sn.sum(make_deferrable([1, 1, 1]))) + self.assertEqual(3, sn.sum(sn.defer([1, 1, 1]))) def test_zip(self): la = [1, 2, 3] - lb = make_deferrable(['a', 'b', 'c']) + lb = sn.defer(['a', 'b', 'c']) la_new = [] lb_new = [] @@ -173,26 +172,26 @@ def test_assert_true(self): self.assertTrue(sn.assert_true([1])) self.assertTrue(sn.assert_true(range(1))) self.assertRaisesRegex(SanityError, 'False is not True', - evaluate, sn.assert_true(False)) + sn.evaluate, sn.assert_true(False)) self.assertRaisesRegex(SanityError, '0 is not True', - evaluate, sn.assert_true(0)) + sn.evaluate, sn.assert_true(0)) self.assertRaisesRegex(SanityError, r'\[\] is not True', - evaluate, sn.assert_true([])) + sn.evaluate, sn.assert_true([])) self.assertRaisesRegex(SanityError, r'range\(.+\) is not True', - evaluate, sn.assert_true(range(0))) + sn.evaluate, sn.assert_true(range(0))) self.assertRaisesRegex(SanityError, 'not true', - evaluate, sn.assert_true(0, msg='not true')) + sn.evaluate, sn.assert_true(0, msg='not true')) def test_assert_true_with_deferrables(self): - self.assertTrue(sn.assert_true(make_deferrable(True))) - self.assertTrue(sn.assert_true(make_deferrable(1))) - self.assertTrue(sn.assert_true(make_deferrable([1]))) + self.assertTrue(sn.assert_true(sn.defer(True))) + self.assertTrue(sn.assert_true(sn.defer(1))) + self.assertTrue(sn.assert_true(sn.defer([1]))) self.assertRaisesRegex(SanityError, 'False is not True', - evaluate, sn.assert_true(make_deferrable(False))) + sn.evaluate, sn.assert_true(sn.defer(False))) self.assertRaisesRegex(SanityError, '0 is not True', - evaluate, sn.assert_true(make_deferrable(0))) + sn.evaluate, sn.assert_true(sn.defer(0))) self.assertRaisesRegex(SanityError, r'\[\] is not True', - evaluate, sn.assert_true(make_deferrable([]))) + sn.evaluate, sn.assert_true(sn.defer([]))) def test_assert_false(self): self.assertTrue(sn.assert_false(False)) @@ -200,125 +199,125 @@ def test_assert_false(self): self.assertTrue(sn.assert_false([])) self.assertTrue(sn.assert_false(range(0))) self.assertRaisesRegex(SanityError, 'True is not False', - evaluate, sn.assert_false(True)) + sn.evaluate, sn.assert_false(True)) self.assertRaisesRegex(SanityError, '1 is not False', - evaluate, sn.assert_false(1)) + sn.evaluate, sn.assert_false(1)) self.assertRaisesRegex(SanityError, r'\[1\] is not False', - evaluate, sn.assert_false([1])) + sn.evaluate, sn.assert_false([1])) self.assertRaisesRegex(SanityError, r'range\(.+\) is not False', - evaluate, sn.assert_false(range(1))) + sn.evaluate, sn.assert_false(range(1))) def test_assert_false_with_deferrables(self): - self.assertTrue(sn.assert_false(make_deferrable(False))) - self.assertTrue(sn.assert_false(make_deferrable(0))) - self.assertTrue(sn.assert_false(make_deferrable([]))) + self.assertTrue(sn.assert_false(sn.defer(False))) + self.assertTrue(sn.assert_false(sn.defer(0))) + self.assertTrue(sn.assert_false(sn.defer([]))) self.assertRaisesRegex(SanityError, 'True is not False', - evaluate, sn.assert_false(make_deferrable(True))) + sn.evaluate, sn.assert_false(sn.defer(True))) self.assertRaisesRegex(SanityError, '1 is not False', - evaluate, sn.assert_false(make_deferrable(1))) + sn.evaluate, sn.assert_false(sn.defer(1))) self.assertRaisesRegex(SanityError, r'\[1\] is not False', - evaluate, sn.assert_false(make_deferrable([1]))) + sn.evaluate, sn.assert_false(sn.defer([1]))) def test_assert_eq(self): self.assertTrue(sn.assert_eq(1, 1)) self.assertTrue(sn.assert_eq(1, True)) self.assertRaisesRegex(SanityError, '1 != 2', - evaluate, sn.assert_eq(1, 2)) + sn.evaluate, sn.assert_eq(1, 2)) self.assertRaisesRegex(SanityError, '1 != False', - evaluate, sn.assert_eq(1, False)) + sn.evaluate, sn.assert_eq(1, False)) self.assertRaisesRegex( SanityError, '1 is not equals to 2', - evaluate, sn.assert_eq(1, 2, '{0} is not equals to {1}')) + sn.evaluate, sn.assert_eq(1, 2, '{0} is not equals to {1}')) def test_assert_eq_with_deferrables(self): - self.assertTrue(sn.assert_eq(1, make_deferrable(1))) - self.assertTrue(sn.assert_eq(make_deferrable(1), True)) + self.assertTrue(sn.assert_eq(1, sn.defer(1))) + self.assertTrue(sn.assert_eq(sn.defer(1), True)) self.assertRaisesRegex(SanityError, '1 != 2', - evaluate, sn.assert_eq(make_deferrable(1), 2)) + sn.evaluate, sn.assert_eq(sn.defer(1), 2)) self.assertRaisesRegex(SanityError, '1 != False', - evaluate, sn.assert_eq(make_deferrable(1), False)) + sn.evaluate, sn.assert_eq(sn.defer(1), False)) def test_assert_ne(self): self.assertTrue(sn.assert_ne(1, 2)) self.assertTrue(sn.assert_ne(1, False)) self.assertRaisesRegex(SanityError, '1 == 1', - evaluate, sn.assert_ne(1, 1)) + sn.evaluate, sn.assert_ne(1, 1)) self.assertRaisesRegex(SanityError, '1 == True', - evaluate, sn.assert_ne(1, True)) + sn.evaluate, sn.assert_ne(1, True)) def test_assert_ne_with_deferrables(self): - self.assertTrue(sn.assert_ne(1, make_deferrable(2))) - self.assertTrue(sn.assert_ne(make_deferrable(1), False)) + self.assertTrue(sn.assert_ne(1, sn.defer(2))) + self.assertTrue(sn.assert_ne(sn.defer(1), False)) self.assertRaisesRegex(SanityError, '1 == 1', - evaluate, sn.assert_ne(make_deferrable(1), 1)) + sn.evaluate, sn.assert_ne(sn.defer(1), 1)) self.assertRaisesRegex(SanityError, '1 == True', - evaluate, sn.assert_ne(make_deferrable(1), True)) + sn.evaluate, sn.assert_ne(sn.defer(1), True)) def test_assert_gt(self): self.assertTrue(sn.assert_gt(3, 1)) self.assertRaisesRegex(SanityError, '1 <= 3', - evaluate, sn.assert_gt(1, 3)) + sn.evaluate, sn.assert_gt(1, 3)) def test_assert_gt_with_deferrables(self): - self.assertTrue(sn.assert_gt(3, make_deferrable(1))) + self.assertTrue(sn.assert_gt(3, sn.defer(1))) self.assertRaisesRegex(SanityError, '1 <= 3', - evaluate, sn.assert_gt(1, make_deferrable(3))) + sn.evaluate, sn.assert_gt(1, sn.defer(3))) def test_assert_ge(self): self.assertTrue(sn.assert_ge(3, 1)) self.assertTrue(sn.assert_ge(3, 3)) self.assertRaisesRegex(SanityError, '1 < 3', - evaluate, sn.assert_ge(1, 3)) + sn.evaluate, sn.assert_ge(1, 3)) def test_assert_ge_with_deferrables(self): - self.assertTrue(sn.assert_ge(3, make_deferrable(1))) - self.assertTrue(sn.assert_ge(3, make_deferrable(3))) + self.assertTrue(sn.assert_ge(3, sn.defer(1))) + self.assertTrue(sn.assert_ge(3, sn.defer(3))) self.assertRaisesRegex(SanityError, '1 < 3', - evaluate, sn.assert_ge(1, make_deferrable(3))) + sn.evaluate, sn.assert_ge(1, sn.defer(3))) def test_assert_lt(self): self.assertTrue(sn.assert_lt(1, 3)) self.assertRaisesRegex(SanityError, '3 >= 1', - evaluate, sn.assert_lt(3, 1)) + sn.evaluate, sn.assert_lt(3, 1)) def test_assert_lt_with_deferrables(self): - self.assertTrue(sn.assert_lt(1, make_deferrable(3))) + self.assertTrue(sn.assert_lt(1, sn.defer(3))) self.assertRaisesRegex(SanityError, '3 >= 1', - evaluate, sn.assert_lt(3, make_deferrable(1))) + sn.evaluate, sn.assert_lt(3, sn.defer(1))) def test_assert_le(self): self.assertTrue(sn.assert_le(1, 1)) self.assertTrue(sn.assert_le(3, 3)) self.assertRaisesRegex(SanityError, '3 > 1', - evaluate, sn.assert_le(3, 1)) + sn.evaluate, sn.assert_le(3, 1)) def test_assert_le_with_deferrables(self): - self.assertTrue(sn.assert_le(1, make_deferrable(3))) - self.assertTrue(sn.assert_le(3, make_deferrable(3))) + self.assertTrue(sn.assert_le(1, sn.defer(3))) + self.assertTrue(sn.assert_le(3, sn.defer(3))) self.assertRaisesRegex(SanityError, '3 > 1', - evaluate, sn.assert_le(3, make_deferrable(1))) + sn.evaluate, sn.assert_le(3, sn.defer(1))) def test_assert_in(self): self.assertTrue(sn.assert_in(1, [1, 2, 3])) self.assertRaisesRegex(SanityError, r'0 is not in \[1, 2, 3\]', - evaluate, sn.assert_in(0, [1, 2, 3])) + sn.evaluate, sn.assert_in(0, [1, 2, 3])) def test_assert_in_with_deferrables(self): - self.assertTrue(sn.assert_in(1, make_deferrable([1, 2, 3]))) + self.assertTrue(sn.assert_in(1, sn.defer([1, 2, 3]))) self.assertRaisesRegex( SanityError, r'0 is not in \[1, 2, 3\]', - evaluate, sn.assert_in(0, make_deferrable([1, 2, 3]))) + sn.evaluate, sn.assert_in(0, sn.defer([1, 2, 3]))) def test_assert_not_in(self): self.assertTrue(sn.assert_not_in(0, [1, 2, 3])) self.assertRaisesRegex(SanityError, r'1 is in \[1, 2, 3\]', - evaluate, sn.assert_not_in(1, [1, 2, 3])) + sn.evaluate, sn.assert_not_in(1, [1, 2, 3])) def test_assert_not_in_with_deferrables(self): - self.assertTrue(sn.assert_not_in(0, make_deferrable([1, 2, 3]))) + self.assertTrue(sn.assert_not_in(0, sn.defer([1, 2, 3]))) self.assertRaisesRegex( SanityError, r'1 is in \[1, 2, 3\]', - evaluate, sn.assert_not_in(1, make_deferrable([1, 2, 3]))) + sn.evaluate, sn.assert_not_in(1, sn.defer([1, 2, 3]))) def test_assert_bounded(self): self.assertTrue(sn.assert_bounded(1, -1.5, 1.5)) @@ -327,15 +326,15 @@ def test_assert_bounded(self): self.assertTrue(sn.assert_bounded(1)) self.assertRaisesRegex(SanityError, r'value 1 not within bounds -0\.5\.\.0\.5', - evaluate, sn.assert_bounded(1, -0.5, 0.5)) + sn.evaluate, sn.assert_bounded(1, -0.5, 0.5)) self.assertRaisesRegex(SanityError, r'value 1 not within bounds -inf\.\.0\.5', - evaluate, sn.assert_bounded(1, upper=0.5)) + sn.evaluate, sn.assert_bounded(1, upper=0.5)) self.assertRaisesRegex(SanityError, r'value 1 not within bounds 1\.5\.\.inf', - evaluate, sn.assert_bounded(1, lower=1.5)) + sn.evaluate, sn.assert_bounded(1, lower=1.5)) self.assertRaisesRegex( - SanityError, 'value 1 is out of bounds', evaluate, + SanityError, 'value 1 is out of bounds', sn.evaluate, sn.assert_bounded(1, -0.5, 0.5, 'value {0} is out of bounds')) def test_assert_reference(self): @@ -357,48 +356,48 @@ def test_assert_reference(self): self.assertRaisesRegex( SanityError, r'0\.5 is beyond reference value 1 \(l=0\.8, u=1\.1\)', - evaluate, sn.assert_reference(0.5, 1, -0.2, 0.1) + sn.evaluate, sn.assert_reference(0.5, 1, -0.2, 0.1) ) self.assertRaisesRegex( SanityError, r'0\.5 is beyond reference value 1 \(l=0\.8, u=inf\)', - evaluate, sn.assert_reference(0.5, 1, -0.2) + sn.evaluate, sn.assert_reference(0.5, 1, -0.2) ) self.assertRaisesRegex( SanityError, r'1\.5 is beyond reference value 1 \(l=0\.8, u=1\.1\)', - evaluate, sn.assert_reference(1.5, 1, -0.2, 0.1) + sn.evaluate, sn.assert_reference(1.5, 1, -0.2, 0.1) ) self.assertRaisesRegex( SanityError, r'1\.5 is beyond reference value 1 \(l=-inf, u=1\.1\)', - evaluate, sn.assert_reference( + sn.evaluate, sn.assert_reference( 1.5, 1, lower_thres=None, upper_thres=0.1) ) self.assertRaisesRegex( SanityError, r'-0\.8 is beyond reference value -1 \(l=-1\.2, u=-0\.9\)', - evaluate, sn.assert_reference(-0.8, -1, -0.2, 0.1) + sn.evaluate, sn.assert_reference(-0.8, -1, -0.2, 0.1) ) # Check invalid thresholds self.assertRaisesRegex(SanityError, r'invalid high threshold value: -0\.1', - evaluate, sn.assert_reference(0.9, 1, -0.2, -0.1)) + sn.evaluate, sn.assert_reference(0.9, 1, -0.2, -0.1)) self.assertRaisesRegex(SanityError, r'invalid low threshold value: 0\.2', - evaluate, sn.assert_reference(0.9, 1, 0.2, 0.1)) + sn.evaluate, sn.assert_reference(0.9, 1, 0.2, 0.1)) self.assertRaisesRegex(SanityError, r'invalid low threshold value: 1\.2', - evaluate, sn.assert_reference(0.9, 1, 1.2, 0.1)) + sn.evaluate, sn.assert_reference(0.9, 1, 1.2, 0.1)) # check invalid thresholds greater than 1 self.assertRaisesRegex(SanityError, r'invalid low threshold value: -2\.0', - evaluate, sn.assert_reference(0.9, 1, -2.0, 0.1)) + sn.evaluate, sn.assert_reference(0.9, 1, -2.0, 0.1)) self.assertRaisesRegex(SanityError, r'invalid high threshold value: 1\.5', - evaluate, sn.assert_reference(-1.5, -1, -0.5, 1.5)) + sn.evaluate, sn.assert_reference(-1.5, -1, -0.5, 1.5)) def _write_tempfile(self): ret = None @@ -414,8 +413,8 @@ def test_assert_found(self): tempfile = self._write_tempfile() self.assertTrue(sn.assert_found(r'Step: \d+', tempfile)) self.assertTrue(sn.assert_found( - r'Step: \d+', make_deferrable(tempfile))) - self.assertRaises(SanityError, evaluate, + r'Step: \d+', sn.defer(tempfile))) + self.assertRaises(SanityError, sn.evaluate, sn.assert_found(r'foo: \d+', tempfile)) os.remove(tempfile) @@ -428,9 +427,9 @@ def test_assert_not_found(self): tempfile = self._write_tempfile() self.assertTrue(sn.assert_not_found(r'foo: \d+', tempfile)) self.assertTrue( - sn.assert_not_found(r'foo: \d+', make_deferrable(tempfile)) + sn.assert_not_found(r'foo: \d+', sn.defer(tempfile)) ) - self.assertRaises(SanityError, evaluate, + self.assertRaises(SanityError, sn.evaluate, sn.assert_not_found(r'Step: \d+', tempfile)) os.remove(tempfile) @@ -448,20 +447,20 @@ def test_getitem(self): self.assertEqual(2, sn.getitem(l, 1)) self.assertEqual(2, sn.getitem(d, 'b')) self.assertRaisesRegex(SanityError, 'index out of bounds: 10', - evaluate, sn.getitem(l, 10)) + sn.evaluate, sn.getitem(l, 10)) self.assertRaisesRegex(SanityError, 'key not found: k', - evaluate, sn.getitem(d, 'k')) + sn.evaluate, sn.getitem(d, 'k')) def test_getitem_with_deferrables(self): - l = make_deferrable([1, 2, 3]) - d = make_deferrable({'a': 1, 'b': 2, 'c': 3}) + l = sn.defer([1, 2, 3]) + d = sn.defer({'a': 1, 'b': 2, 'c': 3}) self.assertEqual(2, sn.getitem(l, 1)) self.assertEqual(2, sn.getitem(d, 'b')) self.assertRaisesRegex(SanityError, 'index out of bounds: 10', - evaluate, sn.getitem(l, 10)) + sn.evaluate, sn.getitem(l, 10)) self.assertRaisesRegex(SanityError, 'key not found: k', - evaluate, sn.getitem(d, 'k')) + sn.evaluate, sn.getitem(d, 'k')) def test_count(self): # Use a custom generator for testing @@ -505,22 +504,22 @@ def my_mod_range(n, mod=2): # Test deferred expressions d = [1, 2, 2, 1] - self.assertEqual(2, sn.count_uniq(make_deferrable(d))) + self.assertEqual(2, sn.count_uniq(sn.defer(d))) def test_glob(self): filepatt = os.path.join(TEST_RESOURCES_CHECKS, '*.py') self.assertTrue(sn.glob(filepatt)) - self.assertTrue(sn.glob(make_deferrable(filepatt))) + self.assertTrue(sn.glob(sn.defer(filepatt))) def test_iglob(self): filepatt = os.path.join(TEST_RESOURCES_CHECKS, '*.py') self.assertTrue(sn.count(sn.iglob(filepatt))) - self.assertTrue(sn.count(sn.iglob(make_deferrable(filepatt)))) + self.assertTrue(sn.count(sn.iglob(sn.defer(filepatt)))) def test_chain(self): list1 = ['A', 'B', 'C'] list2 = ['D', 'E', 'F'] - chain1 = evaluate(sn.chain(make_deferrable(list1), list2)) + chain1 = sn.evaluate(sn.chain(sn.defer(list1), list2)) chain2 = itertools.chain(list1, list2) self.assertTrue(all((a == b for a, b in zip(chain1, chain2)))) @@ -540,13 +539,13 @@ def tearDown(self): os.remove(self.tempfile) def test_findall(self): - res = evaluate(sn.findall(r'Step: \d+', self.tempfile)) + res = sn.evaluate(sn.findall(r'Step: \d+', self.tempfile)) self.assertEqual(3, len(res)) - res = evaluate(sn.findall('Step:.*', self.tempfile)) + res = sn.evaluate(sn.findall('Step:.*', self.tempfile)) self.assertEqual(3, len(res)) - res = evaluate(sn.findall('Step: [12]', self.tempfile)) + res = sn.evaluate(sn.findall('Step: [12]', self.tempfile)) self.assertEqual(2, len(res)) # Check the matches @@ -554,67 +553,69 @@ def test_findall(self): self.assertEqual(expected, match.group(0)) # Check groups - res = evaluate(sn.findall(r'Step: (?P\d+)', self.tempfile)) + res = sn.evaluate(sn.findall(r'Step: (?P\d+)', self.tempfile)) for step, match in enumerate(res, start=1): self.assertEqual(step, int(match.group(1))) self.assertEqual(step, int(match.group('no'))) def test_findall_encoding(self): - res = evaluate( + res = sn.evaluate( sn.findall('Odyssey', self.utf16_file, encoding='utf-16') ) self.assertEqual(1, len(res)) def test_findall_error(self): - self.assertRaises(SanityError, evaluate, + self.assertRaises(SanityError, sn.evaluate, sn.findall(r'Step: \d+', 'foo.txt')) def test_extractall(self): # Check numeric groups - res = evaluate(sn.extractall(r'Step: (?P\d+)', self.tempfile, 1)) + res = sn.evaluate(sn.extractall( + r'Step: (?P\d+)', self.tempfile, 1)) for expected, v in enumerate(res, start=1): self.assertEqual(str(expected), v) # Check named groups - res = evaluate(sn.extractall(r'Step: (?P\d+)', self.tempfile, 'no')) + res = sn.evaluate(sn.extractall( + r'Step: (?P\d+)', self.tempfile, 'no')) for expected, v in enumerate(res, start=1): self.assertEqual(str(expected), v) # Check convert function - res = evaluate(sn.extractall(r'Step: (?P\d+)', - self.tempfile, 'no', int)) + res = sn.evaluate(sn.extractall(r'Step: (?P\d+)', + self.tempfile, 'no', int)) for expected, v in enumerate(res, start=1): self.assertEqual(expected, v) def test_extractall_encoding(self): - res = evaluate( + res = sn.evaluate( sn.extractall('Odyssey', self.utf16_file, encoding='utf-16') ) self.assertEqual(1, len(res)) def test_extractall_error(self): - self.assertRaises(SanityError, evaluate, + self.assertRaises(SanityError, sn.evaluate, sn.extractall(r'Step: (\d+)', 'foo.txt', 1)) self.assertRaises( - SanityError, evaluate, + SanityError, sn.evaluate, sn.extractall(r'Step: (?P\d+)', self.tempfile, conv=int) ) - self.assertRaises(SanityError, evaluate, + self.assertRaises(SanityError, sn.evaluate, sn.extractall(r'Step: (\d+)', self.tempfile, 2)) self.assertRaises( - SanityError, evaluate, + SanityError, sn.evaluate, sn.extractall(r'Step: (?P\d+)', self.tempfile, 'foo')) def test_extractall_custom_conv(self): - res = evaluate(sn.extractall(r'Step: (\d+)', self.tempfile, 1, - lambda x: int(x))) + res = sn.evaluate(sn.extractall(r'Step: (\d+)', self.tempfile, 1, + lambda x: int(x))) for expected, v in enumerate(res, start=1): self.assertEqual(expected, v) # Check error in custom function self.assertRaises( - SanityError, evaluate, + SanityError, sn.evaluate, sn.extractall(r'Step: (\d+)', self.tempfile, conv=lambda x: int(x)) ) @@ -625,7 +626,7 @@ def __call__(self, x): return int(x) self.assertRaises( - SanityError, evaluate, + SanityError, sn.evaluate, sn.extractall(r'Step: (\d+)', self.tempfile, conv=C()) ) @@ -638,12 +639,12 @@ def test_extractsingle(self): # Test out of bounds access self.assertRaises( - SanityError, evaluate, + SanityError, sn.evaluate, sn.extractsingle(r'Step: (\d+)', self.tempfile, 1, int, 100) ) def test_extractsingle_encoding(self): - res = evaluate( + res = sn.evaluate( sn.extractsingle(r'Odyssey', self.utf16_file, encoding='utf-16') ) self.assertNotEqual(-1, res.find('Odyssey')) @@ -665,16 +666,16 @@ def test_safe_format(self): class TestNumericFunctions(unittest.TestCase): def test_avg(self): - res = evaluate(sn.avg([1, 2, 3, 4])) + res = sn.evaluate(sn.avg([1, 2, 3, 4])) self.assertEqual(2.5, res) # Check result when passing a generator - res = evaluate(sn.avg(range(1, 5))) + res = sn.evaluate(sn.avg(range(1, 5))) self.assertEqual(2.5, res) # Check with single element container - res = evaluate(sn.avg(range(1, 2))) + res = sn.evaluate(sn.avg(range(1, 2))) self.assertEqual(1, res) # Check with empty container - self.assertRaises(SanityError, evaluate, sn.avg([])) + self.assertRaises(SanityError, sn.evaluate, sn.avg([])) From f282c55419b49886c599b7226be68ace6e07e82d Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Thu, 14 Nov 2019 22:05:53 +0100 Subject: [PATCH 2/3] Fix PEP8 issues --- unittests/test_sanity_functions.py | 40 +++++++++++++++++++----------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/unittests/test_sanity_functions.py b/unittests/test_sanity_functions.py index ab2590dc06..ee3f2557e8 100644 --- a/unittests/test_sanity_functions.py +++ b/unittests/test_sanity_functions.py @@ -381,23 +381,33 @@ def test_assert_reference(self): ) # Check invalid thresholds - self.assertRaisesRegex(SanityError, - r'invalid high threshold value: -0\.1', - sn.evaluate, sn.assert_reference(0.9, 1, -0.2, -0.1)) - self.assertRaisesRegex(SanityError, - r'invalid low threshold value: 0\.2', - sn.evaluate, sn.assert_reference(0.9, 1, 0.2, 0.1)) - self.assertRaisesRegex(SanityError, - r'invalid low threshold value: 1\.2', - sn.evaluate, sn.assert_reference(0.9, 1, 1.2, 0.1)) + self.assertRaisesRegex( + SanityError, + r'invalid high threshold value: -0\.1', + sn.evaluate, sn.assert_reference(0.9, 1, -0.2, -0.1) + ) + self.assertRaisesRegex( + SanityError, + r'invalid low threshold value: 0\.2', + sn.evaluate, sn.assert_reference(0.9, 1, 0.2, 0.1) + ) + self.assertRaisesRegex( + SanityError, + r'invalid low threshold value: 1\.2', + sn.evaluate, sn.assert_reference(0.9, 1, 1.2, 0.1) + ) # check invalid thresholds greater than 1 - self.assertRaisesRegex(SanityError, - r'invalid low threshold value: -2\.0', - sn.evaluate, sn.assert_reference(0.9, 1, -2.0, 0.1)) - self.assertRaisesRegex(SanityError, - r'invalid high threshold value: 1\.5', - sn.evaluate, sn.assert_reference(-1.5, -1, -0.5, 1.5)) + self.assertRaisesRegex( + SanityError, + r'invalid low threshold value: -2\.0', + sn.evaluate, sn.assert_reference(0.9, 1, -2.0, 0.1) + ) + self.assertRaisesRegex( + SanityError, + r'invalid high threshold value: 1\.5', + sn.evaluate, sn.assert_reference(-1.5, -1, -0.5, 1.5) + ) def _write_tempfile(self): ret = None From 31499c60e4d2f68be59f741d2a2bc4cbb4f552bf Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Thu, 21 Nov 2019 16:16:29 -0700 Subject: [PATCH 3/3] Address PR comments --- reframe/utility/sanity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reframe/utility/sanity.py b/reframe/utility/sanity.py index b7252c95db..cfce935026 100644 --- a/reframe/utility/sanity.py +++ b/reframe/utility/sanity.py @@ -94,7 +94,7 @@ def myfunc(*args): This decorator is an alias to the :func:`reframe.core.deferrable.deferrable` decorator. -