On Fri, Nov 27, 2009 at 12:32:52PM +0100, Martijn Faassen wrote: > Hi there, > > Introduction > ------------ > > So now that we've had some discussion and to exit the "bikeshed" phase, > let's see about getting some volunteers to work on this. > > The goal here is to make interfaces disappear into the language as much > as possible. This means that I'll ignore backwards compatibility while > sketching out the "ideal semantics" below - I have the impression we can > get consensus on the following behavior: > > Simple adaptation: > > IFoo(adapted) > > Named adaptation: > > IFoo(adapted, name="foo") > > Adaptation with a default > > IFoo(adapted, default=bar) > > Multi-adaptation: > > IFoo(one, two) > > Named multi adaptation: > > IFoo(one, two, name="foo") > > Multi-adaptation with a default: > > IFoo(one, two, default=bar) > > Utility lookup: > > IFoo() > > Named utility lookup: > > IFoo(name="foo") > > Utility lookup with a default: > > IFoo(default=bar) > > Where "name" and "default" can be combined. The name and default keyword > parameters have to be used explicitly - *args is interpreted as what to > adapt only. Any other keyword parameters should be rejected.
+0.5 --- I can live with it. Backwards incompatibility with IFoo(one, default) will be a slight inconvenience. There were proposals I liked more (IFoo.adapt(), IFoo.utility()) and proposals I liked less (IFoo((one, two, we_like_parentheses, and_screw_people_adapting_tuples))). > Utility lookups versus adapter lookups > -------------------------------------- > > There was some discussion on whether utility lookups are really > something fundamentally different than adaptation as adaptation > *creates* a new instance while utility lookup uses a registered > instance. I think the essential part here is however: "give me an > instance that implements IFoo", and utility lookup fits there. We could > even envision a way to create utilities that *does* instantiate them on > the fly - it shouldn't affect the semantics for the user of the utility. +1 I've often had the need to "give me an instance that implements IFoo" where that instance is not a singleton. I can write the code to find the right IFoo, but since utilities are so limited, I had to resort to adapting None. > Features off the table for now > ------------------------------- > > Saying an interface is implemented by a class (Python 2.6 and up) with a > decorator we'll leave out of the discussion for now. Personally, I prefer Zope's syntax ("decorators" inside the class block) to Python's (decorators above the class block), aesthetically. > It would also be come up with an improved API to look up the adapter > *before* it is called, but I'd also like to take this off the table for > this discussion. > > Backwards compatibility > ----------------------- > > Now let's get back to my favorite topic in this discussion: backwards > compatibility. The ideal semantics unfortunately break backwards > compatibility for the single adapter lookup case, as this supports a > second argument, the default. > > The challenge is therefore to come up with a way to support the new > semantics without breaking the old. Can't be done. > We could introduce the following upgrade pattern: > > zope.component 3.8.0: old semantics > > zope.component 3.9: old semantics is the default. new semantics > supported too somehow but explicitly triggered. How? from zope.__future__ import new_adapter_lookup? > zope.component 4.0: new semantics is the default. Old semantics is not > supported anymore. > > We could, if needed, maintain zope.component 3.x in parallel with the > new-semantics 4.0 line for a while. > > A per-module triggering of the new semantics might be done like this: > > from zope.component.__future__ import __new_lookup__ Whoa, great minds think alike ;) > Is that implementable at all however? I think so, with some caveats. E.g. something like class Interface(...): def __call__(...): new_semantics = (sys._getframe(1).f_globals.get('__new_lookup__') is zope.component.__future__.__new_lookup__) > Someone needs to experiment. > > Alternatively we could do something special when we see this: IFoo(foo, > bar). This is ambiguous - is the new semantics in use or the old one? If > the adapter cannot be looked up using multi adaptation we *could* fall > back on single adaptation under the assumption that the old semantics > are desired. But this will lead to a problem if the new semantics *was* > desired but the component simply could not be found. Which is why I'd maybe slightly prefer IFoo.adapt(foo, bar) as the explicit syntax for multiadaptation. Or live with the status quo. > I think it's important not to do a "big bang" upgrade but instead allow > people to upgrade bit by bit. It should be possible to compose an > application that mixes code that expects the old semantics with code > that expects the new semantics. A bit by bit upgrade I think would > ideally be on a per-module basis. I think it's important to make sure we > can support such an upgrade *before* we release any of this. +1 > Conclusions > ----------- > > Are people okay with the proposed semantics? +0.5 > Would people be okay with such an upgrade path? Any better ideas? IFoo(one, default), IFoo.adapt(one, two, default=default), IFoo.utility(default=default). > Most importantly, any volunteers? Ah. Um. Maybe, but only if I get to choose my preferred syntax, and am allowed to give up after a couple of days declaring the task too hard. Marius Gedminas -- http://pov.lt/ -- Zope 3 consulting and development
Description: Digital signature
_______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org https://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - https://mail.zope.org/mailman/listinfo/zope-announce https://mail.zope.org/mailman/listinfo/zope )