Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions reframe/frontend/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import reframe.core.config as config
import reframe.core.logging as logging
import reframe.core.runtime as runtime
import reframe.utility as util
import reframe.utility.os_ext as os_ext
from reframe.core.exceptions import (EnvironError, ConfigError, ReframeError,
ReframeFatalError, format_exception,
Expand Down Expand Up @@ -349,12 +350,14 @@ def main():
)

# Filter checks by prgenv
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)

if not options.skip_prgenv_check:
checks_matched = filter(
lambda c: c if all(c.supports_environ(e)
for e in options.prgenv) else None,
checks_matched
)
checks_matched = filter(filter_prgenv, checks_matched)

# Filter checks further
if options.gpu_only and options.cpu_only:
Expand Down
24 changes: 24 additions & 0 deletions reframe/utility/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import collections
import importlib
import importlib.util
import itertools
import os
import re
import sys
import types

from collections import UserDict

Expand Down Expand Up @@ -58,6 +60,28 @@ def import_module_from_file(filename):
return importlib.import_module(module_name)


def allx(iterable):
"""Same as the built-in all, except that it returns :class:`False` if
``iterable`` is empty.
"""

# Generators must be treated specially, because there is no way to get
# their size without consuming their elements.
if isinstance(iterable, types.GeneratorType):
try:
head = next(iterable)
except StopIteration:
return False
else:
return all(itertools.chain([head], iterable))

if not isinstance(iterable, collections.abc.Iterable):
raise TypeError("'%s' object is not iterable" %
iterable.__class__.__name__)

return all(iterable) if iterable else False


def decamelize(s):
"""Decamelize the string ``s``.

Expand Down
11 changes: 11 additions & 0 deletions reframe/utility/sanity.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
import itertools
import re

import reframe.utility as util
from reframe.core.deferrable import deferrable, evaluate
from reframe.core.exceptions import SanityError

Expand Down Expand Up @@ -662,6 +663,16 @@ def avg(iterable):

# Other utility functions

@deferrable
def allx(iterable):
"""Same as the built-in :func:`all() <python:all>` function, except that it
returns :class:`False` if ``iterable`` is empty.

.. versionadded:: 2.13
"""
return util.allx(iterable)


@deferrable
def getitem(container, item):
"""Get ``item`` from ``container``.
Expand Down
33 changes: 30 additions & 3 deletions unittests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,19 +257,19 @@ def test_checkpath_recursion(self):
self.checkpath = []
returncode, stdout, _ = self._run_reframe()
num_checks_default = re.search(
'Found (\d+) check', stdout, re.MULTILINE).group(1)
r'Found (\d+) check', stdout, re.MULTILINE).group(1)

self.checkpath = ['checks/']
self.more_options = ['-R']
returncode, stdout, _ = self._run_reframe()
num_checks_in_checkdir = re.search(
'Found (\d+) check', stdout, re.MULTILINE).group(1)
r'Found (\d+) check', stdout, re.MULTILINE).group(1)
self.assertEqual(num_checks_in_checkdir, num_checks_default)

self.more_options = []
returncode, stdout, stderr = self._run_reframe()
num_checks_in_checkdir = re.search(
'Found (\d+) check', stdout, re.MULTILINE).group(1)
r'Found (\d+) check', stdout, re.MULTILINE).group(1)
self.assertEqual('0', num_checks_in_checkdir)

def test_same_output_stage_dir(self):
Expand Down Expand Up @@ -317,3 +317,30 @@ def test_timestamp_option(self):
returncode, stdout, _ = self._run_reframe()
self.assertNotEqual(0, returncode)
self.assertIn(timefmt, stdout)

def test_list_empty_prgenvs_check_and_options(self):
self.checkpath = ['unittests/resources/checks/frontend_checks.py']
self.action = 'list'
self.environs = []
self.more_options = ['-n', 'NoPrgEnvCheck']
returncode, stdout, _ = self._run_reframe()
self.assertIn('Found 0 check(s)', stdout)
self.assertEqual(0, returncode)

def test_list_check_with_empty_prgenvs(self):
self.checkpath = ['unittests/resources/checks/frontend_checks.py']
self.action = 'list'
self.environs = ['foo']
self.more_options = ['-n', 'NoPrgEnvCheck']
returncode, stdout, _ = self._run_reframe()
self.assertIn('Found 0 check(s)', stdout)
self.assertEqual(0, returncode)

def test_list_empty_prgenvs_in_check_and_options(self):
self.checkpath = ['unittests/resources/checks/frontend_checks.py']
self.action = 'list'
self.environs = []
self.more_options = ['-n', 'NoPrgEnvCheck']
returncode, stdout, _ = self._run_reframe()
self.assertIn('Found 0 check(s)', stdout)
self.assertEqual(0, returncode)
Loading