[Checkins] SVN: zope.component/tseaver-test_cleanup/ Move doctest files into Sphinx docs.

Tres Seaver cvs-admin at zope.org
Sun Jun 17 17:39:15 UTC 2012


Log message for revision 126886:
  Move doctest files into Sphinx docs.
  
  They still need tweaking to get the doctest snippets to pass.

Changed:
  _U  zope.component/tseaver-test_cleanup/
  A   zope.component/tseaver-test_cleanup/docs/api/
  A   zope.component/tseaver-test_cleanup/docs/configure.rst
  A   zope.component/tseaver-test_cleanup/docs/event.rst
  A   zope.component/tseaver-test_cleanup/docs/factory.rst
  A   zope.component/tseaver-test_cleanup/docs/hooks.rst
  D   zope.component/tseaver-test_cleanup/docs/index.rst
  A   zope.component/tseaver-test_cleanup/docs/index.rst
  A   zope.component/tseaver-test_cleanup/docs/narr.rst
  A   zope.component/tseaver-test_cleanup/docs/persistentregistry.rst
  A   zope.component/tseaver-test_cleanup/docs/registry.rst
  A   zope.component/tseaver-test_cleanup/docs/socketexample.rst
  A   zope.component/tseaver-test_cleanup/docs/testlayer.rst
  A   zope.component/tseaver-test_cleanup/docs/zcml.rst
  A   zope.component/tseaver-test_cleanup/docs/zcml_conditional.rst
  U   zope.component/tseaver-test_cleanup/setup.py
  D   zope.component/tseaver-test_cleanup/src/zope/component/README.txt
  D   zope.component/tseaver-test_cleanup/src/zope/component/configure.txt
  D   zope.component/tseaver-test_cleanup/src/zope/component/event.txt
  D   zope.component/tseaver-test_cleanup/src/zope/component/factory.txt
  D   zope.component/tseaver-test_cleanup/src/zope/component/hooks.txt
  D   zope.component/tseaver-test_cleanup/src/zope/component/index.txt
  D   zope.component/tseaver-test_cleanup/src/zope/component/persistentregistry.txt
  D   zope.component/tseaver-test_cleanup/src/zope/component/registry.txt
  D   zope.component/tseaver-test_cleanup/src/zope/component/socketexample.txt
  D   zope.component/tseaver-test_cleanup/src/zope/component/testlayer.txt
  U   zope.component/tseaver-test_cleanup/src/zope/component/tests/test_doctests.py
  D   zope.component/tseaver-test_cleanup/src/zope/component/zcml.txt
  D   zope.component/tseaver-test_cleanup/src/zope/component/zcml_conditional.txt

-=-
Copied: zope.component/tseaver-test_cleanup/docs/configure.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/configure.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/configure.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/configure.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,13 @@
+Package configuration
+=====================
+
+The ``zope.component`` package provides a ZCML file that configures some basic
+components:
+
+  >>> from zope.configuration.xmlconfig import XMLConfig
+  >>> import zope.component
+
+  >>> XMLConfig('configure.zcml', zope.component)()
+
+  >>> len(list(zope.component.getGlobalSiteManager().registeredHandlers()))
+  5

Copied: zope.component/tseaver-test_cleanup/docs/event.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/event.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/event.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/event.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,142 @@
+Events
+======
+
+The Component Architecture provides a way to dispatch events to event
+handlers.  Event handlers are registered as *subscribers*
+a.k.a. *handlers*.
+
+Before we can start we need to import ``zope.component.event`` to make
+the dispatching effective:
+
+  >>> import zope.component.event
+
+Consider two event classes:
+
+  >>> class Event1(object):
+  ...     pass
+
+  >>> class Event2(Event1):
+  ...     pass
+
+Now consider two handlers for these event classes:
+
+  >>> called = []
+
+  >>> import zope.component
+  >>> @zope.component.adapter(Event1)
+  ... def handler1(event):
+  ...     called.append(1)
+
+  >>> @zope.component.adapter(Event2)
+  ... def handler2(event):
+  ...     called.append(2)
+
+We can register them with the Component Architecture:
+
+  >>> zope.component.provideHandler(handler1)
+  >>> zope.component.provideHandler(handler2)
+
+Now let's go through the events.  We'll see that the handlers have been
+called accordingly:
+
+  >>> from zope.event import notify
+  >>> notify(Event1())
+  >>> called
+  [1]
+
+  >>> del called[:]
+  >>> notify(Event2())
+  >>> called.sort()
+  >>> called
+  [1, 2]
+
+
+
+Object events
+-------------
+
+
+The ``objectEventNotify`` function is a subscriber to dispatch
+ObjectEvents to interested adapters.
+
+First create an object class:
+
+  >>> class IUseless(zope.interface.Interface):
+  ...     """Useless object"""
+
+  >>> class UselessObject(object):
+  ...     """Useless object"""
+  ...     zope.interface.implements(IUseless)
+
+Then create an event class:
+
+  >>> class IObjectThrownEvent(zope.component.interfaces.IObjectEvent):
+  ...     """An object has been thrown away"""
+
+  >>> class ObjectThrownEvent(zope.component.interfaces.ObjectEvent):
+  ...     """An object has been thrown away"""
+  ...     zope.interface.implements(IObjectThrownEvent)
+
+Create an object and an event:
+
+  >>> hammer = UselessObject()
+  >>> event = ObjectThrownEvent(hammer)
+
+Then notify the event to the subscribers.
+Since the subscribers list is empty, nothing happens.
+
+  >>> zope.component.event.objectEventNotify(event)
+
+Now create an handler for the event:
+
+  >>> events = []
+  >>> def record(*args):
+  ...     events.append(args)
+
+  >>> zope.component.provideHandler(record, [IUseless, IObjectThrownEvent])
+
+The event is notified to the subscriber:
+
+  >>> zope.component.event.objectEventNotify(event)
+  >>> events == [(hammer, event)]
+  True
+
+Following test demonstrates how a subscriber can raise an exception
+to prevent an action.
+
+  >>> zope.component.provideHandler(zope.component.event.objectEventNotify)
+
+Let's create a container:
+
+  >>> class ToolBox(dict):
+  ...     def __delitem__(self, key):
+  ...         notify(ObjectThrownEvent(self[key]))
+  ...         return super(ToolBox,self).__delitem__(key)
+
+  >>> container = ToolBox()
+
+And put the object into the container:
+
+  >>> container['Red Hammer'] = hammer
+
+Create an handler function that will raise an error when called:
+
+  >>> class Veto(Exception):
+  ...     pass
+
+  >>> def callback(item, event):
+  ...     assert(item == event.object)
+  ...     raise Veto
+
+Register the handler:
+
+  >>> zope.component.provideHandler(callback, [IUseless, IObjectThrownEvent])
+
+Then if we try to remove the object, an ObjectThrownEvent is fired:
+
+  >>> del container['Red Hammer']
+  ... # doctest: +NORMALIZE_WHITESPACE
+  Traceback (most recent call last):
+  ...
+      raise Veto
+  Veto

Copied: zope.component/tseaver-test_cleanup/docs/factory.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/factory.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/factory.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/factory.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,131 @@
+Factories
+=========
+
+
+The Factory Class
+-----------------
+
+  >>> from zope.interface import Interface
+  >>> class IFunction(Interface):
+  ...     pass
+
+  >>> class IKlass(Interface):
+  ...     pass
+
+  >>> from zope.interface import implements
+  >>> class Klass(object):
+  ...     implements(IKlass)
+  ... 
+  ...     def __init__(self, *args, **kw):
+  ...         self.args = args
+  ...         self.kw = kw
+
+  >>> from zope.component.factory import Factory
+  >>> factory = Factory(Klass, 'Klass', 'Klassier')
+  >>> factory2 = Factory(lambda x: x, 'Func', 'Function')
+  >>> factory3 = Factory(lambda x: x, 'Func', 'Function', (IFunction,))
+
+Calling a Factory
+~~~~~~~~~~~~~~~~~
+
+Here we test whether the factory correctly creates the objects and
+including the correct handling of constructor elements.
+
+First we create a factory that creates instanace of the `Klass` class:
+
+  >>> factory = Factory(Klass, 'Klass', 'Klassier')
+
+Now we use the factory to create the instance
+
+  >>> kl = factory(1, 2, foo=3, bar=4)
+
+and make sure that the correct class was used to create the object:
+
+  >>> kl.__class__
+  <class 'Klass'>
+
+Since we passed in a couple positional and keyword arguments
+  
+  >>> kl.args
+  (1, 2)
+  >>> kl.kw
+  {'foo': 3, 'bar': 4}
+  
+  >>> factory2(3)
+  3
+  >>> factory3(3)
+  3
+
+
+Title and Description
+~~~~~~~~~~~~~~~~~~~~~
+
+  >>> factory.title
+  'Klass'
+  >>> factory.description
+  'Klassier'
+  >>> factory2.title
+  'Func'
+  >>> factory2.description
+  'Function'
+  >>> factory3.title
+  'Func'
+  >>> factory3.description
+  'Function'
+
+
+Provided Interfaces
+~~~~~~~~~~~~~~~~~~~
+
+  >>> implemented = factory.getInterfaces()
+  >>> implemented.isOrExtends(IKlass)
+  True
+  >>> list(implemented)
+  [<InterfaceClass __builtin__.IKlass>]
+  
+  >>> implemented2 = factory2.getInterfaces()
+  >>> list(implemented2)
+  []
+  
+  >>> implemented3 = factory3.getInterfaces()
+  >>> list(implemented3)
+  [<InterfaceClass __builtin__.IFunction>]
+
+
+The Component Architecture Factory API
+--------------------------------------
+
+  >>> import zope.component
+  >>> factory = Factory(Klass, 'Klass', 'Klassier')
+  >>> gsm = zope.component.getGlobalSiteManager() 
+
+  >>> from zope.component.interfaces import IFactory
+  >>> gsm.registerUtility(factory, IFactory, 'klass')
+
+Creating an Object
+~~~~~~~~~~~~~~~~~~
+
+  >>> kl = zope.component.createObject('klass', 1, 2, foo=3, bar=4)
+  >>> isinstance(kl, Klass)
+  True
+  >>> kl.args
+  (1, 2)
+  >>> kl.kw
+  {'foo': 3, 'bar': 4}
+
+Accessing Provided Interfaces
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+  >>> implemented = zope.component.getFactoryInterfaces('klass')
+  >>> implemented.isOrExtends(IKlass)
+  True
+  >>> [iface for iface in implemented]
+  [<InterfaceClass __builtin__.IKlass>]
+
+List of All Factories
+~~~~~~~~~~~~~~~~~~~~~
+
+  >>> [(name, fac.__class__) for name, fac in
+  ...  zope.component.getFactoriesFor(IKlass)]
+  [(u'klass', <class 'zope.component.factory.Factory'>)]
+

Copied: zope.component/tseaver-test_cleanup/docs/hooks.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/hooks.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/hooks.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/hooks.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,97 @@
+==============================
+The current component registry
+==============================
+
+There can be any number of component registries in an application. One of them
+is the global component registry, and there is also the concept of a currently
+used component registry. Component registries other than the global one are
+associated with objects called sites. The ``zope.component.hooks`` module
+provides an API to set and access the current site as well as manipulate the
+adapter hook associated with it.
+
+As long as we haven't set a site, none is being considered current:
+
+>>> from zope.component.hooks import getSite
+>>> print getSite()
+None
+
+We can also ask for the current component registry (aka site manager
+historically); it will return the global one if no current site is set:
+
+>>> from zope.component.hooks import getSiteManager
+>>> getSiteManager()
+<BaseGlobalComponents base>
+
+Let's set a site now. A site has to be an object that provides the
+``getSiteManager`` method, which is specified by
+``zope.component.interfaces.IPossibleSite``:
+
+>>> from zope.interface.registry import Components
+>>> class Site(object):
+...     def __init__(self):
+...         self.registry = Components('components')
+...     def getSiteManager(self):
+...         return self.registry
+
+>>> from zope.component.hooks import setSite
+>>> site1 = Site()
+>>> setSite(site1)
+
+After this, the newly set site is considered the currently active one:
+
+>>> getSite() is site1
+True
+>>> getSiteManager() is site1.registry
+True
+
+If we set another site, that one will be considered current:
+
+>>> site2 = Site()
+>>> site2.registry is not site1.registry
+True
+>>> setSite(site2)
+
+>>> getSite() is site2
+True
+>>> getSiteManager() is site2.registry
+True
+
+Finally we can unset the site and the global component registry is used again:
+
+>>> setSite()
+>>> print getSite()
+None
+>>> getSiteManager()
+<BaseGlobalComponents base>
+
+
+Context manager
+===============
+
+There also is a context manager for setting the site, which is especially
+useful when writing tests:
+
+>>> import zope.component.hooks
+>>> dummy = with_statement # support for Python-2.5
+>>> print getSite()
+None
+>>> with zope.component.hooks.site(site2):
+...     getSite() is site2
+True
+>>> print getSite()
+None
+
+The site is properly restored even if the body of the with statement
+raises an exception:
+
+>>> print getSite()
+None
+>>> with zope.component.hooks.site(site2):
+...    getSite() is site2
+...    raise ValueError('An error in the body')
+Traceback (most recent call last):
+    ...
+ValueError: An error in the body
+>>> print getSite()
+None
+

Deleted: zope.component/tseaver-test_cleanup/docs/index.rst
===================================================================
--- zope.component/tseaver-test_cleanup/docs/index.rst	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/docs/index.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,22 +0,0 @@
-.. zope.configuration documentation master file, created by
-   sphinx-quickstart on Thu May 10 21:03:35 2012.
-   You can adapt this file completely to your liking, but it should at least
-   contain the root `toctree` directive.
-
-Welcome to zope.configuration's documentation!
-==============================================
-
-Contents:
-
-.. toctree::
-   :maxdepth: 2
-
-
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
-

