Merge master into features
Conflicts: src/_pytest/debugging.py
This commit is contained in:
commit
4e45472405
|
@ -60,7 +60,7 @@ jobs:
|
|||
- env: TOXENV=py37-freeze
|
||||
|
||||
- env: TOXENV=py38-xdist
|
||||
python: '3.8-dev'
|
||||
python: '3.8'
|
||||
|
||||
- stage: baseline
|
||||
env: TOXENV=py36-xdist
|
||||
|
@ -94,11 +94,6 @@ jobs:
|
|||
tags: true
|
||||
repo: pytest-dev/pytest
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- python: '3.8-dev'
|
||||
env: TOXENV=py38-xdist
|
||||
|
||||
before_script:
|
||||
- |
|
||||
# Do not (re-)upload coverage with cron runs.
|
||||
|
|
|
@ -13,7 +13,7 @@ with advance notice in the **Deprecations** section of releases.
|
|||
file is managed by towncrier. You *may* edit previous change logs to
|
||||
fix problems like typo corrections or such.
|
||||
To add a new change log entry, please see
|
||||
https://pip.pypa.io/en/latest/development/#adding-a-news-entry
|
||||
https://pip.pypa.io/en/latest/development/contributing/#news-entries
|
||||
we named the news folder changelog
|
||||
|
||||
.. towncrier release notes start
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Fix ``--trace`` when used with parametrized functions.
|
|
@ -137,7 +137,7 @@ class Frame:
|
|||
def exec_(self, code, **vars):
|
||||
""" exec 'code' in the frame
|
||||
|
||||
'vars' are optiona; additional local variables
|
||||
'vars' are optional; additional local variables
|
||||
"""
|
||||
f_locals = self.f_locals.copy()
|
||||
f_locals.update(vars)
|
||||
|
@ -207,7 +207,7 @@ class TracebackEntry:
|
|||
|
||||
@property
|
||||
def locals(self):
|
||||
""" locals of underlaying frame """
|
||||
""" locals of underlying frame """
|
||||
return self.frame.f_locals
|
||||
|
||||
def getfirstlinesource(self):
|
||||
|
@ -274,7 +274,7 @@ class TracebackEntry:
|
|||
|
||||
@property
|
||||
def name(self):
|
||||
""" co_name of underlaying code """
|
||||
""" co_name of underlying code """
|
||||
return self.frame.code.raw.co_name
|
||||
|
||||
|
||||
|
@ -302,7 +302,7 @@ class Traceback(list):
|
|||
def cut(self, path=None, lineno=None, firstlineno=None, excludepath=None):
|
||||
""" return a Traceback instance wrapping part of this Traceback
|
||||
|
||||
by provding any combination of path, lineno and firstlineno, the
|
||||
by providing any combination of path, lineno and firstlineno, the
|
||||
first frame to start the to-be-returned traceback is determined
|
||||
|
||||
this allows cutting the first part of a Traceback instance e.g.
|
||||
|
@ -1008,7 +1008,7 @@ class ReprFileLocation(TerminalRepr):
|
|||
|
||||
def toterminal(self, tw) -> None:
|
||||
# filename and lineno output for each entry,
|
||||
# using an output format that most editors unterstand
|
||||
# using an output format that most editors understand
|
||||
msg = self.message
|
||||
i = msg.find("\n")
|
||||
if i != -1:
|
||||
|
|
|
@ -38,7 +38,6 @@ def format_explanation(explanation: str) -> str:
|
|||
for when one explanation needs to span multiple lines, e.g. when
|
||||
displaying diffs.
|
||||
"""
|
||||
explanation = explanation
|
||||
lines = _split_explanation(explanation)
|
||||
result = _format_lines(lines)
|
||||
return "\n".join(result)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
""" interactive debugging with PDB, the Python Debugger. """
|
||||
import argparse
|
||||
import functools
|
||||
import sys
|
||||
|
||||
from _pytest import outcomes
|
||||
|
@ -278,13 +279,16 @@ class PdbTrace:
|
|||
def _test_pytest_function(pyfuncitem):
|
||||
_pdb = pytestPDB._init_pdb("runcall")
|
||||
testfunction = pyfuncitem.obj
|
||||
pyfuncitem.obj = _pdb.runcall
|
||||
if "func" in pyfuncitem._fixtureinfo.argnames: # pragma: no branch
|
||||
raise ValueError("--trace can't be used with a fixture named func!")
|
||||
pyfuncitem.funcargs["func"] = testfunction
|
||||
new_list = list(pyfuncitem._fixtureinfo.argnames)
|
||||
new_list.append("func")
|
||||
pyfuncitem._fixtureinfo.argnames = tuple(new_list)
|
||||
|
||||
# we can't just return `partial(pdb.runcall, testfunction)` because (on
|
||||
# python < 3.7.4) runcall's first param is `func`, which means we'd get
|
||||
# an exception if one of the kwargs to testfunction was called `func`
|
||||
@functools.wraps(testfunction)
|
||||
def wrapper(*args, **kwargs):
|
||||
func = functools.partial(testfunction, *args, **kwargs)
|
||||
_pdb.runcall(func)
|
||||
|
||||
pyfuncitem.obj = wrapper
|
||||
|
||||
|
||||
def _enter_pdb(node, excinfo, rep):
|
||||
|
|
|
@ -513,7 +513,7 @@ class LogXML:
|
|||
key = nodeid, slavenode
|
||||
|
||||
if key in self.node_reporters:
|
||||
# TODO: breasks for --dist=each
|
||||
# TODO: breaks for --dist=each
|
||||
return self.node_reporters[key]
|
||||
|
||||
reporter = _NodeReporter(nodeid, self)
|
||||
|
|
|
@ -437,7 +437,7 @@ class Session(nodes.FSCollector):
|
|||
# one or more conftests are not in use at this fspath
|
||||
proxy = FSHookProxy(fspath, pm, remove_mods)
|
||||
else:
|
||||
# all plugis are active for this fspath
|
||||
# all plugins are active for this fspath
|
||||
proxy = self.config.hook
|
||||
return proxy
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class MarkEvaluator:
|
|||
self._mark_name = name
|
||||
|
||||
def __bool__(self):
|
||||
# dont cache here to prevent staleness
|
||||
# don't cache here to prevent staleness
|
||||
return bool(self._get_marks())
|
||||
|
||||
__nonzero__ = __bool__
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""
|
||||
this is a place where we put datastructures used by legacy apis
|
||||
we hope ot remove
|
||||
we hope to remove
|
||||
"""
|
||||
import keyword
|
||||
|
||||
|
|
|
@ -211,8 +211,8 @@ def pytest_pycollect_makeitem(collector, name, obj):
|
|||
# mock seems to store unbound methods (issue473), normalize it
|
||||
obj = getattr(obj, "__func__", obj)
|
||||
# We need to try and unwrap the function if it's a functools.partial
|
||||
# or a funtools.wrapped.
|
||||
# We musn't if it's been wrapped with mock.patch (python 2 only)
|
||||
# or a functools.wrapped.
|
||||
# We mustn't if it's been wrapped with mock.patch (python 2 only)
|
||||
if not (inspect.isfunction(obj) or inspect.isfunction(get_real_func(obj))):
|
||||
filename, lineno = getfslineno(obj)
|
||||
warnings.warn_explicit(
|
||||
|
@ -596,7 +596,7 @@ class Package(Module):
|
|||
# one or more conftests are not in use at this fspath
|
||||
proxy = FSHookProxy(fspath, pm, remove_mods)
|
||||
else:
|
||||
# all plugis are active for this fspath
|
||||
# all plugins are active for this fspath
|
||||
proxy = self.config.hook
|
||||
return proxy
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ def pytest_runtest_makereport(item, call):
|
|||
outcome = yield
|
||||
rep = outcome.get_result()
|
||||
evalxfail = getattr(item, "_evalxfail", None)
|
||||
# unitttest special case, see setting of _unexpectedsuccess
|
||||
# unittest special case, see setting of _unexpectedsuccess
|
||||
if hasattr(item, "_unexpectedsuccess") and rep.when == "call":
|
||||
|
||||
if item._unexpectedsuccess:
|
||||
|
@ -132,7 +132,7 @@ def pytest_runtest_makereport(item, call):
|
|||
rep.outcome = "failed"
|
||||
|
||||
elif item.config.option.runxfail:
|
||||
pass # don't interefere
|
||||
pass # don't interfere
|
||||
elif call.excinfo and call.excinfo.errisinstance(xfail.Exception):
|
||||
rep.wasxfail = "reason: " + call.excinfo.value.msg
|
||||
rep.outcome = "skipped"
|
||||
|
|
|
@ -15,7 +15,7 @@ class TestMetafunc:
|
|||
def Metafunc(self, func, config=None):
|
||||
# the unit tests of this class check if things work correctly
|
||||
# on the funcarg level, so we don't need a full blown
|
||||
# initiliazation
|
||||
# initialization
|
||||
class FixtureInfo:
|
||||
name2fixturedefs = None
|
||||
|
||||
|
|
|
@ -482,7 +482,7 @@ class TestFunctional:
|
|||
items, rec = testdir.inline_genitems(p)
|
||||
base_item, sub_item, sub_item_other = items
|
||||
print(items, [x.nodeid for x in items])
|
||||
# new api seregates
|
||||
# new api segregates
|
||||
assert not list(base_item.iter_markers(name="b"))
|
||||
assert not list(sub_item_other.iter_markers(name="b"))
|
||||
assert list(sub_item.iter_markers(name="b"))
|
||||
|
|
|
@ -229,7 +229,7 @@ def test_nose_setup_ordering(testdir):
|
|||
|
||||
def test_apiwrapper_problem_issue260(testdir):
|
||||
# this would end up trying a call an optional teardown on the class
|
||||
# for plain unittests we dont want nose behaviour
|
||||
# for plain unittests we don't want nose behaviour
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
|
|
|
@ -304,7 +304,7 @@ def test_argcomplete(testdir, monkeypatch):
|
|||
shlex.quote(sys.executable)
|
||||
)
|
||||
)
|
||||
# alternative would be exteneded Testdir.{run(),_run(),popen()} to be able
|
||||
# alternative would be extended Testdir.{run(),_run(),popen()} to be able
|
||||
# to handle a keyword argument env that replaces os.environ in popen or
|
||||
# extends the copy, advantage: could not forget to restore
|
||||
monkeypatch.setenv("_ARGCOMPLETE", "1")
|
||||
|
|
|
@ -603,7 +603,7 @@ class TestPDB:
|
|||
# No extra newline.
|
||||
assert child.before.endswith(b"c\r\nprint_from_foo\r\n")
|
||||
|
||||
# set_debug should not raise outcomes.Exit, if used recrursively.
|
||||
# set_debug should not raise outcomes. Exit, if used recursively.
|
||||
child.sendline("debug 42")
|
||||
child.sendline("q")
|
||||
child.expect("LEAVING RECURSIVE DEBUGGER")
|
||||
|
@ -1047,6 +1047,51 @@ class TestTraceOption:
|
|||
assert "Exit: Quitting debugger" not in child.before.decode("utf8")
|
||||
TestPDB.flush(child)
|
||||
|
||||
def test_trace_with_parametrize_handles_shared_fixtureinfo(self, testdir):
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.mark.parametrize('myparam', [1,2])
|
||||
def test_1(myparam, request):
|
||||
assert myparam in (1, 2)
|
||||
assert request.function.__name__ == "test_1"
|
||||
@pytest.mark.parametrize('func', [1,2])
|
||||
def test_func(func, request):
|
||||
assert func in (1, 2)
|
||||
assert request.function.__name__ == "test_func"
|
||||
@pytest.mark.parametrize('myparam', [1,2])
|
||||
def test_func_kw(myparam, request, func="func_kw"):
|
||||
assert myparam in (1, 2)
|
||||
assert func == "func_kw"
|
||||
assert request.function.__name__ == "test_func_kw"
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("--trace " + str(p1))
|
||||
for func, argname in [
|
||||
("test_1", "myparam"),
|
||||
("test_func", "func"),
|
||||
("test_func_kw", "myparam"),
|
||||
]:
|
||||
child.expect_exact("> PDB runcall (IO-capturing turned off) >")
|
||||
child.expect_exact(func)
|
||||
child.expect_exact("Pdb")
|
||||
child.sendline("args")
|
||||
child.expect_exact("{} = 1\r\n".format(argname))
|
||||
child.expect_exact("Pdb")
|
||||
child.sendline("c")
|
||||
child.expect_exact("Pdb")
|
||||
child.sendline("args")
|
||||
child.expect_exact("{} = 2\r\n".format(argname))
|
||||
child.expect_exact("Pdb")
|
||||
child.sendline("c")
|
||||
child.expect_exact("> PDB continue (IO-capturing resumed) >")
|
||||
rest = child.read().decode("utf8")
|
||||
assert "6 passed in" in rest
|
||||
assert "reading from stdin while output" not in rest
|
||||
# Only printed once - not on stderr.
|
||||
assert "Exit: Quitting debugger" not in child.before.decode("utf8")
|
||||
TestPDB.flush(child)
|
||||
|
||||
|
||||
def test_trace_after_runpytest(testdir):
|
||||
"""Test that debugging's pytest_configure is re-entrant."""
|
||||
|
@ -1172,7 +1217,6 @@ def test_pdbcls_via_local_module(testdir):
|
|||
|
||||
def runcall(self, *args, **kwds):
|
||||
print("runcall_called", args, kwds)
|
||||
assert "func" in kwds
|
||||
""",
|
||||
)
|
||||
result = testdir.runpytest(
|
||||
|
|
|
@ -4,7 +4,7 @@ import pytest
|
|||
@pytest.fixture
|
||||
def stepwise_testdir(testdir):
|
||||
# Rather than having to modify our testfile between tests, we introduce
|
||||
# a flag for wether or not the second test should fail.
|
||||
# a flag for whether or not the second test should fail.
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
def pytest_addoption(parser):
|
||||
|
|
Loading…
Reference in New Issue