Search code examples
pythonnetworkingtwistedtubes

Getting TypeError with Python Tubes and Twisted module


I'm currently following the documentation for Python Tubes and all was going well for the most part. Issue is, once I implemented the Reverser class into my code, a TypeError kept appearing when I attempted to connect via Telnet.

Here's my code:

#!/etc/python2.7
from tubes.protocol import flowFountFromEndpoint
from tubes.listening import Listener

from twisted.internet.endpoints import serverFromString
from twisted.internet.defer import Deferred, inlineCallbacks
from twisted.python import log

from tubes.framing import bytesToLines, linesToBytes
from tubes.tube import series



class Reverser(object):
    def received(self, item):
        yield b"".join(reversed(item))

def reverseFlow(flow):
    lineReverser = series(bytesToLines(), Reverser(), linesToBytes())
    flow.fount.flowTo(lineReverser).flowTo(flow.drain)

@inlineCallbacks
def main(reactor, listenOn="stdio:"):
    listener = Listener(reverseFlow)
    endpoint = serverFromString(reactor, listenOn)
    flowFount = yield flowFountFromEndpoint(endpoint)
    flowFount.flowTo(listener)
    yield Deferred()

if __name__ == '__main__':
    from twisted.internet.task import react
    react(main, ["tcp:8000"])

I'm using this command in another terminal (Linux, Ubuntu 19.10) to connect to the server shown above:

telnet 127.0.0.1 8000

The second it attempts to connect, the server shows this message:

Unhandled Error
Traceback (most recent call last):
  File "/home/edgecase/.local/lib/python2.7/site-packages/twisted/python/log.py", line 86, in callWithContext
    return context.call({ILogContext: newCtx}, func, *args, **kw)
  File "/home/edgecase/.local/lib/python2.7/site-packages/twisted/python/context.py", line 122, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/home/edgecase/.local/lib/python2.7/site-packages/twisted/python/context.py", line 85, in callWithContext
    return func(*args,**kw)
  File "/home/edgecase/.local/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 614, in _doReadOrWrite
    why = selectable.doRead()
--- <exception caught here> ---
  File "/home/edgecase/.local/lib/python2.7/site-packages/twisted/internet/tcp.py", line 1435, in doRead
    protocol.makeConnection(transport)
  File "/home/edgecase/.local/lib/python2.7/site-packages/twisted/internet/protocol.py", line 514, in makeConnection
    self.connectionMade()
  File "/home/edgecase/.local/lib/python2.7/site-packages/tubes/protocol.py", line 239, in connectionMade
    self._flow(self._fount, self._drain)
  File "/home/edgecase/.local/lib/python2.7/site-packages/tubes/protocol.py", line 411, in aFlowFunction
    listening.impl.drain.receive(Flow(fount, drain))
  File "/home/edgecase/.local/lib/python2.7/site-packages/tubes/listening.py", line 93, in receive
    item.drain))
  File "/home/edgecase/Programs/Tubes/test3.py", line 19, in reverseFlow
    lineReverser = series(bytesToLines(), Reverser(), linesToBytes())
  File "/home/edgecase/.local/lib/python2.7/site-packages/tubes/tube.py", line 235, in series
    drains = [IDrain(tube) for tube in tubes]
exceptions.TypeError: ('Could not adapt', <__main__.Reverser object at 0x7faf92066a90>, <InterfaceClass tubes.itube.IDrain>)

Ideally, the server should take in any data sent to it, reverse that data and send it back - just as a simple example of processing data using the Tubes module. And for the life of me I can't figure out why it's not working. I've tried looking online, but I can't seem to find a solution. What exactly is causing this?


Solution

  • There appears to be a bug in the documentation renderer. If you read the source listing then you see that Reverser is supposed to be decorated with tube:

    from tubes.tube import tube, series
    
    @tube
    class Reverser(object):
        def received(self, item):
            yield b"".join(reversed(item))
    

    I expect that this decorator makes the necessary annotations so that Reverser instances will be adaptable to IDrain.