Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/_pytest/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,16 +633,20 @@ def snap(self):

class SysCapture:

CLOSE_STDIN = object
EMPTY_BUFFER = str()
_state = None

def __init__(self, fd, tmpfile=None):
def __init__(self, fd, tmpfile=None, stdin=CLOSE_STDIN):
name = patchsysdict[fd]
self._old = getattr(sys, name)
self.name = name
if tmpfile is None:
if name == "stdin":
tmpfile = DontReadFromInput()
if stdin is self.CLOSE_STDIN:
tmpfile = DontReadFromInput()
else:
tmpfile = stdin
else:
tmpfile = CaptureIO()
self.tmpfile = tmpfile
Expand Down
26 changes: 24 additions & 2 deletions src/_pytest/pytester.py
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ class reprec:
for finalizer in finalizers:
finalizer()

def runpytest_inprocess(self, *args, **kwargs):
def runpytest_inprocess(self, *args, stdin=CLOSE_STDIN, **kwargs):
"""Return result of running pytest in-process, providing a similar
interface to what self.runpytest() provides.
"""
Expand All @@ -856,7 +856,26 @@ def runpytest_inprocess(self, *args, **kwargs):
if syspathinsert:
self.syspathinsert()
now = time.time()
capture = MultiCapture(Capture=SysCapture)
if stdin is self.CLOSE_STDIN:
Capture = SysCapture
else:
old_stdin = sys.stdin
if isinstance(stdin, str):
import io
import functools

class EchoingInput(io.StringIO):
def readline(self, *args, **kwargs):
ret = super().readline(*args, **kwargs)
if ret is not None:
sys.stdout.write(ret)
return ret

Capture = functools.partial(SysCapture, stdin=EchoingInput(stdin))
else:
Capture = stdin

capture = MultiCapture(Capture=Capture)
capture.start_capturing()
try:
try:
Expand All @@ -878,6 +897,9 @@ class reprec:
sys.stdout.write(out)
sys.stderr.write(err)

if stdin is not self.CLOSE_STDIN:
sys.stdin = old_stdin

res = RunResult(reprec.ret, out.split("\n"), err.split("\n"), time.time() - now)
res.reprec = reprec
return res
Expand Down
16 changes: 10 additions & 6 deletions testing/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,17 +724,21 @@ def test_pdb_used_in_generate_tests(self, testdir):
"""
import pytest
def pytest_generate_tests(metafunc):
pytest.set_trace()
x = 5
pytest.set_trace()

def test_foo(a):
pass
"""
)
child = testdir.spawn_pytest(str(p1))
child.expect("x = 5")
child.expect("Pdb")
child.sendeof()
self.flush(child)
result = testdir.runpytest(str(p1), stdin="p 'x=' + str(x)\nq\n")
result.stdout.fnmatch_lines(
[
"*> PDB set_trace (IO-capturing turned off) >*",
"'x=5'",
"E _pytest.outcomes.Exit: Quitting debugger",
]
)

def test_pdb_collection_failure_is_shown(self, testdir):
p1 = testdir.makepyfile("xxx")
Expand Down