[Checkins] SVN: Sandbox/chrism/zope.registry/ Create zope.registry package for perusal.
Chris McDonough
chrism at plope.com
Wed Nov 25 16:56:33 EST 2009
Log message for revision 106017:
Create zope.registry package for perusal.
Changed:
A Sandbox/chrism/zope.registry/
A Sandbox/chrism/zope.registry/.installed.cfg
A Sandbox/chrism/zope.registry/CHANGES.txt
A Sandbox/chrism/zope.registry/README.txt
A Sandbox/chrism/zope.registry/bootstrap.py
A Sandbox/chrism/zope.registry/buildout.cfg
A Sandbox/chrism/zope.registry/setup.py
A Sandbox/chrism/zope.registry/src/
A Sandbox/chrism/zope.registry/src/zope/
A Sandbox/chrism/zope.registry/src/zope/__init__.py
A Sandbox/chrism/zope.registry/src/zope/registry/
A Sandbox/chrism/zope.registry/src/zope/registry/__init__.py
A Sandbox/chrism/zope.registry/src/zope/registry/interfaces.py
A Sandbox/chrism/zope.registry/src/zope/registry/registry.txt
A Sandbox/chrism/zope.registry/src/zope/registry/testfiles/
A Sandbox/chrism/zope.registry/src/zope/registry/testfiles/__init__.py
A Sandbox/chrism/zope.registry/src/zope/registry/testfiles/adapter.py
A Sandbox/chrism/zope.registry/src/zope/registry/testfiles/components.py
A Sandbox/chrism/zope.registry/src/zope/registry/testfiles/views.py
A Sandbox/chrism/zope.registry/src/zope/registry/tests.py
-=-
Added: Sandbox/chrism/zope.registry/.installed.cfg
===================================================================
--- Sandbox/chrism/zope.registry/.installed.cfg (rev 0)
+++ Sandbox/chrism/zope.registry/.installed.cfg 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,33 @@
+[buildout]
+installed_develop_eggs = /Users/chrism/projects/zope.registry/develop-eggs/zope.registry.egg-link
+parts = test python
+
+[test]
+__buildout_installed__ = /Users/chrism/projects/zope.registry/parts/test
+ /Users/chrism/projects/zope.registry/bin/test
+__buildout_signature__ = zc.recipe.testrunner-1.2.0-py2.4.egg zc.recipe.egg-1.2.2-py2.4.egg setuptools-0.6c11-py2.4.egg zope.testing-3.8.3-py2.4.egg zc.buildout-1.4.2-py2.4.egg zope.interface-3.5.2-py2.4-macosx-10.6-i386.egg zope.exceptions-3.5.2-py2.4.egg
+_b = /Users/chrism/projects/zope.registry/bin
+_d = /Users/chrism/projects/zope.registry/develop-eggs
+_e = /Users/chrism/projects/zope.registry/eggs
+bin-directory = /Users/chrism/projects/zope.registry/bin
+develop-eggs-directory = /Users/chrism/projects/zope.registry/develop-eggs
+eggs = zope.registry
+eggs-directory = /Users/chrism/projects/zope.registry/eggs
+executable = /Users/chrism/projects/zope.registry/bin/python
+location = /Users/chrism/projects/zope.registry/parts/test
+recipe = zc.recipe.testrunner
+script = /Users/chrism/projects/zope.registry/bin/test
+
+[python]
+__buildout_installed__ = /Users/chrism/projects/zope.registry/bin/py
+__buildout_signature__ = zc.recipe.egg-1.2.2-py2.4.egg setuptools-0.6c11-py2.4.egg zc.buildout-1.4.2-py2.4.egg
+_b = /Users/chrism/projects/zope.registry/bin
+_d = /Users/chrism/projects/zope.registry/develop-eggs
+_e = /Users/chrism/projects/zope.registry/eggs
+bin-directory = /Users/chrism/projects/zope.registry/bin
+develop-eggs-directory = /Users/chrism/projects/zope.registry/develop-eggs
+eggs = zope.registry
+eggs-directory = /Users/chrism/projects/zope.registry/eggs
+executable = /Users/chrism/projects/zope.registry/bin/python
+interpreter = py
+recipe = zc.recipe.egg
Added: Sandbox/chrism/zope.registry/CHANGES.txt
===================================================================
--- Sandbox/chrism/zope.registry/CHANGES.txt (rev 0)
+++ Sandbox/chrism/zope.registry/CHANGES.txt 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,7 @@
+CHANGES
+*******
+
+Next release
+------------
+
+- ...
Added: Sandbox/chrism/zope.registry/README.txt
===================================================================
--- Sandbox/chrism/zope.registry/README.txt (rev 0)
+++ Sandbox/chrism/zope.registry/README.txt 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,12 @@
+*****************************
+zope.registry Package Readme
+*****************************
+
+*This package is intended to be independently reusable in any Python
+project. It is maintained by the* `Zope Toolkit project <http://docs.zope.org/zopetoolkit/>`_.
+
+This package represents the core registry of the Zope Component
+Architecture. Together with the 'zope.interface' package, it provides
+facilities for defining, registering and looking up components.
+
+.. contents::
Added: Sandbox/chrism/zope.registry/bootstrap.py
===================================================================
--- Sandbox/chrism/zope.registry/bootstrap.py (rev 0)
+++ Sandbox/chrism/zope.registry/bootstrap.py 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+# 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 72703 2007-02-20 11:49:26Z jim $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+ ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+ cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+ os.P_WAIT, sys.executable, sys.executable,
+ '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+ dict(os.environ,
+ PYTHONPATH=
+ ws.find(pkg_resources.Requirement.parse('setuptools')).location
+ ),
+ ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)
Added: Sandbox/chrism/zope.registry/buildout.cfg
===================================================================
--- Sandbox/chrism/zope.registry/buildout.cfg (rev 0)
+++ Sandbox/chrism/zope.registry/buildout.cfg 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,14 @@
+[buildout]
+develop = .
+parts = test python
+unzip = true
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = zope.registry
+
+[python]
+recipe = zc.recipe.egg
+interpreter = py
+eggs = ${test:eggs}
+
Added: Sandbox/chrism/zope.registry/setup.py
===================================================================
--- Sandbox/chrism/zope.registry/setup.py (rev 0)
+++ Sandbox/chrism/zope.registry/setup.py 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,53 @@
+##############################################################################
+#
+# 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.
+# 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.
+#
+##############################################################################
+# This package is developed by the Zope Toolkit project, documented here:
+# http://docs.zope.org/zopetoolkit
+# When developing and releasing this package, please follow the documented
+# Zope Toolkit policies as described by this documentation.
+##############################################################################
+
+"""Setup for zope.registry package
+
+$Id: setup.py 105736 2009-11-16 22:34:23Z kobold $
+"""
+
+import os
+from setuptools import setup, find_packages
+
+
+def read(*rnames):
+ return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+setup(
+ name='zope.registry',
+ version = '0.0',
+ url='http://pypi.python.org/pypi/zope.registry',
+ license='ZPL 2.1',
+ description='Zope Component Architecture',
+ author='Zope Corporation and Contributors',
+ author_email='zope-dev at zope.org',
+ long_description='long description',
+ packages = find_packages('src'),
+ package_dir = {'': 'src'},
+ namespace_packages=['zope',],
+ tests_require = [
+ 'zope.testing'
+ ],
+ install_requires=['setuptools',
+ 'zope.interface',
+ 'zope.event',
+ ],
+ include_package_data = True,
+ zip_safe = False,
+ )
Added: Sandbox/chrism/zope.registry/src/zope/__init__.py
===================================================================
--- Sandbox/chrism/zope.registry/src/zope/__init__.py (rev 0)
+++ Sandbox/chrism/zope.registry/src/zope/__init__.py 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
Added: Sandbox/chrism/zope.registry/src/zope/registry/__init__.py
===================================================================
--- Sandbox/chrism/zope.registry/src/zope/registry/__init__.py (rev 0)
+++ Sandbox/chrism/zope.registry/src/zope/registry/__init__.py 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,539 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+# 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.
+#
+##############################################################################
+"""Basic components support
+
+$Id: registry.py 100603 2009-06-02 19:44:19Z jim $
+"""
+
+import sys
+import types
+
+from zope.interface import Interface
+from zope.interface import implementedBy
+from zope.interface import implements
+from zope.interface import implementsOnly
+from zope.interface import providedBy
+from zope.interface.adapter import AdapterRegistry
+from zope.interface.interfaces import ISpecification
+
+from zope.registry.interfaces import ComponentLookupError
+from zope.registry.interfaces import IAdapterRegistration
+from zope.registry.interfaces import IComponents
+from zope.registry.interfaces import IHandlerRegistration
+from zope.registry.interfaces import ISubscriptionAdapterRegistration
+from zope.registry.interfaces import IUtilityRegistration
+from zope.registry.interfaces import Registered
+from zope.registry.interfaces import Unregistered
+from zope.event import notify
+
+class Components(object):
+
+ implements(IComponents)
+
+ def __init__(self, name='', bases=()):
+ assert isinstance(name, basestring)
+ self.__name__ = name
+ self._init_registries()
+ self._init_registrations()
+ self.__bases__ = tuple(bases)
+
+ def __repr__(self):
+ return "<%s %s>" % (self.__class__.__name__, self.__name__)
+
+ def _init_registries(self):
+ self.adapters = AdapterRegistry()
+ self.utilities = AdapterRegistry()
+
+ def _init_registrations(self):
+ self._utility_registrations = {}
+ self._adapter_registrations = {}
+ self._subscription_registrations = []
+ self._handler_registrations = []
+
+ def _getBases(self):
+ # Subclasses might override
+ return self.__dict__.get('__bases__', ())
+
+ def _setBases(self, bases):
+ # Subclasses might override
+ self.adapters.__bases__ = tuple([
+ base.adapters for base in bases])
+ self.utilities.__bases__ = tuple([
+ base.utilities for base in bases])
+ self.__dict__['__bases__'] = tuple(bases)
+
+ __bases__ = property(
+ lambda self: self._getBases(),
+ lambda self, bases: self._setBases(bases),
+ )
+
+ def registerUtility(self, component=None, provided=None, name=u'', info=u'',
+ event=True, factory=None):
+ if factory:
+ if component:
+ raise TypeError("Can't specify factory and component.")
+ component = factory()
+
+ if provided is None:
+ provided = _getUtilityProvided(component)
+
+ reg = self._utility_registrations.get((provided, name))
+ if reg is not None:
+ if reg[:2] == (component, info):
+ # already registered
+ return
+ self.unregisterUtility(reg[0], provided, name)
+
+ subscribed = False
+ for ((p, _), data) in self._utility_registrations.iteritems():
+ if p == provided and data[0] == component:
+ subscribed = True
+ break
+
+ self._utility_registrations[(provided, name)] = component, info, factory
+ self.utilities.register((), provided, name, component)
+
+ if not subscribed:
+ self.utilities.subscribe((), provided, component)
+
+ if event:
+ notify(Registered(
+ UtilityRegistration(self, provided, name, component, info,
+ factory)
+ ))
+
+ def unregisterUtility(self, component=None, provided=None, name=u'',
+ factory=None):
+ if factory:
+ if component:
+ raise TypeError("Can't specify factory and component.")
+ component = factory()
+
+ if provided is None:
+ if component is None:
+ raise TypeError("Must specify one of component, factory and "
+ "provided")
+ provided = _getUtilityProvided(component)
+
+ old = self._utility_registrations.get((provided, name))
+ if (old is None) or ((component is not None) and
+ (component != old[0])):
+ return False
+
+ if component is None:
+ component = old[0]
+
+ # Note that component is now the old thing registered
+
+ del self._utility_registrations[(provided, name)]
+ self.utilities.unregister((), provided, name)
+
+ subscribed = False
+ for ((p, _), data) in self._utility_registrations.iteritems():
+ if p == provided and data[0] == component:
+ subscribed = True
+ break
+
+ if not subscribed:
+ self.utilities.unsubscribe((), provided, component)
+
+ notify(Unregistered(
+ UtilityRegistration(self, provided, name, component, *old[1:])
+ ))
+
+ return True
+
+ def registeredUtilities(self):
+ for ((provided, name), data
+ ) in self._utility_registrations.iteritems():
+ yield UtilityRegistration(self, provided, name, *data)
+
+ def queryUtility(self, provided, name=u'', default=None):
+ return self.utilities.lookup((), provided, name, default)
+
+ def getUtility(self, provided, name=u''):
+ utility = self.utilities.lookup((), provided, name)
+ if utility is None:
+ raise ComponentLookupError(provided, name)
+ return utility
+
+ def getUtilitiesFor(self, interface):
+ for name, utility in self.utilities.lookupAll((), interface):
+ yield name, utility
+
+ def getAllUtilitiesRegisteredFor(self, interface):
+ return self.utilities.subscriptions((), interface)
+
+ def registerAdapter(self, factory, required=None, provided=None, name=u'',
+ info=u'', event=True):
+ if provided is None:
+ provided = _getAdapterProvided(factory)
+ required = _getAdapterRequired(factory, required)
+ self._adapter_registrations[(required, provided, name)
+ ] = factory, info
+ self.adapters.register(required, provided, name, factory)
+
+ if event:
+ notify(Registered(
+ AdapterRegistration(self, required, provided, name,
+ factory, info)
+ ))
+
+
+ def unregisterAdapter(self, factory=None,
+ required=None, provided=None, name=u'',
+ ):
+ if provided is None:
+ if factory is None:
+ raise TypeError("Must specify one of factory and provided")
+ provided = _getAdapterProvided(factory)
+
+ if (required is None) and (factory is None):
+ raise TypeError("Must specify one of factory and required")
+
+ required = _getAdapterRequired(factory, required)
+ old = self._adapter_registrations.get((required, provided, name))
+ if (old is None) or ((factory is not None) and
+ (factory != old[0])):
+ return False
+
+ del self._adapter_registrations[(required, provided, name)]
+ self.adapters.unregister(required, provided, name)
+
+ notify(Unregistered(
+ AdapterRegistration(self, required, provided, name,
+ *old)
+ ))
+
+ return True
+
+ def registeredAdapters(self):
+ for ((required, provided, name), (component, info)
+ ) in self._adapter_registrations.iteritems():
+ yield AdapterRegistration(self, required, provided, name,
+ component, info)
+
+ def queryAdapter(self, object, interface, name=u'', default=None):
+ return self.adapters.queryAdapter(object, interface, name, default)
+
+ def getAdapter(self, object, interface, name=u''):
+ adapter = self.adapters.queryAdapter(object, interface, name)
+ if adapter is None:
+ raise ComponentLookupError(object, interface, name)
+ return adapter
+
+ def queryMultiAdapter(self, objects, interface, name=u'', default=None):
+ return self.adapters.queryMultiAdapter(
+ objects, interface, name, default)
+
+ def getMultiAdapter(self, objects, interface, name=u''):
+ adapter = self.adapters.queryMultiAdapter(objects, interface, name)
+ if adapter is None:
+ raise ComponentLookupError(objects, interface, name)
+ return adapter
+
+ def getAdapters(self, objects, provided):
+ for name, factory in self.adapters.lookupAll(
+ map(providedBy, objects),
+ provided):
+ adapter = factory(*objects)
+ if adapter is not None:
+ yield name, adapter
+
+ def registerSubscriptionAdapter(self,
+ factory, required=None, provided=None,
+ name=u'', info=u'',
+ event=True):
+ if name:
+ raise TypeError("Named subscribers are not yet supported")
+ if provided is None:
+ provided = _getAdapterProvided(factory)
+ required = _getAdapterRequired(factory, required)
+ self._subscription_registrations.append(
+ (required, provided, name, factory, info)
+ )
+ self.adapters.subscribe(required, provided, factory)
+
+ if event:
+ notify(Registered(
+ SubscriptionRegistration(self, required, provided, name,
+ factory, info)
+ ))
+
+ def registeredSubscriptionAdapters(self):
+ for data in self._subscription_registrations:
+ yield SubscriptionRegistration(self, *data)
+
+ def unregisterSubscriptionAdapter(self, factory=None,
+ required=None, provided=None, name=u'',
+ ):
+ if name:
+ raise TypeError("Named subscribers are not yet supported")
+ if provided is None:
+ if factory is None:
+ raise TypeError("Must specify one of factory and provided")
+ provided = _getAdapterProvided(factory)
+
+ if (required is None) and (factory is None):
+ raise TypeError("Must specify one of factory and required")
+
+ required = _getAdapterRequired(factory, required)
+
+ if factory is None:
+ new = [(r, p, n, f, i)
+ for (r, p, n, f, i)
+ in self._subscription_registrations
+ if not (r == required and p == provided)
+ ]
+ else:
+ new = [(r, p, n, f, i)
+ for (r, p, n, f, i)
+ in self._subscription_registrations
+ if not (r == required and p == provided and f == factory)
+ ]
+
+ if len(new) == len(self._subscription_registrations):
+ return False
+
+
+ self._subscription_registrations[:] = new
+ self.adapters.unsubscribe(required, provided, factory)
+
+ notify(Unregistered(
+ SubscriptionRegistration(self, required, provided, name,
+ factory, '')
+ ))
+
+ return True
+
+ def subscribers(self, objects, provided):
+ return self.adapters.subscribers(objects, provided)
+
+ def registerHandler(self,
+ factory, required=None,
+ name=u'', info=u'',
+ event=True):
+ if name:
+ raise TypeError("Named handlers are not yet supported")
+ required = _getAdapterRequired(factory, required)
+ self._handler_registrations.append(
+ (required, name, factory, info)
+ )
+ self.adapters.subscribe(required, None, factory)
+
+ if event:
+ notify(Registered(
+ HandlerRegistration(self, required, name, factory, info)
+ ))
+
+ def registeredHandlers(self):
+ for data in self._handler_registrations:
+ yield HandlerRegistration(self, *data)
+
+ def unregisterHandler(self, factory=None, required=None, name=u''):
+ if name:
+ raise TypeError("Named subscribers are not yet supported")
+
+ if (required is None) and (factory is None):
+ raise TypeError("Must specify one of factory and required")
+
+ required = _getAdapterRequired(factory, required)
+
+ if factory is None:
+ new = [(r, n, f, i)
+ for (r, n, f, i)
+ in self._handler_registrations
+ if r != required
+ ]
+ else:
+ new = [(r, n, f, i)
+ for (r, n, f, i)
+ in self._handler_registrations
+ if not (r == required and f == factory)
+ ]
+
+ if len(new) == len(self._handler_registrations):
+ return False
+
+ self._handler_registrations[:] = new
+ self.adapters.unsubscribe(required, None, factory)
+
+ notify(Unregistered(
+ HandlerRegistration(self, required, name, factory, '')
+ ))
+
+ return True
+
+ def handle(self, *objects):
+ self.adapters.subscribers(objects, None)
+
+
+def _getUtilityProvided(component):
+ provided = list(providedBy(component))
+ if len(provided) == 1:
+ return provided[0]
+ raise TypeError(
+ "The utility doesn't provide a single interface "
+ "and no provided interface was specified.")
+
+def _getAdapterProvided(factory):
+ provided = list(implementedBy(factory))
+ if len(provided) == 1:
+ return provided[0]
+ raise TypeError(
+ "The adapter factory doesn't implement a single interface "
+ "and no provided interface was specified.")
+
+
+classTypes = type, types.ClassType
+def _getAdapterRequired(factory, required):
+ if required is None:
+ try:
+ required = factory.__component_adapts__
+ except AttributeError:
+ raise TypeError(
+ "The adapter factory doesn't have a __component_adapts__ "
+ "attribute and no required specifications were specified"
+ )
+ elif ISpecification.providedBy(required):
+ raise TypeError("the required argument should be a list of "
+ "interfaces, not a single interface")
+
+ result = []
+ for r in required:
+ if r is None:
+ r = Interface
+ elif not ISpecification.providedBy(r):
+ if isinstance(r, classTypes):
+ r = implementedBy(r)
+ else:
+ raise TypeError("Required specification must be a "
+ "specification or class."
+ )
+ result.append(r)
+ return tuple(result)
+
+
+class UtilityRegistration(object):
+
+ implements(IUtilityRegistration)
+
+ def __init__(self, registry, provided, name, component, doc, factory=None):
+ (self.registry, self.provided, self.name, self.component, self.info,
+ self.factory
+ ) = registry, provided, name, component, doc, factory
+
+ def __repr__(self):
+ return '%s(%r, %s, %r, %s, %r, %r)' % (
+ self.__class__.__name__,
+ self.registry,
+ getattr(self.provided, '__name__', None), self.name,
+ getattr(self.component, '__name__', `self.component`),
+ self.factory, self.info,
+ )
+
+ def __cmp__(self, other):
+ return cmp(self.__repr__(), other.__repr__())
+
+class AdapterRegistration(object):
+
+ implements(IAdapterRegistration)
+
+ def __init__(self, registry, required, provided, name, component, doc):
+ (self.registry, self.required, self.provided, self.name,
+ self.factory, self.info
+ ) = registry, required, provided, name, component, doc
+
+ def __repr__(self):
+ return '%s(%r, %s, %s, %r, %s, %r)' % (
+ self.__class__.__name__,
+ self.registry,
+ '[' + ", ".join([r.__name__ for r in self.required]) + ']',
+ getattr(self.provided, '__name__', None), self.name,
+ getattr(self.factory, '__name__', `self.factory`), self.info,
+ )
+
+ def __cmp__(self, other):
+ return cmp(self.__repr__(), other.__repr__())
+
+class SubscriptionRegistration(AdapterRegistration):
+
+ implementsOnly(ISubscriptionAdapterRegistration)
+
+class HandlerRegistration(AdapterRegistration):
+
+ implementsOnly(IHandlerRegistration)
+
+ def __init__(self, registry, required, name, handler, doc):
+ (self.registry, self.required, self.name, self.handler, self.info
+ ) = registry, required, name, handler, doc
+
+ @property
+ def factory(self):
+ return self.handler
+
+ provided = None
+
+ def __repr__(self):
+ return '%s(%r, %s, %r, %s, %r)' % (
+ self.__class__.__name__,
+ self.registry,
+ '[' + ", ".join([r.__name__ for r in self.required]) + ']',
+ self.name,
+ getattr(self.factory, '__name__', `self.factory`), self.info,
+ )
+
+class adapter:
+
+ def __init__(self, *interfaces):
+ self.interfaces = interfaces
+
+ def __call__(self, ob):
+ if isinstance(ob, _class_types):
+ ob.__component_adapts__ = _adapts_descr(self.interfaces)
+ else:
+ ob.__component_adapts__ = self.interfaces
+
+ return ob
+
+def adapts(*interfaces):
+ frame = sys._getframe(1)
+ locals = frame.f_locals
+
+ # Try to make sure we were called from a class def. In 2.2.0 we can't
+ # check for __module__ since it doesn't seem to be added to the locals
+ # until later on.
+ if (locals is frame.f_globals) or (
+ ('__module__' not in locals) and sys.version_info[:3] > (2, 2, 0)):
+ raise TypeError("adapts can be used only from a class definition.")
+
+ if '__component_adapts__' in locals:
+ raise TypeError("adapts can be used only once in a class definition.")
+
+ locals['__component_adapts__'] = _adapts_descr(interfaces)
+
+def adaptedBy(ob):
+ return getattr(ob, '__component_adapts__', None)
+
+_class_types = type, types.ClassType
+
+class _adapts_descr(object):
+ def __init__(self, interfaces):
+ self.interfaces = interfaces
+
+ def __get__(self, inst, cls):
+ if inst is None:
+ return self.interfaces
+ raise AttributeError('__component_adapts__')
+
Added: Sandbox/chrism/zope.registry/src/zope/registry/interfaces.py
===================================================================
--- Sandbox/chrism/zope.registry/src/zope/registry/interfaces.py (rev 0)
+++ Sandbox/chrism/zope.registry/src/zope/registry/interfaces.py 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,944 @@
+############################################################################
+#
+# Copyright (c) 2001, 2002 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.
+# 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.
+#
+############################################################################
+"""Component and Component Architecture Interfaces
+
+$Id: interfaces.py 105528 2009-11-08 11:05:28Z kobold $
+"""
+__docformat__ = "reStructuredText"
+
+from zope.interface import Attribute
+from zope.interface import Interface
+from zope.interface import implements
+
+class ComponentLookupError(LookupError):
+ """A component could not be found."""
+
+class Invalid(Exception):
+ """A component doesn't satisfy a promise."""
+
+class Misused(Exception):
+ """A component is being used (registered) for the wrong interface."""
+
+
+class IObjectEvent(Interface):
+ """An event related to an object.
+
+ The object that generated this event is not necessarily the object
+ refered to by location.
+ """
+
+ object = Attribute("The subject of the event.")
+
+
+class ObjectEvent(object):
+ implements(IObjectEvent)
+
+ def __init__(self, object):
+ self.object = object
+
+class IComponentArchitecture(Interface):
+ """The Component Architecture is defined by two key components: Adapters
+ and Utiltities. Both are managed by site managers. All other components
+ build on top of them.
+ """
+ # Site Manager API
+
+ def getGlobalSiteManager():
+ """Return the global site manager.
+
+ This function should never fail and always return an object that
+ provides `IGlobalSiteManager`.
+ """
+
+ def getSiteManager(context=None):
+ """Get the nearest site manager in the given context.
+
+ If `context` is `None`, return the global site manager.
+
+ If the `context` is not `None`, it is expected that an adapter
+ from the `context` to `IComponentLookup` can be found. If no
+ adapter is found, a `ComponentLookupError` is raised.
+
+ """
+
+ # Utility API
+
+ def getUtility(interface, name='', context=None):
+ """Get the utility that provides interface
+
+ Returns the nearest utility to the context that implements the
+ specified interface. If one is not found, raises
+ ComponentLookupError.
+ """
+
+ def queryUtility(interface, name='', default=None, context=None):
+ """Look for the utility that provides interface
+
+ Returns the nearest utility to the context that implements
+ the specified interface. If one is not found, returns default.
+ """
+
+ def queryNextUtility(context, interface, name='', default=None):
+ """Query for the next available utility.
+
+ Find the next available utility providing `interface` and having the
+ specified name. If no utility was found, return the specified `default`
+ value.
+ """
+
+ def getNextUtility(context, interface, name=''):
+ """Get the next available utility.
+
+ If no utility was found, a `ComponentLookupError` is raised.
+ """
+
+ def getUtilitiesFor(interface, context=None):
+ """Return the utilities that provide an interface
+
+ An iterable of utility name-value pairs is returned.
+ """
+
+ def getAllUtilitiesRegisteredFor(interface, context=None):
+ """Return all registered utilities for an interface
+
+ This includes overridden utilities.
+
+ An iterable of utility instances is returned. No names are
+ returned.
+ """
+
+ # Adapter API
+
+ def getAdapter(object,
+ interface=Interface, name=u'',
+ context=None):
+ """Get a named adapter to an interface for an object
+
+ Returns an adapter that can adapt object to interface. If a matching
+ adapter cannot be found, raises ComponentLookupError.
+
+ If context is None, an application-defined policy is used to choose
+ an appropriate service manager from which to get an 'Adapters' service.
+
+ If 'context' is not None, context is adapted to IServiceService,
+ and this adapter's 'Adapters' service is used.
+ """
+
+ def getAdapterInContext(object, interface, context):
+ """Get a special adapter to an interface for an object
+
+ NOTE: This method should only be used if a custom context
+ needs to be provided to provide custom component
+ lookup. Otherwise, call the interface, as in::
+
+ interface(object)
+
+ Returns an adapter that can adapt object to interface. If a matching
+ adapter cannot be found, raises ComponentLookupError.
+
+ Context is adapted to IServiceService, and this adapter's
+ 'Adapters' service is used.
+
+ If the object has a __conform__ method, this method will be
+ called with the requested interface. If the method returns a
+ non-None value, that value will be returned. Otherwise, if the
+ object already implements the interface, the object will be
+ returned.
+ """
+
+ def getMultiAdapter(objects,
+ interface=Interface, name='',
+ context=None):
+ """Look for a multi-adapter to an interface for an objects
+
+ Returns a multi-adapter that can adapt objects to interface. If a
+ matching adapter cannot be found, raises ComponentLookupError.
+
+ If context is None, an application-defined policy is used to choose
+ an appropriate service manager from which to get an 'Adapters' service.
+
+ If 'context' is not None, context is adapted to IServiceService,
+ and this adapter's 'Adapters' service is used.
+
+ The name consisting of an empty string is reserved for unnamed
+ adapters. The unnamed adapter methods will often call the
+ named adapter methods with an empty string for a name.
+ """
+
+ def queryAdapter(object, interface=Interface, name=u'',
+ default=None, context=None):
+ """Look for a named adapter to an interface for an object
+
+ Returns an adapter that can adapt object to interface. If a matching
+ adapter cannot be found, returns the default.
+
+ If context is None, an application-defined policy is used to choose
+ an appropriate service manager from which to get an 'Adapters' service.
+
+ If 'context' is not None, context is adapted to IServiceService,
+ and this adapter's 'Adapters' service is used.
+ """
+
+ def queryAdapterInContext(object, interface, context, default=None):
+ """Look for a special adapter to an interface for an object
+
+ NOTE: This method should only be used if a custom context
+ needs to be provided to provide custom component
+ lookup. Otherwise, call the interface, as in::
+
+ interface(object, default)
+
+ Returns an adapter that can adapt object to interface. If a matching
+ adapter cannot be found, returns the default.
+
+ Context is adapted to IServiceService, and this adapter's
+ 'Adapters' service is used.
+
+ If the object has a __conform__ method, this method will be
+ called with the requested interface. If the method returns a
+ non-None value, that value will be returned. Otherwise, if the
+ object already implements the interface, the object will be
+ returned.
+ """
+
+ def queryMultiAdapter(objects,
+ interface=Interface, name=u'',
+ default=None,
+ context=None):
+ """Look for a multi-adapter to an interface for objects
+
+ Returns a multi-adapter that can adapt objects to interface. If a
+ matching adapter cannot be found, returns the default.
+
+ If context is None, an application-defined policy is used to choose
+ an appropriate service manager from which to get an 'Adapters' service.
+
+ If 'context' is not None, context is adapted to IServiceService,
+ and this adapter's 'Adapters' service is used.
+
+ The name consisting of an empty string is reserved for unnamed
+ adapters. The unnamed adapter methods will often call the
+ named adapter methods with an empty string for a name.
+ """
+
+ def getAdapters(objects, provided, context=None):
+ """Look for all matching adapters to a provided interface for objects
+
+ Return a list of adapters that match. If an adapter is named, only the
+ most specific adapter of a given name is returned.
+
+ If context is None, an application-defined policy is used to choose
+ an appropriate service manager from which to get an 'Adapters'
+ service.
+
+ If 'context' is not None, context is adapted to IServiceService,
+ and this adapter's 'Adapters' service is used.
+ """
+
+ def subscribers(required, provided, context=None):
+ """Get subscribers
+
+ Subscribers are returned that provide the provided interface
+ and that depend on and are computed from the sequence of
+ required objects.
+
+ If context is None, an application-defined policy is used to choose
+ an appropriate service manager from which to get an 'Adapters'
+ service.
+
+ If 'context' is not None, context is adapted to IServiceService,
+ and this adapter's 'Adapters' service is used.
+ """
+
+ def handle(*objects):
+ """Call all of the handlers for the given objects
+
+ Handlers are subscription adapter factories that don't produce
+ anything. They do all of their work when called. Handlers
+ are typically used to handle events.
+
+ """
+
+
+ def adapts(*interfaces):
+ """Declare that a class adapts the given interfaces.
+
+ This function can only be used in a class definition.
+
+ (TODO, allow classes to be passed as well as interfaces.)
+ """
+
+ # Factory service
+
+ def createObject(factory_name, *args, **kwargs):
+ """Create an object using a factory
+
+ Finds the named factory in the current site and calls it with
+ the given arguments. If a matching factory cannot be found
+ raises ComponentLookupError. Returns the created object.
+
+ A context keyword argument can be provided to cause the
+ factory to be looked up in a location other than the current
+ site. (Of course, this means that it is impossible to pass a
+ keyword argument named "context" to the factory.
+ """
+
+ def getFactoryInterfaces(name, context=None):
+ """Get interfaces implemented by a factory
+
+ Finds the factory of the given name that is nearest to the
+ context, and returns the interface or interface tuple that
+ object instances created by the named factory will implement.
+ """
+
+ def getFactoriesFor(interface, context=None):
+ """Return a tuple (name, factory) of registered factories that
+ create objects which implement the given interface.
+ """
+
+class IComponentLookup(Interface):
+ """Component Manager for a Site
+
+ This object manages the components registered at a particular site. The
+ definition of a site is intentionally vague.
+ """
+
+ adapters = Attribute(
+ "Adapter Registry to manage all registered adapters.")
+
+ utilities = Attribute(
+ "Adapter Registry to manage all registered utilities.")
+
+ def queryAdapter(object, interface, name=u'', default=None):
+ """Look for a named adapter to an interface for an object
+
+ If a matching adapter cannot be found, returns the default.
+ """
+
+ def getAdapter(object, interface, name=u''):
+ """Look for a named adapter to an interface for an object
+
+ If a matching adapter cannot be found, a ComponentLookupError
+ is raised.
+ """
+
+ def queryMultiAdapter(objects, interface, name=u'', default=None):
+ """Look for a multi-adapter to an interface for multiple objects
+
+ If a matching adapter cannot be found, returns the default.
+ """
+
+ def getMultiAdapter(objects, interface, name=u''):
+ """Look for a multi-adapter to an interface for multiple objects
+
+ If a matching adapter cannot be found, a ComponentLookupError
+ is raised.
+ """
+
+ def getAdapters(objects, provided):
+ """Look for all matching adapters to a provided interface for objects
+
+ Return an iterable of name-adapter pairs for adapters that
+ provide the given interface.
+ """
+
+ def subscribers(objects, provided):
+ """Get subscribers
+
+ Subscribers are returned that provide the provided interface
+ and that depend on and are comuted from the sequence of
+ required objects.
+ """
+
+ def handle(*objects):
+ """Call handlers for the given objects
+
+ Handlers registered for the given objects are called.
+ """
+
+ def queryUtility(interface, name='', default=None):
+ """Look up a utility that provides an interface.
+
+ If one is not found, returns default.
+ """
+
+ def getUtilitiesFor(interface):
+ """Look up the registered utilities that provide an interface.
+
+ Returns an iterable of name-utility pairs.
+ """
+
+ def getAllUtilitiesRegisteredFor(interface):
+ """Return all registered utilities for an interface
+
+ This includes overridden utilities.
+
+ An iterable of utility instances is returned. No names are
+ returned.
+ """
+
+class IComponentRegistrationConvenience(Interface):
+ """API for registering components.
+
+ CAUTION: This API should only be used from test or
+ application-setup code. This api shouldn't be used by regular
+ library modules, as component registration is a configuration
+ activity.
+ """
+
+ def provideUtility(component, provides=None, name=u''):
+ """Register a utility globally
+
+ A utility is registered to provide an interface with a
+ name. If a component provides only one interface, then the
+ provides argument can be omitted and the provided interface
+ will be used. (In this case, provides argument can still be
+ provided to provide a less specific interface.)
+
+ CAUTION: This API should only be used from test or
+ application-setup code. This API shouldn't be used by regular
+ library modules, as component registration is a configuration
+ activity.
+
+ """
+
+ def provideAdapter(factory, adapts=None, provides=None, name=u''):
+ """Register an adapter globally
+
+ An adapter is registered to provide an interface with a name
+ for some number of object types. If a factory implements only
+ one interface, then the provides argument can be omitted and
+ the provided interface will be used. (In this case, a provides
+ argument can still be provided to provide a less specific
+ interface.)
+
+ If the factory has an adapts declaration, then the adapts
+ argument can be omitted and the declaration will be used. (An
+ adapts argument can be provided to override the declaration.)
+
+ CAUTION: This API should only be used from test or
+ application-setup code. This API shouldn't be used by regular
+ library modules, as component registration is a configuration
+ activity.
+ """
+
+ def provideSubscriptionAdapter(factory, adapts=None, provides=None):
+ """Register a subscription adapter
+
+ A subscription adapter is registered to provide an interface
+ for some number of object types. If a factory implements only
+ one interface, then the provides argument can be omitted and
+ the provided interface will be used. (In this case, a provides
+ argument can still be provided to provide a less specific
+ interface.)
+
+ If the factory has an adapts declaration, then the adapts
+ argument can be omitted and the declaration will be used. (An
+ adapts argument can be provided to override the declaration.)
+
+ CAUTION: This API should only be used from test or
+ application-setup code. This API shouldn't be used by regular
+ library modules, as component registration is a configuration
+ activity.
+ """
+
+ def provideHandler(handler, adapts=None):
+ """Register a handler
+
+ Handlers are subscription adapter factories that don't produce
+ anything. They do all of their work when called. Handlers
+ are typically used to handle events.
+
+ If the handler has an adapts declaration, then the adapts
+ argument can be omitted and the declaration will be used. (An
+ adapts argument can be provided to override the declaration.)
+
+ CAUTION: This API should only be used from test or
+ application-setup code. This API shouldn't be used by regular
+ library modules, as component registration is a configuration
+ activity.
+ """
+
+class IRegistry(Interface):
+ """Object that supports component registry
+ """
+
+ def registrations():
+ """Return an iterable of component registrations
+ """
+
+class IFactory(Interface):
+ """A factory is responsible for creating other components."""
+
+ title = Attribute("The factory title.")
+
+ description = Attribute("A brief description of the factory.")
+
+ def __call__(*args, **kw):
+ """Return an instance of the objects we're a factory for."""
+
+
+ def getInterfaces():
+ """Get the interfaces implemented by the factory
+
+ Return the interface(s), as an instance of Implements, that objects
+ created by this factory will implement. If the callable's Implements
+ instance cannot be created, an empty Implements instance is returned.
+ """
+
+class IRegistration(Interface):
+ """A registration-information object
+ """
+
+ registry = Attribute("The registry having the registration")
+
+ name = Attribute("The registration name")
+
+ info = Attribute("""Information about the registration
+
+ This is information deemed useful to people browsing the
+ configuration of a system. It could, for example, include
+ commentary or information about the source of the configuration.
+ """)
+
+class IUtilityRegistration(IRegistration):
+ """Information about the registration of a utility
+ """
+
+ factory = Attribute("The factory used to create the utility. Optional.")
+ component = Attribute("The object registered")
+ provided = Attribute("The interface provided by the component")
+
+class _IBaseAdapterRegistration(IRegistration):
+ """Information about the registration of an adapter
+ """
+
+ factory = Attribute("The factory used to create adapters")
+
+ required = Attribute("""The adapted interfaces
+
+ This is a sequence of interfaces adapters by the registered
+ factory. The factory will be caled with a sequence of objects, as
+ positional arguments, that provide these interfaces.
+ """)
+
+ provided = Attribute("""The interface provided by the adapters.
+
+ This interface is implemented by the factory
+ """)
+
+class IAdapterRegistration(_IBaseAdapterRegistration):
+ """Information about the registration of an adapter
+ """
+
+class ISubscriptionAdapterRegistration(_IBaseAdapterRegistration):
+ """Information about the registration of a subscription adapter
+ """
+
+class IHandlerRegistration(IRegistration):
+
+ handler = Attribute("An object called used to handle an event")
+
+ required = Attribute("""The handled interfaces
+
+ This is a sequence of interfaces handled by the registered
+ handler. The handler will be caled with a sequence of objects, as
+ positional arguments, that provide these interfaces.
+ """)
+
+class IRegistrationEvent(IObjectEvent):
+ """An event that involves a registration"""
+
+class RegistrationEvent(ObjectEvent):
+ """There has been a change in a registration
+ """
+ implements(IRegistrationEvent)
+
+ def __repr__(self):
+ return "%s event:\n%r" % (self.__class__.__name__, self.object)
+
+class IRegistered(IRegistrationEvent):
+ """A component or factory was registered
+ """
+
+class Registered(RegistrationEvent):
+ implements(IRegistered)
+
+class IUnregistered(IRegistrationEvent):
+ """A component or factory was unregistered
+ """
+
+class Unregistered(RegistrationEvent):
+ """A component or factory was unregistered
+ """
+ implements(IUnregistered)
+
+class IComponentRegistry(Interface):
+ """Register components
+ """
+
+ def registerUtility(component=None, provided=None, name=u'', info=u'', factory=None):
+ """Register a utility
+
+ factory
+ Factory for the component to be registerd.
+
+ component
+ The registered component
+
+ provided
+ This is the interface provided by the utility. If the
+ component provides a single interface, then this
+ argument is optional and the component-implemented
+ interface will be used.
+
+ name
+ The utility name.
+
+ info
+ An object that can be converted to a string to provide
+ information about the registration.
+
+ Only one of component and factory can be used.
+ A Registered event is generated with an IUtilityRegistration.
+ """
+
+ def unregisterUtility(component=None, provided=None, name=u'', factory=None):
+ """Unregister a utility
+
+ A boolean is returned indicating whether the registry was
+ changed. If the given component is None and there is no
+ component registered, or if the given component is not
+ None and is not registered, then the function returns
+ False, otherwise it returns True.
+
+ factory
+ Factory for the component to be unregisterd.
+
+ component
+ The registered component The given component can be
+ None, in which case any component registered to provide
+ the given provided interface with the given name is
+ unregistered.
+
+ provided
+ This is the interface provided by the utility. If the
+ component is not None and provides a single interface,
+ then this argument is optional and the
+ component-implemented interface will be used.
+
+ name
+ The utility name.
+
+ Only one of component and factory can be used.
+ An UnRegistered event is generated with an IUtilityRegistration.
+ """
+
+ def registeredUtilities():
+ """Return an iterable of IUtilityRegistration instances.
+
+ These registrations describe the current utility registrations
+ in the object.
+ """
+
+ def registerAdapter(factory, required=None, provided=None, name=u'',
+ info=u''):
+ """Register an adapter factory
+
+ Parameters:
+
+ factory
+ The object used to compute the adapter
+
+ required
+ This is a sequence of specifications for objects to be
+ adapted. If omitted, then the value of the factory's
+ __component_adapts__ attribute will be used. The
+ __component_adapts__ attribute is usually attribute is
+ normally set in class definitions using adapts
+ function, or for callables using the adapter
+ decorator. If the factory doesn't have a
+ __component_adapts__ adapts attribute, then this
+ argument is required.
+
+ provided
+ This is the interface provided by the adapter and
+ implemented by the factory. If the factory
+ implements a single interface, then this argument is
+ optional and the factory-implemented interface will be
+ used.
+
+ name
+ The adapter name.
+
+ info
+ An object that can be converted to a string to provide
+ information about the registration.
+
+ A Registered event is generated with an IAdapterRegistration.
+ """
+
+ def unregisterAdapter(factory=None, required=None,
+ provided=None, name=u''):
+ """Register an adapter factory
+
+ A boolean is returned indicating whether the registry was
+ changed. If the given component is None and there is no
+ component registered, or if the given component is not
+ None and is not registered, then the function returns
+ False, otherwise it returns True.
+
+ Parameters:
+
+ factory
+ This is the object used to compute the adapter. The
+ factory can be None, in which case any factory
+ registered to implement the given provided interface
+ for the given required specifications with the given
+ name is unregistered.
+
+ required
+ This is a sequence of specifications for objects to be
+ adapted. If the factory is not None and the required
+ arguments is omitted, then the value of the factory's
+ __component_adapts__ attribute will be used. The
+ __component_adapts__ attribute attribute is normally
+ set in class definitions using adapts function, or for
+ callables using the adapter decorator. If the factory
+ is None or doesn't have a __component_adapts__ adapts
+ attribute, then this argument is required.
+
+ provided
+ This is the interface provided by the adapter and
+ implemented by the factory. If the factory is not
+ None and implements a single interface, then this
+ argument is optional and the factory-implemented
+ interface will be used.
+
+ name
+ The adapter name.
+
+ An Unregistered event is generated with an IAdapterRegistration.
+ """
+
+ def registeredAdapters():
+ """Return an iterable of IAdapterRegistration instances.
+
+ These registrations describe the current adapter registrations
+ in the object.
+ """
+
+ def registerSubscriptionAdapter(factory, required=None, provides=None,
+ name=u'', info=''):
+ """Register a subscriber factory
+
+ Parameters:
+
+ factory
+ The object used to compute the adapter
+
+ required
+ This is a sequence of specifications for objects to be
+ adapted. If omitted, then the value of the factory's
+ __component_adapts__ attribute will be used. The
+ __component_adapts__ attribute is usually attribute is
+ normally set in class definitions using adapts
+ function, or for callables using the adapter
+ decorator. If the factory doesn't have a
+ __component_adapts__ adapts attribute, then this
+ argument is required.
+
+ provided
+ This is the interface provided by the adapter and
+ implemented by the factory. If the factory implements
+ a single interface, then this argument is optional and
+ the factory-implemented interface will be used.
+
+ name
+ The adapter name.
+
+ Currently, only the empty string is accepted. Other
+ strings will be accepted in the future when support for
+ named subscribers is added.
+
+ info
+ An object that can be converted to a string to provide
+ information about the registration.
+
+ A Registered event is generated with an
+ ISubscriptionAdapterRegistration.
+ """
+
+ def unregisterSubscriptionAdapter(factory=None, required=None,
+ provides=None, name=u''):
+ """Unregister a subscriber factory.
+
+ A boolean is returned indicating whether the registry was
+ changed. If the given component is None and there is no
+ component registered, or if the given component is not
+ None and is not registered, then the function returns
+ False, otherwise it returns True.
+
+ Parameters:
+
+ factory
+ This is the object used to compute the adapter. The
+ factory can be None, in which case any factories
+ registered to implement the given provided interface
+ for the given required specifications with the given
+ name are unregistered.
+
+ required
+ This is a sequence of specifications for objects to be
+ adapted. If the factory is not None and the required
+ arguments is omitted, then the value of the factory's
+ __component_adapts__ attribute will be used. The
+ __component_adapts__ attribute attribute is normally
+ set in class definitions using adapts function, or for
+ callables using the adapter decorator. If the factory
+ is None or doesn't have a __component_adapts__ adapts
+ attribute, then this argument is required.
+
+ provided
+ This is the interface provided by the adapter and
+ implemented by the factory. If the factory is not
+ None implements a single interface, then this argument
+ is optional and the factory-implemented interface will
+ be used.
+
+ name
+ The adapter name.
+
+ Currently, only the empty string is accepted. Other
+ strings will be accepted in the future when support for
+ named subscribers is added.
+
+ An Unregistered event is generated with an
+ ISubscriptionAdapterRegistration.
+ """
+
+ def registeredSubscriptionAdapters():
+ """Return an iterable of ISubscriptionAdapterRegistration instances.
+
+ These registrations describe the current subscription adapter
+ registrations in the object.
+ """
+
+ def registerHandler(handler, required=None, name=u'', info=''):
+ """Register a handler.
+
+ A handler is a subscriber that doesn't compute an adapter
+ but performs some function when called.
+
+ Parameters:
+
+ handler
+ The object used to handle some event represented by
+ the objects passed to it.
+
+ required
+ This is a sequence of specifications for objects to be
+ adapted. If omitted, then the value of the factory's
+ __component_adapts__ attribute will be used. The
+ __component_adapts__ attribute is usually attribute is
+ normally set in class definitions using adapts
+ function, or for callables using the adapter
+ decorator. If the factory doesn't have a
+ __component_adapts__ adapts attribute, then this
+ argument is required.
+
+ name
+ The handler name.
+
+ Currently, only the empty string is accepted. Other
+ strings will be accepted in the future when support for
+ named handlers is added.
+
+ info
+ An object that can be converted to a string to provide
+ information about the registration.
+
+
+ A Registered event is generated with an IHandlerRegistration.
+ """
+
+ def unregisterHandler(handler=None, required=None, name=u''):
+ """Unregister a handler.
+
+ A handler is a subscriber that doesn't compute an adapter
+ but performs some function when called.
+
+ A boolean is returned indicating whether the registry was
+ changed.
+
+ Parameters:
+
+ handler
+ This is the object used to handle some event
+ represented by the objects passed to it. The handler
+ can be None, in which case any handlers registered for
+ the given required specifications with the given are
+ unregistered.
+
+ required
+ This is a sequence of specifications for objects to be
+ adapted. If omitted, then the value of the factory's
+ __component_adapts__ attribute will be used. The
+ __component_adapts__ attribute is usually attribute is
+ normally set in class definitions using adapts
+ function, or for callables using the adapter
+ decorator. If the factory doesn't have a
+ __component_adapts__ adapts attribute, then this
+ argument is required.
+
+ name
+ The handler name.
+
+ Currently, only the empty string is accepted. Other
+ strings will be accepted in the future when support for
+ named handlers is added.
+
+ An Unregistered event is generated with an IHandlerRegistration.
+ """
+
+ def registeredHandlers():
+ """Return an iterable of IHandlerRegistration instances.
+
+ These registrations describe the current handler registrations
+ in the object.
+ """
+
+
+class IComponents(IComponentLookup, IComponentRegistry):
+ """Component registration and access
+ """
+
+
+class IPossibleSite(Interface):
+ """An object that could be a site.
+ """
+
+ def setSiteManager(sitemanager):
+ """Sets the site manager for this object.
+ """
+
+ def getSiteManager():
+ """Returns the site manager contained in this object.
+
+ If there isn't a site manager, raise a component lookup.
+ """
+
+
+class ISite(IPossibleSite):
+ """Marker interface to indicate that we have a site"""
Added: Sandbox/chrism/zope.registry/src/zope/registry/registry.txt
===================================================================
--- Sandbox/chrism/zope.registry/src/zope/registry/registry.txt (rev 0)
+++ Sandbox/chrism/zope.registry/src/zope/registry/registry.txt 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,990 @@
+Component-Management objects
+============================
+
+Component-management objects provide a higher-level
+component-management API over the basic adapter-registration API
+provided by the zope.interface package. In particular, it provides:
+
+- utilities
+
+- support for computing adapters, rather than just looking up adapter
+ factories.
+
+- management of registration comments
+
+The zope.registry.Components class provides an
+implementation of zope.registry.interfaces.IComponents that provides
+these features.
+
+ >>> from zope import registry
+ >>> from zope.registry import tests
+ >>> components = registry.Components('comps')
+
+As components are registered, events are generated. Let's register
+an event subscriber, so we can see the events generated:
+
+ >>> import zope.event
+ >>> def logevent(event):
+ ... print event
+ >>> zope.event.subscribers.append(logevent)
+
+Utilities
+---------
+
+You can register Utilities using registerUtility:
+
+ >>> components.registerUtility(tests.U1(1))
+ Registered event:
+ UtilityRegistration(<Components comps>, I1, u'', 1, None, u'')
+
+Here we didn't specify an interface or name. An unnamed utility was
+registered for interface I1, since that is only interface implemented
+by the U1 class:
+
+ >>> components.getUtility(tests.I1)
+ U1(1)
+
+You can also register a utility using a factory instead of a utility instance:
+
+ >>> def factory():
+ ... return tests.U1(1)
+ >>> components.registerUtility(factory=factory)
+ Unregistered event:
+ UtilityRegistration(<Components comps>, I1, u'', 1, None, u'')
+ Registered event:
+ UtilityRegistration(<Components comps>, I1, u'', 1, <function factory at <SOME ADDRESS>>, u'')
+
+
+If a component implements other than one interface or no interface,
+then an error will be raised:
+
+ >>> components.registerUtility(tests.U12(2))
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The utility doesn't provide a single interface and
+ no provided interface was specified.
+
+ >>> components.registerUtility(tests.A)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The utility doesn't provide a single interface and
+ no provided interface was specified.
+
+
+We can provide an interface if desired:
+
+ >>> components.registerUtility(tests.U12(2), tests.I2)
+ Registered event:
+ UtilityRegistration(<Components comps>, I2, u'', 2, None, u'')
+
+and we can specify a name:
+
+ >>> components.registerUtility(tests.U12(3), tests.I2, u'three')
+ Registered event:
+ UtilityRegistration(<Components comps>, I2, u'three', 3, None, u'')
+
+ >>> components.getUtility(tests.I2)
+ U12(2)
+
+ >>> components.getUtility(tests.I2, 'three')
+ U12(3)
+
+If you try to get a utility that doesn't exist, you'll get a component
+lookup error:
+
+ >>> components.getUtility(tests.I3)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError:
+ (<InterfaceClass zope.registry.tests.I3>, u'')
+
+Unless you use queryUtility:
+
+ >>> components.queryUtility(tests.I3)
+ >>> components.queryUtility(tests.I3, default=42)
+ 42
+
+You can get information about registered utilities with the
+registeredUtilities method:
+
+ >>> for registration in sorted(components.registeredUtilities()):
+ ... print registration.provided, registration.name
+ ... print registration.component, registration.info
+ <InterfaceClass zope.registry.tests.I1>
+ U1(1)
+ <InterfaceClass zope.registry.tests.I2>
+ U12(2)
+ <InterfaceClass zope.registry.tests.I2> three
+ U12(3)
+
+Duplicate registrations replace existing ones:
+
+ >>> components.registerUtility(tests.U1(4), info=u'use 4 now')
+ Unregistered event:
+ UtilityRegistration(<Components comps>, I1, u'', 1, <function factory at <SOME ADDRESS>>, u'')
+ Registered event:
+ UtilityRegistration(<Components comps>, I1, u'', 4, None, u'use 4 now')
+ >>> components.getUtility(tests.I1)
+ U1(4)
+
+ >>> for registration in sorted(components.registeredUtilities()):
+ ... print registration.provided, registration.name
+ ... print registration.component, registration.info
+ <InterfaceClass zope.registry.tests.I1>
+ U1(4) use 4 now
+ <InterfaceClass zope.registry.tests.I2>
+ U12(2)
+ <InterfaceClass zope.registry.tests.I2> three
+ U12(3)
+
+As shown in the this example, you can provide an "info" argumemnt when
+registering utilities. This provides extra documentation about the
+registration itself that is shown when listing registrations.
+
+You can also unregister utilities:
+
+ >>> components.unregisterUtility(provided=tests.I1)
+ Unregistered event:
+ UtilityRegistration(<Components comps>, I1, u'', 4, None, u'use 4 now')
+ True
+
+A boolean is returned indicating whether anything changed:
+
+ >>> components.queryUtility(tests.I1)
+ >>> for registration in sorted(components.registeredUtilities()):
+ ... print registration.provided, registration.name
+ ... print registration.component, registration.info
+ <InterfaceClass zope.registry.tests.I2>
+ U12(2)
+ <InterfaceClass zope.registry.tests.I2> three
+ U12(3)
+
+When you unregister, you can specify a component. If the component
+doesn't match the one registered, then nothing happens:
+
+ >>> u5 = tests.U1(5)
+ >>> components.registerUtility(u5)
+ Registered event:
+ UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+ >>> components.unregisterUtility(tests.U1(6))
+ False
+ >>> components.queryUtility(tests.I1)
+ U1(5)
+ >>> components.unregisterUtility(u5)
+ Unregistered event:
+ UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+ True
+ >>> components.queryUtility(tests.I1)
+
+You can get the name and utility for all of the utilities that provide
+an interface using getUtilitiesFor:
+
+ >>> sorted(components.getUtilitiesFor(tests.I2))
+ [(u'', U12(2)), (u'three', U12(3))]
+
+getAllUtilitiesRegisteredFor is similar to getUtilitiesFor except that
+it includes utilities that are overridden. For example, we'll
+register a utility that for an extending interface of I2:
+
+ >>> util = tests.U('ext')
+ >>> components.registerUtility(util, tests.I2e)
+ Registered event:
+ UtilityRegistration(<Components comps>, I2e, u'', ext, None, u'')
+
+We don't get the new utility for getUtilitiesFor:
+
+ >>> sorted(components.getUtilitiesFor(tests.I2))
+ [(u'', U12(2)), (u'three', U12(3))]
+
+but we do get it from getAllUtilitiesRegisteredFor:
+
+ >>> sorted(map(str, components.getAllUtilitiesRegisteredFor(tests.I2)))
+ ['U(ext)', 'U12(2)', 'U12(3)']
+
+Removing a utility also makes it disappear from getUtilitiesFor:
+
+ >>> components.unregisterUtility(util, tests.I2e)
+ Unregistered event:
+ UtilityRegistration(<Components comps>, I2e, u'', ext, None, u'')
+ True
+ >>> list(components.getAllUtilitiesRegisteredFor(tests.I2e))
+ []
+
+Adapters
+--------
+
+You can register adapters with registerAdapter:
+
+ >>> components.registerAdapter(tests.A12_1)
+ Registered event:
+ AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+
+Here, we didn't specify required interfaces, a provided interface, or
+a name. The required interfaces were determined from the factory
+s __component_adapts__ attribute and the provided interface was
+determined by introspecting what the factory implements.
+
+ >>> components.getMultiAdapter((tests.U1(6), tests.U12(7)), tests.IA1)
+ A12_1(U1(6), U12(7))
+
+If a factory implements more than one interface, an exception will be
+raised:
+
+ >>> components.registerAdapter(tests.A1_12)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't implement a single
+ interface and no provided interface was specified.
+
+Unless the provided interface is specified:
+
+ >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
+ Registered event:
+ AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+
+If a factory doesn't declare an implemented interface, an exception will be
+raised:
+
+ >>> components.registerAdapter(tests.A12_)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't implement a single
+ interface and no provided interface was specified.
+
+Unless the provided interface is specified:
+
+ >>> components.registerAdapter(tests.A12_, provided=tests.IA2)
+ Registered event:
+ AdapterRegistration(<Components comps>, [I1, I2], IA2, u'', A12_, u'')
+
+The required interface needs to be specified in the registration if
+the factory doesn't have a __component_adapts__ attribute:
+
+ >>> components.registerAdapter(tests.A_2)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't have a __component_adapts__
+ attribute and no required specifications were specified
+
+Unless the required specifications specified:
+
+ >>> components.registerAdapter(tests.A_2, required=[tests.I3])
+ Registered event:
+ AdapterRegistration(<Components comps>, [I3], IA2, u'', A_2, u'')
+
+Classes can be specified in place of specifications, in which case the
+implementedBy specification for the class is used:
+
+ >>> components.registerAdapter(tests.A_3, required=[tests.U],
+ ... info="Really class specific")
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Registered event:
+ AdapterRegistration(<Components comps>, [zope.registry.tests.U], IA3, u'',
+ A_3, 'Really class specific')
+
+We can see the adapters that have been registered using the
+registeredAdapters method:
+
+ >>> for registration in sorted(components.registeredAdapters()):
+ ... print registration.required
+ ... print registration.provided, registration.name
+ ... print registration.factory, registration.info
+ ... # doctest: +NORMALIZE_WHITESPACE
+ (<InterfaceClass zope.registry.tests.I1>,
+ <InterfaceClass zope.registry.tests.I2>)
+ <InterfaceClass zope.registry.tests.IA1>
+ zope.registry.tests.A12_1
+ (<InterfaceClass zope.registry.tests.I1>,
+ <InterfaceClass zope.registry.tests.I2>)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A12_
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A1_12
+ (<InterfaceClass zope.registry.tests.I3>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A_2
+ (<implementedBy zope.registry.tests.U>,)
+ <InterfaceClass zope.registry.tests.IA3>
+ zope.registry.tests.A_3 Really class specific
+
+As with utilities, we can provide registration information when
+registering adapters.
+
+If you try to fetch an adapter that isn't registered, you'll get a
+component-lookup error:
+
+ >>> components.getMultiAdapter((tests.U(8), ), tests.IA1)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError: ((U(8),),
+ <InterfaceClass zope.registry.tests.IA1>, u'')
+
+unless you use queryAdapter:
+
+ >>> components.queryMultiAdapter((tests.U(8), ), tests.IA1)
+ >>> components.queryMultiAdapter((tests.U(8), ), tests.IA1, default=42)
+ 42
+
+When looking up an adapter for a single object, you can use the
+slightly simpler getAdapter and queryAdapter calls:
+
+ >>> components.getAdapter(tests.U1(9), tests.IA2)
+ A1_12(U1(9))
+
+ >>> components.queryAdapter(tests.U1(9), tests.IA2)
+ A1_12(U1(9))
+
+ >>> components.getAdapter(tests.U(8), tests.IA1)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError: (U(8),
+ <InterfaceClass zope.registry.tests.IA1>, u'')
+
+ >>> components.queryAdapter(tests.U(8), tests.IA2)
+ >>> components.queryAdapter(tests.U(8), tests.IA2, default=42)
+ 42
+
+You can unregister an adapter. If a factory is provided and if the
+rewuired and provided interfaces, can be infered, then they need not
+be provided:
+
+ >>> components.unregisterAdapter(tests.A12_1)
+ Unregistered event:
+ AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+ True
+
+ >>> for registration in sorted(components.registeredAdapters()):
+ ... print registration.required
+ ... print registration.provided, registration.name
+ ... print registration.factory, registration.info
+ ... # doctest: +NORMALIZE_WHITESPACE
+ (<InterfaceClass zope.registry.tests.I1>,
+ <InterfaceClass zope.registry.tests.I2>)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A12_
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A1_12
+ (<InterfaceClass zope.registry.tests.I3>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A_2
+ (<implementedBy zope.registry.tests.U>,)
+ <InterfaceClass zope.registry.tests.IA3>
+ zope.registry.tests.A_3 Really class specific
+
+A boolean is returned indicating whether a change was made.
+
+If a factory implements more than one interface, an exception will be
+raised:
+
+ >>> components.unregisterAdapter(tests.A1_12)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't implement a single
+ interface and no provided interface was specified.
+
+Unless the provided interface is specified:
+
+ >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2)
+ Unregistered event:
+ AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+ True
+
+If a factory doesn't declare an implemented interface, an exception will be
+raised:
+
+ >>> components.unregisterAdapter(tests.A12_)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't implement a single
+ interface and no provided interface was specified.
+
+Unless the provided interface is specified:
+
+ >>> components.unregisterAdapter(tests.A12_, provided=tests.IA2)
+ Unregistered event:
+ AdapterRegistration(<Components comps>, [I1, I2], IA2, u'', A12_, u'')
+ True
+
+The required interface needs to be specified if the factory doesn't
+have a __component_adapts__ attribute:
+
+ >>> components.unregisterAdapter(tests.A_2)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't have a __component_adapts__
+ attribute and no required specifications were specified
+
+ >>> components.unregisterAdapter(tests.A_2, required=[tests.I3])
+ Unregistered event:
+ AdapterRegistration(<Components comps>, [I3], IA2, u'', A_2, u'')
+ True
+
+ >>> for registration in sorted(components.registeredAdapters()):
+ ... print registration.required
+ ... print registration.provided, registration.name
+ ... print registration.factory, registration.info
+ ... # doctest: +NORMALIZE_WHITESPACE
+ (<implementedBy zope.registry.tests.U>,)
+ <InterfaceClass zope.registry.tests.IA3>
+ zope.registry.tests.A_3 Really class specific
+
+If a factory is unregistered that is not registered, False is
+returned:
+
+
+ >>> components.unregisterAdapter(tests.A_2, required=[tests.I3])
+ False
+ >>> components.unregisterAdapter(tests.A12_1, required=[tests.U])
+ False
+
+The factory can be omitted, to unregister *any* factory that matches
+specified required and provided interfaces:
+
+ >>> components.unregisterAdapter(required=[tests.U], provided=tests.IA3)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Unregistered event:
+ AdapterRegistration(<Components comps>, [zope.registry.tests.U],
+ IA3, u'', A_3, 'Really class specific')
+ True
+
+ >>> for registration in sorted(components.registeredAdapters()):
+ ... print registration
+
+Adapters can be named:
+
+ >>> components.registerAdapter(tests.A1_12, provided=tests.IA2,
+ ... name=u'test')
+ Registered event:
+ AdapterRegistration(<Components comps>, [I1], IA2, u'test', A1_12, u'')
+
+ >>> components.queryMultiAdapter((tests.U1(9), ), tests.IA2)
+ >>> components.queryMultiAdapter((tests.U1(9), ), tests.IA2, name=u'test')
+ A1_12(U1(9))
+
+ >>> components.queryAdapter(tests.U1(9), tests.IA2)
+ >>> components.queryAdapter(tests.U1(9), tests.IA2, name=u'test')
+ A1_12(U1(9))
+ >>> components.getAdapter(tests.U1(9), tests.IA2, name=u'test')
+ A1_12(U1(9))
+
+It is possible to look up all of the adapters that provide an
+interface:
+
+ >>> components.registerAdapter(tests.A1_23, provided=tests.IA2,
+ ... name=u'test 2')
+ Registered event:
+ AdapterRegistration(<Components comps>, [I1], IA2, u'test 2', A1_23, u'')
+
+ >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
+ Registered event:
+ AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+
+ >>> for name, adapter in sorted(components.getAdapters((tests.U1(9), ),
+ ... tests.IA2)):
+ ... print name, adapter
+ A1_12(U1(9))
+ test A1_12(U1(9))
+ test 2 A1_23(U1(9))
+
+
+getAdapters is most commonly used as the basis of menu systems.
+
+If an adapter factory returns None, it is equivalent to there being no
+factory:
+
+ >>> components.registerAdapter(tests.noop,
+ ... required=[tests.IA1], provided=tests.IA2,
+ ... name=u'test noop')
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Registered event:
+ AdapterRegistration(<Components comps>, [IA1], IA2, u'test noop',
+ noop, u'')
+ >>> components.queryAdapter(tests.U1(9), tests.IA2, name=u'test noop')
+
+ >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
+ Registered event:
+ AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+
+ >>> for name, adapter in sorted(components.getAdapters((tests.U1(9), ),
+ ... tests.IA2)):
+ ... print name, adapter
+ A1_12(U1(9))
+ test A1_12(U1(9))
+ test 2 A1_23(U1(9))
+
+
+ >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2,
+ ... name=u'test')
+ Unregistered event:
+ AdapterRegistration(<Components comps>, [I1], IA2, u'test', A1_12, u'')
+ True
+ >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2)
+ Unregistered event:
+ AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+ True
+ >>> for registration in sorted(components.registeredAdapters()):
+ ... print registration.required
+ ... print registration.provided, registration.name
+ ... print registration.factory, registration.info
+ ... # doctest: +NORMALIZE_WHITESPACE
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2> test 2
+ zope.registry.tests.A1_23
+ (<InterfaceClass zope.registry.tests.IA1>,)
+ <InterfaceClass zope.registry.tests.IA2> test noop
+ <function noop at 0xb79a1064>
+
+
+Subscribers
+-----------
+
+Subscribers provide a way to get multiple adapters of a given type.
+In this regard, subscribers are like named adapters, except that there
+isn't any concept of the most specific adapter for a given name.
+
+Subscribers are registered by calling registerSubscriptionAdapter:
+
+ >>> components.registerSubscriptionAdapter(tests.A1_2)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Registered event:
+ SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+
+ >>> components.registerSubscriptionAdapter(
+ ... tests.A1_12, provided=tests.IA2)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Registered event:
+ SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+
+ >>> components.registerSubscriptionAdapter(
+ ... tests.A, [tests.I1], tests.IA2,
+ ... info='a sample comment')
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Registered event:
+ SubscriptionRegistration(<Components comps>, [I1], IA2, u'',
+ A, 'a sample comment')
+
+The same rules, with regard to when required and provided interfaces
+have to be specified apply as with adapters:
+
+ >>> components.registerSubscriptionAdapter(tests.A1_12)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't implement a single
+ interface and no provided interface was specified.
+
+ >>> components.registerSubscriptionAdapter(tests.A)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't implement a single interface and
+ no provided interface was specified.
+
+ >>> components.registerSubscriptionAdapter(tests.A, required=[tests.IA1])
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't implement a single interface
+ and no provided interface was specified.
+
+Note that we provided the info argument as a keyword argument above.
+That's because there is a name argument that's reserved for future
+use. We can give a name, as long as it is an empty string:
+
+ >>> components.registerSubscriptionAdapter(
+ ... tests.A, [tests.I1], tests.IA2, u'', 'a sample comment')
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Registered event:
+ SubscriptionRegistration(<Components comps>, [I1], IA2, u'',
+ A, 'a sample comment')
+
+ >>> components.registerSubscriptionAdapter(
+ ... tests.A, [tests.I1], tests.IA2, u'oops', 'a sample comment')
+ Traceback (most recent call last):
+ ...
+ TypeError: Named subscribers are not yet supported
+
+Subscribers are looked up using the subscribers method:
+
+ >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
+ ... print s
+ A1_2(U1(1))
+ A1_12(U1(1))
+ A(U1(1),)
+ A(U1(1),)
+
+Note that, because we created multiple subscriptions for A, we got multiple
+subscriber instances.
+
+As with normal adapters, if a factory returns None, the result is skipped:
+
+ >>> components.registerSubscriptionAdapter(
+ ... tests.noop, [tests.I1], tests.IA2)
+ Registered event:
+ SubscriptionRegistration(<Components comps>, [I1], IA2, u'', noop, u'')
+
+ >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
+ ... print s
+ A1_2(U1(1))
+ A1_12(U1(1))
+ A(U1(1),)
+ A(U1(1),)
+
+We can get registration information for subscriptions:
+
+ >>> for registration in sorted(
+ ... components.registeredSubscriptionAdapters()):
+ ... print registration.required
+ ... print registration.provided, registration.name
+ ... print registration.factory, registration.info
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A a sample comment
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A a sample comment
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A1_12
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A1_2
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ <function noop at 0xb796ff7c>
+
+We can also unregister subscriptions in much the same way we can for adapters:
+
+ >>> components.unregisterSubscriptionAdapter(tests.A1_2)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Unregistered event:
+ SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, '')
+ True
+
+ >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
+ ... print s
+ A1_12(U1(1))
+ A(U1(1),)
+ A(U1(1),)
+
+ >>> for registration in sorted(
+ ... components.registeredSubscriptionAdapters()):
+ ... print registration.required
+ ... print registration.provided, registration.name
+ ... print registration.factory, registration.info
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A a sample comment
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A a sample comment
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A1_12
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ <function noop at 0xb796ff7c>
+
+ >>> components.unregisterSubscriptionAdapter(
+ ... tests.A, [tests.I1], tests.IA2)
+ Unregistered event:
+ SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A, '')
+ True
+
+ >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
+ ... print s
+ A1_12(U1(1))
+
+ >>> for registration in sorted(
+ ... components.registeredSubscriptionAdapters()):
+ ... print registration.required
+ ... print registration.provided, registration.name
+ ... print registration.factory, registration.info
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ zope.registry.tests.A1_12
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <InterfaceClass zope.registry.tests.IA2>
+ <function noop at 0xb796ff7c>
+
+Note here that both registrations for A were removed.
+
+If we omit the factory, we must specify the required and provided interfaces:
+
+ >>> components.unregisterSubscriptionAdapter(required=[tests.I1])
+ Traceback (most recent call last):
+ ...
+ TypeError: Must specify one of factory and provided
+
+ >>> components.unregisterSubscriptionAdapter(provided=tests.IA2)
+ Traceback (most recent call last):
+ ...
+ TypeError: Must specify one of factory and required
+
+ >>> components.unregisterSubscriptionAdapter(
+ ... required=[tests.I1], provided=tests.IA2)
+ Unregistered event:
+ SubscriptionRegistration(<Components comps>, [I1], IA2, u'', None, '')
+ True
+
+ >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
+ ... print s
+
+ >>> for registration in sorted(
+ ... components.registeredSubscriptionAdapters()):
+ ... print registration.factory
+
+As when registering, an error is raised if the registration
+information can't be determined from the factory and isn't specified:
+
+ >>> components.unregisterSubscriptionAdapter(tests.A1_12)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't implement a single
+ interface and no provided interface was specified.
+
+ >>> components.unregisterSubscriptionAdapter(tests.A)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't implement a single interface and
+ no provided interface was specified.
+
+ >>> components.unregisterSubscriptionAdapter(tests.A, required=[tests.IA1])
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't implement a single interface
+ and no provided interface was specified.
+
+If you unregister something that's not registered, nothing will be
+changed and False will be returned:
+
+
+ >>> components.unregisterSubscriptionAdapter(
+ ... required=[tests.I1], provided=tests.IA2)
+ False
+
+Handlers
+--------
+
+Handlers are used when you want to perform some function in response
+to an event. Handlers aren't expected to return anything when called
+and are not registered to provide any interface.
+
+ >>> from zope import registry
+ >>> @registry.adapter(tests.I1)
+ ... def handle1(x):
+ ... print 'handle1', x
+
+ >>> components.registerHandler(handle1, info="First handler")
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Registered event:
+ HandlerRegistration(<Components comps>, [I1], u'',
+ handle1, 'First handler')
+ >>> components.handle(tests.U1(1))
+ handle1 U1(1)
+
+ >>> @registry.adapter(tests.I1, tests.I2)
+ ... def handle12(x, y):
+ ... print 'handle12', x, y
+
+ >>> components.registerHandler(handle12)
+ Registered event:
+ HandlerRegistration(<Components comps>, [I1, I2], u'', handle12, u'')
+ >>> components.handle(tests.U1(1), tests.U12(2))
+ handle12 U1(1) U12(2)
+
+If a handler doesn't document interfaces it handles, then
+the required interfaces must be specified:
+
+ >>> def handle(*objects):
+ ... print 'handle', objects
+
+ >>> components.registerHandler(handle)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't have a __component_adapts__
+ attribute and no required specifications were specified
+
+ >>> components.registerHandler(handle, required=[tests.I1],
+ ... info="a comment")
+ Registered event:
+ HandlerRegistration(<Components comps>, [I1], u'', handle, 'a comment')
+
+Handlers can also be registered for classes:
+
+ >>> components.registerHandler(handle, required=[tests.U],
+ ... info="handle a class")
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Registered event:
+ HandlerRegistration(<Components comps>, [zope.registry.tests.U], u'',
+ handle, 'handle a class')
+
+
+ >>> components.handle(tests.U1(1))
+ handle (U1(1),)
+ handle1 U1(1)
+ handle (U1(1),)
+
+We can list the handler registrations:
+
+ >>> for registration in components.registeredHandlers():
+ ... print registration.required
+ ... print registration.handler, registration.info
+ ... # doctest: +NORMALIZE_WHITESPACE
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <function handle1 at 0xb78f5bfc> First handler
+ (<InterfaceClass zope.registry.tests.I1>,
+ <InterfaceClass zope.registry.tests.I2>)
+ <function handle12 at 0xb78f5c34>
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <function handle at 0xb78f5ca4> a comment
+ (<implementedBy zope.registry.tests.U>,)
+ <function handle at 0xb78f5ca4> handle a class
+
+and we can unregister handlers:
+
+ >>> components.unregisterHandler(required=[tests.U])
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Unregistered event:
+ HandlerRegistration(<Components comps>, [zope.registry.tests.U], u'',
+ None, '')
+ True
+
+ >>> for registration in components.registeredHandlers():
+ ... print registration.required
+ ... print registration.handler, registration.info
+ ... # doctest: +NORMALIZE_WHITESPACE
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <function handle1 at 0xb78f5bfc> First handler
+ (<InterfaceClass zope.registry.tests.I1>,
+ <InterfaceClass zope.registry.tests.I2>)
+ <function handle12 at 0xb78f5c34>
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <function handle at 0xb78f5ca4> a comment
+
+ >>> components.unregisterHandler(handle12)
+ Unregistered event:
+ HandlerRegistration(<Components comps>, [I1, I2], u'', handle12, '')
+ True
+
+ >>> for registration in components.registeredHandlers():
+ ... print registration.required
+ ... print registration.handler, registration.info
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <function handle1 at 0xb78f5bfc> First handler
+ (<InterfaceClass zope.registry.tests.I1>,)
+ <function handle at 0xb78f5ca4> a comment
+
+ >>> components.unregisterHandler(handle12)
+ False
+
+ >>> components.unregisterHandler()
+ Traceback (most recent call last):
+ ...
+ TypeError: Must specify one of factory and required
+
+ >>> components.registerHandler(handle)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: The adapter factory doesn't have a __component_adapts__
+ attribute and no required specifications were specified
+
+Extending
+---------
+
+Component-management objects can extend other component-management
+objects.
+
+ >>> c1 = registry.Components('1')
+ >>> c1.__bases__
+ ()
+
+ >>> c2 = registry.Components('2', (c1, ))
+ >>> c2.__bases__ == (c1, )
+ True
+
+ >>> c1.registerUtility(tests.U1(1))
+ Registered event:
+ UtilityRegistration(<Components 1>, I1, u'', 1, None, u'')
+
+ >>> c1.queryUtility(tests.I1)
+ U1(1)
+ >>> c2.queryUtility(tests.I1)
+ U1(1)
+ >>> c1.registerUtility(tests.U1(2))
+ Unregistered event:
+ UtilityRegistration(<Components 1>, I1, u'', 1, None, u'')
+ Registered event:
+ UtilityRegistration(<Components 1>, I1, u'', 2, None, u'')
+
+ >>> c2.queryUtility(tests.I1)
+ U1(2)
+
+We can use multiple inheritence:
+
+ >>> c3 = registry.Components('3', (c1, ))
+ >>> c4 = registry.Components('4', (c2, c3))
+ >>> c4.queryUtility(tests.I1)
+ U1(2)
+
+ >>> c1.registerUtility(tests.U12(1), tests.I2)
+ Registered event:
+ UtilityRegistration(<Components 1>, I2, u'', 1, None, u'')
+
+ >>> c4.queryUtility(tests.I2)
+ U12(1)
+
+ >>> c3.registerUtility(tests.U12(3), tests.I2)
+ Registered event:
+ UtilityRegistration(<Components 3>, I2, u'', 3, None, u'')
+ >>> c4.queryUtility(tests.I2)
+ U12(3)
+
+ >>> c1.registerHandler(handle1, info="First handler")
+ Registered event:
+ HandlerRegistration(<Components 1>, [I1], u'', handle1, 'First handler')
+
+ >>> c2.registerHandler(handle, required=[tests.U])
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Registered event:
+ HandlerRegistration(<Components 2>, [zope.registry.tests.U], u'',
+ handle, u'')
+
+ >>> @registry.adapter(tests.I1)
+ ... def handle3(x):
+ ... print 'handle3', x
+ >>> c3.registerHandler(handle3)
+ Registered event:
+ HandlerRegistration(<Components 3>, [I1], u'', handle3, u'')
+
+ >>> @registry.adapter(tests.I1)
+ ... def handle4(x):
+ ... print 'handle4', x
+ >>> c4.registerHandler(handle4)
+ Registered event:
+ HandlerRegistration(<Components 4>, [I1], u'', handle4, u'')
+
+ >>> c4.handle(tests.U1(1))
+ handle1 U1(1)
+ handle3 U1(1)
+ handle (U1(1),)
+ handle4 U1(1)
+
Added: Sandbox/chrism/zope.registry/src/zope/registry/testfiles/__init__.py
===================================================================
--- Sandbox/chrism/zope.registry/src/zope/registry/testfiles/__init__.py (rev 0)
+++ Sandbox/chrism/zope.registry/src/zope/registry/testfiles/__init__.py 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1 @@
+#Python package
Added: Sandbox/chrism/zope.registry/src/zope/registry/testfiles/adapter.py
===================================================================
--- Sandbox/chrism/zope.registry/src/zope/registry/testfiles/adapter.py (rev 0)
+++ Sandbox/chrism/zope.registry/src/zope/registry/testfiles/adapter.py 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,63 @@
+##############################################################################
+#
+# 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.
+# 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.
+#
+##############################################################################
+"""Sample adapter class for testing
+
+$Id: adapter.py 70573 2006-10-08 12:34:17Z baijum $
+"""
+import zope.interface
+import zope.registry
+import components
+
+class I1(zope.interface.Interface):
+ pass
+
+class I2(zope.interface.Interface):
+ pass
+
+class I3(zope.interface.Interface):
+ def f1(): pass
+ def f2(): pass
+ def f3(): pass
+
+class IS(zope.interface.Interface):
+ pass
+
+
+class Adapter(object):
+ def __init__(self, *args):
+ self.context = args
+
+class A1(Adapter):
+ zope.interface.implements(I1)
+
+class A2(Adapter):
+ zope.interface.implements(I2)
+
+class A3(Adapter):
+ zope.registry.adapts(components.IContent, I1, I2)
+ zope.interface.implements(I3)
+
+class A4:
+ pass
+
+a4 = A4()
+
+class A5:
+ zope.interface.implements(I1, I2)
+
+a5 = A5()
+
+def Handler(content, *args):
+ # uninteresting handler
+ content.args = getattr(content, 'args', ()) + (args, )
Added: Sandbox/chrism/zope.registry/src/zope/registry/testfiles/components.py
===================================================================
--- Sandbox/chrism/zope.registry/src/zope/registry/testfiles/components.py (rev 0)
+++ Sandbox/chrism/zope.registry/src/zope/registry/testfiles/components.py 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,44 @@
+##############################################################################
+#
+# Copyright (c) 2002 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.
+# 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.
+#
+##############################################################################
+"""Components for testing
+
+$Id: components.py 70573 2006-10-08 12:34:17Z baijum $
+"""
+from zope.interface import Interface, Attribute, implements
+from zope.registry import adapts
+
+class IAppb(Interface):
+ a = Attribute('test attribute')
+ def f(): "test func"
+
+class IApp(IAppb):
+ pass
+
+class IContent(Interface): pass
+
+class Content(object):
+ implements(IContent)
+
+class Comp(object):
+ adapts(IContent)
+ implements(IApp)
+
+ def __init__(self, *args):
+ # Ignore arguments passed to constructor
+ pass
+
+ a = 1
+ def f(): pass
+
+comp = Comp()
Added: Sandbox/chrism/zope.registry/src/zope/registry/testfiles/views.py
===================================================================
--- Sandbox/chrism/zope.registry/src/zope/registry/testfiles/views.py (rev 0)
+++ Sandbox/chrism/zope.registry/src/zope/registry/testfiles/views.py 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 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.
+# 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.
+#
+##############################################################################
+"""Views test.
+
+$Id: views.py 100192 2009-05-21 13:22:14Z faassen $
+"""
+from zope.interface import Interface, implements, directlyProvides
+
+class Request(object):
+
+ def __init__(self, type):
+ directlyProvides(self, type)
+
+class IR(Interface):
+ pass
+
+class IV(Interface):
+ def index():
+ pass
+
+class IC(Interface): pass
+
+class V1(object):
+ implements(IV)
+
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ def index(self):
+ return 'V1 here'
+
+ def action(self):
+ return 'done'
+
+class VZMI(V1):
+ def index(self):
+ return 'ZMI here'
+
+class R1(object):
+
+ def index(self):
+ return 'R1 here'
+
+ def action(self):
+ return 'R done'
+
+ def __init__(self, request):
+ pass
+
+ implements(IV)
+
+class RZMI(R1):
+ pass
Added: Sandbox/chrism/zope.registry/src/zope/registry/tests.py
===================================================================
--- Sandbox/chrism/zope.registry/src/zope/registry/tests.py (rev 0)
+++ Sandbox/chrism/zope.registry/src/zope/registry/tests.py 2009-11-25 21:56:33 UTC (rev 106017)
@@ -0,0 +1,282 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002, 2009 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.
+# 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.
+#
+##############################################################################
+"""Component Architecture Tests
+
+$Id: tests.py 105528 2009-11-08 11:05:28Z kobold $
+"""
+import re
+import unittest
+
+from zope.testing.cleanup import cleanUp
+
+from zope import interface
+import zope.interface
+from zope.registry import adapts
+from zope.registry import adapter
+from zope.interface.interfaces import IInterface
+from zope.testing import doctest, renormalizing
+
+from zope.registry.interfaces import IComponentLookup
+
+from zope.registry.testfiles.adapter import A1, A2, A3
+from zope.registry.testfiles.components import IContent, Content
+from zope.registry.testfiles.components import IApp
+from zope.registry.testfiles.views import Request, IC, IV, V1, R1, IR
+
+# side effect gets component-based event dispatcher installed.
+# we should obviously make this more explicit
+# import zope.component.event
+
+class I1(interface.Interface):
+ pass
+class I2(interface.Interface):
+ pass
+class I2e(I2):
+ pass
+class I3(interface.Interface):
+ pass
+
+class ITestType(IInterface):
+ pass
+
+class U:
+
+ def __init__(self, name):
+ self.__name__ = name
+
+ def __repr__(self):
+ return "%s(%s)" % (self.__class__.__name__, self.__name__)
+
+class U1(U):
+ interface.implements(I1)
+
+class U12(U):
+ interface.implements(I1, I2)
+
+class IA1(interface.Interface):
+ pass
+
+class IA2(interface.Interface):
+ pass
+
+class IA3(interface.Interface):
+ pass
+
+class A:
+
+ def __init__(self, *context):
+ self.context = context
+
+ def __repr__(self):
+ return "%s%r" % (self.__class__.__name__, self.context)
+
+class A12_1(A):
+ adapts(I1, I2)
+ interface.implements(IA1)
+
+class A12_(A):
+ adapts(I1, I2)
+
+class A_2(A):
+ interface.implements(IA2)
+
+class A_3(A):
+ interface.implements(IA3)
+
+class A1_12(U):
+ adapts(I1)
+ interface.implements(IA1, IA2)
+
+class A1_2(U):
+ adapts(I1)
+ interface.implements(IA2)
+
+class A1_23(U):
+ adapts(I1)
+ interface.implements(IA1, IA3)
+
+def noop(*args):
+ pass
+
+ at adapter(I1)
+def handle1(x):
+ print 'handle1', x
+
+def handle(*objects):
+ print 'handle', objects
+
+ at adapter(I1)
+def handle3(x):
+ print 'handle3', x
+
+ at adapter(I1)
+def handle4(x):
+ print 'handle4', x
+
+class Ob(object):
+ interface.implements(I1)
+ def __repr__(self):
+ return '<instance Ob>'
+
+
+ob = Ob()
+
+class Ob2(object):
+ interface.implements(I2)
+ def __repr__(self):
+ return '<instance Ob2>'
+
+class Comp(object):
+ interface.implements(I2)
+ def __init__(self, context):
+ self.context = context
+
+comp = Comp(1)
+
+class Comp2(object):
+ interface.implements(I3)
+ def __init__(self, context):
+ self.context = context
+
+
+class ConformsToIComponentLookup(object):
+ """This object allows the sitemanager to conform/adapt to
+ `IComponentLookup` and thus to itself."""
+
+ def __init__(self, sitemanager):
+ self.sitemanager = sitemanager
+
+ def __conform__(self, interface):
+ """This method is specified by the adapter PEP to do the adaptation."""
+ if interface is IComponentLookup:
+ return self.sitemanager
+
+
+def testNo__component_adapts__leakage():
+ """
+ We want to make sure that an `adapts()` call in a class definition
+ doesn't affect instances.
+
+ >>> class C:
+ ... adapts()
+
+ >>> C.__component_adapts__
+ ()
+ >>> C().__component_adapts__
+ Traceback (most recent call last):
+ ...
+ AttributeError: __component_adapts__
+ """
+
+def test_multi_handler_unregistration():
+ """
+ There was a bug where multiple handlers for the same required
+ specification would all be removed when one of them was
+ unregistered:
+
+ >>> class I(zope.interface.Interface):
+ ... pass
+ >>> def factory1(event):
+ ... print "| Factory 1 is here"
+ >>> def factory2(event):
+ ... print "| Factory 2 is here"
+ >>> class Event(object):
+ ... zope.interface.implements(I)
+ >>> from zope.registry import Components
+ >>> registry = Components()
+ >>> registry.registerHandler(factory1, [I,])
+ >>> registry.registerHandler(factory2, [I,])
+ >>> registry.handle(Event())
+ | Factory 1 is here
+ | Factory 2 is here
+ >>> registry.unregisterHandler(factory1, [I,])
+ True
+ >>> registry.handle(Event())
+ | Factory 2 is here
+ """
+
+
+def dont_leak_utility_registrations_in__subscribers():
+ """
+
+ We've observed utilities getting left in _subscribers when they
+ get unregistered.
+
+ >>> import zope.registry
+ >>> reg = zope.registry.Components()
+ >>> class C:
+ ... def __init__(self, name):
+ ... self.name = name
+ ... def __repr__(self):
+ ... return "C(%s)" % self.name
+
+ >>> c1 = C(1)
+ >>> reg.registerUtility(c1, I1)
+ >>> reg.registerUtility(c1, I1)
+ >>> list(reg.getAllUtilitiesRegisteredFor(I1))
+ [C(1)]
+
+ >>> reg.unregisterUtility(provided=I1)
+ True
+ >>> list(reg.getAllUtilitiesRegisteredFor(I1))
+ []
+
+ >>> reg.registerUtility(c1, I1)
+ >>> reg.registerUtility(C(2), I1)
+
+ >>> list(reg.getAllUtilitiesRegisteredFor(I1))
+ [C(2)]
+
+ """
+
+class Ob3(object):
+ interface.implements(IC)
+
+template = """<configure
+ xmlns='http://namespaces.zope.org/zope'
+ i18n_domain='zope'>
+ %s
+ </configure>"""
+
+
+def setUpRegistryTests(tests):
+ cleanUp()
+
+def tearDownRegistryTests(tests):
+ cleanUp()
+ import zope.event
+ zope.event.subscribers.pop()
+
+def setUp(test=None):
+ cleanUp()
+
+def tearDown(test=None):
+ cleanUp()
+
+def test_suite():
+ checker = renormalizing.RENormalizing([
+ (re.compile('at 0x[0-9a-fA-F]+'), 'at <SOME ADDRESS>'),
+ (re.compile(r"<type 'exceptions.(\w+)Error'>:"),
+ r'exceptions.\1Error:'),
+ ])
+
+ return unittest.TestSuite((
+ doctest.DocTestSuite(setUp=setUp, tearDown=tearDown),
+ doctest.DocFileSuite('registry.txt', checker=checker,
+ setUp=setUpRegistryTests,
+ tearDown=tearDownRegistryTests),
+ ))
+
+if __name__ == "__main__":
+ unittest.main(defaultTest='test_suite')
More information about the checkins
mailing list