On 2/5/10 5:23 PM, Mark Bailey wrote: > Good day, everyone: > > Continuing my effort to learn Python and Twisted, I need to create > several Telnet clients and somehow send two arguments to each and > receive data from each. > > I tried the same pattern that I used with the Telnet server and created > a Factory, actually a ReconnectingClientFactory. It doesn't work. My > source and the error (no attribute 'factory') are below. > > Do the "conch" protocols not support a factory? Is there an alternative > that provides a Telnet client with a lineReceived method? > > What am I doing wrong? :-) I suppose I could pass arguments to > ClusterClient by overriding __init__, but that seems inelegant. > > Thanks for your help. > > Mark > > ---------- > > from twisted.internet.protocol import Protocol, ReconnectingClientFactory > from sys import stdout > > from twisted.internet import reactor > > from twisted.conch.telnet import StatefulTelnetProtocol > > class ClusterClient(StatefulTelnetProtocol): > > def lineReceived(self, data): > print self.factory.prompt, self.factory.call > print data > > class ClusterClientFactory(ReconnectingClientFactory): > > protocol = ClusterClient > > def __init__(self): > self.prompt = "call:" > self.call = "kd4d" > > def startedConnecting(self, connector): > print 'Started to connect.' > > def buildProtocol(self, addr): > print 'Connected.' > self.resetDelay() > return ClusterClient() > > def clientConnectionLost(self, connector, reason): > print 'Lost connection. Reason:', reason > ReconnectingClientFactory.clientConnectionLost(self, connector, > reason) > > def clientConnectionFailed(self, connector, reason): > print 'Connection failed. Reason:', reason > ReconnectingClientFactory.clientConnectionFailed(self, connector, > reason) > if __name__ == '__main__': > factory = ClusterClientFactory() > factory.maxDelay = 120 # two minutes > print factory.prompt, factory.call > reactor.connectTCP("localhost", 8023, factory) > > > reactor.run() > > ----------------- > > File "ClusterClient.py", line 11, in lineReceived > print self.factory.prompt, self.factory.call > exceptions.AttributeError: ClusterClient instance has no attribute 'factory' > Lost connection. Reason: [Failure instance: Traceback (failure with no > frames): > <type 'exceptions.AttributeError'>: ClusterClient instance has no > attribute 'fa > ctory' > ] >
Hi Mark, The problem is that you have overridden buildProtocol in your Factory and not set the factory attribute on the protocol instance (ClusterClient instance has no attribute 'factory'). buildProtocol is responsible for creating the protocol instance and the default implementation takes care of assigning the factory to the protocol. see the source for Factory and buildProtocol...it's very concise: http://twistedmatrix.com/trac/browser/tags/releases/twisted-9.0.0/twisted/internet/protocol.py#L87 http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.protocol.Factory.html#buildProtocol So something like this should work in your case: def buildProtocol(self, addr): print 'Connected.' self.resetDelay() p = self.protocol() p.factory = self return p This doc is also helpful for understanding the relationship between Protocols and Factories: http://twistedmatrix.com/documents/current/core/howto/servers.html It may be worth emphasizing that there's no real magic going on here...you're just assigning a python object as an attribute of the protocol instance. Lucas _______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python