-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Description
When using e.g. --pdbcls=IPython.terminal.debugger:TerminalPdb with pytest, it might import TerminalPdb with output capturing being active, which results in _use_simple_prompt being True then.
The debugger_cls will return Pdb then (which makes --pdbcls=ipdb:__main__.debugger_cls not crash, but use the simple prompt).
The crash:
def test_foo():
print(1)
> __import__('pytest').set_trace()
t-pdb.py:7:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src/_pytest/debugging.py:221: in set_trace
_pdb = cls._init_pdb(*args, **kwargs)
src/_pytest/debugging.py:211: in _init_pdb
_pdb = _PdbWrapper(**kwargs)
../ipython/IPython/terminal/debugger.py:27: in __init__
self.pt_init()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <_pytest.debugging.pytestPDB._init_pdb.<locals>._PdbWrapper object at 0x7f74ea3c75f8>
self.pt_app = PromptSession(
message=(lambda: PygmentsTokens(get_prompt_tokens())),
editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()),
key_bindings=kb,
history=self.shell.debugger_history,
completer=self._ptcomp,
enable_history_search=True,
mouse_support=self.shell.mouse_support,
complete_style=self.shell.pt_complete_style,
> style=self.shell.style,
inputhook=self.shell.inputhook,
color_depth=self.shell.color_depth,
)
E AttributeError: 'TerminalInteractiveShell' object has no attribute 'style'
../ipython/IPython/terminal/debugger.py:62: AttributeError
Code reference:
ipython/IPython/terminal/interactiveshell.py
Lines 75 to 98 in b70b3f2
| # conservatively check for tty | |
| # overridden streams can result in things like: | |
| # - sys.stdin = None | |
| # - no isatty method | |
| for _name in ('stdin', 'stdout', 'stderr'): | |
| _stream = getattr(sys, _name) | |
| if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty(): | |
| _is_tty = False | |
| break | |
| else: | |
| _is_tty = True | |
| _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty) | |
| class TerminalInteractiveShell(InteractiveShell): | |
| space_for_menu = Integer(6, help='Number of line at the bottom of the screen ' | |
| 'to reserve for the completion menu' | |
| ).tag(config=True) | |
| pt_app = None | |
| debugger_history = None | |
| simple_prompt = Bool(_use_simple_prompt, |
- I think there should be a way to force usage of the enhanced prompt always (via a new class maybe?)
- the is-a-tty check should be done on initialization, not import time
- the is-a-tty check should not require all streams to be a tty really (usually it is ok for one of them to be a tty)
- it should not crash like this in the first place (i.e. not try to access an attribute that is skipped ()
ipython/IPython/terminal/interactiveshell.py
Line 249 in b70b3f2
if self.simple_prompt:
I can think of fixes in pytest itself (e.g. disabling capturing for when the debugger class is imported, or importing it only later), but there are several issues here that should be addressed also.