forked from mirrors/gecko-dev
		
	Vendor in Pytest (2.9.2) and its requirement Py (1.4.31), so that it can be used for e.g. the Marionette harness unit tests and a pytest plugin for mozlog. Copy pytest and py package directories (extracted from tars on Pip) into `mozilla-central/python/`, removing some support files (e.g. changelog, docs, tests). Add both `.pth` entries to `virtualenv_packages.txt`. Add both paths to `SEARCH_PATHS` in `mach_bootstrap.py`. MozReview-Commit-ID: IOTCOUxX8R9 --HG-- extra : rebase_source : e03d8a4be084062c0055b365bcc18da6dbb0b7a7
		
			
				
	
	
		
			176 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""
 | 
						|
support for presenting detailed information in failing assertions.
 | 
						|
"""
 | 
						|
import py
 | 
						|
import os
 | 
						|
import sys
 | 
						|
from _pytest.monkeypatch import monkeypatch
 | 
						|
from _pytest.assertion import util
 | 
						|
 | 
						|
 | 
						|
def pytest_addoption(parser):
 | 
						|
    group = parser.getgroup("debugconfig")
 | 
						|
    group.addoption('--assert',
 | 
						|
                    action="store",
 | 
						|
                    dest="assertmode",
 | 
						|
                    choices=("rewrite", "reinterp", "plain",),
 | 
						|
                    default="rewrite",
 | 
						|
                    metavar="MODE",
 | 
						|
                    help="""control assertion debugging tools.  'plain'
 | 
						|
                            performs no assertion debugging.  'reinterp'
 | 
						|
                            reinterprets assert statements after they failed
 | 
						|
                            to provide assertion expression information.
 | 
						|
                            'rewrite' (the default) rewrites assert
 | 
						|
                            statements in test modules on import to
 | 
						|
                            provide assert expression information. """)
 | 
						|
    group.addoption('--no-assert',
 | 
						|
                    action="store_true",
 | 
						|
                    default=False,
 | 
						|
                    dest="noassert",
 | 
						|
                    help="DEPRECATED equivalent to --assert=plain")
 | 
						|
    group.addoption('--nomagic', '--no-magic',
 | 
						|
                    action="store_true",
 | 
						|
                    default=False,
 | 
						|
                    help="DEPRECATED equivalent to --assert=plain")
 | 
						|
 | 
						|
 | 
						|
class AssertionState:
 | 
						|
    """State for the assertion plugin."""
 | 
						|
 | 
						|
    def __init__(self, config, mode):
 | 
						|
        self.mode = mode
 | 
						|
        self.trace = config.trace.root.get("assertion")
 | 
						|
 | 
						|
 | 
						|
def pytest_configure(config):
 | 
						|
    mode = config.getvalue("assertmode")
 | 
						|
    if config.getvalue("noassert") or config.getvalue("nomagic"):
 | 
						|
        mode = "plain"
 | 
						|
    if mode == "rewrite":
 | 
						|
        try:
 | 
						|
            import ast  # noqa
 | 
						|
        except ImportError:
 | 
						|
            mode = "reinterp"
 | 
						|
        else:
 | 
						|
            # Both Jython and CPython 2.6.0 have AST bugs that make the
 | 
						|
            # assertion rewriting hook malfunction.
 | 
						|
            if (sys.platform.startswith('java') or
 | 
						|
                    sys.version_info[:3] == (2, 6, 0)):
 | 
						|
                mode = "reinterp"
 | 
						|
    if mode != "plain":
 | 
						|
        _load_modules(mode)
 | 
						|
        m = monkeypatch()
 | 
						|
        config._cleanup.append(m.undo)
 | 
						|
        m.setattr(py.builtin.builtins, 'AssertionError',
 | 
						|
                  reinterpret.AssertionError)  # noqa
 | 
						|
    hook = None
 | 
						|
    if mode == "rewrite":
 | 
						|
        hook = rewrite.AssertionRewritingHook()  # noqa
 | 
						|
        sys.meta_path.insert(0, hook)
 | 
						|
    warn_about_missing_assertion(mode)
 | 
						|
    config._assertstate = AssertionState(config, mode)
 | 
						|
    config._assertstate.hook = hook
 | 
						|
    config._assertstate.trace("configured with mode set to %r" % (mode,))
 | 
						|
    def undo():
 | 
						|
        hook = config._assertstate.hook
 | 
						|
        if hook is not None and hook in sys.meta_path:
 | 
						|
            sys.meta_path.remove(hook)
 | 
						|
    config.add_cleanup(undo)
 | 
						|
 | 
						|
 | 
						|
def pytest_collection(session):
 | 
						|
    # this hook is only called when test modules are collected
 | 
						|
    # so for example not in the master process of pytest-xdist
 | 
						|
    # (which does not collect test modules)
 | 
						|
    hook = session.config._assertstate.hook
 | 
						|
    if hook is not None:
 | 
						|
        hook.set_session(session)
 | 
						|
 | 
						|
 | 
						|
def _running_on_ci():
 | 
						|
    """Check if we're currently running on a CI system."""
 | 
						|
    env_vars = ['CI', 'BUILD_NUMBER']
 | 
						|
    return any(var in os.environ for var in env_vars)
 | 
						|
 | 
						|
 | 
						|
