Serious Python/Curses Wierdness

Matthew Alton simplicissimus at gmail.com
Sat Sep 18 17:18:13 CEST 2004


The appended program freaks python 2.2 & 2.3 completely out.  To
reproduce the wierdness: i) copy the source to a file called
consarn.py ii) $ python consarn.py; iii) the program is now doing a
getch();  iv) hit a key;  v) the program locks up, the interptreter is
now munching on the CPU;  vi) kill the interpreter from another shell;
 vii) scratch head and wonder why neither of the mutually exclusive
clauses in the _io() member function have written any output via dbg()
calls to the consarn.debug file.

This has simply got to be a major problem with the interpreter and/or
the curses module(s).



__rcsid__ = "$Id: consarn.py,v 1.10 2004/09/17 22:43:30 mqa Exp
zma0472 $"

import string, curses, curses.ascii, time

(_Y, _X) = (24, 80)

def dbg(str):
    f = open("consarn.debug", 'a')
    f.write(time.ctime() + " : " + str + '\n')
    f.close()

class Menu:
    def __init__(self, title="Consarn Menu"):
        self.title = string.center(string.strip(title), _X)
        self.items = []; self.label_width = 0; self.linked = False

    def link(self):
        y = 1; idx = 0; screen = 0
        x = range(2, _X-self.label_width+1, self.label_width+2)
        up = left = ppage = top = self.items[0]
        for i in self.items:
            i["up"] = up; i["down"] = i; i["up"]["down"] = i; up = i
            i["right"] = i["left"] = i["npage"] = i
            if idx > 0: i["left"] = left
            i["left"]["right"] = i; i["ppage"] = ppage
            i["screen"] = screen; i["y"] = y; i["x"] = x[idx]
            if _Y-1 == y:
                y = 1; left = top
                if len(x)-1 == idx:
                    idx = 0; ppage = i; screen += 1
                else:
                    idx += 1
            else:
                if 1 == y: top = i
                y += 1; left = left["down"]
        self.linked = True

        f = open("link.out", 'w')
        for i in self.items:
            f.write("%s:\n" % i["label"])
            f.write("    up     = " + i["up"]["label"] + '\n')
            f.write("    down   = " + i["down"]["label"] + '\n')
            f.write("    right  = " + i["right"]["label"] + '\n')
            f.write("    left   = " + i["left"]["label"] + '\n')
            f.write("    npage  = " + i["npage"]["label"] + '\n')
            f.write("    ppage  = " + i["ppage"]["label"] + '\n')
            f.write("    x      = " + str(i["x"]) + '\n')
            f.write("    y      = " + str(i["y"]) + '\n')
            f.write("    screen = " + str(i["screen"]) + '\n')
        f.close()

    def _io(self, scr):
        if not self.linked: self.link(); scr.keypad(1); #
curses.curs_set(0);
        item = self.items[0]; item["attributes"] = curses.A_STANDOUT
        while True:
            scr.clear()
            scr.addnstr(0, 0, self.title, _X, curses.A_STANDOUT)
            for i in [j for j in self.items if j["screen"] ==
item["screen"]]:
                scr.addnstr(i["y"], i["x"], i["label"], _X,
i["attributes"])
            scr.refresh()
            while True:
                m = { curses.KEY_DOWN  : item["down"],
                      curses.KEY_UP    : item["up"],
                      curses.KEY_RIGHT : item["right"],
                      curses.KEY_LEFT  : item["left"],
                      curses.KEY_PPAGE : item["ppage"] }
                c = scr.getch(); dbg("c = scr.getch()")
                if c in m.keys():
                if c in m.keys():
                    dbg("if c in m.keys():")
                    if m[c] != item:
                        dbg("    if m[c] != item:")
                        item["attributes"] = curses.A_NORMAL
                        m[c]["attributes"] = curses.A_STANDOUT
                        scr.addnstr(item["y"], item["x"],
item["label"], _X,
                                                          
item["attributes"])
                        scr.addnstr(m[c]["y"], m[c]["x"],
m[c]["label"], _X,
                                                          
m[c]["attributes"])
                        if item["screen"] == m[c]["screen"]:
                            item = m[c]; scr.refresh()
                        else:
                            item = m[c]; break
                    else:
                        dbg("Inside else")
                elif curses.ascii.ESC == c:
                    return

    def add_item(self, item_label):
        self.items.append({"label" : item_label, "up" : None, "down" :
None,
                           "left" : None, "right" : None, "ppage" :
None,
                           "npage" : None, "x" : None, "y" : None,
                           "screen" : None, "attributes" :
curses.A_NORMAL})
        self.label_width = max(len(item_label), self.label_width)
        self.linked = False

    def delete_item(self, item):
        if item in self.items:
            self.items.remove(item); self.linked = False

    def IO(self):
        curses.wrapper(self._io)

def test():
    import string
    import random

    print "Initializing the Consarn Demo..."
    random.seed()
    population = string.ascii_letters+string.digits+string.punctuation
#    max_width = random.randint(1, _X-1)
    for max_width in range(1, _X-1):
        m = Menu(title="ROWS=%d COLS=%d R=%d" % (_Y, _X, max_width))
        for x in range(0, 400):
            width = random.randint(1, max_width)
            s = random.sample(population, width)
            label = ""
            for c in s: label += c
            m.add_item(label)
        m.IO()
        del(m)

def test1():
    print "Initializing Debug Test..."
    m = Menu(title="ROWS=%d COLS=%d" % (_Y, _X))
    f = open("debug", 'w')
    f.write("Create start = " + time.ctime() + '\n')
    for x in range(0, 40):
        m.add_item(str(x))
    f.write("Create end = " + time.ctime() + '\n')
    f.close()
    m.IO()
    del(m)

if "__main__" == __name__:
    curses.wrapper(test1())



More information about the Python-list mailing list