[Zodb-checkins] CVS: Zope3/src/zope/interface - surrogate.py:1.1.2.10

Jim Fulton cvs-admin at zope.org
Wed Nov 12 15:08:19 EST 2003


Update of /cvs-repository/Zope3/src/zope/interface
In directory cvs.zope.org:/tmp/cvs-serv25410/src/zope/interface

Modified Files:
      Tag: adaptergeddon-branch
	surrogate.py 
Log Message:
Changed the strategy for tracking changes. Now, when we register new
adapters, we mark affected surrogates as dirty.  They will recompute
their implied information only when it is needed.


=== Zope3/src/zope/interface/surrogate.py 1.1.2.9 => 1.1.2.10 ===
--- Zope3/src/zope/interface/surrogate.py:1.1.2.9	Tue Nov 11 10:52:33 2003
+++ Zope3/src/zope/interface/surrogate.py	Wed Nov 12 15:08:15 2003
@@ -11,7 +11,7 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Surrogate-interface registry implementation
+"""Surrogate-specification registry implementation
 
 $Id$
 """
@@ -40,13 +40,13 @@
 
 # where:
 
-#   with is a tuple of surrogates that is non-empty only in the case
+#   with is a tuple of specs that is non-empty only in the case
 #   of multi-adapters.  
 
 #   name is a unicode adapter name.  Unnamed adapters have an empty
 #   name.
 
-#   specification is the surrogate of the interface being adapted to.
+#   specification is the interface being adapted to.
 
 #   factories is normally a tuple of factories, but can be anything.
 #   (See the "raw" option to the query-adapter calls.)
@@ -75,6 +75,16 @@
 
 Default = InterfaceClass("Default", (), {})
 
+class ReadProperty(object):
+
+    def __init__(self, func):
+        self.func = func
+
+    def __get__(self, inst, class_):
+        if inst is None:
+            return self
+        return self.func(inst)
+
 class Surrogate(object):
     """Specification surrogate
 
@@ -82,55 +92,29 @@
     behalf of a specification.
     """
 
-    def __init__(self, interface, registry):
-        self._adapters = {}
-        self._implied = {}
-        self._selfimplied = {}
-        self._multimplied = {}
-        
-        self._interface = interface.weakref()
-        interface.subscribe(self)
-
-        self._registry = registry
+    def __init__(self, spec, registry):
+        self.spec = spec.weakref()
+        spec.subscribe(self)
+        self.adapters = {}
         self.dependents = weakref.WeakKeyDictionary()
-        self.__bases__ = [registry.get(base) for base in interface.__bases__]
+
+        self.__bases__ = [registry.get(base) for base in spec.__bases__]
         for base in self.__bases__:
             base.subscribe(self)
 
-    def subscribe(self, dependent):
-        self.dependents[dependent] = 1
-
-    def unsubscribe(self, dependent):
-        del self.dependents[dependent]
-
-    def extends(self, other, strict=True):
-        return self._interface().extends(other._interface(), strict)
-
-    def isImplementedBy(self, ob):
-        return self._interface().isImplementedBy(ob)
-
-    def _adaptTo(self, specification, factories, name='', with=()):
-        if factories is None:
-            try:
-                del self._adapters[with, name, specification]
-            except KeyError:
-                pass
-        else:
-            self._adapters[with, name, specification] = factories
-
-        adapterImplied(self._adapters,
-                       self._selfimplied,
-                       self._multimplied)
-        self.changed()
-
-    def changed(self):
-        self._computeImplied()
+    def dirty(self):
+        if 'get' in self.__dict__:
+            # Not already dirty
+            del self.selfImplied
+            del self.multImplied
+            del self.get
         for dependent in self.dependents.keys():
-            dependent.changed()
+            dependent.dirty()
+
+    def clean(self):
+        self.selfImplied, self.multImplied = adapterImplied(self.adapters)
 
-    def _computeImplied(self):
-        implied = self._implied
-        implied.clear()
+        implied = {}
 
         ancestors = ro(self)
 
@@ -138,17 +122,60 @@
         # override less-specific data.
         ancestors.reverse()
         for ancestor in ancestors:
