[Twisted-Python] Question about ReconnectingClientFactory and conch StatefulTelnetProtocol
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):
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):
: 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/in... http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.protocol.Facto... 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
Thanks, Lucas. I spent several hours struggling with this. The source code
DOES make it very obvious. :-) I hadn't realized from the buildProtocol
API documentation that it assigned the factory attribute to the protocol
instance. It's so obvious now... :-)
And, now, I understand the "magic" of assigning the protocol to a factory
which I did not before.
It runs fine!
Mark
On Fri, Feb 5, 2010 at 8:04 PM, Lucas Taylor
On 2/5/10 5:23 PM, Mark Bailey wrote:
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/in...
http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.protocol.Facto...
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
participants (2)
-
Lucas Taylor
-
Mark Bailey