fix issue126 : introduce py.test.set_trace() to allow dropping to
interactive debugging even when py.test is configured to capture output.
If you like you can override pdb.set_trace by default like this:
    # content of conftest.py
    def pytest_configure():
        import py, pdb
        pdb.set_trace = py.test.set_trace
--HG--
branch : trunk
			
			
This commit is contained in:
		
							parent
							
								
									60a9b60634
								
							
						
					
					
						commit
						eccc2a868c
					
				| 
						 | 
				
			
			@ -182,6 +182,8 @@ class CaptureManager:
 | 
			
		|||
                outerr = (item.outerr[0] + outerr[0],
 | 
			
		||||
                          item.outerr[1] + outerr[1])
 | 
			
		||||
            return outerr
 | 
			
		||||
        if hasattr(item, 'outerr'):
 | 
			
		||||
            return item.outerr
 | 
			
		||||
        return "", ""
 | 
			
		||||
 | 
			
		||||
    def activate_funcargs(self, pyfuncitem):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,9 +10,37 @@ def pytest_addoption(parser):
 | 
			
		|||
               action="store_true", dest="usepdb", default=False,
 | 
			
		||||
               help="start the interactive Python debugger on errors.")
 | 
			
		||||
 | 
			
		||||
def pytest_namespace():
 | 
			
		||||
    return {'set_trace': pytestPDB().set_trace}
 | 
			
		||||
 | 
			
		||||
def pytest_configure(config):
 | 
			
		||||
    if config.getvalue("usepdb"):
 | 
			
		||||
        config.pluginmanager.register(PdbInvoke(), 'pdb')
 | 
			
		||||
        config.pluginmanager.register(PdbInvoke(), 'pdbinvoke')
 | 
			
		||||
 | 
			
		||||
class pytestPDB:
 | 
			
		||||
    """ Pseudo PDB that defers to the real pdb. """
 | 
			
		||||
    item = None
 | 
			
		||||
 | 
			
		||||
    def set_trace(self):
 | 
			
		||||
        """ invoke PDB set_trace debugging, dropping any IO capturing. """
 | 
			
		||||
        frame = sys._getframe().f_back
 | 
			
		||||
        item = getattr(self, 'item', None)
 | 
			
		||||
        if item is not None:
 | 
			
		||||
            capman = item.config.pluginmanager.getplugin("capturemanager")
 | 
			
		||||
            out, err = capman.suspendcapture()
 | 
			
		||||
            if hasattr(item, 'outerr'):
 | 
			
		||||
                item.outerr = (item.outerr[0] + out, item.outerr[1] + err)
 | 
			
		||||
            tw = py.io.TerminalWriter()
 | 
			
		||||
            tw.line()
 | 
			
		||||
            tw.sep(">", "PDB set_trace (IO-capturing turned off)")
 | 
			
		||||
        py.std.pdb.Pdb().set_trace(frame)
 | 
			
		||||
 | 
			
		||||
def pdbitem(item):
 | 
			
		||||
    pytestPDB.item = item
 | 
			
		||||
pytest_runtest_setup = pytest_runtest_call = pytest_runtest_teardown = pdbitem
 | 
			
		||||
 | 
			
		||||
def pytest_runtest_makereport():
 | 
			
		||||
    pytestPDB.item = None
 | 
			
		||||
    
 | 
			
		||||
