summaryrefslogtreecommitdiff
path: root/lib/spack/external/_pytest/outcomes.py
blob: ff5ef756d91b9fee9e4ff345f38d24853c27c415 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"""
exception classes and constants handling test outcomes
as well as functions creating them
"""
from __future__ import absolute_import, division, print_function
import py
import sys


class OutcomeException(BaseException):
    """ OutcomeException and its subclass instances indicate and
        contain info about test and collection outcomes.
    """
    def __init__(self, msg=None, pytrace=True):
        BaseException.__init__(self, msg)
        self.msg = msg
        self.pytrace = pytrace

    def __repr__(self):
        if self.msg:
            val = self.msg
            if isinstance(val, bytes):
                val = py._builtin._totext(val, errors='replace')
            return val
        return "<%s instance>" % (self.__class__.__name__,)
    __str__ = __repr__


TEST_OUTCOME = (OutcomeException, Exception)


class Skipped(OutcomeException):
    # XXX hackish: on 3k we fake to live in the builtins
    # in order to have Skipped exception printing shorter/nicer
    __module__ = 'builtins'

    def __init__(self, msg=None, pytrace=True, allow_module_level=False):
        OutcomeException.__init__(self, msg=msg, pytrace=pytrace)
        self.allow_module_level = allow_module_level


class Failed(OutcomeException):
    """ raised from an explicit call to pytest.fail() """
    __module__ = 'builtins'


class Exit(KeyboardInterrupt):
    """ raised for immediate program exits (no tracebacks/summaries)"""
    def __init__(self, msg="unknown reason"):
        self.msg = msg
        KeyboardInterrupt.__init__(self, msg)

# exposed helper methods


def exit(msg):
    """ exit testing process as if KeyboardInterrupt was triggered. """
    __tracebackhide__ = True
    raise Exit(msg)


exit.Exception = Exit


def skip(msg=""):
    """ skip an executing test with the given message.  Note: it's usually
    better to use the pytest.mark.skipif marker to declare a test to be
    skipped under certain conditions like mismatching platforms or
    dependencies.  See the pytest_skipping plugin for details.
    """
    __tracebackhide__ = True
    raise Skipped(msg=msg)


skip.Exception = Skipped


def fail(msg="", pytrace=True):
    """ explicitly fail an currently-executing test with the given Message.

    :arg pytrace: if false the msg represents the full failure information
                  and no python traceback will be reported.
    """
    __tracebackhide__ = True
    raise Failed(msg=msg, pytrace=pytrace)


fail.Exception = Failed


class XFailed(fail.Exception):
    """ raised from an explicit call to pytest.xfail() """


def xfail(reason=""):
    """ xfail an executing test or setup functions with the given reason."""
    __tracebackhide__ = True
    raise XFailed(reason)


xfail.Exception = XFailed


def importorskip(modname, minversion=None):
    """ return imported module if it has at least "minversion" as its
    __version__ attribute.  If no minversion is specified the a skip
    is only triggered if the module can not be imported.
    """
    import warnings
    __tracebackhide__ = True
    compile(modname, '', 'eval')  # to catch syntaxerrors
    should_skip = False

    with warnings.catch_warnings():
        # make sure to ignore ImportWarnings that might happen because
        # of existing directories with the same name we're trying to
        # import but without a __init__.py file
        warnings.simplefilter('ignore')
        try:
            __import__(modname)
        except ImportError:
            # Do not raise chained exception here(#1485)
            should_skip = True
    if should_skip:
        raise Skipped("could not import %r" % (modname,), allow_module_level=True)
    mod = sys.modules[modname]
    if minversion is None:
        return mod
    verattr = getattr(mod, '__version__', None)
    if minversion is not None:
        try:
            from pkg_resources import parse_version as pv
        except ImportError:
            raise Skipped("we have a required version for %r but can not import "
                          "pkg_resources to parse version strings." % (modname,),
                          allow_module_level=True)
        if verattr is None or pv(verattr) < pv(minversion):
            raise Skipped("module %r has __version__ %r, required is: %r" % (
                          modname, verattr, minversion), allow_module_level=True)
    return mod