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