Skip to content

Instantly share code, notes, and snippets.

@yc0
Created May 14, 2017 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yc0/92fafae1b5457f10dfd6e64ab64a0fe4 to your computer and use it in GitHub Desktop.
Save yc0/92fafae1b5457f10dfd6e64ab64a0fe4 to your computer and use it in GitHub Desktop.
# This is the Twisted Get Poetry Now! client, version 2.1.
# NOTE: This should not be used as the basis for production code.
import optparse,sys
from twisted.internet.protocol import Protocol, ClientFactory
from twisted.internet import reactor
from twisted.python.failure import Failure
def parse_args():
usage = """usage: %prog [options] [hostname]:port ...
This is the Get Poetry Now! client, Twisted version 2.1.
Run it like this:
python get-poetry-simple.py port1 port2 port3 ...
If you are in the base directory of the twisted-intro package,
you could run it like this:
python twisted-client-2/get-poetry-simple.py 10001 10002 10003
to grab poetry from servers on ports 10001, 10002, and 10003.
Of course, there need to be servers listening on those ports
for that to work.
"""
parser = optparse.OptionParser(usage)
_, addresses = parser.parse_args()
if not addresses:
print(parser.format_help())
parser.exit()
def parse_address(addr):
if ':' not in addr:
host = '127.0.0.1'
port = addr
else:
host, port = addr.split(':', 1)
if not port.isdigit():
parser.error('Ports must be integers.')
return host, int(port)
return map(parse_address, addresses)
class PoetryProtocol(Protocol):
poem = ''
timeout = None
def dataReceived(self, data):
self.poem += data.decode('utf-8')
def connectionLost(self, reason):
if self.delayedTimeout.active():
self.delayedTimeout.cancel()
self.poemReceived(self.poem)
def poemReceived(self, poem):
self.factory.poem_finished(poem)
def connectionMade(self):
self.delayedTimeout = reactor.callLater(1,self.timeouthandler,Failure(TimeoutException(),TimeoutException))
def timeouthandler(self,failure):
self.factory.errback(failure)
self.transport.loseConnection()
class TimeoutException(Exception):
def __init__(self):
self.message = "timeout exception"
def __str__(self):
return repr(self.message)
class PoetryClientFactory(ClientFactory):
protocol = PoetryProtocol # tell base class what proto to build
def __init__(self, callback,errback,timeout):
self.callback = callback
self.errback = errback
self.timeout = timeout
def buildProtocol(self, addr):
proto = ClientFactory.buildProtocol(self,addr)
proto.timeout = self.timeout
return proto
def poem_finished(self, poem=None):
self.callback(poem)
def clientConnectionFailed(self, connector, reason):
'''
reason : A Failure object records Exception and possibly trackback
'''
self.errback(reason)
print("invoke after get_poetry")
def get_poetry(host,port,callback,errback,timeout):
from twisted.internet import reactor
factory = PoetryClientFactory(callback,errback,timeout)
reactor.connectTCP(host,port,factory)
def poetry_main():
addresses = list(parse_args())
from twisted.internet import reactor
poems = []
errs = []
def get_poem(poem):
poems.append(poem)
poem_done()
def poem_failed(err):
from twisted.internet.error import ConnectionRefusedError
r = err.trap(ConnectionRefusedError, TimeoutException)
if r == TimeoutException:
print('Timeout Now')
else:
print("Connection Problem")
errs.append(err)
print("Poem Failed:",err, file=sys.stderr)
poem_done()
def poem_done():
if len(poems) + len(errs) == len(addresses):
reactor.stop()
for addr in addresses:
host,port = addr
get_poetry(host, port, get_poem,poem_failed, 2)
print("exercise 3")
reactor.run()
for poem in poems:
print(poem)
if __name__ == '__main__':
poetry_main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment