gotcha / ipdb

Integration of IPython pdb
BSD 3-Clause "New" or "Revised" License
1.86k stars 147 forks source link

Weird prompttoolkit error when running with `ipdb` #151

Open alphaCTzo7G opened 6 years ago

alphaCTzo7G commented 6 years ago

I am getting this error when I try to insert a breakpoint with ipdb using import ipbd; ipdb.set_trace().

================================== FAILURES ===================================
________________ TestClass.test_Class _________________

self = <pkg.tests.test_module.TestClass object at 0x103F0050>

>       import ipdb; ipdb.set_trace()  # XXX BREAKPOINT

pkg\tests\test_module.py:547: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
automatework\env\lib\site-packages\ipdb\__main__.py:67: in set_trace
    p = _init_pdb(context).set_trace(frame)
automatework\env\lib\site-packages\ipdb\__main__.py:48: in _init_pdb
    p = debugger_cls(def_colors, context=context)
automatework\env\lib\site-packages\IPython\terminal\debugger.py:26: in __init__
    self.pt_init()
automatework\env\lib\site-packages\IPython\terminal\debugger.py:68: in pt_init
    self.pt_cli = CommandLineInterface(self._pt_app, eventloop=self.shell._eventloop)
automatework\env\lib\site-packages\prompt_toolkit\interface.py:80: in __init__
    self.output = output or create_output()
automatework\env\lib\site-packages\prompt_toolkit\shortcuts.py:118: in create_output
    return Win32Output(stdout)
automatework\env\lib\site-packages\prompt_toolkit\terminal\win32_output.py:80: in __init__
    info = self.get_win32_screen_buffer_info()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <prompt_toolkit.terminal.win32_output.Win32Output object at 0x10422C90>

    def get_win32_screen_buffer_info(self):
        """
            Return Screen buffer info.
            """
        # NOTE: We don't call the `GetConsoleScreenBufferInfo` API through
        #     `self._winapi`. Doing so causes Python to crash on certain 64bit
        #     Python versions. (Reproduced with 64bit Python 2.7.6, on Windows
        #     10). It is not clear why. Possibly, it has to do with passing
        #     these objects as an argument, or through *args.

        # The Python documentation contains the following - possibly related - warning:
        #     ctypes does not support passing unions or structures with
        #     bit-fields to functions by value. While this may work on 32-bit
        #     x86, it's not guaranteed by the library to work in the general
        #     case. Unions and structures with bit-fields should always be
        #     passed to functions by pointer.

        # Also see:
        #    - https://github.com/ipython/ipython/issues/10070
        #    - https://github.com/jonathanslenders/python-prompt-toolkit/issues/406
        #    - https://github.com/jonathanslenders/python-prompt-toolkit/issues/86

        self.flush()
        sbinfo = CONSOLE_SCREEN_BUFFER_INFO()
        success = windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(sbinfo))

        # success = self._winapi(windll.kernel32.GetConsoleScreenBufferInfo,
        #                        self.hconsole, byref(sbinfo))

        if success:
            return sbinfo
        else:
>           raise NoConsoleScreenBufferError
E           prompt_toolkit.terminal.win32_output.NoConsoleScreenBufferError: No Windows console found. Are you running cmd.exe?

automatework\env\lib\site-packages\prompt_toolkit\terminal\win32_output.py:172: NoConsoleScreenBufferError
====================== 1 failed, 1 error in 0.43 seconds ======================

When I remove the import ipdb; ipdb.set_trace() it seems the error goes away.

The error happens pretty repeatably now by running it this way:

in Ipython:

In [1]: with redirect_output("C:/Users/username/Desktop/logging_file.log", "C:/Users/username/Desktop/logging_file.log"):
   ...:     %cd D:/path/to/pkg
   ...:     %reset -s -f
   ...:     %run -m pytest -- --capture=fd pkg/tests/test_module.py::TestClass

where redirect_output is as follows (https://stackoverflow.com/a/14573397/4752883):

class redirect_output(object):
    """context manager for reditrecting stdout/err to files"""

    def __init__(self, stdout='', stderr=''):
        self.stdout = stdout
        self.stderr = stderr

    def __enter__(self):
        self.sys_stdout = sys.stdout
        self.sys_stderr = sys.stderr

        if self.stdout:
            sys.stdout = open(self.stdout, 'a+')
        if self.stderr:
            if self.stderr == self.stdout:
                sys.stderr = sys.stdout
            else:
                sys.stderr = open(self.stderr, 'a+')

    def __exit__(self, exc_type, exc_value, traceback):
        sys.stdout = self.sys_stdout
        sys.stderr = self.sys_stderr

Can this be resolved, or any pointers to resovle this?

alphaCTzo7G commented 6 years ago

Couple of other observations:

  1. this doesn't happen if I use pdb instead of ipdb.
  2. the redirect_output function doesn't seem to have anything to do with this error. even if I just run
%cd D:/path/to/pkg
%reset -s -f
%run -m pytest -- --capture=fd pkg/tests/test_module.py::TestClass

I can still reproduce it.

gotcha commented 6 years ago

This seems to be related to pytest. Did you ask that community ?

alphaCTzo7G commented 6 years ago

hmm... I see.. I thought it was something to do with ipdb, because the same thing works fine when using pdb.

So I had to start using pdb when I wanted to capture the output.

I will ask the pytest community as well..