pdb++, a drop-in replacement for pdb (the Python debugger)

Overview

pdb++, a drop-in replacement for pdb

What is it?

This module is an extension of the pdb module of the standard library. It is meant to be fully compatible with its predecessor, yet it introduces a number of new features to make your debugging experience as nice as possible.

https://user-images.githubusercontent.com/412005/64484794-2f373380-d20f-11e9-9f04-e1dabf113c6f.png

pdb++ features include:

  • colorful TAB completion of Python expressions (through fancycompleter)
  • optional syntax highlighting of code listings (through Pygments)
  • sticky mode
  • several new commands to be used from the interactive (Pdb++) prompt
  • smart command parsing (hint: have you ever typed r or c at the prompt to print the value of some variable?)
  • additional convenience functions in the pdb module, to be used from your program

pdb++ is meant to be a drop-in replacement for pdb. If you find some unexpected behavior, please report it as a bug.

Installation

Since pdb++ is not a valid package name the package is named pdbpp:

$ pip install pdbpp

pdb++ is also available via conda:

$ conda install -c conda-forge pdbpp

Alternatively, you can just put pdb.py somewhere inside your PYTHONPATH.

Usage

Note that the module is called pdb.py so that pdb++ will automatically be used in all places that do import pdb (e.g. pytest --pdb will give you a pdb++ prompt).

The old pdb module is still available by doing e.g. import pdb; pdb.pdb.set_trace().

New interactive commands

The following are new commands that you can use from the interative (Pdb++) prompt.

sticky [start end]
Toggle sticky mode. When in this mode, every time the current position changes, the screen is repainted and the whole function shown. Thus, when doing step-by-step execution you can easily follow the flow of the execution. If start and end are given, sticky mode is enabled and only lines within that range (extremes included) will be displayed.
longlist (ll)
List source code for the current function. Different from the normal pdb list command, longlist displays the whole function. The current line is marked with ->. In case of post-mortem debugging, the line which actually raised the exception is marked with >>. If the highlight config option is set and Pygments is installed, the source code is highlighted.
interact
Start an interative interpreter whose global namespace contains all the names found in the current scope.
track EXPRESSION
Display a graph showing which objects are the value of the expression refers to and are referred by. This command requires the pypy source code to be importable.
display EXPRESSION
Add an expression to the display list; expressions in this list are evaluated at each step, and printed every time its value changes. WARNING: since these expressions are evaluated multiple times, make sure not to put expressions with side-effects in the display list.
undisplay EXPRESSION:
Remove EXPRESSION from the display list.
source EXPRESSION
Show the source code for the given function/method/class.
edit EXPRESSION
Open the editor in the right position to edit the given function/method/class. The editor used is specified in a config option.
hf_unhide, hf_hide, hf_list
Some frames might be marked as "hidden" by e.g. using the @pdb.hideframe function decorator. By default, hidden frames are not shown in the stack trace, and cannot be reached using up and down. You can use hf_unhide to tell pdb to ignore the hidden status (i.e., to treat hidden frames as normal ones), and hf_hide to hide them again. hf_list prints a list of hidden frames. The config option enable_hidden_frames can be used to disable handling of hidden frames in general.

Smart command parsing

By default, pdb tries hard to interpret what you enter at the command prompt as one of its builtin commands. However, this is inconvenient if you want to just print the value of a local variable which happens to have the same name as one of the commands. E.g.:

(Pdb) list
  1
  2     def fn():
  3         c = 42
  4         import pdb;pdb.set_trace()
  5  ->     return c
(Pdb) c

In the example above, instead of printing 42 pdb interprets the input as the command continue, and then you lose your prompt. It's even worse than that, because it happens even if you type e.g. c.__class__.