Copied: zope.component/tseaver-test_cleanup/docs/index.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/index.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/index.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/index.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,26 @@
+Welcome to zope.component's documentation!
+==========================================
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+   narr
+   socketexample
+   event
+   factory
+   registry
+   persistentregistry
+   zcml
+   configure
+   hooks
+   testlayer
+   zcml_conditional
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`

Copied: zope.component/tseaver-test_cleanup/docs/narr.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/README.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/narr.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/narr.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,402 @@
+Zope Component Architecture
+===========================
+
+This package, together with `zope.interface`, provides facilities for
+defining, registering and looking up components.  There are two basic
+kinds of components: adapters and utilities.
+
+Utilities
+---------
+
+Utilities are just components that provide an interface and that are
+looked up by an interface and a name.  Let's look at a trivial utility
+definition:
+
+    >>> from zope import interface
+
+    >>> class IGreeter(interface.Interface):
+    ...     def greet():
+    ...         "say hello"
+
+    >>> class Greeter:
+    ...     interface.implements(IGreeter)
+    ...
+    ...     def __init__(self, other="world"):
+    ...         self.other = other
+    ...
+    ...     def greet(self):
+    ...         print "Hello", self.other
+
+We can register an instance this class using `provideUtility` [1]_:
+
+    >>> from zope import component
+    >>> greet = Greeter('bob')
+    >>> component.provideUtility(greet, IGreeter, 'robert')
+
+In this example we registered the utility as providing the `IGreeter`
+interface with a name of 'bob'. We can look the interface up with
+either `queryUtility` or `getUtility`:
+
+    >>> component.queryUtility(IGreeter, 'robert').greet()
+    Hello bob
+
+    >>> component.getUtility(IGreeter, 'robert').greet()
+    Hello bob
+
+`queryUtility` and `getUtility` differ in how failed lookups are handled:
+
+    >>> component.queryUtility(IGreeter, 'ted')
+    >>> component.queryUtility(IGreeter, 'ted', 42)
+    42
+    >>> component.getUtility(IGreeter, 'ted')
+    ... # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ...
+    ComponentLookupError: (<InterfaceClass ...IGreeter>, 'ted')
+
+If a component provides only one interface, as in the example above,
+then we can omit the provided interface from the call to `provideUtility`:
+
+    >>> ted = Greeter('ted')
+    >>> component.provideUtility(ted, name='ted')
+    >>> component.queryUtility(IGreeter, 'ted').greet()
+    Hello ted
+
+The name defaults to an empty string:
+
+    >>> world = Greeter()
+    >>> component.provideUtility(world)
+    >>> component.queryUtility(IGreeter).greet()
+    Hello world
+
+Adapters
+--------
+
+Adapters are components that are computed from other components to
+adapt them to some interface.  Because they are computed from other
+objects, they are provided as factories, usually classes.  Here, we'll
+create a greeter for persons, so we can provide personalized greetings
+for different people:
+
+    >>> class IPerson(interface.Interface):
+    ...     name = interface.Attribute("Name")
+
+    >>> class PersonGreeter:
+    ...
+    ...     component.adapts(IPerson)
+    ...     interface.implements(IGreeter)
+    ...
+    ...     def __init__(self, person):
+    ...         self.person = person
+    ...
+    ...     def greet(self):
+    ...         print "Hello", self.person.name
+
+The class defines a constructor that takes an argument for every
+object adapted.
+
+We used `component.adapts` to declare what we adapt.  We can find
+out if an object declares that it adapts anything using adaptedBy:
+
+    >>> list(component.adaptedBy(PersonGreeter)) == [IPerson]
+    True
+
+If an object makes no declaration, then None is returned:
+
+    >>> component.adaptedBy(Greeter()) is None
+    True
+
+
+If we declare the interfaces adapted and if we provide only one
+interface, as in the example above, then we can provide the adapter
+very simply [1]_:
+
+    >>> component.provideAdapter(PersonGreeter)
+
+For adapters that adapt a single interface to a single interface
+without a name, we can get the adapter by simply calling the
+interface:
+
+    >>> class Person:
+    ...     interface.implements(IPerson)
+    ...
+    ...     def __init__(self, name):
+    ...         self.name = name
+
+    >>> IGreeter(Person("Sally")).greet()
+    Hello Sally
+
+We can also provide arguments to be very specific about what
+how to register the adapter.
+
+    >>> class BobPersonGreeter(PersonGreeter):
+    ...     name = 'Bob'
+    ...     def greet(self):
+    ...         print "Hello", self.person.name, "my name is", self.name
+
+    >>> component.provideAdapter(
+    ...                        BobPersonGreeter, [IPerson], IGreeter, 'bob')
+
+The arguments can also be provided as keyword arguments:
+
+    >>> class TedPersonGreeter(BobPersonGreeter):
+    ...     name = "Ted"
+
+    >>> component.provideAdapter(
+    ...     factory=TedPersonGreeter, adapts=[IPerson],
+    ...     provides=IGreeter, name='ted')
+
+For named adapters, use `queryAdapter`, or `getAdapter`:
+
+    >>> component.queryAdapter(Person("Sally"), IGreeter, 'bob').greet()
+    Hello Sally my name is Bob
+
+    >>> component.getAdapter(Person("Sally"), IGreeter, 'ted').greet()
+    Hello Sally my name is Ted
+
+If an adapter can't be found, `queryAdapter` returns a default value
+and `getAdapter` raises an error:
+
+    >>> component.queryAdapter(Person("Sally"), IGreeter, 'frank')
+    >>> component.queryAdapter(Person("Sally"), IGreeter, 'frank', 42)
+    42
+    >>> component.getAdapter(Person("Sally"), IGreeter, 'frank')
+    ... # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ...
+    ComponentLookupError: (...Person...>, <...IGreeter>, 'frank')
+
+Adapters can adapt multiple objects:
+
+    >>> class TwoPersonGreeter:
+    ...
+    ...     component.adapts(IPerson, IPerson)
+    ...     interface.implements(IGreeter)
+    ...
+    ...     def __init__(self, person, greeter):
+    ...         self.person = person
+    ...         self.greeter = greeter
+    ...
+    ...     def greet(self):
+    ...         print "Hello", self.person.name
+    ...         print "my name is", self.greeter.name
+
+    >>> component.provideAdapter(TwoPersonGreeter)
+
+Note that the declaration-order of the Interfaces beeing adapted to is
+important for adapter look up. It must be the the same as the order of
+parameters given to the adapter and used to query the adapter. This is
+especially the case when different Interfaces are adapt to (opposed to
+this example).
+
+To look up a multi-adapter, use either `queryMultiAdapter` or
+`getMultiAdapter`:
+
+    >>> component.queryMultiAdapter((Person("Sally"), Person("Bob")),
+    ...                                  IGreeter).greet()
+    Hello Sally
+    my name is Bob
+
+Adapters need not be classes.  Any callable will do.  We use the
+adapter decorator (in the Python 2.4 decorator sense) to declare that
+a callable object adapts some interfaces (or classes):
+
+    >>> class IJob(interface.Interface):
+    ...     "A job"
+
+    >>> class Job:
+    ...     interface.implements(IJob)
+
+    >>> def personJob(person):
+    ...     return getattr(person, 'job', None)
+    >>> personJob = interface.implementer(IJob)(personJob)
+    >>> personJob = component.adapter(IPerson)(personJob)
+
+In Python 2.4, the example can be written:
+
+    >>> @interface.implementer(IJob)
+    ... @component.adapter(IPerson)
+    ... def personJob(person):
+    ...     return getattr(person, 'job', None)
+
+which looks a bit nicer.
+
+In this example, the personJob function simply returns the person's
+`job` attribute if present, or None if it's not present.  An adapter
+factory can return None to indicate that adaptation wasn't possible.
+Let's register this adapter and try it out:
+
+    >>> component.provideAdapter(personJob)
+    >>> sally = Person("Sally")
+    >>> IJob(sally) # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ...
+    TypeError: ('Could not adapt', ...
+
+The adaptation failed because sally didn't have a job.  Let's give her
+one:
+
+    >>> job = Job()
+    >>> sally.job = job
+    >>> IJob(sally) is job
+    True
+
+Subscription Adapters
+---------------------
+
+Unlike regular adapters, subscription adapters are used when we want
+all of the adapters that adapt an object to a particular adapter.
+
+Consider a validation problem.  We have objects and we want to assess
+whether they meet some sort of standards.  We define a validation
+interface:
+
+    >>> class IValidate(interface.Interface):
+    ...     def validate(ob):
+    ...         """Determine whether the object is valid
+    ...
+    ...         Return a string describing a validation problem.
+    ...         An empty string is returned to indicate that the
+    ...         object is valid.
+    ...         """
+
+Perhaps we have documents:
+
+    >>> class IDocument(interface.Interface):
+    ...     summary = interface.Attribute("Document summary")
+    ...     body = interface.Attribute("Document text")
+
+    >>> class Document:
+    ...     interface.implements(IDocument)
+    ...     def __init__(self, summary, body):
+    ...         self.summary, self.body = summary, body
+
+Now, we may want to specify various validation rules for
+documents. For example, we might require that the summary be a single
+line:
+
+    >>> class SingleLineSummary:
+    ...     component.adapts(IDocument)
+    ...     interface.implements(IValidate)
+    ...
+    ...     def __init__(self, doc):
+    ...         self.doc = doc
+    ...
+    ...     def validate(self):
+    ...         if '\n' in self.doc.summary:
+    ...             return 'Summary should only have one line'
+    ...         else:
+    ...             return ''
+
+Or we might require the body to be at least 1000 characters in length:
+
+    >>> class AdequateLength:
+    ...     component.adapts(IDocument)
+    ...     interface.implements(IValidate)
+    ...
+    ...     def __init__(self, doc):
+    ...         self.doc = doc
+    ...
+    ...     def validate(self):
+    ...         if len(self.doc.body) < 1000:
+    ...             return 'too short'
+    ...         else:
+    ...             return ''
+
+We can register these as subscription adapters [1]_:
+
+    >>> component.provideSubscriptionAdapter(SingleLineSummary)
+    >>> component.provideSubscriptionAdapter(AdequateLength)
+
+We can then use the subscribers to validate objects:
+
+    >>> doc = Document("A\nDocument", "blah")
+    >>> [adapter.validate()
+    ...  for adapter in component.subscribers([doc], IValidate)
+    ...  if adapter.validate()]
+    ['Summary should only have one line', 'too short']
+
+    >>> doc = Document("A\nDocument", "blah" * 1000)
+    >>> [adapter.validate()
+    ...  for adapter in component.subscribers([doc], IValidate)
+    ...  if adapter.validate()]
+    ['Summary should only have one line']
+
+    >>> doc = Document("A Document", "blah")
+    >>> [adapter.validate()
+    ...  for adapter in component.subscribers([doc], IValidate)
+    ...  if adapter.validate()]
+    ['too short']
+
+Handlers
+--------
+
+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.
+
+Event subscribers are different from other subscription adapters in
+that the caller of event subscribers doesn't expect to interact with
+them in any direct way.  For example, an event publisher doesn't
+expect to get any return value.  Because subscribers don't need to
+provide an API to their callers, it is more natural to define them
+with functions, rather than classes.  For example, in a
+document-management system, we might want to record creation times for
+documents:
+
+    >>> import datetime
+
+    >>> def documentCreated(event):
+    ...     event.doc.created = datetime.datetime.utcnow()
+
+In this example, we have a function that takes an event and performs
+some processing.  It doesn't actually return anything.  This is a
+special case of a subscription adapter that adapts an event to
+nothing.  All of the work is done when the adapter "factory" is
+called.  We call subscribers that don't actually create anything
+"handlers".  There are special APIs for registering and calling
+them.
+
+To register the subscriber above, we define a document-created event:
+
+    >>> class IDocumentCreated(interface.Interface):
+    ...     doc = interface.Attribute("The document that was created")
+
+    >>> class DocumentCreated:
+    ...     interface.implements(IDocumentCreated)
+    ...
+    ...     def __init__(self, doc):
+    ...         self.doc = doc
+
+We'll also change our handler definition to:
+
+    >>> def documentCreated(event):
+    ...     event.doc.created = datetime.datetime.utcnow()
+
+    >>> documentCreated = component.adapter(IDocumentCreated)(documentCreated)
+
+Note that in Python 2.4, this can be written:
+
+    >>> @component.adapter(IDocumentCreated)
+    ... def documentCreated(event):
+    ...     event.doc.created = datetime.datetime.utcnow()
+
+This marks the handler as an adapter of `IDocumentCreated` events.
+
+Now we'll register the handler  [1]_:
+
+    >>> component.provideHandler(documentCreated)
+
+Now, if we can create an event and use the `handle` function to call
+handlers registered for the event:
+
+    >>> component.handle(DocumentCreated(doc))
+    >>> doc.created.__class__.__name__
+    'datetime'
+
+
+
+.. [1] 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.

Copied: zope.component/tseaver-test_cleanup/docs/persistentregistry.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/persistentregistry.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/persistentregistry.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/persistentregistry.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,6 @@
+Persistent Component Management
+===============================
+
+Persistent component management allows persistent management of
+components.  From a usage point of view, there shouldn't be any new
+behavior beyond what's described in registry.txt.

Copied: zope.component/tseaver-test_cleanup/docs/registry.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/registry.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/registry.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/registry.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,1117 @@
+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.component.registry.Components class provides an
+implementation of zope.component.interfaces.IComponents that provides
+these features.
+
+    >>> from zope.component import registry
+    >>> from zope.component 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.component.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.component.tests.I1> 
+    U1(1) 
+    <InterfaceClass zope.component.tests.I2> 
+    U12(2) 
+    <InterfaceClass zope.component.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.component.tests.I1> 
+    U1(4) use 4 now
+    <InterfaceClass zope.component.tests.I2> 
+    U12(2) 
+    <InterfaceClass zope.component.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.component.tests.I2> 
+    U12(2) 
+    <InterfaceClass zope.component.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.component.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.component.tests.I1>, 
+     <InterfaceClass zope.component.tests.I2>)
+    <InterfaceClass zope.component.tests.IA1> 
+    zope.component.tests.A12_1 
+    (<InterfaceClass zope.component.tests.I1>, 
+     <InterfaceClass zope.component.tests.I2>)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A12_ 
+    (<InterfaceClass zope.component.tests.I1>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A1_12 
+    (<InterfaceClass zope.component.tests.I3>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A_2 
+    (<implementedBy zope.component.tests.U>,)
+    <InterfaceClass zope.component.tests.IA3> 
+    zope.component.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.component.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.component.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.component.tests.I1>, 
+     <InterfaceClass zope.component.tests.I2>)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A12_ 
+    (<InterfaceClass zope.component.tests.I1>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A1_12 
+    (<InterfaceClass zope.component.tests.I3>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A_2 
+    (<implementedBy zope.component.tests.U>,)
+    <InterfaceClass zope.component.tests.IA3> 
+    zope.component.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.component.tests.U>,)
+    <InterfaceClass zope.component.tests.IA3> 
+    zope.component.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.component.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.component.tests.I1>,)
+    <InterfaceClass zope.component.tests.IA2> test 2
+    zope.component.tests.A1_23 
+    (<InterfaceClass zope.component.tests.IA1>,)
+    <InterfaceClass zope.component.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.component.tests.I1>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A a sample comment
+    (<InterfaceClass zope.component.tests.I1>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A a sample comment
+    (<InterfaceClass zope.component.tests.I1>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A1_12 
+    (<InterfaceClass zope.component.tests.I1>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A1_2 
+    (<InterfaceClass zope.component.tests.I1>,)
+    <InterfaceClass zope.component.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.component.tests.I1>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A a sample comment
+    (<InterfaceClass zope.component.tests.I1>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A a sample comment
+    (<InterfaceClass zope.component.tests.I1>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A1_12 
+    (<InterfaceClass zope.component.tests.I1>,)
+    <InterfaceClass zope.component.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.component.tests.I1>,)
+    <InterfaceClass zope.component.tests.IA2> 
+    zope.component.tests.A1_12 
+    (<InterfaceClass zope.component.tests.I1>,)
+    <InterfaceClass zope.component.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 component
+    >>> @component.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)
+
+    >>> @component.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.component.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.component.tests.I1>,)
+    <function handle1 at 0xb78f5bfc> First handler
+    (<InterfaceClass zope.component.tests.I1>,
+     <InterfaceClass zope.component.tests.I2>)
+    <function handle12 at 0xb78f5c34> 
+    (<InterfaceClass zope.component.tests.I1>,)
+    <function handle at 0xb78f5ca4> a comment
+    (<implementedBy zope.component.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.component.tests.U], u'', 
+                        None, '')
+    True
+
+    >>> for registration in components.registeredHandlers():
+    ...     print registration.required
+    ...     print registration.handler, registration.info
+    ... # doctest: +NORMALIZE_WHITESPACE
+    (<InterfaceClass zope.component.tests.I1>,)
+    <function handle1 at 0xb78f5bfc> First handler
+    (<InterfaceClass zope.component.tests.I1>,
+     <InterfaceClass zope.component.tests.I2>)
+    <function handle12 at 0xb78f5c34> 
+    (<InterfaceClass zope.component.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.component.tests.I1>,)
+    <function handle1 at 0xb78f5bfc> First handler
+    (<InterfaceClass zope.component.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.component.tests.U], u'', 
+                        handle, u'')
+    
+    >>> @component.adapter(tests.I1)
+    ... def handle3(x):
+    ...     print 'handle3', x
+    >>> c3.registerHandler(handle3)
+    Registered event:
+    HandlerRegistration(<Components 3>, [I1], u'', handle3, u'')
+    
+    >>> @component.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)
+
+Redispatch of registration events
+---------------------------------
+
+Some handlers are available that, if registered, redispatch
+registration events to the objects being registered.  They depend on
+being dispatched to by the object-event dispatcher:
+
+    >>> from zope import component
+    >>> import zope.component.event
+    >>> zope.component.getGlobalSiteManager().registerHandler(
+    ...      zope.component.event.objectEventNotify)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Registered event:
+    HandlerRegistration(<BaseGlobalComponents base>, 
+                        [IObjectEvent], u'', objectEventNotify, u'')
+
+To see this, we'll first register a multi-handler to show is when
+handlers are called on 2 objects:
+
+    >>> @zope.component.adapter(None, None)
+    ... def double_handler(o1, o2):
+    ...     print 'Double dispatch:'
+    ...     print ' ', o1
+    ...     print ' ', o2
+    >>> zope.component.getGlobalSiteManager().registerHandler(double_handler)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Double dispatch:
+      HandlerRegistration(<BaseGlobalComponents base>, 
+                          [Interface, Interface], u'', double_handler, u'')
+      Registered event:
+      HandlerRegistration(<BaseGlobalComponents base>, 
+      [Interface, Interface], u'', double_handler, u'')
+    Registered event:
+    HandlerRegistration(<BaseGlobalComponents base>, 
+                        [Interface, Interface], u'', double_handler, u'')
+
+In the example above, the double_handler reported it's own registration. :)
+
+Now we'll register our handlers:
+
+    >>> zope.component.getGlobalSiteManager().registerHandler(
+    ...     registry.dispatchUtilityRegistrationEvent)
+    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+    Double dispatch:
+    ...
+
+    >>> zope.component.getGlobalSiteManager().registerHandler(
+    ...     registry.dispatchAdapterRegistrationEvent)
+    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+    Double dispatch:
+    ...
+
+    >>> zope.component.getGlobalSiteManager().registerHandler(
+    ...     registry.dispatchSubscriptionAdapterRegistrationEvent)
+    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+    Double dispatch:
+    ...
+
+    >>> zope.component.getGlobalSiteManager().registerHandler(
+    ...     registry.dispatchHandlerRegistrationEvent)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Double dispatch:
+      HandlerRegistration(<BaseGlobalComponents base>, 
+                          [IHandlerRegistration, IRegistrationEvent], u'', 
+                          dispatchHandlerRegistrationEvent, u'')
+      Registered event:
+      HandlerRegistration(<BaseGlobalComponents base>, 
+                          [IHandlerRegistration, IRegistrationEvent], u'', 
+                          dispatchHandlerRegistrationEvent, u'')
+    Double dispatch:
+      <function dispatchHandlerRegistrationEvent at 0xb799f72c>
+      Registered event:
+      HandlerRegistration(<BaseGlobalComponents base>,
+                          [IHandlerRegistration, IRegistrationEvent], u'',
+                          dispatchHandlerRegistrationEvent, u'')
+    Registered event:
+    HandlerRegistration(<BaseGlobalComponents base>,
+                        [IHandlerRegistration, IRegistrationEvent], u'',
+                        dispatchHandlerRegistrationEvent, u'')
+
+In the last example above, we can see that the registration of
+dispatchHandlerRegistrationEvent was handled by
+dispatchHandlerRegistrationEvent and redispatched.  This can be seen
+in the second double-dispatch output, where the first argument is the
+object being registered, which is dispatchHandlerRegistrationEvent.
+
+If we change some other registrations, we can the double dispatch
+taking place:
+
+    >>> components.registerUtility(u5)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Double dispatch:
+      UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+      Registered event:
+      UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+    Double dispatch:
+      U1(5)
+      Registered event:
+      UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+    Registered event:
+    UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+
+    >>> components.registerAdapter(tests.A12_1)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Double dispatch:
+      AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+      Registered event:
+      AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+    Double dispatch:
+      zope.component.tests.A12_1
+      Registered event:
+      AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+    Registered event:
+    AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+
+    >>> components.registerSubscriptionAdapter(tests.A1_2)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Double dispatch:
+      SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+      Registered event:
+      SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+    Double dispatch:
+      zope.component.tests.A1_2
+      Registered event:
+      SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+    Registered event:
+    SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')

Copied: zope.component/tseaver-test_cleanup/docs/socketexample.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/socketexample.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/socketexample.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/socketexample.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,597 @@
+The Zope 3 Component Architecture (Socket Example)
+==================================================
+
+The component architecture provides an application framework that provides its
+functionality through loosely-connected components. A *component* can be any
+Python object and has a particular purpose associated with it. Thus, in a
+component-based applications you have many small component in contrast to
+classical object-oriented development, where you have a few big objects. 
+
+Components communicate via specific APIs, which are formally defined by
+interfaces, which are provided by the `zope.interface` package. *Interfaces*
+describe the methods and properties that a component is expected to
+provide. They are also used as a primary mean to provide developer-level
+documentation for the components. For more details about interfaces see
+`zope/interface/README.txt`.
+
+The two main types of components are *adapters* and *utilities*. They will be
+discussed in detail later in this document. Both component types are managed
+by the *site manager*, with which you can register and access these
+components. However, most of the site manager's functionality is hidden behind
+the component architecture's public API, which is documented in
+`IComponentArchitecture`.
+
+
+Adapters
+--------
+
+Adapters are a well-established pattern. An *adapter* uses an object providing
+one interface to produce an object that provides another interface. Here an
+example: Imagine that you purchased an electric shaver in the US, and thus
+you require the US socket type. You are now traveling in Germany, where another
+socket style is used. You will need a device, an adapter, that converts from
+the German to the US socket style.
+
+The functionality of adapters is actually natively provided by the
+`zope.interface` package and is thus well documented there. The `human.txt`
+file provides a gentle introduction to adapters, whereby `adapter.txt` is
+aimed at providing a comprehensive insight into adapters, but is too abstract
+for many as an initial read. Thus, we will only explain adapters in the context
+of the component architecture's API.
+
+So let's say that we have a German socket
+
+  >>> from zope.interface import Interface, implements
+
+  >>> class IGermanSocket(Interface):
+  ...     pass
+
+  >>> class Socket(object):
+  ...     def __repr__(self):
+  ...         return '<instance of %s>' %self.__class__.__name__
+
+  >>> class GermanSocket(Socket):
+  ...     """German wall socket."""
+  ...     implements(IGermanSocket)
+
+and we want to convert it to an US socket
+
+  >>> class IUSSocket(Interface):
+  ...     pass
+
+so that our shaver can be used in Germany. So we go to a German electronics
+store to look for an adapter that we can plug in the wall:
+
+  >>> class GermanToUSSocketAdapter(Socket):
+  ...     implements(IUSSocket)
+  ...     __used_for__ = IGermanSocket
+  ...     
+  ...     def __init__(self, socket):
+  ...         self.context = socket
+
+Note that I could have called the passed in socket any way I like, but
+`context` is the standard name accepted.
+
+
+Single Adapters
+~~~~~~~~~~~~~~~
+
+Before we can use the adapter, we have to buy it and make it part of our
+inventory. In the component architecture we do this by registering the adapter
+with the framework, more specifically with the global site manager:
+
+  >>> import zope.component
+  >>> gsm = zope.component.getGlobalSiteManager()
+  >>> gsm.registerAdapter(GermanToUSSocketAdapter, (IGermanSocket,), IUSSocket)
+
+`zope.component` is the component architecture API that is being
+presented by this file. You registered an adapter from `IGermanSocket`
+to `IUSSocket` having no name (thus the empty string).
+
+Anyways, you finally get back to your hotel room and shave, since you have not
+been able to shave in the plane. In the bathroom you discover a socket:
+
+  >>> bathroomDE = GermanSocket()
+  >>> IGermanSocket.providedBy(bathroomDE)
+  True
+
+You now insert the adapter in the German socket
+
+  >>> bathroomUS = zope.component.getAdapter(bathroomDE, IUSSocket, '')
+
+so that the socket now provides the US version:
+
+  >>> IUSSocket.providedBy(bathroomUS)
+  True
+
+Now you can insert your shaver and get on with your day. 
+
+After a week you travel for a couple of days to the Prague and you notice that
+the Czech have yet another socket type:
+
+  >>> class ICzechSocket(Interface):
+  ...     pass
+
+  >>> class CzechSocket(Socket):
+  ...     implements(ICzechSocket)
+
+  >>> czech = CzechSocket()
+
+You try to find an adapter for your shaver in your bag, but you fail, since
+you do not have one:
+
+  >>> zope.component.getAdapter(czech, IUSSocket, '') \
+  ... #doctest: +NORMALIZE_WHITESPACE
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: (<instance of CzechSocket>, 
+                         <InterfaceClass __builtin__.IUSSocket>,
+                         '')
+
+or the more graceful way:
+
+  >>> marker = object()
+  >>> socket = zope.component.queryAdapter(czech, IUSSocket, '', marker)
+  >>> socket is marker
+  True
+
+In the component architecture API any `get*` method will fail with a specific
+exception, if a query failed, whereby methods starting with `query*` will
+always return a `default` value after a failure.
+
+
+Named Adapters
+~~~~~~~~~~~~~~
+
+You are finally back in Germany. You also brought your DVD player and a couple
+DVDs with you, which you would like to watch. Your shaver was able to convert
+automatically from 110 volts to 240 volts, but your DVD player cannot. So you
+have to buy another adapter that also handles converting the voltage and the
+frequency of the AC current:
+
+  >>> class GermanToUSSocketAdapterAndTransformer(object):
+  ...     implements(IUSSocket)
+  ...     __used_for__ = IGermanSocket
+  ...     
+  ...     def __init__(self, socket):
+  ...         self.context = socket
+
+Now, we need a way to keep the two adapters apart. Thus we register them with
+a name:
+
+  >>> gsm.registerAdapter(GermanToUSSocketAdapter,
+  ...                     (IGermanSocket,), IUSSocket, 'shaver',)
+  >>> gsm.registerAdapter(GermanToUSSocketAdapterAndTransformer,
+  ...                     (IGermanSocket,), IUSSocket, 'dvd')
+
+Now we simply look up the adapters using their labels (called *name*):
+
+  >>> socket = zope.component.getAdapter(bathroomDE, IUSSocket, 'shaver')
+  >>> socket.__class__ is GermanToUSSocketAdapter
+  True
+
+  >>> socket = zope.component.getAdapter(bathroomDE, IUSSocket, 'dvd')
+  >>> socket.__class__ is GermanToUSSocketAdapterAndTransformer
+  True
+
+Clearly, we do not have an adapter for the MP3 player
+
+  >>> zope.component.getAdapter(bathroomDE, IUSSocket, 'mp3') \
+  ... #doctest: +NORMALIZE_WHITESPACE
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: (<instance of GermanSocket>, 
+                         <InterfaceClass __builtin__.IUSSocket>,
+                         'mp3')
+
+but you could use the 'dvd' adapter in this case of course. ;)
+
+Sometimes you want to know all adapters that are available. Let's say you want
+to know about all the adapters that convert a German to a US socket type:
+
+  >>> sockets = list(zope.component.getAdapters((bathroomDE,), IUSSocket))
+  >>> len(sockets)
+  3
+  >>> names = [name for name, socket in sockets]
+  >>> names.sort()
+  >>> names
+  [u'', u'dvd', u'shaver']
+
+`zope.component.getAdapters()` returns a list of tuples. The first
+entry of the tuple is the name of the adapter and the second is the
+adapter itself.
+
+
+Multi-Adapters
+~~~~~~~~~~~~~~
+
+After watching all the DVDs you brought at least twice, you get tired of them
+and you want to listen to some music using your MP3 player. But darn, the MP3
+player plug has a ground pin and all the adapters you have do not support
+that:
+
+  >>> class IUSGroundedSocket(IUSSocket):
+  ...     pass
+
+So you go out another time to buy an adapter. This time, however, you do not
+buy yet another adapter, but a piece that provides the grounding plug:
+
+  >>> class IGrounder(Interface):
+  ...     pass
+
+  >>> class Grounder(object):
+  ...     implements(IGrounder)
+  ...     def __repr__(self):
+  ...         return '<instance of Grounder>'
+
+
+Then together they will provided a grounded us socket:
+
+  >>> class GroundedGermanToUSSocketAdapter(object):
+  ...     implements(IUSGroundedSocket)
+  ...     __used_for__ = (IGermanSocket, IGrounder)
+  ...     def __init__(self, socket, grounder):
+  ...         self.socket, self.grounder = socket, grounder
+
+You now register the combination, so that you know you can create a
+`IUSGroundedSocket`:
+
+  >>> gsm.registerAdapter(GroundedGermanToUSSocketAdapter,
+  ...                 (IGermanSocket, IGrounder), IUSGroundedSocket, 'mp3')
+
+Given the grounder
+
+  >>> grounder = Grounder()
+
+and a German socket
+
+  >>> livingroom = GermanSocket()
+
+we can now get a grounded US socket:
+
+  >>> socket = zope.component.getMultiAdapter((livingroom, grounder), 
+  ...                                         IUSGroundedSocket, 'mp3')
+
+  >>> socket.__class__ is GroundedGermanToUSSocketAdapter
+  True
+  >>> socket.socket is livingroom
+  True
+  >>> socket.grounder is grounder
+  True
+
+Of course, you do not have a 'dvd' grounded US socket available:
+
+  >>> zope.component.getMultiAdapter((livingroom, grounder),
+  ...                                IUSGroundedSocket, 'dvd') \
+  ... #doctest: +NORMALIZE_WHITESPACE
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: ((<instance of GermanSocket>, 
+                          <instance of Grounder>), 
+                         <InterfaceClass __builtin__.IUSGroundedSocket>,
+                         'dvd')
+
+
+  >>> socket = zope.component.queryMultiAdapter(
+  ...     (livingroom, grounder), IUSGroundedSocket, 'dvd', marker)
+  >>> socket is marker
+  True
+
+Again, you might want to read `adapter.txt` in `zope.interface` for a more
+comprehensive coverage of multi-adapters.
+
+Subscribers
+-----------
+
+While subscribers are directly supported by the adapter registry and are
+adapters for all theoretical purposes, practically it might be better to think
+of them as separate components. Subscribers are particularly useful for
+events.
+
+Let's say one of our adapters overheated and caused a small fire:
+
+  >>> class IFire(Interface):
+  ...     pass
+
+  >>> class Fire(object):
+  ...     implements(IFire)
+
+  >>> fire = Fire()
+
+We want to use all available objects to put out the fire:
+
+  >>> class IFireExtinguisher(Interface):
+  ...     def extinguish():
+  ...         pass
+
+  >>> class FireExtinguisher(object):
+  ...     def __init__(self, fire):
+  ...         pass
+  ...     def extinguish(self):
+  ...         "Place extinguish code here."
+  ...         print 'Used ' + self.__class__.__name__ + '.'
+
+Here some specific methods to put out the fire:
+
+  >>> class PowderExtinguisher(FireExtinguisher):
+  ...     pass
+  >>> gsm.registerSubscriptionAdapter(PowderExtinguisher, 
+  ...                                 (IFire,), IFireExtinguisher)
+
+  >>> class Blanket(FireExtinguisher):
+  ...     pass
+  >>> gsm.registerSubscriptionAdapter(Blanket, (IFire,), IFireExtinguisher)
+
+  >>> class SprinklerSystem(FireExtinguisher):
+  ...     pass
+  >>> gsm.registerSubscriptionAdapter(SprinklerSystem,
+  ...                                 (IFire,), IFireExtinguisher)
+
+Now let use all these things to put out the fire:
+
+  >>> extinguishers = zope.component.subscribers((fire,), IFireExtinguisher)
+  >>> extinguishers.sort()
+  >>> for extinguisher in extinguishers:
+  ...     extinguisher.extinguish()
+  Used Blanket.
+  Used PowderExtinguisher.
+  Used SprinklerSystem.
+
+If no subscribers are found for a particular object, then an empty list is
+returned: 
+
+  >>> zope.component.subscribers((object(),), IFireExtinguisher)
+  []
+
+
+Utilities
+---------
+
+Utilities are the second type of component, the component architecture
+implements. *Utilities* are simply components that provide an interface. When
+you register an utility, you always register an instance (in contrast to a
+factory for adapters) since the initialization and setup process of a utility
+might be complex and is not well defined. In some ways a utility is much more
+fundamental than an adapter, because an adapter cannot be used without another
+component, but a utility is always self-contained. I like to think of
+utilities as the foundation of your application and adapters as components
+extending beyond this foundation.
+
+Back to our story...
+
+After your vacation is over you fly back home to Tampa, Florida. But it is
+August now, the middle of the Hurricane season. And, believe it or not, you are
+worried that you will not be able to shave when the power goes out for several
+days. (You just hate wet shavers.)
+
+So you decide to go to your favorite hardware store and by a Diesel-powered
+electric generator. The generator provides of course a US-style socket:
+
+  >>> class Generator(object):
+  ...     implements(IUSSocket)
+  ...     def __repr__(self):
+  ...         return '<instance of Generator>'
+
+  >>> generator = Generator()
+
+Like for adapters, we now have to add the newly-acquired generator to our
+inventory by registering it as a utility:
+
+  >>> gsm.registerUtility(generator, IUSSocket)
+
+We can now get the utility using
+
+  >>> utility = zope.component.getUtility(IUSSocket)
+  >>> utility is generator
+  True
+
+As you can see, it is very simple to register and retrieve utilities. If a
+utility does not exist for a particular interface, such as the German socket,
+then the lookup fails
+
+  >>> zope.component.getUtility(IGermanSocket)
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: (<InterfaceClass __builtin__.IGermanSocket>, '')
+
+or more gracefully when specifying a default value:
+
+  >>> default = object()
+  >>> utility = zope.component.queryUtility(IGermanSocket, default=default)
+  >>> utility is default
+  True
+
+Note: The only difference between `getUtility()` and `queryUtility()` is the
+fact that you can specify a default value for the latter function, so that it
+will never cause a `ComponentLookupError`.
+
+
+Named Utilities
+~~~~~~~~~~~~~~~
+
+It is often desirable to have several utilities providing the same interface
+per site. This way you can implement any sort of registry using utilities. For
+this reason, utilities -- like adapters -- can be named.
+
+In the context of our story, we might want to do the following: You really do
+not trust gas stations either. What if the roads are blocked after a hurricane
+and the gas stations run out of oil. So you look for another renewable power
+source. Then you think about solar panels! After a storm there is usually very
+nice weather, so why not? Via the Web you order a set of 110V/120W solar
+panels that provide a regular US-style socket as output:
+
+  >>> class SolarPanel(object):
+  ...     implements(IUSSocket)
+  ...     def __repr__(self):
+  ...         return '<instance of Solar Panel>'
+
+  >>> panel = SolarPanel()
+
+Once it arrives, we add it to our inventory:
+
+  >>> gsm.registerUtility(panel, IUSSocket, 'Solar Panel')
+
+You can now access the solar panel using
+
+  >>> utility = zope.component.getUtility(IUSSocket, 'Solar Panel')
+  >>> utility is panel
+  True
+
+Of course, if a utility is not available, then the lookup will simply fail
+
+  >>> zope.component.getUtility(IUSSocket, 'Wind Mill')
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: (<InterfaceClass __builtin__.IUSSocket>, 'Wind Mill')
+
+or more gracefully when specifying a default value:
+
+  >>> default = object()
+  >>> utility = zope.component.queryUtility(IUSSocket, 'Wind Mill',
+  ...                                       default=default)
+  >>> utility is default
+  True
+
+Now you want to look at all the utilities you have for a particular kind. The
+following API function will return a list of name/utility pairs:
+
+  >>> utils = list(zope.component.getUtilitiesFor(IUSSocket))
+  >>> utils.sort()
+  >>> utils #doctest: +NORMALIZE_WHITESPACE
+  [(u'', <instance of Generator>), 
+   (u'Solar Panel', <instance of Solar Panel>)]
+
+Another method of looking up all utilities is by using
+`getAllUtilitiesRegisteredFor(iface)`. This function will return an iterable
+of utilities (without names); however, it will also return overridden
+utilities. If you are not using multiple site managers, you will not actually
+need this method.
+
+  >>> utils = list(zope.component.getAllUtilitiesRegisteredFor(IUSSocket))
+  >>> utils.sort()
+  >>> utils
+  [<instance of Generator>, <instance of Solar Panel>]
+
+
+Factories
+~~~~~~~~~
+
+A *factory* is a special kind of utility that exists to create other
+components. A factory is always identified by a name. It also provides a title
+and description and is able to tell the developer what interfaces the created
+object will provide. The advantage of using a factory to create an object
+instead of directly instantiating a class or executing any other callable is
+that we can refer to the factory by name. As long as the name stays fixed, the
+implementation of the callable can be renamed or moved without a breakage in
+code.
+
+Let's say that our solar panel comes in parts and they have to be
+assembled. This assembly would be done by a factory, so let's create one for
+the solar panel. To do this, we can use a standard implementation of the
+`IFactory` interface:
+
+  >>> from zope.component.factory import Factory
+  >>> factory = Factory(SolarPanel, 
+  ...                   'Solar Panel',
+  ...                   'This factory creates a solar panel.')
+
+Optionally, I could have also specified the interfaces that the created object
+will provide, but the factory class is smart enough to determine the
+implemented interface from the class. We now register the factory:
+
+  >>> from zope.component.interfaces import IFactory
+  >>> gsm.registerUtility(factory, IFactory, 'SolarPanel')
+
+We can now get a list of interfaces the produced object will provide:
+
+  >>> ifaces = zope.component.getFactoryInterfaces('SolarPanel')
+  >>> IUSSocket in ifaces
+  True
+
+By the way, this is equivalent to
+
+  >>> ifaces2 = factory.getInterfaces()
+  >>> ifaces is ifaces2
+  True
+
+Of course you can also just create an object:
+
+  >>> panel = zope.component.createObject('SolarPanel')
+  >>> panel.__class__ is SolarPanel
+  True
+
+Note: Ignore the first argument (`None`) for now; it is the context of the
+utility lookup, which is usually an optional argument, but cannot be in this
+case, since all other arguments beside the `name` are passed in as arguments
+to the specified callable.
+
+Once you register several factories
+
+  >>> gsm.registerUtility(Factory(Generator), IFactory, 'Generator')
+
+you can also determine, which available factories will create objects
+providing a certain interface:
+
+  >>> factories = zope.component.getFactoriesFor(IUSSocket)
+  >>> factories = [(name, factory.__class__) for name, factory in factories]
+  >>> factories.sort()
+  >>> factories #doctest: +NORMALIZE_WHITESPACE
+  [(u'Generator', <class 'zope.component.factory.Factory'>), 
+   (u'SolarPanel', <class 'zope.component.factory.Factory'>)]
+
+
+Site Managers
+-------------
+
+Why do we need site managers? Why is the component architecture API not
+sufficient? Some applications, including Zope 3, have a concept of
+locations. It is often desirable to have different configurations for these
+location; this can be done by overwriting existing or adding new component
+registrations. Site managers in locations below the root location, should be
+able to delegate requests to their parent locations. The root site manager is
+commonly known as *global site manager*, since it is always available. You can
+always get the global site manager using the API:
+
+  >>> gsm = zope.component.getGlobalSiteManager()
+
+  >>> from zope.component import globalSiteManager
+  >>> gsm is globalSiteManager
+  True
+  >>> from zope.component.interfaces import IComponentLookup
+  >>> IComponentLookup.providedBy(gsm)
+  True
+  >>> from zope.component.interfaces import IComponents
+  >>> IComponents.providedBy(gsm)
+  True
+
+You can also lookup at site manager in a given context. The only requirement
+is that the context can be adapted to a site manager. So let's create a
+special site manager:
+
+  >>> from zope.component.globalregistry import BaseGlobalComponents
+  >>> sm = BaseGlobalComponents()
+
+Now we create a context that adapts to the site manager via the `__conform__`
+method as specified in PEP 246.
+
+  >>> class Context(object):
+  ...     def __init__(self, sm):
+  ...         self.sm = sm
+  ...     def __conform__(self, interface):
+  ...         if interface.isOrExtends(IComponentLookup):
+  ...             return self.sm
+
+We now instantiate the `Context` with our special site manager:
+
+  >>> context = Context(sm)
+  >>> context.sm is sm
+  True
+
+We can now ask for the site manager of this context:
+
+  >>> lsm = zope.component.getSiteManager(context)
+  >>> lsm is sm
+  True
+
+The site manager instance `lsm` is formally known as a *local site manager* of
+`context`.

Copied: zope.component/tseaver-test_cleanup/docs/testlayer.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/testlayer.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/testlayer.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/testlayer.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,100 @@
+Layers
+======
+
+zope.component.testlayer defines two things:
+
+* a LayerBase that makes it easier and saner to use zope.testing's
+  test layers.
+
+* a ZCMLLayer which lets you implement a layer that loads up some
+  ZCML.
+
+LayerBase
+---------
+
+We check whether our LayerBase can be used to create layers of our
+own. We do this simply by subclassing:
+
+  >>> from zope.component.testlayer import LayerBase
+  >>> class OurLayer(LayerBase):
+  ...     def setUp(self):
+  ...         super(OurLayer, self).setUp()
+  ...         print "setUp called"
+  ...     def tearDown(self):
+  ...         super(OurLayer, self).tearDown()
+  ...         print "tearDown called"
+  ...     def testSetUp(self):
+  ...         super(OurLayer, self).testSetUp()
+  ...         print "testSetUp called"
+  ...     def testTearDown(self):
+  ...         super(OurLayer, self).testTearDown()
+  ...         print "testTearDown called"
+
+Note that if we wanted to ensure that the methods of the superclass
+were called we have to use super(). In this case we actually wouldn't
+need to, as these methods do nothing at all, but we just ensure that
+they are there in the first place.
+
+Let's instantiate our layer. We need to supply it with the package the
+layer is defined in::
+
+  >>> import zope.component
+  >>> layer = OurLayer(zope.component)
+
+Now we run some tests with this layer:
+
+  >>> import unittest
+  >>> class TestCase(unittest.TestCase):
+  ...    layer = layer
+  ...    
+  ...    def testFoo(self):
+  ...        print "testFoo"
+  >>> suite = unittest.TestSuite()
+  >>> suite.addTest(unittest.makeSuite(TestCase))
+  >>> from zope.testrunner.runner import Runner
+  >>> runner = Runner(args=[], found_suites=[suite])
+  >>> succeeded = runner.run()
+  Running zope.component.OurLayer tests:
+    Set up zope.component.OurLayer setUp called
+  in ... seconds.
+  testSetUp called
+  testFoo
+  testTearDown called
+    Ran 1 tests with 0 failures and 0 errors in ... seconds.
+  Tearing down left over layers:
+    Tear down zope.component.OurLayer tearDown called
+  in ... seconds.
+
+ZCMLLayer
+---------
+
+We now want a layer that loads up some ZCML from a file. The default
+is ``ftesting.zcml``, but here we'll load a test ``testlayer.zcml``.
+
+  >>> from zope.component.testlayer import ZCMLFileLayer
+  >>> zcml_file_layer = ZCMLFileLayer(
+  ...     zope.component.testfiles,
+  ...     'testlayer.zcml')
+
+  >>> class TestCase(unittest.TestCase):
+  ...    layer = zcml_file_layer
+  ...    
+  ...    def testFoo(self):
+  ...        # we should now have the adapter registered
+  ...        from zope import component
+  ...        from zope.component.testfiles import components
+  ...        self.assert_(isinstance(
+  ...            components.IApp2(components.content), components.Comp2))
+
+Since the ZCML sets up an adapter, we expect the tests to pass::
+
+  >>> suite = unittest.TestSuite()
+  >>> suite.addTest(unittest.makeSuite(TestCase))
+  >>> runner = Runner(args=[], found_suites=[suite])
+  >>> succeeded = runner.run()
+  Running zope.component.testfiles.ZCMLFileLayer tests:
+    Set up zope.component.testfiles.ZCMLFileLayer in ... seconds.
+    Ran 1 tests with 0 failures and 0 errors in ... seconds.
+  Tearing down left over layers:
+    Tear down zope.component.testfiles.ZCMLFileLayer in ... seconds.
+

Copied: zope.component/tseaver-test_cleanup/docs/zcml.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/zcml.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/zcml.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/zcml.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,1021 @@
+ZCML directives
+===============
+
+Components may be registered using the registration API exposed by
+``zope.component`` (provideAdapter, provideUtility, etc.).  They may
+also be registered using configuration files.  The common way to do
+that is by using ZCML (Zope Configuration Markup Language), an XML
+spelling of component registration.
+
+In ZCML, each XML element is a *directive*.  There are different
+top-level directives that let us register components.  We will
+introduce them one by one here.
+
+This helper will let us easily execute ZCML snippets:
+
+  >>> from cStringIO import StringIO
+  >>> from zope.configuration.xmlconfig import xmlconfig
+  >>> def runSnippet(snippet):
+  ...     template = """\
+  ...     <configure xmlns='http://namespaces.zope.org/zope'
+  ...                i18n_domain="zope">
+  ...     %s
+  ...     </configure>"""
+  ...     xmlconfig(StringIO(template % snippet))
+
+adapter
+-------
+
+Adapters play a key role in the Component Architecture.  In ZCML, they
+are registered with the <adapter /> directive.
+
+  >>> from zope.component.testfiles.adapter import A1, A2, A3, Handler
+  >>> from zope.component.testfiles.adapter import I1, I2, I3, IS
+  >>> from zope.component.testfiles.components import IContent, Content, Comp, comp
+
+Before we register the first test adapter, we can verify that adapter
+lookup doesn't work yet:
+
+  >>> from zope.component.tests.test_doctests import clearZCML
+  >>> clearZCML()
+  >>> from zope.component.testfiles.components import IApp
+  >>> IApp(Content(), None) is None
+  True
+
+Then we register the adapter and see that the lookup works:
+
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.components.Comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       />''')
+
+  >>> IApp(Content()).__class__
+  <class 'zope.component.testfiles.components.Comp'>
+
+It is also possible to give adapters names.  Then the combination of
+required interface, provided interface and name makes the adapter
+lookup unique.  The name is supplied using the ``name`` argument to
+the <adapter /> directive:
+
+  >>> from zope.component.tests.test_doctests import clearZCML
+  >>> clearZCML()
+  >>> import zope.component
+  >>> zope.component.queryAdapter(Content(), IApp, 'test') is None
+  True
+
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.components.Comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       name="test"
+  ...       />''')
+
+  >>> zope.component.getAdapter(Content(), IApp, 'test').__class__
+  <class 'zope.component.testfiles.components.Comp'>
+
+Adapter factories
+~~~~~~~~~~~~~~~~~
+
+It is possible to supply more than one adapter factory.  In this case,
+during adapter lookup each factory will be called and the return value
+will be given to the next factory.  The return value of the last
+factory is returned as the result of the adapter lookup.  For examle:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.adapter.A1
+  ...                zope.component.testfiles.adapter.A2
+  ...                zope.component.testfiles.adapter.A3"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       />''')
+
+The resulting adapter is an A3, around an A2, around an A1, around the
+adapted object:
+
+  >>> content = Content()
+  >>> a3 = IApp(content)
+  >>> a3.__class__ is A3
+  True
+
+  >>> a2 = a3.context[0]
+  >>> a2.__class__ is A2
+  True
+
+  >>> a1 = a2.context[0]
+  >>> a1.__class__ is A1
+  True
+
+  >>> a1.context[0] is content
+  True
+
+Of course, if no factory is provided at all, we will get an error:
+
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory=""
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-8.8
+      ValueError: No factory specified
+
+
+Declaring ``for`` and ``provides`` in Python
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The <adapter /> directive can figure out from the in-line Python
+declaration (using ``zope.component.adapts()`` or
+``zope.component.adapter()`` as well as ``zope.interface.implements``)
+what the adapter should be registered for and what it provides::
+
+  >>> clearZCML()
+  >>> IApp(Content(), None) is None
+  True
+
+  >>> runSnippet('''
+  ...   <adapter factory="zope.component.testfiles.components.Comp" />''')
+
+  >>> IApp(Content()).__class__
+  <class 'zope.component.testfiles.components.Comp'>
+
+Of course, if the adapter has no ``implements()`` declaration, ZCML
+can't figure out what it provides:
+
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.adapter.A4"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
+      TypeError: Missing 'provides' attribute
+
+On the other hand, if the factory implements more than one interface,
+ZCML can't figure out what it should provide either:
+
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.adapter.A5"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
+      TypeError: Missing 'provides' attribute
+
+A not so common edge case is registering adapters directly for
+classes, not for interfaces.  For example:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for="zope.component.testfiles.components.Content"
+  ...       provides="zope.component.testfiles.adapter.I1"
+  ...       factory="zope.component.testfiles.adapter.A1"
+  ...       />''')
+
+  >>> content = Content()
+  >>> a1 = zope.component.getAdapter(content, I1, '')
+  >>> isinstance(a1, A1)
+  True
+
+This time, any object providing ``IContent`` won't work if it's not an
+instance of the ``Content`` class:
+
+  >>> import zope.interface
+  >>> class MyContent:
+  ...     zope.interface.implements(IContent)
+  >>> zope.component.getAdapter(MyContent(), I1, '')  # doctest: +ELLIPSIS
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: ...
+
+Multi-adapters
+~~~~~~~~~~~~~~
+
+Conventional adapters adapt one object to provide another interface.
+Multi-adapters adapt several objects at once:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1
+  ...            zope.component.testfiles.adapter.I2"
+  ...       provides="zope.component.testfiles.adapter.I3"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       />''')
+
+  >>> content = Content()
+  >>> a1 = A1()
+  >>> a2 = A2()
+  >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == (content, a1, a2)
+  True
+
+You can even adapt an empty list of objects (we call this a
+null-adapter):
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for=""
+  ...       provides="zope.component.testfiles.adapter.I3"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       />''')
+
+  >>> a3 = zope.component.queryMultiAdapter((), I3)
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == ()
+  True
+
+Even with multi-adapters, ZCML can figure out the ``for`` and
+``provides`` parameters from the Python declarations:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter factory="zope.component.testfiles.adapter.A3" />''')
+
+  >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == (content, a1, a2)
+  True
+
+Chained factories are not supported for multi-adapters, though:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1
+  ...            zope.component.testfiles.adapter.I2"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       factory="zope.component.testfiles.adapter.A1
+  ...                zope.component.testfiles.adapter.A2"
+  ...       />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-11.8
+      ValueError: Can't use multiple factories and multiple for
+
+And neither for null-adapters:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for=""
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       factory="zope.component.testfiles.adapter.A1
+  ...                zope.component.testfiles.adapter.A2"
+  ...       />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-9.8
+      ValueError: Can't use multiple factories and multiple for
+
+Protected adapters
+~~~~~~~~~~~~~~~~~~
+
+Adapters can be protected with a permission.  First we have to define
+a permission for which we'll have to register the <permission />
+directive:
+
+  >>> clearZCML()
+  >>> IApp(Content(), None) is None
+  True
+
+  >>> import zope.security
+  >>> from zope.configuration.xmlconfig import XMLConfig
+  >>> XMLConfig('meta.zcml', zope.security)()
+  >>> runSnippet('''
+  ...   <permission
+  ...       id="y.x"
+  ...       title="XY"
+  ...       description="Allow XY."
+  ...       />
+  ...   <adapter
+  ...       factory="zope.component.testfiles.components.Comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       permission="y.x"
+  ...       />''')
+
+We see that the adapter is a location proxy now so that the
+appropriate permissions can be found from the context:
+
+  >>> IApp(Content()).__class__
+  <class 'zope.component.testfiles.components.Comp'>
+  >>> type(IApp(Content()))
+  <class 'zope.location.location.LocationProxy'>
+
+We can also go about it a different way.  Let's make a public adapter
+and wrap the adapter in a security proxy.  That often happens when
+an adapter is turned over to untrusted code:
+
+  >>> clearZCML()
+  >>> IApp(Content(), None) is None
+  True
+
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.components.Comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       permission="zope.Public"
+  ...       />''')
+
+  >>> from zope.security.checker import ProxyFactory
+  >>> adapter = ProxyFactory(IApp(Content()))
+  >>> from zope.security.proxy import getTestProxyItems
+  >>> items = [item[0] for item in getTestProxyItems(adapter)]
+  >>> items
+  ['a', 'f']
+
+  >>> from zope.security.proxy import removeSecurityProxy
+  >>> removeSecurityProxy(adapter).__class__ is Comp
+  True
+
+Of course, this still works when we let the ZCML directive handler
+figure out ``for`` and ``provides`` from the Python declarations:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.components.Comp"
+  ...       permission="zope.Public"
+  ...       />''')
+
+  >>> adapter = ProxyFactory(IApp(Content()))
+  >>> [item[0] for item in getTestProxyItems(adapter)]
+  ['a', 'f']
+  >>> removeSecurityProxy(adapter).__class__ is Comp
+  True
+
+It also works with multi adapters:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       provides="zope.component.testfiles.adapter.I3"
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1
+  ...            zope.component.testfiles.adapter.I2"
+  ...       permission="zope.Public"
+  ...       />''')
+
+  >>> content = Content()
+  >>> a1 = A1()
+  >>> a2 = A2()
+  >>> a3 = ProxyFactory(zope.component.queryMultiAdapter((content, a1, a2), I3))
+  >>> a3.__class__ == A3
+  True
+  >>> [item[0] for item in getTestProxyItems(a3)]
+  ['f1', 'f2', 'f3']
+
+It's probably not worth mentioning, but when we try to protect an
+adapter with a permission that doesn't exist, we'll obviously get an
+error:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.components.Comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       permission="zope.UndefinedPermission"
+  ...       />''')
+  Traceback (most recent call last):
+    ...
+  ConfigurationExecutionError: exceptions.ValueError: ('Undefined permission id', 'zope.UndefinedPermission')
+    in:
+    File "<string>", line 4.2-9.8
+    Could not read source.
+
+Trusted adapters
+~~~~~~~~~~~~~~~~
+
+Trusted adapters are adapters that are trusted to do anything with the
+objects they are given so that these objects are not security-proxied.
+They are registered using the ``trusted`` argument to the <adapter />
+directive:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       provides="zope.component.testfiles.adapter.I1"
+  ...       factory="zope.component.testfiles.adapter.A1"
+  ...       trusted="yes"
+  ...       />''')
+
+With an unproxied object, it's business as usual:
+
+  >>> ob = Content()
+  >>> type(I1(ob)) is A1
+  True
+
+With a security-proxied object, however, we get a security-proxied
+adapter:
+
+  >>> p = ProxyFactory(ob)
+  >>> a = I1(p)
+  >>> type(a)
+  <type 'zope.security._proxy._Proxy'>
+
+While the adapter is security-proxied, the object it adapts is now
+proxy-free.  The adapter has umlimited access to it:
+
+  >>> a = removeSecurityProxy(a)
+  >>> type(a) is A1
+  True
+  >>> a.context[0] is ob
+  True
+
+We can also protect the trusted adapter with a permission:
+
+  >>> clearZCML()
+  >>> XMLConfig('meta.zcml', zope.security)()
+  >>> runSnippet('''
+  ...   <permission
+  ...       id="y.x"
+  ...       title="XY"
+  ...       description="Allow XY."
+  ...       />
+  ...   <adapter
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       provides="zope.component.testfiles.adapter.I1"
+  ...       factory="zope.component.testfiles.adapter.A1"
+  ...       permission="y.x"
+  ...       trusted="yes"
+  ...       />''')
+
+Again, with an unproxied object, it's business as usual:
+
+  >>> ob = Content()
+  >>> type(I1(ob)) is A1
+  True
+
+With a security-proxied object, we again get a security-proxied
+adapter:
+
+  >>> p = ProxyFactory(ob)
+  >>> a = I1(p)
+  >>> type(a)
+  <type 'zope.security._proxy._Proxy'>
+
+Since we protected the adapter with a permission, we now encounter a
+location proxy behind the security proxy:
+
+  >>> a = removeSecurityProxy(a)
+  >>> type(a)
+  <class 'zope.location.location.LocationProxy'>
+  >>> a.context[0] is ob
+  True
+
+There's one exception to all of this: When you use the public
+permission (``zope.Public``), there will be no location proxy:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       provides="zope.component.testfiles.adapter.I1"
+  ...       factory="zope.component.testfiles.adapter.A1"
+  ...       permission="zope.Public"
+  ...       trusted="yes"
+  ...       />''')
+
+  >>> ob = Content()
+  >>> p = ProxyFactory(ob)
+  >>> a = I1(p)
+  >>> type(a)
+  <type 'zope.security._proxy._Proxy'>
+
+  >>> a = removeSecurityProxy(a)
+  >>> type(a) is A1
+  True
+
+We can also explicitply pass the ``locate`` argument to make sure we
+get location proxies:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       provides="zope.component.testfiles.adapter.I1"
+  ...       factory="zope.component.testfiles.adapter.A1"
+  ...       trusted="yes"
+  ...       locate="yes"
+  ...       />''')
+
+  >>> ob = Content()
+  >>> p = ProxyFactory(ob)
+  >>> a = I1(p)
+  >>> type(a)
+  <type 'zope.security._proxy._Proxy'>
+
+  >>> a = removeSecurityProxy(a)
+  >>> type(a)
+  <class 'zope.location.location.LocationProxy'>
+
+
+subscriber
+----------
+
+With the <subscriber /> directive you can register subscription
+adapters or event subscribers with the adapter registry.  Consider
+this very typical example of a <subscriber /> directive:
+ 
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       provides="zope.component.testfiles.adapter.IS"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1"
+  ...       />''')
+
+  >>> content = Content()
+  >>> a1 = A1()
+
+  >>> subscribers = zope.component.subscribers((content, a1), IS)
+  >>> a3 = subscribers[0]
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == (content, a1)
+  True
+
+Note how ZCML provides some additional information when registering
+components, such as the ZCML filename and line numbers:
+
+  >>> sm = zope.component.getSiteManager()
+  >>> doc = [reg.info for reg in sm.registeredSubscriptionAdapters()
+  ...        if reg.provided is IS][0]
+  >>> print doc
+  File "<string>", line 4.2-9.8
+    Could not read source.
+
+The "fun" behind subscription adapters/subscribers is that when
+several ones are declared for the same for/provides, they are all
+found.  With regular adapters, the most specific one (and in doubt the
+one registered last) wins.  Consider these two subscribers:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       provides="zope.component.testfiles.adapter.IS"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1"
+  ...       />
+  ...   <subscriber
+  ...       provides="zope.component.testfiles.adapter.IS"
+  ...       factory="zope.component.testfiles.adapter.A2"
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1"
+  ...       />''')
+
+  >>> subscribers = zope.component.subscribers((content, a1), IS)
+  >>> len(subscribers)
+  2
+  >>> sorted([a.__class__.__name__ for a in subscribers])
+  ['A2', 'A3']
+
+Declaring ``for`` and ``provides`` in Python
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Like the <adapter /> directive, the <subscriber /> directive can
+figure out from the in-line Python declaration (using
+``zope.component.adapts()`` or ``zope.component.adapter()``) what the
+subscriber should be registered for:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       provides="zope.component.testfiles.adapter.IS"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       />''')
+
+  >>> content = Content()
+  >>> a2 = A2()
+  >>> subscribers = zope.component.subscribers((content, a1, a2), IS)
+
+  >>> a3 = subscribers[0]
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == (content, a1, a2)
+  True
+
+In the same way the directive can figure out what a subscriber
+provides:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber handler="zope.component.testfiles.adapter.A3" />''')
+
+  >>> sm = zope.component.getSiteManager()
+  >>> a3 = sm.adapters.subscriptions((IContent, I1, I2), None)[0]
+  >>> a3 is A3
+  True
+
+A not so common edge case is declaring subscribers directly for
+classes, not for interfaces.  For example:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       for="zope.component.testfiles.components.Content"
+  ...       provides="zope.component.testfiles.adapter.I1"
+  ...       factory="zope.component.testfiles.adapter.A1"
+  ...       />''')
+
+  >>> subs = list(zope.component.subscribers((Content(),), I1))
+  >>> isinstance(subs[0], A1)
+  True
+
+This time, any object providing ``IContent`` won't work if it's not an
+instance of the ``Content`` class:
+
+  >>> list(zope.component.subscribers((MyContent(),), I1))
+  []
+
+Protected subscribers
+~~~~~~~~~~~~~~~~~~~~~
+
+Subscribers can also be protected with a permission.  First we have to
+define a permission for which we'll have to register the <permission />
+directive:
+
+  >>> clearZCML()
+  >>> XMLConfig('meta.zcml', zope.security)()
+  >>> runSnippet('''
+  ...   <permission
+  ...       id="y.x"
+  ...       title="XY"
+  ...       description="Allow XY."
+  ...       />
+  ...   <subscriber
+  ...       provides="zope.component.testfiles.adapter.IS"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1"
+  ...       permission="y.x"
+  ...       />''')
+
+  >>> subscribers = zope.component.subscribers((content, a1), IS)
+  >>> a3 = subscribers[0]
+  >>> a3.__class__ is A3
+  True
+  >>> type(a3)
+  <class 'zope.location.location.LocationProxy'>
+  >>> a3.context == (content, a1)
+  True
+
+Trusted subscribers
+~~~~~~~~~~~~~~~~~~~
+
+Like trusted adapters, trusted subscribers are subscribers that are
+trusted to do anything with the objects they are given so that these
+objects are not security-proxied.  In analogy to the <adapter />
+directive, they are registered using the ``trusted`` argument to the
+<subscriber /> directive:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       provides="zope.component.testfiles.adapter.IS"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1"
+  ...       trusted="yes"
+  ...       />''')
+
+With an unproxied object, it's business as usual:
+
+  >>> subscribers = zope.component.subscribers((content, a1), IS)
+  >>> a3 = subscribers[0]
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == (content, a1)
+  True
+  >>> type(a3) is A3
+  True
+
+Now with a proxied object.  We will see that the subscriber has
+unproxied access to it, but the subscriber itself is proxied:
+
+  >>> p = ProxyFactory(content)
+  >>> a3 = zope.component.subscribers((p, a1), IS)[0]
+  >>> type(a3)
+  <type 'zope.security._proxy._Proxy'>
+
+There's no location proxy behind the security proxy:
+
+  >>> removeSecurityProxy(a3).context[0] is content
+  True
+  >>> type(removeSecurityProxy(a3)) is A3
+  True
+
+If you want the trusted subscriber to be located, you'll also have to
+use the ``locate`` argument:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       provides="zope.component.testfiles.adapter.IS"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1"
+  ...       trusted="yes"
+  ...       locate="yes"
+  ...       />''')
+
+Again, it's business as usual with an unproxied object:
+
+  >>> subscribers = zope.component.subscribers((content, a1), IS)
+  >>> a3 = subscribers[0]
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == (content, a1)
+  True
+  >>> type(a3) is A3
+  True
+
+With a proxied object, we again get a security-proxied subscriber:
+
+  >>> p = ProxyFactory(content)
+  >>> a3 = zope.component.subscribers((p, a1), IS)[0]
+
+  >>> type(a3)
+  <type 'zope.security._proxy._Proxy'>
+
+  >>> removeSecurityProxy(a3).context[0] is content
+  True
+
+However, thanks to the ``locate`` argument, we now have a location
+proxy behind the security proxy:
+
+  >>> type(removeSecurityProxy(a3))
+  <class 'zope.location.location.LocationProxy'>
+
+Event subscriber (handlers)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sometimes, subscribers don't need to be adapters that actually provide
+anything.  It's enough that a callable is called for a certain event.
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1"
+  ...       handler="zope.component.testfiles.adapter.Handler"
+  ...       />''')
+
+In this case, simply getting the subscribers is enough to invoke them:
+
+  >>> list(zope.component.subscribers((content, a1), None))
+  []
+  >>> content.args == ((a1,),)
+  True
+
+
+utility
+-------
+
+Apart from adapters (and subscription adapters), the Component
+Architecture knows a second kind of component: utilities.  They are
+registered using the <utility /> directive.
+
+Before we register the first test utility, we can verify that utility
+lookup doesn't work yet:
+
+  >>> clearZCML()
+  >>> zope.component.queryUtility(IApp) is None
+  True
+
+Then we register the utility:
+
+  >>> runSnippet('''
+  ...   <utility
+  ...       component="zope.component.testfiles.components.comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       />''')
+  >>> zope.component.getUtility(IApp) is comp
+  True
+
+Like adapters, utilities can also have names.  There can be more than
+one utility registered for a certain interface, as long as they each
+have a different name.
+
+First, we make sure that there's no utility yet:
+
+  >>> clearZCML()
+  >>> zope.component.queryUtility(IApp, 'test') is None
+  True
+
+Then we register it:
+
+  >>> runSnippet('''
+  ...   <utility
+  ...       component="zope.component.testfiles.components.comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       name="test"
+  ...       />''')
+  >>> zope.component.getUtility(IApp, 'test') is comp
+  True
+
+Utilities can also be registered from a factory.  In this case, the
+ZCML handler calls the factory (without any arguments) and registers
+the returned value as a utility.  Typically, you'd pass a class for
+the factory:
+
+  >>> clearZCML()
+  >>> zope.component.queryUtility(IApp) is None
+  True
+
+  >>> runSnippet('''
+  ...   <utility
+  ...       factory="zope.component.testfiles.components.Comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       />''')
+  >>> zope.component.getUtility(IApp).__class__ is Comp
+  True
+
+Declaring ``provides`` in Python
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Like other directives, <utility /> can also figure out which interface
+a utility provides from the Python declaration:
+
+  >>> clearZCML()
+  >>> zope.component.queryUtility(IApp) is None
+  True
+
+  >>> runSnippet('''
+  ...   <utility component="zope.component.testfiles.components.comp" />''')
+  >>> zope.component.getUtility(IApp) is comp
+  True
+
+It won't work if the component that is to be registered doesn't
+provide anything:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <utility component="zope.component.testfiles.adapter.a4" />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
+      TypeError: Missing 'provides' attribute
+
+Or if more than one interface is provided (then the ZCML directive
+handler doesn't know under which the utility should be registered):
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <utility component="zope.component.testfiles.adapter.a5" />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
+      TypeError: Missing 'provides' attribute
+
+We can repeat the same drill for utility factories:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <utility factory="zope.component.testfiles.components.Comp" />''')
+  >>> zope.component.getUtility(IApp).__class__ is Comp
+  True
+
+  >>> runSnippet('''
+  ...   <utility factory="zope.component.testfiles.adapter.A4" />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
+      TypeError: Missing 'provides' attribute
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <utility factory="zope.component.testfiles.adapter.A5" />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
+      TypeError: Missing 'provides' attribute
+
+Protected utilities
+~~~~~~~~~~~~~~~~~~~
+
+TODO::
+
+    def testProtectedUtility(self):
+        """Test that we can protect a utility.
+
+        Also:
+        Check that multiple configurations for the same utility and
+        don't interfere.
+        """
+        self.assertEqual(zope.component.queryUtility(IV), None)
+        xmlconfig(StringIO(template % (
+            '''
+            <permission id="tell.everyone" title="Yay" />
+            <utility
+              component="zope.component.testfiles.components.comp"
+              provides="zope.component.testfiles.components.IApp"
+              permission="tell.everyone"
+              />
+            <permission id="top.secret" title="shhhh" />
+            <utility
+              component="zope.component.testfiles.components.comp"
+              provides="zope.component.testfiles.components.IAppb"
+              permission="top.secret"
+              />
+            '''
+            )))
+
+        utility = ProxyFactory(zope.component.getUtility(IApp))
+        items = getTestProxyItems(utility)
+        self.assertEqual(items, [('a', 'tell.everyone'),
+                                 ('f', 'tell.everyone')
+                                 ])
+        self.assertEqual(removeSecurityProxy(utility), comp)
+
+    def testUtilityUndefinedPermission(self):
+        config = StringIO(template % (
+             '''
+             <utility
+              component="zope.component.testfiles.components.comp"
+              provides="zope.component.testfiles.components.IApp"
+              permission="zope.UndefinedPermission"
+              />
+            '''
+            ))
+        self.assertRaises(ValueError, xmlconfig, config,
+                          testing=1)
+
+interface
+---------
+
+The <interface /> directive lets us register an interface.  Interfaces
+are registered as named utilities.  We therefore needn't go though all
+the lookup details again, it is sufficient to see whether the
+directive handler emits the right actions.
+
+First we provide a stub configuration context:
+
+  >>> import re, pprint
+  >>> atre = re.compile(' at [0-9a-fA-Fx]+')
+  >>> class Context(object):
+  ...    actions = ()
+  ...    def action(self, discriminator, callable, args):
+  ...        self.actions += ((discriminator, callable, args), )
+  ...    def __repr__(self):
+  ...        stream = StringIO()
+  ...        pprinter = pprint.PrettyPrinter(stream=stream, width=60)
+  ...        pprinter.pprint(self.actions)
+  ...        r = stream.getvalue()
+  ...        return (''.join(atre.split(r))).strip()
+  >>> context = Context()
+
+Then we provide a test interface that we'd like to register:
+
+  >>> from zope.interface import Interface
+  >>> class I(Interface):
+  ...     pass
+
+It doesn't yet provide ``ITestType``:
+
+  >>> from zope.component.tests.test_doctests import ITestType
+  >>> ITestType.providedBy(I)
+  False
+
+However, after calling the directive handler...
+
+  >>> from zope.component.zcml import interface
+  >>> interface(context, I, ITestType)
+  >>> context
+  ((None,
+    <function provideInterface>,
+    ('',
+     <InterfaceClass __builtin__.I>,
+     <InterfaceClass zope.component.tests.test_doctests.ITestType>)),)
+
+...it does provide ``ITestType``:
+
+  >>> from zope.interface.interfaces import IInterface
+  >>> ITestType.extends(IInterface)
+  True
+  >>> IInterface.providedBy(I)
+  True

Copied: zope.component/tseaver-test_cleanup/docs/zcml_conditional.rst (from rev 125846, zope.component/tseaver-test_cleanup/src/zope/component/zcml_conditional.txt)
===================================================================
--- zope.component/tseaver-test_cleanup/docs/zcml_conditional.rst	                        (rev 0)
+++ zope.component/tseaver-test_cleanup/docs/zcml_conditional.rst	2012-06-17 17:39:11 UTC (rev 126886)
@@ -0,0 +1,611 @@
+ZCML directives without zope.security support
+=============================================
+
+This tests run without zope.security available:
+
+  >>> from zope.component.zcml import check_security_support
+  >>> check_security_support()
+  Traceback (most recent call last):
+  ...
+  ConfigurationError: security proxied components are not supported because zope.security is not available
+
+Components may be registered using the registration API exposed by
+``zope.component`` (provideAdapter, provideUtility, etc.).  They may
+also be registered using configuration files.  The common way to do
+that is by using ZCML (Zope Configuration Markup Language), an XML
+spelling of component registration.
+
+In ZCML, each XML element is a *directive*.  There are different
+top-level directives that let us register components.  We will
+introduce them one by one here.
+
+This helper will let us easily execute ZCML snippets:
+
+  >>> from cStringIO import StringIO
+  >>> from zope.configuration.xmlconfig import xmlconfig
+  >>> def runSnippet(snippet):
+  ...     template = """\
+  ...     <configure xmlns='http://namespaces.zope.org/zope'
+  ...                i18n_domain="zope">
+  ...     %s
+  ...     </configure>"""
+  ...     xmlconfig(StringIO(template % snippet))
+
+adapter
+-------
+
+Adapters play a key role in the Component Architecture.  In ZCML, they
+are registered with the <adapter /> directive.
+
+  >>> from zope.component.testfiles.adapter import A1, A2, A3, Handler
+  >>> from zope.component.testfiles.adapter import I1, I2, I3, IS
+  >>> from zope.component.testfiles.components import IContent, Content, Comp, comp
+
+Before we register the first test adapter, we can verify that adapter
+lookup doesn't work yet:
+
+  >>> from zope.component.tests.test_doctests import clearZCML
+  >>> clearZCML()
+  >>> from zope.component.testfiles.components import IApp
+  >>> IApp(Content(), None) is None
+  True
+
+Then we register the adapter and see that the lookup works:
+
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.components.Comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       />''')
+
+  >>> IApp(Content()).__class__
+  <class 'zope.component.testfiles.components.Comp'>
+
+It is also possible to give adapters names.  Then the combination of
+required interface, provided interface and name makes the adapter
+lookup unique.  The name is supplied using the ``name`` argument to
+the <adapter /> directive:
+
+  >>> clearZCML()
+  >>> import zope.component
+  >>> zope.component.queryAdapter(Content(), IApp, 'test') is None
+  True
+
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.components.Comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       name="test"
+  ...       />''')
+
+  >>> zope.component.getAdapter(Content(), IApp, 'test').__class__
+  <class 'zope.component.testfiles.components.Comp'>
+
+Adapter factories
+~~~~~~~~~~~~~~~~~
+
+It is possible to supply more than one adapter factory.  In this case,
+during adapter lookup each factory will be called and the return value
+will be given to the next factory.  The return value of the last
+factory is returned as the result of the adapter lookup.  For examle:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.adapter.A1
+  ...                zope.component.testfiles.adapter.A2
+  ...                zope.component.testfiles.adapter.A3"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       />''')
+
+The resulting adapter is an A3, around an A2, around an A1, around the
+adapted object:
+
+  >>> content = Content()
+  >>> a3 = IApp(content)
+  >>> a3.__class__ is A3
+  True
+
+  >>> a2 = a3.context[0]
+  >>> a2.__class__ is A2
+  True
+
+  >>> a1 = a2.context[0]
+  >>> a1.__class__ is A1
+  True
+
+  >>> a1.context[0] is content
+  True
+
+Of course, if no factory is provided at all, we will get an error:
+
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory=""
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-8.8
+      ValueError: No factory specified
+
+Declaring ``for`` and ``provides`` in Python
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The <adapter /> directive can figure out from the in-line Python
+declaration (using ``zope.component.adapts()`` or
+``zope.component.adapter()`` as well as ``zope.interface.implements``)
+what the adapter should be registered for and what it provides::
+
+  >>> clearZCML()
+  >>> IApp(Content(), None) is None
+  True
+
+  >>> runSnippet('''
+  ...   <adapter factory="zope.component.testfiles.components.Comp" />''')
+
+  >>> IApp(Content()).__class__
+  <class 'zope.component.testfiles.components.Comp'>
+
+Of course, if the adapter has no ``implements()`` declaration, ZCML
+can't figure out what it provides:
+
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.adapter.A4"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
+      TypeError: Missing 'provides' attribute
+
+On the other hand, if the factory implements more than one interface,
+ZCML can't figure out what it should provide either:
+
+  >>> runSnippet('''
+  ...   <adapter
+  ...       factory="zope.component.testfiles.adapter.A5"
+  ...       for="zope.component.testfiles.components.IContent"
+  ...       />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
+      TypeError: Missing 'provides' attribute
+
+A not so common edge case is registering adapters directly for
+classes, not for interfaces.  For example:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for="zope.component.testfiles.components.Content"
+  ...       provides="zope.component.testfiles.adapter.I1"
+  ...       factory="zope.component.testfiles.adapter.A1"
+  ...       />''')
+
+  >>> content = Content()
+  >>> a1 = zope.component.getAdapter(content, I1, '')
+  >>> isinstance(a1, A1)
+  True
+
+This time, any object providing ``IContent`` won't work if it's not an
+instance of the ``Content`` class:
+
+  >>> import zope.interface
+  >>> class MyContent:
+  ...     zope.interface.implements(IContent)
+  >>> zope.component.getAdapter(MyContent(), I1, '')  # doctest: +ELLIPSIS
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: ...
+
+Multi-adapters
+~~~~~~~~~~~~~~
+
+Conventional adapters adapt one object to provide another interface.
+Multi-adapters adapt several objects at once:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1
+  ...            zope.component.testfiles.adapter.I2"
+  ...       provides="zope.component.testfiles.adapter.I3"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       />''')
+
+  >>> content = Content()
+  >>> a1 = A1()
+  >>> a2 = A2()
+  >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == (content, a1, a2)
+  True
+
+You can even adapt an empty list of objects (we call this a
+null-adapter):
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for=""
+  ...       provides="zope.component.testfiles.adapter.I3"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       />''')
+
+  >>> a3 = zope.component.queryMultiAdapter((), I3)
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == ()
+  True
+
+Even with multi-adapters, ZCML can figure out the ``for`` and
+``provides`` parameters from the Python declarations:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter factory="zope.component.testfiles.adapter.A3" />''')
+
+  >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == (content, a1, a2)
+  True
+
+Chained factories are not supported for multi-adapters, though:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1
+  ...            zope.component.testfiles.adapter.I2"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       factory="zope.component.testfiles.adapter.A1
+  ...                zope.component.testfiles.adapter.A2"
+  ...       />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-11.8
+      ValueError: Can't use multiple factories and multiple for
+
+And neither for null-adapters:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <adapter
+  ...       for=""
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       factory="zope.component.testfiles.adapter.A1
+  ...                zope.component.testfiles.adapter.A2"
+  ...       />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-9.8
+      ValueError: Can't use multiple factories and multiple for
+
+subscriber
+----------
+
+With the <subscriber /> directive you can register subscription
+adapters or event subscribers with the adapter registry.  Consider
+this very typical example of a <subscriber /> directive:
+ 
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       provides="zope.component.testfiles.adapter.IS"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1"
+  ...       />''')
+
+  >>> content = Content()
+  >>> a1 = A1()
+
+  >>> subscribers = zope.component.subscribers((content, a1), IS)
+  >>> a3 = subscribers[0]
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == (content, a1)
+  True
+
+Note how ZCML provides some additional information when registering
+components, such as the ZCML filename and line numbers:
+
+  >>> sm = zope.component.getSiteManager()
+  >>> doc = [reg.info for reg in sm.registeredSubscriptionAdapters()
+  ...        if reg.provided is IS][0]
+  >>> print doc
+  File "<string>", line 4.2-9.8
+    Could not read source.
+
+The "fun" behind subscription adapters/subscribers is that when
+several ones are declared for the same for/provides, they are all
+found.  With regular adapters, the most specific one (and in doubt the
+one registered last) wins.  Consider these two subscribers:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       provides="zope.component.testfiles.adapter.IS"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1"
+  ...       />
+  ...   <subscriber
+  ...       provides="zope.component.testfiles.adapter.IS"
+  ...       factory="zope.component.testfiles.adapter.A2"
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1"
+  ...       />''')
+
+  >>> subscribers = zope.component.subscribers((content, a1), IS)
+  >>> len(subscribers)
+  2
+  >>> sorted([a.__class__.__name__ for a in subscribers])
+  ['A2', 'A3']
+
+Declaring ``for`` and ``provides`` in Python
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Like the <adapter /> directive, the <subscriber /> directive can
+figure out from the in-line Python declaration (using
+``zope.component.adapts()`` or ``zope.component.adapter()``) what the
+subscriber should be registered for:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       provides="zope.component.testfiles.adapter.IS"
+  ...       factory="zope.component.testfiles.adapter.A3"
+  ...       />''')
+
+  >>> content = Content()
+  >>> a2 = A2()
+  >>> subscribers = zope.component.subscribers((content, a1, a2), IS)
+
+  >>> a3 = subscribers[0]
+  >>> a3.__class__ is A3
+  True
+  >>> a3.context == (content, a1, a2)
+  True
+
+In the same way the directive can figure out what a subscriber
+provides:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber handler="zope.component.testfiles.adapter.A3" />''')
+
+  >>> sm = zope.component.getSiteManager()
+  >>> a3 = sm.adapters.subscriptions((IContent, I1, I2), None)[0]
+  >>> a3 is A3
+  True
+
+A not so common edge case is declaring subscribers directly for
+classes, not for interfaces.  For example:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       for="zope.component.testfiles.components.Content"
+  ...       provides="zope.component.testfiles.adapter.I1"
+  ...       factory="zope.component.testfiles.adapter.A1"
+  ...       />''')
+
+  >>> subs = list(zope.component.subscribers((Content(),), I1))
+  >>> isinstance(subs[0], A1)
+  True
+
+This time, any object providing ``IContent`` won't work if it's not an
+instance of the ``Content`` class:
+
+  >>> list(zope.component.subscribers((MyContent(),), I1))
+  []
+
+Event subscriber (handlers)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sometimes, subscribers don't need to be adapters that actually provide
+anything.  It's enough that a callable is called for a certain event.
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <subscriber
+  ...       for="zope.component.testfiles.components.IContent
+  ...            zope.component.testfiles.adapter.I1"
+  ...       handler="zope.component.testfiles.adapter.Handler"
+  ...       />''')
+
+In this case, simply getting the subscribers is enough to invoke them:
+
+  >>> list(zope.component.subscribers((content, a1), None))
+  []
+  >>> content.args == ((a1,),)
+  True
+
+
+utility
+-------
+
+Apart from adapters (and subscription adapters), the Component
+Architecture knows a second kind of component: utilities.  They are
+registered using the <utility /> directive.
+
+Before we register the first test utility, we can verify that utility
+lookup doesn't work yet:
+
+  >>> clearZCML()
+  >>> zope.component.queryUtility(IApp) is None
+  True
+
+Then we register the utility:
+
+  >>> runSnippet('''
+  ...   <utility
+  ...       component="zope.component.testfiles.components.comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       />''')
+  >>> zope.component.getUtility(IApp) is comp
+  True
+
+Like adapters, utilities can also have names.  There can be more than
+one utility registered for a certain interface, as long as they each
+have a different name.
+
+First, we make sure that there's no utility yet:
+
+  >>> clearZCML()
+  >>> zope.component.queryUtility(IApp, 'test') is None
+  True
+
+Then we register it:
+
+  >>> runSnippet('''
+  ...   <utility
+  ...       component="zope.component.testfiles.components.comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       name="test"
+  ...       />''')
+  >>> zope.component.getUtility(IApp, 'test') is comp
+  True
+
+Utilities can also be registered from a factory.  In this case, the
+ZCML handler calls the factory (without any arguments) and registers
+the returned value as a utility.  Typically, you'd pass a class for
+the factory:
+
+  >>> clearZCML()
+  >>> zope.component.queryUtility(IApp) is None
+  True
+
+  >>> runSnippet('''
+  ...   <utility
+  ...       factory="zope.component.testfiles.components.Comp"
+  ...       provides="zope.component.testfiles.components.IApp"
+  ...       />''')
+  >>> zope.component.getUtility(IApp).__class__ is Comp
+  True
+
+Declaring ``provides`` in Python
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Like other directives, <utility /> can also figure out which interface
+a utility provides from the Python declaration:
+
+  >>> clearZCML()
+  >>> zope.component.queryUtility(IApp) is None
+  True
+
+  >>> runSnippet('''
+  ...   <utility component="zope.component.testfiles.components.comp" />''')
+  >>> zope.component.getUtility(IApp) is comp
+  True
+
+It won't work if the component that is to be registered doesn't
+provide anything:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <utility component="zope.component.testfiles.adapter.a4" />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
+      TypeError: Missing 'provides' attribute
+
+Or if more than one interface is provided (then the ZCML directive
+handler doesn't know under which the utility should be registered):
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <utility component="zope.component.testfiles.adapter.a5" />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
+      TypeError: Missing 'provides' attribute
+
+We can repeat the same drill for utility factories:
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <utility factory="zope.component.testfiles.components.Comp" />''')
+  >>> zope.component.getUtility(IApp).__class__ is Comp
+  True
+
+  >>> runSnippet('''
+  ...   <utility factory="zope.component.testfiles.adapter.A4" />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
+      TypeError: Missing 'provides' attribute
+
+  >>> clearZCML()
+  >>> runSnippet('''
+  ...   <utility factory="zope.component.testfiles.adapter.A5" />''')
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
+      TypeError: Missing 'provides' attribute
+
+interface
+---------
+
+The <interface /> directive lets us register an interface.  Interfaces
+are registered as named utilities.  We therefore needn't go though all
+the lookup details again, it is sufficient to see whether the
+directive handler emits the right actions.
+
+First we provide a stub configuration context:
+
+  >>> import re, pprint
+  >>> atre = re.compile(' at [0-9a-fA-Fx]+')
+  >>> class Context(object):
+  ...    actions = ()
+  ...    def action(self, discriminator, callable, args):
+  ...        self.actions += ((discriminator, callable, args), )
+  ...    def __repr__(self):
+  ...        stream = StringIO()
+  ...        pprinter = pprint.PrettyPrinter(stream=stream, width=60)
+  ...        pprinter.pprint(self.actions)
+  ...        r = stream.getvalue()
+  ...        return (''.join(atre.split(r))).strip()
+  >>> context = Context()
+
+Then we provide a test interface that we'd like to register:
+
+  >>> from zope.interface import Interface
+  >>> class I(Interface):
+  ...     pass
+
+It doesn't yet provide ``ITestType``:
+
+  >>> from zope.component.tests.test_doctests import ITestType
+  >>> ITestType.providedBy(I)
+  False
+
+However, after calling the directive handler...
+
+  >>> from zope.component.zcml import interface
+  >>> interface(context, I, ITestType)
+  >>> context
+  ((None,
+    <function provideInterface>,
+    ('',
+     <InterfaceClass __builtin__.I>,
+     <InterfaceClass zope.component.tests.test_doctests.ITestType>)),)
+
+...it does provide ``ITestType``:
+
+  >>> from zope.interface.interfaces import IInterface
+  >>> ITestType.extends(IInterface)
+  True
+  >>> IInterface.providedBy(I)
+  True

Modified: zope.component/tseaver-test_cleanup/setup.py
===================================================================
--- zope.component/tseaver-test_cleanup/setup.py	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/setup.py	2012-06-17 17:39:11 UTC (rev 126886)
@@ -80,25 +80,7 @@
     long_description=(
         read('README.txt')
         + '\n' +
-        'Detailed Documentation\n'
-        '**********************\n'
-        + '\n' +
-        read('src', 'zope', 'component', 'README.txt')
-        + '\n' +
-        read('src', 'zope', 'component', 'event.txt')
-        + '\n' +
-        read('src', 'zope', 'component', 'factory.txt')
-        + '\n' +
-        read('src', 'zope', 'component', 'registry.txt')
-        + '\n' +
-        read('src', 'zope', 'component', 'persistentregistry.txt')
-        + '\n' +
-        read('src', 'zope', 'component', 'socketexample.txt')
-        + '\n' +
         read('CHANGES.txt')
-        + '\n' +
-        'Download\n'
-        '********\n'
         ),
     packages = find_packages('src'),
     package_dir = {'': 'src'},

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/README.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/README.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/README.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,402 +0,0 @@
-Zope Component Architecture
-===========================
-
-This package, together with `zope.interface`, provides facilities for
-defining, registering and looking up components.  There are two basic
-kinds of components: adapters and utilities.
-
-Utilities
----------
-
-Utilities are just components that provide an interface and that are
-looked up by an interface and a name.  Let's look at a trivial utility
-definition:
-
-    >>> from zope import interface
-
-    >>> class IGreeter(interface.Interface):
-    ...     def greet():
-    ...         "say hello"
-
-    >>> class Greeter:
-    ...     interface.implements(IGreeter)
-    ...
-    ...     def __init__(self, other="world"):
-    ...         self.other = other
-    ...
-    ...     def greet(self):
-    ...         print "Hello", self.other
-
-We can register an instance this class using `provideUtility` [1]_:
-
-    >>> from zope import component
-    >>> greet = Greeter('bob')
-    >>> component.provideUtility(greet, IGreeter, 'robert')
-
-In this example we registered the utility as providing the `IGreeter`
-interface with a name of 'bob'. We can look the interface up with
-either `queryUtility` or `getUtility`:
-
-    >>> component.queryUtility(IGreeter, 'robert').greet()
-    Hello bob
-
-    >>> component.getUtility(IGreeter, 'robert').greet()
-    Hello bob
-
-`queryUtility` and `getUtility` differ in how failed lookups are handled:
-
-    >>> component.queryUtility(IGreeter, 'ted')
-    >>> component.queryUtility(IGreeter, 'ted', 42)
-    42
-    >>> component.getUtility(IGreeter, 'ted')
-    ... # doctest: +ELLIPSIS
-    Traceback (most recent call last):
-    ...
-    ComponentLookupError: (<InterfaceClass ...IGreeter>, 'ted')
-
-If a component provides only one interface, as in the example above,
-then we can omit the provided interface from the call to `provideUtility`:
-
-    >>> ted = Greeter('ted')
-    >>> component.provideUtility(ted, name='ted')
-    >>> component.queryUtility(IGreeter, 'ted').greet()
-    Hello ted
-
-The name defaults to an empty string:
-
-    >>> world = Greeter()
-    >>> component.provideUtility(world)
-    >>> component.queryUtility(IGreeter).greet()
-    Hello world
-
-Adapters
---------
-
-Adapters are components that are computed from other components to
-adapt them to some interface.  Because they are computed from other
-objects, they are provided as factories, usually classes.  Here, we'll
-create a greeter for persons, so we can provide personalized greetings
-for different people:
-
-    >>> class IPerson(interface.Interface):
-    ...     name = interface.Attribute("Name")
-
-    >>> class PersonGreeter:
-    ...
-    ...     component.adapts(IPerson)
-    ...     interface.implements(IGreeter)
-    ...
-    ...     def __init__(self, person):
-    ...         self.person = person
-    ...
-    ...     def greet(self):
-    ...         print "Hello", self.person.name
-
-The class defines a constructor that takes an argument for every
-object adapted.
-
-We used `component.adapts` to declare what we adapt.  We can find
-out if an object declares that it adapts anything using adaptedBy:
-
-    >>> list(component.adaptedBy(PersonGreeter)) == [IPerson]
-    True
-
-If an object makes no declaration, then None is returned:
-
-    >>> component.adaptedBy(Greeter()) is None
-    True
-
-
-If we declare the interfaces adapted and if we provide only one
-interface, as in the example above, then we can provide the adapter
-very simply [1]_:
-
-    >>> component.provideAdapter(PersonGreeter)
-
-For adapters that adapt a single interface to a single interface
-without a name, we can get the adapter by simply calling the
-interface:
-
-    >>> class Person:
-    ...     interface.implements(IPerson)
-    ...
-    ...     def __init__(self, name):
-    ...         self.name = name
-
-    >>> IGreeter(Person("Sally")).greet()
-    Hello Sally
-
-We can also provide arguments to be very specific about what
-how to register the adapter.
-
-    >>> class BobPersonGreeter(PersonGreeter):
-    ...     name = 'Bob'
-    ...     def greet(self):
-    ...         print "Hello", self.person.name, "my name is", self.name
-
-    >>> component.provideAdapter(
-    ...                        BobPersonGreeter, [IPerson], IGreeter, 'bob')
-
-The arguments can also be provided as keyword arguments:
-
-    >>> class TedPersonGreeter(BobPersonGreeter):
-    ...     name = "Ted"
-
-    >>> component.provideAdapter(
-    ...     factory=TedPersonGreeter, adapts=[IPerson],
-    ...     provides=IGreeter, name='ted')
-
-For named adapters, use `queryAdapter`, or `getAdapter`:
-
-    >>> component.queryAdapter(Person("Sally"), IGreeter, 'bob').greet()
-    Hello Sally my name is Bob
-
-    >>> component.getAdapter(Person("Sally"), IGreeter, 'ted').greet()
-    Hello Sally my name is Ted
-
-If an adapter can't be found, `queryAdapter` returns a default value
-and `getAdapter` raises an error:
-
-    >>> component.queryAdapter(Person("Sally"), IGreeter, 'frank')
-    >>> component.queryAdapter(Person("Sally"), IGreeter, 'frank', 42)
-    42
-    >>> component.getAdapter(Person("Sally"), IGreeter, 'frank')
-    ... # doctest: +ELLIPSIS
-    Traceback (most recent call last):
-    ...
-    ComponentLookupError: (...Person...>, <...IGreeter>, 'frank')
-
-Adapters can adapt multiple objects:
-
-    >>> class TwoPersonGreeter:
-    ...
-    ...     component.adapts(IPerson, IPerson)
-    ...     interface.implements(IGreeter)
-    ...
-    ...     def __init__(self, person, greeter):
-    ...         self.person = person
-    ...         self.greeter = greeter
-    ...
-    ...     def greet(self):
-    ...         print "Hello", self.person.name
-    ...         print "my name is", self.greeter.name
-
-    >>> component.provideAdapter(TwoPersonGreeter)
-
-Note that the declaration-order of the Interfaces beeing adapted to is
-important for adapter look up. It must be the the same as the order of
-parameters given to the adapter and used to query the adapter. This is
-especially the case when different Interfaces are adapt to (opposed to
-this example).
-
-To look up a multi-adapter, use either `queryMultiAdapter` or
-`getMultiAdapter`:
-
-    >>> component.queryMultiAdapter((Person("Sally"), Person("Bob")),
-    ...                                  IGreeter).greet()
-    Hello Sally
-    my name is Bob
-
-Adapters need not be classes.  Any callable will do.  We use the
-adapter decorator (in the Python 2.4 decorator sense) to declare that
-a callable object adapts some interfaces (or classes):
-
-    >>> class IJob(interface.Interface):
-    ...     "A job"
-
-    >>> class Job:
-    ...     interface.implements(IJob)
-
-    >>> def personJob(person):
-    ...     return getattr(person, 'job', None)
-    >>> personJob = interface.implementer(IJob)(personJob)
-    >>> personJob = component.adapter(IPerson)(personJob)
-
-In Python 2.4, the example can be written:
-
-    >>> @interface.implementer(IJob)
-    ... @component.adapter(IPerson)
-    ... def personJob(person):
-    ...     return getattr(person, 'job', None)
-
-which looks a bit nicer.
-
-In this example, the personJob function simply returns the person's
-`job` attribute if present, or None if it's not present.  An adapter
-factory can return None to indicate that adaptation wasn't possible.
-Let's register this adapter and try it out:
-
-    >>> component.provideAdapter(personJob)
-    >>> sally = Person("Sally")
-    >>> IJob(sally) # doctest: +ELLIPSIS
-    Traceback (most recent call last):
-    ...
-    TypeError: ('Could not adapt', ...
-
-The adaptation failed because sally didn't have a job.  Let's give her
-one:
-
-    >>> job = Job()
-    >>> sally.job = job
-    >>> IJob(sally) is job
-    True
-
-Subscription Adapters
----------------------
-
-Unlike regular adapters, subscription adapters are used when we want
-all of the adapters that adapt an object to a particular adapter.
-
-Consider a validation problem.  We have objects and we want to assess
-whether they meet some sort of standards.  We define a validation
-interface:
-
-    >>> class IValidate(interface.Interface):
-    ...     def validate(ob):
-    ...         """Determine whether the object is valid
-    ...
-    ...         Return a string describing a validation problem.
-    ...         An empty string is returned to indicate that the
-    ...         object is valid.
-    ...         """
-
-Perhaps we have documents:
-
-    >>> class IDocument(interface.Interface):
-    ...     summary = interface.Attribute("Document summary")
-    ...     body = interface.Attribute("Document text")
-
-    >>> class Document:
-    ...     interface.implements(IDocument)
-    ...     def __init__(self, summary, body):
-    ...         self.summary, self.body = summary, body
-
-Now, we may want to specify various validation rules for
-documents. For example, we might require that the summary be a single
-line:
-
-    >>> class SingleLineSummary:
-    ...     component.adapts(IDocument)
-    ...     interface.implements(IValidate)
-    ...
-    ...     def __init__(self, doc):
-    ...         self.doc = doc
-    ...
-    ...     def validate(self):
-    ...         if '\n' in self.doc.summary:
-    ...             return 'Summary should only have one line'
-    ...         else:
-    ...             return ''
-
-Or we might require the body to be at least 1000 characters in length:
-
-    >>> class AdequateLength:
-    ...     component.adapts(IDocument)
-    ...     interface.implements(IValidate)
-    ...
-    ...     def __init__(self, doc):
-    ...         self.doc = doc
-    ...
-    ...     def validate(self):
-    ...         if len(self.doc.body) < 1000:
-    ...             return 'too short'
-    ...         else:
-    ...             return ''
-
-We can register these as subscription adapters [1]_:
-
-    >>> component.provideSubscriptionAdapter(SingleLineSummary)
-    >>> component.provideSubscriptionAdapter(AdequateLength)
-
-We can then use the subscribers to validate objects:
-
-    >>> doc = Document("A\nDocument", "blah")
-    >>> [adapter.validate()
-    ...  for adapter in component.subscribers([doc], IValidate)
-    ...  if adapter.validate()]
-    ['Summary should only have one line', 'too short']
-
-    >>> doc = Document("A\nDocument", "blah" * 1000)
-    >>> [adapter.validate()
-    ...  for adapter in component.subscribers([doc], IValidate)
-    ...  if adapter.validate()]
-    ['Summary should only have one line']
-
-    >>> doc = Document("A Document", "blah")
-    >>> [adapter.validate()
-    ...  for adapter in component.subscribers([doc], IValidate)
-    ...  if adapter.validate()]
-    ['too short']
-
-Handlers
---------
-
-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.
-
-Event subscribers are different from other subscription adapters in
-that the caller of event subscribers doesn't expect to interact with
-them in any direct way.  For example, an event publisher doesn't
-expect to get any return value.  Because subscribers don't need to
-provide an API to their callers, it is more natural to define them
-with functions, rather than classes.  For example, in a
-document-management system, we might want to record creation times for
-documents:
-
-    >>> import datetime
-
-    >>> def documentCreated(event):
-    ...     event.doc.created = datetime.datetime.utcnow()
-
-In this example, we have a function that takes an event and performs
-some processing.  It doesn't actually return anything.  This is a
-special case of a subscription adapter that adapts an event to
-nothing.  All of the work is done when the adapter "factory" is
-called.  We call subscribers that don't actually create anything
-"handlers".  There are special APIs for registering and calling
-them.
-
-To register the subscriber above, we define a document-created event:
-
-    >>> class IDocumentCreated(interface.Interface):
-    ...     doc = interface.Attribute("The document that was created")
-
-    >>> class DocumentCreated:
-    ...     interface.implements(IDocumentCreated)
-    ...
-    ...     def __init__(self, doc):
-    ...         self.doc = doc
-
-We'll also change our handler definition to:
-
-    >>> def documentCreated(event):
-    ...     event.doc.created = datetime.datetime.utcnow()
-
-    >>> documentCreated = component.adapter(IDocumentCreated)(documentCreated)
-
-Note that in Python 2.4, this can be written:
-
-    >>> @component.adapter(IDocumentCreated)
-    ... def documentCreated(event):
-    ...     event.doc.created = datetime.datetime.utcnow()
-
-This marks the handler as an adapter of `IDocumentCreated` events.
-
-Now we'll register the handler  [1]_:
-
-    >>> component.provideHandler(documentCreated)
-
-Now, if we can create an event and use the `handle` function to call
-handlers registered for the event:
-
-    >>> component.handle(DocumentCreated(doc))
-    >>> doc.created.__class__.__name__
-    'datetime'
-
-
-
-.. [1] 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.

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/configure.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/configure.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/configure.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,13 +0,0 @@
-Package configuration
-=====================
-
-The ``zope.component`` package provides a ZCML file that configures some basic
-components:
-
-  >>> from zope.configuration.xmlconfig import XMLConfig
-  >>> import zope.component
-
-  >>> XMLConfig('configure.zcml', zope.component)()
-
-  >>> len(list(zope.component.getGlobalSiteManager().registeredHandlers()))
-  5

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/event.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/event.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/event.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,142 +0,0 @@
-Events
-======
-
-The Component Architecture provides a way to dispatch events to event
-handlers.  Event handlers are registered as *subscribers*
-a.k.a. *handlers*.
-
-Before we can start we need to import ``zope.component.event`` to make
-the dispatching effective:
-
-  >>> import zope.component.event
-
-Consider two event classes:
-
-  >>> class Event1(object):
-  ...     pass
-
-  >>> class Event2(Event1):
-  ...     pass
-
-Now consider two handlers for these event classes:
-
-  >>> called = []
-
-  >>> import zope.component
-  >>> @zope.component.adapter(Event1)
-  ... def handler1(event):
-  ...     called.append(1)
-
-  >>> @zope.component.adapter(Event2)
-  ... def handler2(event):
-  ...     called.append(2)
-
-We can register them with the Component Architecture:
-
-  >>> zope.component.provideHandler(handler1)
-  >>> zope.component.provideHandler(handler2)
-
-Now let's go through the events.  We'll see that the handlers have been
-called accordingly:
-
-  >>> from zope.event import notify
-  >>> notify(Event1())
-  >>> called
-  [1]
-
-  >>> del called[:]
-  >>> notify(Event2())
-  >>> called.sort()
-  >>> called
-  [1, 2]
-
-
-
-Object events
--------------
-
-
-The ``objectEventNotify`` function is a subscriber to dispatch
-ObjectEvents to interested adapters.
-
-First create an object class:
-
-  >>> class IUseless(zope.interface.Interface):
-  ...     """Useless object"""
-
-  >>> class UselessObject(object):
-  ...     """Useless object"""
-  ...     zope.interface.implements(IUseless)
-
-Then create an event class:
-
-  >>> class IObjectThrownEvent(zope.component.interfaces.IObjectEvent):
-  ...     """An object has been thrown away"""
-
-  >>> class ObjectThrownEvent(zope.component.interfaces.ObjectEvent):
-  ...     """An object has been thrown away"""
-  ...     zope.interface.implements(IObjectThrownEvent)
-
-Create an object and an event:
-
-  >>> hammer = UselessObject()
-  >>> event = ObjectThrownEvent(hammer)
-
-Then notify the event to the subscribers.
-Since the subscribers list is empty, nothing happens.
-
-  >>> zope.component.event.objectEventNotify(event)
-
-Now create an handler for the event:
-
-  >>> events = []
-  >>> def record(*args):
-  ...     events.append(args)
-
-  >>> zope.component.provideHandler(record, [IUseless, IObjectThrownEvent])
-
-The event is notified to the subscriber:
-
-  >>> zope.component.event.objectEventNotify(event)
-  >>> events == [(hammer, event)]
-  True
-
-Following test demonstrates how a subscriber can raise an exception
-to prevent an action.
-
-  >>> zope.component.provideHandler(zope.component.event.objectEventNotify)
-
-Let's create a container:
-
-  >>> class ToolBox(dict):
-  ...     def __delitem__(self, key):
-  ...         notify(ObjectThrownEvent(self[key]))
-  ...         return super(ToolBox,self).__delitem__(key)
-
-  >>> container = ToolBox()
-
-And put the object into the container:
-
-  >>> container['Red Hammer'] = hammer
-
-Create an handler function that will raise an error when called:
-
-  >>> class Veto(Exception):
-  ...     pass
-
-  >>> def callback(item, event):
-  ...     assert(item == event.object)
-  ...     raise Veto
-
-Register the handler:
-
-  >>> zope.component.provideHandler(callback, [IUseless, IObjectThrownEvent])
-
-Then if we try to remove the object, an ObjectThrownEvent is fired:
-
-  >>> del container['Red Hammer']
-  ... # doctest: +NORMALIZE_WHITESPACE
-  Traceback (most recent call last):
-  ...
-      raise Veto
-  Veto

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/factory.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/factory.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/factory.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,131 +0,0 @@
-Factories
-=========
-
-
-The Factory Class
------------------
-
-  >>> from zope.interface import Interface
-  >>> class IFunction(Interface):
-  ...     pass
-
-  >>> class IKlass(Interface):
-  ...     pass
-
-  >>> from zope.interface import implements
-  >>> class Klass(object):
-  ...     implements(IKlass)
-  ... 
-  ...     def __init__(self, *args, **kw):
-  ...         self.args = args
-  ...         self.kw = kw
-
-  >>> from zope.component.factory import Factory
-  >>> factory = Factory(Klass, 'Klass', 'Klassier')
-  >>> factory2 = Factory(lambda x: x, 'Func', 'Function')
-  >>> factory3 = Factory(lambda x: x, 'Func', 'Function', (IFunction,))
-
-Calling a Factory
-~~~~~~~~~~~~~~~~~
-
-Here we test whether the factory correctly creates the objects and
-including the correct handling of constructor elements.
-
-First we create a factory that creates instanace of the `Klass` class:
-
-  >>> factory = Factory(Klass, 'Klass', 'Klassier')
-
-Now we use the factory to create the instance
-
-  >>> kl = factory(1, 2, foo=3, bar=4)
-
-and make sure that the correct class was used to create the object:
-
-  >>> kl.__class__
-  <class 'Klass'>
-
-Since we passed in a couple positional and keyword arguments
-  
-  >>> kl.args
-  (1, 2)
-  >>> kl.kw
-  {'foo': 3, 'bar': 4}
-  
-  >>> factory2(3)
-  3
-  >>> factory3(3)
-  3
-
-
-Title and Description
-~~~~~~~~~~~~~~~~~~~~~
-
-  >>> factory.title
-  'Klass'
-  >>> factory.description
-  'Klassier'
-  >>> factory2.title
-  'Func'
-  >>> factory2.description
-  'Function'
-  >>> factory3.title
-  'Func'
-  >>> factory3.description
-  'Function'
-
-
-Provided Interfaces
-~~~~~~~~~~~~~~~~~~~
-
-  >>> implemented = factory.getInterfaces()
-  >>> implemented.isOrExtends(IKlass)
-  True
-  >>> list(implemented)
-  [<InterfaceClass __builtin__.IKlass>]
-  
-  >>> implemented2 = factory2.getInterfaces()
-  >>> list(implemented2)
-  []
-  
-  >>> implemented3 = factory3.getInterfaces()
-  >>> list(implemented3)
-  [<InterfaceClass __builtin__.IFunction>]
-
-
-The Component Architecture Factory API
---------------------------------------
-
-  >>> import zope.component
-  >>> factory = Factory(Klass, 'Klass', 'Klassier')
-  >>> gsm = zope.component.getGlobalSiteManager() 
-
-  >>> from zope.component.interfaces import IFactory
-  >>> gsm.registerUtility(factory, IFactory, 'klass')
-
-Creating an Object
-~~~~~~~~~~~~~~~~~~
-
-  >>> kl = zope.component.createObject('klass', 1, 2, foo=3, bar=4)
-  >>> isinstance(kl, Klass)
-  True
-  >>> kl.args
-  (1, 2)
-  >>> kl.kw
-  {'foo': 3, 'bar': 4}
-
-Accessing Provided Interfaces
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-  >>> implemented = zope.component.getFactoryInterfaces('klass')
-  >>> implemented.isOrExtends(IKlass)
-  True
-  >>> [iface for iface in implemented]
-  [<InterfaceClass __builtin__.IKlass>]
-
-List of All Factories
-~~~~~~~~~~~~~~~~~~~~~
-
-  >>> [(name, fac.__class__) for name, fac in
-  ...  zope.component.getFactoriesFor(IKlass)]
-  [(u'klass', <class 'zope.component.factory.Factory'>)]
-

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/hooks.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/hooks.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/hooks.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,97 +0,0 @@
-==============================
-The current component registry
-==============================
-
-There can be any number of component registries in an application. One of them
-is the global component registry, and there is also the concept of a currently
-used component registry. Component registries other than the global one are
-associated with objects called sites. The ``zope.component.hooks`` module
-provides an API to set and access the current site as well as manipulate the
-adapter hook associated with it.
-
-As long as we haven't set a site, none is being considered current:
-
->>> from zope.component.hooks import getSite
->>> print getSite()
-None
-
-We can also ask for the current component registry (aka site manager
-historically); it will return the global one if no current site is set:
-
->>> from zope.component.hooks import getSiteManager
->>> getSiteManager()
-<BaseGlobalComponents base>
-
-Let's set a site now. A site has to be an object that provides the
-``getSiteManager`` method, which is specified by
-``zope.component.interfaces.IPossibleSite``:
-
->>> from zope.interface.registry import Components
->>> class Site(object):
-...     def __init__(self):
-...         self.registry = Components('components')
-...     def getSiteManager(self):
-...         return self.registry
-
->>> from zope.component.hooks import setSite
->>> site1 = Site()
->>> setSite(site1)
-
-After this, the newly set site is considered the currently active one:
-
->>> getSite() is site1
-True
->>> getSiteManager() is site1.registry
-True
-
-If we set another site, that one will be considered current:
-
->>> site2 = Site()
->>> site2.registry is not site1.registry
-True
->>> setSite(site2)
-
->>> getSite() is site2
-True
->>> getSiteManager() is site2.registry
-True
-
-Finally we can unset the site and the global component registry is used again:
-
->>> setSite()
->>> print getSite()
-None
->>> getSiteManager()
-<BaseGlobalComponents base>
-
-
-Context manager
-===============
-
-There also is a context manager for setting the site, which is especially
-useful when writing tests:
-
->>> import zope.component.hooks
->>> dummy = with_statement # support for Python-2.5
->>> print getSite()
-None
->>> with zope.component.hooks.site(site2):
-...     getSite() is site2
-True
->>> print getSite()
-None
-
-The site is properly restored even if the body of the with statement
-raises an exception:
-
->>> print getSite()
-None
->>> with zope.component.hooks.site(site2):
-...    getSite() is site2
-...    raise ValueError('An error in the body')
-Traceback (most recent call last):
-    ...
-ValueError: An error in the body
->>> print getSite()
-None
-

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/index.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/index.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/index.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,22 +0,0 @@
-Welcome to zope.component's documentation!
-==========================================
-
-Contents:
-
-.. toctree::
-   :maxdepth: 2
-
-   README
-   socketexample
-   event
-   factory
-   registry
-   persistentregistry
-   zcml
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/persistentregistry.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/persistentregistry.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/persistentregistry.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,6 +0,0 @@
-Persistent Component Management
-===============================
-
-Persistent component management allows persistent management of
-components.  From a usage point of view, there shouldn't be any new
-behavior beyond what's described in registry.txt.

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/registry.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/registry.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/registry.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,1117 +0,0 @@
-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.component.registry.Components class provides an
-implementation of zope.component.interfaces.IComponents that provides
-these features.
-
-    >>> from zope.component import registry
-    >>> from zope.component 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.component.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.component.tests.I1> 
-    U1(1) 
-    <InterfaceClass zope.component.tests.I2> 
-    U12(2) 
-    <InterfaceClass zope.component.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.component.tests.I1> 
-    U1(4) use 4 now
-    <InterfaceClass zope.component.tests.I2> 
-    U12(2) 
-    <InterfaceClass zope.component.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.component.tests.I2> 
-    U12(2) 
-    <InterfaceClass zope.component.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.component.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.component.tests.I1>, 
-     <InterfaceClass zope.component.tests.I2>)
-    <InterfaceClass zope.component.tests.IA1> 
-    zope.component.tests.A12_1 
-    (<InterfaceClass zope.component.tests.I1>, 
-     <InterfaceClass zope.component.tests.I2>)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A12_ 
-    (<InterfaceClass zope.component.tests.I1>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A1_12 
-    (<InterfaceClass zope.component.tests.I3>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A_2 
-    (<implementedBy zope.component.tests.U>,)
-    <InterfaceClass zope.component.tests.IA3> 
-    zope.component.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.component.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.component.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.component.tests.I1>, 
-     <InterfaceClass zope.component.tests.I2>)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A12_ 
-    (<InterfaceClass zope.component.tests.I1>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A1_12 
-    (<InterfaceClass zope.component.tests.I3>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A_2 
-    (<implementedBy zope.component.tests.U>,)
-    <InterfaceClass zope.component.tests.IA3> 
-    zope.component.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.component.tests.U>,)
-    <InterfaceClass zope.component.tests.IA3> 
-    zope.component.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.component.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.component.tests.I1>,)
-    <InterfaceClass zope.component.tests.IA2> test 2
-    zope.component.tests.A1_23 
-    (<InterfaceClass zope.component.tests.IA1>,)
-    <InterfaceClass zope.component.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.component.tests.I1>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A a sample comment
-    (<InterfaceClass zope.component.tests.I1>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A a sample comment
-    (<InterfaceClass zope.component.tests.I1>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A1_12 
-    (<InterfaceClass zope.component.tests.I1>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A1_2 
-    (<InterfaceClass zope.component.tests.I1>,)
-    <InterfaceClass zope.component.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.component.tests.I1>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A a sample comment
-    (<InterfaceClass zope.component.tests.I1>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A a sample comment
-    (<InterfaceClass zope.component.tests.I1>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A1_12 
-    (<InterfaceClass zope.component.tests.I1>,)
-    <InterfaceClass zope.component.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.component.tests.I1>,)
-    <InterfaceClass zope.component.tests.IA2> 
-    zope.component.tests.A1_12 
-    (<InterfaceClass zope.component.tests.I1>,)
-    <InterfaceClass zope.component.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 component
-    >>> @component.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)
-
-    >>> @component.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.component.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.component.tests.I1>,)
-    <function handle1 at 0xb78f5bfc> First handler
-    (<InterfaceClass zope.component.tests.I1>,
-     <InterfaceClass zope.component.tests.I2>)
-    <function handle12 at 0xb78f5c34> 
-    (<InterfaceClass zope.component.tests.I1>,)
-    <function handle at 0xb78f5ca4> a comment
-    (<implementedBy zope.component.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.component.tests.U], u'', 
-                        None, '')
-    True
-
-    >>> for registration in components.registeredHandlers():
-    ...     print registration.required
-    ...     print registration.handler, registration.info
-    ... # doctest: +NORMALIZE_WHITESPACE
-    (<InterfaceClass zope.component.tests.I1>,)
-    <function handle1 at 0xb78f5bfc> First handler
-    (<InterfaceClass zope.component.tests.I1>,
-     <InterfaceClass zope.component.tests.I2>)
-    <function handle12 at 0xb78f5c34> 
-    (<InterfaceClass zope.component.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.component.tests.I1>,)
-    <function handle1 at 0xb78f5bfc> First handler
-    (<InterfaceClass zope.component.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.component.tests.U], u'', 
-                        handle, u'')
-    
-    >>> @component.adapter(tests.I1)
-    ... def handle3(x):
-    ...     print 'handle3', x
-    >>> c3.registerHandler(handle3)
-    Registered event:
-    HandlerRegistration(<Components 3>, [I1], u'', handle3, u'')
-    
-    >>> @component.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)
-
-Redispatch of registration events
----------------------------------
-
-Some handlers are available that, if registered, redispatch
-registration events to the objects being registered.  They depend on
-being dispatched to by the object-event dispatcher:
-
-    >>> from zope import component
-    >>> import zope.component.event
-    >>> zope.component.getGlobalSiteManager().registerHandler(
-    ...      zope.component.event.objectEventNotify)
-    ... # doctest: +NORMALIZE_WHITESPACE
-    Registered event:
-    HandlerRegistration(<BaseGlobalComponents base>, 
-                        [IObjectEvent], u'', objectEventNotify, u'')
-
-To see this, we'll first register a multi-handler to show is when
-handlers are called on 2 objects:
-
-    >>> @zope.component.adapter(None, None)
-    ... def double_handler(o1, o2):
-    ...     print 'Double dispatch:'
-    ...     print ' ', o1
-    ...     print ' ', o2
-    >>> zope.component.getGlobalSiteManager().registerHandler(double_handler)
-    ... # doctest: +NORMALIZE_WHITESPACE
-    Double dispatch:
-      HandlerRegistration(<BaseGlobalComponents base>, 
-                          [Interface, Interface], u'', double_handler, u'')
-      Registered event:
-      HandlerRegistration(<BaseGlobalComponents base>, 
-      [Interface, Interface], u'', double_handler, u'')
-    Registered event:
-    HandlerRegistration(<BaseGlobalComponents base>, 
-                        [Interface, Interface], u'', double_handler, u'')
-
-In the example above, the double_handler reported it's own registration. :)
-
-Now we'll register our handlers:
-
-    >>> zope.component.getGlobalSiteManager().registerHandler(
-    ...     registry.dispatchUtilityRegistrationEvent)
-    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
-    Double dispatch:
-    ...
-
-    >>> zope.component.getGlobalSiteManager().registerHandler(
-    ...     registry.dispatchAdapterRegistrationEvent)
-    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
-    Double dispatch:
-    ...
-
-    >>> zope.component.getGlobalSiteManager().registerHandler(
-    ...     registry.dispatchSubscriptionAdapterRegistrationEvent)
-    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
-    Double dispatch:
-    ...
-
-    >>> zope.component.getGlobalSiteManager().registerHandler(
-    ...     registry.dispatchHandlerRegistrationEvent)
-    ... # doctest: +NORMALIZE_WHITESPACE
-    Double dispatch:
-      HandlerRegistration(<BaseGlobalComponents base>, 
-                          [IHandlerRegistration, IRegistrationEvent], u'', 
-                          dispatchHandlerRegistrationEvent, u'')
-      Registered event:
-      HandlerRegistration(<BaseGlobalComponents base>, 
-                          [IHandlerRegistration, IRegistrationEvent], u'', 
-                          dispatchHandlerRegistrationEvent, u'')
-    Double dispatch:
-      <function dispatchHandlerRegistrationEvent at 0xb799f72c>
-      Registered event:
-      HandlerRegistration(<BaseGlobalComponents base>,
-                          [IHandlerRegistration, IRegistrationEvent], u'',
-                          dispatchHandlerRegistrationEvent, u'')
-    Registered event:
-    HandlerRegistration(<BaseGlobalComponents base>,
-                        [IHandlerRegistration, IRegistrationEvent], u'',
-                        dispatchHandlerRegistrationEvent, u'')
-
-In the last example above, we can see that the registration of
-dispatchHandlerRegistrationEvent was handled by
-dispatchHandlerRegistrationEvent and redispatched.  This can be seen
-in the second double-dispatch output, where the first argument is the
-object being registered, which is dispatchHandlerRegistrationEvent.
-
-If we change some other registrations, we can the double dispatch
-taking place:
-
-    >>> components.registerUtility(u5)
-    ... # doctest: +NORMALIZE_WHITESPACE
-    Double dispatch:
-      UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
-      Registered event:
-      UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
-    Double dispatch:
-      U1(5)
-      Registered event:
-      UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
-    Registered event:
-    UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
-
-    >>> components.registerAdapter(tests.A12_1)
-    ... # doctest: +NORMALIZE_WHITESPACE
-    Double dispatch:
-      AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
-      Registered event:
-      AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
-    Double dispatch:
-      zope.component.tests.A12_1
-      Registered event:
-      AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
-    Registered event:
-    AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
-
-    >>> components.registerSubscriptionAdapter(tests.A1_2)
-    ... # doctest: +NORMALIZE_WHITESPACE
-    Double dispatch:
-      SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
-      Registered event:
-      SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
-    Double dispatch:
-      zope.component.tests.A1_2
-      Registered event:
-      SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
-    Registered event:
-    SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/socketexample.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/socketexample.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/socketexample.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,597 +0,0 @@
-The Zope 3 Component Architecture (Socket Example)
-==================================================
-
-The component architecture provides an application framework that provides its
-functionality through loosely-connected components. A *component* can be any
-Python object and has a particular purpose associated with it. Thus, in a
-component-based applications you have many small component in contrast to
-classical object-oriented development, where you have a few big objects. 
-
-Components communicate via specific APIs, which are formally defined by
-interfaces, which are provided by the `zope.interface` package. *Interfaces*
-describe the methods and properties that a component is expected to
-provide. They are also used as a primary mean to provide developer-level
-documentation for the components. For more details about interfaces see
-`zope/interface/README.txt`.
-
-The two main types of components are *adapters* and *utilities*. They will be
-discussed in detail later in this document. Both component types are managed
-by the *site manager*, with which you can register and access these
-components. However, most of the site manager's functionality is hidden behind
-the component architecture's public API, which is documented in
-`IComponentArchitecture`.
-
-
-Adapters
---------
-
-Adapters are a well-established pattern. An *adapter* uses an object providing
-one interface to produce an object that provides another interface. Here an
-example: Imagine that you purchased an electric shaver in the US, and thus
-you require the US socket type. You are now traveling in Germany, where another
-socket style is used. You will need a device, an adapter, that converts from
-the German to the US socket style.
-
-The functionality of adapters is actually natively provided by the
-`zope.interface` package and is thus well documented there. The `human.txt`
-file provides a gentle introduction to adapters, whereby `adapter.txt` is
-aimed at providing a comprehensive insight into adapters, but is too abstract
-for many as an initial read. Thus, we will only explain adapters in the context
-of the component architecture's API.
-
-So let's say that we have a German socket
-
-  >>> from zope.interface import Interface, implements
-
-  >>> class IGermanSocket(Interface):
-  ...     pass
-
-  >>> class Socket(object):
-  ...     def __repr__(self):
-  ...         return '<instance of %s>' %self.__class__.__name__
-
-  >>> class GermanSocket(Socket):
-  ...     """German wall socket."""
-  ...     implements(IGermanSocket)
-
-and we want to convert it to an US socket
-
-  >>> class IUSSocket(Interface):
-  ...     pass
-
-so that our shaver can be used in Germany. So we go to a German electronics
-store to look for an adapter that we can plug in the wall:
-
-  >>> class GermanToUSSocketAdapter(Socket):
-  ...     implements(IUSSocket)
-  ...     __used_for__ = IGermanSocket
-  ...     
-  ...     def __init__(self, socket):
-  ...         self.context = socket
-
-Note that I could have called the passed in socket any way I like, but
-`context` is the standard name accepted.
-
-
-Single Adapters
-~~~~~~~~~~~~~~~
-
-Before we can use the adapter, we have to buy it and make it part of our
-inventory. In the component architecture we do this by registering the adapter
-with the framework, more specifically with the global site manager:
-
-  >>> import zope.component
-  >>> gsm = zope.component.getGlobalSiteManager()
-  >>> gsm.registerAdapter(GermanToUSSocketAdapter, (IGermanSocket,), IUSSocket)
-
-`zope.component` is the component architecture API that is being
-presented by this file. You registered an adapter from `IGermanSocket`
-to `IUSSocket` having no name (thus the empty string).
-
-Anyways, you finally get back to your hotel room and shave, since you have not
-been able to shave in the plane. In the bathroom you discover a socket:
-
-  >>> bathroomDE = GermanSocket()
-  >>> IGermanSocket.providedBy(bathroomDE)
-  True
-
-You now insert the adapter in the German socket
-
-  >>> bathroomUS = zope.component.getAdapter(bathroomDE, IUSSocket, '')
-
-so that the socket now provides the US version:
-
-  >>> IUSSocket.providedBy(bathroomUS)
-  True
-
-Now you can insert your shaver and get on with your day. 
-
-After a week you travel for a couple of days to the Prague and you notice that
-the Czech have yet another socket type:
-
-  >>> class ICzechSocket(Interface):
-  ...     pass
-
-  >>> class CzechSocket(Socket):
-  ...     implements(ICzechSocket)
-
-  >>> czech = CzechSocket()
-
-You try to find an adapter for your shaver in your bag, but you fail, since
-you do not have one:
-
-  >>> zope.component.getAdapter(czech, IUSSocket, '') \
-  ... #doctest: +NORMALIZE_WHITESPACE
-  Traceback (most recent call last):
-  ...
-  ComponentLookupError: (<instance of CzechSocket>, 
-                         <InterfaceClass __builtin__.IUSSocket>,
-                         '')
-
-or the more graceful way:
-
-  >>> marker = object()
-  >>> socket = zope.component.queryAdapter(czech, IUSSocket, '', marker)
-  >>> socket is marker
-  True
-
-In the component architecture API any `get*` method will fail with a specific
-exception, if a query failed, whereby methods starting with `query*` will
-always return a `default` value after a failure.
-
-
-Named Adapters
-~~~~~~~~~~~~~~
-
-You are finally back in Germany. You also brought your DVD player and a couple
-DVDs with you, which you would like to watch. Your shaver was able to convert
-automatically from 110 volts to 240 volts, but your DVD player cannot. So you
-have to buy another adapter that also handles converting the voltage and the
-frequency of the AC current:
-
-  >>> class GermanToUSSocketAdapterAndTransformer(object):
-  ...     implements(IUSSocket)
-  ...     __used_for__ = IGermanSocket
-  ...     
-  ...     def __init__(self, socket):
-  ...         self.context = socket
-
-Now, we need a way to keep the two adapters apart. Thus we register them with
-a name:
-
-  >>> gsm.registerAdapter(GermanToUSSocketAdapter,
-  ...                     (IGermanSocket,), IUSSocket, 'shaver',)
-  >>> gsm.registerAdapter(GermanToUSSocketAdapterAndTransformer,
-  ...                     (IGermanSocket,), IUSSocket, 'dvd')
-
-Now we simply look up the adapters using their labels (called *name*):
-
-  >>> socket = zope.component.getAdapter(bathroomDE, IUSSocket, 'shaver')
-  >>> socket.__class__ is GermanToUSSocketAdapter
-  True
-
-  >>> socket = zope.component.getAdapter(bathroomDE, IUSSocket, 'dvd')
-  >>> socket.__class__ is GermanToUSSocketAdapterAndTransformer
-  True
-
-Clearly, we do not have an adapter for the MP3 player
-
-  >>> zope.component.getAdapter(bathroomDE, IUSSocket, 'mp3') \
-  ... #doctest: +NORMALIZE_WHITESPACE
-  Traceback (most recent call last):
-  ...
-  ComponentLookupError: (<instance of GermanSocket>, 
-                         <InterfaceClass __builtin__.IUSSocket>,
-                         'mp3')
-
-but you could use the 'dvd' adapter in this case of course. ;)
-
-Sometimes you want to know all adapters that are available. Let's say you want
-to know about all the adapters that convert a German to a US socket type:
-
-  >>> sockets = list(zope.component.getAdapters((bathroomDE,), IUSSocket))
-  >>> len(sockets)
-  3
-  >>> names = [name for name, socket in sockets]
-  >>> names.sort()
-  >>> names
-  [u'', u'dvd', u'shaver']
-
-`zope.component.getAdapters()` returns a list of tuples. The first
-entry of the tuple is the name of the adapter and the second is the
-adapter itself.
-
-
-Multi-Adapters
-~~~~~~~~~~~~~~
-
-After watching all the DVDs you brought at least twice, you get tired of them
-and you want to listen to some music using your MP3 player. But darn, the MP3
-player plug has a ground pin and all the adapters you have do not support
-that:
-
-  >>> class IUSGroundedSocket(IUSSocket):
-  ...     pass
-
-So you go out another time to buy an adapter. This time, however, you do not
-buy yet another adapter, but a piece that provides the grounding plug:
-
-  >>> class IGrounder(Interface):
-  ...     pass
-
-  >>> class Grounder(object):
-  ...     implements(IGrounder)
-  ...     def __repr__(self):
-  ...         return '<instance of Grounder>'
-
-
-Then together they will provided a grounded us socket:
-
-  >>> class GroundedGermanToUSSocketAdapter(object):
-  ...     implements(IUSGroundedSocket)
-  ...     __used_for__ = (IGermanSocket, IGrounder)
-  ...     def __init__(self, socket, grounder):
-  ...         self.socket, self.grounder = socket, grounder
-
-You now register the combination, so that you know you can create a
-`IUSGroundedSocket`:
-
-  >>> gsm.registerAdapter(GroundedGermanToUSSocketAdapter,
-  ...                 (IGermanSocket, IGrounder), IUSGroundedSocket, 'mp3')
-
-Given the grounder
-
-  >>> grounder = Grounder()
-
-and a German socket
-
-  >>> livingroom = GermanSocket()
-
-we can now get a grounded US socket:
-
-  >>> socket = zope.component.getMultiAdapter((livingroom, grounder), 
-  ...                                         IUSGroundedSocket, 'mp3')
-
-  >>> socket.__class__ is GroundedGermanToUSSocketAdapter
-  True
-  >>> socket.socket is livingroom
-  True
-  >>> socket.grounder is grounder
-  True
-
-Of course, you do not have a 'dvd' grounded US socket available:
-
-  >>> zope.component.getMultiAdapter((livingroom, grounder),
-  ...                                IUSGroundedSocket, 'dvd') \
-  ... #doctest: +NORMALIZE_WHITESPACE
-  Traceback (most recent call last):
-  ...
-  ComponentLookupError: ((<instance of GermanSocket>, 
-                          <instance of Grounder>), 
-                         <InterfaceClass __builtin__.IUSGroundedSocket>,
-                         'dvd')
-
-
-  >>> socket = zope.component.queryMultiAdapter(
-  ...     (livingroom, grounder), IUSGroundedSocket, 'dvd', marker)
-  >>> socket is marker
-  True
-
-Again, you might want to read `adapter.txt` in `zope.interface` for a more
-comprehensive coverage of multi-adapters.
-
-Subscribers
------------
-
-While subscribers are directly supported by the adapter registry and are
-adapters for all theoretical purposes, practically it might be better to think
-of them as separate components. Subscribers are particularly useful for
-events.
-
-Let's say one of our adapters overheated and caused a small fire:
-
-  >>> class IFire(Interface):
-  ...     pass
-
-  >>> class Fire(object):
-  ...     implements(IFire)
-
-  >>> fire = Fire()
-
-We want to use all available objects to put out the fire:
-
-  >>> class IFireExtinguisher(Interface):
-  ...     def extinguish():
-  ...         pass
-
-  >>> class FireExtinguisher(object):
-  ...     def __init__(self, fire):
-  ...         pass
-  ...     def extinguish(self):
-  ...         "Place extinguish code here."
-  ...         print 'Used ' + self.__class__.__name__ + '.'
-
-Here some specific methods to put out the fire:
-
-  >>> class PowderExtinguisher(FireExtinguisher):
-  ...     pass
-  >>> gsm.registerSubscriptionAdapter(PowderExtinguisher, 
-  ...                                 (IFire,), IFireExtinguisher)
-
-  >>> class Blanket(FireExtinguisher):
-  ...     pass
-  >>> gsm.registerSubscriptionAdapter(Blanket, (IFire,), IFireExtinguisher)
-
-  >>> class SprinklerSystem(FireExtinguisher):
-  ...     pass
-  >>> gsm.registerSubscriptionAdapter(SprinklerSystem,
-  ...                                 (IFire,), IFireExtinguisher)
-
-Now let use all these things to put out the fire:
-
-  >>> extinguishers = zope.component.subscribers((fire,), IFireExtinguisher)
-  >>> extinguishers.sort()
-  >>> for extinguisher in extinguishers:
-  ...     extinguisher.extinguish()
-  Used Blanket.
-  Used PowderExtinguisher.
-  Used SprinklerSystem.
-
-If no subscribers are found for a particular object, then an empty list is
-returned: 
-
-  >>> zope.component.subscribers((object(),), IFireExtinguisher)
-  []
-
-
-Utilities
----------
-
-Utilities are the second type of component, the component architecture
-implements. *Utilities* are simply components that provide an interface. When
-you register an utility, you always register an instance (in contrast to a
-factory for adapters) since the initialization and setup process of a utility
-might be complex and is not well defined. In some ways a utility is much more
-fundamental than an adapter, because an adapter cannot be used without another
-component, but a utility is always self-contained. I like to think of
-utilities as the foundation of your application and adapters as components
-extending beyond this foundation.
-
-Back to our story...
-
-After your vacation is over you fly back home to Tampa, Florida. But it is
-August now, the middle of the Hurricane season. And, believe it or not, you are
-worried that you will not be able to shave when the power goes out for several
-days. (You just hate wet shavers.)
-
-So you decide to go to your favorite hardware store and by a Diesel-powered
-electric generator. The generator provides of course a US-style socket:
-
-  >>> class Generator(object):
-  ...     implements(IUSSocket)
-  ...     def __repr__(self):
-  ...         return '<instance of Generator>'
-
-  >>> generator = Generator()
-
-Like for adapters, we now have to add the newly-acquired generator to our
-inventory by registering it as a utility:
-
-  >>> gsm.registerUtility(generator, IUSSocket)
-
-We can now get the utility using
-
-  >>> utility = zope.component.getUtility(IUSSocket)
-  >>> utility is generator
-  True
-
-As you can see, it is very simple to register and retrieve utilities. If a
-utility does not exist for a particular interface, such as the German socket,
-then the lookup fails
-
-  >>> zope.component.getUtility(IGermanSocket)
-  Traceback (most recent call last):
-  ...
-  ComponentLookupError: (<InterfaceClass __builtin__.IGermanSocket>, '')
-
-or more gracefully when specifying a default value:
-
-  >>> default = object()
-  >>> utility = zope.component.queryUtility(IGermanSocket, default=default)
-  >>> utility is default
-  True
-
-Note: The only difference between `getUtility()` and `queryUtility()` is the
-fact that you can specify a default value for the latter function, so that it
-will never cause a `ComponentLookupError`.
-
-
-Named Utilities
-~~~~~~~~~~~~~~~
-
-It is often desirable to have several utilities providing the same interface
-per site. This way you can implement any sort of registry using utilities. For
-this reason, utilities -- like adapters -- can be named.
-
-In the context of our story, we might want to do the following: You really do
-not trust gas stations either. What if the roads are blocked after a hurricane
-and the gas stations run out of oil. So you look for another renewable power
-source. Then you think about solar panels! After a storm there is usually very
-nice weather, so why not? Via the Web you order a set of 110V/120W solar
-panels that provide a regular US-style socket as output:
-
-  >>> class SolarPanel(object):
-  ...     implements(IUSSocket)
-  ...     def __repr__(self):
-  ...         return '<instance of Solar Panel>'
-
-  >>> panel = SolarPanel()
-
-Once it arrives, we add it to our inventory:
-
-  >>> gsm.registerUtility(panel, IUSSocket, 'Solar Panel')
-
-You can now access the solar panel using
-
-  >>> utility = zope.component.getUtility(IUSSocket, 'Solar Panel')
-  >>> utility is panel
-  True
-
-Of course, if a utility is not available, then the lookup will simply fail
-
-  >>> zope.component.getUtility(IUSSocket, 'Wind Mill')
-  Traceback (most recent call last):
-  ...
-  ComponentLookupError: (<InterfaceClass __builtin__.IUSSocket>, 'Wind Mill')
-
-or more gracefully when specifying a default value:
-
-  >>> default = object()
-  >>> utility = zope.component.queryUtility(IUSSocket, 'Wind Mill',
-  ...                                       default=default)
-  >>> utility is default
-  True
-
-Now you want to look at all the utilities you have for a particular kind. The
-following API function will return a list of name/utility pairs:
-
-  >>> utils = list(zope.component.getUtilitiesFor(IUSSocket))
-  >>> utils.sort()
-  >>> utils #doctest: +NORMALIZE_WHITESPACE
-  [(u'', <instance of Generator>), 
-   (u'Solar Panel', <instance of Solar Panel>)]
-
-Another method of looking up all utilities is by using
-`getAllUtilitiesRegisteredFor(iface)`. This function will return an iterable
-of utilities (without names); however, it will also return overridden
-utilities. If you are not using multiple site managers, you will not actually
-need this method.
-
-  >>> utils = list(zope.component.getAllUtilitiesRegisteredFor(IUSSocket))
-  >>> utils.sort()
-  >>> utils
-  [<instance of Generator>, <instance of Solar Panel>]
-
-
-Factories
-~~~~~~~~~
-
-A *factory* is a special kind of utility that exists to create other
-components. A factory is always identified by a name. It also provides a title
-and description and is able to tell the developer what interfaces the created
-object will provide. The advantage of using a factory to create an object
-instead of directly instantiating a class or executing any other callable is
-that we can refer to the factory by name. As long as the name stays fixed, the
-implementation of the callable can be renamed or moved without a breakage in
-code.
-
-Let's say that our solar panel comes in parts and they have to be
-assembled. This assembly would be done by a factory, so let's create one for
-the solar panel. To do this, we can use a standard implementation of the
-`IFactory` interface:
-
-  >>> from zope.component.factory import Factory
-  >>> factory = Factory(SolarPanel, 
-  ...                   'Solar Panel',
-  ...                   'This factory creates a solar panel.')
-
-Optionally, I could have also specified the interfaces that the created object
-will provide, but the factory class is smart enough to determine the
-implemented interface from the class. We now register the factory:
-
-  >>> from zope.component.interfaces import IFactory
-  >>> gsm.registerUtility(factory, IFactory, 'SolarPanel')
-
-We can now get a list of interfaces the produced object will provide:
-
-  >>> ifaces = zope.component.getFactoryInterfaces('SolarPanel')
-  >>> IUSSocket in ifaces
-  True
-
-By the way, this is equivalent to
-
-  >>> ifaces2 = factory.getInterfaces()
-  >>> ifaces is ifaces2
-  True
-
-Of course you can also just create an object:
-
-  >>> panel = zope.component.createObject('SolarPanel')
-  >>> panel.__class__ is SolarPanel
-  True
-
-Note: Ignore the first argument (`None`) for now; it is the context of the
-utility lookup, which is usually an optional argument, but cannot be in this
-case, since all other arguments beside the `name` are passed in as arguments
-to the specified callable.
-
-Once you register several factories
-
-  >>> gsm.registerUtility(Factory(Generator), IFactory, 'Generator')
-
-you can also determine, which available factories will create objects
-providing a certain interface:
-
-  >>> factories = zope.component.getFactoriesFor(IUSSocket)
-  >>> factories = [(name, factory.__class__) for name, factory in factories]
-  >>> factories.sort()
-  >>> factories #doctest: +NORMALIZE_WHITESPACE
-  [(u'Generator', <class 'zope.component.factory.Factory'>), 
-   (u'SolarPanel', <class 'zope.component.factory.Factory'>)]
-
-
-Site Managers
--------------
-
-Why do we need site managers? Why is the component architecture API not
-sufficient? Some applications, including Zope 3, have a concept of
-locations. It is often desirable to have different configurations for these
-location; this can be done by overwriting existing or adding new component
-registrations. Site managers in locations below the root location, should be
-able to delegate requests to their parent locations. The root site manager is
-commonly known as *global site manager*, since it is always available. You can
-always get the global site manager using the API:
-
-  >>> gsm = zope.component.getGlobalSiteManager()
-
-  >>> from zope.component import globalSiteManager
-  >>> gsm is globalSiteManager
-  True
-  >>> from zope.component.interfaces import IComponentLookup
-  >>> IComponentLookup.providedBy(gsm)
-  True
-  >>> from zope.component.interfaces import IComponents
-  >>> IComponents.providedBy(gsm)
-  True
-
-You can also lookup at site manager in a given context. The only requirement
-is that the context can be adapted to a site manager. So let's create a
-special site manager:
-
-  >>> from zope.component.globalregistry import BaseGlobalComponents
-  >>> sm = BaseGlobalComponents()
-
-Now we create a context that adapts to the site manager via the `__conform__`
-method as specified in PEP 246.
-
-  >>> class Context(object):
-  ...     def __init__(self, sm):
-  ...         self.sm = sm
-  ...     def __conform__(self, interface):
-  ...         if interface.isOrExtends(IComponentLookup):
-  ...             return self.sm
-
-We now instantiate the `Context` with our special site manager:
-
-  >>> context = Context(sm)
-  >>> context.sm is sm
-  True
-
-We can now ask for the site manager of this context:
-
-  >>> lsm = zope.component.getSiteManager(context)
-  >>> lsm is sm
-  True
-
-The site manager instance `lsm` is formally known as a *local site manager* of
-`context`.

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/testlayer.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/testlayer.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/testlayer.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,100 +0,0 @@
-Layers
-======
-
-zope.component.testlayer defines two things:
-
-* a LayerBase that makes it easier and saner to use zope.testing's
-  test layers.
-
-* a ZCMLLayer which lets you implement a layer that loads up some
-  ZCML.
-
-LayerBase
----------
-
-We check whether our LayerBase can be used to create layers of our
-own. We do this simply by subclassing:
-
-  >>> from zope.component.testlayer import LayerBase
-  >>> class OurLayer(LayerBase):
-  ...     def setUp(self):
-  ...         super(OurLayer, self).setUp()
-  ...         print "setUp called"
-  ...     def tearDown(self):
-  ...         super(OurLayer, self).tearDown()
-  ...         print "tearDown called"
-  ...     def testSetUp(self):
-  ...         super(OurLayer, self).testSetUp()
-  ...         print "testSetUp called"
-  ...     def testTearDown(self):
-  ...         super(OurLayer, self).testTearDown()
-  ...         print "testTearDown called"
-
-Note that if we wanted to ensure that the methods of the superclass
-were called we have to use super(). In this case we actually wouldn't
-need to, as these methods do nothing at all, but we just ensure that
-they are there in the first place.
-
-Let's instantiate our layer. We need to supply it with the package the
-layer is defined in::
-
-  >>> import zope.component
-  >>> layer = OurLayer(zope.component)
-
-Now we run some tests with this layer:
-
-  >>> import unittest
-  >>> class TestCase(unittest.TestCase):
-  ...    layer = layer
-  ...    
-  ...    def testFoo(self):
-  ...        print "testFoo"
-  >>> suite = unittest.TestSuite()
-  >>> suite.addTest(unittest.makeSuite(TestCase))
-  >>> from zope.testrunner.runner import Runner
-  >>> runner = Runner(args=[], found_suites=[suite])
-  >>> succeeded = runner.run()
-  Running zope.component.OurLayer tests:
-    Set up zope.component.OurLayer setUp called
-  in ... seconds.
-  testSetUp called
-  testFoo
-  testTearDown called
-    Ran 1 tests with 0 failures and 0 errors in ... seconds.
-  Tearing down left over layers:
-    Tear down zope.component.OurLayer tearDown called
-  in ... seconds.
-
-ZCMLLayer
----------
-
-We now want a layer that loads up some ZCML from a file. The default
-is ``ftesting.zcml``, but here we'll load a test ``testlayer.zcml``.
-
-  >>> from zope.component.testlayer import ZCMLFileLayer
-  >>> zcml_file_layer = ZCMLFileLayer(
-  ...     zope.component.testfiles,
-  ...     'testlayer.zcml')
-
-  >>> class TestCase(unittest.TestCase):
-  ...    layer = zcml_file_layer
-  ...    
-  ...    def testFoo(self):
-  ...        # we should now have the adapter registered
-  ...        from zope import component
-  ...        from zope.component.testfiles import components
-  ...        self.assert_(isinstance(
-  ...            components.IApp2(components.content), components.Comp2))
-
-Since the ZCML sets up an adapter, we expect the tests to pass::
-
-  >>> suite = unittest.TestSuite()
-  >>> suite.addTest(unittest.makeSuite(TestCase))
-  >>> runner = Runner(args=[], found_suites=[suite])
-  >>> succeeded = runner.run()
-  Running zope.component.testfiles.ZCMLFileLayer tests:
-    Set up zope.component.testfiles.ZCMLFileLayer in ... seconds.
-    Ran 1 tests with 0 failures and 0 errors in ... seconds.
-  Tearing down left over layers:
-    Tear down zope.component.testfiles.ZCMLFileLayer in ... seconds.
-

Modified: zope.component/tseaver-test_cleanup/src/zope/component/tests/test_doctests.py
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/tests/test_doctests.py	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/tests/test_doctests.py	2012-06-17 17:39:11 UTC (rev 126886)
@@ -13,16 +13,7 @@
 ##############################################################################
 """Component Architecture Tests
 """
-
-import __future__
-
-import doctest
-import persistent
-import re
-import sys
 import unittest
-import transaction
-from cStringIO import StringIO
 
 from zope import interface, component
 from zope.interface.verify import verifyObject
@@ -913,22 +904,23 @@
 def clear_base():
     base.__init__(GlobalRegistry, 'adapters')
 
-class IFoo(interface.Interface):
-    pass
-class Foo(persistent.Persistent):
-    interface.implements(IFoo)
-    name = ''
-    def __init__(self, name=''):
-        self.name = name
-
-    def __repr__(self):
-        return 'Foo(%r)' % self.name
-
 def test_deghostification_of_persistent_adapter_registries():
     """
 
 We want to make sure that we see updates corrextly.
 
+    >>> import persistent
+    >>> import transaction
+    >>> class IFoo(interface.Interface):
+    ...     pass
+    >>> class Foo(persistent.Persistent):
+    ...     interface.implements(IFoo)
+    ...     name = ''
+    ...     def __init__(self, name=''):
+    ...         self.name = name
+    ...     def __repr__(self):
+    ...         return 'Foo(%r)' % self.name
+
     >>> from zope.component.testing import setUp, tearDown
     >>> setUp()
     >>> len(base._v_subregistries)
@@ -1343,20 +1335,23 @@
         XMLConfig('meta.zcml', zope.component)()
         XMLConfig('meta.zcml', zope.security)()
 
+    def _config(self, zcml):
+        from cStringIO import StringIO
+        xmlconfig(StringIO(template % zcml))
+
     def testView(self):
         ob = Ob3()
         request = Request(IV)
         self.assertEqual(
             zope.component.queryMultiAdapter((ob, request), name=u'test'), None)
 
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <view name="test"
                   factory="zope.component.testfiles.views.V1"
                   for="zope.component.testfiles.views.IC"
                   type="zope.component.testfiles.views.IV"/>
-            '''
-            ))
+            ''')
 
         self.assertEqual(
             zope.component.queryMultiAdapter((ob, request),
@@ -1365,7 +1360,7 @@
 
 
     def testMultiView(self):
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <view name="test"
                   factory="zope.component.testfiles.adapter.A3"
@@ -1373,8 +1368,7 @@
                        zope.component.testfiles.adapter.I1
                        zope.component.testfiles.adapter.I2"
                   type="zope.component.testfiles.views.IV"/>
-            '''
-            ))
+            ''')
 
 
         ob = Ob3()
@@ -1388,11 +1382,9 @@
 
 
     def testMultiView_fails_w_multiple_factories(self):
-        self.assertRaises(
-            ConfigurationError,
-            xmlconfig,
-            StringIO(template %
-              '''
+        self.assertRaises(ConfigurationError,
+            self._config,
+            '''
               <view name="test"
                     factory="zope.component.testfiles.adapter.A3
                              zope.component.testfiles.adapter.A2"
@@ -1400,12 +1392,10 @@
                          zope.component.testfiles.adapter.I1
                          zope.component.testfiles.adapter.I2"
                     type="zope.component.testfiles.views.IV"/>
-              '''
-              )
-            )
+            ''')
 
     def testView_w_multiple_factories(self):
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <view name="test"
                   factory="zope.component.testfiles.adapter.A1
@@ -1414,8 +1404,7 @@
                            zope.component.testfiles.views.V1"
                   for="zope.component.testfiles.views.IC"
                   type="zope.component.testfiles.views.IV"/>
-            '''
-            ))
+            ''')
 
         ob = Ob3()
 
@@ -1433,16 +1422,13 @@
 
     def testView_fails_w_no_factories(self):
         self.assertRaises(ConfigurationError,
-                          xmlconfig,
-                          StringIO(template %
-                                   '''
-                                   <view name="test"
+            self._config,
+            '''
+                          <view name="test"
                                    factory=""
                                    for="zope.component.testfiles.views.IC"
                                    type="zope.component.testfiles.views.IV"/>
-                                   '''
-                                   ),
-                          )
+            ''')
 
 
     def testViewThatProvidesAnInterface(self):
@@ -1451,21 +1437,20 @@
             zope.component.queryMultiAdapter((ob, Request(IR)), IV, u'test'),
             None)
 
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <view name="test"
                   factory="zope.component.testfiles.views.V1"
                   for="zope.component.testfiles.views.IC"
                   type="zope.component.testfiles.views.IR"
                   />
-            '''
-            ))
+            ''')
 
         self.assertEqual(
             zope.component.queryMultiAdapter((ob, Request(IR)), IV, u'test'),
             None)
 
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <view name="test"
                   factory="zope.component.testfiles.views.V1"
@@ -1473,8 +1458,7 @@
                   type="zope.component.testfiles.views.IR"
                   provides="zope.component.testfiles.views.IV"
                   />
-            '''
-            ))
+            ''')
 
         v = zope.component.queryMultiAdapter((ob, Request(IR)), IV, u'test')
         self.assertEqual(v.__class__, V1)
@@ -1485,41 +1469,38 @@
         self.assertEqual(
             zope.component.queryMultiAdapter((ob, Request(IR)), IV), None)
 
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <view factory="zope.component.testfiles.views.V1"
                   for="zope.component.testfiles.views.IC"
                   type="zope.component.testfiles.views.IR"
                   />
-            '''
-            ))
+            ''')
 
         v = zope.component.queryMultiAdapter((ob, Request(IR)), IV)
         self.assertEqual(v, None)
 
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <view factory="zope.component.testfiles.views.V1"
                   for="zope.component.testfiles.views.IC"
                   type="zope.component.testfiles.views.IR"
                   provides="zope.component.testfiles.views.IV"
                   />
-            '''
-            ))
+            ''')
 
         v = zope.component.queryMultiAdapter((ob, Request(IR)), IV)
         self.assertEqual(v.__class__, V1)
 
     def testViewHavingARequiredClass(self):
-        xmlconfig(StringIO(template % (
+        self._config(
             '''
             <view
               for="zope.component.testfiles.components.Content"
               type="zope.component.testfiles.views.IR"
               factory="zope.component.testfiles.adapter.A1"
               />
-            '''
-            )))
+            '''))
 
         content = Content()
         a1 = zope.component.getMultiAdapter((content, Request(IR)))
@@ -1532,7 +1513,7 @@
                           (MyContent(), Request(IR)))
 
     def testInterfaceProtectedView(self):
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <view name="test"
                   factory="zope.component.testfiles.views.V1"
@@ -1541,8 +1522,7 @@
                   permission="zope.Public"
               allowed_interface="zope.component.testfiles.views.IV"
                   />
-            '''
-            ))
+            ''')
 
         v = ProxyFactory(zope.component.getMultiAdapter((Ob3(), Request(IV)),
                                                         name='test'))
@@ -1550,7 +1530,7 @@
         self.assertRaises(Exception, getattr, v, 'action')
 
     def testAttributeProtectedView(self):
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <view name="test"
                   factory="zope.component.testfiles.views.V1"
@@ -1559,8 +1539,7 @@
                   permission="zope.Public"
                   allowed_attributes="action"
                   />
-            '''
-            ))
+            ''')
 
         v = ProxyFactory(zope.component.getMultiAdapter((Ob3(), Request(IV)),
                                                         name='test'))
@@ -1568,7 +1547,7 @@
         self.assertRaises(Exception, getattr, v, 'index')
 
     def testInterfaceAndAttributeProtectedView(self):
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <view name="test"
                   factory="zope.component.testfiles.views.V1"
@@ -1578,15 +1557,14 @@
                   allowed_attributes="action"
               allowed_interface="zope.component.testfiles.views.IV"
                   />
-            '''
-            ))
+            ''')
 
         v = zope.component.getMultiAdapter((Ob3(), Request(IV)), name='test')
         self.assertEqual(v.index(), 'V1 here')
         self.assertEqual(v.action(), 'done')
 
     def testDuplicatedInterfaceAndAttributeProtectedView(self):
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <view name="test"
                   factory="zope.component.testfiles.views.V1"
@@ -1596,8 +1574,7 @@
                   allowed_attributes="action index"
               allowed_interface="zope.component.testfiles.views.IV"
                   />
-            '''
-            ))
+            ''')
 
         v = zope.component.getMultiAdapter((Ob3(), Request(IV)), name='test')
         self.assertEqual(v.index(), 'V1 here')
@@ -1606,7 +1583,7 @@
     def testIncompleteProtectedViewNoPermission(self):
         self.assertRaises(
             ConfigurationError,
-            xmlconfig,
+            self._config(
             StringIO(template %
             '''
             <view name="test"
@@ -1615,11 +1592,11 @@
                   type="zope.component.testfiles.views.IV"
                   allowed_attributes="action index"
                   />
-            '''
-            ))
+            ''')
 
     def testViewUndefinedPermission(self):
-        config = StringIO(template % (
+        self.assertRaises(ValueError,
+            self._config,
             '''
             <view name="test"
                   factory="zope.component.testfiles.views.V1"
@@ -1629,21 +1606,19 @@
                   allowed_attributes="action index"
               allowed_interface="zope.component.testfiles.views.IV"
                   />
-            '''
-            ))
-        self.assertRaises(ValueError, xmlconfig, config, testing=1)
+            ''',
+            testing=1)
 
     def testResource(self):
         ob = Ob3()
         self.assertEqual(
             zope.component.queryAdapter(Request(IV), name=u'test'), None)
-        xmlconfig(StringIO(template % (
+        self._config(
             '''
             <resource name="test"
                   factory="zope.component.testfiles.views.R1"
                   type="zope.component.testfiles.views.IV"/>
-            '''
-            )))
+            ''')
 
         self.assertEqual(
             zope.component.queryAdapter(Request(IV), name=u'test').__class__,
@@ -1654,20 +1629,19 @@
         self.assertEqual(zope.component.queryAdapter(Request(IR), IV, u'test'),
                          None)
 
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <resource
                 name="test"
                 factory="zope.component.testfiles.views.R1"
                 type="zope.component.testfiles.views.IR"
                 />
-            '''
-            ))
+            ''')
 
         v = zope.component.queryAdapter(Request(IR), IV, name=u'test')
         self.assertEqual(v, None)
 
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <resource
                 name="test"
@@ -1675,8 +1649,7 @@
                 type="zope.component.testfiles.views.IR"
                 provides="zope.component.testfiles.views.IV"
                 />
-            '''
-            ))
+            ''')
 
         v = zope.component.queryAdapter(Request(IR), IV, name=u'test')
         self.assertEqual(v.__class__, R1)
@@ -1685,42 +1658,39 @@
         ob = Ob3()
         self.assertEqual(zope.component.queryAdapter(Request(IR), IV), None)
 
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <resource
                 factory="zope.component.testfiles.views.R1"
                 type="zope.component.testfiles.views.IR"
                 />
-            '''
-            ))
+            ''')
 
         v = zope.component.queryAdapter(Request(IR), IV)
         self.assertEqual(v, None)
 
-        xmlconfig(StringIO(template %
+        self._config(
             '''
             <resource
                 factory="zope.component.testfiles.views.R1"
                 type="zope.component.testfiles.views.IR"
                 provides="zope.component.testfiles.views.IV"
                 />
-            '''
-            ))
+            ''')
 
         v = zope.component.queryAdapter(Request(IR), IV)
         self.assertEqual(v.__class__, R1)
 
     def testResourceUndefinedPermission(self):
-
-        config = StringIO(template % (
+        self.assertRaises(ValueError,
+            self._config,
             '''
             <resource name="test"
                   factory="zope.component.testfiles.views.R1"
                   type="zope.component.testfiles.views.IV"
                   permission="zope.UndefinedPermission"/>
-            '''
-            ))
-        self.assertRaises(ValueError, xmlconfig, config, testing=1)
+            ''',
+            testing=1)
 
 
 class ConditionalSecurityLayer(UnitTests):
@@ -1729,19 +1699,21 @@
     __bases__ = ()
 
     def setUp(self):
+        import sys
+        import zope.component.zcml
         setUp()
         self.modules = {}
         for m in ('zope.security', 'zope.proxy'):
             self.modules[m] = sys.modules[m]
             sys.modules[m] = None
-        import zope.component.zcml
         reload(zope.component.zcml)
 
     def tearDown(self):
+        import sys
+        import zope.component.zcml
         tearDown()
         for m in ('zope.security', 'zope.proxy'):
             sys.modules[m] = self.modules[m]
-        import zope.component.zcml
         reload(zope.component.zcml)
 
 
@@ -1759,52 +1731,13 @@
     XMLConfig('meta.zcml', component)()
 
 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:'),
-        ])
-
-    zcml_conditional = doctest.DocFileSuite('../zcml_conditional.txt',
-                                            checker=checker)
-    zcml_conditional.layer = ConditionalSecurityLayer()
-
-    with_globs = dict(with_statement=__future__.with_statement)
-    hooks_conditional = doctest.DocFileSuite(
-        '../hooks.txt', checker=checker, globs=with_globs)
-    hooks_conditional.layer = ConditionalSecurityLayer()
-
+    import doctest
     return unittest.TestSuite((
         doctest.DocTestSuite(setUp=setUp, tearDown=tearDown),
         unittest.makeSuite(HookableTests),
         doctest.DocTestSuite('zope.component.interface',
                              setUp=setUp, tearDown=tearDown),
         doctest.DocTestSuite('zope.component.nexttesting'),
-        doctest.DocFileSuite('../README.txt',
-                             setUp=setUp, tearDown=tearDown),
-        doctest.DocFileSuite('../socketexample.txt',
-                             setUp=setUp, tearDown=tearDown),
-        doctest.DocFileSuite('../factory.txt',
-                             setUp=setUp, tearDown=tearDown),
-        doctest.DocFileSuite('../hooks.txt', checker=checker,
-                             setUp=setUp, tearDown=tearDown,
-                             globs=with_globs),
-        doctest.DocFileSuite('../event.txt',
-                             setUp=setUp, tearDown=tearDown),
-        doctest.DocTestSuite('zope.component.security'),
-        doctest.DocFileSuite('../zcml.txt', checker=checker,
-                             setUp=setUp, tearDown=tearDown),
-        doctest.DocFileSuite('../configure.txt',
-                             setUp=setUp, tearDown=tearDown),
-        doctest.DocFileSuite('../testlayer.txt',
-                             optionflags=(doctest.ELLIPSIS +
-                                          doctest.NORMALIZE_WHITESPACE +
-                                          doctest.REPORT_NDIFF)),
-        zcml_conditional,
-        hooks_conditional,
         unittest.makeSuite(StandaloneTests),
         unittest.makeSuite(ResourceViewTests),
         ))
-
-if __name__ == "__main__":
-    unittest.main(defaultTest='test_suite')

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/zcml.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/zcml.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/zcml.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,1021 +0,0 @@
-ZCML directives
-===============
-
-Components may be registered using the registration API exposed by
-``zope.component`` (provideAdapter, provideUtility, etc.).  They may
-also be registered using configuration files.  The common way to do
-that is by using ZCML (Zope Configuration Markup Language), an XML
-spelling of component registration.
-
-In ZCML, each XML element is a *directive*.  There are different
-top-level directives that let us register components.  We will
-introduce them one by one here.
-
-This helper will let us easily execute ZCML snippets:
-
-  >>> from cStringIO import StringIO
-  >>> from zope.configuration.xmlconfig import xmlconfig
-  >>> def runSnippet(snippet):
-  ...     template = """\
-  ...     <configure xmlns='http://namespaces.zope.org/zope'
-  ...                i18n_domain="zope">
-  ...     %s
-  ...     </configure>"""
-  ...     xmlconfig(StringIO(template % snippet))
-
-adapter
--------
-
-Adapters play a key role in the Component Architecture.  In ZCML, they
-are registered with the <adapter /> directive.
-
-  >>> from zope.component.testfiles.adapter import A1, A2, A3, Handler
-  >>> from zope.component.testfiles.adapter import I1, I2, I3, IS
-  >>> from zope.component.testfiles.components import IContent, Content, Comp, comp
-
-Before we register the first test adapter, we can verify that adapter
-lookup doesn't work yet:
-
-  >>> from zope.component.tests.test_doctests import clearZCML
-  >>> clearZCML()
-  >>> from zope.component.testfiles.components import IApp
-  >>> IApp(Content(), None) is None
-  True
-
-Then we register the adapter and see that the lookup works:
-
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.components.Comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       />''')
-
-  >>> IApp(Content()).__class__
-  <class 'zope.component.testfiles.components.Comp'>
-
-It is also possible to give adapters names.  Then the combination of
-required interface, provided interface and name makes the adapter
-lookup unique.  The name is supplied using the ``name`` argument to
-the <adapter /> directive:
-
-  >>> from zope.component.tests.test_doctests import clearZCML
-  >>> clearZCML()
-  >>> import zope.component
-  >>> zope.component.queryAdapter(Content(), IApp, 'test') is None
-  True
-
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.components.Comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       name="test"
-  ...       />''')
-
-  >>> zope.component.getAdapter(Content(), IApp, 'test').__class__
-  <class 'zope.component.testfiles.components.Comp'>
-
-Adapter factories
-~~~~~~~~~~~~~~~~~
-
-It is possible to supply more than one adapter factory.  In this case,
-during adapter lookup each factory will be called and the return value
-will be given to the next factory.  The return value of the last
-factory is returned as the result of the adapter lookup.  For examle:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.adapter.A1
-  ...                zope.component.testfiles.adapter.A2
-  ...                zope.component.testfiles.adapter.A3"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       />''')
-
-The resulting adapter is an A3, around an A2, around an A1, around the
-adapted object:
-
-  >>> content = Content()
-  >>> a3 = IApp(content)
-  >>> a3.__class__ is A3
-  True
-
-  >>> a2 = a3.context[0]
-  >>> a2.__class__ is A2
-  True
-
-  >>> a1 = a2.context[0]
-  >>> a1.__class__ is A1
-  True
-
-  >>> a1.context[0] is content
-  True
-
-Of course, if no factory is provided at all, we will get an error:
-
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory=""
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-8.8
-      ValueError: No factory specified
-
-
-Declaring ``for`` and ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The <adapter /> directive can figure out from the in-line Python
-declaration (using ``zope.component.adapts()`` or
-``zope.component.adapter()`` as well as ``zope.interface.implements``)
-what the adapter should be registered for and what it provides::
-
-  >>> clearZCML()
-  >>> IApp(Content(), None) is None
-  True
-
-  >>> runSnippet('''
-  ...   <adapter factory="zope.component.testfiles.components.Comp" />''')
-
-  >>> IApp(Content()).__class__
-  <class 'zope.component.testfiles.components.Comp'>
-
-Of course, if the adapter has no ``implements()`` declaration, ZCML
-can't figure out what it provides:
-
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.adapter.A4"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
-      TypeError: Missing 'provides' attribute
-
-On the other hand, if the factory implements more than one interface,
-ZCML can't figure out what it should provide either:
-
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.adapter.A5"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
-      TypeError: Missing 'provides' attribute
-
-A not so common edge case is registering adapters directly for
-classes, not for interfaces.  For example:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for="zope.component.testfiles.components.Content"
-  ...       provides="zope.component.testfiles.adapter.I1"
-  ...       factory="zope.component.testfiles.adapter.A1"
-  ...       />''')
-
-  >>> content = Content()
-  >>> a1 = zope.component.getAdapter(content, I1, '')
-  >>> isinstance(a1, A1)
-  True
-
-This time, any object providing ``IContent`` won't work if it's not an
-instance of the ``Content`` class:
-
-  >>> import zope.interface
-  >>> class MyContent:
-  ...     zope.interface.implements(IContent)
-  >>> zope.component.getAdapter(MyContent(), I1, '')  # doctest: +ELLIPSIS
-  Traceback (most recent call last):
-    ...
-  ComponentLookupError: ...
-
-Multi-adapters
-~~~~~~~~~~~~~~
-
-Conventional adapters adapt one object to provide another interface.
-Multi-adapters adapt several objects at once:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1
-  ...            zope.component.testfiles.adapter.I2"
-  ...       provides="zope.component.testfiles.adapter.I3"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       />''')
-
-  >>> content = Content()
-  >>> a1 = A1()
-  >>> a2 = A2()
-  >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == (content, a1, a2)
-  True
-
-You can even adapt an empty list of objects (we call this a
-null-adapter):
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for=""
-  ...       provides="zope.component.testfiles.adapter.I3"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       />''')
-
-  >>> a3 = zope.component.queryMultiAdapter((), I3)
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == ()
-  True
-
-Even with multi-adapters, ZCML can figure out the ``for`` and
-``provides`` parameters from the Python declarations:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter factory="zope.component.testfiles.adapter.A3" />''')
-
-  >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == (content, a1, a2)
-  True
-
-Chained factories are not supported for multi-adapters, though:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1
-  ...            zope.component.testfiles.adapter.I2"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       factory="zope.component.testfiles.adapter.A1
-  ...                zope.component.testfiles.adapter.A2"
-  ...       />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-11.8
-      ValueError: Can't use multiple factories and multiple for
-
-And neither for null-adapters:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for=""
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       factory="zope.component.testfiles.adapter.A1
-  ...                zope.component.testfiles.adapter.A2"
-  ...       />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-9.8
-      ValueError: Can't use multiple factories and multiple for
-
-Protected adapters
-~~~~~~~~~~~~~~~~~~
-
-Adapters can be protected with a permission.  First we have to define
-a permission for which we'll have to register the <permission />
-directive:
-
-  >>> clearZCML()
-  >>> IApp(Content(), None) is None
-  True
-
-  >>> import zope.security
-  >>> from zope.configuration.xmlconfig import XMLConfig
-  >>> XMLConfig('meta.zcml', zope.security)()
-  >>> runSnippet('''
-  ...   <permission
-  ...       id="y.x"
-  ...       title="XY"
-  ...       description="Allow XY."
-  ...       />
-  ...   <adapter
-  ...       factory="zope.component.testfiles.components.Comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       permission="y.x"
-  ...       />''')
-
-We see that the adapter is a location proxy now so that the
-appropriate permissions can be found from the context:
-
-  >>> IApp(Content()).__class__
-  <class 'zope.component.testfiles.components.Comp'>
-  >>> type(IApp(Content()))
-  <class 'zope.location.location.LocationProxy'>
-
-We can also go about it a different way.  Let's make a public adapter
-and wrap the adapter in a security proxy.  That often happens when
-an adapter is turned over to untrusted code:
-
-  >>> clearZCML()
-  >>> IApp(Content(), None) is None
-  True
-
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.components.Comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       permission="zope.Public"
-  ...       />''')
-
-  >>> from zope.security.checker import ProxyFactory
-  >>> adapter = ProxyFactory(IApp(Content()))
-  >>> from zope.security.proxy import getTestProxyItems
-  >>> items = [item[0] for item in getTestProxyItems(adapter)]
-  >>> items
-  ['a', 'f']
-
-  >>> from zope.security.proxy import removeSecurityProxy
-  >>> removeSecurityProxy(adapter).__class__ is Comp
-  True
-
-Of course, this still works when we let the ZCML directive handler
-figure out ``for`` and ``provides`` from the Python declarations:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.components.Comp"
-  ...       permission="zope.Public"
-  ...       />''')
-
-  >>> adapter = ProxyFactory(IApp(Content()))
-  >>> [item[0] for item in getTestProxyItems(adapter)]
-  ['a', 'f']
-  >>> removeSecurityProxy(adapter).__class__ is Comp
-  True
-
-It also works with multi adapters:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       provides="zope.component.testfiles.adapter.I3"
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1
-  ...            zope.component.testfiles.adapter.I2"
-  ...       permission="zope.Public"
-  ...       />''')
-
-  >>> content = Content()
-  >>> a1 = A1()
-  >>> a2 = A2()
-  >>> a3 = ProxyFactory(zope.component.queryMultiAdapter((content, a1, a2), I3))
-  >>> a3.__class__ == A3
-  True
-  >>> [item[0] for item in getTestProxyItems(a3)]
-  ['f1', 'f2', 'f3']
-
-It's probably not worth mentioning, but when we try to protect an
-adapter with a permission that doesn't exist, we'll obviously get an
-error:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.components.Comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       permission="zope.UndefinedPermission"
-  ...       />''')
-  Traceback (most recent call last):
-    ...
-  ConfigurationExecutionError: exceptions.ValueError: ('Undefined permission id', 'zope.UndefinedPermission')
-    in:
-    File "<string>", line 4.2-9.8
-    Could not read source.
-
-Trusted adapters
-~~~~~~~~~~~~~~~~
-
-Trusted adapters are adapters that are trusted to do anything with the
-objects they are given so that these objects are not security-proxied.
-They are registered using the ``trusted`` argument to the <adapter />
-directive:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       provides="zope.component.testfiles.adapter.I1"
-  ...       factory="zope.component.testfiles.adapter.A1"
-  ...       trusted="yes"
-  ...       />''')
-
-With an unproxied object, it's business as usual:
-
-  >>> ob = Content()
-  >>> type(I1(ob)) is A1
-  True
-
-With a security-proxied object, however, we get a security-proxied
-adapter:
-
-  >>> p = ProxyFactory(ob)
-  >>> a = I1(p)
-  >>> type(a)
-  <type 'zope.security._proxy._Proxy'>
-
-While the adapter is security-proxied, the object it adapts is now
-proxy-free.  The adapter has umlimited access to it:
-
-  >>> a = removeSecurityProxy(a)
-  >>> type(a) is A1
-  True
-  >>> a.context[0] is ob
-  True
-
-We can also protect the trusted adapter with a permission:
-
-  >>> clearZCML()
-  >>> XMLConfig('meta.zcml', zope.security)()
-  >>> runSnippet('''
-  ...   <permission
-  ...       id="y.x"
-  ...       title="XY"
-  ...       description="Allow XY."
-  ...       />
-  ...   <adapter
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       provides="zope.component.testfiles.adapter.I1"
-  ...       factory="zope.component.testfiles.adapter.A1"
-  ...       permission="y.x"
-  ...       trusted="yes"
-  ...       />''')
-
-Again, with an unproxied object, it's business as usual:
-
-  >>> ob = Content()
-  >>> type(I1(ob)) is A1
-  True
-
-With a security-proxied object, we again get a security-proxied
-adapter:
-
-  >>> p = ProxyFactory(ob)
-  >>> a = I1(p)
-  >>> type(a)
-  <type 'zope.security._proxy._Proxy'>
-
-Since we protected the adapter with a permission, we now encounter a
-location proxy behind the security proxy:
-
-  >>> a = removeSecurityProxy(a)
-  >>> type(a)
-  <class 'zope.location.location.LocationProxy'>
-  >>> a.context[0] is ob
-  True
-
-There's one exception to all of this: When you use the public
-permission (``zope.Public``), there will be no location proxy:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       provides="zope.component.testfiles.adapter.I1"
-  ...       factory="zope.component.testfiles.adapter.A1"
-  ...       permission="zope.Public"
-  ...       trusted="yes"
-  ...       />''')
-
-  >>> ob = Content()
-  >>> p = ProxyFactory(ob)
-  >>> a = I1(p)
-  >>> type(a)
-  <type 'zope.security._proxy._Proxy'>
-
-  >>> a = removeSecurityProxy(a)
-  >>> type(a) is A1
-  True
-
-We can also explicitply pass the ``locate`` argument to make sure we
-get location proxies:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       provides="zope.component.testfiles.adapter.I1"
-  ...       factory="zope.component.testfiles.adapter.A1"
-  ...       trusted="yes"
-  ...       locate="yes"
-  ...       />''')
-
-  >>> ob = Content()
-  >>> p = ProxyFactory(ob)
-  >>> a = I1(p)
-  >>> type(a)
-  <type 'zope.security._proxy._Proxy'>
-
-  >>> a = removeSecurityProxy(a)
-  >>> type(a)
-  <class 'zope.location.location.LocationProxy'>
-
-
-subscriber
-----------
-
-With the <subscriber /> directive you can register subscription
-adapters or event subscribers with the adapter registry.  Consider
-this very typical example of a <subscriber /> directive:
- 
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       provides="zope.component.testfiles.adapter.IS"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1"
-  ...       />''')
-
-  >>> content = Content()
-  >>> a1 = A1()
-
-  >>> subscribers = zope.component.subscribers((content, a1), IS)
-  >>> a3 = subscribers[0]
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == (content, a1)
-  True
-
-Note how ZCML provides some additional information when registering
-components, such as the ZCML filename and line numbers:
-
-  >>> sm = zope.component.getSiteManager()
-  >>> doc = [reg.info for reg in sm.registeredSubscriptionAdapters()
-  ...        if reg.provided is IS][0]
-  >>> print doc
-  File "<string>", line 4.2-9.8
-    Could not read source.
-
-The "fun" behind subscription adapters/subscribers is that when
-several ones are declared for the same for/provides, they are all
-found.  With regular adapters, the most specific one (and in doubt the
-one registered last) wins.  Consider these two subscribers:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       provides="zope.component.testfiles.adapter.IS"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1"
-  ...       />
-  ...   <subscriber
-  ...       provides="zope.component.testfiles.adapter.IS"
-  ...       factory="zope.component.testfiles.adapter.A2"
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1"
-  ...       />''')
-
-  >>> subscribers = zope.component.subscribers((content, a1), IS)
-  >>> len(subscribers)
-  2
-  >>> sorted([a.__class__.__name__ for a in subscribers])
-  ['A2', 'A3']
-
-Declaring ``for`` and ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Like the <adapter /> directive, the <subscriber /> directive can
-figure out from the in-line Python declaration (using
-``zope.component.adapts()`` or ``zope.component.adapter()``) what the
-subscriber should be registered for:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       provides="zope.component.testfiles.adapter.IS"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       />''')
-
-  >>> content = Content()
-  >>> a2 = A2()
-  >>> subscribers = zope.component.subscribers((content, a1, a2), IS)
-
-  >>> a3 = subscribers[0]
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == (content, a1, a2)
-  True
-
-In the same way the directive can figure out what a subscriber
-provides:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber handler="zope.component.testfiles.adapter.A3" />''')
-
-  >>> sm = zope.component.getSiteManager()
-  >>> a3 = sm.adapters.subscriptions((IContent, I1, I2), None)[0]
-  >>> a3 is A3
-  True
-
-A not so common edge case is declaring subscribers directly for
-classes, not for interfaces.  For example:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       for="zope.component.testfiles.components.Content"
-  ...       provides="zope.component.testfiles.adapter.I1"
-  ...       factory="zope.component.testfiles.adapter.A1"
-  ...       />''')
-
-  >>> subs = list(zope.component.subscribers((Content(),), I1))
-  >>> isinstance(subs[0], A1)
-  True
-
-This time, any object providing ``IContent`` won't work if it's not an
-instance of the ``Content`` class:
-
-  >>> list(zope.component.subscribers((MyContent(),), I1))
-  []
-
-Protected subscribers
-~~~~~~~~~~~~~~~~~~~~~
-
-Subscribers can also be protected with a permission.  First we have to
-define a permission for which we'll have to register the <permission />
-directive:
-
-  >>> clearZCML()
-  >>> XMLConfig('meta.zcml', zope.security)()
-  >>> runSnippet('''
-  ...   <permission
-  ...       id="y.x"
-  ...       title="XY"
-  ...       description="Allow XY."
-  ...       />
-  ...   <subscriber
-  ...       provides="zope.component.testfiles.adapter.IS"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1"
-  ...       permission="y.x"
-  ...       />''')
-
-  >>> subscribers = zope.component.subscribers((content, a1), IS)
-  >>> a3 = subscribers[0]
-  >>> a3.__class__ is A3
-  True
-  >>> type(a3)
-  <class 'zope.location.location.LocationProxy'>
-  >>> a3.context == (content, a1)
-  True
-
-Trusted subscribers
-~~~~~~~~~~~~~~~~~~~
-
-Like trusted adapters, trusted subscribers are subscribers that are
-trusted to do anything with the objects they are given so that these
-objects are not security-proxied.  In analogy to the <adapter />
-directive, they are registered using the ``trusted`` argument to the
-<subscriber /> directive:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       provides="zope.component.testfiles.adapter.IS"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1"
-  ...       trusted="yes"
-  ...       />''')
-
-With an unproxied object, it's business as usual:
-
-  >>> subscribers = zope.component.subscribers((content, a1), IS)
-  >>> a3 = subscribers[0]
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == (content, a1)
-  True
-  >>> type(a3) is A3
-  True
-
-Now with a proxied object.  We will see that the subscriber has
-unproxied access to it, but the subscriber itself is proxied:
-
-  >>> p = ProxyFactory(content)
-  >>> a3 = zope.component.subscribers((p, a1), IS)[0]
-  >>> type(a3)
-  <type 'zope.security._proxy._Proxy'>
-
-There's no location proxy behind the security proxy:
-
-  >>> removeSecurityProxy(a3).context[0] is content
-  True
-  >>> type(removeSecurityProxy(a3)) is A3
-  True
-
-If you want the trusted subscriber to be located, you'll also have to
-use the ``locate`` argument:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       provides="zope.component.testfiles.adapter.IS"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1"
-  ...       trusted="yes"
-  ...       locate="yes"
-  ...       />''')
-
-Again, it's business as usual with an unproxied object:
-
-  >>> subscribers = zope.component.subscribers((content, a1), IS)
-  >>> a3 = subscribers[0]
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == (content, a1)
-  True
-  >>> type(a3) is A3
-  True
-
-With a proxied object, we again get a security-proxied subscriber:
-
-  >>> p = ProxyFactory(content)
-  >>> a3 = zope.component.subscribers((p, a1), IS)[0]
-
-  >>> type(a3)
-  <type 'zope.security._proxy._Proxy'>
-
-  >>> removeSecurityProxy(a3).context[0] is content
-  True
-
-However, thanks to the ``locate`` argument, we now have a location
-proxy behind the security proxy:
-
-  >>> type(removeSecurityProxy(a3))
-  <class 'zope.location.location.LocationProxy'>
-
-Event subscriber (handlers)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Sometimes, subscribers don't need to be adapters that actually provide
-anything.  It's enough that a callable is called for a certain event.
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1"
-  ...       handler="zope.component.testfiles.adapter.Handler"
-  ...       />''')
-
-In this case, simply getting the subscribers is enough to invoke them:
-
-  >>> list(zope.component.subscribers((content, a1), None))
-  []
-  >>> content.args == ((a1,),)
-  True
-
-
-utility
--------
-
-Apart from adapters (and subscription adapters), the Component
-Architecture knows a second kind of component: utilities.  They are
-registered using the <utility /> directive.
-
-Before we register the first test utility, we can verify that utility
-lookup doesn't work yet:
-
-  >>> clearZCML()
-  >>> zope.component.queryUtility(IApp) is None
-  True
-
-Then we register the utility:
-
-  >>> runSnippet('''
-  ...   <utility
-  ...       component="zope.component.testfiles.components.comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       />''')
-  >>> zope.component.getUtility(IApp) is comp
-  True
-
-Like adapters, utilities can also have names.  There can be more than
-one utility registered for a certain interface, as long as they each
-have a different name.
-
-First, we make sure that there's no utility yet:
-
-  >>> clearZCML()
-  >>> zope.component.queryUtility(IApp, 'test') is None
-  True
-
-Then we register it:
-
-  >>> runSnippet('''
-  ...   <utility
-  ...       component="zope.component.testfiles.components.comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       name="test"
-  ...       />''')
-  >>> zope.component.getUtility(IApp, 'test') is comp
-  True
-
-Utilities can also be registered from a factory.  In this case, the
-ZCML handler calls the factory (without any arguments) and registers
-the returned value as a utility.  Typically, you'd pass a class for
-the factory:
-
-  >>> clearZCML()
-  >>> zope.component.queryUtility(IApp) is None
-  True
-
-  >>> runSnippet('''
-  ...   <utility
-  ...       factory="zope.component.testfiles.components.Comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       />''')
-  >>> zope.component.getUtility(IApp).__class__ is Comp
-  True
-
-Declaring ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Like other directives, <utility /> can also figure out which interface
-a utility provides from the Python declaration:
-
-  >>> clearZCML()
-  >>> zope.component.queryUtility(IApp) is None
-  True
-
-  >>> runSnippet('''
-  ...   <utility component="zope.component.testfiles.components.comp" />''')
-  >>> zope.component.getUtility(IApp) is comp
-  True
-
-It won't work if the component that is to be registered doesn't
-provide anything:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <utility component="zope.component.testfiles.adapter.a4" />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
-      TypeError: Missing 'provides' attribute
-
-Or if more than one interface is provided (then the ZCML directive
-handler doesn't know under which the utility should be registered):
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <utility component="zope.component.testfiles.adapter.a5" />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
-      TypeError: Missing 'provides' attribute
-
-We can repeat the same drill for utility factories:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <utility factory="zope.component.testfiles.components.Comp" />''')
-  >>> zope.component.getUtility(IApp).__class__ is Comp
-  True
-
-  >>> runSnippet('''
-  ...   <utility factory="zope.component.testfiles.adapter.A4" />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
-      TypeError: Missing 'provides' attribute
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <utility factory="zope.component.testfiles.adapter.A5" />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
-      TypeError: Missing 'provides' attribute
-
-Protected utilities
-~~~~~~~~~~~~~~~~~~~
-
-TODO::
-
-    def testProtectedUtility(self):
-        """Test that we can protect a utility.
-
-        Also:
-        Check that multiple configurations for the same utility and
-        don't interfere.
-        """
-        self.assertEqual(zope.component.queryUtility(IV), None)
-        xmlconfig(StringIO(template % (
-            '''
-            <permission id="tell.everyone" title="Yay" />
-            <utility
-              component="zope.component.testfiles.components.comp"
-              provides="zope.component.testfiles.components.IApp"
-              permission="tell.everyone"
-              />
-            <permission id="top.secret" title="shhhh" />
-            <utility
-              component="zope.component.testfiles.components.comp"
-              provides="zope.component.testfiles.components.IAppb"
-              permission="top.secret"
-              />
-            '''
-            )))
-
-        utility = ProxyFactory(zope.component.getUtility(IApp))
-        items = getTestProxyItems(utility)
-        self.assertEqual(items, [('a', 'tell.everyone'),
-                                 ('f', 'tell.everyone')
-                                 ])
-        self.assertEqual(removeSecurityProxy(utility), comp)
-
-    def testUtilityUndefinedPermission(self):
-        config = StringIO(template % (
-             '''
-             <utility
-              component="zope.component.testfiles.components.comp"
-              provides="zope.component.testfiles.components.IApp"
-              permission="zope.UndefinedPermission"
-              />
-            '''
-            ))
-        self.assertRaises(ValueError, xmlconfig, config,
-                          testing=1)
-
-interface
----------
-
-The <interface /> directive lets us register an interface.  Interfaces
-are registered as named utilities.  We therefore needn't go though all
-the lookup details again, it is sufficient to see whether the
-directive handler emits the right actions.
-
-First we provide a stub configuration context:
-
-  >>> import re, pprint
-  >>> atre = re.compile(' at [0-9a-fA-Fx]+')
-  >>> class Context(object):
-  ...    actions = ()
-  ...    def action(self, discriminator, callable, args):
-  ...        self.actions += ((discriminator, callable, args), )
-  ...    def __repr__(self):
-  ...        stream = StringIO()
-  ...        pprinter = pprint.PrettyPrinter(stream=stream, width=60)
-  ...        pprinter.pprint(self.actions)
-  ...        r = stream.getvalue()
-  ...        return (''.join(atre.split(r))).strip()
-  >>> context = Context()
-
-Then we provide a test interface that we'd like to register:
-
-  >>> from zope.interface import Interface
-  >>> class I(Interface):
-  ...     pass
-
-It doesn't yet provide ``ITestType``:
-
-  >>> from zope.component.tests.test_doctests import ITestType
-  >>> ITestType.providedBy(I)
-  False
-
-However, after calling the directive handler...
-
-  >>> from zope.component.zcml import interface
-  >>> interface(context, I, ITestType)
-  >>> context
-  ((None,
-    <function provideInterface>,
-    ('',
-     <InterfaceClass __builtin__.I>,
-     <InterfaceClass zope.component.tests.test_doctests.ITestType>)),)
-
-...it does provide ``ITestType``:
-
-  >>> from zope.interface.interfaces import IInterface
-  >>> ITestType.extends(IInterface)
-  True
-  >>> IInterface.providedBy(I)
-  True

Deleted: zope.component/tseaver-test_cleanup/src/zope/component/zcml_conditional.txt
===================================================================
--- zope.component/tseaver-test_cleanup/src/zope/component/zcml_conditional.txt	2012-06-15 22:56:00 UTC (rev 126885)
+++ zope.component/tseaver-test_cleanup/src/zope/component/zcml_conditional.txt	2012-06-17 17:39:11 UTC (rev 126886)
@@ -1,611 +0,0 @@
-ZCML directives without zope.security support
-=============================================
-
-This tests run without zope.security available:
-
-  >>> from zope.component.zcml import check_security_support
-  >>> check_security_support()
-  Traceback (most recent call last):
-  ...
-  ConfigurationError: security proxied components are not supported because zope.security is not available
-
-Components may be registered using the registration API exposed by
-``zope.component`` (provideAdapter, provideUtility, etc.).  They may
-also be registered using configuration files.  The common way to do
-that is by using ZCML (Zope Configuration Markup Language), an XML
-spelling of component registration.
-
-In ZCML, each XML element is a *directive*.  There are different
-top-level directives that let us register components.  We will
-introduce them one by one here.
-
-This helper will let us easily execute ZCML snippets:
-
-  >>> from cStringIO import StringIO
-  >>> from zope.configuration.xmlconfig import xmlconfig
-  >>> def runSnippet(snippet):
-  ...     template = """\
-  ...     <configure xmlns='http://namespaces.zope.org/zope'
-  ...                i18n_domain="zope">
-  ...     %s
-  ...     </configure>"""
-  ...     xmlconfig(StringIO(template % snippet))
-
-adapter
--------
-
-Adapters play a key role in the Component Architecture.  In ZCML, they
-are registered with the <adapter /> directive.
-
-  >>> from zope.component.testfiles.adapter import A1, A2, A3, Handler
-  >>> from zope.component.testfiles.adapter import I1, I2, I3, IS
-  >>> from zope.component.testfiles.components import IContent, Content, Comp, comp
-
-Before we register the first test adapter, we can verify that adapter
-lookup doesn't work yet:
-
-  >>> from zope.component.tests.test_doctests import clearZCML
-  >>> clearZCML()
-  >>> from zope.component.testfiles.components import IApp
-  >>> IApp(Content(), None) is None
-  True
-
-Then we register the adapter and see that the lookup works:
-
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.components.Comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       />''')
-
-  >>> IApp(Content()).__class__
-  <class 'zope.component.testfiles.components.Comp'>
-
-It is also possible to give adapters names.  Then the combination of
-required interface, provided interface and name makes the adapter
-lookup unique.  The name is supplied using the ``name`` argument to
-the <adapter /> directive:
-
-  >>> clearZCML()
-  >>> import zope.component
-  >>> zope.component.queryAdapter(Content(), IApp, 'test') is None
-  True
-
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.components.Comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       name="test"
-  ...       />''')
-
-  >>> zope.component.getAdapter(Content(), IApp, 'test').__class__
-  <class 'zope.component.testfiles.components.Comp'>
-
-Adapter factories
-~~~~~~~~~~~~~~~~~
-
-It is possible to supply more than one adapter factory.  In this case,
-during adapter lookup each factory will be called and the return value
-will be given to the next factory.  The return value of the last
-factory is returned as the result of the adapter lookup.  For examle:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.adapter.A1
-  ...                zope.component.testfiles.adapter.A2
-  ...                zope.component.testfiles.adapter.A3"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       />''')
-
-The resulting adapter is an A3, around an A2, around an A1, around the
-adapted object:
-
-  >>> content = Content()
-  >>> a3 = IApp(content)
-  >>> a3.__class__ is A3
-  True
-
-  >>> a2 = a3.context[0]
-  >>> a2.__class__ is A2
-  True
-
-  >>> a1 = a2.context[0]
-  >>> a1.__class__ is A1
-  True
-
-  >>> a1.context[0] is content
-  True
-
-Of course, if no factory is provided at all, we will get an error:
-
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory=""
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-8.8
-      ValueError: No factory specified
-
-Declaring ``for`` and ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The <adapter /> directive can figure out from the in-line Python
-declaration (using ``zope.component.adapts()`` or
-``zope.component.adapter()`` as well as ``zope.interface.implements``)
-what the adapter should be registered for and what it provides::
-
-  >>> clearZCML()
-  >>> IApp(Content(), None) is None
-  True
-
-  >>> runSnippet('''
-  ...   <adapter factory="zope.component.testfiles.components.Comp" />''')
-
-  >>> IApp(Content()).__class__
-  <class 'zope.component.testfiles.components.Comp'>
-
-Of course, if the adapter has no ``implements()`` declaration, ZCML
-can't figure out what it provides:
-
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.adapter.A4"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
-      TypeError: Missing 'provides' attribute
-
-On the other hand, if the factory implements more than one interface,
-ZCML can't figure out what it should provide either:
-
-  >>> runSnippet('''
-  ...   <adapter
-  ...       factory="zope.component.testfiles.adapter.A5"
-  ...       for="zope.component.testfiles.components.IContent"
-  ...       />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
-      TypeError: Missing 'provides' attribute
-
-A not so common edge case is registering adapters directly for
-classes, not for interfaces.  For example:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for="zope.component.testfiles.components.Content"
-  ...       provides="zope.component.testfiles.adapter.I1"
-  ...       factory="zope.component.testfiles.adapter.A1"
-  ...       />''')
-
-  >>> content = Content()
-  >>> a1 = zope.component.getAdapter(content, I1, '')
-  >>> isinstance(a1, A1)
-  True
-
-This time, any object providing ``IContent`` won't work if it's not an
-instance of the ``Content`` class:
-
-  >>> import zope.interface
-  >>> class MyContent:
-  ...     zope.interface.implements(IContent)
-  >>> zope.component.getAdapter(MyContent(), I1, '')  # doctest: +ELLIPSIS
-  Traceback (most recent call last):
-    ...
-  ComponentLookupError: ...
-
-Multi-adapters
-~~~~~~~~~~~~~~
-
-Conventional adapters adapt one object to provide another interface.
-Multi-adapters adapt several objects at once:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1
-  ...            zope.component.testfiles.adapter.I2"
-  ...       provides="zope.component.testfiles.adapter.I3"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       />''')
-
-  >>> content = Content()
-  >>> a1 = A1()
-  >>> a2 = A2()
-  >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == (content, a1, a2)
-  True
-
-You can even adapt an empty list of objects (we call this a
-null-adapter):
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for=""
-  ...       provides="zope.component.testfiles.adapter.I3"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       />''')
-
-  >>> a3 = zope.component.queryMultiAdapter((), I3)
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == ()
-  True
-
-Even with multi-adapters, ZCML can figure out the ``for`` and
-``provides`` parameters from the Python declarations:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter factory="zope.component.testfiles.adapter.A3" />''')
-
-  >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == (content, a1, a2)
-  True
-
-Chained factories are not supported for multi-adapters, though:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1
-  ...            zope.component.testfiles.adapter.I2"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       factory="zope.component.testfiles.adapter.A1
-  ...                zope.component.testfiles.adapter.A2"
-  ...       />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-11.8
-      ValueError: Can't use multiple factories and multiple for
-
-And neither for null-adapters:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <adapter
-  ...       for=""
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       factory="zope.component.testfiles.adapter.A1
-  ...                zope.component.testfiles.adapter.A2"
-  ...       />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-9.8
-      ValueError: Can't use multiple factories and multiple for
-
-subscriber
-----------
-
-With the <subscriber /> directive you can register subscription
-adapters or event subscribers with the adapter registry.  Consider
-this very typical example of a <subscriber /> directive:
- 
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       provides="zope.component.testfiles.adapter.IS"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1"
-  ...       />''')
-
-  >>> content = Content()
-  >>> a1 = A1()
-
-  >>> subscribers = zope.component.subscribers((content, a1), IS)
-  >>> a3 = subscribers[0]
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == (content, a1)
-  True
-
-Note how ZCML provides some additional information when registering
-components, such as the ZCML filename and line numbers:
-
-  >>> sm = zope.component.getSiteManager()
-  >>> doc = [reg.info for reg in sm.registeredSubscriptionAdapters()
-  ...        if reg.provided is IS][0]
-  >>> print doc
-  File "<string>", line 4.2-9.8
-    Could not read source.
-
-The "fun" behind subscription adapters/subscribers is that when
-several ones are declared for the same for/provides, they are all
-found.  With regular adapters, the most specific one (and in doubt the
-one registered last) wins.  Consider these two subscribers:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       provides="zope.component.testfiles.adapter.IS"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1"
-  ...       />
-  ...   <subscriber
-  ...       provides="zope.component.testfiles.adapter.IS"
-  ...       factory="zope.component.testfiles.adapter.A2"
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1"
-  ...       />''')
-
-  >>> subscribers = zope.component.subscribers((content, a1), IS)
-  >>> len(subscribers)
-  2
-  >>> sorted([a.__class__.__name__ for a in subscribers])
-  ['A2', 'A3']
-
-Declaring ``for`` and ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Like the <adapter /> directive, the <subscriber /> directive can
-figure out from the in-line Python declaration (using
-``zope.component.adapts()`` or ``zope.component.adapter()``) what the
-subscriber should be registered for:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       provides="zope.component.testfiles.adapter.IS"
-  ...       factory="zope.component.testfiles.adapter.A3"
-  ...       />''')
-
-  >>> content = Content()
-  >>> a2 = A2()
-  >>> subscribers = zope.component.subscribers((content, a1, a2), IS)
-
-  >>> a3 = subscribers[0]
-  >>> a3.__class__ is A3
-  True
-  >>> a3.context == (content, a1, a2)
-  True
-
-In the same way the directive can figure out what a subscriber
-provides:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber handler="zope.component.testfiles.adapter.A3" />''')
-
-  >>> sm = zope.component.getSiteManager()
-  >>> a3 = sm.adapters.subscriptions((IContent, I1, I2), None)[0]
-  >>> a3 is A3
-  True
-
-A not so common edge case is declaring subscribers directly for
-classes, not for interfaces.  For example:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       for="zope.component.testfiles.components.Content"
-  ...       provides="zope.component.testfiles.adapter.I1"
-  ...       factory="zope.component.testfiles.adapter.A1"
-  ...       />''')
-
-  >>> subs = list(zope.component.subscribers((Content(),), I1))
-  >>> isinstance(subs[0], A1)
-  True
-
-This time, any object providing ``IContent`` won't work if it's not an
-instance of the ``Content`` class:
-
-  >>> list(zope.component.subscribers((MyContent(),), I1))
-  []
-
-Event subscriber (handlers)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Sometimes, subscribers don't need to be adapters that actually provide
-anything.  It's enough that a callable is called for a certain event.
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <subscriber
-  ...       for="zope.component.testfiles.components.IContent
-  ...            zope.component.testfiles.adapter.I1"
-  ...       handler="zope.component.testfiles.adapter.Handler"
-  ...       />''')
-
-In this case, simply getting the subscribers is enough to invoke them:
-
-  >>> list(zope.component.subscribers((content, a1), None))
-  []
-  >>> content.args == ((a1,),)
-  True
-
-
-utility
--------
-
-Apart from adapters (and subscription adapters), the Component
-Architecture knows a second kind of component: utilities.  They are
-registered using the <utility /> directive.
-
-Before we register the first test utility, we can verify that utility
-lookup doesn't work yet:
-
-  >>> clearZCML()
-  >>> zope.component.queryUtility(IApp) is None
-  True
-
-Then we register the utility:
-
-  >>> runSnippet('''
-  ...   <utility
-  ...       component="zope.component.testfiles.components.comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       />''')
-  >>> zope.component.getUtility(IApp) is comp
-  True
-
-Like adapters, utilities can also have names.  There can be more than
-one utility registered for a certain interface, as long as they each
-have a different name.
-
-First, we make sure that there's no utility yet:
-
-  >>> clearZCML()
-  >>> zope.component.queryUtility(IApp, 'test') is None
-  True
-
-Then we register it:
-
-  >>> runSnippet('''
-  ...   <utility
-  ...       component="zope.component.testfiles.components.comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       name="test"
-  ...       />''')
-  >>> zope.component.getUtility(IApp, 'test') is comp
-  True
-
-Utilities can also be registered from a factory.  In this case, the
-ZCML handler calls the factory (without any arguments) and registers
-the returned value as a utility.  Typically, you'd pass a class for
-the factory:
-
-  >>> clearZCML()
-  >>> zope.component.queryUtility(IApp) is None
-  True
-
-  >>> runSnippet('''
-  ...   <utility
-  ...       factory="zope.component.testfiles.components.Comp"
-  ...       provides="zope.component.testfiles.components.IApp"
-  ...       />''')
-  >>> zope.component.getUtility(IApp).__class__ is Comp
-  True
-
-Declaring ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Like other directives, <utility /> can also figure out which interface
-a utility provides from the Python declaration:
-
-  >>> clearZCML()
-  >>> zope.component.queryUtility(IApp) is None
-  True
-
-  >>> runSnippet('''
-  ...   <utility component="zope.component.testfiles.components.comp" />''')
-  >>> zope.component.getUtility(IApp) is comp
-  True
-
-It won't work if the component that is to be registered doesn't
-provide anything:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <utility component="zope.component.testfiles.adapter.a4" />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
-      TypeError: Missing 'provides' attribute
-
-Or if more than one interface is provided (then the ZCML directive
-handler doesn't know under which the utility should be registered):
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <utility component="zope.component.testfiles.adapter.a5" />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
-      TypeError: Missing 'provides' attribute
-
-We can repeat the same drill for utility factories:
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <utility factory="zope.component.testfiles.components.Comp" />''')
-  >>> zope.component.getUtility(IApp).__class__ is Comp
-  True
-
-  >>> runSnippet('''
-  ...   <utility factory="zope.component.testfiles.adapter.A4" />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
-      TypeError: Missing 'provides' attribute
-
-  >>> clearZCML()
-  >>> runSnippet('''
-  ...   <utility factory="zope.component.testfiles.adapter.A5" />''')
-  Traceback (most recent call last):
-    ...
-  ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
-      TypeError: Missing 'provides' attribute
-
-interface
----------
-
-The <interface /> directive lets us register an interface.  Interfaces
-are registered as named utilities.  We therefore needn't go though all
-the lookup details again, it is sufficient to see whether the
-directive handler emits the right actions.
-
-First we provide a stub configuration context:
-
-  >>> import re, pprint
-  >>> atre = re.compile(' at [0-9a-fA-Fx]+')
-  >>> class Context(object):
-  ...    actions = ()
-  ...    def action(self, discriminator, callable, args):
-  ...        self.actions += ((discriminator, callable, args), )
-  ...    def __repr__(self):
-  ...        stream = StringIO()
-  ...        pprinter = pprint.PrettyPrinter(stream=stream, width=60)
-  ...        pprinter.pprint(self.actions)
-  ...        r = stream.getvalue()
-  ...        return (''.join(atre.split(r))).strip()
-  >>> context = Context()
-
-Then we provide a test interface that we'd like to register:
-
-  >>> from zope.interface import Interface
-  >>> class I(Interface):
-  ...     pass
-
-It doesn't yet provide ``ITestType``:
-
-  >>> from zope.component.tests.test_doctests import ITestType
-  >>> ITestType.providedBy(I)
-  False
-
-However, after calling the directive handler...
-
-  >>> from zope.component.zcml import interface
-  >>> interface(context, I, ITestType)
-  >>> context
-  ((None,
-    <function provideInterface>,
-    ('',
-     <InterfaceClass __builtin__.I>,
-     <InterfaceClass zope.component.tests.test_doctests.ITestType>)),)
-
-...it does provide ``ITestType``:
-
-  >>> from zope.interface.interfaces import IInterface
-  >>> ITestType.extends(IInterface)
-  True
-  >>> IInterface.providedBy(I)
-  True



More information about the checkins mailing list