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?
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
.