[Zope3-checkins] SVN: Zope3/branches/jim-adapter-redesign/ First
cut at adapter-registry refactoring. The refactoring makes
Jim Fulton
jim at zope.com
Thu Sep 8 06:17:23 EDT 2005
Log message for revision 38384:
First cut at adapter-registry refactoring. The refactoring makes
adapter lookup work more like method lookup. This provides:
- a much simpler algorithm,
- a basis for super-like adapter lookup, and
- a fix for a bug in multi-adapter lookup.
These changes also remove the distinction between objects with no
interface declarations and objects that declare that they provide
Interface.
Unfortunately, these version is *much* too slow. I'm checking this
version in to save it before trying some variations.
Changed:
U Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/component.py
U Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/component.txt
U Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/ifacemodule/browser.txt
U Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/presentation.txt
U Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/tests.py
U Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilities.py
U Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilities.txt
U Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilitymodule/browser.txt
U Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/zcmlmodule/browser.txt
U Zope3/branches/jim-adapter-redesign/src/zope/app/authentication/browser/principalfolder.txt
U Zope3/branches/jim-adapter-redesign/src/zope/app/component/adapter.py
U Zope3/branches/jim-adapter-redesign/src/zope/app/component/interfaces/__init__.py
U Zope3/branches/jim-adapter-redesign/src/zope/app/component/site.py
U Zope3/branches/jim-adapter-redesign/src/zope/app/component/tests/test_adapter.py
U Zope3/branches/jim-adapter-redesign/src/zope/app/component/tests/test_directives.py
U Zope3/branches/jim-adapter-redesign/src/zope/app/debugskin/configure.zcml
U Zope3/branches/jim-adapter-redesign/src/zope/app/form/browser/configure.zcml
U Zope3/branches/jim-adapter-redesign/src/zope/app/locking/tests.py
U Zope3/branches/jim-adapter-redesign/src/zope/app/module/README.txt
U Zope3/branches/jim-adapter-redesign/src/zope/app/pagetemplate/configure.zcml
U Zope3/branches/jim-adapter-redesign/src/zope/app/publication/traversers.py
U Zope3/branches/jim-adapter-redesign/src/zope/app/traversing/browser/configure.zcml
U Zope3/branches/jim-adapter-redesign/src/zope/component/site.py
U Zope3/branches/jim-adapter-redesign/src/zope/interface/_zope_interface_coptimizations.c
U Zope3/branches/jim-adapter-redesign/src/zope/interface/adapter.py
U Zope3/branches/jim-adapter-redesign/src/zope/interface/adapter.txt
U Zope3/branches/jim-adapter-redesign/src/zope/interface/declarations.py
U Zope3/branches/jim-adapter-redesign/src/zope/interface/interface.py
U Zope3/branches/jim-adapter-redesign/src/zope/interface/interfaces.py
U Zope3/branches/jim-adapter-redesign/src/zope/interface/tests/test_adapter.py
U Zope3/branches/jim-adapter-redesign/src/zope/security/checker.py
U Zope3/branches/jim-adapter-redesign/z3.py
-=-
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/component.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/component.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/component.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -59,14 +59,16 @@
gsm = zapi.getGlobalSiteManager()
for reg in gsm.registrations():
# Only get adapters
- if not isinstance(reg, (AdapterRegistration, SubscriptionRegistration)):
+ if not isinstance(reg,
+ (AdapterRegistration, SubscriptionRegistration)):
continue
# Ignore adapters that have no required interfaces
if len(reg.required) == 0:
continue
# Ignore views
- if not withViews and reg.required[-1] and \
- reg.required[-1].isOrExtends(IRequest):
+ if (not withViews and reg.required[-1]
+ and reg.required[-1].isOrExtends(IRequest)
+ ):
continue
# Only get adapters for which this interface is provided
if reg.provided is None or not reg.provided.isOrExtends(iface):
@@ -172,6 +174,11 @@
url = None
else:
url = path.replace('.', '/')
+
+ if ' ' in url:
+ # We got a generated class. It can't have a url
+ url = None
+
if isinstance(reg.doc, (str, unicode)):
doc = reg.doc
zcml = None
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/component.txt
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/component.txt 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/component.txt 2005-09-08 10:17:23 UTC (rev 38384)
@@ -241,8 +241,8 @@
>>> pprint(component.getAdapterInfoDictionary(reg))
{'doc': 'doc info',
- 'factory': '__builtin__.MyResult',
- 'factory_url': '__builtin__/MyResult',
+ 'factory': '__builtin__.MyResult ?',
+ 'factory_url': None,
'name': 'FooToResult',
'provided': {'module': '__builtin__', 'name': 'IResult'},
'required': [{'module': '__builtin__', 'name': 'IFoo'},
@@ -258,8 +258,8 @@
>>> pprint(component.getAdapterInfoDictionary(reg))
{'doc': 'doc info',
- 'factory': '__builtin__.MyResult',
- 'factory_url': '__builtin__/MyResult',
+ 'factory': '__builtin__.MyResult ?',
+ 'factory_url': None,
'name': u'<subscription>',
'provided': None,
'required': [{'module': '__builtin__', 'name': 'IFoo'},
@@ -281,7 +281,7 @@
{'description': u'<p>My Foo Bar</p>\n',
'name': 'MyFooBar',
'title': 'MyFooBar',
- 'url': '__builtin__/MyFooBar'}
+ 'url': '__builtin__/MyFooBar ?'}
`getUtilityInfoDictionary(name, factory)`
@@ -296,6 +296,6 @@
>>> pprint(component.getUtilityInfoDictionary(
... component.getUtilities(IFooBar).next()))
{'name': u'<i>no name</i>',
- 'path': '__builtin__.MyFooBar',
- 'url': '__builtin__/MyFooBar',
+ 'path': '__builtin__.MyFooBar ?',
+ 'url': '__builtin__/MyFooBar ?',
'url_name': '__noname__'}
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/ifacemodule/browser.txt
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/ifacemodule/browser.txt 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/ifacemodule/browser.txt 2005-09-08 10:17:23 UTC (rev 38384)
@@ -218,9 +218,12 @@
>>> pprint(details.getTypes())
[{'name': 'IMyType',
- 'path': '__builtin__.IMyType'}]
+ 'path': '__builtin__.IMyType ?'}]
+Note that a space and question mark is shown after the object name to
+indicate that the object name wasn't found in the module.
+
`getAttributes()`
-----------------
@@ -300,8 +303,96 @@
Get adapters where this interface is required.
>>> pprint(details.getGenericRequiredAdapters())
- []
+ [{'doc': '',
+ 'factory': 'append',
+ 'factory_url': 'append',
+ 'name': u'<subscription>',
+ 'provided': None,
+ 'required': [{'module': 'zope.interface',
+ 'name': 'Interface'}],
+ 'zcml': None},
+ {'doc': '',
+ 'factory': 'zope.app.traversing.adapters.Traverser',
+ 'factory_url': 'zope/app/traversing/adapters/Traverser',
+ 'name': '',
+ 'provided': {'module': 'zope.app.traversing.interfaces',
+ 'name': 'ITraverser'},
+ 'required': [{'module': 'zope.interface',
+ 'name': 'Interface'}],
+ 'zcml': None},
+ {'doc': '',
+ 'factory': 'zope.app.traversing.adapters.DefaultTraversable',
+ 'factory_url': 'zope/app/traversing/adapters/DefaultTraversable',
+ 'name': '',
+ 'provided': {'module': 'zope.app.traversing.interfaces',
+ 'name': 'ITraversable'},
+ 'required': [{'module': 'zope.interface',
+ 'name': 'Interface'}],
+ 'zcml': None},
+ {'doc': '',
+ 'factory': 'zope.app.location.traversing.LocationPhysicallyLocatable',
+ 'factory_url': 'zope/app/location/traversing/LocationPhysicallyLocatable',
+ 'name': '',
+ 'provided': {'module': 'zope.app.traversing.interfaces',
+ 'name': 'IPhysicallyLocatable'},
+ 'required': [{'module': 'zope.interface',
+ 'name': 'Interface'}],
+ 'zcml': None},
+ {'doc': '',
+ 'factory': 'zope.app.traversing.namespace.etc',
+ 'factory_url': 'zope/app/traversing/namespace/etc',
+ 'name': 'etc',
+ 'provided': {'module': 'zope.app.traversing.interfaces',
+ 'name': 'ITraversable'},
+ 'required': [{'module': 'zope.interface',
+ 'name': 'Interface'}],
+ 'zcml': None},
+ {'doc': '',
+ 'factory': 'zope.app.traversing.namespace.etc',
+ 'factory_url': 'zope/app/traversing/namespace/etc',
+ 'name': 'etc',
+ 'provided': {'module': 'zope.app.traversing.interfaces',
+ 'name': 'ITraversable'},
+ 'required': [{'module': 'zope.interface',
+ 'name': 'Interface'},
+ {'module': 'zope.interface',
+ 'name': 'Interface'}],
+ 'zcml': None},
+ {'doc': '',
+ 'factory': 'zope.app.traversing.namespace.etc',
+ 'factory_url': 'zope/app/traversing/namespace/etc',
+ 'name': 'etc',
+ 'provided': {'module': 'zope.app.traversing.interfaces',
+ 'name': 'ITraversable'},
+ 'required': [{'module': 'zope.interface',
+ 'name': 'Interface'},
+ {'module': 'zope.interface',
+ 'name': 'Interface'}],
+ 'zcml': None},
+ {'doc': '',
+ 'factory': 'zope.app.traversing.namespace.etc',
+ 'factory_url': 'zope/app/traversing/namespace/etc',
+ 'name': 'etc',
+ 'provided': {'module': 'zope.app.traversing.interfaces',
+ 'name': 'ITraversable'},
+ 'required': [{'module': 'zope.interface',
+ 'name': 'Interface'},
+ {'module': 'zope.interface',
+ 'name': 'Interface'}],
+ 'zcml': None},
+ {'doc': '',
+ 'factory': 'zope.app.traversing.namespace.etc',
+ 'factory_url': 'zope/app/traversing/namespace/etc',
+ 'name': 'etc',
+ 'provided': {'module': 'zope.app.traversing.interfaces',
+ 'name': 'ITraversable'},
+ 'required': [{'module': 'zope.interface',
+ 'name': 'Interface'},
+ {'module': 'zope.interface',
+ 'name': 'Interface'}],
+ 'zcml': None}]
+Note that these include interfaces for which *any* interface is required.
`getProvidedAdapters()`
-----------------------
@@ -310,8 +401,8 @@
>>> pprint(details.getProvidedAdapters())
[{'doc': '',
- 'factory': '__builtin__.Foo',
- 'factory_url': '__builtin__/Foo',
+ 'factory': '__builtin__.Foo ?',
+ 'factory_url': None,
'name': '',
'provided': {'module': '__builtin__',
'name': 'IFoo'},
@@ -319,6 +410,8 @@
'name': 'IBar'}],
'zcml': None}]
+Note that the factory URL is None, because the factory doesn't
+actually exist in __builtin__.
`getClasses()`
---------------
@@ -339,7 +432,7 @@
[{'description': u'',
'name': 'FooFactory',
'title': 'Foo Factory',
- 'url': '__builtin__/Foo'}]
+ 'url': '__builtin__/Foo ?'}]
`getUtilities()`
----------------
@@ -348,6 +441,6 @@
>>> pprint(details.getUtilities())
[{'name': 'The Foo',
- 'path': '__builtin__.Foo',
- 'url': '__builtin__/Foo',
- 'url_name': 'The Foo'}]
\ No newline at end of file
+ 'path': '__builtin__.Foo ?',
+ 'url': '__builtin__/Foo ?',
+ 'url_name': 'The Foo'}]
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/presentation.txt
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/presentation.txt 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/presentation.txt 2005-09-08 10:17:23 UTC (rev 38384)
@@ -62,22 +62,22 @@
>>> info = presentation.getViewFactoryData(Factory())
>>> pprint(info)
- {'path': '__builtin__.Factory',
+ {'path': '__builtin__.Factory ?',
'referencable': True,
'resource': None,
'template': None,
- 'url': '__builtin__/Factory'}
+ 'url': '__builtin__/Factory ?'}
One of the more common cases, however, is that the factory is a class or
type. In this case we can just retrieve the reference directly:
>>> info = presentation.getViewFactoryData(Factory)
>>> pprint(info)
- {'path': '__builtin__.Factory',
+ {'path': '__builtin__.Factory ?',
'referencable': True,
'resource': None,
'template': None,
- 'url': '__builtin__/Factory'}
+ 'url': '__builtin__/Factory ?'}
When factories are created by the directive, they can also be functions. In
those cases we just simply return the function path:
@@ -90,11 +90,11 @@
>>> info = presentation.getViewFactoryData(factory)
>>> pprint(info)
- {'path': '__builtin__.factory',
+ {'path': '__builtin__.factory ?',
'referencable': True,
'resource': None,
'template': None,
- 'url': '__builtin__/factory'}
+ 'url': '__builtin__/factory ?'}
However, the function is rather unhelpful, since it will be the same for all
views that use that code path. For this reason the function keeps track of the
@@ -104,11 +104,11 @@
>>> info = presentation.getViewFactoryData(factory)
>>> pprint(info)
- {'path': '__builtin__.Factory',
+ {'path': '__builtin__.Factory ?',
'referencable': True,
'resource': None,
'template': None,
- 'url': '__builtin__/Factory'}
+ 'url': '__builtin__/Factory ?'}
`getPresentationType(iface)`
@@ -303,11 +303,11 @@
>>> pprint(presentation.getViewInfoDictionary(reg))
{'doc': 'reg info',
- 'factory': {'path': '__builtin__.Factory',
+ 'factory': {'path': '__builtin__.Factory ?',
'referencable': True,
'resource': None,
'template': None,
- 'url': '__builtin__/Factory'},
+ 'url': '__builtin__/Factory ?'},
'layer': None,
'name': 'view.html',
'provided': {'module': 'zope.interface',
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/tests.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/tests.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/tests.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -18,6 +18,8 @@
from pprint import PrettyPrinter
import unittest
+import zope.component.testing
+
from zope.component.interfaces import IFactory
from zope.interface import implements
from zope.testing import doctest, doctestunit
@@ -32,7 +34,7 @@
def setUp(test):
- placelesssetup.setUp()
+ zope.component.testing.setUp()
# Register Renderer Components
ztapi.provideUtility(IFactory, ReStructuredTextSourceFactory,
'zope.source.rest')
@@ -80,8 +82,8 @@
globs={'pprint': doctestunit.pprint},
optionflags=doctest.NORMALIZE_WHITESPACE),
doctest.DocFileSuite('presentation.txt',
- setUp=placelesssetup.setUp,
- tearDown=placelesssetup.tearDown,
+ setUp=zope.component.testing.setUp,
+ tearDown=zope.component.testing.tearDown,
globs={'pprint': doctestunit.pprint},
optionflags=doctest.NORMALIZE_WHITESPACE),
doctest.DocFileSuite('utilities.txt',
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilities.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilities.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilities.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -98,10 +98,17 @@
if hasattr(naked, "im_class"):
naked = naked.im_class
module = getattr(naked, '__module__', _marker)
- if module is _marker:
- return naked.__name__
+ name = naked.__name__
+ if module is _marker or module is None:
+ return name
else:
- return '%s.%s' %(module, naked.__name__)
+ m = sys.modules.get(module)
+ if m is None:
+ module += ' ?'
+ else:
+ if m.__dict__.get(name) is not naked:
+ name += ' ?'
+ return '%s.%s' %(module, name)
def _evalId(id):
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilities.txt
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilities.txt 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilities.txt 2005-09-08 10:17:23 UTC (rev 38384)
@@ -164,7 +164,7 @@
... pass
>>> utilities.getPythonPath(ISample)
- '__builtin__.ISample'
+ '__builtin__.ISample ?'
and for classes
@@ -173,7 +173,7 @@
... pass
>>> utilities.getPythonPath(Sample.sample)
- '__builtin__.Sample'
+ '__builtin__.Sample ?'
One can also pass functions
@@ -182,12 +182,12 @@
>>> # Result is a bit strange due to doctests
>>> utilities.getPythonPath(sample)
- 'None.sample'
+ 'sample'
and even methods. If a method is passed in, its class path is returned.
>>> utilities.getPythonPath(Sample.sample)
- '__builtin__.Sample'
+ '__builtin__.Sample ?'
Modules are another kind of objects that can return a python path:
@@ -471,7 +471,7 @@
returned:
>>> utilities.getInterfaceForAttribute('attr', (I1, I2))
- '__builtin__.I1'
+ '__builtin__.I1 ?'
If no match is found, ``None`` is returned.
@@ -571,4 +571,4 @@
often safer (if available):
>>> utilities.renderText('Hello!\n', module=apidoc)
- u'<p>Hello!</p>\n'
\ No newline at end of file
+ u'<p>Hello!</p>\n'
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilitymodule/browser.txt
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilitymodule/browser.txt 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/utilitymodule/browser.txt 2005-09-08 10:17:23 UTC (rev 38384)
@@ -123,7 +123,7 @@
>>> iface = details.getInterface()
>>> iface.getId()
- '__builtin__.IBlah'
+ '__builtin__.IBlah ?'
`getComponent()`
@@ -150,5 +150,5 @@
Now we can get the component information:
>>> pprint(details.getComponent())
- {'path': '__builtin__.Foo',
- 'url': '__builtin__/Foo'}
+ {'path': '__builtin__.Foo ?',
+ 'url': '__builtin__/Foo ?'}
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/zcmlmodule/browser.txt
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/zcmlmodule/browser.txt 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/apidoc/zcmlmodule/browser.txt 2005-09-08 10:17:23 UTC (rev 38384)
@@ -186,8 +186,8 @@
Return information about the directive handler object.
>>> pprint(details.getHandler())
- {'path': 'None.foo',
- 'url': 'None/foo'}
+ {'path': 'foo',
+ 'url': 'foo'}
`getSubdirectives()`
@@ -210,9 +210,9 @@
the result becomes more interesting:
>>> pprint(details.getSubdirectives()) #doctest:+ELLIPSIS
- [{'handler': {'path': 'None.handler',
- 'url': 'None/handler'},
+ [{'handler': {'path': 'handler',
+ 'url': 'handler'},
'info': 'info',
'name': 'foo',
'namespace': 'browser',
- 'schema': <zope.app.apidoc.ifacemodule.browser.InterfaceDetails ...>}]
\ No newline at end of file
+ 'schema': <zope.app.apidoc.ifacemodule.browser.InterfaceDetails ...>}]
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/authentication/browser/principalfolder.txt
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/authentication/browser/principalfolder.txt 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/authentication/browser/principalfolder.txt 2005-09-08 10:17:23 UTC (rev 38384)
@@ -246,7 +246,7 @@
...
... users
... -----------------------------6519411471194050603270010787--
- ... """)
+ ... """, handle_errors=False)
HTTP/1.1 200 Ok
...
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/component/adapter.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/component/adapter.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/component/adapter.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -25,36 +25,10 @@
from zope.app.component import interfaces
-class LocalSurrogate(zope.interface.adapter.Surrogate):
- """Local Surrogate
-
- Local surrogates are transient, rather than persistent. Their adapter
- data are stored in their registry objects.
- """
- def __init__(self, spec, registry):
- super(LocalSurrogate, self).__init__(spec, registry)
- self.registry = registry
- registry.baseFor(spec).subscribe(self)
-
- def clean(self):
- spec = self.spec()
- base = self.registry.baseFor(spec)
- ladapters = self.registry.adapters.get(spec)
- if ladapters:
- adapters = base.adapters.copy()
- adapters.update(ladapters)
- else:
- adapters = base.adapters
- self.adapters = adapters
- super(LocalSurrogate, self).clean()
-
-
class LocalAdapterRegistry(zope.interface.adapter.AdapterRegistry,
persistent.Persistent):
"""Local/persistent surrogate registry"""
zope.interface.implements(interfaces.ILocalAdapterRegistry)
-
- _surrogateClass = LocalSurrogate
# See interfaces.registration.ILocatedRegistry
next = None
@@ -82,24 +56,43 @@
"""See interfaces.registration.ILocatedRegistry"""
if base is not None:
self.base = base
- if self.next is not None:
- self.next.removeSub(self)
- if next is not None:
- next.addSub(self)
- self.next = next
- self.adaptersChanged()
+ if next != self.next:
+ if self.next is not None:
+ self.next.removeSub(self)
+ if next is not None:
+ next.addSub(self)
+ self.next = next
+
+ self.__bases__ = tuple([b for b in (next, self.base) if b is not None])
+
+ for sub in self.subs:
+ sub.setNext(self)
+
+
def register(self, registration):
"""See zope.app.component.interfaces.registration.IRegistry"""
self._registrations += (registration,)
- self.adaptersChanged()
+ zope.interface.adapter.AdapterRegistry.register(
+ self,
+ (registration.required, ) + registration.with,
+ registration.provided, registration.name,
+ registration.component,
+ )
+
def unregister(self, registration):
"""See zope.app.component.interfaces.registration.IRegistry"""
self._registrations = tuple([reg for reg in self._registrations
if reg is not registration])
- self.adaptersChanged()
+ zope.interface.adapter.AdapterRegistry.unregister(
+ self,
+ (registration.required, ) + registration.with,
+ registration.provided, registration.name,
+ registration.component,
+ )
+
def registered(self, registration):
"""See zope.app.component.interfaces.registration.IRegistry"""
return registration in self._registrations
@@ -108,76 +101,6 @@
"""See zope.app.component.interfaces.registration.IRegistry"""
return self._registrations
- def __getstate__(self):
- state = persistent.Persistent.__getstate__(self).copy()
-
- for name in ('_default', '_null', 'adapter_hook',
- 'lookup', 'lookup1', 'queryAdapter', 'get',
- 'subscriptions', 'queryMultiAdapter', 'subscribers'
- ):
- del state[name]
- return state
-
- def __setstate__(self, state):
- persistent.Persistent.__setstate__(self, state)
- zope.interface.adapter.AdapterRegistry.__init__(self)
-
- def baseFor(self, spec):
- """Used by LocalSurrogate"""
- return self.base.get(spec)
-
- def _updateAdaptersFromRegistration(self, radapters, registration):
- """Only to be used by _updateAdaptersFromLocalData, but can be
- overridden to implement custom behavior."""
- key = (False, registration.with, registration.name,
- registration.provided)
- radapters[key] = removeSecurityProxy(registration.component)
-
- def _updateAdaptersFromLocalData(self, adapters):
- """Update all adapter surrogates locally."""
- for registration in self._registrations:
- required = registration.required
- if required is None:
- required = zope.interface.adapter.Default
- radapters = adapters.get(required)
- if not radapters:
- radapters = {}
- adapters[required] = radapters
-
- # Needs more thought:
- # We have to remove the proxy because we're
- # storing the value amd we can't store proxies.
- # (Why can't we?) we need to think more about
- # why/if this is truly safe
- self._updateAdaptersFromRegistration(radapters, registration)
-
-
- def adaptersChanged(self):
- """See interfaces.registration.ILocalAdapterRegistry"""
- adapters = {}
- if self.next is not None:
- for required, radapters in self.next.adapters.iteritems():
- adapters[required] = radapters.copy()
-
- self._updateAdaptersFromLocalData(adapters)
-
- if adapters != self.adapters:
- self.adapters = adapters
-
- # Throw away all of our surrogates, rather than dirtrying
- # them individually
- super(LocalAdapterRegistry, self).__init__()
-
- for sub in self.subs:
- sub.adaptersChanged()
-
- def baseChanged(self):
- """See interfaces.registration.ILocalAdapterRegistry"""
- super(LocalAdapterRegistry, self).__init__()
- for sub in self.subs:
- sub.baseChanged()
-
-
class AdapterRegistration(registration.ComponentRegistration):
"""A simple implementation of the adapter registration interface."""
zope.interface.implements(interfaces.IAdapterRegistration)
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/component/interfaces/__init__.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/component/interfaces/__init__.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/component/interfaces/__init__.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -26,16 +26,8 @@
class ILocalAdapterRegistry(registration.IRegistry,
registration.ILocatedRegistry):
+ pass
- def adaptersChanged():
- """Update the adapter surrogates, since the registrations changed."""
-
- def baseChanged():
- """Someone changed the base registry
-
- This should only happen during testing
- """
-
class IPossibleSite(zope.interface.Interface):
"""An object that could be a site
"""
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/component/site.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/component/site.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/component/site.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -137,17 +137,48 @@
"""Custom local adapter registry for utilities, since utilities do not
just register themselves as null adapters, but also as subscribers."""
- def _updateAdaptersFromRegistration(self, radapters, registration):
- # Register as null adapter
- key = (False, registration.with, registration.name,
- registration.provided)
- radapters[key] = removeSecurityProxy(registration.component)
- # Register as subscriber
- key = (True, registration.with, '', registration.provided)
- radapters[key] = radapters.get(key, ()) + (
- removeSecurityProxy(registration.component), )
+ def register(self, registration):
+ """See zope.app.component.interfaces.registration.IRegistry"""
+ self._registrations += (registration,)
+ zope.interface.adapter.AdapterRegistry.register(
+ self,
+ (),
+ registration.provided, registration.name,
+ registration.component,
+ )
+
+ # XXX need test that this second part happens
+ zope.interface.adapter.AdapterRegistry.subscribe(
+ self,
+ (),
+ registration.provided,
+ registration.component,
+ )
+
+ def unregister(self, registration):
+ """See zope.app.component.interfaces.registration.IRegistry"""
+ self._registrations = tuple([reg for reg in self._registrations
+ if reg is not registration])
+
+ zope.interface.adapter.AdapterRegistry.unregister(
+ self,
+ (),
+ registration.provided, registration.name,
+ registration.component,
+ )
+
+
+ # XXX need test that this second part happens
+ zope.interface.adapter.AdapterRegistry.unsubscribe(
+ self,
+ (),
+ registration.provided,
+ registration.component,
+ )
+
+
class LocalSiteManager(BTreeContainer,
bbb.site.BBBSiteManager,
zope.component.site.SiteManager):
@@ -284,12 +315,6 @@
"""
zope.interface.implements(interfaces.IUtilityRegistration)
- ############################################################
- # Make the adapter code happy.
- required = zope.interface.adapter.Null
- with = ()
- ############################################################
-
def __init__(self, name, provided, component, permission=None):
super(UtilityRegistration, self).__init__(component, permission)
self.name = name
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/component/tests/test_adapter.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/component/tests/test_adapter.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/component/tests/test_adapter.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -115,13 +115,13 @@
>>> G.lookup([IF0], IB1)
- Note that it doesn't override the non-local adapter:
+ Note that it overrides the non-local adapter:
>>> L1.lookup([IF2], IB1)
- 'A11G'
+ 'A011'
>>> L2.lookup([IF2], IB1)
- 'A11G'
+ 'A011'
because it was more specific.
@@ -137,18 +137,13 @@
>>> L2.lookup([IF2], IB1)
'A112'
- But we still get the old one in L1
-
- >>> L1.lookup([IF2], IB1)
- 'A11G'
-
Note that we can ask for less specific interfaces and still get the adapter:
>>> L2.lookup([IF2], IB0)
'A112'
>>> L1.lookup([IF2], IB0)
- 'A11G'
+ 'A011'
We get the more specific adapter even if there is a less-specific
adapter to B0:
@@ -177,12 +172,12 @@
'A102'
>>> L2.lookup([IF2], IB1)
- 'A10G'
+ 'A011'
>>> ra102.status = interfaces.registration.InactiveStatus
>>> L2.lookup([IF2], IB0)
- 'A10G'
+ 'A011'
We can ask for all of the registrations :
@@ -247,15 +242,15 @@
>>> G.lookup([IF0], IB1, 'bob')
- Note that it doesn't override the non-local adapter:
+ Note that it overrides the non-local adapter:
>>> L1.lookup([IF2], IB1)
>>> L1.lookup([IF2], IB1, 'bob')
- 'A11G'
+ 'A011'
>>> L2.lookup([IF2], IB1)
>>> L2.lookup([IF2], IB1, 'bob')
- 'A11G'
+ 'A011'
because it was more specific.
@@ -273,21 +268,16 @@
>>> L2.lookup([IF2], IB1, 'bob')
'A112'
- But we still get thye old one in L1
+ Note that we can ask for less specific interfaces and still get
+ the adapter:
- >>> L1.lookup([IF2], IB1)
- >>> L1.lookup([IF2], IB1, 'bob')
- 'A11G'
-
- Note that we can ask for less specific interfaces and still get the adapter:
-
>>> L2.lookup([IF2], IB0)
>>> L2.lookup([IF2], IB0, 'bob')
'A112'
>>> L1.lookup([IF2], IB0)
>>> L1.lookup([IF2], IB0, 'bob')
- 'A11G'
+ 'A011'
We get the more specific adapter even if there is a less-specific
adapter to B0:
@@ -321,13 +311,13 @@
>>> L2.lookup([IF2], IB1)
>>> L2.lookup([IF2], IB1, 'bob')
- 'A10G'
+ 'A011'
>>> ra102.status = interfaces.registration.InactiveStatus
>>> L2.lookup([IF2], IB0)
>>> L2.lookup([IF2], IB0, 'bob')
- 'A10G'
+ 'A011'
"""
def test_multi_adapters():
@@ -375,13 +365,13 @@
>>> G.lookup((IF0, IR1), IB1, 'bob')
- Note that it doesn't override the non-local adapter:
+ Note that overridea the non-local adapter:
>>> L1.lookup([IF2, IR1], IB1, 'bob')
- 'A11G'
+ 'A011'
>>> L2.lookup((IF2, IR1), IB1, 'bob')
- 'A11G'
+ 'A011'
because it was more specific.
@@ -398,11 +388,6 @@
>>> L2.lookup((IF2, IR1), IB1, 'bob')
'A112'
- But we still get the old one in L1
-
- >>> L1.lookup((IF2, IR1), IB1, 'bob')
- 'A11G'
-
Note that we can ask for less specific interfaces and still get
the adapter:
@@ -410,7 +395,7 @@
'A112'
>>> L1.lookup((IF2, IR1), IB0, 'bob')
- 'A11G'
+ 'A011'
We get the more specific adapter even if there is a less-specific
adapter to B0:
@@ -439,13 +424,13 @@
'A102'
>>> L2.lookup((IF2, IR1), IB1, 'bob')
- 'A10G'
+ 'A011'
>>> ra102.status = interfaces.registration.InactiveStatus
>>> L2.lookup([IF2], IB0)
>>> L2.lookup((IF2, IR1), IB0, 'bob')
- 'A10G'
+ 'A011'
"""
def test_persistence():
@@ -490,15 +475,15 @@
>>> G.lookup([IF0], IB1)
- Note that it doesn't override the non-local adapter:
+ Note that it overrides the non-local adapter:
>>> L1.lookup([IF2], IB1)
>>> L1.lookup([IF2], IB1, 'bob')
- 'A11G'
+ 'A011'
>>> L2.lookup([IF2], IB1)
>>> L2.lookup([IF2], IB1, 'bob')
- 'A11G'
+ 'A011'
because it was more specific.
@@ -516,12 +501,6 @@
>>> L2.lookup([IF2], IB1, 'bob')
'A112'
- But we still get the old one in L1
-
- >>> L1.lookup([IF2], IB1)
- >>> L1.lookup([IF2], IB1, 'bob')
- 'A11G'
-
Note that we can ask for less specific interfaces and still get
the adapter:
@@ -531,7 +510,7 @@
>>> L1.lookup([IF2], IB0)
>>> L1.lookup([IF2], IB0, 'bob')
- 'A11G'
+ 'A011'
We get the more specific adapter even if there is a less-specific
adapter to B0:
@@ -555,9 +534,9 @@
'A102'
>>> L1.lookup([IF2], IB0, 'bob')
- 'A11G'
+ 'A011'
>>> L1.lookup([IF2], IB1, 'bob')
- 'A11G'
+ 'A011'
>>> L2.lookup([IF2], IB0, 'bob')
'A102'
>>> L2.lookup([IF2], IB1, 'bob')
@@ -577,9 +556,9 @@
We should get the same outputs:
>>> L1.lookup([IF2], IB0, 'bob')
- 'A11G'
+ 'A011'
>>> L1.lookup([IF2], IB1, 'bob')
- 'A11G'
+ 'A011'
>>> L2.lookup([IF2], IB0, 'bob')
'A102'
>>> L2.lookup([IF2], IB1, 'bob')
@@ -592,13 +571,13 @@
>>> ra102.status = interfaces.registration.InactiveStatus
>>> L1.lookup([IF2], IB0, 'bob')
- 'A11G'
+ 'A011'
>>> L1.lookup([IF2], IB1, 'bob')
- 'A11G'
+ 'A011'
>>> L2.lookup([IF2], IB0, 'bob')
- 'A11G'
+ 'A011'
>>> L2.lookup([IF2], IB1, 'bob')
- 'A11G'
+ 'A011'
>>> transaction.commit()
@@ -611,13 +590,13 @@
We should see the result of the deactivations:
>>> L1.lookup([IF2], IB0, 'bob')
- 'A11G'
+ 'A011'
>>> L1.lookup([IF2], IB1, 'bob')
- 'A11G'
+ 'A011'
>>> L2.lookup([IF2], IB0, 'bob')
- 'A11G'
+ 'A011'
>>> L2.lookup([IF2], IB1, 'bob')
- 'A11G'
+ 'A011'
Cleanup:
>>> G.__init__()
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/component/tests/test_directives.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/component/tests/test_directives.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/component/tests/test_directives.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -42,7 +42,8 @@
from zope.app.testing.placelesssetup import PlacelessSetup
from zope.app.component.interface import queryInterface
from zope.app.component.metaconfigure import interface
-from zope.app.component.tests.adapter import A1, A2, A3, I1, I3, IS, Handler
+from zope.app.component.tests.adapter import A1, A2, A3, Handler
+from zope.app.component.tests.adapter import I1, I2, I3, IS
from zope.app.component.tests.components import IContent, Content, Comp, comp
from zope.app.component.tests.components import IApp
from zope.app.component.tests.views import IV, IC, V1, R1, IR
@@ -161,15 +162,9 @@
'''
)))
- content = Content()
- a1 = A1()
- a2 = A2()
- subscribers = zapi.subscribers((content, a1, a2), None)
-
- a3 = subscribers[0]
-
- self.assertEqual(a3.__class__, A3)
- self.assertEqual(a3.context, (content, a1, a2))
+ sm = zapi.getSiteManager()
+ a3 = sm.adapters.subscriptions((IContent, I1, I2), None)[0]
+ self.assertEqual(a3, A3)
def testTrustedSubscriber(self):
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/debugskin/configure.zcml
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/debugskin/configure.zcml 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/debugskin/configure.zcml 2005-09-08 10:17:23 UTC (rev 38384)
@@ -21,4 +21,16 @@
permission="zope.Public"
layer="debug" />
+ <!-- Need to repeat for NotFound to override default view -->
+ <!-- XXX there is a functional test for NotFound. Did it really
+ mean to test the IException registration?
+ -->
+ <page
+ name="index.html"
+ template="error_debug.pt"
+ for="zope.publisher.interfaces.INotFound"
+ class=".exceptions.ExceptionDebugView"
+ permission="zope.Public"
+ layer="debug" />
+
</configure>
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/form/browser/configure.zcml
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/form/browser/configure.zcml 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/form/browser/configure.zcml 2005-09-08 10:17:23 UTC (rev 38384)
@@ -259,7 +259,6 @@
factory=".CollectionDisplayWidget"
permission="zope.Public"
/>
-
<view
type="zope.publisher.interfaces.browser.IBrowserRequest"
for="zope.schema.interfaces.ICollection"
@@ -268,6 +267,29 @@
permission="zope.Public"
/>
+ <!-- XXX
+
+ Need to repeat the above for Sequence to avoid being overridden by a
+ DAV widget. This suggests that we should be getting something
+ more specific than IInputWidget.
+
+ -->
+ <view
+ type="zope.publisher.interfaces.browser.IBrowserRequest"
+ for="zope.schema.interfaces.ISequence"
+ provides="zope.app.form.interfaces.IDisplayWidget"
+ factory=".CollectionDisplayWidget"
+ permission="zope.Public"
+ />
+ <view
+ type="zope.publisher.interfaces.browser.IBrowserRequest"
+ for="zope.schema.interfaces.ISequence"
+ provides="zope.app.form.interfaces.IInputWidget"
+ factory=".CollectionInputWidget"
+ permission="zope.Public"
+ />
+
+
<!-- non-choice collection fields should register for the field + value type
so as to allow specific field + value_type widgets such as the Choice
pattern -->
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/locking/tests.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/locking/tests.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/locking/tests.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -54,6 +54,9 @@
def __cmp__(self, other):
return cmp(id(self.object), id(other.object))
+def maybeFakeKeyReference(ob):
+ if not isinstance(ob, int):
+ return FakeKeyReference(ob)
def setUp(test):
@@ -71,7 +74,7 @@
from zope.app.locking.storage import ILockStorage, PersistentLockStorage
from zope.app.traversing.interfaces import IPathAdapter
- ztapi.provideAdapter(Interface, IKeyReference, FakeKeyReference)
+ ztapi.provideAdapter(Interface, IKeyReference, maybeFakeKeyReference)
ztapi.provideAdapter(Interface, ILockable, LockingAdapterFactory)
ztapi.provideAdapter(None, IPathAdapter, LockingPathAdapter,
"locking")
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/module/README.txt
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/module/README.txt 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/module/README.txt 2005-09-08 10:17:23 UTC (rev 38384)
@@ -113,7 +113,7 @@
>>> ZopeModuleRegistry.findModule('mymodule') is module
True
>>> ZopeModuleRegistry.modules()
- ['mymodule']
+ [u'mymodule']
Additionally, the package provides two API functions that look up a module in
the registry and then in `sys.modules`:
@@ -149,4 +149,4 @@
>>> zope.app.module.uninstallPersistentModuleImporter(event)
>>> __builtin__.__import__
- <built-in function __import__>
\ No newline at end of file
+ <built-in function __import__>
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/pagetemplate/configure.zcml
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/pagetemplate/configure.zcml 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/pagetemplate/configure.zcml 2005-09-08 10:17:23 UTC (rev 38384)
@@ -44,4 +44,11 @@
<allow attributes="__call__" />
</class>
+ <adapter
+ for="zope.app.pagetemplate.viewpagetemplatefile.BoundPageTemplate
+ zope.publisher.interfaces.browser.IBrowserRequest"
+ provides="zope.publisher.interfaces.browser.IBrowserPublisher"
+ factory="zope.app.publication.traversers.NoTraverser"
+ />
+
</configure>
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/publication/traversers.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/publication/traversers.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/publication/traversers.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -67,6 +67,9 @@
return view, path
+def NoTraverser(ob, request):
+ return None
+
class TestTraverser(object):
"""Bobo-style traverser, mostly useful for testing"""
implements(IBrowserPublisher)
@@ -77,7 +80,7 @@
def browserDefault(self, request):
ob = self.context
- if providedBy(ob):
+ if list(providedBy(ob)):
view_name = zapi.getDefaultViewName(ob, request)
return ob, (("@@%s" % view_name),)
Modified: Zope3/branches/jim-adapter-redesign/src/zope/app/traversing/browser/configure.zcml
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/app/traversing/browser/configure.zcml 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/app/traversing/browser/configure.zcml 2005-09-08 10:17:23 UTC (rev 38384)
@@ -10,6 +10,12 @@
permission="zope.Public"
/>
+ <adapter
+ for="types.MethodType zope.publisher.interfaces.browser.IBrowserRequest"
+ provides="zope.publisher.interfaces.browser.IBrowserPublisher"
+ factory="zope.app.publication.traversers.NoTraverser"
+ />
+
<view
for="zope.app.container.interfaces.IItemContainer"
type="zope.publisher.interfaces.browser.IBrowserRequest"
Modified: Zope3/branches/jim-adapter-redesign/src/zope/component/site.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/component/site.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/component/site.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -18,9 +18,10 @@
__docformat__ = "reStructuredText"
import types
+from zope import interface
from zope.interface import implements, providedBy, implementedBy, declarations
from zope.interface.adapter import AdapterRegistry
-from zope.interface.interfaces import IInterface
+from zope.interface.interfaces import ISpecification
from zope.component.interfaces import ISiteManager, IRegistry
from zope.component.interfaces import ComponentLookupError, Invalid
@@ -90,21 +91,13 @@
def queryUtility(self, interface, name='', default=None):
"""See ISiteManager interface"""
+ return self.utilities.lookup((), interface, name, default)
- byname = self.utilities._null.get(interface)
- if byname:
- return byname.get(name, default)
- else:
- return default
-
def getUtilitiesFor(self, interface):
- byname = self.utilities._null.get(interface)
- if byname:
- for item in byname.iteritems():
- yield item
+ return self.utilities.lookupAll((), interface)
def getAllUtilitiesRegisteredFor(self, interface):
- return iter(self.utilities._null.get(('s', interface)) or ())
+ return self.utilities.subscriptions((), interface)
class GlobalSiteManager(SiteManager):
@@ -114,7 +107,7 @@
def __init__(self, name=None):
self.__name__ = name
- self._registrations = {}
+ self._registrations = []
self.adapters = GlobalAdapterRegistry(self, 'adapters')
self.utilities = GlobalAdapterRegistry(self, 'utilities')
@@ -164,19 +157,12 @@
>>> registry.queryMultiAdapter((O1(), O2()), R1, '').__class__
<class 'zope.component.site.O3'>
"""
- ifaces = []
- for iface in required:
- if not IInterface.providedBy(iface) and iface is not None:
- if not isinstance(iface, (type, types.ClassType)):
- raise TypeError(iface, IInterface)
- iface = implementedBy(iface)
+ required = tuple(map(_spec, required))
- ifaces.append(iface)
- required = tuple(ifaces)
+ self._registrations.append(
+ AdapterRegistration(required, provided, name, factory, info),
+ )
- self._registrations[(required, provided, name)] = AdapterRegistration(
- required, provided, name, factory, info)
-
self.adapters.register(required, provided, name, factory)
def subscribe(self, required, provided, factory, info=''):
@@ -208,25 +194,11 @@
SubscriptionRegistration(('R1',), 'P2', 'c1', 'd1')
SubscriptionRegistration(('R1',), 'P2', 'c2', 'd2')
"""
- ifaces = []
- for iface in required:
- if not IInterface.providedBy(iface) and \
- not isinstance(iface, declarations.Implements) and \
- iface is not None:
- if not isinstance(iface, (type, types.ClassType)):
- raise TypeError(iface, IInterface)
- iface = implementedBy(iface)
- ifaces.append(iface)
- required = tuple(ifaces)
+ required = tuple(map(_spec, required))
- registration = SubscriptionRegistration(
- required, provided, factory, info)
-
- self._registrations[(required, provided)] = (
- self._registrations.get((required, provided), ())
- +
- (registration, )
+ self._registrations.append(
+ SubscriptionRegistration(required, provided, factory, info),
)
self.adapters.subscribe(required, provided, factory)
@@ -243,22 +215,28 @@
# Also subscribe to support getAllUtilitiesRegisteredFor:
self.utilities.subscribe((), providedInterface, component)
- self._registrations[(providedInterface, name)] = UtilityRegistration(
- providedInterface, name, component, info)
+ self._registrations.append(
+ UtilityRegistration(providedInterface, name, component, info),
+ )
def registrations(self):
- for registration in self._registrations.itervalues():
- if isinstance(registration, tuple):
- for r in registration:
- yield r
- else:
- yield registration
+ return iter(self._registrations)
def __reduce__(self):
# Global site managers are pickled as global objects
return self.__name__
+_class_types = (type, types.ClassType)
+def _spec(iface_or_class):
+ if ISpecification.providedBy(iface_or_class):
+ return iface_or_class
+ if iface_or_class is None:
+ return interface.Interface
+ if isinstance(iface_or_class, _class_types):
+ return interface.implementedBy(iface_or_class)
+ raise TypeError(iface_or_class, ISpecification)
+
def GAR(siteManager, registryName):
return getattr(siteManager, registryName)
Modified: Zope3/branches/jim-adapter-redesign/src/zope/interface/_zope_interface_coptimizations.c
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/interface/_zope_interface_coptimizations.c 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/interface/_zope_interface_coptimizations.c 2005-09-08 10:17:23 UTC (rev 38384)
@@ -23,6 +23,7 @@
static PyObject *BuiltinImplementationSpecifications, *str__provides__;
static PyObject *str__class__, *str__providedBy__, *strisOrExtends;
static PyObject *empty, *fallback, *str_implied, *str_cls, *str_implements;
+static PyObject *str__sro__;
static PyTypeObject *Implements;
static int imported_declarations = 0;
@@ -487,7 +488,425 @@
/* tp_descr_get */ (descrgetfunc)CPB_descr_get,
};
+/*
+def _lookup(components, specs, 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 r is not None:
+ return r
+ return None
+
+ return components
+ */
+static PyObject *
+_lookup(PyObject *components, PyObject *specs, int i, int l)
+{
+ /* Note that result is NOT increfed */
+
+ PyObject *specs_i, *spec, *sro, *comps;
+ int ls, is;
+
+ if (i < l)
+ {
+ specs_i = PyTuple_GET_ITEM(specs, i);
+ if (specs_i != NULL)
+ {
+ sro = PyObject_GetAttr(specs_i, str__sro__);
+ if (sro == NULL)
+ return NULL;
+ ls = PyTuple_Size(sro);
+ if (ls < 0)
+ {
+ Py_DECREF(sro);
+ return NULL;
+ }
+ for (is = 0; is < ls; is++)
+ {
+ spec = PyTuple_GET_ITEM(sro, is);
+ if (spec == NULL)
+ continue;
+ comps = PyDict_GetItem(components, spec);
+ if (comps == NULL)
+ continue;
+ comps = _lookup(comps, specs, i+1, l);
+ if (comps != Py_None)
+ {
+ Py_DECREF(sro);
+ return comps;
+ }
+ }
+
+ }
+ return Py_None;
+ }
+
+ return components;
+}
+
+static PyObject *
+tuple(PyObject *iterable)
+{
+ if (PyTuple_Check(iterable))
+ {
+ Py_INCREF(iterable);
+ return iterable;
+ }
+ return PyObject_CallFunctionObjArgs((PyObject*)&PyTuple_Type, iterable,
+ NULL);
+}
+
+/*
+
+def lookup(components, required, provided):
+ components = components.get(provided)
+ if components:
+
+ if required:
+ components = find(components, required, 0, len(required))
+ if not components:
+ return None
+
+ return components[0][0]
+
+ return None
+
+ */
+static PyObject *
+lookup(PyObject *ignored, PyObject *args)
+{
+ PyObject *components, *required, *provided, *result=Py_None;
+ int l;
+
+ if (PyArg_ParseTuple(args, "O!OO",
+ &PyDict_Type, &components, &required, &provided)
+ == 0)
+ return NULL;
+
+ required = tuple(required);
+ if (required == NULL)
+ goto err;
+
+ components = PyDict_GetItem(components, provided);
+ if (components != NULL)
+ {
+ l = PyTuple_GET_SIZE(required);
+ if (l > 0)
+ {
+ components = _lookup(components, required, 0, l);
+ if (components == Py_None)
+ goto done;
+ }
+
+ components = PyTuple_GetItem(components, 0);
+ if (components == NULL)
+ return NULL;
+ result = PyTuple_GetItem(components, 0);
+ }
+
+ done:
+ Py_DECREF(required);
+ Py_INCREF(result);
+ return result;
+
+ err:
+ Py_DECREF(required);
+ return NULL;
+}
+
+/*
+
+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
+
+ */
+
+static PyObject *
+lookup1(PyObject *ignored, PyObject *args)
+{
+ PyObject *components, *required, *provided, *r=Py_None;
+
+ if (PyArg_ParseTuple(args, "O!OO",
+ &PyDict_Type, &components, &required, &provided)
+ == 0)
+ return NULL;
+
+ components = PyDict_GetItem(components, provided);
+ if (components != NULL)
+ {
+ PyObject *sro;
+ int is, ls;
+
+ sro = PyObject_GetAttr(required, str__sro__);
+ if (sro == NULL)
+ return NULL;
+ ls = PyTuple_Size(sro);
+ if (ls < 0)
+ {
+ Py_DECREF(sro);
+ return NULL;
+ }
+
+ for (is = 0; is < ls; is++)
+ {
+ PyObject *spec, *comps;
+ int l;
+
+ spec = PyTuple_GET_ITEM(sro, is);
+ if (spec == NULL)
+ continue;
+ comps = PyDict_GetItem(components, spec);
+ if (comps == NULL)
+ continue;
+ l = PyTuple_Size(comps);
+ if (l == 0)
+ continue;
+ if (l < 0)
+ r = NULL;
+ else
+ {
+ r = PyTuple_GET_ITEM(comps, 0);
+ r = PyTuple_GetItem(r, 0);
+ }
+ break;
+ }
+
+ Py_DECREF(sro);
+ }
+
+ Py_XINCREF(r);
+ return r;
+}
+
+/*
+
+def _subscribers(components, specs, i, l, objects, result):
+ if i < l:
+ sro = list(specs[i].__sro__)
+ sro.reverse()
+ for spec in sro:
+ comps = components.get(spec)
+ if comps is not None:
+ _subscribers(comps, specs, i+1, l, objects, result)
+ else:
+ if objects is None:
+ result.extend([c[0] for c in components])
+ else:
+ for c in components:
+ c = c[0](*objects)
+ if c is not None and result is not None:
+ result.append(c)
+
+ */
+
+static int
+_subscribers(PyObject *components, PyObject *specs, int i, int l,
+ PyObject *objects, PyObject *result)
+{
+ PyObject *comps;
+
+ if (i < l)
+ {
+ PyObject *sro, *spec;
+ int ls;
+
+ spec = PyTuple_GET_ITEM(specs, i);
+ if (specs == NULL)
+ return 0; /* should never happen. Treat as empty spec. */
+
+ sro = PyObject_GetAttr(spec, str__sro__);
+ if (sro == NULL)
+ return -1;
+ ls = PyTuple_Size(sro);
+ if (ls < 0)
+ {
+ Py_DECREF(sro);
+ return -1;
+ }
+ for (ls-- ; ls >= 0; ls--)
+ {
+ spec = PyTuple_GET_ITEM(sro, ls);
+ if (spec == NULL)
+ continue;
+ comps = PyDict_GetItem(components, spec);
+ if (comps == NULL)
+ continue;
+ if (_subscribers(comps, specs, i+1, l, objects, result) < 0)
+ {
+ Py_DECREF(sro);
+ return -1;
+ }
+ }
+ Py_DECREF(sro);
+ }
+ else
+ {
+ l = PyTuple_Size(components);
+ if (l < 0)
+ return -1;
+ for (i=0; i < l; i++)
+ {
+ comps = PyTuple_GET_ITEM(components, i);
+ comps = PyTuple_GetItem(comps, 0);
+ if (comps == NULL)
+ return -1;
+
+ if (objects != NULL)
+ {
+ comps = PyObject_CallObject(comps, objects);
+ if (comps == NULL)
+ return -1;
+
+ if (result != NULL && comps != Py_None)
+ {
+ int a = 0;
+
+ a = PyList_Append(result, comps);
+ Py_DECREF(comps);
+ if (a < 0)
+ return -1;
+ }
+ else
+ Py_DECREF(comps);
+ }
+ else if (PyList_Append(result, comps) < 0)
+ /* if objects is NULL, then result is not NULL */
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+
+def subscriptions(components, required, provided, result):
+ components = components.get(provided)
+ if components:
+ _subsciptions(components, required, 0, len(required), result)
+ */
+static PyObject *
+subscriptions(PyObject *ignored, PyObject *args)
+{
+ PyObject *components, *required, *provided, *result;
+
+ if (PyArg_ParseTuple(args, "O!OOO",
+ &PyDict_Type, &components, &required, &provided,
+ &result)
+ == 0)
+ return NULL;
+
+ required = tuple(required);
+ if (required == NULL)
+ return NULL;
+
+ components = PyDict_GetItem(components, provided);
+ if (components != NULL)
+ {
+ int l;
+
+ l = PyTuple_GET_SIZE(required);
+ if (_subscribers(components, required, 0, l, NULL, result) < 0)
+ goto err;
+ }
+
+ Py_DECREF(required);
+ Py_INCREF(Py_None);
+ return Py_None;
+
+ err:
+ Py_DECREF(required);
+ return NULL;
+}
+
+/*
+
+def subscribers(components, objects, provided, result):
+ components = components.get(provided)
+ if not components:
+ return
+
+ required = map(providedBy, objects)
+
+ if provided is None:
+ result == None
+
+ _subscribers(components, required, 0, len(required), objects, result)
+
+ */
+static PyObject *
+subscribers(PyObject *ignored, PyObject *args)
+{
+ PyObject *components, *objects, *provided, *result;
+
+ if (PyArg_ParseTuple(args, "O!OOO",
+ &PyDict_Type, &components,
+ &objects, &provided,
+ &result)
+ == 0)
+ return NULL;
+
+ objects = tuple(objects);
+ if (objects == NULL)
+ return NULL;
+
+ components = PyDict_GetItem(components, provided);
+ if (components != NULL)
+ {
+ int i, l;
+ PyObject *required;
+
+ l = PyTuple_GET_SIZE(objects);
+ required = PyTuple_New(l);
+ if (required == NULL)
+ goto err;
+
+ for (i=0; i < l; i++)
+ {
+ PyObject *o;
+
+ o = PyTuple_GET_ITEM(objects, i);
+ if (o == NULL)
+ continue;
+ o = providedBy(NULL, o);
+ if (o == NULL)
+ {
+ Py_DECREF(required);
+ goto err;
+ }
+ PyTuple_SET_ITEM(required, i, o);
+ }
+
+ if (provided == Py_None)
+ result = NULL;
+
+ i = _subscribers(components, required, 0, l, objects, result);
+ Py_DECREF(required);
+
+ if (i < 0)
+ goto err;
+ }
+
+ Py_DECREF(objects);
+ Py_INCREF(Py_None);
+ return Py_None;
+
+ err:
+ Py_DECREF(objects);
+ return NULL;
+}
+
+
static struct PyMethodDef m_methods[] = {
{"implementedBy", (PyCFunction)implementedBy, METH_O,
"Interfaces implemented by instances of a class"},
@@ -495,6 +914,24 @@
"Get an object's interfaces (internal api)"},
{"providedBy", (PyCFunction)providedBy, METH_O,
"Get an object's interfaces"},
+
+ {"lookup", (PyCFunction)lookup, METH_VARARGS,
+ "lookup(components, required, provided) -- lookup a multi-adapter factory"
+ },
+
+ {"lookup1", (PyCFunction)lookup1, METH_VARARGS,
+ "lookup(components, required, provided) -- lookup an adapter factory"
+ },
+
+ {"subscriptions", (PyCFunction)subscriptions, METH_VARARGS,
+ "subscriptions(components, required, provided, result)"
+ " -- find subscriptions"
+ },
+
+ {"subscribers", (PyCFunction)subscribers, METH_VARARGS,
+ "subscriptions(components, objects, provided, result)"
+ " -- find subscriptions"
+ },
{NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
};
@@ -520,6 +957,7 @@
DEFINE_STRING(_implied);
DEFINE_STRING(_implements);
DEFINE_STRING(_cls);
+ DEFINE_STRING(__sro__);
#undef DEFINE_STRING
Modified: Zope3/branches/jim-adapter-redesign/src/zope/interface/adapter.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/interface/adapter.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/interface/adapter.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -1,746 +1,436 @@
-############################################################################
+##############################################################################
#
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
-############################################################################
-"""Adapter-style interface registry
+##############################################################################
+"""Adapter management
-This implementation is based on a notion of "surrogate" interfaces.
-
$Id$
"""
-# Implementation notes
+from zope.interface import providedBy, Interface, ro
-# We keep a collection of surrogates.
+_marker = object
+class AdapterRegistry(object):
-# A surrogate is a surrogate for a specification (interface or
-# declaration). We use weak references in order to remove surrogates
-# if the corresponding specification goes away.
+ def __init__(self, bases=()):
+ self._unnamed_adapters = [] # [{ provided -> components }]
+ self._named_adapters = {} # { name -> [{ provided -> components }] }
+ self._unnamed_subscriptions = [] # ditto
+ self._named_subscriptions = {} # ditto
+ self.__bases__ = bases
-# Each surrogate keeps track of:
+ def __bases__():
+ def get(self):
+ return self.__dict__['__bases__']
+ def set(self, v):
+ self.__dict__['__bases__'] = v
+ self.ro = ro.ro(self)
+
+ return property(get, set)
+ __bases__ = __bases__()
+
+ def register(self, required, provided, name, value):
+ if value is None:
+ self.unregister(required, provided, name, value)
+ return
-# - The adapters registered directly for that surrogate, and
+ 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
-# - The "implied" adapters, which is the adapters that can be computed
-# from instances of that surrogate.
+ order = len(required)
+ while len(byorder) <= order:
+ byorder.append(Adapters())
-# The later data structure takes into account adapters registered for
-# specifications that the registered surrogate extends.
+ components = byorder[order]
+ components.register(required, provided, value)
+
+ 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
-# The registrations are of the form:
+ order = len(required)
+ if order >= len(byorder):
+ return
+ components = byorder[order]
+ components.unregister(required, provided, value)
-# {(subscription, with, name, specification) -> factories}
-# where:
+ def lookup(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
-# 'subscription' is a flag indicating if this registration is for
-# subscription adapters.
+ order = len(required)
+ if order >= len(byorder):
+ continue
-# 'with' is a tuple of specs that is non-empty only in the case
-# of multi-adapters.
+ components = byorder[order]
+ result = lookup(components.components, required, provided)
+ if result is not None:
+ return result
-# 'name' is a unicode adapter name. Unnamed adapters have an empty
-# name.
+ return default
-# 'specification' is the interface being adapted to.
+ def queryMultiAdapter(self, objects, provided, name=u'', default=None):
+ factory = self.lookup(map(providedBy, objects), provided, name)
+ if factory is None:
+ return default
-# 'factories' is normally a tuple of factories, but can be anything.
-# (See the "raw" option to the query-adapter calls.) For subscription
-# adapters, it is a tuple of tuples of factories.
+ result = factory(*objects)
+ if result is None:
+ return default
-# The implied adapters are held in a single dictionary. The items in the
-# dictionary are of several forms:
+ return result
-# For single adapters:
-#
-# {specification -> {name -> object}
-#
-# where object is usually a sequence of factories
+ 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
-# For multiple adapters:
-#
-# {(specification, order) -> {name -> {with -> object}}}
+ if 1 >= len(byorder):
+ continue
-# For single subscription adapters:
-#
-# {('s', specification) -> tuple([object])}
+ components = byorder[1]
+ result = lookup1(components.components, required, provided)
+ if result is not None:
+ return result
-# For multiple-subscription adapters:
-#
-# {('s', specification, order) -> {with -> tuple([object])}}
+ return default
+ def queryAdapter(self, object, provided, name=u'', default=None):
+ return self.adapter_hook(provided, object, name, default)
-from __future__ import generators
+ def adapter_hook(self, provided, object, name=u'', default=None):
+ factory = self.lookup1(providedBy(object), provided, name)
+ if factory is not None:
+ result = factory(object)
+ if result is not None:
+ return result
-import weakref
-from zope.interface.ro import ro
-from zope.interface.declarations import providedBy
-from zope.interface.interface import InterfaceClass, Interface
+ return default
-Default = InterfaceClass("Default", (), {})
-Null = InterfaceClass("Null", (), {})
+ 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)
-# 2.2 backwards compatability
-try:
- enumerate
-except NameError:
- def enumerate(l):
- i = 0
- for o in l:
- yield i, o
- i += 1
-try:
- basestring
-except NameError:
- basestring = (str, unicode)
+ 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)
+ def names(self, required, provided):
+ return [c[0] for c in self.lookupAll(required, provided)]
-class ReadProperty(object):
+ def subscribe(self, required, provided, value):
- def __init__(self, func):
- self.func = func
+# XXX when we are ready to support named subscribers, we'll add a name
+# argument and uncomment the following.
+## if name:
+## name = _normalize_name(name)
+## byorder = self._named_subscriptions.get(name)
+## if byorder is None:
+## self._named_subscriptions[name] = byorder = []
+## else:
+## byorder = self._unnamed_subscriptions
- def __get__(self, inst, class_):
- if inst is None:
- return self
- return self.func(inst)
+ byorder = self._unnamed_subscriptions
-class Surrogate(object):
- """Specification surrogate
+ order = len(required)
+ while len(byorder) <= order:
+ byorder.append(Subscriptions())
- A specification surrogate is used to hold adapter registrations on
- behalf of a specification.
- """
+ components = byorder[order]
+ components.register(required, provided, value)
- def __init__(self, spec, registry):
- self.spec = spec.weakref()
- self.registry = registry
- spec.subscribe(self)
- self.adapters = {}
- self.dependents = weakref.WeakKeyDictionary()
+ def unsubscribe(self, required, provided, value):
- self.registry = registry
- self.__bases__ = [registry.get(base) for base in spec.__bases__]
- for base in self.__bases__:
- base.subscribe(self)
+# XXX when we are ready to support named subscribers, we'll add a name
+# argument and uncomment the following.
+## if name:
+## name = _normalize_name(name)
+## byorder = self._named_subscriptions.get(name)
+## if byorder is None:
+## self._named_subscriptions[name] = byorder = []
+## else:
+## byorder = self._unnamed_subscriptions
- def dirty(self):
- if 'get' in self.__dict__:
- # Not already dirty
- del self.selfImplied
- del self.multImplied
- del self.get
+ byorder = self._unnamed_subscriptions
- bases = [self.registry.get(base) for base in self.spec().__bases__]
- if bases != self.__bases__:
- # Our bases changed. unsubscribe from the old ones
- # and subscribe to the new ones
- for base in self.__bases__:
- base.unsubscribe(self)
+ order = len(required)
+ if len(byorder) <= order:
+ return
- self.__bases__ = bases
- for base in bases:
- base.subscribe(self)
+ components = byorder[order]
+ components.unregister(required, provided, value)
- for dependent in self.dependents.keys():
- dependent.dirty()
+ def subscriptions(self, required, provided, name=u''):
+ result = []
+ # XXX should we traverse ro in reverse?
+ for self in self.ro:
+ if name:
+ byorder = self._named_subscriptions.get(name)
+ if byorder is None:
+ continue
+ else:
+ byorder = self._unnamed_subscriptions
- def clean(self):
- for base in self.__bases__:
- base.unsubscribe(self)
- self.__bases__ = [self.registry.get(base)
- for base in self.spec().__bases__]
- for base in self.__bases__:
- base.subscribe(self)
-
- self.selfImplied, self.multImplied = adapterImplied(self.adapters)
-
- implied = {}
-
- ancestors = ro(self)
-
- # Collect implied data in reverse order to have more specific data
- # override less-specific data.
- ancestors.reverse()
- for ancestor in ancestors:
+ order = len(required)
+ if order >= len(byorder):
+ continue
- for key, v in ancestor.selfImplied.iteritems():
+ subscriptions(byorder[order].components, required, provided,
+ result)
- # key is specification or ('s', specification)
- subscription = isinstance(key, tuple) and key[0] == 's'
- if subscription:
- # v is tuple of subs
- implied[key] = implied.get(key, ()) + v
- else:
- oldbyname = implied.get(key)
- if not oldbyname:
- implied[key] = oldbyname = {}
-
- # v is name -> object
- oldbyname.update(v)
+ return result
- for key, v in ancestor.multImplied.iteritems():
- # key is (specification, order)
- # or ('s', specification, order)
- subscription = key[0] == 's'
- if subscription:
- oldwithobs = implied.get(key)
- if not oldwithobs:
- oldwithobs = implied[key] = {}
-
- # v is {with -> tuple([object])}
- for with, objects in v.iteritems():
- oldwithobs[with] = oldwithobs.get(with, ()) + objects
-
- else:
- oldbyname = implied.get(key)
- if not oldbyname:
- implied[key] = oldbyname = {}
-
- # v is {name -> {with -> ?}}
- for name, withobs in v.iteritems():
- oldwithobs = oldbyname.get(name)
- if not oldwithobs:
- oldwithobs = oldbyname[name] = {}
-
- # withobs is {with -> object}
- oldwithobs.update(withobs)
-
- # Now flatten with mappings to tuples
- for key, v in implied.iteritems():
- if isinstance(key, tuple):
- if key[0] == 's':
- # subscriptions
- if isinstance(v, dict):
- implied[key] = v.items()
- else:
- byname = v
- for name, value in byname.iteritems():
- if isinstance(value, dict):
- # We have {with -> value}
- # convert it to sorted [(with, value]
- byname[name] = orderwith(value)
-
- 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, object, name='', with=()):
- if object is None:
- try:
- del self.adapters[False, tuple(with), name, specification]
- except KeyError:
- pass
+ def subscribers(self, objects, provided, name=u''):
+ if provided is None:
+ result = ()
else:
- self.adapters[False, tuple(with), name, specification
- ] = object
-
- self.dirty()
-
- def _subscriptionAdaptTo(self, specification, object, with=()):
- if object is None:
- raise TypeError, ("Unregistering subscription adapters"
- " isn't implemented")
-
- key = (True, tuple(with), '', specification)
- self.adapters[key] = self.adapters.get(key, ()) + (object, )
- self.dirty()
-
- def changed(self, which=None):
- self.dirty()
-
- def __repr__(self):
- return '<%s(%s)>' % (self.__class__.__name__, self.spec())
-
-def orderwith(bywith):
-
- # Convert {with -> adapter} to withs, [(with, value)]
- # such that there are no i, j, i < j, such that
- # withs[j][0] extends withs[i][0].
-
- withs = []
- for with, value in bywith.iteritems():
- for i, (w, v) in enumerate(withs):
- if withextends(with, w):
- withs.insert(i, (with, value))
- break
- else:
- withs.append((with, value))
+ result = []
- return withs
-
-
-def withextends(with1, with2):
- for spec1, spec2 in zip(with1, with2):
- if spec1.extends(spec2):
- return True
- if spec1 != spec2:
- break
- return False
-
-
-class AdapterLookup(object):
- # Adapter lookup support
- # We have a class here because we want to provide very
- # fast lookup support in C and making this part of the adapter
- # registry itself would provide problems if someone wanted
- # persistent adapter registries, because we want C slots for fast
- # lookup that would clash with persistence-supplied slots.
- # so this class acts a little bit like a lookup adapter for the adapter
- # registry.
-
- def __init__(self, registry, surrogates, _remove):
- self._registry = registry
- self._surrogateClass = registry._surrogateClass
- self._default = registry._default
- self._null = registry._null
- self._surrogates = surrogates
- self._remove = _remove
-
- def lookup(self, required, provided, name='', default=None):
- order = len(required)
- if order == 1:
- # Simple adapter:
- s = self.get(required[0])
- byname = s.get(provided)
- if byname:
- value = byname.get(name)
+ for self in self.ro:
+ if name:
+ byorder = self._named_subscriptions.get(name)
+ if byorder is None:
+ continue
else:
- value = None
+ byorder = self._unnamed_subscriptions
- if value is None:
- byname = self._default.get(provided)
- if byname:
- value = byname.get(name, default)
- else:
- return default
-
- return value
-
- elif order == 0:
- # null adapter
- byname = self._null.get(provided)
- if byname:
- return byname.get(name, default)
- else:
- return default
-
- # Multi adapter
-
- with = required[1:]
- key = provided, order
-
- for surrogate in self.get(required[0]), self._default:
- byname = surrogate.get(key)
- if not byname:
+ order = len(objects)
+ if order >= len(byorder):
continue
- bywith = byname.get(name)
- if not bywith:
- continue
+ subscribers(byorder[order].components, objects, provided, result)
- # Selecting multi-adapters is not just a matter of matching the
- # required interfaces of the adapter to the ones passed. Several
- # adapters might match, but we only want the best one. We use a
- # ranking algorithm to determine the best match.
+ return result
- # `best` carries the rank and value of the best found adapter.
- best = None
- for rwith, value in bywith:
- # the `rank` describes how well the found adapter matches.
- rank = []
- for rspec, spec in zip(rwith, with):
- if not spec.isOrExtends(rspec):
- break # This one is no good
- # Determine the rank of this particular specification.
- rank.append(list(spec.__sro__).index(rspec))
- else:
- # If the new rank is better than the best previously
- # recorded one, make the new adapter the best one found.
- rank = tuple(rank)
- if best is None or rank < best[0]:
- best = rank, value
- # If any match was found, return the best one.
- if best:
- return best[1]
+def _normalize_name(name):
+ if isinstance(name, basestring):
+ return unicode(name)
- return default
+ raise TypeError("name must be a regular or unicode string")
- def lookup1(self, required, provided, name='', default=None):
- return self.lookup((required,), provided, name, default)
-
- def adapter_hook(self, interface, object, name='', default=None):
- """Hook function used when calling interfaces.
-
- When called from Interface.__adapt__, only the interface and
- object parameters will be passed.
-
- If the factory produces `None`, then the default is returned. This
- allows us to prevent adaptation (if desired) and make the factory
- decide whether an adapter will be available.
- """
- factory = self.lookup1(providedBy(object), interface, name)
- if factory is not None:
- adapter = factory(object)
- if adapter is not None:
- return adapter
- return default
-
- def queryAdapter(self, object, interface, name='', default=None):
- # Note that we rarely call queryAdapter directly
- # We usually end up calling adapter_hook
- return self.adapter_hook(interface, object, name, default)
-
- def subscriptions(self, required, provided):
- if provided is None:
- provided = Null
-
- order = len(required)
- if order == 1:
- # Simple subscriptions:
- s = self.get(required[0])
- result = s.get(('s', provided))
- if result:
- result = list(result)
- else:
- result = []
-
- default = self._default.get(('s', provided))
- if default:
- result.extend(default)
-
- return result
-
- elif order == 0:
- result = self._null.get(('s', provided))
- if result:
- return list(result)
- else:
- return []
- # Multi
- key = 's', provided, order
- with = required[1:]
- result = []
-
- for surrogate in self.get(required[0]), self._default:
- bywith = surrogate.get(key)
- if not bywith:
- continue
+class Next:
- for rwith, values in bywith:
- for rspec, spec in zip(rwith, with):
- if not spec.isOrExtends(rspec):
- break # This one is no good
- else:
- # we didn't break, so we have a match
- result.extend(values)
-
- return result
-
+ def __init__(self, spec, basis):
+ sro = spec.__sro__
+ self.__sro__ = sro[sro.index(basis)+1:]
- def queryMultiAdapter(self, objects, interface, name='', default=None):
- factory = self.lookup(map(providedBy, objects), interface, name)
- if factory is not None:
- return factory(*objects)
+class Adapters(object):
- return default
+ def __init__(self):
+ self.components = {}
+ self.provided = {} # {iface -> (iro, [(required, value)])}
- def subscribers(self, objects, interface):
- subscriptions = self.subscriptions(map(providedBy, objects), interface)
- subscribers = [subscription(*objects)
- for subscription in subscriptions]
- # Filter None values
- return [x for x in subscribers if x is not None]
+ def register(self, required, provided, value):
+ if (provided is None) or (provided is Interface):
+ self._register(required, provided, provided, value)
+ else:
+ registered = self.provided.get(provided)
+ if registered is None:
+ self.provided[provided] = registered = provided.__iro__, []
+ provided.subscribe(self)
+ registered[1].append((required, value))
- def get(self, declaration):
- if declaration is None:
- return self._default
+ for p in provided.__iro__:
+ self._register(required, provided, p, value)
- ref = declaration.weakref(self._remove)
- surrogate = self._surrogates.get(ref)
- if surrogate is None:
- surrogate = self._surrogateClass(declaration, self._registry)
- self._surrogates[ref] = surrogate
+ def _register(self, required, provided, p, value):
+ d = self.components
+ k = p
+ for r in required:
+ if r is None:
+ r = Interface
+ v = d.get(k)
+ if v is None:
+ d[k] = v = {}
+ d = v
+ k = r
- return surrogate
+ components = d.get(k, ())
+ d[k] = self._add(components, provided, value)
-
-class AdapterRegistry(object):
- """Adapter registry
- """
-
- # Implementation note:
- # We are like a weakref dict ourselves. We can't use a weakref
- # dict because we have to use spec.weakref() rather than
- # weakref.ref(spec) to get weak refs to specs.
-
- _surrogateClass = Surrogate
-
- def __init__(self):
- default = self._surrogateClass(Default, self)
- self._default = default
- null = self._surrogateClass(Null, self)
- self._null = null
-
- # Create separate lookup object and copy it's methods
- surrogates = {Default.weakref(): default, Null.weakref(): null}
- def _remove(k):
- try:
- del surrogates[k]
- except KeyError:
- pass
- lookup = AdapterLookup(self, surrogates, _remove)
+ def _add(self, components, provided, value):
+ if provided is None:
+ return components + ((value, provided), )
- for name in ('lookup', 'lookup1', 'queryAdapter', 'get',
- 'adapter_hook', 'subscriptions',
- 'queryMultiAdapter', 'subscribers',
- ):
- setattr(self, name, getattr(lookup, name))
-
- def register(self, required, provided, name, value):
- if required:
- with = []
- for iface in required[1:]:
- if iface is None:
- iface = Interface
- with.append(iface)
- with = tuple(with)
- required = self.get(required[0])
- else:
- with = ()
- required = self._null
+ return (
+ tuple([c for c in components if provided.extends(c[1])])
+ +
+ ((value, provided), )
+ +
+ tuple([c for c in components if not provided.extends(c[1])])
+ )
- if not isinstance(name, basestring):
- raise TypeError("The name provided to provideAdapter "
- "must be a string or unicode")
+ def unregister(self, required, provided, value):
+ if (provided is None) or (provided is Interface):
+ self._unregister(required, provided, provided, value)
+ else:
+ registered = self.provided.get(provided)
+ if registered is None:
+ return
+ if value is None:
+ rv = [r for r in registered[1] if r[0] != required]
+ else:
+ rv = [r for r in registered[1] if r != (required, value)]
- required._adaptTo(provided, value, unicode(name), with)
+ if rv:
+ self.provided[provided] = registered[0], rv
+ else:
+ del self.provided[provided]
- def lookupAll(self, required, provided):
- order = len(required)
- if order == 1:
- # Simple adapter:
- s = self.get(required[0])
- byname = s.get(provided)
- if byname:
- for item in byname.iteritems():
- yield item
+ for p in provided.__iro__:
+ self._unregister(required, provided, p, value)
- defbyname = self._default.get(provided)
- if defbyname:
- for name, value in defbyname.iteritems():
- if name in byname:
- continue
- yield name, value
+ def _unregister(self, required, provided, p, value):
+ items = []
+ d = self.components
+ k = p
+ for r in required:
+ if r is None:
+ r = Interface
+ v = d.get(k)
+ if v is None:
+ return
+ items.append((d, k))
+ d = v
+ k = r
+ components = d.get(k, None)
+ if components is None:
return
- elif order == 0:
- # null adapter
- byname = self._null.get(provided)
- if byname:
- for item in byname.iteritems():
- yield item
-
- return
-
-
- # Multi adapter
-
- with = required[1:]
- key = provided, order
- first = ()
-
- for surrogate in self.get(required[0]), self._default:
- byname = surrogate.get(key)
- if not byname:
- continue
-
- for name, bywith in byname.iteritems():
- if not bywith or name in first:
- continue
-
- # See comments on lookup() above
- best = None
- for rwith, value in bywith:
- # the `rank` describes how well the found adapter matches.
- rank = []
- for rspec, spec in zip(rwith, with):
- if not spec.isOrExtends(rspec):
- break # This one is no good
- # Determine the rank of this particular specification.
- rank.append(list(spec.__sro__).index(rspec))
- else:
- # If the new rank is better than the best previously
- # recorded one, make the new adapter the best one found.
- rank = tuple(rank)
- if best is None or rank < best[0]:
- best = rank, value
-
- # If any match was found, return the best one.
- if best:
- yield name, best[1]
-
- first = byname
-
- def subscribe(self, required, provided, value):
- if required:
- required, with = self.get(required[0]), tuple(required[1:])
+ if value is None:
+ # unregister all
+ components = [c for c in components
+ if c[1] != provided]
else:
- required = self._null
- with = ()
+ # unregister just this one
+ components = [c for c in components
+ if c != (value, provided)]
- if provided is None:
- provided = Null
-
- required._subscriptionAdaptTo(provided, value, with)
-
-def mextends(with, rwith):
- if len(with) == len(rwith):
- for w, r in zip(with, rwith):
- if not w.isOrExtends(r):
- break
+ if components:
+ d[k] = tuple(components)
else:
- return True
- return False
+ del d[k]
-def adapterImplied(adapters):
- implied = {}
- multi = {}
+ items.reverse()
+ for d, k in items:
+ if not d[k]:
+ del d[k]
- # This dictionary is used to catch situations specific adapters
- # override less specific adapters.
- # Because subscriptions are cumulative, registered doesn't apply.
- registered = {}
+class Subscriptions(Adapters):
- # Add adapters and interfaces directly implied by same:
+ def _add(self, components, provided, value):
+ return components + ((value, provided), )
- for key, value in adapters.iteritems():
-
- # TODO: Backward compatibility
- # BBB ? Don't need to handle 3-tuples some day
- try:
- (subscription, with, name, target) = key
- except ValueError:
- (with, name, target) = key
- subscription = False
-
- if subscription:
- if with:
- _add_multi_sub_adapter(with, target, multi, value)
- else:
- _add_named_sub_adapter(target, implied, value)
- else:
- if with:
- _add_multi_adapter(with, name, target, target, multi,
- registered, value)
- else:
- _add_named_adapter(target, target, name, implied,
- registered, value)
-
- return implied, multi
-
-def _add_named_adapter(target, provided, name, implied,
- registered, value):
+def _lookup(components, specs, 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 r is not None:
+ return r
+ return None
- ikey = target
- rkey = target, name
+ return components
- byname = implied.get(ikey)
- if not byname:
- byname = implied[ikey] = {}
+def lookup(components, required, provided):
+ components = components.get(provided)
+ if components:
- if (name not in byname
- or
- (rkey in registered and registered[rkey].extends(provided))
- ):
+ if required:
+ components = _lookup(components, required, 0, len(required))
+ if not components:
+ return None
- registered[rkey] = provided
- byname[name] = value
+ return components[0][0]
- for b in target.__bases__:
- _add_named_adapter(b, provided, name, implied,
- registered, value)
+ return None
-def _add_multi_adapter(with, name, target, provided, implied,
- registered, object):
+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]
- ikey = target, (len(with) + 1)
- byname = implied.get(ikey)
- if not byname:
- byname = implied[ikey] = {}
+ return None
- bywith = byname.get(name)
- if not bywith:
- bywith = byname[name] = {}
+def _subscribers(components, specs, i, l, objects, result):
+ if i < l:
+ sro = list(specs[i].__sro__)
+ sro.reverse()
+ for spec in sro:
+ comps = components.get(spec)
+ if comps is not None:
+ _subscribers(comps, specs, i+1, l, objects, result)
+ else:
+ if objects is None:
+ result.extend([c[0] for c in components])
+ else:
+ for c in components:
+ c = c[0](*objects)
+ if c is not None and result is not None:
+ result.append(c)
-
- rkey = ikey, name, with # The full key has all 4
- if (with not in bywith
- or
- (rkey not in registered or registered[rkey].extends(provided))
- ):
- # This is either a new entry or it is an entry for a more
- # general interface that is closer provided than what we had
- # before
- registered[rkey] = provided
- bywith[with] = object
+def subscriptions(components, required, provided, result):
+ components = components.get(provided)
+ if components:
+ _subscribers(components, required, 0, len(required), None, result)
- for b in target.__bases__:
- _add_multi_adapter(with, name, b, provided, implied,
- registered, object)
+def subscribers(components, objects, provided, result):
+ components = components.get(provided)
+ if components:
+ required = map(providedBy, objects)
-def _add_named_sub_adapter(target, implied, objects):
- key = ('s', target)
- implied[key] = implied.get(key, ()) + objects
-
- for b in target.__bases__:
- _add_named_sub_adapter(b, implied, objects)
+ if provided is None:
+ result == None
-def _add_multi_sub_adapter(with, target, implied, objects):
- key = 's', target, (len(with) + 1)
- bywith = implied.get(key)
- if not bywith:
- bywith = implied[key] = {}
+ _subscribers(components, required, 0, len(required), objects, result)
- bywith[with] = bywith.get(with, ()) + objects
-
- for b in target.__bases__:
- _add_multi_sub_adapter(with, b, implied, objects)
+try:
+ from _zope_interface_coptimizations import lookup, lookup1
+ from _zope_interface_coptimizations import subscribers, subscriptions
+except ImportError:
+ pass
+
Modified: Zope3/branches/jim-adapter-redesign/src/zope/interface/adapter.txt
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/interface/adapter.txt 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/interface/adapter.txt 2005-09-08 10:17:23 UTC (rev 38384)
@@ -382,6 +382,9 @@
Subscriptions
=============
+XXX need tests that demonstrate that more general subscribers are
+ called before more specific subscribers
+
Normally, we want to look up an object that most-closely matches a
specification. Sometimes, we want to get all of the objects that
match some specification. We use subscriptions for this. We
@@ -452,7 +455,7 @@
You can have subscriptions that are indepenent of any specifications::
- >>> registry.subscriptions([], IP1)
+ >>> list(registry.subscriptions([], IP1))
[]
>>> registry.subscribe([], IP2, 'sub2')
Modified: Zope3/branches/jim-adapter-redesign/src/zope/interface/declarations.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/interface/declarations.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/interface/declarations.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -237,22 +237,7 @@
__radd__ = __add__
- def __nonzero__(self):
- """Test whether there are any interfaces in a specification.
- >>> from zope.interface import Interface
- >>> class I1(Interface): pass
- ...
- >>> spec = Declaration(I1)
- >>> int(bool(spec))
- 1
- >>> spec = Declaration()
- >>> int(bool(spec))
- 0
- """
- return bool(self.__iro__)
-
-
##############################################################################
#
# Implementation specifications
@@ -1216,31 +1201,6 @@
1
- nonzero:
-
- >>> from zope.interface import Interface
- >>> class I1(Interface):
- ... pass
- >>> class I2(Interface):
- ... pass
- >>> class C(object):
- ... implements(I1)
- >>> c = C()
- >>> int(bool(providedBy(c)))
- 1
- >>> directlyProvides(c, I2)
- >>> int(bool(providedBy(c)))
- 1
- >>> class C(object):
- ... pass
- >>> c = C()
- >>> int(bool(providedBy(c)))
- 0
- >>> directlyProvides(c, I2)
- >>> int(bool(providedBy(c)))
- 1
-
-
"""
return Provides(cls, direct)
Modified: Zope3/branches/jim-adapter-redesign/src/zope/interface/interface.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/interface/interface.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/interface/interface.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -137,7 +137,7 @@
...
>>> spec = Declaration()
>>> int(spec.extends(Interface))
- 0
+ 1
>>> spec = Declaration(I2)
>>> int(spec.extends(Interface))
1
@@ -160,6 +160,8 @@
except ImportError:
pass
+
+
class Specification(SpecificationBase):
"""Specifications
@@ -262,10 +264,17 @@
implied.clear()
ancestors = ro(self)
+
+ try:
+ if Interface not in ancestors:
+ ancestors.append(Interface)
+ except NameError:
+ pass # defining Interface itself
+
self.__sro__ = tuple(ancestors)
self.__iro__ = tuple([ancestor for ancestor in ancestors
if isinstance(ancestor, InterfaceClass)
- ])
+ ])
for ancestor in ancestors:
# We directly imply our ancestors:
@@ -330,7 +339,7 @@
...
>>> spec = Declaration()
>>> int(spec.extends(Interface))
- 0
+ 1
>>> spec = Declaration(I2)
>>> int(spec.extends(Interface))
1
@@ -938,8 +947,9 @@
from zope.interface.interfaces import IMethod
classImplements(Method, IMethod)
- from zope.interface.interfaces import IInterface
+ from zope.interface.interfaces import IInterface, ISpecification
classImplements(InterfaceClass, IInterface)
+ classImplements(Specification, ISpecification)
# We import this here to deal with module dependencies.
from zope.interface.declarations import providedBy, implementedBy
Modified: Zope3/branches/jim-adapter-redesign/src/zope/interface/interfaces.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/interface/interfaces.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/interface/interfaces.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -645,13 +645,32 @@
provided interface, and a name.
"""
- def lookup(required, provided, name, default=None):
+ def lookup(required, provided, name='', default=None):
"""Lookup a value
A value is looked up based on a *sequence* of required
specifications, a provided interface, and a name.
"""
+ def queryMultiAdapter(objects, provided, name=u'', default=None):
+ """Adapt a sequence of objects to a named, provided, interface
+ """
+
+ def lookup1(required, provided, name=u'', default=None):
+ """Lookup a value using a single required interface
+
+ A value is looked up based on a single required
+ specifications, a provided interface, and a name.
+ """
+
+ def queryAdapter(object, provided, name=u'', default=None):
+ """Adapt an object using a registered adapter factory.
+ """
+
+ def adapter_hook(provided, object, name=u'', default=None):
+ """Adapt an object using a registered adapter factory.
+ """
+
def lookupAll(required, provided):
"""Find all adapters from the required to the provided interfaces
@@ -662,7 +681,7 @@
"""Return the names for which there are registered objects
"""
- def subscribe(required, provided, subscriber):
+ def subscribe(required, provided, subscriber, name=u''):
"""Register a subscriber
A subscriber is registered for a *sequence* of required
@@ -672,10 +691,13 @@
equivalent) interfaces.
"""
- def subscriptions(required, provided):
+ def subscriptions(required, provided, name=u''):
"""Get a sequence of subscribers
Subscribers for a *sequence* of required interfaces, and a provided
interface are returned.
"""
+ def subscribers(objects, provided, name=u''):
+ """Get a sequence of subscription adapters
+ """
Modified: Zope3/branches/jim-adapter-redesign/src/zope/interface/tests/test_adapter.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/interface/tests/test_adapter.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/interface/tests/test_adapter.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -36,23 +36,7 @@
pass
-def test_orderwith():
- """
- >>> Interface = zope.interface.Interface
- >>> bywith = {(Interface, Interface): 'A0',
- ... (IF0, Interface): 'A1',
- ... (Interface, IB0): 'A2',
- ... (IF0, IB0): 'A3',
- ... (IF1, IB0): 'A4',
- ... (IF0, IB1): 'A5',
- ... (IF1, IB1): 'A6',
- ... }
- >>> [value for spec, value in zope.interface.adapter.orderwith(bywith)]
- ['A6', 'A4', 'A5', 'A3', 'A1', 'A2', 'A0']
- """
-
-
def test_multi_adapter_get_best_match():
"""
>>> registry = AdapterRegistry()
Modified: Zope3/branches/jim-adapter-redesign/src/zope/security/checker.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/src/zope/security/checker.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/src/zope/security/checker.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -568,6 +568,7 @@
complex: NoProxy,
types.NoneType: NoProxy,
str: NoProxy,
+ tuple: NoProxy,
unicode: NoProxy,
type(True): NoProxy, # Boolean, if available :)
datetime.timedelta: NoProxy,
@@ -621,9 +622,9 @@
sets.ImmutableSet: _setChecker,
# YAGNI: () a rock
- tuple: NamesChecker(['__getitem__', '__getslice__', '__add__', '__radd__',
- '__contains__', '__len__', '__iter__',
- '__str__']),
+## tuple: NamesChecker(['__getitem__', '__getslice__', '__add__', '__radd__',
+## '__contains__', '__len__', '__iter__',
+## '__str__']),
types.InstanceType: _instanceChecker,
Proxy: NoProxy,
type(weakref.ref(_Sequence())): NamesChecker(['__call__']),
Modified: Zope3/branches/jim-adapter-redesign/z3.py
===================================================================
--- Zope3/branches/jim-adapter-redesign/z3.py 2005-09-08 10:17:17 UTC (rev 38383)
+++ Zope3/branches/jim-adapter-redesign/z3.py 2005-09-08 10:17:23 UTC (rev 38384)
@@ -23,7 +23,7 @@
def run(argv=list(sys.argv)):
- if sys.version_info < ( 2,3,5 ):
+ if sys.version_info < ( 2,3,4 ):
print """\
ERROR: Your python version is not supported by Zope3.
Zope3 needs Python 2.3.5 or greater. You are running:""" + sys.version
More information about the Zope3-Checkins
mailing list