[Zope3-checkins]
SVN: Zope3/branches/jim-adapter-alt1/src/zope/interface/adapter.py
Try simpler alternate registry layout.
Jim Fulton
jim at zope.com
Sun Jan 29 14:08:39 EST 2006
Log message for revision 41484:
Try simpler alternate registry layout.
Changed:
U Zope3/branches/jim-adapter-alt1/src/zope/interface/adapter.py
-=-
Modified: Zope3/branches/jim-adapter-alt1/src/zope/interface/adapter.py
===================================================================
--- Zope3/branches/jim-adapter-alt1/src/zope/interface/adapter.py 2006-01-29 19:07:32 UTC (rev 41483)
+++ Zope3/branches/jim-adapter-alt1/src/zope/interface/adapter.py 2006-01-29 19:08:39 UTC (rev 41484)
@@ -18,16 +18,30 @@
from zope.interface import providedBy, Interface, ro
+class readproperty(object):
+
+ def __init__(self, func):
+ self.func = func
+
+ def __get__(self, inst, class_):
+ if inst is None:
+ return self
+
+ func = self.func
+ return func(inst)
+
+
_marker = object
class AdapterRegistry(object):
def __init__(self, bases=()):
- self._unnamed_adapters = [] # [{ provided -> components }]
- self._named_adapters = {} # { name -> [{ provided -> components }] }
- self._unnamed_subscriptions = [] # ditto
- self._named_subscriptions = {} # ditto
+ self._adapters = []
+ self._provided = {}
+ self._unnamed_subscriptions = []
+ self._named_subscriptions = {}
self.__bases__ = bases
+ @apply
def __bases__():
def get(self):
return self.__dict__['__bases__']
@@ -36,59 +50,99 @@
self.ro = ro.ro(self)
return property(get, set)
- __bases__ = __bases__()
-
+
+
+ @readproperty
+ def _v_extendors(self):
+ _v_extendors = {}
+ for provided in self._provided:
+ for i in provided.__iro__:
+ extendors = _v_extendors.get(i, ())
+ if provided not in extendors:
+ _v_extendors[i] = (
+ [e for e in extendors if provided.isOrExtends(e)]
+ +
+ [provided]
+ +
+ [e for e in extendors if not provided.isOrExtends(e)]
+ )
+ self._v_extendors = _v_extendors
+ return self._v_extendors
+
def register(self, required, provided, name, value):
if value is None:
self.unregister(required, provided, name, value)
return
- if name:
- name = _normalize_name(name)
- byorder = self._named_adapters.get(name)
- if byorder is None:
- self._named_adapters[name] = byorder = []
- else:
- byorder = self._unnamed_adapters
-
+ required = tuple(map(_convert_None_to_Interface, required))
+ name = _normalize_name(name)
order = len(required)
+ byorder = self._adapters
while len(byorder) <= order:
- byorder.append(Adapters())
-
+ byorder.append({})
components = byorder[order]
- components.register(required, provided, value)
+ key = required + (provided,)
+ for k in key:
+ d = components.get(k)
+ if d is None:
+ d = {}
+ components[k] = d
+ components = d
+
+ if components.get(name) == value:
+ return
+
+ components[name] = value
+
+ n = self._provided.get(provided, 0) + 1
+ self._provided[provided] = n
+ if n == 1 and '_v_extendors' in self.__dict__:
+ del self.__dict__['_v_extendors']
+
def unregister(self, required, provided, name, value=None):
- if name:
- name = _normalize_name(name)
- byorder = self._named_adapters.get(name)
- if byorder is None:
- return
- else:
- byorder = self._unnamed_adapters
-
+ required = tuple(map(_convert_None_to_Interface, required))
order = len(required)
+ byorder = self._adapters
if order >= len(byorder):
- return
+ return False
components = byorder[order]
- components.unregister(required, provided, value)
+ key = required + (provided,)
+
+ for k in key:
+ d = components.get(k)
+ if d is None:
+ return
+ components = d
+ old = components.get(name)
+ if old is None:
+ return
+ if value is not None and old != value:
+ return
+ del components[name]
+ n = self._provided[provided] - 1
+ if n == 0:
+ del self._provided[provided]
+ if '_v_extendors' in self.__dict__:
+ del self.__dict__['_v_extendors']
+
+ return
+
def lookup(self, required, provided, name=u'', default=None):
+ order = len(required)
for self in self.ro:
- if name:
- byorder = self._named_adapters.get(name)
- if byorder is None:
- continue
- else:
- byorder = self._unnamed_adapters
-
- order = len(required)
+ byorder = self._adapters
if order >= len(byorder):
continue
+ extendors = self._v_extendors.get(provided)
+ if not extendors:
+ continue
+
components = byorder[order]
- result = lookup(components.components, required, provided)
+ result = _lookup(components, required, extendors, name, 0, order)
if result is not None:
return result
@@ -106,24 +160,8 @@
return result
def lookup1(self, required, provided, name=u'', default=None):
- for self in self.ro:
- if name:
- byorder = self._named_adapters.get(name)
- if byorder is None:
- continue
- else:
- byorder = self._unnamed_adapters
+ return self.lookup((required, ), provided, name, default)
- if 1 >= len(byorder):
- continue
-
- components = byorder[1]
- result = lookup1(components.components, required, provided)
- if result is not None:
- return result
-
- return default
-
def queryAdapter(self, object, provided, name=u'', default=None):
return self.adapter_hook(provided, object, name, default)
@@ -137,20 +175,19 @@
return default
def lookupAll(self, required, provided):
- for self in self.ro:
- order = len(required)
- if order < len(self._unnamed_adapters):
- result = lookup(self._unnamed_adapters[order].components,
- required, provided)
- if result is not None:
- yield (u'', result)
+ order = len(required)
+ result = {}
+ for self in reversed(self.ro):
+ byorder = self._adapters
+ if order >= len(byorder):
+ continue
+ extendors = self._v_extendors.get(provided)
+ if not extendors:
+ continue
+ components = byorder[order]
+ _lookupAll(components, required, extendors, result, 0, order)
- for name, byorder in self._named_adapters.iteritems():
- if order < len(byorder):
- result = lookup(byorder[order].components,
- required, provided)
- if result is not None:
- yield (name, result)
+ return result.iteritems()
def names(self, required, provided):
return [c[0] for c in self.lookupAll(required, provided)]
@@ -247,8 +284,12 @@
selfImplied = {}
return XXXTwistedFakeOut
+def _convert_None_to_Interface(x):
+ if x is None:
+ return Interface
+ else:
+ return x
-
def _normalize_name(name):
if isinstance(name, basestring):
return unicode(name)
@@ -276,6 +317,7 @@
registered = self.provided.get(provided)
if registered is None:
self.provided[provided] = registered = provided.__iro__, []
+ # XXX where is changed? Where is unsubscribe on unregister?
provided.subscribe(self)
registered[1].append((required, value))
@@ -371,41 +413,42 @@
def _add(self, components, provided, value):
return components + ((value, provided), )
-def _lookup(components, specs, i, l):
+def _lookup(components, specs, provided, name, i, l):
if i < l:
for spec in specs[i].__sro__:
comps = components.get(spec)
- if comps is not None:
- r = _lookup(comps, specs, i+1, l)
+ if comps:
+ r = _lookup(comps, specs, provided, name, i+1, l)
if r is not None:
return r
- return None
-
- return components
+ else:
+ for iface in provided:
+ comps = components.get(iface)
+ if comps:
+ r = comps.get(name)
+ if r is not None:
+ return r
+
+ return None
-def lookup(components, required, provided):
- components = components.get(provided)
- if components:
+def _lookupAll(components, specs, provided, result, i, l):
+ if i < l:
+ for spec in reversed(specs[i].__sro__):
+ comps = components.get(spec)
+ if comps:
+ r = _lookupAll(comps, specs, provided, result, i+1, l)
+ if r is not None:
+ return r
+ else:
+ for iface in reversed(provided):
+ comps = components.get(iface)
+ if comps:
+ result.update(comps)
- if required:
- components = _lookup(components, required, 0, len(required))
- if not components:
- return None
- return components[0][0]
- return None
-def lookup1(components, required, provided):
- components = components.get(provided)
- if components:
- for s in required.__sro__:
- comps = components.get(s)
- if comps:
- return comps[0][0]
- return None
-
def _subscribers(components, specs, i, l, objects, result):
if i < l:
sro = list(specs[i].__sro__)
More information about the Zope3-Checkins
mailing list