[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