# Source code for _pytest.outcomes

    # -*- coding: utf-8 -*-
    """
    exception classes and constants handling test outcomes
    as well as functions creating them
    """
    from __future__ import absolute_import
    from __future__ import division
    from __future__ import print_function

    import sys

    from packaging.version import Version

    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 = val.decode("UTF-8", 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(Exception):
        """ raised for immediate program exits (no tracebacks/summaries)"""

        def __init__(self, msg="unknown reason", returncode=None):
            self.msg = msg
            self.returncode = returncode
            super(Exit, self).__init__(msg)

    # exposed helper methods

    def exit(msg, returncode=None):
        """
        Exit testing process.

        :param str msg: message to display upon exit.
        :param int returncode: return code to be used when exiting pytest.
        """
        __tracebackhide__ = True
        raise Exit(msg, returncode)

    exit.Exception = Exit

    def skip(msg="", **kwargs):
        """
        Skip an executing test with the given message.

        This function should be called only during testing (setup, call or teardown) or
        during collection by using the ``allow_module_level`` flag.  This function can
        be called in doctests as well.

        :kwarg bool allow_module_level: allows this function to be called at
            module level, skipping the rest of the module. Default to False.

        .. note::
            It is better to use the :ref:`pytest.mark.skipif ref` marker when possible to declare a test to be
            skipped under certain conditions like mismatching platforms or
            dependencies.
            Similarly, use the ``# doctest: +SKIP`` directive (see `doctest.SKIP
            <https://docs.python.org/3/library/doctest.html#doctest.SKIP>`_)
            to skip a doctest statically.
        """
        __tracebackhide__ = True
        allow_module_level = kwargs.pop("allow_module_level", False)
        if kwargs:
            raise TypeError("unexpected keyword arguments: {}".format(sorted(kwargs)))
        raise Skipped(msg=msg, allow_module_level=allow_module_level)

    skip.Exception = Skipped

    def fail(msg="", pytrace=True):
        """
        Explicitly fail an executing test with the given message.

        :param str msg: the message to show the user as reason for the failure.
        :param bool 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=""):
        """
        Imperatively xfail an executing test or setup functions with the given reason.

        This function should be called only during testing (setup, call or teardown).

        .. note::
            It is better to use the :ref:`pytest.mark.xfail ref` marker when possible to declare a test to be
            xfailed under certain conditions like known bugs or missing features.
        """
        __tracebackhide__ = True
        raise XFailed(reason)

    xfail.Exception = XFailed

    def importorskip(modname, minversion=None, reason=None):
        """Imports and returns the requested module ``modname``, or skip the current test
        if the module cannot be imported.

        :param str modname: the name of the module to import
        :param str minversion: if given, the imported module ``__version__`` attribute must be
            at least this minimal version, otherwise the test is still skipped.
        :param str reason: if given, this reason is shown as the message when the module
            cannot be imported.
        """
        import warnings

        __tracebackhide__ = True
        compile(modname, "", "eval")  # to catch syntaxerrors
        import_exc = None

        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 as exc:
                # Do not raise chained exception here(#1485)
                import_exc = exc
        if import_exc:
            if reason is None:
                reason = "could not import %r: %s" % (modname, import_exc)
            raise Skipped(reason, allow_module_level=True)
        mod = sys.modules[modname]
        if minversion is None:
            return mod
        verattr = getattr(mod, "__version__", None)
        if minversion is not None:
            if verattr is None or Version(verattr) < Version(minversion):
                raise Skipped(
                    "module %r has __version__ %r, required is: %r"
                    % (modname, verattr, minversion),
                    allow_module_level=True,
                )
        return mod