EzDevInfo.com

urwid

Console user interface library for Python (official repo) Overview — Urwid 1.3.0

Python Console UI Suggestions

I'm currently rewriting a perl console application that was using curses, and planning to implement it in Python. So far I've narrowed my library options to straight curses, urwid, and dialog.

The application is basically an installer for an appliance that will accommodate basic configuration (network options, hostname, etc). Are there any suggestions or advocates for one of these over the other? Any serious limitations with urwid or dialog?


Source: (StackOverflow)

Python library for (n)curses widgets

While Python's standard library has a module for curses, that seems to require a lot of fairly low-level handling.

Is there a simpler way to get started with writing a basic curses UI which includes standard elements like checkboxes, input fields etc.?

I've found urwid, but not sure whether that's the state of the art.


Source: (StackOverflow)

Advertisements

Python ncurses, CDK, urwid difference

What's the difference between these 3? As far as I understand it they both provide binding to curses which is the C library for terminal text-based UI.

I currently have no knowledge of any of the 3 and I've never used curses. Which one would you recommend? I've heard of ncurses many times but only once or twice about CDK (through research) and never heard of urwid (I think).


Source: (StackOverflow)

main function call fails in python

I wrote the following code that creates a layout and displays some text in the layout. Next the layout is displayed on the console screen using raw display module from urwid library. However running the code fails as it doesn't find the function main that I wrote separately in a class.

Error code on running is :

Traceback (most recent call last):  
  File "./yamlUrwidUIPhase5.py", line 89, in <module>
    main()  
  File "./yamlUrwidUIPhase5.py", line 83, in main
    FormDisplay().main()  
AttributeError: 'NoneType' object has no attribute 'main'

The code :

import sys  
sys.path.append('./lib')  
import os  
from pprint import pprint  
import random  
import urwid  

def formLayout():
    text1 = urwid.Text("Urwid 3DS Application program - F8 exits.")
    text2 = urwid.Text("One mission accomplished")

    textH = urwid.Text("topmost Pile text")
    cols = urwid.Columns([text1,text2])
    pile = urwid.Pile([textH,cols])
    fill = urwid.Filler(pile)

    textT  = urwid.Text("Display") 

    textSH = urwid.Text("Pile text in Frame")
    textF = urwid.Text("Good progress !")

    frame = urwid.Frame(fill,header=urwid.Pile([textT,textSH]),footer=textF)
    dim = ui.get_cols_rows()

    ui.draw_screen(dim, frame.render(dim, True))  

def RandomColor():
    '''Pick a random color for the main menu text'''
    listOfColors = ['dark red', 'dark green', 'brown', 'dark blue',
                    'dark magenta', 'dark cyan', 'light gray',
                    'dark gray', 'light red', 'light green', 'yellow',
                    'light blue', 'light magenta', 'light cyan', 'default']
    color = listOfColors[random.randint(0, 14)]
    return color

def FormDisplay():
    import urwid.raw_display
    ui = urwid.raw_display.Screen()
    palette = ui.register_palette([
            ('Field', 'dark green, bold', 'black'), # information fields, Search: etc.
            ('Info', 'dark green', 'black'), # information in fields
            ('Bg', 'black', 'black'), # screen background
            ('InfoFooterText', 'white', 'dark blue'), # footer text
            ('InfoFooterHotkey', 'dark cyan, bold', 'dark blue'), # hotkeys in footer text
            ('InfoFooter', 'black', 'dark blue'),  # footer background
            ('InfoHeaderText', 'white, bold', 'dark blue'), # header text
            ('InfoHeader', 'black', 'dark blue'), # header background
            ('BigText', RandomColor(), 'black'), # main menu banner text
            ('GeneralInfo', 'brown', 'black'), # main menu text
            ('LastModifiedField', 'dark cyan, bold', 'black'), # Last modified:
            ('LastModifiedDate', 'dark cyan', 'black'), # info in Last modified:
            ('PopupMessageText', 'black', 'dark cyan'), # popup message text
            ('PopupMessageBg', 'black', 'dark cyan'), # popup message background
            ('SearchBoxHeaderText', 'light gray, bold', 'dark cyan'), # field names in the search box
            ('SearchBoxHeaderBg', 'black', 'dark cyan'), # field name background in the search box
            ('OnFocusBg', 'white', 'dark magenta') # background when a widget is focused
           ])
urwid.set_encoding('utf8')