class PdbInvoke:
 | 
			
		||||
    def pytest_sessionfinish(self, session):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -351,13 +351,17 @@ class TmpTestdir:
 | 
			
		|||
        return self.runpybin("py.test", *args)
 | 
			
		||||
 | 
			
		||||
    def spawn_pytest(self, string, expect_timeout=10.0):
 | 
			
		||||
        pexpect = py.test.importorskip("pexpect", "2.4")
 | 
			
		||||
        if self.request.config.getvalue("notoolsonpath"):
 | 
			
		||||
            py.test.skip("--no-tools-on-path prevents running pexpect-spawn tests")
 | 
			
		||||
        basetemp = self.tmpdir.mkdir("pexpect")
 | 
			
		||||
        invoke = self._getpybinargs("py.test")[0]
 | 
			
		||||
        cmd = "%s --basetemp=%s %s" % (invoke, basetemp, string)
 | 
			
		||||
        child = pexpect.spawn(cmd, logfile=basetemp.join("spawn.out").open("w"))
 | 
			
		||||
        return self.spawn(cmd, expect_timeout=expect_timeout)
 | 
			
		||||
 | 
			
		||||
    def spawn(self, cmd, expect_timeout=10.0):
 | 
			
		||||
        pexpect = py.test.importorskip("pexpect", "2.4")
 | 
			
		||||
        logfile = self.tmpdir.join("spawn.out")
 | 
			
		||||
        child = pexpect.spawn(cmd, logfile=logfile.open("w"))
 | 
			
		||||
        child.timeout = expect_timeout
 | 
			
		||||
        return child
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
import py
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
class TestPDB:
 | 
			
		||||
    def pytest_funcarg__pdblist(self, request):
 | 
			
		||||
| 
						 | 
				
			
			@ -83,3 +84,62 @@ class TestPDB:
 | 
			
		|||
        child.expect("1 failed")
 | 
			
		||||
        if child.isalive():
 | 
			
		||||
            child.wait()
 | 
			
		||||
 | 
			
		||||
    def test_pdb_interaction_capturing_simple(self, testdir):
 | 
			
		||||
        p1 = testdir.makepyfile("""
 | 
			
		||||
            import py
 | 
			
		||||
            def test_1():
 | 
			
		||||
                i = 0
 | 
			
		||||
                print ("hello17")
 | 
			
		||||
                py.test.set_trace()
 | 
			
		||||
                x = 3
 | 
			
		||||
        """)
 | 
			
		||||
        child = testdir.spawn_pytest(str(p1))
 | 
			
		||||
        child.expect("test_1")
 | 
			
		||||
        child.expect("x = 3")
 | 
			
		||||
        child.expect("(Pdb)")
 | 
			
		||||
        child.sendeof()
 | 
			
		||||
        rest = child.read()
 | 
			
		||||
        assert "1 failed" in rest
 | 
			
		||||
        assert "def test_1" in rest
 | 
			
		||||
        assert "hello17" in rest # out is captured
 | 
			
		||||
        if child.isalive():
 | 
			
		||||
            child.wait()
 | 
			
		||||
 | 
			
		||||
    def test_pdb_interaction_capturing_twice(self, testdir):
 | 
			
		||||
        p1 = testdir.makepyfile("""
 | 
			
		||||
            import py
 | 
			
		||||
            def test_1():
 | 
			
		||||
                i = 0
 | 
			
		||||
                print ("hello17")
 | 
			
		||||
                py.test.set_trace()
 | 
			
		||||
                x = 3
 | 
			
		||||
                print ("hello18")
 | 
			
		||||
                py.test.set_trace()
 | 
			
		||||
                x = 4
 | 
			
		||||
        """)
 | 
			
		||||
        child = testdir.spawn_pytest(str(p1))
 | 
			
		||||
        child.expect("test_1")
 | 
			
		||||
        child.expect("x = 3")
 | 
			
		||||
        child.expect("(Pdb)")
 | 
			
		||||
        child.sendline('c')
 | 
			
		||||
        child.expect("x = 4")
 | 
			
		||||
        child.sendeof()
 | 
			
		||||
        rest = child.read()
 | 
			
		||||
        assert "1 failed" in rest
 | 
			
		||||
        assert "def test_1" in rest
 | 
			
		||||
        assert "hello17" in rest # out is captured
 | 
			
		||||
        assert "hello18" in rest # out is captured
 | 
			
		||||
        if child.isalive():
 | 
			
		||||
            child.wait()
 | 
			
		||||
 | 
			
		||||
    def test_pdb_used_outside_test(self, testdir):
 | 
			
		||||
        p1 = testdir.makepyfile("""
 | 
			
		||||
            import py
 | 
			
		||||
            py.test.set_trace()
 | 
			
		||||
            x = 5
 | 
			
		||||
        """)
 | 
			
		||||
        child = testdir.spawn("%s %s" %(sys.executable, p1))
 | 
			
		||||
        child.expect("x = 5")
 | 
			
		||||
        child.sendeof()
 | 
			
		||||
        child.wait()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue