-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Filter out tests with no programming environments #319
Conversation
* Create the corresponding unit test.
Codecov Report
@@ Coverage Diff @@
## master #319 +/- ##
==========================================
+ Coverage 91.18% 91.26% +0.08%
==========================================
Files 67 67
Lines 7941 8005 +64
==========================================
+ Hits 7241 7306 +65
+ Misses 700 699 -1
Continue to review full report at Codecov.
|
reframe/frontend/cli.py
Outdated
for e in options.prgenv) else None, | ||
lambda c: c if (c.valid_prog_environs | ||
and all(c.supports_environ(e) | ||
for e in options.prgenv)) else None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This lambda gets a bit too complicated. Since this operation is quite useful, I suggest writing a function in utility doing that thing:
def allx(iterable):
# we should check here specifically if `iterable` is actually an iterable, as real all() does
if not iterable:
return False
return all(iterable)
Would it also make sense to provide a deferrable version of this function in this PR, too?
* Create `allx` function in `reframe/utility/__init__.py`. * Create the corresponding deferrable version of `allx`. * Create the unit tests for the above functions. * Use raw strings in some regular expressions to avoid warnings.
reframe/utility/sanity.py
Outdated
@@ -116,6 +117,16 @@ def all(iterable): | |||
return builtins.all(iterable) | |||
|
|||
|
|||
@deferrable | |||
def allx(iterable): | |||
"""Replacement for the :func:`allx() <reframe.utility.allx>` function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation of reframe.utility
is not public, so you may not refer to it here.
reframe/utility/__init__.py
Outdated
@@ -54,6 +56,28 @@ def import_module_from_file(filename): | |||
return importlib.import_module(module_name) | |||
|
|||
|
|||
def allx(iterable): | |||
"""Return ``True`` if all elements of the `iterable` are true. If | |||
iterable is empty or ``None`` return ``False``. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I would phrase this different to stress the connection with the builtin
all()
: Same as the built-inall
, except that it returnsFalse
ifiterable
is empty. - This function must be fully equivalent with the built-in
all()
ifiterable
is not empty, which means, we should raiseTypeError
if the argument isNone
. Pay attention to have fully compatible behaviour. - There are several documentation formatting issues here:
- Double backquotes must be used for citing function arguments, here
iterable
. None
,True
andFalse
must be formatted as:class:`None`
,:class:`True`
etc.
- Double backquotes must be used for citing function arguments, here
reframe/utility/__init__.py
Outdated
first_item = next(iterable) | ||
return all(itertools.chain([first_item], iterable)) | ||
except StopIteration: | ||
return False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't understand all this fuss here. Why a check of iterable
against collections.abc.Iterable
wouldn't just work?
>>> import collections
>>> isinstance(range(0), collections.abc.Iterable)
True
>>>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we do not want to accept empty generators. Is there any other way to check that a generator is empty?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by "empty generator"? A generator is a generator, i.e., an iterable, even if it doesn't produce any values. Your unit tests should pass fine using my proposal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean a generator like (i for i in [])
if it is passed to allx
how can I check that there are no elements and return False
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now, I get what you are trying to do. The comment above the code is really misleading... Please change it with sth more precise!
reframe/utility/__init__.py
Outdated
except StopIteration: | ||
return False | ||
|
||
if not iterable: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not enough. If iterable
is None
, we should raise a TypeError
as all()
does.
unittests/test_sanity_functions.py
Outdated
self.assertFalse(expr3) | ||
self.assertFalse(expr4) | ||
self.assertFalse(expr5) | ||
self.assertTrue(expr6) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can combine these assertions with the expressions above.
unittests/test_sanity_functions.py
Outdated
expr3 = sn.allx([]) | ||
expr4 = sn.allx(None) | ||
expr5 = sn.allx(i for i in []) | ||
expr6 = sn.allx(i for i in [1]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use ranges here.
reframe/utility/__init__.py
Outdated
if isinstance(iterable, types.GeneratorType): | ||
try: | ||
first_item = next(iterable) | ||
return all(itertools.chain([first_item], iterable)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better put this in the else
block of the try/except. Also rename first_item
to first
or head
.
- Rationale on special treatment of generators in allx. - Document the sanity function correctly. - Correct line splits.
…-fixes Code organisation fixes
@jenkins-cscs retry all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@teojgo @victorusu I think there is a fundamental problem with this PR:
On master, this
./reframe.py -C config/cscs.py -c cscs-checks/ -R -l
gives a whole listing of the tests, whereas here it gives nothing!
@victorusu what should be the expected behavior when a check has an empty prgenv list and we also do not specify any particular prgenv to ReFrame? |
@teojgo @victorusu The logical thing to do would be to print the test if it supports any programming environment, i.e., |
reframe/frontend/cli.py
Outdated
# Here we also check that the valid_prog_environs of the check | ||
# is an iterable and not empty | ||
filter_func = lambda c: c if util.allx( | ||
c.valid_prog_environs) else None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest replacing the lambdas altogether here in favour of a closure:
def filter_prgenv(c):
if options.prgenv:
return util.allx(c.supports_environ(e) for e in options.prgenv)
else:
return bool(c.valid_prog_environs)
Fixes #244