--- contrib/python/pytest/py3/_pytest/debugging.py (index) +++ contrib/python/pytest/py3/_pytest/debugging.py (working tree) @@ -1,6 +1,7 @@ from __future__ import absolute_import """Interactive debugging with PDB, the Python Debugger.""" import argparse import functools +import os import sys import types from typing import Any @@ -29,6 +30,42 @@ from _pytest import outcomes from _pytest.runner import CallInfo +def import_readline(): + try: + import readline + except ImportError: + sys.path.append('/usr/lib/python2.7/lib-dynload') + + try: + import readline + except ImportError as e: + print('can not import readline:', e) + + import subprocess + try: + subprocess.check_call('stty icrnl'.split()) + except OSError as e: + print('can not restore Enter, use Control+J:', e) + + +def tty(): + if os.isatty(1): + return + + fd = os.open('/dev/tty', os.O_RDWR) + os.dup2(fd, 0) + os.dup2(fd, 1) + os.dup2(fd, 2) + os.close(fd) + + old_sys_path = sys.path + sys.path = list(sys.path) + try: + import_readline() + finally: + sys.path = old_sys_path + + def _validate_usepdb_cls(value: str) -> Tuple[str, str]: """Validate syntax of --pdbcls option.""" try: @@ -277,6 +314,7 @@ class pytestPDB(object): @classmethod def set_trace(cls, *args, **kwargs) -> None: """Invoke debugging via ``Pdb.set_trace``, dropping any IO capturing.""" + tty() frame = sys._getframe().f_back _pdb = cls._init_pdb("set_trace", *args, **kwargs) _pdb.set_trace(frame) @@ -292,6 +330,7 @@ class PdbInvoke(object): out, err = capman.read_global_capture() sys.stdout.write(out) sys.stdout.write(err) + tty() assert call.excinfo is not None _enter_pdb(node, call.excinfo, report)