The latest version of Urwid in subversion now incorporates a new caching mechanism and a compiled C version of some string utilities from Rebecca Breu.

The performance has really improved since the last stable release (0.9.7.2). Here are the results I get when comparing the two versions running the benchmark programs in contrib:

: reduction in running time / speed improvement
bench_1.py (tour):      41% /  70%
bench_2.py (bigtext):   82% / 450%
bench_3.py (calc):      56% / 125%
bench_4.py (graph):     73% / 268%

Some further improvements are still possible, but the latest version is very close to what will be released as 0.9.8.


Now to the changes.

All the standard widgets in Urwid now cache the canvas they produce from their render() functions. The caching is done using a new CanvasCache class. The CanvasCache will hold on to a canvas as long as there is still a reference to it. The Screen objects in raw_display and curses_display hold on to a reference to the last screen rendered, allowing the cache to work without modifying your applications.

However, caching canvases requires that we know when a widget has changed, so there are a couple changes to Urwid's interface that I couldn't avoid.

Pile and Columns widgets need to know when their content changes, so while you used to be able to write code like:

  some_widgets = [widget_a, widget_b, widget_c]
  piled_widgets = urwid.Pile(some_widgets)
  # later add/remove items from some_widgets

Now you will have to write:

  piled_widgets = urwid.Pile([widget_a, widget_b, widget_c])
  some_widgets = piled_widgets.widget_list
  # later add/remove items from some_widgets

This change is backwards-compatible with earlier versions of Urwid. Now the widget_list member of Pile and Columns is a special list type that can detect changes to its contents.


The ListBox class delegates determining what widgets are displayed to a "list walker". The default list walker class can now detect changes in the same way that Pile and Columns do. If you are using code similar to:

  some_widgets = [widget_a, widget_b, widget_c]
  listbox = urwid.ListBox(some_widgets)
  # later add/remove items from some_widgets

Now you will have to write:

  listbox = urwid.ListBox([widget_a, widget_b, widget_c])
  some_widgets = urwid.ListBox.body
  # later add/remove items from some_widgets

This change is also backwards compatible.

Custom list walker classes now need to support sending a "modified" signal when their contents change. A list walker class might have looked like:

  class CustomListWalker(object):
    # definitions of get_focus, set_focus, get_next, get_prev...

Now you will have to write:

  class CustomListWalker(urwid.ListWalker):
    # definitions of get_focus, set_focus, get_next, get_prev...
    # call self._modified() when the contents change.

Or, if you need to have backwards compatibility write:

  try: ListWalker = urwid.ListWalker
  except:
    class ListWalker(object):
      def _modified(self): pass

  class CustomListWalker(ListWalker):
    # definitions of get_focus, set_focus, get_next, get_prev...
    # call self._modified() when the contents change.


Please post to this list or join our IRC channel if you have any questions or comments.

Ian


_______________________________________________
Urwid mailing list
[email protected]
http://lists.excess.org/mailman/listinfo/urwid

Reply via email to