[Python-Dev] PEP 246, redux

Alex Martelli aleax at aleax.it
Thu Jan 13 18:27:08 CET 2005


On 2005 Jan 13, at 15:34, Clark C. Evans wrote:
    ...
> The 'implicit' adaptation refers to the automagical construction of
> composite adapters assuming that a 'transitive' property holds. I've
> seen nothing in this thread to explain why this is so valueable, why

Let me play devil's advocate: I _have_ seen explanations of why 
transitive adaptation can be convenient -- the most direct one being an 
example by Guido which came in two parts, the second one a 
clarification which came in response to my request about the first one. 
  To summarize it: say we have N concrete classes A1, A2, ... AN which 
all implement interface I.
Now we want to integrate into the system function f1, which requires an 
argument with interface J1, i.e.
     def f1(x):
         x = adapt(x, J1)
         ...
or in Guido's new notation equivalently
     def f1(x: J1):
         ...
and also f2, ..., fM, requiring an argument with interface J2, ..., JM 
respectively.

Without transitivity, we need to code and register M*N adapters.  WITH 
transitivity, we only need M: I->J1, I->J2, ..., I->JM.

The convenience of this is undeniable; and (all other things being 
equal) convenience raises productivity and thus is valuable.

James Knight gave a real-life example, although, since no combinatorial 
explosion was involved, the extra convenience that he missed in 
transitivity was minor compared to the potential for it when the N*M 
issue should arise.

> it shouldn't be explicit,

On this point I'm partly with you: I do not see any real loss of 
convenience in requiring that an adapter which is so perfect and 
lossless as to be usable in transitivity chains be explicitly so 
registered/defined/marker.  E.g., provide a
     registerAdapter_TRANSITIVITY_SUITABLE(X, Y)
entry in addition to the standard registerAdapter which does not supply 
transitivity (or equivalently an optional suitable_for_transitivity 
argument to registerAdapter defaulting to False, etc, etc).
In terms of "should" as opposed to convenience, though, the argument is 
that interface to interface adapters SHOULD always, inherently be 
suitable for transitive chains because there is NO reason, EVER, under 
ANY circumstances, to have such adapters be less than perfect, 
lossless, noiseless, etc, etc.  I am not entirely convinced of this but 
"devil's advocacy wise" I could probably argue for it: for the hapless 
programmers' own good, they should be forced to think very VERY 
carefully of what they're doing, etc, etc.  Yeah, I know, I don't sound 
convincing because I'm not all that convinced myself;-).

>  and on the contrary, most of the "problems
> with adapt()" seem to stem from this aggressive extension of what
> was proposed: Automatic construction of adapter chains is _not_ part

Fair enough, except that it's not just chains of explicitly registered 
adapters: interface inheritance has just the same issues, indeed, in 
PJE's experience, MORE so, because no code is interposed -- if by 
inheriting an interface you're asserting 100% no-problem 
substitutability, the resulting "transitivity" may thus well give 
problems (PJE and I even came close to agreeing that MS COM's 
QueryInterface idea that interface inheritance does NOT implicitly and 
undeniably assert substitutability is very practical, nice, and 
usable...).

> of the original PEP 246 and I hope it remains that way.   I've
> outlined in several posts how this case could be made easy for a
> application developer to do:
>
>   - transitive adapters should always be explicit

What about "registered explicitly as being suitable for transitivity", 
would that suffice?

>   - it should be an error to have more than one adapter
>     from A to Z in the registry

OK, I think.  There has to be a way to replace an adapter with another, 
I think, but it might be fair to require that this be done in two 
steps:
     unregister the old adapter, THEN immediately
     register the new one
so that trying to register an adapter for some A->Z pair which already 
has one is an error.  Replacing adapters feels like a rare enough 
operation that the tiny inconvenience should not be a problem, it 
appears to me.

>   - when adaptation fails, an informative error message can
>     tell the application developer of possible "chains"
>     which could work

Nice, if not too much work.

>   - registration of transitive adapters can be simple command
>     application developers use:  adapt.transitive(from=A,to=Z,via=M)
>     error message can tell an application developer

OK, convenient if feasible.


Considering all of your proposals, I'm wondering: would you be willing 
to author the next needed draft of the PEP in the minimal spirit I was 
proposing?  Since I wrote the last round, you might do a better job of 
editing the next, and if more rounds are needed we could keep 
alternating (perhaps using private mail to exchange partially edited 
drafts, too)...

> The 'registry' idea (which was not explored in the PEP) emerges from
> the need, albeit limited, for the application developer who is
> plugging a component into a framework, to have some say in the
> process.  I think that any actions taken by the user, by registering
> an adapter, should be explicit.

Jim Fulton is VERY keen to have registration of adapters happen "behind 
the scenes" at startup, starting from some kind of declarative form (a 
configuration textfile or the like), given the deployment needs of 
Zope3 -- that shouldn't be a problem, it seems to me (if we have a way 
to to explicit registrations, zope3 can have a startup component that 
finds configuration files and does the registration calls based on that 
'declarative' form).

This potentially opens the door to N-players scenarios for N>3, but, 
like going from 3-tier to N-tier applications, that's not as huge a 
jump as that from N==2 to N==3;-).


> | BUT, and again, Philip has made this point, I can't reason about
> | interfaces in the context of PEP 246, because interfaces aren't
> | defined there. So PEP 246 can't make a clear statement about
> | transitivity, precisely because it doesn't define interfaces. But 
> does
> | this harm PEP 246? I'm not sure.
>
> Well, PEP 246 should be edited, IMHO, to assert that all 'implicit'
> adaptions are out-of-scope, and if they are supported should be done
> so under the direct control of the application developer.

So, are you willing to do that round of editing to PEP 246...?  I'll 
then to the NEXT one which will still undoubtedly be needed...


Alex



More information about the Python-Dev mailing list