Merge master into features
Conflicts: testing/test_pdb.py
This commit is contained in:
commit
377888140f
|
@ -0,0 +1 @@
|
||||||
|
Fix regression with ``--pdbcls``, which stopped working with local modules in 4.0.0.
|
|
@ -10,31 +10,18 @@ from doctest import UnexpectedException
|
||||||
|
|
||||||
from _pytest import outcomes
|
from _pytest import outcomes
|
||||||
from _pytest.config import hookimpl
|
from _pytest.config import hookimpl
|
||||||
|
from _pytest.config.exceptions import UsageError
|
||||||
|
|
||||||
|
|
||||||
def _validate_usepdb_cls(value):
|
def _validate_usepdb_cls(value):
|
||||||
|
"""Validate syntax of --pdbcls option."""
|
||||||
try:
|
try:
|
||||||
modname, classname = value.split(":")
|
modname, classname = value.split(":")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise argparse.ArgumentTypeError(
|
raise argparse.ArgumentTypeError(
|
||||||
"{!r} is not in the format 'modname:classname'".format(value)
|
"{!r} is not in the format 'modname:classname'".format(value)
|
||||||
)
|
)
|
||||||
|
return (modname, classname)
|
||||||
try:
|
|
||||||
__import__(modname)
|
|
||||||
mod = sys.modules[modname]
|
|
||||||
|
|
||||||
# Handle --pdbcls=pdb:pdb.Pdb (useful e.g. with pdbpp).
|
|
||||||
parts = classname.split(".")
|
|
||||||
pdb_cls = getattr(mod, parts[0])
|
|
||||||
for part in parts[1:]:
|
|
||||||
pdb_cls = getattr(pdb_cls, part)
|
|
||||||
|
|
||||||
return pdb_cls
|
|
||||||
except Exception as exc:
|
|
||||||
raise argparse.ArgumentTypeError(
|
|
||||||
"could not get pdb class for {!r}: {}".format(value, exc)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
|
@ -68,9 +55,28 @@ def pytest_addoption(parser):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _import_pdbcls(modname, classname):
|
||||||
|
try:
|
||||||
|
__import__(modname)
|
||||||
|
mod = sys.modules[modname]
|
||||||
|
|
||||||
|
# Handle --pdbcls=pdb:pdb.Pdb (useful e.g. with pdbpp).
|
||||||
|
parts = classname.split(".")
|
||||||
|
pdb_cls = getattr(mod, parts[0])
|
||||||
|
for part in parts[1:]:
|
||||||
|
pdb_cls = getattr(pdb_cls, part)
|
||||||
|
|
||||||
|
return pdb_cls
|
||||||
|
except Exception as exc:
|
||||||
|
value = ":".join((modname, classname))
|
||||||
|
raise UsageError("--pdbcls: could not import {!r}: {}".format(value, exc))
|
||||||
|
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
pdb_cls = config.getvalue("usepdb_cls")
|
pdb_cls = config.getvalue("usepdb_cls")
|
||||||
if not pdb_cls:
|
if pdb_cls:
|
||||||
|
pdb_cls = _import_pdbcls(*pdb_cls)
|
||||||
|
else:
|
||||||
pdb_cls = pdb.Pdb
|
pdb_cls = pdb.Pdb
|
||||||
|
|
||||||
if config.getvalue("trace"):
|
if config.getvalue("trace"):
|
||||||
|
|
|
@ -2,7 +2,6 @@ from __future__ import absolute_import
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import argparse
|
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
|
@ -804,13 +803,12 @@ class TestPDB(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_pdb_validate_usepdb_cls(self, testdir):
|
def test_pdb_validate_usepdb_cls(self, testdir):
|
||||||
assert _validate_usepdb_cls("os.path:dirname.__name__") == "dirname"
|
assert _validate_usepdb_cls("os.path:dirname.__name__") == (
|
||||||
|
"os.path",
|
||||||
|
"dirname.__name__",
|
||||||
|
)
|
||||||
|
|
||||||
with pytest.raises(
|
assert _validate_usepdb_cls("pdb:DoesNotExist") == ("pdb", "DoesNotExist")
|
||||||
argparse.ArgumentTypeError,
|
|
||||||
match=r"^could not get pdb class for 'pdb:DoesNotExist': .*'DoesNotExist'",
|
|
||||||
):
|
|
||||||
_validate_usepdb_cls("pdb:DoesNotExist")
|
|
||||||
|
|
||||||
def test_pdb_custom_cls_without_pdb(self, testdir, custom_pdb_calls):
|
def test_pdb_custom_cls_without_pdb(self, testdir, custom_pdb_calls):
|
||||||
p1 = testdir.makepyfile("""xxx """)
|
p1 = testdir.makepyfile("""xxx """)
|
||||||
|
@ -1136,3 +1134,35 @@ def test_pdb_skip_option(testdir):
|
||||||
result = testdir.runpytest_inprocess("--pdb-ignore-set_trace", "-s", p)
|
result = testdir.runpytest_inprocess("--pdb-ignore-set_trace", "-s", p)
|
||||||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||||
result.stdout.fnmatch_lines(["*before_set_trace*", "*after_set_trace*"])
|
result.stdout.fnmatch_lines(["*before_set_trace*", "*after_set_trace*"])
|
||||||
|
|
||||||
|
|
||||||
|
def test_pdbcls_via_local_module(testdir):
|
||||||
|
"""It should be imported in pytest_configure or later only."""
|
||||||
|
p1 = testdir.makepyfile(
|
||||||
|
"""
|
||||||
|
def test():
|
||||||
|
print("before_settrace")
|
||||||
|
__import__("pdb").set_trace()
|
||||||
|
""",
|
||||||
|
mypdb="""
|
||||||
|
class Wrapped:
|
||||||
|
class MyPdb:
|
||||||
|
def set_trace(self, *args):
|
||||||
|
print("mypdb_called", args)
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
result = testdir.runpytest(
|
||||||
|
str(p1), "--pdbcls=really.invalid:Value", syspathinsert=True
|
||||||
|
)
|
||||||
|
result.stderr.fnmatch_lines(
|
||||||
|
[
|
||||||
|
"ERROR: --pdbcls: could not import 'really.invalid:Value': No module named *really*"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
assert result.ret == 4
|
||||||
|
|
||||||
|
result = testdir.runpytest(
|
||||||
|
str(p1), "--pdbcls=mypdb:Wrapped.MyPdb", syspathinsert=True
|
||||||
|
)
|
||||||
|
assert result.ret == 0
|
||||||
|
result.stdout.fnmatch_lines(["*mypdb_called*", "* 1 passed in *"])
|
||||||
|
|
Loading…
Reference in New Issue