Hi, Julien Muchembled learn me how to record stdin and then replay it: tee events|program # record program < events Using that, I'm able to do good benchmark. Something _necessary_ to work on optimization.
So one big problem of urwid in UTF-8 is that urwid convert Unicode string to
UTF-8 and then reconvert them to Unicode... It's slow and useless.
The problem is in Canvas class. The attached patch is a proposition to fix the
problem (double conversion). The idea is to store text encoded for the
terminal (UTF-8) in Canvas.text but also to keep the Unicode version in
Canvas.unitext.
Instead of "for ut in unitext: ..." we may use:
if unitext:
...
else:
for t in text:
t = unicode(t, charset)
...
^^ convert to unicode here avoid many slow functions
Don't apply my patch! It's just an example to show the problem. With my patch,
a UTF-8 terminal and with a program (hachoir-urwid) speaking full-Unicode:
the program runs 2 times faster (8 seconds => 4 seconds) ;-) It's not
an "optimization", it's a fix urwid code :)
===
Would it be possible to use spaces in urwid code because I hate TAB! PEP 8
propose "4 spaces per indentation level":
http://www.python.org/dev/peps/pep-0008/
===
Where/How can I download urwid by subversion?
Haypo
--
Victor Stinner
http://hachoir.org/
diff -urb urwid-0.9.7.1/urwid/canvas.py urwid-unicode/urwid/canvas.py
--- urwid-0.9.7.1/urwid/canvas.py 2006-10-09 17:18:35.000000000 +0200
+++ urwid-unicode/urwid/canvas.py 2006-12-31 01:22:48.000000000 +0100
@@ -35,7 +35,7 @@
class for storing rendered text and attributes
"""
def __init__(self,text = None,attr = None, cs = None,
- cursor = None, maxcol=None):
+ cursor = None, maxcol=None, unitext=None):
"""
text -- list of strings, one for each line
attr -- list of run length encoded attributes for text
@@ -46,10 +46,8 @@
if text == None:
text = []
widths = []
- for t in text:
- if type(t) != type(""):
- raise CanvasError("Canvas text must be plain strings encoded in the screen's encoding", `text`)
- widths.append( calc_width( t, 0, len(t)) )
+ for ut in unitext:
+ widths.append( calc_width( ut, 0, len(ut)) )
if maxcol is None:
if widths:
@@ -86,6 +84,7 @@
self.cs = cs
self.cursor = cursor
self.text = text
+ self.unitext = unitext
self.maxcol = maxcol
def rows(self):
@@ -274,6 +273,7 @@
def CanvasCombine(l):
"""Stack canvases in l vertically and return resulting canvas."""
t = []
+ tu = []
a = []
c = []
rows = 0
@@ -281,6 +281,7 @@
cursor = None
for r in l:
t += r.text
+ tu += r.unitext
a += r.attr
c += r.cs
cols = max(cols, r.cols())
@@ -288,7 +289,7 @@
x,y = r.cursor
cursor = x, y+rows
rows = len( t )
- d = Canvas(t, a, c, cursor, cols )
+ d = Canvas(t, a, c, cursor, cols, unitext=tu)
return d
@@ -305,12 +306,14 @@
l2 = [( l[i], l[i+1] ) for i in range(0,len(l),2)]
t = []
+ tu = []
a = []
c = []
rows = max([cnv.rows() for coff, cnv in l2])
for r in range(rows):
t.append([])
+ tu.append([])
a.append([])
c.append([])
@@ -325,35 +328,41 @@
if x > xw:
pad = x-xw
tpad = " "*pad
+ tupad = u" "*pad
for r in range(rows):
t[r].append(tpad)
+ tu[r].append(tupad)
rle_append_modify(a[r],(None,pad))
rle_append_modify(c[r],(None,pad))
xw = x + cnv.cols()
i = 0
while i < cnv.rows():
t[i].append(cnv.text[i])
+ tu[i].append(unicode(cnv.text[i])) # FIXME: This line may crash!
rle_join_modify( a[i], cnv.attr[i] )
rle_join_modify( c[i], cnv.cs[i] )
i += 1
if i < rows:
pad = cnv.cols()
tpad = " "*pad
+ tupad = u" "*pad
while i < rows:
t[i].append(tpad)
+ tu[r].append(tupad)
rle_append_modify(a[i],(None,pad))
rle_append_modify(c[i],(None,pad))
i += 1
if cnv.cursor:
cnv.translate_coords(x, 0)
cursor = cnv.cursor
- d = Canvas( ["".join(lt) for lt in t], a, c, cursor, xw )
+ d = Canvas( ["".join(lt) for lt in t], a, c, cursor, xw , [u"".join(lt) for lt in tu])
return d
def apply_text_layout( text, attr, ls, maxcol ):
utext = type(text)==type(u"")
t = []
+ ut = []
a = []
c = []
@@ -394,6 +403,7 @@
line_layout = trim_line( line_layout, text, 0, maxcol )
line = []
+ uline = []
linea = []
linec = []
@@ -432,27 +442,32 @@
tseg, cs = apply_target_encoding(
text[s.offs:s.end])
line.append(tseg)
+ uline.append(text[s.offs:s.end])
attrrange(s.offs, s.end, rle_len(cs))
rle_join_modify( linec, cs )
elif s.text:
tseg, cs = apply_target_encoding( s.text )
line.append(tseg)
+ uline.append(s.text)
attrrange( s.offs, s.offs, len(tseg) )
rle_join_modify( linec, cs )
elif s.offs:
if s.sc:
line.append(" "*s.sc)
+ uline.append(u" "*s.sc)
attrrange( s.offs, s.offs, s.sc )
else:
line.append(" "*s.sc)
+ uline.append(u" "*s.sc)
linea.append((None, s.sc))
linec.append((None, s.sc))
t.append("".join(line))
+ ut.append("".join(uline))
a.append(linea)
c.append(linec)
- return Canvas(t,a,c, maxcol=maxcol)
+ return Canvas(t,a,c, maxcol=maxcol,unitext=ut)
diff -urb urwid-0.9.7.1/urwid/listbox.py urwid-unicode/urwid/listbox.py
--- urwid-0.9.7.1/urwid/listbox.py 2006-10-09 17:18:35.000000000 +0200
+++ urwid-unicode/urwid/listbox.py 2006-12-31 01:10:27.000000000 +0100
@@ -282,7 +282,7 @@
bottom_pos = focus_pos
if fill_below: bottom_pos = fill_below[-1][1]
assert trim_bottom==0 and self.body.get_next(bottom_pos) == (None,None), "Listbox contents too short! Probably urwid's fault (please report): %s" % `top,middle,bottom`
- l.append( Canvas( [""] * (maxrow-rows), maxcol=maxcol ))
+ l.append( Canvas( [""] * (maxrow-rows), maxcol=maxcol, unitext=[u""] * (maxrow-rows) ))
return CanvasCombine( l )
canvas.py
Description: application/python
_______________________________________________ Urwid mailing list [email protected] http://lists.excess.org/mailman/listinfo/urwid
