pythonurwid

Urwid raising (maxcol,) = size too many values to unpack


I'm trying to create an Urwid UI for a robot. The layout I have in mind is made of three horizontal areas:

I created this code resulting in the screenshotted layout:

brief_message = urwid.Text(u'Robot starting...')
log_messages = urwid.Text('running log messages here')
variables = urwid.Text('k=v variable list here')
body = urwid.Pile([
    #urwid.Filler(brief_message, height=1),
    urwid.LineBox(urwid.Filler(log_messages, valign='bottom', top=1)),
    urwid.LineBox(urwid.Filler(variables, valign='top', bottom=1)),
])
loop = urwid.MainLoop(body)
loop.run()

screenshot of resulting layout

The problem is that if I uncomment urwid.Filler(brief_message, height=1) line, I get an exception and I'm not sure why:

[ full traceback snipped ]
  File "/tmp/venv/lib/python3.8/site-packages/urwid/widget.py", line 1001, in render
    (maxcol,) = size
ValueError: too many values to unpack (expected 1)

I understand this happens because a flow widget is treated like a box widget, but I thought wrapping brief_message with an urwid.Filler is exactly what I'm supposed to do. Further, if I remove height=1 from the Filler the program works, but brief_message's height is a third of the screen, which isn't what I want - it should be a oneliner.

What am I missing?


Solution

  • Looking at the documentation for urwid.Filler it says:

    If body is a flow widget then height must be 'flow' and min_height will be ignored.

    You can't set set to the height to 1 or anything except flow if you are using flow widget like urwid.Text as the body.

    As far as actually getting the result you're looking for, what follows is my best guess. I don't have an appropriate test environment set up so YMMV.

    Looking at the documentation for Pile you can pass tuples with a height value and it will be treated as a box widget. So you might try

    body = urwid.Pile([
        (1, urwid.Filler(brief_message)),
        urwid.LineBox(urwid.Filler(log_messages, valign='bottom', top=1)),
        urwid.LineBox(urwid.Filler(variables, valign='top', bottom=1)),
    ])