[Python-ideas] Tulip / PEP 3156 (original) (raw)

[Python-ideas] Tulip / PEP 3156 - subprocess events

Nick Coghlan ncoghlan at gmail.com
Sun Jan 20 02:51:14 CET 2013


On Sun, Jan 20, 2013 at 8:53 AM, Glyph <glyph at twistedmatrix.com> wrote:

On Jan 19, 2013, at 9:32 AM, Ben Darnell <ben at bendarnell.com> wrote:

On Fri, Jan 18, 2013 at 8:23 PM, Glyph <glyph at twistedmatrix.com> wrote: For starters, nothing "smells wrong" to me about protocol factories. Responding to this kind of criticism is difficult, because it's not substantive - what's the actual problem? I think that some Python programmers have an aversion to factories because a common path to Python is flight from Java environments that over- or mis-use the factory pattern.

I think the smell is that the factory is A) only used once and B) invoked without adding any additional arguments that weren't available when the factory was passed in, so there's no clear reason to defer creation of the protocol. I think it would make more sense if the transport were passed as an argument to the factory (and then we could get rid of connectionmade as a required method on Protocol, although libraries or applications that want to separate protocol creation from connectionmade could still do so in their own factories). The problem with creating the protocol with the transport as an argument to its constructor is that in order to behave correctly, the transport needs to know about the protocol as well; so it also wants to be constructed with a reference to the protocol to its constructor. So adding a no-protocol-yet case adds more edge-cases to every transport's implementation.

But the trade-off in separating protocol creation from notification of the connection is that it means every protocol has to be written to handle the "no connection yet" gap between init and the call to connection_made.

However, if we instead delay the call to the protocol factory until after the connection is made, then most protocols can be written assuming they always have a connection (at least until connection_lost is called). A persistent protocol that spanned multiple connect/reconnect cycles could be written such that you passed "my_protocol.connection_made" as the protocol factory, while normal protocols (that last only the length of a single connection) would pass "MyProtocol" directly.

At the transport layer, the two states "has a protocol" and "has a connection" could then be collapsed into one - if there is a connection, then there will be a protocol, and vice-versa. This differs from the current status in PEP 3156, where it's possible for a transport to have a protocol without a connection if it calls the protocol factory well before calling connection_made.

Now, it may be that there's a good reason why conflating "has a protocol" and "has a connection" at the transport layer is a bad idea, and thus we actually need the "protocol creation" and "protocol association with a connection" events to be distinct. However, the PEP currently doesn't explain why it's necessary to separate the two, hence the confusion for at least Greg, Ben and myself.

Given that new protocol implementations should be significantly more common than new transport implementations, there's a strong case to be made for pushing any required complexity into the transports.

Cheers, Nick.

-- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia



More information about the Python-ideas mailing list