inicio mail me! sindicaci;ón

I love Twisted Matrix

<disclaimer>
Men, this is pure love, I’m a geek and if you aren’t too, don’t read further.
</disclaimer>


In those days in my spare time I’m working on Matt Goodall’s Twisted Pastebin to learn using the framework and Nevow. The original version is very good but needed some enhancements so I put my hands on it and start working around. I knew nothing about Nevow and very little but with the help of the #twisted.web guys on IRC and with some tips given me by my friend Valentino “dialtone” Volonghi I coded a better pastebin featuring persistent cookies, syntax highlighting for about 30 languages, navigation UI (needs to be improved, it’s on my TODO list), export as text of pastings, a yet-to-be-coded archives interface (and perhaps a very simple backend to allow deletion and something like that). Ah! I forgot the main change (the real reason why I started the improving process): Atop, the Python OODB (based on Twisted obviously) developed by the Divmod team. So in a couple of hours I replaced the pickle based backend to use it.

But what excited me most is the thing that I’ve done two minutes ago. I replaced this bad bad code (I was too lazy to read again the manual, shame on me):

def _get_process_output(text, language):
    lang = languagesmap.get(language)
    if not lang:
        return text
    params = ARGS % lang
    cmd = "%s %s" % (PATH, params)
    stdin, stdout_err = os.popen2(cmd, params)
    stdin.write(text)
    stdin.close()
    return stdout_err.read()

def colouriser(text, language):
    text = "\n".join(text.splitlines())
    d = threads.deferToThread(_get_process_output, text, language)
    d.addCallbacks(lambda data: data, lambda data: data)
    return d



with this wonderful piece of code enclosing all the Twisted Matrix Power:

def colouriser(text, language):
    text = "\n".join(text.splitlines())
    lang = languagesmap.get(language)
    if not lang:
        lang = "txt"
    params = ARGS % lang
    params = params.split()
    params.insert(0, PROCESS_NAME)
    d = defer.Deferred()
    hlpp = HLProcessProtocol(text, d)
    reactor.spawnProcess(hlpp, PATH, params)
    return d

class HLProcessProtocol(protocol.ProcessProtocol):
    def __init__(self, text, d):
        self.text = text
        self.d = d
        self.buffer = []

    def connectionMade(self):
        self.transport.write(self.text)
        self.transport.closeStdin()

    def outReceived(self, data):
        self.buffer.append(data)

    def outConnectionLost(self):
        data = "".join(self.buffer)
        self.receiveColourisedText(data)
        
    def receiveColourisedText(self, data):
        self.d.callback(data)


again… shame on me, shame on me :)

  • Twisted Matrix is an event driven framework developed in Python with tons of ready to use protocols; if you want to do networking use Twisted, drop everything else ;)
  • a pastebin is a web application used to share code, more here: http://en.wikipedia.org/wiki/Pastebin
  • Nevow is a web application templating system built upon Twisted Matrix
  • Atop is a OODB mainly used as a backend for Quotient, the Divmod’s messaging oriented application server
  • Pickle is the Python builtin serialization mechanism.

The online demo is here http://rhymes.dyndns.org:8083.

I will not guarantee that it will be up 24hours a day because it’s my 1Ghz laptop, so please, don’t flood it and since I’m still working on the codebase it will be shutted down on my own needs.

Bye, share the love.

update: the archives interface is there, needs only better colors. The backend is useless so I’ll not waste my time coding an interface used only to delete pastings. I noticed that (as usual) the site with IE sucks so I gotta take some time tweaking the css files (perhaps I could go without css at all for IE users <g>).

Related posts

  • mod_python and others…
  • Apple has donated an Xserve to Twisted
  • HttpListener (.NET) vs BaseHTTPServer (Python)
  • PyObjC in OSX Leopard
  • Thinking about the future (and mine too)
  • Gravatar

    Anonymous said,

    September 1, 2004 @ 5:23 pm

    I am dumb. The latter is longer and less clear to me. Also, I don’t think it is much more efficient, given that anyway the bottleneck is the external program you seem to be using the generate the html colorized source (vim? :).

    What’s the point in the new code, except a sytrange usage of a class instead of procedural code?

    Gravatar

    Lawrence said,

    September 1, 2004 @ 6:04 pm

    Hi Anonymous, let me explain… the latter is modeled around the TwistedMatrix way. You have to know that TM is an asynchrounous single-threaded event-driven framework hence everything must return quickly and not block the main thread. If you have something that blocks is better wrapping it around a threads.DeferToThread call (see: http://www.twistedmatrix.com/documents/current/howto/threading)
    but let me say: it was a ugly hack, and if you can avoid using a thread, it’s better (read this: Threads considered harmful)

    Then, because I have to manage an external tool and because I found the howto for process in the docs: http://www.twistedmatrix.com/documents/current/howto/process) that explain step by step how to handle a process from a TM based application.

    You abstract the external program in a ProcessProtocol subclass, write and read with standard methods, TM will handle buffering, async and so on, when the process dies TM will fire outConnectionLost() and you can return the data :)

    Both the code snippets returns a deferred, not blocking the code and the other computations, promising that it will call it when the data will be ready. See: http://www.twistedmatrix.com/documents/current/howto/deferTM is hard, but opens your mind

    Bye!

    RSS feed for comments on this post · TrackBack URI

    Leave a Comment