-            implied.update(ancestor._selfimplied)
-            for k, ancestor_adapters in ancestor._multimplied.iteritems():
+            implied.update(ancestor.selfImplied)
+            for k, ancestor_adapters in ancestor.multImplied.iteritems():
                 implied_adapters = implied.get(k)
                 if implied_adapters:
                     implied_adapters.update(ancestor_adapters)
                 else:
                     implied[k] = ancestor_adapters.copy()
-            
+
+        self.get = implied.get
+
+    def get(self, key):
+        """Get an implied value
+
+        This is only called when the surrogate is dirty
+        """
+        self.clean()
+        return self.__dict__['get'](key)
+
+    def selfImplied(self):
+        """Return selfImplied when dirty
+        """
+        self.clean()
+        return self.__dict__['selfImplied']
+    selfImplied = ReadProperty(selfImplied)
+
+    def multiImplied(self):
+        """Return _multiImplied when dirty
+        """
+        self.clean()
+        return self.__dict__['multiImplied']
+    multiImplied = ReadProperty(multiImplied)
+
+    def subscribe(self, dependent):
+        self.dependents[dependent] = 1
+
+    def unsubscribe(self, dependent):
+        del self.dependents[dependent]
+
+    def _adaptTo(self, specification, factories, name='', with=()):
+        if factories is None:
+            try:
+                del self.adapters[with, name, specification]
+            except KeyError:
+                pass
+        else:
+            self.adapters[with, name, specification] = factories
+
+        self.dirty()
+
+    def changed(self, which=None):
+        self.dirty()
 
     def __repr__(self):
-        return '%s(%s)' % (self.__class__.__name__, self._interface())
+        return '<%s(%s)>' % (self.__class__.__name__, self.spec())
 
 class SurrogateRegistry(object):
     """Surrogate registry
@@ -181,14 +208,12 @@
         surrogate = self._surrogates.get(ref)
         if surrogate is None:
             surrogate = self._surrogateClass(declaration, self)
-            surrogate._computeImplied()
             self._surrogates[ref] = surrogate
 
         return surrogate
 
 
-    def provideAdapter(self, required, provided, factories,
-                       name=u'', with=()):
+    def provideAdapter(self, required, provided, factories, name=u'', with=()):
         """Register an adapter
 
         Note that the given name must be convertable to unicode.
@@ -262,9 +287,9 @@
         declaration = providedBy(ob)
         s = self.get(declaration)
 
-        factories = s._implied.get(interface)
+        factories = s.get(interface)
         if factories is None:
-            factories = self._default._implied.get(interface)
+            factories = self._default.get(interface)
 
         if factories is not None:
             if raw:
@@ -329,9 +354,9 @@
 
         declaration = providedBy(ob)
         s = self.get(declaration)
-        factories = s._implied.get((interface, name))
+        factories = s.get((interface, name))
         if factories is None:
-            factories = self._default._implied.get((interface, name))
+            factories = self._default.get((interface, name))
         if factories is not None:
             if raw:
                 return factories
@@ -413,9 +438,9 @@
         declaration = providedBy(ob)
         s = self.get(declaration)
 
-        adapters = s._implied.get((interface, name, order))
+        adapters = s.get((interface, name, order))
         if adapters is None:
-            adapters = self._default._implied.get((interface, name, order))
+            adapters = self._default.get((interface, name, order))
 
         if adapters:
             matched = None
@@ -596,10 +621,10 @@
                 if ancestor in seen:
                     continue
                 seen[ancestor] = 1
-                adapters = ancestor._adapters
+                adapters = ancestor.adapters
                 if adapters:
                     items = adapters.iteritems()
-                    ancestor = ancestor._interface()
+                    ancestor = ancestor.spec()
                     if ancestor is Default:
                         ancestor = None
                     for (with, aname, target), factories in items:
@@ -620,9 +645,9 @@
 
 
 
-def adapterImplied(adapters, implied, multi):
-    implied.clear()
-    multi.clear()
+def adapterImplied(adapters):
+    implied = {}
+    multi = {}
     registered = {}
 
     # Add adapters and interfaces directly implied by same:
@@ -634,6 +659,8 @@
                                factories)
         else:
             _add_adapter(target, target, implied, registered, factories)
+
+    return implied, multi
 
 def _add_adapter(target, provided, implied, registered, factories):
     if (target not in implied




More information about the Zodb-checkins mailing list