def main(self):
    #self.view = ui.run_wrapper(formLayout)
    self.view = formLayout()
    ui.start()
    self.loop = urwid.MainLoop(self.view, self.palette, unhandled_input=self.unhandled_input)
    self.loop.run()

def unhandled_input(self, key):
    if key == 'f8':
        quit()
        return
def main():
    global ui

    FormDisplay().main()

########################################
##### MAIN ENTRY POINT
########################################
if __name__ == '__main__':
    main()

Source: (StackOverflow)

python - urwid simple listbox example

I'm looking at urwid to develop a console app. As a starting point I'm looking for a simple example of a listbox that displays a few rows that can be scrolled using up/down keys.

Can anyone provide a simple example of how this can be done or point me to a link? I saw the examples on urwid site but I'm looking for something more basic.

Edit

@Adam: I found this example online. I'm having difficulties with the commented out part as I'm not familiar with the API and I'm a python newbie.

Edit2 I figured it out and updated the example. One more question - can I get the item count directly from the ListBox?

import urwid

palette = [('header', 'white', 'black'),
    ('reveal focus', 'black', 'dark cyan', 'standout')]

items = [urwid.Text("foo"),
         urwid.Text("bar"),
         urwid.Text("baz")]

content = urwid.SimpleListWalker([
    urwid.AttrMap(w, None, 'reveal focus') for w in items])

listbox = urwid.ListBox(content)

show_key = urwid.Text("Press any key", wrap='clip')
head = urwid.AttrMap(show_key, 'header')
top = urwid.Frame(listbox, head)

def show_all_input(input, raw):

    show_key.set_text("Pressed: " + " ".join([
        unicode(i) for i in input]))
    return input


def exit_on_cr(input):
    if input in ('q', 'Q'):
        raise urwid.ExitMainLoop()
    elif input == 'up':
        focus_widget, idx = listbox.get_focus()
        if idx > 0:
            idx = idx-1
            listbox.set_focus(idx)
    elif input == 'down':
        focus_widget, idx = listbox.get_focus()
        idx = idx+1
        listbox.set_focus(idx)

def out(s):
    show_key.set_text(str(s))


loop = urwid.MainLoop(top, palette,
    input_filter=show_all_input, unhandled_input=exit_on_cr)
loop.run()

Source: (StackOverflow)

what does @ code construct mean in python?

i was looking at a file wicd-curses.py from the wicd application available with urwid. there is a function named as wrap_exceptions and then at several other places in the file i find some code like this @wrap_exceptions which occurs just before several other functions. What does it mean ?


Source: (StackOverflow)

how to change the ui on urwid

I am creating a small urwid app for my use, the structure is a Filler which has a Pile composed of several Text filed, followed by a Divider, an Edit, another Divier and finally a Text:

Text1
Text2
Text3
Divide
>> Edit
Divide
Textout

Now, I want to replace Text1 .. Text3 with other Text field, the exact number of those varies. I figure I should redraw the entire UI, but I got no response on draw_screen()

My class:

class main_ui(urwid.Filler):
  def __init__(self):
      self.body = welcom()
      self.options = self.body.options
      self.replay = self.body.replay
      self.ask = self.body.ask
      super(main_ui,self).__init__(self.body.pile,valign='top')
  def paint(self):
      super(main_ii,self).__init__(urwid.pile[urwid.Text('test')])

The welcom() function generates the above fields, and options is dict that holds information I need

I run the loop like this

def refresh(_loop,_data):
    m.new_point()
    _loop.draw_screen()
    _loop.set_alarm_in(2,refresh)


m = main_ui()
loop = urwid.MainLoop(m)
loop.set_alarm_in(2,refresh)
loop.run()

How can I update my ui?


Source: (StackOverflow)

mac os x urwid AttributeError: 'SelectableIcon' object has no attribute '_SelectableIcon__super'

I am quite new to python an urwid. I found a seemingly OS X specific problem with urwid 1.3.0: I run Mac OS X 10.9.5 an have the by default installed python 2.7.5 and a manually installed python 3.4.2. I have made no changes to the original code an tried the following:

I copied as instructed (https://github.com/wardi/urwid/wiki/Installation-instructions) the urwid folder from the package (urwid-1.3.0.tar.gz) into its examples folder to make urwid available for python and being able to test the examples. I got always the same error when executing e.g:

python bigtext.py
python3 bigtext.py

I also tried this with the very first tutorial from the urwid site

# hellotest.py
import urwid

txt = urwid.Text(u"Hello World")
fill = urwid.Filler(txt, 'top')
loop = urwid.MainLoop(fill)
loop.run()

All examples, just like the short one above, produce the following Error:

mymac:examples me$ python3 hellotest.py 
Traceback (most recent call last):
  File "hellotest.py", line 1, in <module>
    import urwid
  File "myfolder/urwid-1.3.0/examples/urwid/__init__.py", line 36, in <module>
    from urwid.wimp import (SelectableIcon, CheckBoxError, CheckBox, RadioButton,
  File "myfolder/urwid-1.3.0/examples/urwid/wimp.py", line 99, in <module>
    class CheckBox(WidgetWrap):
  File "myfolder/urwid-1.3.0/examples/urwid/wimp.py", line 104, in CheckBox
    True: SelectableIcon("[X]"),
  File "myfolder/urwid-1.3.0/examples/urwid/wimp.py", line 47, in __init__
    self.__super.__init__(text)
AttributeError: 'SelectableIcon' object has no attribute '_SelectableIcon__super'

This Error does not occur when i try this on a fresh Raspbian (Debian) on a Raspberry Pi. So it seems to me this is a OS specific problem.

Can someone find why this behaviour occurs on OS X, or does it even happen on other systems too? And does someone have an idea on how to fix this?

Thanks in advance


Source: (StackOverflow)

'Assertion Error' while trying to create a console screen using urwid

code below creates a layout and displays some text in the layout. Next the layout is displayed on the console screen using raw display module from urwid library. (More info on my complete project can be gleaned from questions at widget advice for a console project and urwid for a console project. My skype help request being here.) However running the code fails as an Assertion Error is raised as described below :

Error on running code is :
Traceback (most recent call last):
File "./yamlUrwidUIPhase6.py", line 98, in <module>
main()
File "./yamlUrwidUIPhase6.py", line 92, in main
form.main()
File "./yamlUrwidUIPhase6.py", line 48, in main
self.view = formLayout()
File "./yamlUrwidUIPhase6.py", line 77, in formLayout
ui.draw_screen(dim, frame.render(dim, True))
File "/usr/lib64/python2.7/site-packages/urwid/raw_display.py", line 535, in draw_screen
assert self._started
AssertionError

The code :

import sys  
sys.path.append('./lib')  
import os  
from pprint import pprint  
import random  
import urwid  
ui=urwid.raw_display.Screen()


class FormDisplay(object):

    def __init__(self):
        global ui
        self.ui = ui
        palette = ui.register_palette([
            ('Field', 'dark green, bold', 'black'), # information fields, Search: etc.
            ('Info', 'dark green', 'black'), # information in fields
            ('Bg', 'black', 'black'), # screen background
            ('InfoFooterText', 'white', 'dark blue'), # footer text
            ('InfoFooterHotkey', 'dark cyan, bold', 'dark blue'), # hotkeys in footer text
            ('InfoFooter', 'black', 'dark blue'),  # footer background
            ('InfoHeaderText', 'white, bold', 'dark blue'), # header text
            ('InfoHeader', 'black', 'dark blue'), # header background
            ('BigText', RandomColor(), 'black'), # main menu banner text
            ('GeneralInfo', 'brown', 'black'), # main menu text
            ('LastModifiedField', 'dark cyan, bold', 'black'), # Last modified:
            ('LastModifiedDate', 'dark cyan', 'black'), # info in Last modified:
            ('PopupMessageText', 'black', 'dark cyan'), # popup message text
            ('PopupMessageBg', 'black', 'dark cyan'), # popup message background
            ('SearchBoxHeaderText', 'light gray, bold', 'dark cyan'), # field names in the search box
            ('SearchBoxHeaderBg', 'black', 'dark cyan'), # field name background in the search box
            ('OnFocusBg', 'white', 'dark magenta') # background when a widget is focused
           ])
        urwid.set_encoding('utf8')

    def main(self):
        global ui
        #self.view = ui.run_wrapper(formLayout)
        self.view = formLayout()
        self.ui.start()
        self.loop = urwid.MainLoop(self.view, self.palette, unhandled_input=self.unhandled_input)
        self.loop.run()

    def unhandled_input(self, key):
        if key == 'f8':
          quit()
          return


def formLayout():
    global ui
    text1 = urwid.Text("Urwid 3DS Application program - F8 exits.")
    text2 = urwid.Text("One mission accomplished")

    textH = urwid.Text("topmost Pile text")
    cols = urwid.Columns([text1,text2])
    pile = urwid.Pile([textH,cols])
    fill = urwid.Filler(pile)

    textT  = urwid.Text("Display") 

    textSH = urwid.Text("Pile text in Frame")
    textF = urwid.Text("Good progress !")

    frame = urwid.Frame(fill,header=urwid.Pile([textT,textSH]),footer=textF)
    dim = ui.get_cols_rows()

    ui.draw_screen(dim, frame.render(dim, True))
    return

def RandomColor():
    '''Pick a random color for the main menu text'''
    listOfColors = ['dark red', 'dark green', 'brown', 'dark blue',
                    'dark magenta', 'dark cyan', 'light gray',
                    'dark gray', 'light red', 'light green', 'yellow',
                    'light blue', 'light magenta', 'light cyan', 'default']
    color = listOfColors[random.randint(0, 14)]
    return color

def main():
    form = FormDisplay()
    form.main()

########################################
##### MAIN ENTRY POINT
########################################
if __name__ == '__main__':
    main()

I don't want to change the function formLayout as I intend to add more to this basic code framework, where in another function will be added that repeatedly calls formLayout to keep updating the screen based on reading values from a yml file. I already have a separate code that deals with reading the yaml file and extracting ordered dictionaries out it. After figuring out how to get basic urwid console working, I can move on to integrating both to create my final application.


Source: (StackOverflow)

What Options Are There for a Python TUI Backend?

I need to build a python TUI for a project that I am working on. I do not need advice suggestion about the actual TUI libraries out there (like ncurses/npyscreen/Urwid/etc) as my team has already determined that they are too heavyweight for our needs. The TUI takes relatively simple text input and doesn't require all of the nice formatting and widgets. It also will only be accepting input from a single user at any time.

Since we are rolling our own display, that leaves the real question, which is are there options for libs out there that can help implement the event-handling/IO loop that I can reuse? I started the Internet search for GUI/TUI backends and quickly found myself in the Twisted/Tornado/Gevent world, which I am also not sure is the proper avenue to run down. Are these libraries, or possibly Urwid able to let me easy slip in my own display code (to render screens and take simple raw_input() style data)?

This will only be run in a Python 2.7, Linux environment, but if it works on a Mac, that will be a big plus.


Source: (StackOverflow)

Best approach for building text based data entry app

I'm trying to write a script that just uses the terminal, but I don't know how realistic my expectations are. It's a data entry thing I want to make to make my life easier. I would like something that looks like this:

100456 John Doe      []  ()  ()  ()  ()  [                        ]
100873 Alice Everly  []  ()  ()  ()  ()  [                        ]
...
...

Basically a screen with a list of 20-30 people with text entry boxes and check boxes. I want to be able to arrow up and down and move around. I remember using text based programs way back when and they still just seem more efficient.

I've been looking at ncurses, urwid, straight bash... I think I can get any of these to work, but if anyone has a suggestion on a language or framework that would make this easier, I'd sure appreciate it. I don't want to get a week or two in and then realize I could have done it another way in an hour.


Source: (StackOverflow)

Python3: purge exception chain?

I'm trying to raise an exception within an except: block but the interpreter tries to be helpful and prints stack traces 'by force'. Is it possible to avoid this?

A little bit of background information: I'm toying with urwid, a TUI library for python. The user interface is started by calling urwid.MainLoop.run() and ended by raising urwid.ExitMainLoop(). So far this works fine but what happens when another exception is raised? E.g. when I'm catching KeyboardInterrupt (the urwid MainLoop does not), I do some cleanup and want to end the user interface - by raising the appropriate exception. But this results in a screen full of stack traces.

Some little research showed python3 remembers chained exceptions and one can explicitly raise an exception with a 'cause': raise B() from A(). I learned a few ways to change or append data regarding the raised exceptions but I found no way to 'disable' this feature. I'd like to avoid the printing of stack traces and lines like The above exception was the direct cause of... and just raise the interface-ending exception within an except: block like I would outside of one.

Is this possible or am I doing something fundamentally wrong?

Edit: Here's an example resembling my current architecture, resulting in the same problem:

#!/usr/bin/env python3
import time

class Exit_Main_Loop(Exception):
    pass

# UI main loop
def main_loop():
    try:
        while True:
            time.sleep(0.1)
    except Exit_Main_Loop as e:
        print('Exit_Main_Loop')
        # do some UI-related clean up

# my main script
try:
    main_loop()
except KeyboardInterrupt as e:
    print('KeyboardInterrupt')
    # do some clean up
    raise Exit_Main_Loop()      # signal the UI to terminate

Unfortunately I can't change main_loop to except KeyboardInterrupt as well. Is there a pattern to solve this?


Source: (StackOverflow)

urwid listboxes won't scroll

import urwid

palette = [('header', 'white', 'black'),
('reveal focus', 'black', 'dark cyan', 'standout'),]
content = urwid.SimpleListWalker([
        urwid.AttrMap(w, None, 'reveal focus') for w in [
            urwid.Text("This is a text string that is fairly long"),
            urwid.Divider("-"),
            urwid.Text("Short one"),
            urwid.Text("Another"),
            urwid.Divider("-"),
            urwid.Text("What could be after this?"),
            urwid.Text("The end."),]
    ])

listbox = urwid.ListBox(content)
show_key = urwid.Text("", wrap='clip')
head = urwid.AttrMap(show_key, 'header')
top = urwid.Frame(listbox, head)

def show_all_input(input, raw):
    show_key.set_text("Pressed: " + " ".join([
        unicode(i) for i in input]))
    return input

def exit_on_cr(input):
    if input == 'enter':
        raise urwid.ExitMainLoop()

loop = urwid.MainLoop(top, palette, input_filter=show_all_input, unhandled_input=exit_on_cr)
loop.run()

Pressing up or down should scroll the list but in my case it doesn't. Is there something wrong ?

EDIT 1

Code works perfectly in fact I didn't understand what scrollable lists are. I thought pressing up or down would select item in the list but it doesn't. What this does is just scroll your terminal when it doesn't have enough space to display all items at once. You must resize your terminal to a very small size to understand what this code does.

EDIT 2

To change focus when pressing up or down, a strange API has to be used. I would have loved to see an API like listbox.focus_next() / listbox.focus_previous(), but you have to handle the positions yourself. Of course, you can create your own functions (or subclass ListBox) to offer a better API

def handle_input(input):
    if input == "esc":
        raise urwid.ExitMainLoop()
    head.original_widget.set_text("key pressed: %s" % input)
    lw = listbox.body        
    if input == "up":
        # this can raise an error if we scroll past first position
        try:
            lw.set_focus(lw.get_prev(lw.get_focus()[1])[1])
        except:
            pass
    elif input == "down":
        # this can raise an error if we scroll past last position
        try: 
            lw.set_focus(lw.get_next(lw.get_focus()[1])[1])
        except:
            pass

EDIT 3

A better API :

def urwid_test():
    """
            'black', 'dark red', 'dark green', 'brown', 'dark blue',
            'dark magenta', 'dark cyan', 'light gray', 'dark gray',
            'light red', 'light green', 'yellow', 'light blue', 
            'light magenta', 'light cyan', 'white'
    """

    class MyListBox(urwid.ListBox):
        def focus_next(self):
            try: 
                self.body.set_focus(self.body.get_next(self.body.get_focus()[1])[1])
            except:
                pass
        def focus_previous(self):
            try: 
                self.body.set_focus(self.body.get_prev(self.body.get_focus()[1])[1])
            except:
                pass            

    def handle_input(input):
        if input == "esc":
            raise urwid.ExitMainLoop()
        head.original_widget.set_text("key pressed: %s" % input)
        if input == "up":
            listbox.focus_previous()
        elif input == "down":
            listbox.focus_next()
    palette = [("top","white","black"),
               ("line","light green","dark green","standout"),
               ("frame","dark magenta","white"),
               ]
    widgets = [urwid.AttrMap(widget,None,"line") for widget in
                [
                    urwid.Text("Chemma!"),
                    urwid.Divider("-"),
                    urwid.Text("Another text widget!"),
                    urwid.Divider("-"),                   
                    urwid.Text("What is your name"),
                    urwid.Divider("-"),                   
                    urwid.Text("Boy ?"),                                                            
                ]
              ]
    head    = urwid.AttrMap(urwid.Text("key pressed :",wrap="clip"),"top")
    L       = urwid.SimpleListWalker(widgets)
    listbox = MyListBox(L)
    top     = urwid.AttrMap(urwid.Frame(listbox,head),"frame")
    loop    = urwid.MainLoop(top,palette,unhandled_input=handle_input)
    loop.screen.set_terminal_properties(colors=256)
    loop.run()

if __name__ == "__main__":
    urwid_test()

Source: (StackOverflow)

Italicizing text in urwid

I am using urwid to design a curses ui. I can use display attributes to show text bold, underlined, or standout. Is it possible to use italics?


Source: (StackOverflow)

Urwid: how to select the whole row, not one column?

Im coding around this example and I dont understand how to select the whole line when I press up or down arrows.


Source: (StackOverflow)