def pytest_runtest_setup(item):
 | 
						|
    """Setup the pytest_assertrepr_compare hook
 | 
						|
 | 
						|
    The newinterpret and rewrite modules will use util._reprcompare if
 | 
						|
    it exists to use custom reporting via the
 | 
						|
    pytest_assertrepr_compare hook.  This sets up this custom
 | 
						|
    comparison for the test.
 | 
						|
    """
 | 
						|
    def callbinrepr(op, left, right):
 | 
						|
        """Call the pytest_assertrepr_compare hook and prepare the result
 | 
						|
 | 
						|
        This uses the first result from the hook and then ensures the
 | 
						|
        following:
 | 
						|
        * Overly verbose explanations are dropped unless -vv was used or
 | 
						|
          running on a CI.
 | 
						|
        * Embedded newlines are escaped to help util.format_explanation()
 | 
						|
          later.
 | 
						|
        * If the rewrite mode is used embedded %-characters are replaced
 | 
						|
          to protect later % formatting.
 | 
						|
 | 
						|
        The result can be formatted by util.format_explanation() for
 | 
						|
        pretty printing.
 | 
						|
        """
 | 
						|
        hook_result = item.ihook.pytest_assertrepr_compare(
 | 
						|
            config=item.config, op=op, left=left, right=right)
 | 
						|
        for new_expl in hook_result:
 | 
						|
            if new_expl:
 | 
						|
                if (sum(len(p) for p in new_expl[1:]) > 80*8 and
 | 
						|
                        item.config.option.verbose < 2 and
 | 
						|
                        not _running_on_ci()):
 | 
						|
                    show_max = 10
 | 
						|
                    truncated_lines = len(new_expl) - show_max
 | 
						|
                    new_expl[show_max:] = [py.builtin._totext(
 | 
						|
                        'Detailed information truncated (%d more lines)'
 | 
						|
                        ', use "-vv" to show' % truncated_lines)]
 | 
						|
                new_expl = [line.replace("\n", "\\n") for line in new_expl]
 | 
						|
                res = py.builtin._totext("\n~").join(new_expl)
 | 
						|
                if item.config.getvalue("assertmode") == "rewrite":
 | 
						|
                    res = res.replace("%", "%%")
 | 
						|
                return res
 | 
						|
    util._reprcompare = callbinrepr
 | 
						|
 | 
						|
 | 
						|
def pytest_runtest_teardown(item):
 | 
						|
    util._reprcompare = None
 | 
						|
 | 
						|
 | 
						|
def pytest_sessionfinish(session):
 | 
						|
    hook = session.config._assertstate.hook
 | 
						|
    if hook is not None:
 | 
						|
        hook.session = None
 | 
						|
 | 
						|
 | 
						|
def _load_modules(mode):
 | 
						|
    """Lazily import assertion related code."""
 | 
						|
    global rewrite, reinterpret
 | 
						|
    from _pytest.assertion import reinterpret  # noqa
 | 
						|
    if mode == "rewrite":
 | 
						|
        from _pytest.assertion import rewrite  # noqa
 | 
						|
 | 
						|
 | 
						|
def warn_about_missing_assertion(mode):
 | 
						|
    try:
 | 
						|
        assert False
 | 
						|
    except AssertionError:
 | 
						|
        pass
 | 
						|
    else:
 | 
						|
        if mode == "rewrite":
 | 
						|
            specifically = ("assertions which are not in test modules "
 | 
						|
                            "will be ignored")
 | 
						|
        else:
 | 
						|
            specifically = "failing tests may report as passing"
 | 
						|
 | 
						|
        sys.stderr.write("WARNING: " + specifically +
 | 
						|
                         " because assert statements are not executed "
 | 
						|
                         "by the underlying Python interpreter "
 | 
						|
                         "(are you using python -O?)\n")
 | 
						|
 | 
						|
 | 
						|
# Expose this plugin's implementation for the pytest_assertrepr_compare hook
 | 
						|
pytest_assertrepr_compare = util.assertrepr_compare
 |