[Zope3-checkins] CVS: Zope3/src/zope/app/services -
interface.py:1.17.6.1
Jim Fulton
jim at zope.com
Fri Oct 10 07:17:08 EDT 2003
Update of /cvs-repository/Zope3/src/zope/app/services
In directory cvs.zope.org:/tmp/cvs-serv8781/zope/app/services
Modified Files:
Tag: adaptergeddon-branch
interface.py
Log Message:
Committing some initial work on the adaptergeddon branch to facilitate
colaboration.
=== Zope3/src/zope/app/services/interface.py 1.17 => 1.17.6.1 ===
--- Zope3/src/zope/app/services/interface.py:1.17 Sun Sep 21 13:31:59 2003
+++ Zope3/src/zope/app/services/interface.py Fri Oct 10 07:16:37 2003
@@ -123,3 +123,464 @@
if match[0].find(search_string) > -1]
return matching
+
+##############################################################################
+# New code
+
+import weakref
+from zope.interface.ro import ro
+from zope.interface.declarations import providedBy
+from persistence import Persistent
+from persistence.dict import PersistentDict
+from zope.app.location import Location
+from zope.app.container.contained import Contained
+from zope.app.services.registration import RegistrationStack
+
+class Surrogate(Persistent, Location):
+
+ def __init__(self, interface, registry):
+
+ # These two change together, so there's no sense putting them
+ # in seperate records. Well, we can change bases and adapters
+ # independently. A change to either bases or adapters will
+ # force a change to implied, so what the heck.
+ self._adapters = {}
+ self._implied = {}
+ self.__bases__ = [registry.get(base) for base in interface.__bases__]
+ for base in self.__bases__:
+ base.dependents[self] = 1
+
+ # These don't change
+ self._interface = interface
+ interface.addDependent(self)
+ self.__parent__ = registry
+
+ # Dependents can change independently of everything
+ # else, so it makes sense to give it its own record.
+ self.dependents = PersistentDict()
+
+ self._computeImplied()
+
+ def extends(self, other, strict=True):
+ if other is self and strict:
+ return False
+
+ i = self._implied.get(other)
+ if i is not None and not i:
+ return True
+ return False
+
+ def isImplementedBy(self, ob):
+ return self._interface.isImplementedBy(ob)
+
+ def _adaptTo(self, specification, factory, name=None, with=()):
+ self._adapters[with, name, specification] = factory
+ self.changed()
+
+ def changed(self):
+ self._computeImplied()
+ for dependent in self.dependents:
+ dependent.changed()
+
+ def _computeImplied(self):
+
+ implied = self._implied
+ implied.clear()
+
+ ancestors = ro(self)
+
+
+ for ancestor in ancestors:
+ # We directly imply our ancestors:
+ implied[ancestor] = ()
+
+ # Work dict used to keep track of the registered interface
+ # leading to an implied entry. This is so that we can can
+ # override an implied entry of we get a closer "provided"
+ # fit.
+ registered = {}
+
+ # Add adapters and interfaces directly implied by same:
+ items = ancestor._adapters.iteritems()
+ for (with, name, target), factory in items:
+ if with:
+ self.__add_multi_adapter(with, name, target, target,
+ implied, registered,
+ (factory, ))
+ elif name is not None:
+ self.__add_named_adapter(target, target, name,
+ implied, registered,
+ (factory, ))
+ else:
+ self.__add_adapter(target, target,
+ implied, registered,
+ (factory, ))
+
+
+ def __add_adapter(self, target, provided, implied, registered, factories):
+ if (target not in implied
+ or
+ (target in registered and registered[target].extends(provided))
+ ):
+ registered[target] = provided
+ implied[target] = factories
+ for b in target.__bases__:
+ self.__add_adapter(b, provided, implied, registered, factories)
+
+ def __add_named_adapter(self, target, provided, name,
+ implied, registered, factories):
+ key = target, name
+ if (key not in implied
+ or
+ (key in registered and registered[key].extends(provided))
+ ):
+ registered[key] = provided
+ implied[key] = factories
+ for b in target.__bases__:
+ self.__add_named_adapter(b, provided, name,
+ implied, registered, factories)
+
+ def __add_multi_adapter(self, interfaces, name, target, provided,
+ implied, registered, factories):
+
+ order = len(interfaces)+1
+ adapters = implied.get((target, name, order))
+ if adapters is None:
+ adapters = {}
+ implied[(target, name, order)] = adapters
+
+ adapters.setdefault(interfaces, factories)
+
+ for b in target.__bases__:
+ self.__add_multi_adapter(interfaces, name, b, provided,
+ implied, registered, factories)
+
+class InterfaceService(Persistent, Contained):
+
+ def __init__(self):
+ self._surrogates = PersistentDict()
+
+ def get(self, declaration):
+ surrogate = self._surrogates.get(declaration)
+ if surrogate is None:
+ surrogate = Surrogate(declaration, self)
+ self._surrogates[declaration] = surrogate
+ return surrogate
+
+ def provideAdapter(self, required, provided, factory,
+ name=None, with=()):
+ required = self.get(required)
+ provided = self.get(provided)
+ if with:
+ with = tuple(map(self.get, with))
+ else:
+ with = ()
+ required._adaptTo(provided, factory, name, with)
+
+
+ def queryRegistrationsFor(self, registration, default=None):
+ """zope.app.interfaces.services.registration.IRegistry"""
+ required = self.get(registration.forInterfaces[0])
+ provided = self.get(registration.providedInterface)
+ with = tuple(map(self.get, registration.forInterfaces[1:]))
+ name = registration.name
+ return required._adapters.get((with, name, provided))
+
+ def createRegistrationsFor(self, registration):
+ """zope.app.interfaces.services.registration.IRegistry"""
+ required = self.get(registration.forInterfaces[0])
+ provided = self.get(registration.providedInterface)
+ with = tuple(map(self.get, registration.forInterfaces[1:]))
+ name = registration.name
+ stack = required._adapters.get((with, name, provided))
+ if stack is None:
+ stack = AdapterRegistrationStack(self)
+ required._adapters[(with, name, provided)] = stack
+
+
+
+
+
+
+
+ def queryAdapter(self, ob, interface, default=None):
+ """Query a simple adapter
+
+ >>> import zope.interface
+ >>> class F0(zope.interface.Interface):
+ ... pass
+ >>> class F1(F0):
+ ... pass
+
+ >>> class C:
+ ... zope.interface.implements(F1)
+ >>> c = C()
+
+ >>> registry = SurrogateRegistry()
+
+ When we adapt an object to an interface it implements, we get
+ the object back:
+
+ >>> registry.queryAdapter(c, F0) is c
+ 1
+
+ But adapting to some other interface returns the default:
+
+ >>> class B0(zope.interface.Interface):
+ ... pass
+ >>> class B1(B0):
+ ... pass
+
+ >>> registry.queryAdapter(c, B0)
+ >>> registry.queryAdapter(c, B0, 42)
+ 42
+
+ Unless we define an adapter:
+
+ >>> def f1(ob):
+ ... return 1
+
+ >>> registry.provideAdapter(F0, B1, f1)
+ >>> registry.queryAdapter(c, B0)
+ 1
+
+ If we define a more specific adapter (for F1), we'll get that:
+
+ >>> def f2(ob):
+ ... return 2
+
+ >>> registry.provideAdapter(F1, B1, f2)
+ >>> registry.queryAdapter(c, B0)
+ 2
+
+ >>> def f3(ob):
+ ... return 3
+
+ >>> registry.provideAdapter(F1, B0, f3)
+ >>> registry.queryAdapter(c, B0)
+ 3
+
+
+ """
+
+ surrogates = self._surrogates
+
+ surrogate = surrogates.get(interface)
+ if surrogate is None:
+ # If there is no surrogate for the interface, then we can't
+ # have an adapter for it.
+
+ # But we may implement it
+ if interface.isImplementedBy(ob):
+ return ob
+ return default
+
+ interface = surrogate
+
+ for declaration in providedBy(ob):
+ s = surrogates.get(declaration)
+ if s is None:
+ s = self.get(declaration)
+
+ factories = s._implied.get(interface)
+ if factories is not None:
+ for factory in factories:
+ ob = factory(ob)
+ return ob
+
+ return default
+
+ def queryNamedAdapter(self, ob, interface, name, default=None):
+ """Query a named simple adapter
+
+ >>> import zope.interface
+ >>> class F0(zope.interface.Interface):
+ ... pass
+ >>> class F1(F0):
+ ... pass
+
+ >>> class C:
+ ... zope.interface.implements(F1)
+ >>> c = C()
+
+ >>> registry = SurrogateRegistry()
+
+ If we ask for a named adapter, we won't get a result unless there
+ is a named adapter, even if the object implements the interface:
+
+ >>> registry.queryNamedAdapter(c, F0, 'bob')
+
+ >>> class B0(zope.interface.Interface):
+ ... pass
+ >>> class B1(B0):
+ ... pass
+
+
+ >>> def f1(ob):
+ ... return 1
+
+ >>> registry.provideAdapter(F0, B1, f1, name='bob')
+ >>> registry.queryNamedAdapter(c, B0, 'bob')
+ 1
+ >>> registry.queryNamedAdapter(c, B0, 'bruce')
+
+
+ >>> def f2(ob):
+ ... return 2
+
+ >>> registry.provideAdapter(F1, B1, f2, name='bob')
+ >>> registry.queryNamedAdapter(c, B0, 'bob')
+ 2
+
+ >>> def f3(ob):
+ ... return 3
+
+ >>> registry.provideAdapter(F1, B0, f3, name='bob')
+ >>> registry.queryNamedAdapter(c, B0, 'bob')
+ 3
+
+
+ """
+ surrogates = self._surrogates
+
+ interface = surrogates.get(interface)
+ if interface is None:
+ # If there is no surrogate for the interface, then we can't
+ # have an adapter for it.
+ return default
+
+ for declaration in providedBy(ob):
+ s = surrogates.get(declaration)
+ if s is None:
+ s = self.get(declaration)
+
+ factories = s._implied.get((interface, name))
+ if factories is not None:
+ for factory in factories:
+ ob = factory(ob)
+ return ob
+
+ return default
+
+ def queryMultiAdapter(self, objects, interface, name):
+ """
+
+ >>> import zope.interface
+ >>> class IF0(zope.interface.Interface):
+ ... pass
+ >>> class IF1(IF0):
+ ... pass
+
+ >>> class IR0(zope.interface.Interface):
+ ... pass
+ >>> class IR1(IR0):
+ ... pass
+
+ >>> class F1:
+ ... zope.interface.implements(IF1)
+ >>> c = F1()
+
+ >>> class R1:
+ ... zope.interface.implements(IR1)
+ >>> r = R1()
+
+ >>> registry = SurrogateRegistry()
+
+ If we ask for a named adapter, we won't get a result unless there
+ is a named adapter, even if the object implements the interface:
+
+ >>> registry.queryMultiAdapter((c, r), IF0, 'bob')
+
+ >>> class IB0(zope.interface.Interface):
+ ... pass
+ >>> class IB1(IB0):
+ ... pass
+
+
+ >>> def f1(ob):
+ ... return 1
+
+ >>> registry.provideAdapter(IF0, IB1, f1, name='bob', with=[IR0])
+ >>> registry.queryMultiAdapter((c, r), IB0, 'bob')
+ 1
+ >>> registry.queryMultiAdapter((c, r), IB0, 'bruce')
+
+
+ >>> def f2(ob):
+ ... return 2
+
+ >>> registry.provideAdapter(IF1, IB1, f2, name='bob', with=[IR1])
+ >>> registry.queryMultiAdapter((c, r), IB0, 'bob')
+ 2
+
+ >>> def f3(ob):
+ ... return 3
+
+ """
+ surrogates = self._surrogates
+
+ interface = surrogates.get(interface)
+ if interface is None:
+ # If there is no surrogate for the interface, then we can't
+ # have an adapter for it.
+ return None
+
+ ob = objects[0]
+ order = len(objects)
+ objects = objects[1:]
+ for declaration in providedBy(ob):
+ s = surrogates.get(declaration)
+ if s is None:
+ s = self.get(declaration)
+
+ adapters = s._implied.get((interface, name, order))
+ if adapters:
+ matched = None
+ matched_factories = None
+ for interfaces, factories in adapters.iteritems():
+ for iface, ob in zip(interfaces, objects):
+ if not iface.isImplementedBy(ob):
+ break # This one is no good
+ else:
+ # we didn't break, so we have a match
+ if matched is None:
+ matched = interfaces
+ matched_factories = factories
+ else:
+ for iface, m in zip(interfaces, matched):
+ if iface.extends(m):
+ # new is better than old
+ matched = interfaces
+ matched_factories = factories
+ break
+ elif m.extends(iface):
+ # old is better than new
+ break
+
+ for factory in matched_factories:
+ ob = factory(ob)
+ return ob
+
+ return None
+
+
+class AdapterRegistrationStack(RegistrationStack):
+
+ def activate(self, registration):
+ was_active = self.active()
+ RegistrationStack.activate(self, registration)
+ now_active = self.active()
+ if ((was_active and not now_active)
+ or (now_active and not was_active)):
+ self.__parent__.change()
+
+ def deactivate(self, registration):
+ was_active = self.active()
+ RegistrationStack.deactivate(self, registration)
+ now_active = self.active()
+ if ((was_active and not now_active)
+ or (now_active and not was_active)):
+ self.__parent__.change()
+
+
+
More information about the Zope3-Checkins
mailing list