[Zope-dev] implementing zope.component 4.0
Marius Gedminas
marius at gedmin.as
Fri Nov 27 07:11:17 EST 2009
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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: Digital signature
Url : http://mail.zope.org/pipermail/zope-dev/attachments/20091127/98b1aaff/attachment-0001.bin
More information about the Zope-Dev
mailing list