pdb++ fixes this unfriendly (from the author's point of view, of course :-)) behavior by always prefering variable in scope, if it exists. If you really want to execute the corresponding command, you can prefix it with !!. Thus, the example above becomes:

(Pdb++) list
  1
  2     def fn():
  3         c = 42
  4         import pdb;pdb.set_trace()
  5  ->     return c
(Pdb++) c
42
(Pdb++) !!c

Note that the "smart" behavior takes place only when there is ambiguity, i.e. if there exists a variable with the same name as a command: in all other cases, everything works as usual.

Regarding the list command itself, using list(… is a special case that gets handled as the Python builtin:

(Pdb++) list([1, 2])
[1, 2]

Additional functions in the pdb module

The pdb module that comes with pdb++ includes all the functions and classes that are in the module from the standard library. If you find any difference, please report it as a bug.

In addition, there are some new convenience functions that are unique to pdb++.

pdb.xpm()
eXtended Post Mortem: it is equivalent to pdb.post_mortem(sys.exc_info()[2]). If used inside an except clause, it will start a post-mortem pdb prompt from the line that raised the exception being caught.
pdb.disable()
Disable pdb.set_trace(): any subsequent call to it will be ignored.
pdb.enable()
Re-enable pdb.set_trace(), in case it was disabled by pdb.disable().
@pdb.hideframe
A function decorator that tells pdb++ to hide the frame corresponding to the function. Hidden frames do not show up when using interactive commands such as up, down or where, unless hf_unhide is invoked.
@pdb.break_on_setattr(attrname, condition=always)

class decorator: break the execution of the program every time the attribute attrname is set on any instance of the class. condition is a callable that takes the target object of the setattr and the actual value; by default, it breaks every time the attribute is set. E.g.:

@break_on_setattr('bar')
class Foo(object):
    pass
f = Foo()
f.bar = 42    # the program breaks here

If can be used even after the class has already been created, e.g. if we want to break when some attribute of a particular object is set:

class Foo(object):
    pass
a = Foo()
b = Foo()

def break_if_a(obj, value):
    return obj is a

break_on_setattr('bar', condition=break_if_a)(Foo)
b.bar = 10   # no break
a.bar = 42   # the program breaks here

This can be used after pdb.set_trace() also:

(Pdb++) import pdb
(Pdb++) pdb.break_on_setattr('tree_id')(obj.__class__)
(Pdb++) continue

Configuration and customization

To customize pdb++, you can put a file named .pdbrc.py in your home directory. The file must contain a class named Config inheriting from pdb.DefaultConfig and override the desired values.

The following is a list of the options you can customize, together with their default value:

prompt = '(Pdb++) '
The prompt to show when in interactive mode.
highlight = True
Highlight line numbers and the current line when showing the longlist of a function or when in sticky mode.
encoding = 'utf-8'
File encoding. Useful when there are international characters in your string literals or comments.
sticky_by_default = False
Determine whether pdb++ starts in sticky mode or not.
line_number_color = pdb.Color.turquoise
The color to use for line numbers. See Notes on color options.
filename_color = pdb.Color.yellow
The color to use for file names when printing the stack entries. See Notes on color options.
current_line_color = "39;49;7"
The SGR parameters for the ANSI escape sequence to highlight the current line. The default uses the default foreground (39) and background (49) colors, inversed (7). See Notes on color options.
editor = None
The command to invoke when using the edit command. By default, it uses $EDITOR if set, else vim or vi (if found). If only the editor command is specified, the emacs and vi notation will be used to specify the line number: COMMAND +n filename. It's otherwise possible to use another syntax by using the placeholders {filename} and {lineno}. For example with sublime text, specify editor = "subl {filename}:{lineno}".
truncate_long_lines = True
Truncate lines which exceed the terminal width.
exec_if_unfocused = None
Shell command to execute when starting the pdb prompt and the terminal window is not focused. Useful to e.g. play a sound to alert the user that the execution of the program stopped. It requires the wmctrl module.
enable_hidden_frames = True
Certain frames can be hidden by default. If enabled, the commands hf_unhide, hf_hide, and hf_list can be used to control display of them.
show_hidden_frames_count = True
If enable_hidden_frames is True this controls if the number of hidden frames gets displayed.
def setup(self, pdb): pass
This method is called during the initialization of the Pdb class. Useful to do complex setup.
show_traceback_on_error = True

Display tracebacks for errors via Pdb.error, that come from Pdb.default (i.e. the execution of an unrecognized pdb command), and are not a direct cause of the expression itself (e.g. NameError with a command like doesnotexist).

With this option disabled only *** exception string gets printed, which often misses useful context.

show_traceback_on_error_limit = None
This option sets the limit to be used with traceback.format_exception, when show_traceback_on_error is enabled.

Options relevant for source code highlighting (using Pygments)

use_pygments = None
By default Pygments is used for syntax highlighting of source code when it can be imported, e.g. when showing the longlist of a function or when in sticky mode.

pygments_formatter_class = None

You can configure the Pygments formatter to use via the pygments_formatter_class config setting as a string (dotted path). This should should be one of the following typically: "pygments.formatters.Terminal256Formatter", "pygments.formatters.TerminalTrueColorFormatter", or "pygments.formatters.TerminalFormatter".

The default is to auto-detect the best formatter based on the $TERM variable, e.g. it uses Terminal256Formatter if the $TERM variable contains "256color" (e.g. xterm-256color), but also knows about e.g. "xterm-kitty" to support true colors (TerminalTrueColorFormatter). TerminalFormatter gets used as a fallback.

pygments_formatter_kwargs = {}

A dictionary of keyword arguments to pass to the formatter's contructor.

The default arguments (updated with this setting) are:

   {
       "style": "default",
       "bg": self.config.bg,
       "colorscheme": self.config.colorscheme,
   }

 ``style = 'default'``

  The style to use, can be a string or a Pygments Style subclass.
  E.g. ``"solarized-dark"``.
  See http://pygments.org/docs/styles/.

``bg = 'dark'``

  Selects a different palette for dark/light backgrounds.
  Only used by ``TerminalFormatter``.

``colorscheme = None``

  A dictionary mapping token types to (lightbg, darkbg) color names or
  ``None`` (default: ``None`` = use builtin colorscheme).
  Only used by ``TerminalFormatter``.

Example:

class Config(pdb.DefaultConfig):
    pygments_formatter_class = "pygments.formatters.TerminalTrueColorFormatter"
    pygments_formatter_kwargs = {"style": "solarized-light"}

Notes on color options

The values for color options will be used inside of the SGR escape sequence \e[%sm where \e is the ESC character and %s the given value. See SGR parameters.

The following means "reset all colors" (0), set foreground color to 18 (48;5;18), and background to 21: "0;48;5;18;38;5;21".

Constants are available via pdb.Color, e.g. pdb.Color.red ("31;01"), but in general any string can be used here.

Coding guidelines

pdb++ is developed using Test Driven Development, and we try to keep test coverage high.

As a general rule, every commit should come with its own test. If it's a new feature, it should come with one or many tests which excercise it. If it's a bug fix, the test should fail before the fix, and pass after.

The goal is to make refactoring easier in the future: if you wonder why a certain line of code does something, in principle it should be possible to comment it out and see which tests fail.

In exceptional cases, the test might be too hard or impossible to write: in that cases it is fine to do a commmit without a test, but you should explain very precisely in the commit message why it is hard to write a test and how to reproduce the buggy behaviour by hand.

It is fine NOT to write a test in the following cases:

  • typos, documentation, and in general any non-coding commit
  • code refactorings which do not add any feature
  • commits which fix an already failing test
  • commits to silence warnings
  • purely cosmetic changes, such as change the color of the output
Issues
  • TypeError: write() argument must be str, not bytes

    TypeError: write() argument must be str, not bytes

    Originally reported by: Aurélien Campéas (Bitbucket: auc, GitHub: auc)


    #!python
    
      File "C:\Anaconda2\envs\py3k\lib\site-packages\_pytest\pdb.py", line 109, in post_mortem
        p.interaction(None, t)
      File "C:\Anaconda2\envs\py3k\lib\site-packages\pdb.py", line 244, in interaction
        self.print_stack_entry(self.stack[self.curindex])
      File "C:\Anaconda2\envs\py3k\lib\site-packages\pdb.py", line 798, in print_stack_entry
        print('[%d] >' % frame_index, file=self.stdout, end=' ')
      File "C:\Anaconda2\envs\py3k\lib\codecs.py", line 377, in write
        self.stream.write(data)
    TypeError: write() argument must be str, not bytes
    

    • Bitbucket: https://bitbucket.org/antocuni/pdb/issue/63
    bug major 
    opened by antocuni 20
  • Windows tests

    Windows tests

    Add Windows testing via AppVeyor.

    This is a prerequisite for getting proper Windows support (at least for colors - completion is another issue).

    The basic idea is that paths on Windows are stupid and because we need to support Python < 3.6, we can't easily use pathlib. A lot of the tests are regex comparisons, and what happens is that the forward-slashed Windows paths end up looking like they have escape characters in them (namely \p in ...\pdbpp...).

    So we simply modify those path strings and replace all backslashes \ with forward slashes /.

    In addition, Windows is a case-insensitive file system, so C:\foo is the same as c:\foo. This again causes the regex-based tests to fail, so we add in os.path.normcase which, on windows, changes things to lowercase.

    Sometimes we can't adjust the expected output of a file path (like stacktrace.format_exc), so in those cases we just skip checking those lines if we're testing on Windows.

    Lastly there are a couple tests that I just couldn't figure out why they won't work on Windows. I figured that since they're tested on Linux, it's likely OK to skip them on Windows:

    • test_continue_arg_with_error: 'charmap' codec can't decode byte 0x81.
    • test_complete_removes_duplicates_with_coloring: Fails on AppVeyor, but doesn't fail when I run it locally... /shrug.
    • test_stdout_reconfigured: I think this might be an issue with pyreadline. Full stack trace is:
      C:\dev_python\pdbpp\testing\test_pdb.py:5102: in test_stdout_reconfigured
          """)
      C:\dev_python\pdbpp\testing\test_pdb.py:264: in check
          expected, lines = run_func(func, expected)
      C:\dev_python\pdbpp\testing\test_pdb.py:246: in run_func
          return expected, runpdb(func, commands)
      C:\dev_python\pdbpp\testing\test_pdb.py:180: in runpdb
          func()
      C:\dev_python\pdbpp\testing\test_pdb.py:5086: in fn
          assert pdbpp.local.GLOBAL_PDB.stdout is patched_stdout
      C:\dev_python\pdbpp\testing\test_pdb.py:5086: in fn
          assert pdbpp.local.GLOBAL_PDB.stdout is patched_stdout
      C:\WinPython36_x64_zero\python-3.6.3.amd64\Lib\bdb.py:48: in trace_dispatch
          return self.dispatch_line(frame)
      C:\WinPython36_x64_zero\python-3.6.3.amd64\Lib\bdb.py:66: in dispatch_line
          self.user_line(frame)
      C:\WinPython36_x64_zero\python-3.6.3.amd64\Lib\pdb.py:261: in user_line
          self.interaction(frame, None)
      c:\dev_python\pdbpp\.tox\py36\lib\site-packages\pdbpp.py:401: in interaction
          return self._interaction(frame, traceback)
      c:\dev_python\pdbpp\.tox\py36\lib\site-packages\pdbpp.py:429: in _interaction
          self._cmdloop()
      C:\WinPython36_x64_zero\python-3.6.3.amd64\Lib\pdb.py:321: in _cmdloop
          self.cmdloop()
      C:\WinPython36_x64_zero\python-3.6.3.amd64\Lib\cmd.py:111: in cmdloop
          readline.parse_and_bind(self.completekey+": complete")
      c:\dev_python\pdbpp\.tox\py36\lib\site-packages\pyreadline\rlmain.py:100: in parse_and_bind
          self.mode._bind_key(key, func)
      c:\dev_python\pdbpp\.tox\py36\lib\site-packages\pyreadline\modes\basemode.py:165: in _bind_key
          keyinfo = make_KeyPress_from_keydescr(key.lower()).tuple()
      c:\dev_python\pdbpp\.tox\py36\lib\site-packages\pyreadline\keysyms\common.py:121: in make_KeyPress_from_keydescr
          raise IndexError("Not a valid key: '%s'"%keydescr)
      E   IndexError: Not a valid key: 'ck'
      

    Related to #334.

    opened by dougthor42 18
  • tab doesn't start autocomplete

    tab doesn't start autocomplete

    The prompt is correct, (Pdb++), but a tab just moves the cursor over to the right. Possibly a readline issue on my system?

    opened by liavkoren 16
  • Doesn’t install on OS X

    Doesn’t install on OS X

    Originally reported by: Hynek Schlawack (Bitbucket: hynek, GitHub: hynek)


    Hi,

    0.8 seems to (indirectly) depend on funcsigs 0.2 which fails to install on OS X (it also pulls in distribute, good times). funcsigs 0.4 installs fine.

    $ pip wheel pdbpp
    Collecting pdbpp
      Downloading https://pypi.vm.ag/root/pypi/+f/92e/1b8c947d8a8b9/pdbpp-0.8.tar.gz
    Collecting fancycompleter>=0.2 (from pdbpp)
      Downloading https://pypi.vm.ag/root/pypi/+f/446/67c62c6db6318/fancycompleter-0.4.tar.gz
    Collecting ordereddict (from pdbpp)
      Downloading https://pypi.vm.ag/root/pypi/+f/a0e/d854ee442051b/ordereddict-1.1.tar.gz
    Collecting backports.inspect (from pdbpp)
      Downloading https://pypi.vm.ag/root/pypi/+f/17a/5042b2fdb6c2b/backports.inspect-0.0.2.tar.gz
    Collecting wmctrl (from pdbpp)
      Downloading https://pypi.vm.ag/root/pypi/+f/3dd/c4ca04056627c/wmctrl-0.1.tar.gz
    Collecting pygments (from pdbpp)
      File was already downloaded /Users/hynek/.wheels/Pygments-2.0.2-py3-none-any.whl
    Collecting distribute (from backports.inspect->pdbpp)
      File was already downloaded /Users/hynek/.wheels/distribute-0.7.3-cp34-cp34m-macosx_10_9_x86_64.whl
    Collecting funcsigs==0.2 (from backports.inspect->pdbpp)
      Downloading https://pypi.vm.ag/root/pypi/+f/1f5/6853306a9aa69/funcsigs-0.2.tar.gz (698kB)
        100% |################################| 700kB 6.5MB/s
        Downloading http://pypi.python.org/packages/source/d/distribute/distribute-0.6.34.tar.gz
        Extracting in /var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs
        Now working in /var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34
        Building a Distribute egg in /private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs
        RefactoringTool: Skipping implicit fixer: buffer
        RefactoringTool: Skipping implicit fixer: idioms
        RefactoringTool: Skipping implicit fixer: set_literal
        RefactoringTool: Skipping implicit fixer: ws_comma
        RefactoringTool: Refactored build/src/tests/api_tests.txt
        RefactoringTool: Files that were modified:
        RefactoringTool: build/src/tests/api_tests.txt
        --- build/src/tests/api_tests.txt	(original)
        +++ build/src/tests/api_tests.txt	(refactored)
        @@ -39,7 +39,7 @@
             >>> dist.py_version == sys.version[:3]
             True
        -    >>> print dist.platform
        +    >>> print(dist.platform)
             None
         Including various computed attributes::
        @@ -199,7 +199,7 @@
         You can ask a WorkingSet to ``find()`` a distribution matching a requirement::
             >>> from pkg_resources import Requirement
        -    >>> print ws.find(Requirement.parse("Foo==1.0"))    # no match, return None
        +    >>> print(ws.find(Requirement.parse("Foo==1.0")))    # no match, return None
             None
             >>> ws.find(Requirement.parse("Bar==0.9"))  # match, return distribution
        @@ -211,7 +211,7 @@
             >>> try:
             ...     ws.find(Requirement.parse("Bar==1.0"))
             ... except VersionConflict:
        -    ...     print 'ok'
        +    ...     print('ok')
             ok
         You can subscribe a callback function to receive notifications whenever a new
        @@ -219,7 +219,7 @@
         once for each existing distribution in the working set, and then is called
         again for new distributions added thereafter::
        -    >>> def added(dist): print "Added", dist
        +    >>> def added(dist): print("Added", dist)
             >>> ws.subscribe(added)
             Added Bar 0.9
             >>> foo12 = Distribution(project_name="Foo", version="1.2", location="f12")
        Traceback (most recent call last):
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2463, in _dep_map
            return self.__dep_map
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2288, in __getattr__
            raise AttributeError(attr)
        AttributeError: _DistInfoDistribution__dep_map
        During handling of the above exception, another exception occurred:
        Traceback (most recent call last):
          File "setup.py", line 248, in <module>
            scripts = scripts,
          File "/Users/hynek/.pyenv/versions/3.4.2/lib/python3.4/distutils/core.py", line 108, in setup
            _setup_distribution = dist = klass(attrs)
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/setuptools/dist.py", line 225, in __init__
            _Distribution.__init__(self,attrs)
          File "/Users/hynek/.pyenv/versions/3.4.2/lib/python3.4/distutils/dist.py", line 280, in __init__
            self.finalize_options()
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/setuptools/dist.py", line 257, in finalize_options
            ep.require(installer=self.fetch_build_egg)
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2026, in require
            working_set.resolve(self.dist.requires(self.extras),env,installer)))
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2236, in requires
            dm = self._dep_map
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2465, in _dep_map
            self.__dep_map = self._compute_dependencies()
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2498, in _compute_dependencies
            common = frozenset(reqs_for_extra(None))
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2495, in reqs_for_extra
            if req.marker_fn(override={'extra':extra}):
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/_markerlib/markers.py", line 109, in marker_fn
            return eval(compiled_marker, environment)
          File "<environment marker>", line 1, in <module>
        NameError: name 'sys_platform' is not defined
        /private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/distribute-0.6.34-py3.4.egg
        Traceback (most recent call last):
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/distribute_setup.py", line 150, in use_setuptools
            raise ImportError
        ImportError
        During handling of the above exception, another exception occurred:
        Traceback (most recent call last):
          File "<string>", line 20, in <module>
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/setup.py", line 3, in <module>
            use_setuptools()
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/distribute_setup.py", line 152, in use_setuptools
            return _do_download(version, download_base, to_dir, download_delay)
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/distribute_setup.py", line 132, in _do_download
            _build_egg(egg, tarball, to_dir)
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/distribute_setup.py", line 123, in _build_egg
            raise IOError('Could not build the egg.')
        OSError: Could not build the egg.
        Complete output from command python setup.py egg_info:
        Downloading http://pypi.python.org/packages/source/d/distribute/distribute-0.6.34.tar.gz
    
        Extracting in /var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs
    
        Now working in /var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34
    
        Building a Distribute egg in /private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs
    
        creating build
    
        creating build/src
    
        creating build/src/_markerlib
    
        creating build/src/docs
    
        creating build/src/docs/_templates
    
        creating build/src/docs/_theme
    
        creating build/src/docs/_theme/nature
    
        creating build/src/docs/_theme/nature/static
    
        creating build/src/docs/build
    
        creating build/src/docs/build/html
    
        creating build/src/docs/build/html/_sources
    
        creating build/src/docs/build/html/_static
    
        creating build/src/setuptools
    
        creating build/src/setuptools/command
    
        creating build/src/setuptools/tests
    
        creating build/src/setuptools/tests/indexes
    
        creating build/src/setuptools/tests/indexes/test_links_priority
    
        creating build/src/setuptools/tests/indexes/test_links_priority/simple
    
        creating build/src/setuptools/tests/indexes/test_links_priority/simple/foobar
    
        creating build/src/tests
    
        creating build/src/tests/shlib_test
    
        copying setuptools/__init__.py -> build/src/setuptools
    
        copying setuptools/archive_util.py -> build/src/setuptools
    
        copying setuptools/depends.py -> build/src/setuptools
    
        copying setuptools/dist.py -> build/src/setuptools
    
        copying setuptools/extension.py -> build/src/setuptools
    
        copying setuptools/package_index.py -> build/src/setuptools
    
        copying setuptools/sandbox.py -> build/src/setuptools
    
        copying setuptools/script template (dev).py -> build/src/setuptools
    
        copying setuptools/script template.py -> build/src/setuptools
    
        copying setuptools/tests/__init__.py -> build/src/setuptools/tests
    
        copying setuptools/tests/doctest.py -> build/src/setuptools/tests
    
        copying setuptools/tests/py26compat.py -> build/src/setuptools/tests
    
        copying setuptools/tests/server.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_bdist_egg.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_build_ext.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_develop.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_dist_info.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_easy_install.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_markerlib.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_packageindex.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_resources.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_sandbox.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_sdist.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_test.py -> build/src/setuptools/tests
    
        copying setuptools/tests/test_upload_docs.py -> build/src/setuptools/tests
    
        copying setuptools/command/__init__.py -> build/src/setuptools/command
    
        copying setuptools/command/alias.py -> build/src/setuptools/command
    
        copying setuptools/command/bdist_egg.py -> build/src/setuptools/command
    
        copying setuptools/command/bdist_rpm.py -> build/src/setuptools/command
    
        copying setuptools/command/bdist_wininst.py -> build/src/setuptools/command
    
        copying setuptools/command/build_ext.py -> build/src/setuptools/command
    
        copying setuptools/command/build_py.py -> build/src/setuptools/command
    
        copying setuptools/command/develop.py -> build/src/setuptools/command
    
        copying setuptools/command/easy_install.py -> build/src/setuptools/command
    
        copying setuptools/command/egg_info.py -> build/src/setuptools/command
    
        copying setuptools/command/install.py -> build/src/setuptools/command
    
        copying setuptools/command/install_egg_info.py -> build/src/setuptools/command
    
        copying setuptools/command/install_lib.py -> build/src/setuptools/command
    
        copying setuptools/command/install_scripts.py -> build/src/setuptools/command
    
        copying setuptools/command/register.py -> build/src/setuptools/command
    
        copying setuptools/command/rotate.py -> build/src/setuptools/command
    
        copying setuptools/command/saveopts.py -> build/src/setuptools/command
    
        copying setuptools/command/sdist.py -> build/src/setuptools/command
    
        copying setuptools/command/setopt.py -> build/src/setuptools/command
    
        copying setuptools/command/test.py -> build/src/setuptools/command
    
        copying setuptools/command/upload.py -> build/src/setuptools/command
    
        copying setuptools/command/upload_docs.py -> build/src/setuptools/command
    
        copying setuptools/tests/win_script_wrapper.txt -> build/src/setuptools/tests
    
        copying setuptools/cli-32.exe -> build/src/setuptools
    
        copying setuptools/cli-64.exe -> build/src/setuptools
    
        copying setuptools/cli.exe -> build/src/setuptools
    
        copying setuptools/gui-32.exe -> build/src/setuptools
    
        copying setuptools/gui-64.exe -> build/src/setuptools
    
        copying setuptools/gui.exe -> build/src/setuptools
    
        copying tests/install_test.py -> build/src/tests
    
        copying tests/manual_test.py -> build/src/tests
    
        copying tests/test_distribute_setup.py -> build/src/tests
    
        copying tests/shlib_test/setup.py -> build/src/tests/shlib_test
    
        copying tests/shlib_test/test_hello.py -> build/src/tests/shlib_test
    
        copying tests/shlib_test/hello.c -> build/src/tests/shlib_test
    
        copying tests/shlib_test/hellolib.c -> build/src/tests/shlib_test
    
        copying tests/shlib_test/hello.pyx -> build/src/tests/shlib_test
    
        copying tests/api_tests.txt -> build/src/tests
    
        RefactoringTool: Skipping implicit fixer: buffer
    
        RefactoringTool: Skipping implicit fixer: idioms
    
        RefactoringTool: Skipping implicit fixer: set_literal
    
        RefactoringTool: Skipping implicit fixer: ws_comma
    
        RefactoringTool: Refactored build/src/tests/api_tests.txt
    
        RefactoringTool: Files that were modified:
    
        RefactoringTool: build/src/tests/api_tests.txt
    
        --- build/src/tests/api_tests.txt	(original)
    
        +++ build/src/tests/api_tests.txt	(refactored)
    
        @@ -39,7 +39,7 @@
    
             >>> dist.py_version == sys.version[:3]
    
             True
    
    
    
        -    >>> print dist.platform
    
        +    >>> print(dist.platform)
    
             None
    
    
    
         Including various computed attributes::
    
        @@ -199,7 +199,7 @@
    
         You can ask a WorkingSet to ``find()`` a distribution matching a requirement::
    
    
    
             >>> from pkg_resources import Requirement
    
        -    >>> print ws.find(Requirement.parse("Foo==1.0"))    # no match, return None
    
        +    >>> print(ws.find(Requirement.parse("Foo==1.0")))    # no match, return None
    
             None
    
    
    
             >>> ws.find(Requirement.parse("Bar==0.9"))  # match, return distribution
    
        @@ -211,7 +211,7 @@
    
             >>> try:
    
             ...     ws.find(Requirement.parse("Bar==1.0"))
    
             ... except VersionConflict:
    
        -    ...     print 'ok'
    
        +    ...     print('ok')
    
             ok
    
    
    
         You can subscribe a callback function to receive notifications whenever a new
    
        @@ -219,7 +219,7 @@
    
         once for each existing distribution in the working set, and then is called
    
         again for new distributions added thereafter::
    
    
    
        -    >>> def added(dist): print "Added", dist
    
        +    >>> def added(dist): print("Added", dist)
    
             >>> ws.subscribe(added)
    
             Added Bar 0.9
    
             >>> foo12 = Distribution(project_name="Foo", version="1.2", location="f12")
    
        copying setuptools/tests/indexes/test_links_priority/external.html -> build/src/setuptools/tests/indexes/test_links_priority
    
        copying setuptools/tests/indexes/test_links_priority/simple/foobar/index.html -> build/src/setuptools/tests/indexes/test_links_priority/simple/foobar
    
        copying docs/conf.py -> build/src/docs
    
        copying docs/easy_install.txt -> build/src/docs
    
        copying docs/index.txt -> build/src/docs
    
        copying docs/pkg_resources.txt -> build/src/docs
    
        copying docs/python3.txt -> build/src/docs
    
        copying docs/roadmap.txt -> build/src/docs
    
        copying docs/setuptools.txt -> build/src/docs
    
        copying docs/using.txt -> build/src/docs
    
        copying docs/build/html/_sources/easy_install.txt -> build/src/docs/build/html/_sources
    
        copying docs/build/html/_sources/index.txt -> build/src/docs/build/html/_sources
    
        copying docs/build/html/_sources/pkg_resources.txt -> build/src/docs/build/html/_sources
    
        copying docs/build/html/_sources/python3.txt -> build/src/docs/build/html/_sources
    
        copying docs/build/html/_sources/roadmap.txt -> build/src/docs/build/html/_sources
    
        copying docs/build/html/_sources/setuptools.txt -> build/src/docs/build/html/_sources
    
        copying docs/build/html/_sources/using.txt -> build/src/docs/build/html/_sources
    
        copying docs/_theme/nature/theme.conf -> build/src/docs/_theme/nature
    
        copying docs/build/html/_static/basic.css -> build/src/docs/build/html/_static
    
        copying docs/build/html/_static/nature.css -> build/src/docs/build/html/_static
    
        copying docs/build/html/_static/pygments.css -> build/src/docs/build/html/_static
    
        copying docs/_theme/nature/static/pygments.css -> build/src/docs/_theme/nature/static
    
        copying docs/_theme/nature/static/nature.css_t -> build/src/docs/_theme/nature/static
    
        copying docs/Makefile -> build/src/docs
    
        copying docs/_templates/indexsidebar.html -> build/src/docs/_templates
    
        copying _markerlib/__init__.py -> build/src/_markerlib
    
        copying _markerlib/markers.py -> build/src/_markerlib
    
        copying distribute_setup.py -> build/src
    
        copying easy_install.py -> build/src
    
        copying pkg_resources.py -> build/src
    
        copying release.py -> build/src
    
        copying setup.py -> build/src
    
        copying site.py -> build/src
    
        copying CHANGES.txt -> build/src
    
        copying CONTRIBUTORS.txt -> build/src
    
        copying DEVGUIDE.txt -> build/src
    
        copying README.txt -> build/src
    
        copying MANIFEST.in -> build/src
    
        copying launcher.c -> build/src
    
        Skipping implicit fixer: buffer
    
        Skipping implicit fixer: idioms
    
        Skipping implicit fixer: set_literal
    
        Skipping implicit fixer: ws_comma
    
        Traceback (most recent call last):
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2463, in _dep_map
    
            return self.__dep_map
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2288, in __getattr__
    
            raise AttributeError(attr)
    
        AttributeError: _DistInfoDistribution__dep_map
    
    
    
        During handling of the above exception, another exception occurred:
    
    
    
        Traceback (most recent call last):
    
          File "setup.py", line 248, in <module>
    
            scripts = scripts,
    
          File "/Users/hynek/.pyenv/versions/3.4.2/lib/python3.4/distutils/core.py", line 108, in setup
    
            _setup_distribution = dist = klass(attrs)
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/setuptools/dist.py", line 225, in __init__
    
            _Distribution.__init__(self,attrs)
    
          File "/Users/hynek/.pyenv/versions/3.4.2/lib/python3.4/distutils/dist.py", line 280, in __init__
    
            self.finalize_options()
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/setuptools/dist.py", line 257, in finalize_options
    
            ep.require(installer=self.fetch_build_egg)
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2026, in require
    
            working_set.resolve(self.dist.requires(self.extras),env,installer)))
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2236, in requires
    
            dm = self._dep_map
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2465, in _dep_map
    
            self.__dep_map = self._compute_dependencies()
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2498, in _compute_dependencies
    
            common = frozenset(reqs_for_extra(None))
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/pkg_resources.py", line 2495, in reqs_for_extra
    
            if req.marker_fn(override={'extra':extra}):
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/tmpw8_cthqs/distribute-0.6.34/build/src/_markerlib/markers.py", line 109, in marker_fn
    
            return eval(compiled_marker, environment)
    
          File "<environment marker>", line 1, in <module>
    
        NameError: name 'sys_platform' is not defined
    
        /private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/distribute-0.6.34-py3.4.egg
    
        Traceback (most recent call last):
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/distribute_setup.py", line 150, in use_setuptools
    
            raise ImportError
    
        ImportError
    
    
    
        During handling of the above exception, another exception occurred:
    
    
    
        Traceback (most recent call last):
    
          File "<string>", line 20, in <module>
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/setup.py", line 3, in <module>
    
            use_setuptools()
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/distribute_setup.py", line 152, in use_setuptools
    
            return _do_download(version, download_base, to_dir, download_delay)
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/distribute_setup.py", line 132, in _do_download
    
            _build_egg(egg, tarball, to_dir)
    
          File "/private/var/folders/n8/bvhdmjbn4ljc498jpsr3rq6r0000gn/T/pip-build-aby3evdm/funcsigs/distribute_setup.py", line 123, in _build_egg
    
            raise IOError('Could not build the egg.')
    
        OSError: Could not build the egg.
    
        ----------------------------------------
    

    • Bitbucket: https://bitbucket.org/antocuni/pdb/issue/37
    bug critical 
    opened by antocuni 15
  • Namespace confusion

    Namespace confusion

    (CPython) PDB's usual default exec() behavior handles namespaces in very confusing ways

    Consider the following program:

    spam = "global"
    
    def func():
        eggs = "local"
        shopping = ["eggs"]
        breakpoint()
        print(eggs)
        print(shopping)
        print(ham)
    
    func()
    
    1. Restrictive class namespace rules
    -> print(eggs)
    (Pdb++) [spam for i in range(2)]
    ['global', 'global']
    (Pdb++) [eggs for i in range(2)]
    *** NameError: name 'eggs' is not defined
    

    This happens because PDB passes globals and locals and "If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition."

    1. Confusing f_locals behavior

    a)

    -> print(ham)
    (Pdb++) ham = "set from pdb"
    (Pdb++) print(ham)
    set from pdb
    (Pdb++) s
    NameError: name 'ham' is not defined
    

    b)

    [1] > .*(7)func()
    -> print(eggs)
    (Pdb++) ham = "set from pdb"
    (Pdb++) print(ham)
    set from pdb
    (Pdb++) step
    local
    [1] > .*(8)func()
    -> print(shopping)
    (Pdb++) s
    ['eggs']
    [1] > .*(9)func()
    -> print(ham)
    (Pdb++) print(ham)
    set from pdb
    (Pdb++) s
    NameError: name 'ham' is not defined
    

    c)

    (Pdb++) eggs = "redefined from pdb"
    (Pdb++) print(eggs)
    changed from pdb
    (Pdb++) step
    local
    [1] > .*(8)func()
    -> print(shopping)
    (Pdb++) print(eggs)
    local
    

    d)

    -> print(eggs)
    (Pdb++) del eggs
    (Pdb++) print(eggs)
    *** NameError: name 'eggs' is not defined
    (Pdb++) s
    local
    [1] > .*(8)func()
    -> print(shopping)
    (Pdb++) print(eggs)
    local
    

    e) a counterexample

    -> print(shopping)
    (Pdb++) shopping.append("appended from pdb")
    (Pdb++) print(shopping)
    ['eggs', 'appended from pdb']
    (Pdb++) step
    ['eggs', 'appended from pdb']
    
    bug 
    opened by technillogue 14
  • print and log statements in sticky mode

    print and log statements in sticky mode

    Hi! Consider the following simple file:

    import logging
    
    logger = logging.getLogger(__name__)
    logging.basicConfig(
        level=logging.INFO,
        handlers=[logging.StreamHandler()],
    )
    
    breakpoint()
    x = 2
    print(x)
    y = 3
    logger.info(y)
    z = x + y
    

    If I use sticky_by_default = True in my config file then when using n to move along lines both print and logger statements are ignored (not actually ignored but since the screen is repainted the message is lost/not shown). Is there a way to avoid using this while on sticky mode?

    enhancement 
    opened by petobens 14
  • `AttributeError: 'NoneType'` with `python -m pdb`

    `AttributeError: 'NoneType'` with `python -m pdb`

    Hi there! First, thanks for this. I was reminded of it from Clayton Parker's So you think you can PDB? talk at PyCon 2015.

    I've got a particular use case where it would be easier to run python -m pdb and set a breakpoint, rather than using pdb.set_trace(). However, when I try that, I get the following exception:

    $ python -m pdb test.py
    Traceback (most recent call last):
      File "/usr/local/Cellar/[email protected]/2.7.15_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 174, in _run_module_as_main
        "__main__", fname, loader, pkg_name)
      File "/usr/local/Cellar/[email protected]/2.7.15_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code
        exec code in run_globals
      File "/Users/brian/Code/test-pdbpp/venv/lib/python2.7/site-packages/_pdbpp_path_hack/pdb.py", line 5, in <module>
        exec(compile(f.read(), pdb_path, 'exec'))
      File "/Users/brian/Code/test-pdbpp/venv/lib/python2.7/site-packages/pdb.py", line 1165, in <module>
        pdb.main()
      File "/usr/local/Cellar/[email protected]/2.7.15_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pdb.py", line 1329, in main
        traceback.print_exc()
    AttributeError: 'NoneType' object has no attribute 'print_exc'
    

    Some more details:

    $ python --version
    Python 2.7.15
    
    $ pip freeze
    fancycompleter==0.8
    pdbpp==0.9.3
    Pygments==2.3.1
    pyrepl==0.8.4
    wmctrl==0.3
    
    $ cat test.py
    print('Hello World!')
    

    If I uninstall pdbpp, I get the expected result:

    $ python -m pdb test.py
    > /Users/brian/Code/test-pdbpp/test.py(1)<module>()
    -> print('Hello World!')
    (Pdb)
    
    bug 
    opened by bhrutledge 12
  • Make `edit at line` command work for sublime text

    Make `edit at line` command work for sublime text

    Currently, the edit command runs the following command:

    $EDITOR +line file
    

    As this notation might be a standard for some editors, this doesn't work for sublime text, where the syntax for opening a file is:

    subl file:line
    

    I propose an option that would change the default editor call syntax to the colon-notation. Like:

    editor_line_syntax = 'option' # default, give the line as a command option.  $EDITOR +<line> <file>
                         'suffix'  # (give the file line as a suffix, as accepted by sublime text : $EDITOR <file>:<line>
    
    enhancement 
    opened by antoine-gallix 12
  • Does not work when installed from wheel

    Does not work when installed from wheel

    Originally reported by: Aleks Bunin (Bitbucket: b-enlnt, GitHub: Unknown)


    I prepare wheel for every package I use. When I prepared wheel package for pdbpp, and installed that wheel - it did not work, while when installing from sources worked fine.

    Wheel preparation:

    $ (unset PIP_NO_INDEX; pip wheel pdbpp)
    $ pip install pdbpp
    

    When I used import pdb; pdb.set_trace() in the code, regular pdb was loaded.

    When I installed pdbpp from sources, pdbpp will work fine.

    I'm using wheel==0.24.0.


    • Bitbucket: https://bitbucket.org/antocuni/pdb/issue/31
    bug major 
    opened by antocuni 11
  • Possible bug: can't interact with pdbpp prompt

    Possible bug: can't interact with pdbpp prompt

    Hi, I'm attempting to use pdbpp to debug a dockerized python-flask application. I was able to access the pdbpp prompt by setting a breakpoint with pdbpp.set_trace() and running this command in terminal: docker-compose run --rm -p 3000:3000 myApp flask run --host=0.0.0.0 --port=3000
    When I attempt to type a command in the pdbb prompt, it fails to process the command. See below for an example:

    [34] > MyApp/app/main/forms.py(35)FindUserForm()
    -> name = StringField(
    (Pdb++) list
    *** NameError: name 'lt' is not defined
    (Pdb++) l
    *** NameError: name 'lt' is not defined
    (Pdb++) list
    

    I'm using a virtualenv with Python 3.7.1, pdbpp 0.9.15 and Docker version 18.09.03. My OS is Ubuntu 18.0.4.

    I had a similar error when using ipdb and had switched to pdbpp after reading this stackoverflow thread.

    I tried adding the below lines to the myApp service in my docker-compose.yml file

         stdin_open: true
            tty: true
    

    Unfortunately, it didn't resolve the issue. Have other users seen this error when debugging with pdbpp?

    opened by McEileen 11
  • Issues with custom colors, zsh + keyboard shortcuts

    Issues with custom colors, zsh + keyboard shortcuts

    Hello! First of all I just want to thank you for all the hard work put into this package - huge fan of custom colors and I can't live without sticky mode anymore :)

    Here's my custom .pdbrc.py configuration file:

    import pdb
    
    class Config(pdb.DefaultConfig):
        highlight = False
        sticky_by_default = True
        prompt = '[pdb++] '
        use_pygments = True
        pygments_formatter_class = "pygments.formatters.TerminalTrueColorFormatter"
        pygments_formatter_kwargs = {"style": "monokai"}
    

    I'm used to install pdbpp from source (following directions I got from some comments in this repo) with pip install git+git://github.com/pdbpp/[email protected]. Here's my pip freeze:

    fancycompleter @ git+https://github.com/pdbpp/[email protected]
    pdbpp @ git+git://github.com/pdbpp/[email protected]
    Pygments==2.10.0
    pyrepl @ git+https://github.com/pdbpp/[email protected]
    six==1.16.0
    wmctrl==0.4
    

    And as you can see I get colors normally:

    image

    However, recently I've started to get issues with certain keyboard shortcuts (I use zsh+powerlevel10k). i.e. Home or End won't work, as well as holding Option / Control and key arrows to navigate between words. Using tab completions within pdbpp will also yield weird results:

    image

    I've narrowed this issue down to pyrepl and uninstalling the package fixes the issues with the keyboard shortcuts. I'm also aware that I might stumble across issues like this by installing packages from source, so I'm ok with this solution.

    But if the issue is "fixed", then why am I here? Well, while doing some investigation I decided to give the version of pdbpp published to PyPi a try. Turns out that colors suddenly won't work anymore with the package published to PyPi, event though I haven't touched my .pdbrc file. New pip freeze:

    fancycompleter==0.9.1
    pdbpp==0.10.3
    Pygments==2.10.0
    pyrepl==0.9.0
    wmctrl==0.4
    

    Colors are gone (but no keyboard shortcuts issues!): image

    That's super weird, but digging into the problem I've noticed that a file called pdb.py was installed to my environment, and that has no code whatsoever related to Pygments:

    image

    In contrast, this is the tree I get if I install pdbpp from source: image

    That file has the section that understand Pygments ( which I believe is essentially this code).

    Bottom line:

    • pdbpp from source has issues with keyboard shortcuts on zsh due to pyrepl. Uninstalling pyrepl fixes the issue.
    • pdbpp from PyPi won't work with my previous .pdbrc.py configs. I suspect it has to deal with the code being packaged in the whl.

    Anyway, some weird stuff going on, sorry for the long post but just wanted to provide as much information as possible. I've debated over separating these into two issues, but ultimately settled for a single issue that explains the whole story of how I found the problems.

    Let me know if you need any further info. Thanks again for the awesome work here!

    opened by maurcz 0
  • Improve pdbpp.Pdb.parseline(): detect builtin with dot e.g list.foo

    Improve pdbpp.Pdb.parseline(): detect builtin with dot e.g list.foo

    Previous behavior: pdbpp.Pdb.parseline() correctly detects when the user calls a builtin like list and next, and does not mean to call the pdb list or next command, by checking whether cmd in ("list", "next") and arg.startswith("(").

    So this works as expected:

    (Pdb++) list([1])
    [1]
    

    Problem: It doesn't detect cases when the user calls e.g list.mro() or list.__getitem__([1], 0).

    So this doesn't work:

    (Pdb++) list.__getitem__([1], 0)
    *** Error in argument: '.__getitem__([1], 0)'
    

    Fix: I've changed the condition to cmd in ("list", "next") and (arg.startswith("(") or arg.startswith(".")) to fix that.

    So now this works as expected:

    (Pdb++) list.__getitem__([1], 0)
    1
    

    Let me know if this makes sense, follows best practices etc.

    Thanks! Gilad

    opened by giladbarnea 0
  • Issue with ipython and ipykernel

    Issue with ipython and ipykernel

    Dear pdbpp team,

    I've been working in jupyter notebooks that have pdbpp installed in the virtual environment. I'm a user of the %debug magic function which lets me launch a debugger when an exception is raised from one of the jupyter notebook cells.

    I use the following test code in a cell:

    def foo():
        raise Exception("test")
        
    foo()
    

    and then use %debug in the next cell to jump in the debugger.

    With the latest ipython (7.28) and pdbpp (10.3), this causes an issue and we get in the following error:

    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    /scratch/ipykernel_27400/3913957351.py in <module>
    ----> 1 get_ipython().run_line_magic('debug', '')
    
    ~/.virtualenvs/pdb-pp-test-FM1DiXFv-py3.8/lib/python3.8/site-packages/IPython/core/interactiveshell.py in run_line_magic(self, magic_name, line, _stack_depth)
       2349                 kwargs['local_ns'] = self.get_local_scope(stack_depth)
       2350             with self.builtin_trap:
    -> 2351                 result = fn(*args, **kwargs)
       2352             return result
       2353 
    
    ~/.virtualenvs/pdb-pp-test-FM1DiXFv-py3.8/lib/python3.8/site-packages/decorator.py in fun(*args, **kw)
        230             if not kwsyntax:
        231                 args, kw = fix(args, kw, sig)
    --> 232             return caller(func, *(extras + args), **kw)
        233     fun.__name__ = func.__name__
        234     fun.__doc__ = func.__doc__
    
    ~/.virtualenvs/pdb-pp-test-FM1DiXFv-py3.8/lib/python3.8/site-packages/IPython/core/magic.py in <lambda>(f, *a, **k)
        185     # but it's overkill for just that one bit of state.
        186     def magic_deco(arg):
    --> 187         call = lambda f, *a, **k: f(*a, **k)
        188 
        189         if callable(arg):
    
    ~/.virtualenvs/pdb-pp-test-FM1DiXFv-py3.8/lib/python3.8/site-packages/IPython/core/magics/execution.py in debug(self, line, cell)
        467 
        468         if not (args.breakpoint or args.statement or cell):
    --> 469             self._debug_post_mortem()
        470         elif not (args.breakpoint or cell):
        471             # If there is no breakpoints, the line is just code to execute
    
    ~/.virtualenvs/pdb-pp-test-FM1DiXFv-py3.8/lib/python3.8/site-packages/IPython/core/magics/execution.py in _debug_post_mortem(self)
        481 
        482     def _debug_post_mortem(self):
    --> 483         self.shell.debugger(force=True)
        484 
        485     def _debug_exec(self, code, breakpoint):
    
    ~/.virtualenvs/pdb-pp-test-FM1DiXFv-py3.8/lib/python3.8/site-packages/IPython/core/interactiveshell.py in debugger(self, force)
       1191             return
       1192 
    -> 1193         self.InteractiveTB.debugger(force=True)
       1194 
       1195     #-------------------------------------------------------------------------
    
    ~/.virtualenvs/pdb-pp-test-FM1DiXFv-py3.8/lib/python3.8/site-packages/IPython/core/ultratb.py in debugger(self, force)
       1180         if force or self.call_pdb:
       1181             if self.pdb is None:
    -> 1182                 self.pdb = self.debugger_cls()
       1183             # the system displayhook may have changed, restore the original
       1184             # for pdb
    
    ~/.virtualenvs/pdb-pp-test-FM1DiXFv-py3.8/lib/python3.8/site-packages/IPython/core/debugger.py in __init__(self, color_scheme, completekey, stdin, stdout, context, **kwargs)
        244 
        245         # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`.
    --> 246         OldPdb.__init__(self, completekey, stdin, stdout, **kwargs)
        247 
        248         # IPython changes...
    
    ~/.virtualenvs/pdb-pp-test-FM1DiXFv-py3.8/lib/python3.8/site-packages/_pdbpp_path_hack/pdb.py in __init__(self, *args, **kwds)
        167         kwargs = self.config.default_pdb_kwargs.copy()
        168         kwargs.update(**kwds)
    --> 169         super(Pdb, self).__init__(*args, **kwargs)
        170         self.prompt = self.config.prompt
        171         self.display_list = {}  # frame --> (name --> last seen value)
    
    TypeError: super(type, obj): obj must be an instance or subtype of type
    

    Attached is the requirements.txt file of the test env where I reproduced this. pdbpp_requirements.txt

    Workaround Uninstalling pdbpp immediately fixed the issue.

    bug needs info 
    opened by ThomVett 3
  • Fix (not) editing of an object implementing `str`

    Fix (not) editing of an object implementing `str`

    With e.g. pip's tests there are tests.lib.path.Path instances derived from str, where edit cache_dir would edit the path location, not the one of the object.

    This was added in https://github.com/pdbpp/pdbpp/commit/62010a4189b056f61c92d0e4d412f289a9e79cfe, without explanation nor test. Do you remember something about it by chance, @antocuni? :)

    bug 
    opened by blueyed 1
  • Question: Mechanism to automatically show N lines of context at each debugger-stop

    Question: Mechanism to automatically show N lines of context at each debugger-stop

    I really like ipdb, which is built on and uses a lot of ipython features!

    Unfortunately, some portion of ipdb or ipython does NOT like to play nice when embedded inside LLDB to debug LLDB Python scripts. Everything works the first time, then all Python is broken after that.

    pdbpp on the other hand seems to work well! pdbpp has the sticky view which is REALLY cool, but overkill for some uses and detrimental for others (e.g. stepping over a print statement, you won't see the output).

    Is there a way to configure pdbpp to show N lines of context before / after the current line, on every debugger stop? This is the equivalent of hitting l on each stop. I'm digging through the pdbpp internals now to sort it out, but I figured it was worth asking if it might save some time.

    enhancement 
    opened by zachriggle 2
  • JupyterLab: RecursionError: maximum recursion depth exceeded

    JupyterLab: RecursionError: maximum recursion depth exceeded

    I'm encountering a conflict between pdbpp and IPython.debugger when using pdb in JupyterLab, and able to reproduce on a fairly minimal installation:

    conda create -y -p ../venv/test_env_pdb python=3.8
    pip install ipdb pdbpp jupyterlab
    
    # relevant versions snipped out:
    # pdbpp-0.10.3 ipdb-0.13.9 ipykernel-6.4.1 ipython-7.28.0 jupyter-client-7.0.6 jupyterlab-3.1.16 
    

    After launching jupyterlab (jupyter lab --no-browser) and running pdb.set_trace(), I get the following stack trace:

    In [1]: import pdb; pdb.set_trace()
    ---------------------------------------------------------------------------
    RecursionError                            Traceback (most recent call last)
    /tmp/ipykernel_3094870/2402976972.py in <module>
    ----> 1 pdb.set_trace()
    
    ../venv/test_env_pdb/lib/python3.8/site-packages/IPython/core/debugger.py in set_trace(frame)
        961     If frame is not specified, debugging starts from caller's frame.
        962     """
    --> 963     Pdb().set_trace(frame or sys._getframe().f_back)
    
    ../venv/test_env_pdb/lib/python3.8/site-packages/pdbpp.py in __call__(cls, *args, **kwargs)
        305         else:
        306             set_global_pdb = use_global_pdb
    --> 307         obj.__init__(*args, **kwargs)
        308         if set_global_pdb:
        309             obj._env = {"HOME": os.environ.get("HOME")}
    
    ../venv/test_env_pdb/lib/python3.8/site-packages/IPython/core/debugger.py in __init__(self, color_scheme, completekey, stdin, stdout, context, **kwargs)
        244 
        245         # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`.
    --> 246         OldPdb.__init__(self, completekey, stdin, stdout, **kwargs)
        247 
        248         # IPython changes...
    
    ../venv/test_env_pdb/lib/python3.8/site-packages/pdbpp.py in __init__(self, *args, **kwds)
        367         kwargs = self.config.default_pdb_kwargs.copy()
        368         kwargs.update(**kwds)
    --> 369         super(Pdb, self).__init__(*args, **kwargs)
        370         self.prompt = self.config.prompt
        371         self.display_list = {}  # frame --> (name --> last seen value)
    
    ... last 2 frames repeated, from the frame below ...
    
    ../venv/test_env_pdb/lib/python3.8/site-packages/IPython/core/debugger.py in __init__(self, color_scheme, completekey, stdin, stdout, context, **kwargs)
        244 
        245         # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`.
    --> 246         OldPdb.__init__(self, completekey, stdin, stdout, **kwargs)
        247 
        248         # IPython changes...
    
    RecursionError: maximum recursion depth exceeded
    

    I've encountered this both on pdbpp==0.10.3 and the current master.

    bug 
    opened by azjps 3
  • [question] clarify usage with ipython

    [question] clarify usage with ipython

    Hello,

    I've read somewhere that pdbpp could be used with IPython; does that mean that launching pdbpp will work from inside an ipython session, or does it mean that the Pdb++ prompt will gain ipython support (features such as %timeit, %paste, etc)? It seems the former, although I'd have liked the later.

    pdbpp is great by itself, but one thing that is annoying for my flow is that it doesn't have a way (that I know) of understanding multi-line code fragments (this is accomplished using %paste in ipython).

    Thanks for this great project!

    opened by Apteryks 0
  • sys.path seems not working at all

    sys.path seems not working at all

    file is already in sys.path, however, when I set breakpoint on it, pdb++ still can not find the file.

    (Pdb++) pp sys.path
    ['/usr/src/app',
     '/usr/local/bin',
     '/usr/local/lib/python3.7/site-packages/_pdbpp_path_hack',
     '/usr/local/lib/python37.zip',
     '/usr/local/lib/python3.7',
     '/usr/local/lib/python3.7/lib-dynload',
     '/usr/local/lib/python3.7/site-packages',
     '/root/Django/IoTSite/IoTSite/',
     '/root/Django/IoTSite/IoTSite/urls.py']
    (Pdb++) b urls.py:39
    *** 'urls.py' not found from sys.path
    (Pdb++) 
    
    
    bug needs info 
    opened by tian-yan 1
  • Ignore installed code

    Ignore installed code

    Hello,

    I would like the pdbpp debugger to ignore code that is installed (i.e. pip install libraries), so for instance if I call "step" into a installed function, it returns immediately.

    The same option that you have in VScode https://code.visualstudio.com/docs/python/debugging ("justMyCode")

    enhancement 
    opened by TommasoBendinelli 0
Releases(0.10.3)
  • 0.10.3(Jul 9, 2021)

    Minor bugfix release, moving Continuous Integration from Travis/AppVeyor to GitHub Actions, based on changes on master, but without the (more invasive) (test) fixes for Windows.

    • Fixes

      • Fix hideframe decorator for Python 3.8+ (#263)
      • Fix hidden_frames discrepancy with IPython (#426)
    • Misc

      • ci: move to GitHub Actions (#444, #445)
      • ci: use .coveragerc (#304)
      • qa/flake8 fixes
      • test fix for newer PyPy3
    Source code(tar.gz)
    Source code(zip)
  • 0.9.3(Nov 28, 2018)

    Changes between 0.9.2 and 0.9.3

    • Features

      • Improve sticky_by_default: don't clear screen the first time (#83)
      • Handle header kwarg added with Python 3.7 in pdb.set_trace (#115)
      • config: allow to force use_terminal256formatter (#112)
      • Add heuristic for which 'list' is meant (#82)
    • Fixes

      • Skip/step over pdb.set_trace() (#119)
      • Handle completions from original pdb (#116)
      • Handle set_trace being invoked during completion (#89)
      • _pdbpp_path_hack/pdb.py: fix ResourceWarning (#97)
      • Fix "python -m pdb" (#108)
      • setup/interaction: use/handle return value from pdb.Pdb.setup (#107)
      • interaction: use _cmdloop if available (#106)
      • Fixed virtualenv sys.path shuffling issue (#85)
      • set_trace: do not delete pdb.curframe (#103)
      • forget: only call pdb.Pdb.forget with GLOBAL_PDB once
    • Tests

      • Travis: test pypy3
      • Travis/tox: add py37, remove nightly
      • tests: PdbTest: use nosigint=True (#117)
      • Add test_debug_with_overridden_continue (#113)
      • tests: re-enable/fix test_utf8 (#110)
      • tests: fix conditional skipping with test_pdbrc_continue
      • tests: runpdb: print output on Exceptions
      • pytest.ini: addopts: -ra
      • tests: handle pytest's --assert=plain mode
      • tests: harden check: match all lines
      • tests: fix flake8 errors and invalid-escape DeprecationWarnings
    • Misc

      • setup.py: add trove classifier for "… :: Debuggers"
      • doc: separate usage section (#105)
      • Format code: flake8 clean, using autopep8 mainly (#118)
      • Add wheels support
      • README: grammar and example for break_on_setattr (#99)
      • README: fix formatting
      • Simplify the code, since we no longer support python 2.6
    Source code(tar.gz)
    Source code(zip)
A drop-in replacement for Django's runserver.

About A drop in replacement for Django's built-in runserver command. Features include: An extendable interface for handling things such as real-time l

David Cramer 1.3k Jan 9, 2022
A drop-in replacement for Django's runserver.

About A drop in replacement for Django's built-in runserver command. Features include: An extendable interface for handling things such as real-time l

David Cramer 1.3k Jan 9, 2022
Integration of IPython pdb

IPython pdb Use ipdb exports functions to access the IPython debugger, which features tab completion, syntax highlighting, better tracebacks, better i

Godefroid Chapelle 1.5k Jan 11, 2022
Full-screen console debugger for Python

PuDB: a console-based visual debugger for Python Its goal is to provide all the niceties of modern GUI-based debuggers in a more lightweight and keybo

Andreas Klöckner 2.3k Jan 14, 2022
Debugger capable of attaching to and injecting code into python processes.

DISCLAIMER: This is not an official google project, this is just something I wrote while at Google. Pyringe What this is Pyringe is a python debugger

Google 1.6k Jan 2, 2022
Graphical Python debugger which lets you easily view the values of all evaluated expressions

birdseye birdseye is a Python debugger which records the values of expressions in a function call and lets you easily view them after the function exi

Alex Hall 1.4k Jan 2, 2022
Voltron is an extensible debugger UI toolkit written in Python.

Voltron is an extensible debugger UI toolkit written in Python. It aims to improve the user experience of various debuggers (LLDB, GDB, VDB an

snare 5.6k Jan 16, 2022
NoPdb: Non-interactive Python Debugger

NoPdb: Non-interactive Python Debugger Installation: pip install nopdb Docs: https://nopdb.readthedocs.io/ NoPdb is a programmatic (non-interactive) d

Ondřej Cífka 44 Dec 16, 2021
Tracing instruction in lldb debugger.Just a python-script for lldb.

lldb-trace Tracing instruction in lldb debugger. just a python-script for lldb. How to use it? Break at an address where you want to begin tracing. Im

null 102 Jan 8, 2022
Visual Interaction with Code - A portable visual debugger for python

VIC Visual Interaction with Code A simple tool for debugging and interacting with running python code. This tool is designed to make it easy to inspec

Nathan Blank 1 Nov 16, 2021
An improbable web debugger through WebSockets

wdb - Web Debugger Description wdb is a full featured web debugger based on a client-server architecture. The wdb server which is responsible of manag

Kozea 1.5k Jan 11, 2022
PINCE is a front-end/reverse engineering tool for the GNU Project Debugger (GDB), focused on games.

PINCE is a front-end/reverse engineering tool for the GNU Project Debugger (GDB), focused on games. However, it can be used for any reverse-engi

Korcan Karaokçu 1.2k Jan 8, 2022
Little helper to run Steam apps under Proton with a GDB debugger

protongdb A small little helper for running games with Proton and debugging with GDB Requirements At least Python 3.5 protontricks pip package and its

Joshie 17 Jan 9, 2022
Full featured multi arch/os debugger built on top of PyQt5 and frida

Full featured multi arch/os debugger built on top of PyQt5 and frida

iGio90 1k Jan 13, 2022
Arghonaut is an interactive interpreter, visualizer, and debugger for Argh! and Aargh!

Arghonaut Arghonaut is an interactive interpreter, visualizer, and debugger for Argh! and Aargh!, which are Befunge-like esoteric programming language

Aaron Friesen 2 Dec 10, 2021
A simple rubber duck debugger

Rubber Duck Debugger I found myself many times asking a question on StackOverflow or to one of my colleagues just for finding the solution simply by d

null 1 Nov 10, 2021
Hdbg - Historical Debugger

hdbg - Historical Debugger This is in no way a finished product. Do not use this

Fivreld 2 Jan 2, 2022
Trace any Python program, anywhere!

lptrace lptrace is strace for Python programs. It lets you see in real-time what functions a Python program is running. It's particularly useful to de

Karim Hamidou 681 Jan 9, 2022
Debugging manhole for python applications.

Overview docs tests package Manhole is in-process service that will accept unix domain socket connections and present the stacktraces for all threads

Ionel Cristian Mărieș 319 Jan 2, 2022