Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variable ListBox crashes for long variables repr #652

Open
alexfikl opened this issue May 29, 2024 · 5 comments
Open

Variable ListBox crashes for long variables repr #652

alexfikl opened this issue May 29, 2024 · 5 comments
Labels

Comments

@alexfikl
Copy link
Contributor

alexfikl commented May 29, 2024

Describe the bug

When using stringifier = repr and there are several variables with a long repr in the local scope, pudb crashes somewhere in urwid/widget/listbox.py::755 with an error like

urwid.widget.listbox.ListBoxError: Widget <VariableWidget selectable flow widget> at position 1 within listbox calculated 111 rows but rendered 110!

This started happening in the last 2-3 months, I think, but I haven't had time to track it down.

Full traceback
Traceback (most recent call last):
  File "/usr/lib/python3.12/site-packages/pudb/__init__.py", line 162, in runscript
    dbg._runscript(mainpyfile)
  File "/usr/lib/python3.12/site-packages/pudb/debugger.py", line 534, in _runscript
    self.run(statement)
  File "/usr/lib/python3.12/bdb.py", line 600, in run
    exec(cmd, globals, locals)
  File "<string>", line 1, in <module>
  File "pudb-bug.py", line 9, in <module>
    r = np.sqrt(x ** 2 + y ** 2 + z ** 2)
    ^
  File "/usr/lib/python3.12/bdb.py", line 94, in trace_dispatch
    return self.dispatch_return(frame, arg)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/bdb.py", line 153, in dispatch_return
    self.user_return(frame, arg)
  File "/usr/lib/python3.12/site-packages/pudb/debugger.py", line 479, in user_return
    self.interaction(frame)
  File "/usr/lib/python3.12/site-packages/pudb/debugger.py", line 436, in interaction
    self.ui.call_with_ui(self.ui.interaction, exc_tuple,
  File "/usr/lib/python3.12/site-packages/pudb/debugger.py", line 2556, in call_with_ui
    return f(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/pudb/debugger.py", line 2879, in interaction
    self.event_loop()
  File "/usr/lib/python3.12/site-packages/pudb/debugger.py", line 2834, in event_loop
    canvas = toplevel.render(self.size, focus=True)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 112, in cached_render
    canv = fn(self, size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 711, in render
    canv = get_delegate(self).render(size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 112, in cached_render
    canv = fn(self, size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/frame.py", line 481, in render
    body = self.body.render((maxcol, maxrow - ftrim - htrim), focus and self.focus_part == "body")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 112, in cached_render
    canv = fn(self, size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/attr_map.py", line 158, in render
    canv = self._original_widget.render(size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 112, in cached_render
    canv = fn(self, size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/columns.py", line 1026, in render
    w.render(w_size, focus=focus and self.focus_position == i),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 112, in cached_render
    canv = fn(self, size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 711, in render
    canv = get_delegate(self).render(size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 112, in cached_render
    canv = fn(self, size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/pile.py", line 873, in render
    canv = w.render(w_size, focus=focus and item_focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 112, in cached_render
    canv = fn(self, size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/attr_map.py", line 158, in render
    canv = self._original_widget.render(size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 112, in cached_render
    canv = fn(self, size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/pile.py", line 873, in render
    canv = w.render(w_size, focus=focus and item_focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 112, in cached_render
    canv = fn(self, size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/attr_map.py", line 158, in render
    canv = self._original_widget.render(size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 112, in cached_render
    canv = fn(self, size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 711, in render
    canv = get_delegate(self).render(size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/widget.py", line 112, in cached_render
    canv = fn(self, size, focus=focus)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/urwid/widget/listbox.py", line 755, in render
    raise ListBoxError(
urwid.widget.listbox.ListBoxError: Widget <VariableWidget selectable flow widget> at position 1 within listbox calculated 111 rows but rendered 110!

To Reproduce

For a simple reproducer

import numpy as np

rng = np.random.default_rng()

x = rng.random(512)
y = rng.random(512)
z = rng.random(512)

r = np.sqrt(x ** 2 + y ** 2 + z ** 2)

and then running python -m pudb reproducer.py and pressing n a few times will cause the crash above.

Versions

  • python 3.12.3
  • pudb e340f1d
  • urwid 2.6.10
  • Linux archlinux 6.9.2-arch1
@alexfikl alexfikl added the Bug label May 29, 2024
@alexfikl alexfikl changed the title Variable ListBox crashes for long variables Variable ListBox crashes for long variables repr May 31, 2024
@mvanderkamp
Copy link
Contributor

I managed to reproduce, but with the following additions:

  • repr is the default stringifier
  • line wrapping is enabled for the variable display

@mvanderkamp
Copy link
Contributor

mvanderkamp commented Jun 2, 2024

Anyway this looks more like an urwid than pudb bug, and I suspect it's got something to do with the way numpy formats its strings, since I can't reproduce just with a long regular python list of floating point numbers.

@mvanderkamp
Copy link
Contributor

If it helps, just a single one of those numpy arrays is sufficient to trigger the traceback for me.

@mvanderkamp
Copy link
Contributor

Ooh actually to be even more precise it's something to do with the newline characters. If I had to guess I'd say that urwid has a bug with how it handles special characters.

What I did:

import random
floats = [random.random() for _ in range(512)]
columns = [floats[i::5] for i in range(5)]
rows = list(zip(*columns))
strings = '\n'.join(', '.join(str(x) for x in row) for row in rows)

This skips the numpy dependency and, by comparing how the different variables behave, you can see that it's really only when you enable line wrapping and use the str stringifier on the strings variable that urwid hits a traceback.

I'm not sure why str is the one to trigger it instead of repr. Probably something to do with how I included the newlines.

@nikhilweee
Copy link

A workaround for me was to downgrade urwid.

pip install urwid==2.5.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants