[Twisted-Python] Why don't Connectors use deferreds?

I've been wasting yet more time today looking for the "right" way to do a very simple thing: * Given a protocol * Given a destination (e.g. a TCP port) * Connect to the TCP port using the given protocol and return the protocol object to be used by client code Now, I know the "normal" way to do this is to create a one-off factory such as is seen in twisted.web.client and then use the factory to do the after-connection operations. What I'm wondering is why the code doesn't use deferred's to make the operations simpler. That is, a connector succeeds if it completes connecting, and fails otherwise. The return value would be a protocol (and thereby an attached transport). So something like: df = reactor.connectTCP( address, port, factory ) df.addCallbacks( doSomethingWithPortObject,doSomethingIfFailsOrCancelled ) Sure, that doesn't give you the ability to cancel the connection, but I'd guess it's a fairly common pattern for client-side code. With less modification of current code, simply adding a deferred to the connector that is fired on either failure-to-connect or connection would seem reasonable, so: connector = reactor.connectTCP( address, port, factory ) connector.defer.addCallbacks( doSomethingWithPortObject,doSomethingIfFailsOrCancelled ) After all, we're dealing with a classic case of a deferred operation (completion of the connection), so why not make it use the standard deferred mechanisms. I've hacked in a solution for my current code where the factory calls defer.errback in clientConnectionFailed and the protocol calls defer.callback in connectionMade, but that seems extremely inelegant (and to be honest, I'm not sure it really guarantees that the deferred will eventually be called, there may be cases where neither of those methods are called). Maybe I'm just missing something about the "proper" way to do this in Twisted, if so, feel free to point out the one-true-way, Mike ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com

On Thu, 2004-09-09 at 01:12, Mike C. Fletcher wrote:
Maybe I'm just missing something about the "proper" way to do this in Twisted, if so, feel free to point out the one-true-way,
There's a utility class for this in twisted.internet.protocol: deferredOfProtocolInstance = ClientCreator(MyProtocol).connectTCP("localhost", 1234) If this matches your needs I suggest adding an issue to twistedmatrix.com/bugs/ about adding this to the client howto and assign to hypatia or me. -- Itamar Shtull-Trauring http://itamarst.org

Itamar Shtull-Trauring wrote: ...
Okay, issue added to the tracker. Clarification just so no-one else needs to spelunk through to answer the question I had: The return value is a *connected* protocol. I gather so because it looks as though buildProtocol is called by connector.doRead which then calls protocol.makeConnection, which in turn calls protocol.connectionMade, and the use of callLater( 0, ...) makes the callback fire *after* the protocol has had connectionMade called. There appear to be cases where the callback can be called with a protocol that has failed to initialise, that is, if connectionMade (or any of the other operations between callback scheduling and execution) fails for some reason, the callback will still be called. As such the callback really is just notifying that the connection has gone through (more precisely, that the protocol has been built), not necessarily that the protocol is fully initialised and ready-to-go. Still, it does everything I need with a little bit of checking to be sure that the initialisation completed. Thanks, Mike ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com

On Thu, 2004-09-09 at 01:12, Mike C. Fletcher wrote:
Maybe I'm just missing something about the "proper" way to do this in Twisted, if so, feel free to point out the one-true-way,
There's a utility class for this in twisted.internet.protocol: deferredOfProtocolInstance = ClientCreator(MyProtocol).connectTCP("localhost", 1234) If this matches your needs I suggest adding an issue to twistedmatrix.com/bugs/ about adding this to the client howto and assign to hypatia or me. -- Itamar Shtull-Trauring http://itamarst.org

Itamar Shtull-Trauring wrote: ...
Okay, issue added to the tracker. Clarification just so no-one else needs to spelunk through to answer the question I had: The return value is a *connected* protocol. I gather so because it looks as though buildProtocol is called by connector.doRead which then calls protocol.makeConnection, which in turn calls protocol.connectionMade, and the use of callLater( 0, ...) makes the callback fire *after* the protocol has had connectionMade called. There appear to be cases where the callback can be called with a protocol that has failed to initialise, that is, if connectionMade (or any of the other operations between callback scheduling and execution) fails for some reason, the callback will still be called. As such the callback really is just notifying that the connection has gone through (more precisely, that the protocol has been built), not necessarily that the protocol is fully initialised and ready-to-go. Still, it does everything I need with a little bit of checking to be sure that the initialisation completed. Thanks, Mike ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com
participants (2)
-
Itamar Shtull-Trauring
-
Mike C. Fletcher