Friday, February 25, 2011

If you Misspell "protocol", this is what you get

Traceback (most recent call last):
  File "/usr/lib/python2.5/site-packages/twisted/python/log.py", line 51, in callWithLogger
    return callWithContext({"system": lp}, func, *args, **kw)
  File "/usr/lib/python2.5/site-packages/twisted/python/log.py", line 36, in callWithContext
    return context.call({ILogContext: newCtx}, func, *args, **kw)
  File "/usr/lib/python2.5/site-packages/twisted/python/context.py", line 59, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/usr/lib/python2.5/site-packages/twisted/python/context.py", line 37, in callWithContext
    return func(*args,**kw)
---  ---
  File "/usr/lib/python2.5/site-packages/twisted/internet/selectreactor.py", line 146, in _doReadOrWrite
    why = getattr(selectable, method)()
  File "/usr/lib/python2.5/site-packages/twisted/internet/tcp.py", line 563, in doConnect
    self._connectDone()
  File "/usr/lib/python2.5/site-packages/twisted/internet/tcp.py", line 566, in _connectDone
    self.protocol = self.connector.buildProtocol(self.getPeer())
  File "/usr/lib/python2.5/site-packages/twisted/internet/base.py", line 930, in buildProtocol
    return self.factory.buildProtocol(addr)
  File "/usr/lib/python2.5/site-packages/twisted/internet/protocol.py", line 98, in buildProtocol
    p = self.protocol()
This is worth remembering. Note that nothing here refers to the corresponding factory or the code where the error was made. I think this is one reason Twisted can be frustrating.

You can see this error with an simple example:

from twisted.internet import protocol
from twisted.internet import reactor
class MyProtocol(protocol.Protocol):
    pass
class MyFactory(protocol.ReconnectingClientFactory):
    protcol = MyProtocol
reactor.connectTCP('google.com', 80, MyFactory())
reactor.run()
It's certainly convenient to be able to set the protocol so simply, but it's disappointing that the error isn't caught at the source. I wonder why the factories don't have an __init__ method that checks for a valid protocol field?