[Checkins] SVN: zope.interface/branches/tseaver-better_unittests/ Merge from LP branch.

Tres Seaver cvs-admin at zope.org
Mon Mar 26 20:57:01 UTC 2012


Log message for revision 124742:
  Merge from LP branch.

Changed:
  U   zope.interface/branches/tseaver-better_unittests/.bzrignore
  A   zope.interface/branches/tseaver-better_unittests/README-better_unittest.txt
  U   zope.interface/branches/tseaver-better_unittests/buildout.cfg
  A   zope.interface/branches/tseaver-better_unittests/docs/
  A   zope.interface/branches/tseaver-better_unittests/docs/Makefile
  A   zope.interface/branches/tseaver-better_unittests/docs/README.rst
  A   zope.interface/branches/tseaver-better_unittests/docs/README.ru.rst
  A   zope.interface/branches/tseaver-better_unittests/docs/_static/
  A   zope.interface/branches/tseaver-better_unittests/docs/_templates/
  A   zope.interface/branches/tseaver-better_unittests/docs/adapter.rst
  A   zope.interface/branches/tseaver-better_unittests/docs/adapter.ru.rst
  A   zope.interface/branches/tseaver-better_unittests/docs/conf.py
  A   zope.interface/branches/tseaver-better_unittests/docs/foodforthought.rst
  A   zope.interface/branches/tseaver-better_unittests/docs/human.rst
  A   zope.interface/branches/tseaver-better_unittests/docs/human.ru.rst
  A   zope.interface/branches/tseaver-better_unittests/docs/index.rst
  A   zope.interface/branches/tseaver-better_unittests/docs/make.bat
  A   zope.interface/branches/tseaver-better_unittests/docs/verify.rst
  A   zope.interface/branches/tseaver-better_unittests/setup.cfg
  U   zope.interface/branches/tseaver-better_unittests/setup.py
  D   zope.interface/branches/tseaver-better_unittests/src/zope/interface/README.ru.txt
  D   zope.interface/branches/tseaver-better_unittests/src/zope/interface/README.txt
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/__init__.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/_zope_interface_coptimizations.c
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.py
  D   zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.ru.txt
  D   zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.txt
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/advice.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/common/interfaces.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/declarations.py
  D   zope.interface/branches/tseaver-better_unittests/src/zope/interface/human.ru.txt
  D   zope.interface/branches/tseaver-better_unittests/src/zope/interface/human.txt
  D   zope.interface/branches/tseaver-better_unittests/src/zope/interface/index.txt
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/interface.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/interfaces.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/registry.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/ro.py
  A   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/advisory_testing.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/dummy.py
  D   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/foodforthought.txt
  A   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/idummy.py
  D   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/ifoo.py
  A   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/ifoo.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_adapter.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_advice.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_declarations.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_document.py
  A   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_exceptions.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_interface.py
  A   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_interfaces.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_odd_declarations.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_registry.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_verify.py
  D   zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/unitfixtures.py
  U   zope.interface/branches/tseaver-better_unittests/src/zope/interface/verify.py
  D   zope.interface/branches/tseaver-better_unittests/src/zope/interface/verify.txt

-=-
Modified: zope.interface/branches/tseaver-better_unittests/.bzrignore
===================================================================
--- zope.interface/branches/tseaver-better_unittests/.bzrignore	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/.bzrignore	2012-03-26 20:56:58 UTC (rev 124742)
@@ -6,3 +6,7 @@
 ./parts
 *.egg-info
 ./build
+.coverage
+include
+lib
+docs/_build

Added: zope.interface/branches/tseaver-better_unittests/README-better_unittest.txt
===================================================================
--- zope.interface/branches/tseaver-better_unittests/README-better_unittest.txt	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/README-better_unittest.txt	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,79 @@
+Overview
+========
+
+This branch has three goals:
+
+- Convert all doctests in zope.interface to "normal" Sphinx documentation
+
+- Replace existin API coverage previously provided by the doctests with
+  standard unit tests.  
+
+- Get the unit test coverage, sans doctests, to 100%.
+
+There are secondary, related cleanups, mostly in line with the coding
+standards for unit tests proposed here:
+
+- http://palladion.com/home/tseaver/obzervationz/2008/unit_testing_notes-20080724
+
+- http://palladion.com/home/tseaver/obzervationz/2009/unit_testing_redux-20090802
+
+TODO
+====
+
+- [_] Move doctest files to docs:
+
+      o ``src/zope/interface/README.txt``
+
+      o ``src/zope/interface/index.txt``
+
+      o ``src/zope/interface/adapter.txt``
+
+      o ``src/zope/interface/human.txt``
+
+      o ``src/zope/interface/verify.txt``
+
+      o ``src/zope/interface/tests/foodforthought``
+
+      o ``src/zope/interface/README.ru.txt``
+
+      o ``src/zope/interface/adapter.ru.txt``
+
+      o ``src/zope/interface/human.ru.txt``
+
+- [X] Remove ``src/zope/interface/tests/unitfixtures.py``.
+
+- [X] Test both C and Python implementations.
+
+- [X] 100% unit test coverage when run under ``nose --with-coverage``:
+
+      * :mod:`zope.interface`
+
+      * :mod:`zope.interface.adapter`
+
+      * :mod:`zope.interface.common`
+
+      * :mod:`zope.interface.common.idatetime`
+
+      * :mod:`zope.interface.common.interfaces`
+
+      * :mod:`zope.interface.common.mapping`
+
+      * :mod:`zope.interface.common.sequence`
+
+      * :mod:`zope.interface.advice`
+
+      * :mod:`zope.interface.declarations`
+
+      * :mod:`zope.interface.document`
+
+      * :mod:`zope.interface.exceptions`
+
+      * :mod:`zope.interface.interface`
+
+      * :mod:`zope.interface.interfaces`
+
+      * :mod:`zope.interface.registry`
+
+      * :mod:`zope.interface.ro`
+
+      * :mod:`zope.interface.verify`

Modified: zope.interface/branches/tseaver-better_unittests/buildout.cfg
===================================================================
--- zope.interface/branches/tseaver-better_unittests/buildout.cfg	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/buildout.cfg	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,6 +1,6 @@
 [buildout]
 develop = .
-parts = test python docs
+parts = test python
 
 [test]
 recipe = zc.recipe.testrunner
@@ -12,10 +12,3 @@
 eggs = zope.interface
        zope.event
 interpreter = python
-
-[docs]
-recipe = z3c.recipe.sphinxdoc
-eggs = zope.interface [docs]
-build-dir = ${buildout:directory}/docs
-default.css =
-layout.html =

Added: zope.interface/branches/tseaver-better_unittests/docs/Makefile
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/Makefile	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/Makefile	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  texinfo    to make Texinfo files"
+	@echo "  info       to make Texinfo files and run them through makeinfo"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/zopeinterface.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/zopeinterface.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/zopeinterface"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/zopeinterface"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+	@echo "Run \`make' in that directory to run these through makeinfo" \
+	      "(use \`make info' here to do that automatically)."
+
+info:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo "Running Texinfo files through makeinfo..."
+	make -C $(BUILDDIR)/texinfo info
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."

Copied: zope.interface/branches/tseaver-better_unittests/docs/README.rst (from rev 124741, zope.interface/branches/tseaver-better_unittests/src/zope/interface/README.txt)
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/README.rst	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/README.rst	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,829 @@
+==========
+Interfaces
+==========
+
+Interfaces are objects that specify (document) the external behavior
+of objects that "provide" them.  An interface specifies behavior
+through:
+
+- Informal documentation in a doc string
+
+- Attribute definitions
+
+- Invariants, which are conditions that must hold for objects that
+  provide the interface
+
+Attribute definitions specify specific attributes. They define the
+attribute name and provide documentation and constraints of attribute
+values.  Attribute definitions can take a number of forms, as we'll
+see below.
+
+Defining interfaces
+===================
+
+Interfaces are defined using Python class statements::
+
+  >>> import zope.interface
+  >>> class IFoo(zope.interface.Interface):
+  ...    """Foo blah blah"""
+  ...
+  ...    x = zope.interface.Attribute("""X blah blah""")
+  ...
+  ...    def bar(q, r=None):
+  ...        """bar blah blah"""
+
+In the example above, we've created an interface, `IFoo`.  We
+subclassed `zope.interface.Interface`, which is an ancestor interface for
+all interfaces, much as `object` is an ancestor of all new-style
+classes [#create]_.   The interface is not a class, it's an Interface,
+an instance of `InterfaceClass`::
+
+  >>> type(IFoo)
+  <class 'zope.interface.interface.InterfaceClass'>
+
+We can ask for the interface's documentation::
+
+  >>> IFoo.__doc__
+  'Foo blah blah'
+
+and its name::
+
+  >>> IFoo.__name__
+  'IFoo'
+
+and even its module::
+
+  >>> IFoo.__module__
+  '__main__'
+
+The interface defined two attributes:
+
+`x`
+  This is the simplest form of attribute definition.  It has a name
+  and a doc string.  It doesn't formally specify anything else.
+
+`bar`
+  This is a method.  A method is defined via a function definition.  A
+  method is simply an attribute constrained to be a callable with a
+  particular signature, as provided by the function definition.
+
+  Note that `bar` doesn't take a `self` argument.  Interfaces document
+  how an object is *used*.  When calling instance methods, you don't
+  pass a `self` argument, so a `self` argument isn't included in the
+  interface signature.  The `self` argument in instance methods is
+  really an implementation detail of Python instances. Other objects,
+  besides instances can provide interfaces and their methods might not
+  be instance methods. For example, modules can provide interfaces and
+  their methods are usually just functions.  Even instances can have
+  methods that are not instance methods.
+
+You can access the attributes defined by an interface using mapping
+syntax::
+
+  >>> x = IFoo['x']
+  >>> type(x)
+  <class 'zope.interface.interface.Attribute'>
+  >>> x.__name__
+  'x'
+  >>> x.__doc__
+  'X blah blah'
+
+  >>> IFoo.get('x').__name__
+  'x'
+
+  >>> IFoo.get('y')
+
+You can use `in` to determine if an interface defines a name::
+
+  >>> 'x' in IFoo
+  True
+
+You can iterate over interfaces to get the names they define::
+
+  >>> names = list(IFoo)
+  >>> names.sort()
+  >>> names
+  ['bar', 'x']
+
+Remember that interfaces aren't classes. You can't access attribute
+definitions as attributes of interfaces::
+
+  >>> IFoo.x
+  Traceback (most recent call last):
+    File "<stdin>", line 1, in ?
+  AttributeError: 'InterfaceClass' object has no attribute 'x'
+
+Methods provide access to the method signature::
+
+  >>> bar = IFoo['bar']
+  >>> bar.getSignatureString()
+  '(q, r=None)'
+
+TODO
+  Methods really should have a better API.  This is something that
+  needs to be improved.
+
+Declaring interfaces
+====================
+
+Having defined interfaces, we can *declare* that objects provide
+them.  Before we describe the details, lets define some terms:
+
+*provide*
+   We say that objects *provide* interfaces.  If an object provides an
+   interface, then the interface specifies the behavior of the
+   object. In other words, interfaces specify the behavior of the
+   objects that provide them.
+
+*implement*
+   We normally say that classes *implement* interfaces.  If a class
+   implements an interface, then the instances of the class provide
+   the interface.  Objects provide interfaces that their classes
+   implement [#factory]_.  (Objects can provide interfaces directly,
+   in addition to what their classes implement.)
+
+   It is important to note that classes don't usually provide the
+   interfaces that they implement.
+
+   We can generalize this to factories.  For any callable object we
+   can declare that it produces objects that provide some interfaces
+   by saying that the factory implements the interfaces.
+
+Now that we've defined these terms, we can talk about the API for
+declaring interfaces.
+
+Declaring implemented interfaces
+--------------------------------
+
+The most common way to declare interfaces is using the implements
+function in a class statement::
+
+  >>> class Foo:
+  ...     zope.interface.implements(IFoo)
+  ...
+  ...     def __init__(self, x=None):
+  ...         self.x = x
+  ...
+  ...     def bar(self, q, r=None):
+  ...         return q, r, self.x
+  ...
+  ...     def __repr__(self):
+  ...         return "Foo(%s)" % self.x
+
+
+In this example, we declared that `Foo` implements `IFoo`. This means
+that instances of `Foo` provide `IFoo`.  Having made this declaration,
+there are several ways we can introspect the declarations.  First, we
+can ask an interface whether it is implemented by a class::
+
+  >>> IFoo.implementedBy(Foo)
+  True
+
+And we can ask whether an interface is provided by an object::
+
+  >>> foo = Foo()
+  >>> IFoo.providedBy(foo)
+  True
+
+Of course, `Foo` doesn't provide `IFoo`, it implements it::
+
+  >>> IFoo.providedBy(Foo)
+  False
+
+We can also ask what interfaces are implemented by an object::
+
+  >>> list(zope.interface.implementedBy(Foo))
+  [<InterfaceClass __main__.IFoo>]
+
+It's an error to ask for interfaces implemented by a non-callable
+object::
+
+  >>> IFoo.implementedBy(foo)
+  Traceback (most recent call last):
+  ...
+  TypeError: ('ImplementedBy called for non-factory', Foo(None))
+
+  >>> list(zope.interface.implementedBy(foo))
+  Traceback (most recent call last):
+  ...
+  TypeError: ('ImplementedBy called for non-factory', Foo(None))
+
+Similarly, we can ask what interfaces are provided by an object::
+
+  >>> list(zope.interface.providedBy(foo))
+  [<InterfaceClass __main__.IFoo>]
+  >>> list(zope.interface.providedBy(Foo))
+  []
+
+We can declare interfaces implemented by other factories (besides
+classes).  We do this using a Python-2.4-style decorator named
+`implementer`.  In versions of Python before 2.4, this looks like::
+
+  >>> def yfoo(y):
+  ...     foo = Foo()
+  ...     foo.y = y
+  ...     return foo
+  >>> yfoo = zope.interface.implementer(IFoo)(yfoo)
+
+  >>> list(zope.interface.implementedBy(yfoo))
+  [<InterfaceClass __main__.IFoo>]
+
+Note that the implementer decorator may modify it's argument. Callers
+should not assume that a new object is created.
+
+Using implementer also works on callable objects. This is used by
+zope.formlib, as an example.
+
+  >>> class yfactory:
+  ...     def __call__(self, y):
+  ...         foo = Foo()
+  ...         foo.y = y
+  ...         return foo
+  >>> yfoo = yfactory()
+  >>> yfoo = zope.interface.implementer(IFoo)(yfoo)
+
+  >>> list(zope.interface.implementedBy(yfoo))
+  [<InterfaceClass __main__.IFoo>]
+
+XXX: Double check and update these version numbers:
+
+In zope.interface 3.5.2 and lower, the implementer decorator can not
+be used for classes, but in 3.6.0 and higher it can:
+
+  >>> Foo = zope.interface.implementer(IFoo)(Foo)
+  >>> list(zope.interface.providedBy(Foo()))
+  [<InterfaceClass __main__.IFoo>]
+  
+Note that class decorators using the @implementer(IFoo) syntax are only 
+supported in Python 2.6 and later.
+
+
+Declaring provided interfaces
+-----------------------------
+
+We can declare interfaces directly provided by objects.  Suppose that
+we want to document what the `__init__` method of the `Foo` class
+does.  It's not *really* part of `IFoo`.  You wouldn't normally call
+the `__init__` method on Foo instances.  Rather, the `__init__` method
+is part of the `Foo`'s `__call__` method::
+
+  >>> class IFooFactory(zope.interface.Interface):
+  ...     """Create foos"""
+  ...
+  ...     def __call__(x=None):
+  ...         """Create a foo
+  ...
+  ...         The argument provides the initial value for x ...
+  ...         """
+
+It's the class that provides this interface, so we declare the
+interface on the class::
+
+  >>> zope.interface.directlyProvides(Foo, IFooFactory)
+
+And then, we'll see that Foo provides some interfaces::
+
+  >>> list(zope.interface.providedBy(Foo))
+  [<InterfaceClass __main__.IFooFactory>]
+  >>> IFooFactory.providedBy(Foo)
+  True
+
+Declaring class interfaces is common enough that there's a special
+declaration function for it, `classProvides`, that allows the
+declaration from within a class statement::
+
+  >>> class Foo2:
+  ...     zope.interface.implements(IFoo)
+  ...     zope.interface.classProvides(IFooFactory)
+  ...
+  ...     def __init__(self, x=None):
+  ...         self.x = x
+  ...
+  ...     def bar(self, q, r=None):
+  ...         return q, r, self.x
+  ...
+  ...     def __repr__(self):
+  ...         return "Foo(%s)" % self.x
+
+  >>> list(zope.interface.providedBy(Foo2))
+  [<InterfaceClass __main__.IFooFactory>]
+  >>> IFooFactory.providedBy(Foo2)
+  True
+
+There's a similar function, `moduleProvides`, that supports interface
+declarations from within module definitions.  For example, see the use
+of `moduleProvides` call in `zope.interface.__init__`, which declares that
+the package `zope.interface` provides `IInterfaceDeclaration`.
+
+Sometimes, we want to declare interfaces on instances, even though
+those instances get interfaces from their classes.  Suppose we create
+a new interface, `ISpecial`::
+
+  >>> class ISpecial(zope.interface.Interface):
+  ...     reason = zope.interface.Attribute("Reason why we're special")
+  ...     def brag():
+  ...         "Brag about being special"
+
+We can make an existing foo instance special by providing `reason`
+and `brag` attributes::
+
+  >>> foo.reason = 'I just am'
+  >>> def brag():
+  ...      return "I'm special!"
+  >>> foo.brag = brag
+  >>> foo.reason
+  'I just am'
+  >>> foo.brag()
+  "I'm special!"
+
+and by declaring the interface::
+
+  >>> zope.interface.directlyProvides(foo, ISpecial)
+
+then the new interface is included in the provided interfaces::
+
+  >>> ISpecial.providedBy(foo)
+  True
+  >>> list(zope.interface.providedBy(foo))
+  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
+
+We can find out what interfaces are directly provided by an object::
+
+  >>> list(zope.interface.directlyProvidedBy(foo))
+  [<InterfaceClass __main__.ISpecial>]
+
+  >>> newfoo = Foo()
+  >>> list(zope.interface.directlyProvidedBy(newfoo))
+  []
+
+Inherited declarations
+----------------------
+
+Normally, declarations are inherited::
+
+  >>> class SpecialFoo(Foo):
+  ...     zope.interface.implements(ISpecial)
+  ...     reason = 'I just am'
+  ...     def brag(self):
+  ...         return "I'm special because %s" % self.reason
+
+  >>> list(zope.interface.implementedBy(SpecialFoo))
+  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
+
+  >>> list(zope.interface.providedBy(SpecialFoo()))
+  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
+
+Sometimes, you don't want to inherit declarations.  In that case, you
+can use `implementsOnly`, instead of `implements`::
+
+  >>> class Special(Foo):
+  ...     zope.interface.implementsOnly(ISpecial)
+  ...     reason = 'I just am'
+  ...     def brag(self):
+  ...         return "I'm special because %s" % self.reason
+
+  >>> list(zope.interface.implementedBy(Special))
+  [<InterfaceClass __main__.ISpecial>]
+
+  >>> list(zope.interface.providedBy(Special()))
+  [<InterfaceClass __main__.ISpecial>]
+
+External declarations
+---------------------
+
+Normally, we make implementation declarations as part of a class
+definition. Sometimes, we may want to make declarations from outside
+the class definition. For example, we might want to declare interfaces
+for classes that we didn't write.  The function `classImplements` can
+be used for this purpose::
+
+  >>> class C:
+  ...     pass
+
+  >>> zope.interface.classImplements(C, IFoo)
+  >>> list(zope.interface.implementedBy(C))
+  [<InterfaceClass __main__.IFoo>]
+
+We can use `classImplementsOnly` to exclude inherited interfaces::
+
+  >>> class C(Foo):
+  ...     pass
+
+  >>> zope.interface.classImplementsOnly(C, ISpecial)
+  >>> list(zope.interface.implementedBy(C))
+  [<InterfaceClass __main__.ISpecial>]
+
+
+
+Declaration Objects
+-------------------
+
+When we declare interfaces, we create *declaration* objects.  When we
+query declarations, declaration objects are returned::
+
+  >>> type(zope.interface.implementedBy(Special))
+  <class 'zope.interface.declarations.Implements'>
+
+Declaration objects and interface objects are similar in many ways. In
+fact, they share a common base class.  The important thing to realize
+about them is that they can be used where interfaces are expected in
+declarations. Here's a silly example::
+
+  >>> class Special2(Foo):
+  ...     zope.interface.implementsOnly(
+  ...          zope.interface.implementedBy(Foo),
+  ...          ISpecial,
+  ...          )
+  ...     reason = 'I just am'
+  ...     def brag(self):
+  ...         return "I'm special because %s" % self.reason
+
+The declaration here is almost the same as
+``zope.interface.implements(ISpecial)``, except that the order of
+interfaces in the resulting declaration is different::
+
+  >>> list(zope.interface.implementedBy(Special2))
+  [<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.ISpecial>]
+
+
+Interface Inheritance
+=====================
+
+Interfaces can extend other interfaces. They do this simply by listing
+the other interfaces as base interfaces::
+
+  >>> class IBlat(zope.interface.Interface):
+  ...     """Blat blah blah"""
+  ...
+  ...     y = zope.interface.Attribute("y blah blah")
+  ...     def eek():
+  ...         """eek blah blah"""
+
+  >>> IBlat.__bases__
+  (<InterfaceClass zope.interface.Interface>,)
+
+  >>> class IBaz(IFoo, IBlat):
+  ...     """Baz blah"""
+  ...     def eek(a=1):
+  ...         """eek in baz blah"""
+  ...
+
+  >>> IBaz.__bases__
+  (<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.IBlat>)
+
+  >>> names = list(IBaz)
+  >>> names.sort()
+  >>> names
+  ['bar', 'eek', 'x', 'y']
+
+Note that `IBaz` overrides eek::
+
+  >>> IBlat['eek'].__doc__
+  'eek blah blah'
+  >>> IBaz['eek'].__doc__
+  'eek in baz blah'
+
+We were careful to override eek in a compatible way.  When extending
+an interface, the extending interface should be compatible [#compat]_
+with the extended interfaces.
+
+We can ask whether one interface extends another::
+
+  >>> IBaz.extends(IFoo)
+  True
+  >>> IBlat.extends(IFoo)
+  False
+
+Note that interfaces don't extend themselves::
+
+  >>> IBaz.extends(IBaz)
+  False
+
+Sometimes we wish they did, but we can, instead use `isOrExtends`::
+
+  >>> IBaz.isOrExtends(IBaz)
+  True
+  >>> IBaz.isOrExtends(IFoo)
+  True
+  >>> IFoo.isOrExtends(IBaz)
+  False
+
+When we iterate over an interface, we get all of the names it defines,
+including names defined by base interfaces. Sometimes, we want *just*
+the names defined by the interface directly. We bane use the `names`
+method for that::
+
+  >>> list(IBaz.names())
+  ['eek']
+
+Inheritance of attribute specifications
+---------------------------------------
+
+An interface may override attribute definitions from base interfaces.
+If two base interfaces define the same attribute, the attribute is
+inherited from the most specific interface. For example, with::
+
+  >>> class IBase(zope.interface.Interface):
+  ...
+  ...     def foo():
+  ...         "base foo doc"
+
+  >>> class IBase1(IBase):
+  ...     pass
+
+  >>> class IBase2(IBase):
+  ...
+  ...     def foo():
+  ...         "base2 foo doc"
+
+  >>> class ISub(IBase1, IBase2):
+  ...     pass
+
+ISub's definition of foo is the one from IBase2, since IBase2 is more
+specific that IBase::
+
+  >>> ISub['foo'].__doc__
+  'base2 foo doc'
+
+Note that this differs from a depth-first search.
+
+Sometimes, it's useful to ask whether an interface defines an
+attribute directly.  You can use the direct method to get a directly
+defined definitions::
+
+  >>> IBase.direct('foo').__doc__
+  'base foo doc'
+
+  >>> ISub.direct('foo')
+
+Specifications
+--------------
+
+Interfaces and declarations are both special cases of specifications.
+What we described above for interface inheritance applies to both
+declarations and specifications.  Declarations actually extend the
+interfaces that they declare::
+
+  >>> class Baz(object):
+  ...     zope.interface.implements(IBaz)
+
+  >>> baz_implements = zope.interface.implementedBy(Baz)
+  >>> baz_implements.__bases__
+  (<InterfaceClass __main__.IBaz>, <implementedBy ...object>)
+
+  >>> baz_implements.extends(IFoo)
+  True
+
+  >>> baz_implements.isOrExtends(IFoo)
+  True
+  >>> baz_implements.isOrExtends(baz_implements)
+  True
+
+Specifications (interfaces and declarations) provide an `__sro__`
+that lists the specification and all of it's ancestors::
+
+  >>> baz_implements.__sro__
+  (<implementedBy __main__.Baz>,
+   <InterfaceClass __main__.IBaz>,
+   <InterfaceClass __main__.IFoo>,
+   <InterfaceClass __main__.IBlat>,
+   <InterfaceClass zope.interface.Interface>,
+   <implementedBy ...object>)
+
+
+Tagged Values
+=============
+
+Interfaces and attribute descriptions support an extension mechanism,
+borrowed from UML, called "tagged values" that lets us store extra
+data::
+
+  >>> IFoo.setTaggedValue('date-modified', '2004-04-01')
+  >>> IFoo.setTaggedValue('author', 'Jim Fulton')
+  >>> IFoo.getTaggedValue('date-modified')
+  '2004-04-01'
+  >>> IFoo.queryTaggedValue('date-modified')
+  '2004-04-01'
+  >>> IFoo.queryTaggedValue('datemodified')
+  >>> tags = list(IFoo.getTaggedValueTags())
+  >>> tags.sort()
+  >>> tags
+  ['author', 'date-modified']
+
+Function attributes are converted to tagged values when method
+attribute definitions are created::
+
+  >>> class IBazFactory(zope.interface.Interface):
+  ...     def __call__():
+  ...         "create one"
+  ...     __call__.return_type = IBaz
+
+  >>> IBazFactory['__call__'].getTaggedValue('return_type')
+  <InterfaceClass __main__.IBaz>
+
+Tagged values can also be defined from within an interface definition::
+
+  >>> class IWithTaggedValues(zope.interface.Interface):
+  ...     zope.interface.taggedValue('squish', 'squash')
+  >>> IWithTaggedValues.getTaggedValue('squish')
+  'squash'
+
+Invariants
+==========
+
+Interfaces can express conditions that must hold for objects that
+provide them. These conditions are expressed using one or more
+invariants.  Invariants are callable objects that will be called with
+an object that provides an interface. An invariant raises an `Invalid`
+exception if the condition doesn't hold.  Here's an example::
+
+  >>> class RangeError(zope.interface.Invalid):
+  ...     """A range has invalid limits"""
+  ...     def __repr__(self):
+  ...         return "RangeError(%r)" % self.args
+
+  >>> def range_invariant(ob):
+  ...     if ob.max < ob.min:
+  ...         raise RangeError(ob)
+
+Given this invariant, we can use it in an interface definition::
+
+  >>> class IRange(zope.interface.Interface):
+  ...     min = zope.interface.Attribute("Lower bound")
+  ...     max = zope.interface.Attribute("Upper bound")
+  ...
+  ...     zope.interface.invariant(range_invariant)
+
+Interfaces have a method for checking their invariants::
+
+  >>> class Range(object):
+  ...     zope.interface.implements(IRange)
+  ...
+  ...     def __init__(self, min, max):
+  ...         self.min, self.max = min, max
+  ...
+  ...     def __repr__(self):
+  ...         return "Range(%s, %s)" % (self.min, self.max)
+
+  >>> IRange.validateInvariants(Range(1,2))
+  >>> IRange.validateInvariants(Range(1,1))
+  >>> IRange.validateInvariants(Range(2,1))
+  Traceback (most recent call last):
+  ...
+  RangeError: Range(2, 1)
+
+If you have multiple invariants, you may not want to stop checking
+after the first error.  If you pass a list to `validateInvariants`,
+then a single `Invalid` exception will be raised with the list of
+exceptions as it's argument::
+
+  >>> from zope.interface.exceptions import Invalid
+  >>> errors = []
+  >>> try:
+  ...     IRange.validateInvariants(Range(2,1), errors)
+  ... except Invalid, e:
+  ...     str(e)
+  '[RangeError(Range(2, 1))]'
+  
+And the list will be filled with the individual exceptions::
+
+  >>> errors
+  [RangeError(Range(2, 1))]
+
+
+  >>> del errors[:]
+
+Adaptation
+==========
+
+Interfaces can be called to perform adaptation.
+
+The semantics are based on those of the PEP 246 adapt function.
+
+If an object cannot be adapted, then a TypeError is raised::
+
+  >>> class I(zope.interface.Interface):
+  ...     pass
+
+  >>> I(0)
+  Traceback (most recent call last):
+  ...
+  TypeError: ('Could not adapt', 0, <InterfaceClass __main__.I>)
+
+
+
+unless an alternate value is provided as a second positional argument::
+
+  >>> I(0, 'bob')
+  'bob'
+
+If an object already implements the interface, then it will be returned::
+
+  >>> class C(object):
+  ...     zope.interface.implements(I)
+
+  >>> obj = C()
+  >>> I(obj) is obj
+  True
+
+If an object implements __conform__, then it will be used::
+
+  >>> class C(object):
+  ...     zope.interface.implements(I)
+  ...     def __conform__(self, proto):
+  ...          return 0
+
+  >>> I(C())
+  0
+
+Adapter hooks (see __adapt__) will also be used, if present::
+
+  >>> from zope.interface.interface import adapter_hooks
+  >>> def adapt_0_to_42(iface, obj):
+  ...     if obj == 0:
+  ...         return 42
+
+  >>> adapter_hooks.append(adapt_0_to_42)
+  >>> I(0)
+  42
+
+  >>> adapter_hooks.remove(adapt_0_to_42)
+  >>> I(0)
+  Traceback (most recent call last):
+  ...
+  TypeError: ('Could not adapt', 0, <InterfaceClass __main__.I>)
+
+__adapt__
+---------
+
+  >>> class I(zope.interface.Interface):
+  ...     pass
+
+Interfaces implement the PEP 246 __adapt__ method.
+
+This method is normally not called directly. It is called by the PEP
+246 adapt framework and by the interface __call__ operator.
+
+The adapt method is responsible for adapting an object to the
+reciever.
+
+The default version returns None::
+
+  >>> I.__adapt__(0)
+
+unless the object given provides the interface::
+
+  >>> class C(object):
+  ...     zope.interface.implements(I)
+
+  >>> obj = C()
+  >>> I.__adapt__(obj) is obj
+  True
+
+Adapter hooks can be provided (or removed) to provide custom
+adaptation. We'll install a silly hook that adapts 0 to 42.
+We install a hook by simply adding it to the adapter_hooks
+list::
+
+  >>> from zope.interface.interface import adapter_hooks
+  >>> def adapt_0_to_42(iface, obj):
+  ...     if obj == 0:
+  ...         return 42
+
+  >>> adapter_hooks.append(adapt_0_to_42)
+  >>> I.__adapt__(0)
+  42
+
+Hooks must either return an adapter, or None if no adapter can
+be found.
+
+Hooks can be uninstalled by removing them from the list::
+
+  >>> adapter_hooks.remove(adapt_0_to_42)
+  >>> I.__adapt__(0)
+
+
+.. [#create] The main reason we subclass `Interface` is to cause the
+             Python class statement to create an interface, rather
+             than a class.
+
+             It's possible to create interfaces by calling a special
+             interface class directly.  Doing this, it's possible
+             (and, on rare occasions, useful) to create interfaces
+             that don't descend from `Interface`.  Using this
+             technique is beyond the scope of this document.
+
+.. [#factory] Classes are factories.  They can be called to create
+              their instances.  We expect that we will eventually
+              extend the concept of implementation to other kinds of
+              factories, so that we can declare the interfaces
+              provided by the objects created.
+
+.. [#compat] The goal is substitutability.  An object that provides an
+             extending interface should be substitutable for an object
+             that provides the extended interface.  In our example, an
+             object that provides IBaz should be usable whereever an
+             object that provides IBlat is expected.
+
+             The interface implementation doesn't enforce this.
+             but maybe it should do some checks.

Copied: zope.interface/branches/tseaver-better_unittests/docs/README.ru.rst (from rev 124741, zope.interface/branches/tseaver-better_unittests/src/zope/interface/README.ru.txt)
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/README.ru.rst	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/README.ru.rst	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,803 @@
+==========
+Интерфейсы
+==========
+
+.. contents::
+
+Интерфейсы - это объекты специфицирующие (документирующие) внешнее поведение
+объектов которые их "предоставляют". Интерфейсы определяют поведение через
+следующие составляющие:
+
+- Неформальную документацию в строках документации
+
+- Определения атрибутов
+
+- Инварианты - условия, которые должны соблюдаться для объектов предоставляющих
+  интерфейс
+
+Определения атрибутов описывают конкретные атрибуты. Они определяют
+имя атрибута и предоставляют документацию и ограничения для значений
+атрибута. Определения атрибутов могут быть заданы несколькими путями
+как мы увидим ниже.
+
+Определение интерфейсов
+=======================
+
+Интерфейсы определяются с использованием ключевого слова class::
+
+  >>> import zope.interface
+  >>> class IFoo(zope.interface.Interface):
+  ...    """Foo blah blah"""
+  ...
+  ...    x = zope.interface.Attribute("""X blah blah""")
+  ...
+  ...    def bar(q, r=None):
+  ...        """bar blah blah"""
+
+В примере выше мы создали интерфейс `IFoo`. Мы наследуем его от
+класса `zope.interface.Interface`, который является родительским интерфейсом
+для всех интерфейсов, как `object` - это родительский класс для всех новых
+классов [#create]_. Данный интерфейс не является классом, а является
+Интерфейсом, экземпляром `InterfaceClass`::
+
+  >>> type(IFoo)
+  <class 'zope.interface.interface.InterfaceClass'>
+
+Мы можем запросить у интерфейса его документацию::
+
+  >>> IFoo.__doc__
+  'Foo blah blah'
+
+и его имя::
+
+  >>> IFoo.__name__
+  'IFoo'
+
+и даже модуль в котором он определен::
+
+  >>> IFoo.__module__
+  '__main__'
+
+Наш интерфейс определяет два атрибута:
+
+`x`
+  Это простейшая форма определения атрибутов. Определяются имя
+  и строка документации. Формально здесь не определяется ничего более.
+
+`bar`
+  Это метод. Методы определяются как обычные функции. Метод - это просто
+  атрибут который должен быть вызываемым с указанием сигнатуры,
+  предоставляемой определением функции.
+
+  Надо отметить, что аргумент `self` не указывается для `bar`. Интерфейс
+  документирует как объект *используется*. Когда методы экземпляров классов
+  вызываются мы не передаем аргумент `self`, таким образом аргумент `self`
+  не включается и в сигнатуру интерфейса. Аргумент `self` в методах
+  экземпляров классов на самом деле деталь реализации экземпляров классов
+  в Python. Другие объекты кроме экземпляров классов могут предоставлять
+  интерфейсы и их методы могут не быть методами экземпляров классов. Для
+  примера модули могут предоставлять интерфейсы и их методы обычно просто
+  функции. Даже экземпляры могут иметь методы не являющиеся методами
+  экземпляров класса.
+
+Мы можем получить доступ к атрибутам определенным интерфейсом используя
+синтаксис доступа к элементам массива::
+
+  >>> x = IFoo['x']
+  >>> type(x)
+  <class 'zope.interface.interface.Attribute'>
+  >>> x.__name__
+  'x'
+  >>> x.__doc__
+  'X blah blah'
+
+  >>> IFoo.get('x').__name__
+  'x'
+
+  >>> IFoo.get('y')
+
+Можно использовать `in` для определения содержит ли интерфейс
+определенное имя::
+
+  >>> 'x' in IFoo
+  True
+
+Мы можем использовать итератор для интерфейсов что бы получить все имена
+которые интерфейсы определяют::
+
+  >>> names = list(IFoo)
+  >>> names.sort()
+  >>> names
+  ['bar', 'x']
+
+Надо помнить, что интерфейсы не являются классами. Мы не можем получить
+доступ к определениям атрибутов через доступ к атрибутам интерфейсов::
+
+  >>> IFoo.x
+  Traceback (most recent call last):
+    File "<stdin>", line 1, in ?
+  AttributeError: 'InterfaceClass' object has no attribute 'x'
+
+Методы также предоставляют доступ к сигнатуре метода::
+
+  >>> bar = IFoo['bar']
+  >>> bar.getSignatureString()
+  '(q, r=None)'
+
+Объявление интерфейсов
+======================
+
+Определив интерфейс мы можем теперь *объявить*, что объекты предоставляют их.
+Перед описанием деталей определим некоторые термины:
+
+*предоставлять*
+  Мы говорим, что объекты *предоставляют* интерфейсы. Если объект
+  предоставляет интерфейс, тогда интерфейс специфицирует поведение объекта.
+  Другими словами, интерфейсы специфицируют поведение объектов которые
+  предоставляют их.
+
+*реализовать*
+  Мы обычно говорим что классы *реализуют* интерфейсы. Если класс
+  реализует интерфейс, тогда экземпляры этого класса предоставляют
+  данный интерфейс. Объекты предоставляют интерфейсы которые их классы
+  реализуют [#factory]_. (Объекты также могут предоставлять интерфейсы напрямую
+  плюс к тем которые реализуют их классы.)
+
+  Важно помнить, что классы обычно не предоставляют интерфейсы которые
+  они реализуют.
+
+  Мы можем обобщить это до фабрик. Для любого вызываемого объекта мы можем
+  объявить что он производит объекты которые предоставляют какие-либо
+  интерфейсы сказав, что фабрика реализует данные интерфейсы.
+
+Теперь после того как мы определили эти термины мы можем поговорить об
+API для объявления интерфейсов.
+
+Объявление реализуемых интерфейсов
+----------------------------------
+
+Наиболее часто используемый путь для объявления интерфейсов - это использование
+функции implements в определении класса::
+
+  >>> class Foo:
+  ...     zope.interface.implements(IFoo)
+  ...
+  ...     def __init__(self, x=None):
+  ...         self.x = x
+  ...
+  ...     def bar(self, q, r=None):
+  ...         return q, r, self.x
+  ...
+  ...     def __repr__(self):
+  ...         return "Foo(%s)" % self.x
+
+В этом примере мы объявили, что `Foo` реализует `IFoo`. Это значит, что
+экземпляры `Foo` предоставляют `IFoo`. После данного объявления есть
+несколько путей для анализа объявлений. Во-первых мы можем спросить
+что интерфейс реализован классом::
+
+  >>> IFoo.implementedBy(Foo)
+  True
+
+Также мы можем спросить если интерфейс предоставляется объектами класса::
+
+  >>> foo = Foo()
+  >>> IFoo.providedBy(foo)
+  True
+
+Конечно `Foo` не предоставляет `IFoo`, он реализует его::
+
+  >>> IFoo.providedBy(Foo)
+  False
+
+Мы можем также узнать какие интерфейсы реализуются объектами::
+
+  >>> list(zope.interface.implementedBy(Foo))
+  [<InterfaceClass __main__.IFoo>]
+
+Это ошибка спрашивать про интерфейсы реализуемые не вызываемым объектом::
+
+  >>> IFoo.implementedBy(foo)
+  Traceback (most recent call last):
+  ...
+  TypeError: ('ImplementedBy called for non-factory', Foo(None))
+
+  >>> list(zope.interface.implementedBy(foo))
+  Traceback (most recent call last):
+  ...
+  TypeError: ('ImplementedBy called for non-factory', Foo(None))
+
+Также можно узнать какие интерфейсы предоставляются объектами::
+
+  >>> list(zope.interface.providedBy(foo))
+  [<InterfaceClass __main__.IFoo>]
+  >>> list(zope.interface.providedBy(Foo))
+  []
+
+Мы можем объявить интерфейсы реализуемые другими фабриками (кроме классов).
+Это можно сделать используя декоратор `implementer` (в стиле Python 2.4).
+Для версий Python ниже 2.4 это будет выглядеть следующим образом::
+
+  >>> def yfoo(y):
+  ...     foo = Foo()
+  ...     foo.y = y
+  ...     return foo
+  >>> yfoo = zope.interface.implementer(IFoo)(yfoo)
+
+  >>> list(zope.interface.implementedBy(yfoo))
+  [<InterfaceClass __main__.IFoo>]
+
+Надо заметить, что декоратор implementer может модифицировать свои аргументы.
+Вызывающая сторона не должна предполагать, что всегда будет создаваться
+новый объект.
+
+XXX: Double check and update these version numbers, and translate to russian:
+
+In zope.interface 3.5.1 and lower, the implementer decorator can not
+be used for classes, but in 3.5.2 and higher it can:
+
+  >>> Foo = zope.interface.implementer(IFoo)(Foo)
+  >>> list(zope.interface.providedBy(Foo()))
+  [<InterfaceClass __main__.IFoo>]
+  
+Note that class decorators using the @implementer(IFoo) syntax are only 
+supported in Python 2.6 and later.
+
+
+Объявление предоставляемых интерфейсов
+--------------------------------------
+
+Мы можем объявлять интерфейсы напрямую предоставляемые объектами. Предположим
+что мы хотим документировать что делает метод `__init__` класса `Foo`. Это
+*точно* не часть `IFoo`. Обычно мы не должны напрямую вызывать метод `__init__`
+для экземпляров Foo. Скорее метод `__init__` является частью метода `__call__`
+класса `Foo`::
+
+  >>> class IFooFactory(zope.interface.Interface):
+  ...     """Create foos"""
+  ...
+  ...     def __call__(x=None):
+  ...         """Create a foo
+  ...
+  ...         The argument provides the initial value for x ...
+  ...         """
+
+У нас есть класс предоставляющий данный интерфейс, таким образом мы можем
+объявить интерфейс класса::
+
+  >>> zope.interface.directlyProvides(Foo, IFooFactory)
+
+Теперь мы видим, что Foo уже предоставляет интерфейсы::
+
+  >>> list(zope.interface.providedBy(Foo))
+  [<InterfaceClass __main__.IFooFactory>]
+  >>> IFooFactory.providedBy(Foo)
+  True
+
+Объявление интерфейсов класса достаточно частая операция и для нее есть
+специальная функция объявления `classProvides`, которая позволяет объявлять
+интерфейсы при определении класса::
+
+  >>> class Foo2:
+  ...     zope.interface.implements(IFoo)
+  ...     zope.interface.classProvides(IFooFactory)
+  ...
+  ...     def __init__(self, x=None):
+  ...         self.x = x
+  ...
+  ...     def bar(self, q, r=None):
+  ...         return q, r, self.x
+  ...
+  ...     def __repr__(self):
+  ...         return "Foo(%s)" % self.x
+
+  >>> list(zope.interface.providedBy(Foo2))
+  [<InterfaceClass __main__.IFooFactory>]
+  >>> IFooFactory.providedBy(Foo2)
+  True
+
+Похожая функция `moduleProvides` поддерживает объявление интерфейсов при
+определении модуля. Для примера смотрите использование вызова
+`moduleProvides` в `zope.interface.__init__`, который объявляет, что
+пакет `zope.interface` предоставляет `IInterfaceDeclaration`.
+
+Иногда мы хотим объявить интерфейсы экземпляров, даже если эти экземпляры
+уже берут интерфейсы от своих классов. Предположим, что мы создаем новый
+интерфейс `ISpecial`::
+
+  >>> class ISpecial(zope.interface.Interface):
+  ...     reason = zope.interface.Attribute("Reason why we're special")
+  ...     def brag():
+  ...         "Brag about being special"
+
+Мы можем сделать созданный экземпляр foo специальным предоставив атрибуты
+`reason` и `brag`::
+
+  >>> foo.reason = 'I just am'
+  >>> def brag():
+  ...      return "I'm special!"
+  >>> foo.brag = brag
+  >>> foo.reason
+  'I just am'
+  >>> foo.brag()
+  "I'm special!"
+
+и объявив интерфейс::
+
+  >>> zope.interface.directlyProvides(foo, ISpecial)
+
+таким образом новый интерфейс включается в список предоставляемых интерфейсов::
+
+  >>> ISpecial.providedBy(foo)
+  True
+  >>> list(zope.interface.providedBy(foo))
+  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
+
+Мы также можем определить, что интерфейсы напрямую предоставляются
+объектами::
+
+  >>> list(zope.interface.directlyProvidedBy(foo))
+  [<InterfaceClass __main__.ISpecial>]
+
+  >>> newfoo = Foo()
+  >>> list(zope.interface.directlyProvidedBy(newfoo))
+  []
+
+Наследуемые объявления
+----------------------
+
+Обычно объявления наследуются::
+
+  >>> class SpecialFoo(Foo):
+  ...     zope.interface.implements(ISpecial)
+  ...     reason = 'I just am'
+  ...     def brag(self):
+  ...         return "I'm special because %s" % self.reason
+
+  >>> list(zope.interface.implementedBy(SpecialFoo))
+  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
+
+  >>> list(zope.interface.providedBy(SpecialFoo()))
+  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
+
+Иногда мы не хотим наследовать объявления. В этом случае мы можем
+использовать `implementsOnly` вместо `implements`::
+
+  >>> class Special(Foo):
+  ...     zope.interface.implementsOnly(ISpecial)
+  ...     reason = 'I just am'
+  ...     def brag(self):
+  ...         return "I'm special because %s" % self.reason
+
+  >>> list(zope.interface.implementedBy(Special))
+  [<InterfaceClass __main__.ISpecial>]
+
+  >>> list(zope.interface.providedBy(Special()))
+  [<InterfaceClass __main__.ISpecial>]
+
+Внешние объявления
+------------------
+
+Обычно мы создаем объявления реализации как часть объявления класса. Иногда
+мы можем захотеть создать объявления вне объявления класса. Для примера,
+мы можем хотеть объявить интерфейсы для классов которые писали не мы.
+Для этого может использоваться функция `classImplements`::
+
+  >>> class C:
+  ...     pass
+
+  >>> zope.interface.classImplements(C, IFoo)
+  >>> list(zope.interface.implementedBy(C))
+  [<InterfaceClass __main__.IFoo>]
+
+Мы можем использовать `classImplementsOnly` для исключения наследуемых
+интерфейсов::
+
+  >>> class C(Foo):
+  ...     pass
+
+  >>> zope.interface.classImplementsOnly(C, ISpecial)
+  >>> list(zope.interface.implementedBy(C))
+  [<InterfaceClass __main__.ISpecial>]
+
+Объекты объявлений
+------------------
+
+Когда мы объявляем интерфейсы мы создаем объект *объявления*. Когда мы
+запрашиваем объявления возвращается объект объявления::
+
+  >>> type(zope.interface.implementedBy(Special))
+  <class 'zope.interface.declarations.Implements'>
+
+Объекты объявления и объекты интерфейсов во многом похожи друг на друга.
+На самом деле они даже имеют общий базовый класс. Важно понять, что они могут
+использоваться там где в объявлениях ожидаются интерфейсы. Вот простой
+пример::
+
+  >>> class Special2(Foo):
+  ...     zope.interface.implementsOnly(
+  ...          zope.interface.implementedBy(Foo),
+  ...          ISpecial,
+  ...          )
+  ...     reason = 'I just am'
+  ...     def brag(self):
+  ...         return "I'm special because %s" % self.reason
+
+Объявление здесь практически такое же как
+``zope.interface.implements(ISpecial)``, отличие только в порядке
+интерфейсов в итоговом объявления::
+
+  >>> list(zope.interface.implementedBy(Special2))
+  [<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.ISpecial>]
+
+Наследование интерфейсов
+========================
+
+Интерфейсы могут расширять другие интерфейсы. Они делают это просто
+показывая эти интерфейсы как базовые::
+
+  >>> class IBlat(zope.interface.Interface):
+  ...     """Blat blah blah"""
+  ...
+  ...     y = zope.interface.Attribute("y blah blah")
+  ...     def eek():
+  ...         """eek blah blah"""
+
+  >>> IBlat.__bases__
+  (<InterfaceClass zope.interface.Interface>,)
+
+  >>> class IBaz(IFoo, IBlat):
+  ...     """Baz blah"""
+  ...     def eek(a=1):
+  ...         """eek in baz blah"""
+  ...
+
+  >>> IBaz.__bases__
+  (<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.IBlat>)
+
+  >>> names = list(IBaz)
+  >>> names.sort()
+  >>> names
+  ['bar', 'eek', 'x', 'y']
+
+Заметим, что `IBaz` переопределяет eek::
+
+  >>> IBlat['eek'].__doc__
+  'eek blah blah'
+  >>> IBaz['eek'].__doc__
+  'eek in baz blah'
+
+Мы были осторожны переопределяя eek совместимым путем. Когда интерфейс
+расширяется, расширенный интерфейс должен быть совместимым [#compat]_ с
+расширяемыми интерфейсами.
+
+Мы можем запросить расширяет ли один из интерфейсов другой::
+
+  >>> IBaz.extends(IFoo)
+  True
+  >>> IBlat.extends(IFoo)
+  False
+
+Заметим, что интерфейсы не расширяют сами себя::
+
+  >>> IBaz.extends(IBaz)
+  False
+
+Иногда мы можем хотеть что бы они расширяли сами себя, но вместо этого
+мы можем использовать `isOrExtends`::
+
+  >>> IBaz.isOrExtends(IBaz)
+  True
+  >>> IBaz.isOrExtends(IFoo)
+  True
+  >>> IFoo.isOrExtends(IBaz)
+  False
+
+Когда мы применяем итерацию к интерфейсу мы получаем все имена которые он
+определяет включая имена определенные для базовых интерфейсов. Иногда
+мы хотим получить *только* имена определенные интерфейсом напрямую.
+Для этого мы используем метод `names`::
+
+  >>> list(IBaz.names())
+  ['eek']
+
+Наследование в случае определения атрибутов
+--------------------------------------------
+
+Интерфейс может переопределять определения атрибутов из базовых интерфейсов.
+Если два базовых интерфейса определяют один и тот же атрибут атрибут
+наследуется от более специфичного интерфейса. Для примера::
+
+  >>> class IBase(zope.interface.Interface):
+  ...
+  ...     def foo():
+  ...         "base foo doc"
+
+  >>> class IBase1(IBase):
+  ...     pass
+
+  >>> class IBase2(IBase):
+  ...
+  ...     def foo():
+  ...         "base2 foo doc"
+
+  >>> class ISub(IBase1, IBase2):
+  ...     pass
+
+Определение ISub для foo будет из IBase2 т.к. IBase2 более специфичен для
+IBase::
+
+  >>> ISub['foo'].__doc__
+  'base2 foo doc'
+
+Заметим, что это отличается от поиска в глубину.
+
+Иногда полезно узнать, что интерфейс определяет атрибут напрямую. Мы можем
+использовать метод direct для получения напрямую определенных атрибутов::
+
+  >>> IBase.direct('foo').__doc__
+  'base foo doc'
+
+  >>> ISub.direct('foo')
+
+Спецификации
+------------
+
+Интерфейсы и объявления - это специальные случаи спецификаций. Описание
+выше для наследования интерфейсов можно применить и к объявлениям и
+к спецификациям. Объявления фактически расширяют интерфейсы которые они
+объявляют::
+
+  >>> class Baz(object):
+  ...     zope.interface.implements(IBaz)
+
+  >>> baz_implements = zope.interface.implementedBy(Baz)
+  >>> baz_implements.__bases__
+  (<InterfaceClass __main__.IBaz>, <implementedBy ...object>)
+
+  >>> baz_implements.extends(IFoo)
+  True
+
+  >>> baz_implements.isOrExtends(IFoo)
+  True
+  >>> baz_implements.isOrExtends(baz_implements)
+  True
+
+Спецификации (интерфейсы и объявления) предоставляют атрибут `__sro__`
+который описывает спецификацию и всех ее предков::
+
+  >>> baz_implements.__sro__
+  (<implementedBy __main__.Baz>,
+   <InterfaceClass __main__.IBaz>,
+   <InterfaceClass __main__.IFoo>,
+   <InterfaceClass __main__.IBlat>,
+   <InterfaceClass zope.interface.Interface>,
+   <implementedBy ...object>)
+
+Помеченные значения
+===================
+
+Интерфейсы и описания атрибутов поддерживают механизм расширения
+заимствованный из UML и называемый "помеченные значения" который позволяет
+сохранять дополнительные данные::
+
+  >>> IFoo.setTaggedValue('date-modified', '2004-04-01')
+  >>> IFoo.setTaggedValue('author', 'Jim Fulton')
+  >>> IFoo.getTaggedValue('date-modified')
+  '2004-04-01'
+  >>> IFoo.queryTaggedValue('date-modified')
+  '2004-04-01'
+  >>> IFoo.queryTaggedValue('datemodified')
+  >>> tags = list(IFoo.getTaggedValueTags())
+  >>> tags.sort()
+  >>> tags
+  ['author', 'date-modified']
+
+Атрибуты функций конвертируются в помеченные значения когда создаются
+определения атрибутов метода::
+
+  >>> class IBazFactory(zope.interface.Interface):
+  ...     def __call__():
+  ...         "create one"
+  ...     __call__.return_type = IBaz
+
+  >>> IBazFactory['__call__'].getTaggedValue('return_type')
+  <InterfaceClass __main__.IBaz>
+
+Помеченные значения также могут быть определены внутри определения
+интерфейса::
+
+  >>> class IWithTaggedValues(zope.interface.Interface):
+  ...     zope.interface.taggedValue('squish', 'squash')
+  >>> IWithTaggedValues.getTaggedValue('squish')
+  'squash'
+
+Инварианты
+==========
+
+Интерфейсы могут описывать условия которые должны быть соблюдены для объектов
+которые их предоставляют. Эти условия описываются используя один или более
+инвариантов. Инварианты - это вызываемые объекты которые будут вызваны
+с объектом предоставляющим интерфейс в качестве параметра. Инвариант
+должен выкинуть исключение `Invalid` если условие не соблюдено. Например::
+
+  >>> class RangeError(zope.interface.Invalid):
+  ...     """A range has invalid limits"""
+  ...     def __repr__(self):
+  ...         return "RangeError(%r)" % self.args
+
+  >>> def range_invariant(ob):
+  ...     if ob.max < ob.min:
+  ...         raise RangeError(ob)
+
+Определив этот инвариант мы можем использовать его в определении интерфейсов::
+
+  >>> class IRange(zope.interface.Interface):
+  ...     min = zope.interface.Attribute("Lower bound")
+  ...     max = zope.interface.Attribute("Upper bound")
+  ...
+  ...     zope.interface.invariant(range_invariant)
+
+Интерфейсы имеют метод для проверки своих инвариантов::
+
+  >>> class Range(object):
+  ...     zope.interface.implements(IRange)
+  ...
+  ...     def __init__(self, min, max):
+  ...         self.min, self.max = min, max
+  ...
+  ...     def __repr__(self):
+  ...         return "Range(%s, %s)" % (self.min, self.max)
+
+  >>> IRange.validateInvariants(Range(1,2))
+  >>> IRange.validateInvariants(Range(1,1))
+  >>> IRange.validateInvariants(Range(2,1))
+  Traceback (most recent call last):
+  ...
+  RangeError: Range(2, 1)
+
+В случае нескольких инвариантов мы можем захотеть остановить проверку после
+первой ошибки. Если мы передадим в `validateInvariants` пустой список тогда
+будет выкинуто единственное исключение `Invalid` со списком исключений
+как аргументом::
+
+  >>> from zope.interface.exceptions import Invalid
+  >>> errors = []
+  >>> try:
+  ...     IRange.validateInvariants(Range(2,1), errors)
+  ... except Invalid, e:
+  ...     str(e)
+  '[RangeError(Range(2, 1))]'
+
+И список будет заполнен индивидуальными исключениями::
+
+  >>> errors
+  [RangeError(Range(2, 1))]
+
+  >>> del errors[:]
+
+Адаптация
+=========
+
+Интерфейсы могут быть вызваны для осуществления адаптации. Эта семантика
+основана на функции adapt из PEP 246. Если объект не может быть адаптирован
+будет выкинут TypeError::
+
+  >>> class I(zope.interface.Interface):
+  ...     pass
+
+  >>> I(0)
+  Traceback (most recent call last):
+  ...
+  TypeError: ('Could not adapt', 0, <InterfaceClass __main__.I>)
+
+только если альтернативное значение не передано как второй аргумент::
+
+  >>> I(0, 'bob')
+  'bob'
+
+Если объект уже реализует нужный интерфейс он будет возвращен::
+
+  >>> class C(object):
+  ...     zope.interface.implements(I)
+
+  >>> obj = C()
+  >>> I(obj) is obj
+  True
+
+Если объект реализует __conform__, тогда она будет использована::
+
+  >>> class C(object):
+  ...     zope.interface.implements(I)
+  ...     def __conform__(self, proto):
+  ...          return 0
+
+  >>> I(C())
+  0
+
+Также если присутствуют функции для вызова адаптации (см. __adapt__) они будут
+использованы::
+
+  >>> from zope.interface.interface import adapter_hooks
+  >>> def adapt_0_to_42(iface, obj):
+  ...     if obj == 0:
+  ...         return 42
+
+  >>> adapter_hooks.append(adapt_0_to_42)
+  >>> I(0)
+  42
+
+  >>> adapter_hooks.remove(adapt_0_to_42)
+  >>> I(0)
+  Traceback (most recent call last):
+  ...
+  TypeError: ('Could not adapt', 0, <InterfaceClass __main__.I>)
+
+
+__adapt__
+---------
+
+  >>> class I(zope.interface.Interface):
+  ...     pass
+
+Интерфейсы реализуют метод __adapt__ из PEP 246. Этот метод обычно не
+вызывается напрямую. Он вызывается архитектурой адаптации из PEP 246 и методом
+__call__ интерфейсов. Метод адаптации отвечает за адаптацию объекта к
+получателю. Версия по умолчанию возвращает None::
+
+  >>> I.__adapt__(0)
+
+если только переданный объект не предоставляет нужный интерфейс::
+
+  >>> class C(object):
+  ...     zope.interface.implements(I)
+
+  >>> obj = C()
+  >>> I.__adapt__(obj) is obj
+  True
+
+Функции для вызова адаптации могут быть добавлены (или удалены) для
+предоставления адаптации "на заказ". Мы установим глупую функцию которая
+адаптирует 0 к 42. Мы устанавливаем функцию просто добавляя ее к списку
+adapter_hooks::
+
+  >>> from zope.interface.interface import adapter_hooks
+  >>> def adapt_0_to_42(iface, obj):
+  ...     if obj == 0:
+  ...         return 42
+
+  >>> adapter_hooks.append(adapt_0_to_42)
+  >>> I.__adapt__(0)
+  42
+
+Функции должны возвращать либо адаптер, либо None если адаптер не найден.
+Функции могут быть удалены удалением их из списка::
+
+  >>> adapter_hooks.remove(adapt_0_to_42)
+  >>> I.__adapt__(0)
+
+
+.. [#create] Основная причина по которой мы наследуемся от `Interface` - это
+             что бы быть уверенными в том, что ключевое слово class будет
+             создавать интерфейс, а не класс.
+
+             Есть возможность создать интерфейсы вызвав специальный
+             класс интерфейса напрямую. Делая это, возможно (и в редких
+             случаях полезно) создать интерфейсы которые не наследуются
+             от `Interface`. Однако использование этой техники выходит
+	     за рамки данного документа.
+
+.. [#factory] Классы - это фабрики. Они могут быть вызваны для создания
+              своих экземпляров. Мы ожидаем что в итоге мы расширим
+              концепцию реализации на другие типы фабрик, таким образом
+              мы сможем объявлять интерфейсы предоставляемые созданными
+              фабриками объектами.
+
+.. [#compat] Цель - заменяемость. Объект который предоставляет расширенный
+             интерфейс должен быть заменяем в качестве объектов которые
+             предоставляют расширяемый интерфейс. В нашем примере объект
+             который предоставляет IBaz должен быть используемым и
+             в случае если ожидается объект который предоставляет IBlat.
+
+             Реализация интерфейса не требует этого. Но возможно в дальнейшем
+             она должна будет делать какие-либо проверки.

Copied: zope.interface/branches/tseaver-better_unittests/docs/adapter.rst (from rev 124741, zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.txt)
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/adapter.rst	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/adapter.rst	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,543 @@
+================
+Adapter Registry
+================
+
+Adapter registries provide a way to register objects that depend on
+one or more interface specifications and provide (perhaps indirectly)
+some interface.  In addition, the registrations have names. (You can
+think of the names as qualifiers of the provided interfaces.)
+
+The term "interface specification" refers both to interfaces and to
+interface declarations, such as declarations of interfaces implemented
+by a class.
+
+
+Single Adapters
+===============
+
+Let's look at a simple example, using a single required specification::
+
+  >>> from zope.interface.adapter import AdapterRegistry
+  >>> import zope.interface
+
+  >>> class IR1(zope.interface.Interface):
+  ...     pass
+  >>> class IP1(zope.interface.Interface):
+  ...     pass
+  >>> class IP2(IP1):
+  ...     pass
+
+  >>> registry = AdapterRegistry()
+
+We'll register an object that depends on IR1 and "provides" IP2::
+
+  >>> registry.register([IR1], IP2, '', 12)
+
+Given the registration, we can look it up again::
+
+  >>> registry.lookup([IR1], IP2, '')
+  12
+
+Note that we used an integer in the example.  In real applications,
+one would use some objects that actually depend on or provide
+interfaces. The registry doesn't care about what gets registered, so
+we'll use integers and strings to keep the examples simple. There is
+one exception.  Registering a value of None unregisters any
+previously-registered value.
+
+If an object depends on a specification, it can be looked up with a
+specification that extends the specification that it depends on::
+
+  >>> class IR2(IR1):
+  ...     pass
+  >>> registry.lookup([IR2], IP2, '')
+  12
+
+We can use a class implementation specification to look up the object::
+
+  >>> class C2:
+  ...     zope.interface.implements(IR2)
+
+  >>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
+  12
+
+
+and it can be looked up for interfaces that its provided interface
+extends::
+
+  >>> registry.lookup([IR1], IP1, '')
+  12
+  >>> registry.lookup([IR2], IP1, '')
+  12
+
+But if you require a specification that doesn't extend the specification the
+object depends on, you won't get anything::
+
+  >>> registry.lookup([zope.interface.Interface], IP1, '')
+
+By the way, you can pass a default value to lookup::
+
+  >>> registry.lookup([zope.interface.Interface], IP1, '', 42)
+  42
+
+If you try to get an interface the object doesn't provide, you also
+won't get anything::
+
+  >>> class IP3(IP2):
+  ...     pass
+  >>> registry.lookup([IR1], IP3, '')
+
+You also won't get anything if you use the wrong name::
+
+  >>> registry.lookup([IR1], IP1, 'bob')
+  >>> registry.register([IR1], IP2, 'bob', "Bob's 12")
+  >>> registry.lookup([IR1], IP1, 'bob')
+  "Bob's 12"
+
+You can leave the name off when doing a lookup::
+
+  >>> registry.lookup([IR1], IP1)
+  12
+
+If we register an object that provides IP1::
+
+  >>> registry.register([IR1], IP1, '', 11)
+
+then that object will be prefered over O(12)::
+
+  >>> registry.lookup([IR1], IP1, '')
+  11
+
+Also, if we register an object for IR2, then that will be prefered
+when using IR2::
+
+  >>> registry.register([IR2], IP1, '', 21)
+  >>> registry.lookup([IR2], IP1, '')
+  21
+
+Finding out what, if anything, is registered
+--------------------------------------------
+
+We can ask if there is an adapter registered for a collection of
+interfaces. This is different than lookup, because it looks for an
+exact match.
+
+  >>> print registry.registered([IR1], IP1)
+  11
+
+  >>> print registry.registered([IR1], IP2)
+  12
+
+  >>> print registry.registered([IR1], IP2, 'bob')
+  Bob's 12
+  
+
+  >>> print registry.registered([IR2], IP1)
+  21
+
+  >>> print registry.registered([IR2], IP2)
+  None
+
+In the last example, None was returned because nothing was registered
+exactly for the given interfaces.
+
+lookup1
+-------
+
+Lookup of single adapters is common enough that there is a specialized
+version of lookup that takes a single required interface::
+
+  >>> registry.lookup1(IR2, IP1, '')
+  21
+  >>> registry.lookup1(IR2, IP1)
+  21
+
+Actual Adaptation
+-----------------
+
+The adapter registry is intended to support adaptation, where one
+object that implements an interface is adapted to another object that
+supports a different interface.  The adapter registry supports the
+computation of adapters. In this case, we have to register adapter
+factories::
+
+   >>> class IR(zope.interface.Interface):
+   ...     pass
+
+   >>> class X:
+   ...     zope.interface.implements(IR)
+           
+   >>> class Y:
+   ...     zope.interface.implements(IP1)
+   ...     def __init__(self, context):
+   ...         self.context = context
+
+  >>> registry.register([IR], IP1, '', Y)
+
+In this case, we registered a class as the factory. Now we can call
+`queryAdapter` to get the adapted object::
+
+  >>> x = X()
+  >>> y = registry.queryAdapter(x, IP1)
+  >>> y.__class__.__name__
+  'Y'
+  >>> y.context is x
+  True
+
+We can register and lookup by name too::
+
+  >>> class Y2(Y):
+  ...     pass
+
+  >>> registry.register([IR], IP1, 'bob', Y2)
+  >>> y = registry.queryAdapter(x, IP1, 'bob')
+  >>> y.__class__.__name__
+  'Y2'
+  >>> y.context is x
+  True
+
+When the adapter factory produces `None`, then this is treated as if no
+adapter has been found. This allows us to prevent adaptation (when desired)
+and let the adapter factory determine whether adaptation is possible based on
+the state of the object being adapted.
+
+  >>> def factory(context):
+  ...     if context.name == 'object':
+  ...         return 'adapter'
+  ...     return None
+
+  >>> class Object(object):
+  ...     zope.interface.implements(IR)
+  ...     name = 'object'
+
+  >>> registry.register([IR], IP1, 'conditional', factory) 
+  >>> obj = Object()
+  >>> registry.queryAdapter(obj, IP1, 'conditional')
+  'adapter'
+  >>> obj.name = 'no object'
+  >>> registry.queryAdapter(obj, IP1, 'conditional') is None
+  True
+  >>> registry.queryAdapter(obj, IP1, 'conditional', 'default')
+  'default'
+
+An alternate method that provides the same function as `queryAdapter()` is
+`adapter_hook()`::
+
+  >>> y = registry.adapter_hook(IP1, x)
+  >>> y.__class__.__name__
+  'Y'
+  >>> y.context is x
+  True
+  >>> y = registry.adapter_hook(IP1, x, 'bob')
+  >>> y.__class__.__name__
+  'Y2'
+  >>> y.context is x
+  True
+
+The `adapter_hook()` simply switches the order of the object and
+interface arguments.  It is used to hook into the interface call
+mechanism.
+
+
+Default Adapters
+----------------
+  
+Sometimes, you want to provide an adapter that will adapt anything.
+For that, provide None as the required interface::
+
+  >>> registry.register([None], IP1, '', 1)
+  
+then we can use that adapter for interfaces we don't have specific
+adapters for::
+
+  >>> class IQ(zope.interface.Interface):
+  ...     pass
+  >>> registry.lookup([IQ], IP1, '')
+  1
+
+Of course, specific adapters are still used when applicable::
+
+  >>> registry.lookup([IR2], IP1, '')
+  21
+
+Class adapters
+--------------
+
+You can register adapters for class declarations, which is almost the
+same as registering them for a class::
+
+  >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
+  >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
+  'C21'
+
+Dict adapters
+-------------
+
+At some point it was impossible to register dictionary-based adapters due a
+bug. Let's make sure this works now:
+
+  >>> adapter = {}
+  >>> registry.register((), IQ, '', adapter)
+  >>> registry.lookup((), IQ, '') is adapter
+  True
+
+Unregistering
+-------------
+
+You can unregister by registering None, rather than an object::
+
+  >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
+  >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
+  21
+
+Of course, this means that None can't be registered. This is an
+exception to the statement, made earlier, that the registry doesn't
+care what gets registered.
+
+Multi-adapters
+==============
+
+You can adapt multiple specifications::
+
+  >>> registry.register([IR1, IQ], IP2, '', '1q2')
+  >>> registry.lookup([IR1, IQ], IP2, '')
+  '1q2'
+  >>> registry.lookup([IR2, IQ], IP1, '')
+  '1q2'
+
+  >>> class IS(zope.interface.Interface):
+  ...     pass
+  >>> registry.lookup([IR2, IS], IP1, '')
+
+  >>> class IQ2(IQ):
+  ...     pass
+
+  >>> registry.lookup([IR2, IQ2], IP1, '')
+  '1q2'
+
+  >>> registry.register([IR1, IQ2], IP2, '', '1q22')
+  >>> registry.lookup([IR2, IQ2], IP1, '')
+  '1q22'
+
+Multi-adaptation
+----------------
+
+You can adapt multiple objects::
+
+  >>> class Q:
+  ...     zope.interface.implements(IQ)
+
+As with single adapters, we register a factory, which is often a class::
+
+  >>> class IM(zope.interface.Interface):
+  ...     pass
+  >>> class M:
+  ...     zope.interface.implements(IM)
+  ...     def __init__(self, x, q):
+  ...         self.x, self.q = x, q
+  >>> registry.register([IR, IQ], IM, '', M)
+
+And then we can call `queryMultiAdapter` to compute an adapter::
+
+  >>> q = Q()
+  >>> m = registry.queryMultiAdapter((x, q), IM)
+  >>> m.__class__.__name__
+  'M'
+  >>> m.x is x and m.q is q
+  True
+
+and, of course, we can use names::
+
+  >>> class M2(M):
+  ...     pass
+  >>> registry.register([IR, IQ], IM, 'bob', M2)
+  >>> m = registry.queryMultiAdapter((x, q), IM, 'bob')
+  >>> m.__class__.__name__
+  'M2'
+  >>> m.x is x and m.q is q
+  True
+  
+Default Adapters
+----------------
+
+As with single adapters, you can define default adapters by specifying
+None for the *first* specification::
+
+  >>> registry.register([None, IQ], IP2, '', 'q2')
+  >>> registry.lookup([IS, IQ], IP2, '')
+  'q2'
+
+Null Adapters
+=============
+
+You can also adapt no specification::
+
+  >>> registry.register([], IP2, '', 2)
+  >>> registry.lookup([], IP2, '')
+  2
+  >>> registry.lookup([], IP1, '')
+  2
+
+Listing named adapters
+----------------------
+
+Adapters are named. Sometimes, it's useful to get all of the named
+adapters for given interfaces::
+
+  >>> adapters = list(registry.lookupAll([IR1], IP1))
+  >>> adapters.sort()
+  >>> assert adapters == [(u'', 11), (u'bob', "Bob's 12")]
+
+This works for multi-adapters too::
+
+  >>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
+  >>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
+  >>> adapters.sort()
+  >>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]
+
+And even null adapters::
+
+  >>> registry.register([], IP2, 'bob', 3)
+  >>> adapters = list(registry.lookupAll([], IP1))
+  >>> adapters.sort()
+  >>> assert adapters == [(u'', 2), (u'bob', 3)]
+
+Subscriptions
+=============
+
+Normally, we want to look up an object that most-closely matches a
+specification.  Sometimes, we want to get all of the objects that
+match some specification.  We use subscriptions for this.  We
+subscribe objects against specifications and then later find all of
+the subscribed objects::
+
+  >>> registry.subscribe([IR1], IP2, 'sub12 1')
+  >>> registry.subscriptions([IR1], IP2)
+  ['sub12 1']
+
+Note that, unlike regular adapters, subscriptions are unnamed.
+
+You can have multiple subscribers for the same specification::
+
+  >>> registry.subscribe([IR1], IP2, 'sub12 2')
+  >>> registry.subscriptions([IR1], IP2)
+  ['sub12 1', 'sub12 2']
+
+If subscribers are registered for the same required interfaces, they
+are returned in the order of definition.
+
+You can register subscribers for all specifications using None::
+
+  >>> registry.subscribe([None], IP1, 'sub_1')
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2']
+
+Note that the new subscriber is returned first.  Subscribers defined
+for less general required interfaces are returned before subscribers
+for more general interfaces.
+
+Subscriptions may be combined over multiple compatible specifications::
+
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2']
+  >>> registry.subscribe([IR1], IP1, 'sub11')
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2', 'sub11']
+  >>> registry.subscribe([IR2], IP2, 'sub22')
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2', 'sub11', 'sub22']
+  >>> registry.subscriptions([IR2], IP2)
+  ['sub12 1', 'sub12 2', 'sub22']
+
+Subscriptions can be on multiple specifications::
+
+  >>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
+  >>> registry.subscriptions([IR1, IQ], IP2)
+  ['sub1q2']
+  
+As with single subscriptions and non-subscription adapters, you can
+specify None for the first required interface, to specify a default::
+
+  >>> registry.subscribe([None, IQ], IP2, 'sub_q2')
+  >>> registry.subscriptions([IS, IQ], IP2)
+  ['sub_q2']
+  >>> registry.subscriptions([IR1, IQ], IP2)
+  ['sub_q2', 'sub1q2']
+
+You can have subscriptions that are indepenent of any specifications::
+  
+  >>> list(registry.subscriptions([], IP1))
+  []
+
+  >>> registry.subscribe([], IP2, 'sub2')
+  >>> registry.subscriptions([], IP1)
+  ['sub2']
+  >>> registry.subscribe([], IP1, 'sub1')
+  >>> registry.subscriptions([], IP1)
+  ['sub2', 'sub1']
+  >>> registry.subscriptions([], IP2)
+  ['sub2']
+
+Unregistering subscribers
+-------------------------
+
+We can unregister subscribers.  When unregistering a subscriber, we
+can unregister a specific subscriber::
+
+  >>> registry.unsubscribe([IR1], IP1, 'sub11')
+  >>> registry.subscriptions([IR1], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2']
+
+If we don't specify a value, then all subscribers matching the given
+interfaces will be unsubscribed:
+
+  >>> registry.unsubscribe([IR1], IP2)
+  >>> registry.subscriptions([IR1], IP1)
+  ['sub_1']
+
+
+Subscription adapters
+---------------------
+
+We normally register adapter factories, which then allow us to compute
+adapters, but with subscriptions, we get multiple adapters.  Here's an
+example of multiple-object subscribers::
+
+  >>> registry.subscribe([IR, IQ], IM, M)
+  >>> registry.subscribe([IR, IQ], IM, M2)
+
+  >>> subscribers = registry.subscribers((x, q), IM)
+  >>> len(subscribers)
+  2
+  >>> class_names = [s.__class__.__name__ for s in subscribers]
+  >>> class_names.sort()
+  >>> class_names
+  ['M', 'M2']
+  >>> [(s.x is x and s.q is q) for s in subscribers]
+  [True, True]
+
+adapter factory subcribers can't return None values::
+
+  >>> def M3(x, y):
+  ...     return None
+
+  >>> registry.subscribe([IR, IQ], IM, M3)
+  >>> subscribers = registry.subscribers((x, q), IM)
+  >>> len(subscribers)
+  2
+
+Handlers
+--------
+
+A handler is a subscriber factory that doesn't produce any normal
+output.  It returns None.  A handler is unlike adapters in that it does
+all of its work when the factory is called.
+
+To register a handler, simply provide None as the provided interface::
+
+  >>> def handler(event):
+  ...     print 'handler', event
+
+  >>> registry.subscribe([IR1], None, handler)
+  >>> registry.subscriptions([IR1], None) == [handler]
+  True

Copied: zope.interface/branches/tseaver-better_unittests/docs/adapter.ru.rst (from rev 124741, zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.ru.txt)
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/adapter.ru.rst	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/adapter.ru.rst	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,540 @@
+================
+Реестр адаптеров
+================
+
+.. contents::
+
+Реестры адаптеров предоставляют возможность для регистрации объектов которые
+зависят от одной, или нескольких спецификаций интерфейсов и предоставляют
+(возможно не напрямую) какой-либо интерфейс. В дополнение, регистрации имеют
+имена. (Можно думать об именах как о спецификаторах предоставляемого
+интерфейса.)
+
+Термин "спецификация интерфейса" ссылается и на интерфейсы и на определения
+интерфейсов, такие как определения интерфейсов реализованных некоторым классом.
+
+Одиночные адаптеры
+==================
+
+Давайте рассмотрим простой пример использующий единственную требуемую
+спецификацию::
+
+  >>> from zope.interface.adapter import AdapterRegistry
+  >>> import zope.interface
+
+  >>> class IR1(zope.interface.Interface):
+  ...     pass
+  >>> class IP1(zope.interface.Interface):
+  ...     pass
+  >>> class IP2(IP1):
+  ...     pass
+
+  >>> registry = AdapterRegistry()
+
+Мы зарегистрируем объект который зависит от IR1 и "предоставляет" IP2::
+
+  >>> registry.register([IR1], IP2, '', 12)
+
+После регистрации мы можем запросить объект снова::
+
+  >>> registry.lookup([IR1], IP2, '')
+  12
+
+Заметьте, что мы используем целое в этом примере. В реальных приложениях вы
+можете использовать объекты которые на самом деле зависят или предоставляют
+интерфейсы. Реестр не заботиться о том, что регистрируется и таким образом мы
+можем использовать целые, или строки что бы упростить наши примеры. Здесь есть
+одно исключение. Регистрация значения None удаляет регистрацию для любого
+зарегистрированного прежде значения.
+
+Если объект зависит от спецификации он может быть запрошен с помощью
+спецификации которая расширяет спецификацию от которой он зависит::
+
+  >>> class IR2(IR1):
+  ...     pass
+  >>> registry.lookup([IR2], IP2, '')
+  12
+
+Мы можем использовать класс реализующий спецификацию для запроса объекта::
+
+  >>> class C2:
+  ...     zope.interface.implements(IR2)
+
+  >>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
+  12
+
+и объект может быть запрошен для интерфейсов которые предоставляемый объектом
+интерфейс расширяет::
+
+  >>> registry.lookup([IR1], IP1, '')
+  12
+  >>> registry.lookup([IR2], IP1, '')
+  12
+
+Но если вы требуете спецификацию которая не расширяет спецификацию от которой
+зависит объект, вы не получите ничего::
+
+  >>> registry.lookup([zope.interface.Interface], IP1, '')
+
+Между прочим, вы можете передать значение по умолчанию при запросе::
+
+  >>> registry.lookup([zope.interface.Interface], IP1, '', 42)
+  42
+
+Если вы пробуете получить интерфейс который объект не предоставляет вы также
+не получите ничего::
+
+  >>> class IP3(IP2):
+  ...     pass
+  >>> registry.lookup([IR1], IP3, '')
+
+Вы также не получите ничего если вы используете неверное имя::
+
+  >>> registry.lookup([IR1], IP1, 'bob')
+  >>> registry.register([IR1], IP2, 'bob', "Bob's 12")
+  >>> registry.lookup([IR1], IP1, 'bob')
+  "Bob's 12"
+
+Вы можете не использовать имя при запросе::
+
+  >>> registry.lookup([IR1], IP1)
+  12
+
+Если мы регистрируем объект который предоставляет IP1::
+
+  >>> registry.register([IR1], IP1, '', 11)
+
+тогда этот объект будет иметь преимущество перед O(12)::
+
+  >>> registry.lookup([IR1], IP1, '')
+  11
+
+Также, если мы регистрируем объект для IR2 тогда он будет иметь преимущество
+когда используется IR2::
+
+  >>> registry.register([IR2], IP1, '', 21)
+  >>> registry.lookup([IR2], IP1, '')
+  21
+
+Поиск того, что (если вообще что-то) зарегистрировано
+-----------------------------------------------------
+
+Мы можем спросить есть-ли адаптер зарегистрированный для набора интерфейсов.
+Это отличается от обычного запроса так как здесь мы ищем точное совпадение::
+
+  >>> print registry.registered([IR1], IP1)
+  11
+
+  >>> print registry.registered([IR1], IP2)
+  12
+
+  >>> print registry.registered([IR1], IP2, 'bob')
+  Bob's 12
+  
+
+  >>> print registry.registered([IR2], IP1)
+  21
+
+  >>> print registry.registered([IR2], IP2)
+  None
+
+В последнем примере, None был возвращен потому, что для данного интерфейса
+ничего не было зарегистрировано.
+
+lookup1
+-------
+
+Запрос одиночного адаптера - это наиболее частая операция и для нее есть
+специализированная версия запроса которая получает на вход единственный
+требуемый интерфейс::
+
+  >>> registry.lookup1(IR2, IP1, '')
+  21
+  >>> registry.lookup1(IR2, IP1)
+  21
+
+Адаптация на практике
+---------------------
+
+Реестр адаптеров предназначен для поддержки адаптации когда один объект
+реализующий интерфейс адаптируется к другому объекту который поддерживает
+другой интерфейс. Реестр адаптеров также поддерживает вычисление адаптеров. В
+этом случае мы должны регистрировать фабрики для адаптеров::
+
+   >>> class IR(zope.interface.Interface):
+   ...     pass
+
+   >>> class X:
+   ...     zope.interface.implements(IR)
+           
+   >>> class Y:
+   ...     zope.interface.implements(IP1)
+   ...     def __init__(self, context):
+   ...         self.context = context
+
+  >>> registry.register([IR], IP1, '', Y)
+
+В этом случае мы регистрируем класс как фабрику. Теперь мы можем вызвать
+`queryAdapter` для получения адаптированного объекта::
+
+  >>> x = X()
+  >>> y = registry.queryAdapter(x, IP1)
+  >>> y.__class__.__name__
+  'Y'
+  >>> y.context is x
+  True
+
+Мы также можем регистрировать и запрашивать по имени::
+
+  >>> class Y2(Y):
+  ...     pass
+
+  >>> registry.register([IR], IP1, 'bob', Y2)
+  >>> y = registry.queryAdapter(x, IP1, 'bob')
+  >>> y.__class__.__name__
+  'Y2'
+  >>> y.context is x
+  True
+
+Когда фабрика для адаптера возвращает `None` - это рассматривается как если бы
+адаптер не был найден. Это позволяет нам избежать адаптации (по желанию) и дает
+возможность фабрике адаптера определить возможна ли адаптация основываясь на
+состоянии объекта который адаптируется::
+
+  >>> def factory(context):
+  ...     if context.name == 'object':
+  ...         return 'adapter'
+  ...     return None
+
+  >>> class Object(object):
+  ...     zope.interface.implements(IR)
+  ...     name = 'object'
+
+  >>> registry.register([IR], IP1, 'conditional', factory) 
+  >>> obj = Object()
+  >>> registry.queryAdapter(obj, IP1, 'conditional')
+  'adapter'
+  >>> obj.name = 'no object'
+  >>> registry.queryAdapter(obj, IP1, 'conditional') is None
+  True
+  >>> registry.queryAdapter(obj, IP1, 'conditional', 'default')
+  'default'
+
+Альтернативный метод для предоставления такой же функциональности как и
+`queryAdapter()` - это `adapter_hook()`::
+
+  >>> y = registry.adapter_hook(IP1, x)
+  >>> y.__class__.__name__
+  'Y'
+  >>> y.context is x
+  True
+  >>> y = registry.adapter_hook(IP1, x, 'bob')
+  >>> y.__class__.__name__
+  'Y2'
+  >>> y.context is x
+  True
+
+`adapter_hook()` просто меняет порядок аргументов для объекта и интерфейса. Это
+используется для встраивания в механизм вызовов интерфейсов.
+
+Адаптеры по умолчанию
+---------------------
+
+Иногда вы можете захотеть предоставить адаптер который не будет ничего
+адаптировать. Для этого нужно передать None как требуемый интерфейс::
+
+  >>> registry.register([None], IP1, '', 1)
+
+после этого вы можете использовать этот адаптер для интерфейсов для которых у
+вас нет конкретного адаптера::
+
+  >>> class IQ(zope.interface.Interface):
+  ...     pass
+  >>> registry.lookup([IQ], IP1, '')
+  1
+
+Конечно, конкретные адаптеры все еще используются когда необходимо::
+
+  >>> registry.lookup([IR2], IP1, '')
+  21
+
+Адаптеры классов
+----------------
+
+Вы можете регистрировать адаптеры для определений классов, что будет похоже на
+регистрацию их для классов::
+
+  >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
+  >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
+  'C21'
+
+Адаптеры для словарей
+---------------------
+
+В какой-то момент было невозможно регистрировать адаптеры основанные на
+словарях из-за ошибки. Давайте удостоверимся что это теперь работает::
+
+  >>> adapter = {}
+  >>> registry.register((), IQ, '', adapter)
+  >>> registry.lookup((), IQ, '') is adapter
+  True
+
+Удаление регистрации
+--------------------
+
+Вы можете удалить регистрацию регистрируя None вместо объекта::
+
+  >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
+  >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
+  21
+
+Конечно это значит, что None не может быть зарегистрирован. Это исключение к
+утверждению выше о том, что реестр не заботиться о том, что регистрируется.
+
+Мульти-адаптеры
+===============
+
+Вы можете адаптировать несколько спецификаций::
+
+  >>> registry.register([IR1, IQ], IP2, '', '1q2')
+  >>> registry.lookup([IR1, IQ], IP2, '')
+  '1q2'
+  >>> registry.lookup([IR2, IQ], IP1, '')
+  '1q2'
+
+  >>> class IS(zope.interface.Interface):
+  ...     pass
+  >>> registry.lookup([IR2, IS], IP1, '')
+
+  >>> class IQ2(IQ):
+  ...     pass
+
+  >>> registry.lookup([IR2, IQ2], IP1, '')
+  '1q2'
+
+  >>> registry.register([IR1, IQ2], IP2, '', '1q22')
+  >>> registry.lookup([IR2, IQ2], IP1, '')
+  '1q22'
+
+Мульти-адаптация
+----------------
+
+Вы можете адаптировать несколько объектов::
+
+  >>> class Q:
+  ...     zope.interface.implements(IQ)
+
+Как и с одиночными адаптерами, мы регистрируем фабрику которая возвращает
+класс::
+
+  >>> class IM(zope.interface.Interface):
+  ...     pass
+  >>> class M:
+  ...     zope.interface.implements(IM)
+  ...     def __init__(self, x, q):
+  ...         self.x, self.q = x, q
+  >>> registry.register([IR, IQ], IM, '', M)
+
+И затем мы можем вызвать `queryMultiAdapter` для вычисления адаптера::
+
+  >>> q = Q()
+  >>> m = registry.queryMultiAdapter((x, q), IM)
+  >>> m.__class__.__name__
+  'M'
+  >>> m.x is x and m.q is q
+  True
+
+и, конечно, мы можем использовать имена::
+
+  >>> class M2(M):
+  ...     pass
+  >>> registry.register([IR, IQ], IM, 'bob', M2)
+  >>> m = registry.queryMultiAdapter((x, q), IM, 'bob')
+  >>> m.__class__.__name__
+  'M2'
+  >>> m.x is x and m.q is q
+  True
+
+Адаптеры по умолчанию
+---------------------
+
+Как и для одиночных адаптеров вы можете определить адаптер по умолчанию передав
+None вместо *первой* спецификации::
+
+  >>> registry.register([None, IQ], IP2, '', 'q2')
+  >>> registry.lookup([IS, IQ], IP2, '')
+  'q2'
+
+Нулевые адаптеры
+================
+
+Вы можете также адаптировать без спецификации::
+
+  >>> registry.register([], IP2, '', 2)
+  >>> registry.lookup([], IP2, '')
+  2
+  >>> registry.lookup([], IP1, '')
+  2
+
+Перечисление именованных адаптеров
+----------------------------------
+
+Адаптеры имеют имена. Иногда это полезно для получения всех именованных
+адаптеров для заданного интерфейса::
+
+  >>> adapters = list(registry.lookupAll([IR1], IP1))
+  >>> adapters.sort()
+  >>> assert adapters == [(u'', 11), (u'bob', "Bob's 12")]
+
+Это работает также и для мульти-адаптеров::
+
+  >>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
+  >>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
+  >>> adapters.sort()
+  >>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]
+
+И даже для нулевых адаптеров::
+
+  >>> registry.register([], IP2, 'bob', 3)
+  >>> adapters = list(registry.lookupAll([], IP1))
+  >>> adapters.sort()
+  >>> assert adapters == [(u'', 2), (u'bob', 3)]
+
+Подписки
+========
+
+Обычно мы хотим запросить объект который наиболее близко соответствует
+спецификации. Иногда мы хотим получить все объекты которые соответствуют
+какой-либо спецификации. Мы используем подписки для этого. Мы подписываем
+объекты для спецификаций и затем позже находим все подписанные объекты::
+
+  >>> registry.subscribe([IR1], IP2, 'sub12 1')
+  >>> registry.subscriptions([IR1], IP2)
+  ['sub12 1']
+
+Заметьте, что в отличие от обычных адаптеров подписки не имеют имен.
+
+Вы можете иметь несколько подписчиков для одной спецификации::
+
+  >>> registry.subscribe([IR1], IP2, 'sub12 2')
+  >>> registry.subscriptions([IR1], IP2)
+  ['sub12 1', 'sub12 2']
+
+Если подписчики зарегистрированы для одних и тех же требуемых интерфейсов, они
+возвращаются в порядке определения.
+
+Вы можете зарегистрировать подписчики для всех спецификаций используя None::
+
+  >>> registry.subscribe([None], IP1, 'sub_1')
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2']
+
+Заметьте, что новый подписчик возвращается первым. Подписчики определенные
+для менее общих требуемых интерфейсов возвращаются перед подписчиками
+для более общих интерфейсов.
+
+Подписки могут смешиваться между несколькими совместимыми спецификациями::
+
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2']
+  >>> registry.subscribe([IR1], IP1, 'sub11')
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2', 'sub11']
+  >>> registry.subscribe([IR2], IP2, 'sub22')
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2', 'sub11', 'sub22']
+  >>> registry.subscriptions([IR2], IP2)
+  ['sub12 1', 'sub12 2', 'sub22']
+
+Подписки могут существовать для нескольких спецификаций::
+
+  >>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
+  >>> registry.subscriptions([IR1, IQ], IP2)
+  ['sub1q2']
+
+Как и с одиночными подписчиками и адаптерами без подписок, вы можете определить
+None для первого требуемого интерфейса, что бы задать значение по умолчанию::
+
+  >>> registry.subscribe([None, IQ], IP2, 'sub_q2')
+  >>> registry.subscriptions([IS, IQ], IP2)
+  ['sub_q2']
+  >>> registry.subscriptions([IR1, IQ], IP2)
+  ['sub_q2', 'sub1q2']
+
+Вы можете создать подписки которые независимы от любых спецификаций::
+
+  >>> list(registry.subscriptions([], IP1))
+  []
+
+  >>> registry.subscribe([], IP2, 'sub2')
+  >>> registry.subscriptions([], IP1)
+  ['sub2']
+  >>> registry.subscribe([], IP1, 'sub1')
+  >>> registry.subscriptions([], IP1)
+  ['sub2', 'sub1']
+  >>> registry.subscriptions([], IP2)
+  ['sub2']
+
+Удаление регистрации подписчиков
+--------------------------------
+
+Мы можем удалять регистрацию подписчиков. При удалении регистрации подписчика
+мы можем удалить регистрацию заданного адаптера::
+
+  >>> registry.unsubscribe([IR1], IP1, 'sub11')
+  >>> registry.subscriptions([IR1], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2']
+
+Если мы не задаем никакого значения тогда подписки будут удалены для всех
+подписчиков совпадающих с заданным интерфейсом::
+
+  >>> registry.unsubscribe([IR1], IP2)
+  >>> registry.subscriptions([IR1], IP1)
+  ['sub_1']
+
+Адаптеры подписки
+-----------------
+
+Обычно мы регистрируем фабрики для адаптеров которые затем позволяют нам
+вычислять адаптеры, но с подписками мы получаем несколько адаптеров. Это пример
+подписчика для нескольких объектов::
+
+  >>> registry.subscribe([IR, IQ], IM, M)
+  >>> registry.subscribe([IR, IQ], IM, M2)
+
+  >>> subscribers = registry.subscribers((x, q), IM)
+  >>> len(subscribers)
+  2
+  >>> class_names = [s.__class__.__name__ for s in subscribers]
+  >>> class_names.sort()
+  >>> class_names
+  ['M', 'M2']
+  >>> [(s.x is x and s.q is q) for s in subscribers]
+  [True, True]
+
+подписчики фабрик адаптеров не могут возвращать None::
+
+  >>> def M3(x, y):
+  ...     return None
+
+  >>> registry.subscribe([IR, IQ], IM, M3)
+  >>> subscribers = registry.subscribers((x, q), IM)
+  >>> len(subscribers)
+  2
+
+Обработчики
+-----------
+
+Обработчик - это подписанная фабрика которая не возвращает нормального
+значения. Она возвращает None. Обработчик отличается от адаптеров тем, что он
+делает всю работу когда вызывается фабрика.
+
+Для регистрации обработчика надо просто передать None как предоставляемый
+интерфейс::
+
+  >>> def handler(event):
+  ...     print 'handler', event
+
+  >>> registry.subscribe([IR1], None, handler)
+  >>> registry.subscriptions([IR1], None) == [handler]
+  True

Added: zope.interface/branches/tseaver-better_unittests/docs/conf.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/conf.py	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/conf.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,246 @@
+# -*- coding: utf-8 -*-
+#
+# zope.interface documentation build configuration file, created by
+# sphinx-quickstart on Mon Mar 26 16:31:31 2012.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'zope.interface'
+copyright = u'2012, Zope Foundation contributors'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '3.8'
+# The full version, including alpha/beta/rc tags.
+release = '3.8.1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'zopeinterfacedoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'zopeinterface.tex', u'zope.interface Documentation',
+   u'Zope Foundation contributors', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'zopeinterface', u'zope.interface Documentation',
+     [u'Zope Foundation contributors'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'zopeinterface', u'zope.interface Documentation',
+   u'Zope Foundation contributors', 'zopeinterface', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/': None}

Copied: zope.interface/branches/tseaver-better_unittests/docs/foodforthought.rst (from rev 124741, zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/foodforthought.txt)
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/foodforthought.rst	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/foodforthought.rst	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,61 @@
+================================
+Food-based subscription examples
+================================
+
+
+This file gives more subscription examples using a cooking-based example::
+
+    >>> from zope.interface.adapter import AdapterRegistry
+    >>> registry = AdapterRegistry()
+
+    >>> import zope.interface
+    >>> class IAnimal(zope.interface.Interface):
+    ...     pass
+    >>> class IPoultry(IAnimal):
+    ...     pass
+    >>> class IChicken(IPoultry):
+    ...     pass
+    >>> class ISeafood(IAnimal):
+    ...     pass
+
+Adapting to some other interface for which there is no
+subscription adapter returns an empty sequence::
+
+    >>> class IRecipe(zope.interface.Interface):
+    ...     pass
+    >>> class ISausages(IRecipe):
+    ...     pass
+    >>> class INoodles(IRecipe):
+    ...     pass
+    >>> class IKFC(IRecipe):
+    ...     pass
+
+    >>> list(registry.subscriptions([IPoultry], IRecipe))
+    []
+
+unless we define a subscription::
+
+    >>> registry.subscribe([IAnimal], ISausages, 'sausages')
+    >>> list(registry.subscriptions([IPoultry], ISausages))
+    ['sausages']
+
+And define another subscription adapter::
+
+    >>> registry.subscribe([IPoultry], INoodles, 'noodles')
+    >>> meals = list(registry.subscriptions([IPoultry], IRecipe))
+    >>> meals.sort()
+    >>> meals
+    ['noodles', 'sausages']
+
+    >>> registry.subscribe([IChicken], IKFC, 'kfc')
+    >>> meals = list(registry.subscriptions([IChicken], IRecipe))
+    >>> meals.sort()
+    >>> meals
+    ['kfc', 'noodles', 'sausages']
+
+And the answer for poultry hasn't changed::
+
+    >>> meals = list(registry.subscriptions([IPoultry], IRecipe))
+    >>> meals.sort()
+    >>> meals
+    ['noodles', 'sausages']

Copied: zope.interface/branches/tseaver-better_unittests/docs/human.rst (from rev 124741, zope.interface/branches/tseaver-better_unittests/src/zope/interface/human.txt)
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/human.rst	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/human.rst	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,152 @@
+==========================
+Using the Adapter Registry
+==========================
+
+This is a small demonstration of the ``zope.interface`` package including its
+adapter registry. It is intended to provide a concrete but narrow example on
+how to use interfaces and adapters outside of Zope 3.
+
+First we have to import the interface package::
+
+  >>> import zope.interface
+
+We now develop an interface for our object, which is a simple file in this
+case. For now we simply support one attribute, the body, which contains the
+actual file contents::
+
+  >>> class IFile(zope.interface.Interface):
+  ...
+  ...     body = zope.interface.Attribute('Contents of the file.')
+  ...
+
+For statistical reasons we often want to know the size of a file. However, it
+would be clumsy to implement the size directly in the file object, since the
+size really represents meta-data. Thus we create another interface that
+provides the size of something::
+
+  >>> class ISize(zope.interface.Interface):
+  ...
+  ...     def getSize():
+  ...         'Return the size of an object.'
+  ...
+
+Now we need to implement the file. It is essential that the object states
+that it implements the `IFile` interface. We also provide a default body
+value (just to make things simpler for this example)::
+
+  >>> class File(object):
+  ...
+  ...      zope.interface.implements(IFile)
+  ...      body = 'foo bar'
+  ...
+
+Next we implement an adapter that can provide the `ISize` interface given any
+object providing `IFile`. By convention we use `__used_for__` to specify the
+interface that we expect the adapted object to provide, in our case
+`IFile`. However, this attribute is not used for anything. If you have
+multiple interfaces for which an adapter is used, just specify the interfaces
+via a tuple.
+
+Again by convention, the constructor of an adapter takes one argument, the
+context. The context in this case is an instance of `File` (providing `IFile`)
+that is used to extract the size from. Also by convention the context is
+stored in an attribute named `context` on the adapter. The twisted community
+refers to the context as the `original` object. However, you may feel free to
+use a specific argument name, such as `file`::
+
+  >>> class FileSize(object):
+  ...
+  ...      zope.interface.implements(ISize)
+  ...      __used_for__ = IFile
+  ...
+  ...      def __init__(self, context):
+  ...          self.context = context
+  ...
+  ...      def getSize(self):
+  ...          return len(self.context.body)
+  ...
+
+Now that we have written our adapter, we have to register it with an adapter
+registry, so that it can be looked up when needed. There is no such thing as a
+global registry; thus we have to instantiate one for our example manually::
+
+  >>> from zope.interface.adapter import AdapterRegistry
+  >>> registry = AdapterRegistry()
+
+
+The registry keeps a map of what adapters implement based on another
+interface, the object already provides. Therefore, we next have to register an
+adapter that adapts from `IFile` to `ISize`. The first argument to
+the registry's `register()` method is a list of original interfaces.In our
+cause we have only one original interface, `IFile`. A list makes sense, since
+the interface package has the concept of multi-adapters, which are adapters
+that require multiple objects to adapt to a new interface. In these
+situations, your adapter constructor will require an argument for each
+specified interface.
+
+The second argument is the interface the adapter provides, in our case
+`ISize`. The third argument is the name of the adapter. Since we do not care
+about names, we simply leave it as an empty string. Names are commonly useful,
+if you have adapters for the same set of interfaces, but they are useful in
+different situations. The last argument is simply the adapter class::
+
+  >>> registry.register([IFile], ISize, '', FileSize)
+
+You can now use the the registry to lookup the adapter::
+
+  >>> registry.lookup1(IFile, ISize, '')
+  <class '__main__.FileSize'>
+
+Let's get a little bit more practical. Let's create a `File` instance and
+create the adapter using a registry lookup. Then we see whether the adapter
+returns the correct size by calling `getSize()`::
+
+  >>> file = File()
+  >>> size = registry.lookup1(IFile, ISize, '')(file)
+  >>> size.getSize()
+  7
+
+However, this is not very practical, since I have to manually pass in the
+arguments to the lookup method. There is some syntactic candy that will allow
+us to get an adapter instance by simply calling `ISize(file)`. To make use of
+this functionality, we need to add our registry to the adapter_hooks list,
+which is a member of the adapters module. This list stores a collection of
+callables that are automatically invoked when IFoo(obj) is called; their
+purpose is to locate adapters that implement an interface for a certain
+context instance.
+
+You are required to implement your own adapter hook; this example covers one
+of the simplest hooks that use the registry, but you could implement one that
+used an adapter cache or persistent adapters, for instance. The helper hook is
+required to expect as first argument the desired output interface (for us
+`ISize`) and as the second argument the context of the adapter (here
+`file`). The function returns an adapter, i.e. a `FileSize` instance::
+
+  >>> def hook(provided, object):
+  ...     adapter = registry.lookup1(zope.interface.providedBy(object),
+  ...                                provided, '')
+  ...     return adapter(object)
+  ...
+
+We now just add the hook to an `adapter_hooks` list::
+
+  >>> from zope.interface.interface import adapter_hooks
+  >>> adapter_hooks.append(hook)
+
+Once the hook is registered, you can use the desired syntax::
+
+  >>> size = ISize(file)
+  >>> size.getSize()
+  7
+
+Now we have to cleanup after ourselves, so that others after us have a clean
+`adapter_hooks` list::
+
+  >>> adapter_hooks.remove(hook)
+
+That's it. I have intentionally left out a discussion of named adapters and
+multi-adapters, since this text is intended as a practical and simple
+introduction to Zope 3 interfaces and adapters. You might want to read the
+`adapter.txt` in the `zope.interface` package for a more formal, referencial
+and complete treatment of the package. Warning: People have reported that
+`adapter.txt` makes their brain feel soft!

Copied: zope.interface/branches/tseaver-better_unittests/docs/human.ru.rst (from rev 124741, zope.interface/branches/tseaver-better_unittests/src/zope/interface/human.ru.txt)
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/human.ru.rst	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/human.ru.rst	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,156 @@
+===============================
+Использование реестра адаптеров
+===============================
+
+Данный документ содержит небольшую демонстрацию пакета ``zope.interface`` и его
+реестра адаптеров. Документ рассчитывался как конкретный, но более узкий пример
+того как использовать интерфейсы и адаптеры вне Zope 3.
+
+Сначала нам необходимо импортировать пакет для работы с интерфейсами::
+
+  >>> import zope.interface
+
+Теперь мы разработаем интерфейс для нашего объекта - простого файла. Наш файл
+будет содержать всего один атрибут - body, в котором фактически будет сохранено
+содержимое файла::
+
+  >>> class IFile(zope.interface.Interface):
+  ...
+  ...     body = zope.interface.Attribute(u'Содержимое файла.')
+  ...
+
+Для статистики нам часто необходимо знать размер файла. Но было бы несколько
+топорно реализовывать определение размера прямо для объекта файла, т.к. размер
+больше относится к мета-данным. Таким образом мы создаем еще один интерфейс для
+представления размера какого-либо объекта::
+
+  >>> class ISize(zope.interface.Interface):
+  ...
+  ...     def getSize():
+  ...         'Return the size of an object.'
+  ...
+
+Теперь мы должны создать класс реализующий наш файл. Необходимо что бы наш
+объект хранил информацию о том, что он реализует интерфейс `IFile`. Мы также
+создаем атрибут с содержимым файла по умолчанию (для упрощения нашего
+примера)::
+
+  >>> class File(object):
+  ...
+  ...      zope.interface.implements(IFile)
+  ...      body = 'foo bar'
+  ...
+
+Дальше мы создаем адаптер, который будет предоставлять интерфейс `ISize`
+получая любой объект предоставляющий интерфейс `IFile`. По соглашению мы
+используем атрибут `__used_for__` для указания интерфейса который как мы
+ожидаем предоставляет адаптируемый объект, `IFile` в нашем случае. На самом
+деле этот атрибут используется только для документирования. В случае если
+адаптер используется для нескольких интерфейсов можно указать их все в виде
+кортежа.
+
+Опять же по соглашению конструктор адаптера получает один аргумент - context
+(контекст). В нашем случае контекст - это экземпляр `IFile` (объект,
+предоставляющий `IFile`) который используется для получения из него размера.
+Так же по соглашению контекст сохраняется а адаптере в атрибуте с именем
+`context`. Twisted комьюнити ссылается на контекст как на объект `original`.
+Таким образом можно также дать аргументу любое подходящее имя, например
+`file`::
+
+  >>> class FileSize(object):
+  ...
+  ...      zope.interface.implements(ISize)
+  ...      __used_for__ = IFile
+  ...
+  ...      def __init__(self, context):
+  ...          self.context = context
+  ...
+  ...      def getSize(self):
+  ...          return len(self.context.body)
+  ...
+
+Теперь когда мы написали наш адаптер мы должны зарегистрировать его в реестре
+адаптеров, что бы его можно было запросить когда он понадобится. Здесь нет
+какого-либо глобального реестра адаптеров, таким образом мы должны
+самостоятельно создать для нашего примера реестр::
+
+  >>> from zope.interface.adapter import AdapterRegistry
+  >>> registry = AdapterRegistry()
+
+Реестр содержит отображение того, что адаптер реализует на основе другого
+интерфейса который предоставляет объект. Поэтому дальше мы регистрируем адаптер
+который адаптирует интерфейс `IFile` к интерфейсу `ISize`. Первый аргумент к
+методу `register()` реестра - это список адаптируемых интерфейсов. В нашем
+случае мы имеем только один адаптируемый интерфейс - `IFile`. Список
+интерфейсов имеет смысл для использования концепции мульти-адаптеров, которые
+требуют нескольких оригинальных объектов для адаптации к новому интерфейсу. В
+этой ситуации конструктор адаптера будет требовать новый аргумент для каждого
+оригинального интерфейса.
+
+Второй аргумент метода `register()` - это интерфейс который предоставляет
+адаптер, в нашем случае `ISize`. Третий аргумент - имя адаптера. Сейчас нам не
+важно имя адаптера и мы передаем его как пустую строку. Обычно имена полезны
+если используются адаптеры для одинакового набора интерфейсов, но в различных
+ситуациях. Последний аргумент - это класс адаптера::
+
+  >>> registry.register([IFile], ISize, '', FileSize)
+
+Теперь мы можем использовать реестр для запроса адаптера::
+
+  >>> registry.lookup1(IFile, ISize, '')
+  <class '__main__.FileSize'>
+
+Попробуем более практичный пример. Создадим экземпляр `File` и создадим адаптер
+использующий запрос реестра. Затем мы увидим возвращает ли адаптер корректный
+размер при вызове `getSize()`::
+
+  >>> file = File()
+  >>> size = registry.lookup1(IFile, ISize, '')(file)
+  >>> size.getSize()
+  7
+
+На самом деле это не очень практично, т.к. нам нужно самим передавать все
+аргументы методу запроса. Существует некоторый синтаксический леденец который
+позволяет нам получить экземпляр адаптера просто вызвав `ISize(file)`. Что бы
+использовать эту функциональность нам понадобится добавить наш реестр к списку
+adapter_hooks, который находится в модуле с адаптерами. Этот список хранит
+коллекцию вызываемых объектов которые вызываются автоматически когда вызывается
+IFoo(obj); их предназначение - найти адаптеры которые реализуют интерфейс для
+определенного экземпляра контекста.
+
+Необходимо реализовать свою собственную функцию для поиска адаптера; данный
+пример описывает одну из простейших функций для использования с реестром, но
+также можно реализовать поисковые функции которые, например, используют
+кэширование, или адаптеры сохраняемые в базе. Функция поиска должна принимать
+желаемый на выходе интерфейс (в нашем случае `ISize`) как первый аргумент и
+контекст для адаптации (`file`) как второй. Функция должна вернуть адаптер,
+т.е. экземпляр `FileSize`::
+
+  >>> def hook(provided, object):
+  ...     adapter = registry.lookup1(zope.interface.providedBy(object),
+  ...                                provided, '')
+  ...     return adapter(object)
+  ...
+
+Теперь мы просто добавляем нашу функцию к списку `adapter_hooks`::
+
+  >>> from zope.interface.interface import adapter_hooks
+  >>> adapter_hooks.append(hook)
+
+Как только функция зарегистрирована мы можем использовать желаемый синтаксис::
+
+  >>> size = ISize(file)
+  >>> size.getSize()
+  7
+
+После нам нужно прибраться за собой, что бы другие получили чистый список
+`adaper_hooks` после нас::
+
+  >>> adapter_hooks.remove(hook)
+
+Это все. Здесь намеренно отложена дискуссия об именованных и мульти-адаптерах,
+т.к. данный текст рассчитан как практическое и простое введение в интерфейсы и
+адаптеры Zope 3. Для более подробной информации имеет смысл прочитать
+`adapter.txt` из пакета `zope.interface`, что бы получить более формальное,
+справочное и полное трактование пакета. Внимание: многие жаловались, что
+`adapter.txt` приводит их мозг к расплавленному состоянию!

Added: zope.interface/branches/tseaver-better_unittests/docs/index.rst
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/index.rst	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/index.rst	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,38 @@
+.. zope.interface documentation master file, created by
+   sphinx-quickstart on Mon Mar 26 16:31:31 2012.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Welcome to zope.interface's documentation!
+==========================================
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+   README
+   adapter
+   human
+   verify
+   foodforthought
+
+По-русски
+=========
+
+.. toctree::
+   :maxdepth: 2
+
+   README.ru
+   adapter.ru
+   human.ru
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+

Added: zope.interface/branches/tseaver-better_unittests/docs/make.bat
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/make.bat	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/make.bat	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,190 @@
+ at ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html       to make standalone HTML files
+	echo.  dirhtml    to make HTML files named index.html in directories
+	echo.  singlehtml to make a single large HTML file
+	echo.  pickle     to make pickle files
+	echo.  json       to make JSON files
+	echo.  htmlhelp   to make HTML files and a HTML help project
+	echo.  qthelp     to make HTML files and a qthelp project
+	echo.  devhelp    to make HTML files and a Devhelp project
+	echo.  epub       to make an epub
+	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  text       to make text files
+	echo.  man        to make manual pages
+	echo.  texinfo    to make Texinfo files
+	echo.  gettext    to make PO message catalogs
+	echo.  changes    to make an overview over all changed/added/deprecated items
+	echo.  linkcheck  to check all external links for integrity
+	echo.  doctest    to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "singlehtml" (
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\zopeinterface.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\zopeinterface.ghc
+	goto end
+)
+
+if "%1" == "devhelp" (
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished.
+	goto end
+)
+
+if "%1" == "epub" (
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "text" (
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The text files are in %BUILDDIR%/text.
+	goto end
+)
+
+if "%1" == "man" (
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
+	goto end
+)
+
+if "%1" == "texinfo" (
+	%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+	goto end
+)
+
+if "%1" == "gettext" (
+	%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+:end

Copied: zope.interface/branches/tseaver-better_unittests/docs/verify.rst (from rev 124741, zope.interface/branches/tseaver-better_unittests/src/zope/interface/verify.txt)
===================================================================
--- zope.interface/branches/tseaver-better_unittests/docs/verify.rst	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/docs/verify.rst	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,127 @@
+===================================
+Verifying interface implementations
+===================================
+
+The ``zope.interface.verify`` module provides functions that test whether a
+given interface is implemented by a class or provided by an object, resp.
+
+
+Verifying classes
+=================
+
+This is covered by unit tests defined in ``zope.interface.tests.test_verify``.
+
+
+Verifying objects
+=================
+
+An object provides an interface if
+
+- either its class declares that it implements the interfaces, or the object
+  declares that it directly provides the interface
+
+- the object defines all the methods required by the interface
+
+- all the methods have the correct signature
+
+- the object defines all non-method attributes required by the interface
+
+This doctest currently covers only the latter item.
+
+Testing for attributes
+----------------------
+
+Attributes of the object, be they defined by its class or added by its
+``__init__`` method, will be recognized:
+
+>>> from zope.interface import Interface, Attribute, implements
+>>> from zope.interface.exceptions import BrokenImplementation
+>>> class IFoo(Interface):
+...     x = Attribute("The X attribute")
+...     y = Attribute("The Y attribute")
+
+>>> class Foo(object):
+...     implements(IFoo)
+...     x = 1
+...     def __init__(self):
+...         self.y = 2
+
+>>> from zope.interface.verify import verifyObject
+>>> verifyObject(IFoo, Foo())
+True
+
+If either attribute is missing, verification will fail:
+
+>>> class Foo(object):
+...     implements(IFoo)
+...     x = 1
+
+>>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+...     verifyObject(IFoo, Foo())
+... except BrokenImplementation, e:
+...     print str(e)
+An object has failed to implement interface <InterfaceClass ...IFoo>
+<BLANKLINE>
+        The y attribute was not provided.
+<BLANKLINE>
+
+>>> class Foo(object):
+...     implements(IFoo)
+...     def __init__(self):
+...         self.y = 2
+
+>>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+...     verifyObject(IFoo, Foo())
+... except BrokenImplementation, e:
+...     print str(e)
+An object has failed to implement interface <InterfaceClass ...IFoo>
+<BLANKLINE>
+        The x attribute was not provided.
+<BLANKLINE>
+
+If an attribute is implemented as a property that raises an AttributeError
+when trying to get its value, the attribute is considered missing:
+
+>>> class IFoo(Interface):
+...     x = Attribute('The X attribute')
+
+>>> class Foo(object):
+...     implements(IFoo)
+...     @property
+...     def x(self):
+...         raise AttributeError
+
+>>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+...     verifyObject(IFoo, Foo())
+... except BrokenImplementation, e:
+...     print str(e)
+An object has failed to implement interface <InterfaceClass ...IFoo>
+<BLANKLINE>
+        The x attribute was not provided.
+<BLANKLINE>
+
+Any other exception raised by a property will propagate to the caller of
+``verifyObject``:
+
+>>> class Foo(object):
+...     implements(IFoo)
+...     @property
+...     def x(self):
+...         raise Exception
+
+>>> verifyObject(IFoo, Foo())
+Traceback (most recent call last):
+Exception
+
+Of course, broken properties that are not required by the interface don't do
+any harm:
+
+>>> class Foo(object):
+...     implements(IFoo)
+...     x = 1
+...     @property
+...     def y(self):
+...         raise Exception
+
+>>> verifyObject(IFoo, Foo())
+True

Added: zope.interface/branches/tseaver-better_unittests/setup.cfg
===================================================================
--- zope.interface/branches/tseaver-better_unittests/setup.cfg	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/setup.cfg	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,10 @@
+[nosetests]
+nocapture=1
+cover-package=zope.interface
+cover-erase=1
+with-doctest=0
+where=src
+
+[aliases]
+dev = develop easy_install zope.interface[testing]
+docs = easy_install zope.interface[docs]

Modified: zope.interface/branches/tseaver-better_unittests/setup.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/setup.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/setup.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -61,14 +61,18 @@
         features = {}
     else:
         features = {'codeoptimization': codeoptimization}
+    tests_require = ['zope.event']
+    testing_extras = tests_require + ['nose', 'coverage']
     extra = dict(
         namespace_packages=["zope"],
         include_package_data = True,
         zip_safe = False,
-        tests_require = ['zope.event'],
+        tests_require = tests_require,
         install_requires = ['setuptools'],
-        extras_require={'docs': ['z3c.recipe.sphinxdoc'],
-                        'test': ['zope.event']},
+        extras_require={'docs': ['Sphinx'],
+                        'test': tests_require,
+                        'testing': testing_extras,
+                       },
         features = features
         )
 
@@ -87,16 +91,6 @@
     extra['install_requires'] = ['setuptools']
     extra['setup_requires'] = ['zope.fixers']
     extra['use_2to3'] = True
-    extra['convert_2to3_doctests'] = [
-        'src/zope/interface/README.ru.txt',
-        'src/zope/interface/README.txt',
-        'src/zope/interface/adapter.ru.txt',
-        'src/zope/interface/adapter.txt',
-        'src/zope/interface/human.ru.txt',
-        'src/zope/interface/human.txt',
-        'src/zope/interface/index.txt',
-        'src/zope/interface/verify.txt',
-        ]
     extra['use_2to3_fixers'] = ['zope.fixers']
 
 except (ImportError, SyntaxError):

Deleted: zope.interface/branches/tseaver-better_unittests/src/zope/interface/README.ru.txt
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/README.ru.txt	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/README.ru.txt	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,803 +0,0 @@
-==========
-Интерфейсы
-==========
-
-.. contents::
-
-Интерфейсы - это объекты специфицирующие (документирующие) внешнее поведение
-объектов которые их "предоставляют". Интерфейсы определяют поведение через
-следующие составляющие:
-
-- Неформальную документацию в строках документации
-
-- Определения атрибутов
-
-- Инварианты - условия, которые должны соблюдаться для объектов предоставляющих
-  интерфейс
-
-Определения атрибутов описывают конкретные атрибуты. Они определяют
-имя атрибута и предоставляют документацию и ограничения для значений
-атрибута. Определения атрибутов могут быть заданы несколькими путями
-как мы увидим ниже.
-
-Определение интерфейсов
-=======================
-
-Интерфейсы определяются с использованием ключевого слова class::
-
-  >>> import zope.interface
-  >>> class IFoo(zope.interface.Interface):
-  ...    """Foo blah blah"""
-  ...
-  ...    x = zope.interface.Attribute("""X blah blah""")
-  ...
-  ...    def bar(q, r=None):
-  ...        """bar blah blah"""
-
-В примере выше мы создали интерфейс `IFoo`. Мы наследуем его от
-класса `zope.interface.Interface`, который является родительским интерфейсом
-для всех интерфейсов, как `object` - это родительский класс для всех новых
-классов [#create]_. Данный интерфейс не является классом, а является
-Интерфейсом, экземпляром `InterfaceClass`::
-
-  >>> type(IFoo)
-  <class 'zope.interface.interface.InterfaceClass'>
-
-Мы можем запросить у интерфейса его документацию::
-
-  >>> IFoo.__doc__
-  'Foo blah blah'
-
-и его имя::
-
-  >>> IFoo.__name__
-  'IFoo'
-
-и даже модуль в котором он определен::
-
-  >>> IFoo.__module__
-  '__main__'
-
-Наш интерфейс определяет два атрибута:
-
-`x`
-  Это простейшая форма определения атрибутов. Определяются имя
-  и строка документации. Формально здесь не определяется ничего более.
-
-`bar`
-  Это метод. Методы определяются как обычные функции. Метод - это просто
-  атрибут который должен быть вызываемым с указанием сигнатуры,
-  предоставляемой определением функции.
-
-  Надо отметить, что аргумент `self` не указывается для `bar`. Интерфейс
-  документирует как объект *используется*. Когда методы экземпляров классов
-  вызываются мы не передаем аргумент `self`, таким образом аргумент `self`
-  не включается и в сигнатуру интерфейса. Аргумент `self` в методах
-  экземпляров классов на самом деле деталь реализации экземпляров классов
-  в Python. Другие объекты кроме экземпляров классов могут предоставлять
-  интерфейсы и их методы могут не быть методами экземпляров классов. Для
-  примера модули могут предоставлять интерфейсы и их методы обычно просто
-  функции. Даже экземпляры могут иметь методы не являющиеся методами
-  экземпляров класса.
-
-Мы можем получить доступ к атрибутам определенным интерфейсом используя
-синтаксис доступа к элементам массива::
-
-  >>> x = IFoo['x']
-  >>> type(x)
-  <class 'zope.interface.interface.Attribute'>
-  >>> x.__name__
-  'x'
-  >>> x.__doc__
-  'X blah blah'
-
-  >>> IFoo.get('x').__name__
-  'x'
-
-  >>> IFoo.get('y')
-
-Можно использовать `in` для определения содержит ли интерфейс
-определенное имя::
-
-  >>> 'x' in IFoo
-  True
-
-Мы можем использовать итератор для интерфейсов что бы получить все имена
-которые интерфейсы определяют::
-
-  >>> names = list(IFoo)
-  >>> names.sort()
-  >>> names
-  ['bar', 'x']
-
-Надо помнить, что интерфейсы не являются классами. Мы не можем получить
-доступ к определениям атрибутов через доступ к атрибутам интерфейсов::
-
-  >>> IFoo.x
-  Traceback (most recent call last):
-    File "<stdin>", line 1, in ?
-  AttributeError: 'InterfaceClass' object has no attribute 'x'
-
-Методы также предоставляют доступ к сигнатуре метода::
-
-  >>> bar = IFoo['bar']
-  >>> bar.getSignatureString()
-  '(q, r=None)'
-
-Объявление интерфейсов
-======================
-
-Определив интерфейс мы можем теперь *объявить*, что объекты предоставляют их.
-Перед описанием деталей определим некоторые термины:
-
-*предоставлять*
-  Мы говорим, что объекты *предоставляют* интерфейсы. Если объект
-  предоставляет интерфейс, тогда интерфейс специфицирует поведение объекта.
-  Другими словами, интерфейсы специфицируют поведение объектов которые
-  предоставляют их.
-
-*реализовать*
-  Мы обычно говорим что классы *реализуют* интерфейсы. Если класс
-  реализует интерфейс, тогда экземпляры этого класса предоставляют
-  данный интерфейс. Объекты предоставляют интерфейсы которые их классы
-  реализуют [#factory]_. (Объекты также могут предоставлять интерфейсы напрямую
-  плюс к тем которые реализуют их классы.)
-
-  Важно помнить, что классы обычно не предоставляют интерфейсы которые
-  они реализуют.
-
-  Мы можем обобщить это до фабрик. Для любого вызываемого объекта мы можем
-  объявить что он производит объекты которые предоставляют какие-либо
-  интерфейсы сказав, что фабрика реализует данные интерфейсы.
-
-Теперь после того как мы определили эти термины мы можем поговорить об
-API для объявления интерфейсов.
-
-Объявление реализуемых интерфейсов
-----------------------------------
-
-Наиболее часто используемый путь для объявления интерфейсов - это использование
-функции implements в определении класса::
-
-  >>> class Foo:
-  ...     zope.interface.implements(IFoo)
-  ...
-  ...     def __init__(self, x=None):
-  ...         self.x = x
-  ...
-  ...     def bar(self, q, r=None):
-  ...         return q, r, self.x
-  ...
-  ...     def __repr__(self):
-  ...         return "Foo(%s)" % self.x
-
-В этом примере мы объявили, что `Foo` реализует `IFoo`. Это значит, что
-экземпляры `Foo` предоставляют `IFoo`. После данного объявления есть
-несколько путей для анализа объявлений. Во-первых мы можем спросить
-что интерфейс реализован классом::
-
-  >>> IFoo.implementedBy(Foo)
-  True
-
-Также мы можем спросить если интерфейс предоставляется объектами класса::
-
-  >>> foo = Foo()
-  >>> IFoo.providedBy(foo)
-  True
-
-Конечно `Foo` не предоставляет `IFoo`, он реализует его::
-
-  >>> IFoo.providedBy(Foo)
-  False
-
-Мы можем также узнать какие интерфейсы реализуются объектами::
-
-  >>> list(zope.interface.implementedBy(Foo))
-  [<InterfaceClass __main__.IFoo>]
-
-Это ошибка спрашивать про интерфейсы реализуемые не вызываемым объектом::
-
-  >>> IFoo.implementedBy(foo)
-  Traceback (most recent call last):
-  ...
-  TypeError: ('ImplementedBy called for non-factory', Foo(None))
-
-  >>> list(zope.interface.implementedBy(foo))
-  Traceback (most recent call last):
-  ...
-  TypeError: ('ImplementedBy called for non-factory', Foo(None))
-
-Также можно узнать какие интерфейсы предоставляются объектами::
-
-  >>> list(zope.interface.providedBy(foo))
-  [<InterfaceClass __main__.IFoo>]
-  >>> list(zope.interface.providedBy(Foo))
-  []
-
-Мы можем объявить интерфейсы реализуемые другими фабриками (кроме классов).
-Это можно сделать используя декоратор `implementer` (в стиле Python 2.4).
-Для версий Python ниже 2.4 это будет выглядеть следующим образом::
-
-  >>> def yfoo(y):
-  ...     foo = Foo()
-  ...     foo.y = y
-  ...     return foo
-  >>> yfoo = zope.interface.implementer(IFoo)(yfoo)
-
-  >>> list(zope.interface.implementedBy(yfoo))
-  [<InterfaceClass __main__.IFoo>]
-
-Надо заметить, что декоратор implementer может модифицировать свои аргументы.
-Вызывающая сторона не должна предполагать, что всегда будет создаваться
-новый объект.
-
-XXX: Double check and update these version numbers, and translate to russian:
-
-In zope.interface 3.5.1 and lower, the implementer decorator can not
-be used for classes, but in 3.5.2 and higher it can:
-
-  >>> Foo = zope.interface.implementer(IFoo)(Foo)
-  >>> list(zope.interface.providedBy(Foo()))
-  [<InterfaceClass __main__.IFoo>]
-  
-Note that class decorators using the @implementer(IFoo) syntax are only 
-supported in Python 2.6 and later.
-
-
-Объявление предоставляемых интерфейсов
---------------------------------------
-
-Мы можем объявлять интерфейсы напрямую предоставляемые объектами. Предположим
-что мы хотим документировать что делает метод `__init__` класса `Foo`. Это
-*точно* не часть `IFoo`. Обычно мы не должны напрямую вызывать метод `__init__`
-для экземпляров Foo. Скорее метод `__init__` является частью метода `__call__`
-класса `Foo`::
-
-  >>> class IFooFactory(zope.interface.Interface):
-  ...     """Create foos"""
-  ...
-  ...     def __call__(x=None):
-  ...         """Create a foo
-  ...
-  ...         The argument provides the initial value for x ...
-  ...         """
-
-У нас есть класс предоставляющий данный интерфейс, таким образом мы можем
-объявить интерфейс класса::
-
-  >>> zope.interface.directlyProvides(Foo, IFooFactory)
-
-Теперь мы видим, что Foo уже предоставляет интерфейсы::
-
-  >>> list(zope.interface.providedBy(Foo))
-  [<InterfaceClass __main__.IFooFactory>]
-  >>> IFooFactory.providedBy(Foo)
-  True
-
-Объявление интерфейсов класса достаточно частая операция и для нее есть
-специальная функция объявления `classProvides`, которая позволяет объявлять
-интерфейсы при определении класса::
-
-  >>> class Foo2:
-  ...     zope.interface.implements(IFoo)
-  ...     zope.interface.classProvides(IFooFactory)
-  ...
-  ...     def __init__(self, x=None):
-  ...         self.x = x
-  ...
-  ...     def bar(self, q, r=None):
-  ...         return q, r, self.x
-  ...
-  ...     def __repr__(self):
-  ...         return "Foo(%s)" % self.x
-
-  >>> list(zope.interface.providedBy(Foo2))
-  [<InterfaceClass __main__.IFooFactory>]
-  >>> IFooFactory.providedBy(Foo2)
-  True
-
-Похожая функция `moduleProvides` поддерживает объявление интерфейсов при
-определении модуля. Для примера смотрите использование вызова
-`moduleProvides` в `zope.interface.__init__`, который объявляет, что
-пакет `zope.interface` предоставляет `IInterfaceDeclaration`.
-
-Иногда мы хотим объявить интерфейсы экземпляров, даже если эти экземпляры
-уже берут интерфейсы от своих классов. Предположим, что мы создаем новый
-интерфейс `ISpecial`::
-
-  >>> class ISpecial(zope.interface.Interface):
-  ...     reason = zope.interface.Attribute("Reason why we're special")
-  ...     def brag():
-  ...         "Brag about being special"
-
-Мы можем сделать созданный экземпляр foo специальным предоставив атрибуты
-`reason` и `brag`::
-
-  >>> foo.reason = 'I just am'
-  >>> def brag():
-  ...      return "I'm special!"
-  >>> foo.brag = brag
-  >>> foo.reason
-  'I just am'
-  >>> foo.brag()
-  "I'm special!"
-
-и объявив интерфейс::
-
-  >>> zope.interface.directlyProvides(foo, ISpecial)
-
-таким образом новый интерфейс включается в список предоставляемых интерфейсов::
-
-  >>> ISpecial.providedBy(foo)
-  True
-  >>> list(zope.interface.providedBy(foo))
-  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
-Мы также можем определить, что интерфейсы напрямую предоставляются
-объектами::
-
-  >>> list(zope.interface.directlyProvidedBy(foo))
-  [<InterfaceClass __main__.ISpecial>]
-
-  >>> newfoo = Foo()
-  >>> list(zope.interface.directlyProvidedBy(newfoo))
-  []
-
-Наследуемые объявления
-----------------------
-
-Обычно объявления наследуются::
-
-  >>> class SpecialFoo(Foo):
-  ...     zope.interface.implements(ISpecial)
-  ...     reason = 'I just am'
-  ...     def brag(self):
-  ...         return "I'm special because %s" % self.reason
-
-  >>> list(zope.interface.implementedBy(SpecialFoo))
-  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
-  >>> list(zope.interface.providedBy(SpecialFoo()))
-  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
-Иногда мы не хотим наследовать объявления. В этом случае мы можем
-использовать `implementsOnly` вместо `implements`::
-
-  >>> class Special(Foo):
-  ...     zope.interface.implementsOnly(ISpecial)
-  ...     reason = 'I just am'
-  ...     def brag(self):
-  ...         return "I'm special because %s" % self.reason
-
-  >>> list(zope.interface.implementedBy(Special))
-  [<InterfaceClass __main__.ISpecial>]
-
-  >>> list(zope.interface.providedBy(Special()))
-  [<InterfaceClass __main__.ISpecial>]
-
-Внешние объявления
-------------------
-
-Обычно мы создаем объявления реализации как часть объявления класса. Иногда
-мы можем захотеть создать объявления вне объявления класса. Для примера,
-мы можем хотеть объявить интерфейсы для классов которые писали не мы.
-Для этого может использоваться функция `classImplements`::
-
-  >>> class C:
-  ...     pass
-
-  >>> zope.interface.classImplements(C, IFoo)
-  >>> list(zope.interface.implementedBy(C))
-  [<InterfaceClass __main__.IFoo>]
-
-Мы можем использовать `classImplementsOnly` для исключения наследуемых
-интерфейсов::
-
-  >>> class C(Foo):
-  ...     pass
-
-  >>> zope.interface.classImplementsOnly(C, ISpecial)
-  >>> list(zope.interface.implementedBy(C))
-  [<InterfaceClass __main__.ISpecial>]
-
-Объекты объявлений
-------------------
-
-Когда мы объявляем интерфейсы мы создаем объект *объявления*. Когда мы
-запрашиваем объявления возвращается объект объявления::
-
-  >>> type(zope.interface.implementedBy(Special))
-  <class 'zope.interface.declarations.Implements'>
-
-Объекты объявления и объекты интерфейсов во многом похожи друг на друга.
-На самом деле они даже имеют общий базовый класс. Важно понять, что они могут
-использоваться там где в объявлениях ожидаются интерфейсы. Вот простой
-пример::
-
-  >>> class Special2(Foo):
-  ...     zope.interface.implementsOnly(
-  ...          zope.interface.implementedBy(Foo),
-  ...          ISpecial,
-  ...          )
-  ...     reason = 'I just am'
-  ...     def brag(self):
-  ...         return "I'm special because %s" % self.reason
-
-Объявление здесь практически такое же как
-``zope.interface.implements(ISpecial)``, отличие только в порядке
-интерфейсов в итоговом объявления::
-
-  >>> list(zope.interface.implementedBy(Special2))
-  [<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.ISpecial>]
-
-Наследование интерфейсов
-========================
-
-Интерфейсы могут расширять другие интерфейсы. Они делают это просто
-показывая эти интерфейсы как базовые::
-
-  >>> class IBlat(zope.interface.Interface):
-  ...     """Blat blah blah"""
-  ...
-  ...     y = zope.interface.Attribute("y blah blah")
-  ...     def eek():
-  ...         """eek blah blah"""
-
-  >>> IBlat.__bases__
-  (<InterfaceClass zope.interface.Interface>,)
-
-  >>> class IBaz(IFoo, IBlat):
-  ...     """Baz blah"""
-  ...     def eek(a=1):
-  ...         """eek in baz blah"""
-  ...
-
-  >>> IBaz.__bases__
-  (<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.IBlat>)
-
-  >>> names = list(IBaz)
-  >>> names.sort()
-  >>> names
-  ['bar', 'eek', 'x', 'y']
-
-Заметим, что `IBaz` переопределяет eek::
-
-  >>> IBlat['eek'].__doc__
-  'eek blah blah'
-  >>> IBaz['eek'].__doc__
-  'eek in baz blah'
-
-Мы были осторожны переопределяя eek совместимым путем. Когда интерфейс
-расширяется, расширенный интерфейс должен быть совместимым [#compat]_ с
-расширяемыми интерфейсами.
-
-Мы можем запросить расширяет ли один из интерфейсов другой::
-
-  >>> IBaz.extends(IFoo)
-  True
-  >>> IBlat.extends(IFoo)
-  False
-
-Заметим, что интерфейсы не расширяют сами себя::
-
-  >>> IBaz.extends(IBaz)
-  False
-
-Иногда мы можем хотеть что бы они расширяли сами себя, но вместо этого
-мы можем использовать `isOrExtends`::
-
-  >>> IBaz.isOrExtends(IBaz)
-  True
-  >>> IBaz.isOrExtends(IFoo)
-  True
-  >>> IFoo.isOrExtends(IBaz)
-  False
-
-Когда мы применяем итерацию к интерфейсу мы получаем все имена которые он
-определяет включая имена определенные для базовых интерфейсов. Иногда
-мы хотим получить *только* имена определенные интерфейсом напрямую.
-Для этого мы используем метод `names`::
-
-  >>> list(IBaz.names())
-  ['eek']
-
-Наследование в случае определения атрибутов
---------------------------------------------
-
-Интерфейс может переопределять определения атрибутов из базовых интерфейсов.
-Если два базовых интерфейса определяют один и тот же атрибут атрибут
-наследуется от более специфичного интерфейса. Для примера::
-
-  >>> class IBase(zope.interface.Interface):
-  ...
-  ...     def foo():
-  ...         "base foo doc"
-
-  >>> class IBase1(IBase):
-  ...     pass
-
-  >>> class IBase2(IBase):
-  ...
-  ...     def foo():
-  ...         "base2 foo doc"
-
-  >>> class ISub(IBase1, IBase2):
-  ...     pass
-
-Определение ISub для foo будет из IBase2 т.к. IBase2 более специфичен для
-IBase::
-
-  >>> ISub['foo'].__doc__
-  'base2 foo doc'
-
-Заметим, что это отличается от поиска в глубину.
-
-Иногда полезно узнать, что интерфейс определяет атрибут напрямую. Мы можем
-использовать метод direct для получения напрямую определенных атрибутов::
-
-  >>> IBase.direct('foo').__doc__
-  'base foo doc'
-
-  >>> ISub.direct('foo')
-
-Спецификации
-------------
-
-Интерфейсы и объявления - это специальные случаи спецификаций. Описание
-выше для наследования интерфейсов можно применить и к объявлениям и
-к спецификациям. Объявления фактически расширяют интерфейсы которые они
-объявляют::
-
-  >>> class Baz(object):
-  ...     zope.interface.implements(IBaz)
-
-  >>> baz_implements = zope.interface.implementedBy(Baz)
-  >>> baz_implements.__bases__
-  (<InterfaceClass __main__.IBaz>, <implementedBy ...object>)
-
-  >>> baz_implements.extends(IFoo)
-  True
-
-  >>> baz_implements.isOrExtends(IFoo)
-  True
-  >>> baz_implements.isOrExtends(baz_implements)
-  True
-
-Спецификации (интерфейсы и объявления) предоставляют атрибут `__sro__`
-который описывает спецификацию и всех ее предков::
-
-  >>> baz_implements.__sro__
-  (<implementedBy __main__.Baz>,
-   <InterfaceClass __main__.IBaz>,
-   <InterfaceClass __main__.IFoo>,
-   <InterfaceClass __main__.IBlat>,
-   <InterfaceClass zope.interface.Interface>,
-   <implementedBy ...object>)
-
-Помеченные значения
-===================
-
-Интерфейсы и описания атрибутов поддерживают механизм расширения
-заимствованный из UML и называемый "помеченные значения" который позволяет
-сохранять дополнительные данные::
-
-  >>> IFoo.setTaggedValue('date-modified', '2004-04-01')
-  >>> IFoo.setTaggedValue('author', 'Jim Fulton')
-  >>> IFoo.getTaggedValue('date-modified')
-  '2004-04-01'
-  >>> IFoo.queryTaggedValue('date-modified')
-  '2004-04-01'
-  >>> IFoo.queryTaggedValue('datemodified')
-  >>> tags = list(IFoo.getTaggedValueTags())
-  >>> tags.sort()
-  >>> tags
-  ['author', 'date-modified']
-
-Атрибуты функций конвертируются в помеченные значения когда создаются
-определения атрибутов метода::
-
-  >>> class IBazFactory(zope.interface.Interface):
-  ...     def __call__():
-  ...         "create one"
-  ...     __call__.return_type = IBaz
-
-  >>> IBazFactory['__call__'].getTaggedValue('return_type')
-  <InterfaceClass __main__.IBaz>
-
-Помеченные значения также могут быть определены внутри определения
-интерфейса::
-
-  >>> class IWithTaggedValues(zope.interface.Interface):
-  ...     zope.interface.taggedValue('squish', 'squash')
-  >>> IWithTaggedValues.getTaggedValue('squish')
-  'squash'
-
-Инварианты
-==========
-
-Интерфейсы могут описывать условия которые должны быть соблюдены для объектов
-которые их предоставляют. Эти условия описываются используя один или более
-инвариантов. Инварианты - это вызываемые объекты которые будут вызваны
-с объектом предоставляющим интерфейс в качестве параметра. Инвариант
-должен выкинуть исключение `Invalid` если условие не соблюдено. Например::
-
-  >>> class RangeError(zope.interface.Invalid):
-  ...     """A range has invalid limits"""
-  ...     def __repr__(self):
-  ...         return "RangeError(%r)" % self.args
-
-  >>> def range_invariant(ob):
-  ...     if ob.max < ob.min:
-  ...         raise RangeError(ob)
-
-Определив этот инвариант мы можем использовать его в определении интерфейсов::
-
-  >>> class IRange(zope.interface.Interface):
-  ...     min = zope.interface.Attribute("Lower bound")
-  ...     max = zope.interface.Attribute("Upper bound")
-  ...
-  ...     zope.interface.invariant(range_invariant)
-
-Интерфейсы имеют метод для проверки своих инвариантов::
-
-  >>> class Range(object):
-  ...     zope.interface.implements(IRange)
-  ...
-  ...     def __init__(self, min, max):
-  ...         self.min, self.max = min, max
-  ...
-  ...     def __repr__(self):
-  ...         return "Range(%s, %s)" % (self.min, self.max)
-
-  >>> IRange.validateInvariants(Range(1,2))
-  >>> IRange.validateInvariants(Range(1,1))
-  >>> IRange.validateInvariants(Range(2,1))
-  Traceback (most recent call last):
-  ...
-  RangeError: Range(2, 1)
-
-В случае нескольких инвариантов мы можем захотеть остановить проверку после
-первой ошибки. Если мы передадим в `validateInvariants` пустой список тогда
-будет выкинуто единственное исключение `Invalid` со списком исключений
-как аргументом::
-
-  >>> from zope.interface.exceptions import Invalid
-  >>> errors = []
-  >>> try:
-  ...     IRange.validateInvariants(Range(2,1), errors)
-  ... except Invalid, e:
-  ...     str(e)
-  '[RangeError(Range(2, 1))]'
-
-И список будет заполнен индивидуальными исключениями::
-
-  >>> errors
-  [RangeError(Range(2, 1))]
-
-  >>> del errors[:]
-
-Адаптация
-=========
-
-Интерфейсы могут быть вызваны для осуществления адаптации. Эта семантика
-основана на функции adapt из PEP 246. Если объект не может быть адаптирован
-будет выкинут TypeError::
-
-  >>> class I(zope.interface.Interface):
-  ...     pass
-
-  >>> I(0)
-  Traceback (most recent call last):
-  ...
-  TypeError: ('Could not adapt', 0, <InterfaceClass __main__.I>)
-
-только если альтернативное значение не передано как второй аргумент::
-
-  >>> I(0, 'bob')
-  'bob'
-
-Если объект уже реализует нужный интерфейс он будет возвращен::
-
-  >>> class C(object):
-  ...     zope.interface.implements(I)
-
-  >>> obj = C()
-  >>> I(obj) is obj
-  True
-
-Если объект реализует __conform__, тогда она будет использована::
-
-  >>> class C(object):
-  ...     zope.interface.implements(I)
-  ...     def __conform__(self, proto):
-  ...          return 0
-
-  >>> I(C())
-  0
-
-Также если присутствуют функции для вызова адаптации (см. __adapt__) они будут
-использованы::
-
-  >>> from zope.interface.interface import adapter_hooks
-  >>> def adapt_0_to_42(iface, obj):
-  ...     if obj == 0:
-  ...         return 42
-
-  >>> adapter_hooks.append(adapt_0_to_42)
-  >>> I(0)
-  42
-
-  >>> adapter_hooks.remove(adapt_0_to_42)
-  >>> I(0)
-  Traceback (most recent call last):
-  ...
-  TypeError: ('Could not adapt', 0, <InterfaceClass __main__.I>)
-
-
-__adapt__
----------
-
-  >>> class I(zope.interface.Interface):
-  ...     pass
-
-Интерфейсы реализуют метод __adapt__ из PEP 246. Этот метод обычно не
-вызывается напрямую. Он вызывается архитектурой адаптации из PEP 246 и методом
-__call__ интерфейсов. Метод адаптации отвечает за адаптацию объекта к
-получателю. Версия по умолчанию возвращает None::
-
-  >>> I.__adapt__(0)
-
-если только переданный объект не предоставляет нужный интерфейс::
-
-  >>> class C(object):
-  ...     zope.interface.implements(I)
-
-  >>> obj = C()
-  >>> I.__adapt__(obj) is obj
-  True
-
-Функции для вызова адаптации могут быть добавлены (или удалены) для
-предоставления адаптации "на заказ". Мы установим глупую функцию которая
-адаптирует 0 к 42. Мы устанавливаем функцию просто добавляя ее к списку
-adapter_hooks::
-
-  >>> from zope.interface.interface import adapter_hooks
-  >>> def adapt_0_to_42(iface, obj):
-  ...     if obj == 0:
-  ...         return 42
-
-  >>> adapter_hooks.append(adapt_0_to_42)
-  >>> I.__adapt__(0)
-  42
-
-Функции должны возвращать либо адаптер, либо None если адаптер не найден.
-Функции могут быть удалены удалением их из списка::
-
-  >>> adapter_hooks.remove(adapt_0_to_42)
-  >>> I.__adapt__(0)
-
-
-.. [#create] Основная причина по которой мы наследуемся от `Interface` - это
-             что бы быть уверенными в том, что ключевое слово class будет
-             создавать интерфейс, а не класс.
-
-             Есть возможность создать интерфейсы вызвав специальный
-             класс интерфейса напрямую. Делая это, возможно (и в редких
-             случаях полезно) создать интерфейсы которые не наследуются
-             от `Interface`. Однако использование этой техники выходит
-	     за рамки данного документа.
-
-.. [#factory] Классы - это фабрики. Они могут быть вызваны для создания
-              своих экземпляров. Мы ожидаем что в итоге мы расширим
-              концепцию реализации на другие типы фабрик, таким образом
-              мы сможем объявлять интерфейсы предоставляемые созданными
-              фабриками объектами.
-
-.. [#compat] Цель - заменяемость. Объект который предоставляет расширенный
-             интерфейс должен быть заменяем в качестве объектов которые
-             предоставляют расширяемый интерфейс. В нашем примере объект
-             который предоставляет IBaz должен быть используемым и
-             в случае если ожидается объект который предоставляет IBlat.
-
-             Реализация интерфейса не требует этого. Но возможно в дальнейшем
-             она должна будет делать какие-либо проверки.

Deleted: zope.interface/branches/tseaver-better_unittests/src/zope/interface/README.txt
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/README.txt	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/README.txt	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,829 +0,0 @@
-==========
-Interfaces
-==========
-
-Interfaces are objects that specify (document) the external behavior
-of objects that "provide" them.  An interface specifies behavior
-through:
-
-- Informal documentation in a doc string
-
-- Attribute definitions
-
-- Invariants, which are conditions that must hold for objects that
-  provide the interface
-
-Attribute definitions specify specific attributes. They define the
-attribute name and provide documentation and constraints of attribute
-values.  Attribute definitions can take a number of forms, as we'll
-see below.
-
-Defining interfaces
-===================
-
-Interfaces are defined using Python class statements::
-
-  >>> import zope.interface
-  >>> class IFoo(zope.interface.Interface):
-  ...    """Foo blah blah"""
-  ...
-  ...    x = zope.interface.Attribute("""X blah blah""")
-  ...
-  ...    def bar(q, r=None):
-  ...        """bar blah blah"""
-
-In the example above, we've created an interface, `IFoo`.  We
-subclassed `zope.interface.Interface`, which is an ancestor interface for
-all interfaces, much as `object` is an ancestor of all new-style
-classes [#create]_.   The interface is not a class, it's an Interface,
-an instance of `InterfaceClass`::
-
-  >>> type(IFoo)
-  <class 'zope.interface.interface.InterfaceClass'>
-
-We can ask for the interface's documentation::
-
-  >>> IFoo.__doc__
-  'Foo blah blah'
-
-and its name::
-
-  >>> IFoo.__name__
-  'IFoo'
-
-and even its module::
-
-  >>> IFoo.__module__
-  '__main__'
-
-The interface defined two attributes:
-
-`x`
-  This is the simplest form of attribute definition.  It has a name
-  and a doc string.  It doesn't formally specify anything else.
-
-`bar`
-  This is a method.  A method is defined via a function definition.  A
-  method is simply an attribute constrained to be a callable with a
-  particular signature, as provided by the function definition.
-
-  Note that `bar` doesn't take a `self` argument.  Interfaces document
-  how an object is *used*.  When calling instance methods, you don't
-  pass a `self` argument, so a `self` argument isn't included in the
-  interface signature.  The `self` argument in instance methods is
-  really an implementation detail of Python instances. Other objects,
-  besides instances can provide interfaces and their methods might not
-  be instance methods. For example, modules can provide interfaces and
-  their methods are usually just functions.  Even instances can have
-  methods that are not instance methods.
-
-You can access the attributes defined by an interface using mapping
-syntax::
-
-  >>> x = IFoo['x']
-  >>> type(x)
-  <class 'zope.interface.interface.Attribute'>
-  >>> x.__name__
-  'x'
-  >>> x.__doc__
-  'X blah blah'
-
-  >>> IFoo.get('x').__name__
-  'x'
-
-  >>> IFoo.get('y')
-
-You can use `in` to determine if an interface defines a name::
-
-  >>> 'x' in IFoo
-  True
-
-You can iterate over interfaces to get the names they define::
-
-  >>> names = list(IFoo)
-  >>> names.sort()
-  >>> names
-  ['bar', 'x']
-
-Remember that interfaces aren't classes. You can't access attribute
-definitions as attributes of interfaces::
-
-  >>> IFoo.x
-  Traceback (most recent call last):
-    File "<stdin>", line 1, in ?
-  AttributeError: 'InterfaceClass' object has no attribute 'x'
-
-Methods provide access to the method signature::
-
-  >>> bar = IFoo['bar']
-  >>> bar.getSignatureString()
-  '(q, r=None)'
-
-TODO
-  Methods really should have a better API.  This is something that
-  needs to be improved.
-
-Declaring interfaces
-====================
-
-Having defined interfaces, we can *declare* that objects provide
-them.  Before we describe the details, lets define some terms:
-
-*provide*
-   We say that objects *provide* interfaces.  If an object provides an
-   interface, then the interface specifies the behavior of the
-   object. In other words, interfaces specify the behavior of the
-   objects that provide them.
-
-*implement*
-   We normally say that classes *implement* interfaces.  If a class
-   implements an interface, then the instances of the class provide
-   the interface.  Objects provide interfaces that their classes
-   implement [#factory]_.  (Objects can provide interfaces directly,
-   in addition to what their classes implement.)
-
-   It is important to note that classes don't usually provide the
-   interfaces that they implement.
-
-   We can generalize this to factories.  For any callable object we
-   can declare that it produces objects that provide some interfaces
-   by saying that the factory implements the interfaces.
-
-Now that we've defined these terms, we can talk about the API for
-declaring interfaces.
-
-Declaring implemented interfaces
---------------------------------
-
-The most common way to declare interfaces is using the implements
-function in a class statement::
-
-  >>> class Foo:
-  ...     zope.interface.implements(IFoo)
-  ...
-  ...     def __init__(self, x=None):
-  ...         self.x = x
-  ...
-  ...     def bar(self, q, r=None):
-  ...         return q, r, self.x
-  ...
-  ...     def __repr__(self):
-  ...         return "Foo(%s)" % self.x
-
-
-In this example, we declared that `Foo` implements `IFoo`. This means
-that instances of `Foo` provide `IFoo`.  Having made this declaration,
-there are several ways we can introspect the declarations.  First, we
-can ask an interface whether it is implemented by a class::
-
-  >>> IFoo.implementedBy(Foo)
-  True
-
-And we can ask whether an interface is provided by an object::
-
-  >>> foo = Foo()
-  >>> IFoo.providedBy(foo)
-  True
-
-Of course, `Foo` doesn't provide `IFoo`, it implements it::
-
-  >>> IFoo.providedBy(Foo)
-  False
-
-We can also ask what interfaces are implemented by an object::
-
-  >>> list(zope.interface.implementedBy(Foo))
-  [<InterfaceClass __main__.IFoo>]
-
-It's an error to ask for interfaces implemented by a non-callable
-object::
-
-  >>> IFoo.implementedBy(foo)
-  Traceback (most recent call last):
-  ...
-  TypeError: ('ImplementedBy called for non-factory', Foo(None))
-
-  >>> list(zope.interface.implementedBy(foo))
-  Traceback (most recent call last):
-  ...
-  TypeError: ('ImplementedBy called for non-factory', Foo(None))
-
-Similarly, we can ask what interfaces are provided by an object::
-
-  >>> list(zope.interface.providedBy(foo))
-  [<InterfaceClass __main__.IFoo>]
-  >>> list(zope.interface.providedBy(Foo))
-  []
-
-We can declare interfaces implemented by other factories (besides
-classes).  We do this using a Python-2.4-style decorator named
-`implementer`.  In versions of Python before 2.4, this looks like::
-
-  >>> def yfoo(y):
-  ...     foo = Foo()
-  ...     foo.y = y
-  ...     return foo
-  >>> yfoo = zope.interface.implementer(IFoo)(yfoo)
-
-  >>> list(zope.interface.implementedBy(yfoo))
-  [<InterfaceClass __main__.IFoo>]
-
-Note that the implementer decorator may modify it's argument. Callers
-should not assume that a new object is created.
-
-Using implementer also works on callable objects. This is used by
-zope.formlib, as an example.
-
-  >>> class yfactory:
-  ...     def __call__(self, y):
-  ...         foo = Foo()
-  ...         foo.y = y
-  ...         return foo
-  >>> yfoo = yfactory()
-  >>> yfoo = zope.interface.implementer(IFoo)(yfoo)
-
-  >>> list(zope.interface.implementedBy(yfoo))
-  [<InterfaceClass __main__.IFoo>]
-
-XXX: Double check and update these version numbers:
-
-In zope.interface 3.5.2 and lower, the implementer decorator can not
-be used for classes, but in 3.6.0 and higher it can:
-
-  >>> Foo = zope.interface.implementer(IFoo)(Foo)
-  >>> list(zope.interface.providedBy(Foo()))
-  [<InterfaceClass __main__.IFoo>]
-  
-Note that class decorators using the @implementer(IFoo) syntax are only 
-supported in Python 2.6 and later.
-
-
-Declaring provided interfaces
------------------------------
-
-We can declare interfaces directly provided by objects.  Suppose that
-we want to document what the `__init__` method of the `Foo` class
-does.  It's not *really* part of `IFoo`.  You wouldn't normally call
-the `__init__` method on Foo instances.  Rather, the `__init__` method
-is part of the `Foo`'s `__call__` method::
-
-  >>> class IFooFactory(zope.interface.Interface):
-  ...     """Create foos"""
-  ...
-  ...     def __call__(x=None):
-  ...         """Create a foo
-  ...
-  ...         The argument provides the initial value for x ...
-  ...         """
-
-It's the class that provides this interface, so we declare the
-interface on the class::
-
-  >>> zope.interface.directlyProvides(Foo, IFooFactory)
-
-And then, we'll see that Foo provides some interfaces::
-
-  >>> list(zope.interface.providedBy(Foo))
-  [<InterfaceClass __main__.IFooFactory>]
-  >>> IFooFactory.providedBy(Foo)
-  True
-
-Declaring class interfaces is common enough that there's a special
-declaration function for it, `classProvides`, that allows the
-declaration from within a class statement::
-
-  >>> class Foo2:
-  ...     zope.interface.implements(IFoo)
-  ...     zope.interface.classProvides(IFooFactory)
-  ...
-  ...     def __init__(self, x=None):
-  ...         self.x = x
-  ...
-  ...     def bar(self, q, r=None):
-  ...         return q, r, self.x
-  ...
-  ...     def __repr__(self):
-  ...         return "Foo(%s)" % self.x
-
-  >>> list(zope.interface.providedBy(Foo2))
-  [<InterfaceClass __main__.IFooFactory>]
-  >>> IFooFactory.providedBy(Foo2)
-  True
-
-There's a similar function, `moduleProvides`, that supports interface
-declarations from within module definitions.  For example, see the use
-of `moduleProvides` call in `zope.interface.__init__`, which declares that
-the package `zope.interface` provides `IInterfaceDeclaration`.
-
-Sometimes, we want to declare interfaces on instances, even though
-those instances get interfaces from their classes.  Suppose we create
-a new interface, `ISpecial`::
-
-  >>> class ISpecial(zope.interface.Interface):
-  ...     reason = zope.interface.Attribute("Reason why we're special")
-  ...     def brag():
-  ...         "Brag about being special"
-
-We can make an existing foo instance special by providing `reason`
-and `brag` attributes::
-
-  >>> foo.reason = 'I just am'
-  >>> def brag():
-  ...      return "I'm special!"
-  >>> foo.brag = brag
-  >>> foo.reason
-  'I just am'
-  >>> foo.brag()
-  "I'm special!"
-
-and by declaring the interface::
-
-  >>> zope.interface.directlyProvides(foo, ISpecial)
-
-then the new interface is included in the provided interfaces::
-
-  >>> ISpecial.providedBy(foo)
-  True
-  >>> list(zope.interface.providedBy(foo))
-  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
-We can find out what interfaces are directly provided by an object::
-
-  >>> list(zope.interface.directlyProvidedBy(foo))
-  [<InterfaceClass __main__.ISpecial>]
-
-  >>> newfoo = Foo()
-  >>> list(zope.interface.directlyProvidedBy(newfoo))
-  []
-
-Inherited declarations
-----------------------
-
-Normally, declarations are inherited::
-
-  >>> class SpecialFoo(Foo):
-  ...     zope.interface.implements(ISpecial)
-  ...     reason = 'I just am'
-  ...     def brag(self):
-  ...         return "I'm special because %s" % self.reason
-
-  >>> list(zope.interface.implementedBy(SpecialFoo))
-  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
-  >>> list(zope.interface.providedBy(SpecialFoo()))
-  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
-
-Sometimes, you don't want to inherit declarations.  In that case, you
-can use `implementsOnly`, instead of `implements`::
-
-  >>> class Special(Foo):
-  ...     zope.interface.implementsOnly(ISpecial)
-  ...     reason = 'I just am'
-  ...     def brag(self):
-  ...         return "I'm special because %s" % self.reason
-
-  >>> list(zope.interface.implementedBy(Special))
-  [<InterfaceClass __main__.ISpecial>]
-
-  >>> list(zope.interface.providedBy(Special()))
-  [<InterfaceClass __main__.ISpecial>]
-
-External declarations
----------------------
-
-Normally, we make implementation declarations as part of a class
-definition. Sometimes, we may want to make declarations from outside
-the class definition. For example, we might want to declare interfaces
-for classes that we didn't write.  The function `classImplements` can
-be used for this purpose::
-
-  >>> class C:
-  ...     pass
-
-  >>> zope.interface.classImplements(C, IFoo)
-  >>> list(zope.interface.implementedBy(C))
-  [<InterfaceClass __main__.IFoo>]
-
-We can use `classImplementsOnly` to exclude inherited interfaces::
-
-  >>> class C(Foo):
-  ...     pass
-
-  >>> zope.interface.classImplementsOnly(C, ISpecial)
-  >>> list(zope.interface.implementedBy(C))
-  [<InterfaceClass __main__.ISpecial>]
-
-
-
-Declaration Objects
--------------------
-
-When we declare interfaces, we create *declaration* objects.  When we
-query declarations, declaration objects are returned::
-
-  >>> type(zope.interface.implementedBy(Special))
-  <class 'zope.interface.declarations.Implements'>
-
-Declaration objects and interface objects are similar in many ways. In
-fact, they share a common base class.  The important thing to realize
-about them is that they can be used where interfaces are expected in
-declarations. Here's a silly example::
-
-  >>> class Special2(Foo):
-  ...     zope.interface.implementsOnly(
-  ...          zope.interface.implementedBy(Foo),
-  ...          ISpecial,
-  ...          )
-  ...     reason = 'I just am'
-  ...     def brag(self):
-  ...         return "I'm special because %s" % self.reason
-
-The declaration here is almost the same as
-``zope.interface.implements(ISpecial)``, except that the order of
-interfaces in the resulting declaration is different::
-
-  >>> list(zope.interface.implementedBy(Special2))
-  [<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.ISpecial>]
-
-
-Interface Inheritance
-=====================
-
-Interfaces can extend other interfaces. They do this simply by listing
-the other interfaces as base interfaces::
-
-  >>> class IBlat(zope.interface.Interface):
-  ...     """Blat blah blah"""
-  ...
-  ...     y = zope.interface.Attribute("y blah blah")
-  ...     def eek():
-  ...         """eek blah blah"""
-
-  >>> IBlat.__bases__
-  (<InterfaceClass zope.interface.Interface>,)
-
-  >>> class IBaz(IFoo, IBlat):
-  ...     """Baz blah"""
-  ...     def eek(a=1):
-  ...         """eek in baz blah"""
-  ...
-
-  >>> IBaz.__bases__
-  (<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.IBlat>)
-
-  >>> names = list(IBaz)
-  >>> names.sort()
-  >>> names
-  ['bar', 'eek', 'x', 'y']
-
-Note that `IBaz` overrides eek::
-
-  >>> IBlat['eek'].__doc__
-  'eek blah blah'
-  >>> IBaz['eek'].__doc__
-  'eek in baz blah'
-
-We were careful to override eek in a compatible way.  When extending
-an interface, the extending interface should be compatible [#compat]_
-with the extended interfaces.
-
-We can ask whether one interface extends another::
-
-  >>> IBaz.extends(IFoo)
-  True
-  >>> IBlat.extends(IFoo)
-  False
-
-Note that interfaces don't extend themselves::
-
-  >>> IBaz.extends(IBaz)
-  False
-
-Sometimes we wish they did, but we can, instead use `isOrExtends`::
-
-  >>> IBaz.isOrExtends(IBaz)
-  True
-  >>> IBaz.isOrExtends(IFoo)
-  True
-  >>> IFoo.isOrExtends(IBaz)
-  False
-
-When we iterate over an interface, we get all of the names it defines,
-including names defined by base interfaces. Sometimes, we want *just*
-the names defined by the interface directly. We bane use the `names`
-method for that::
-
-  >>> list(IBaz.names())
-  ['eek']
-
-Inheritance of attribute specifications
----------------------------------------
-
-An interface may override attribute definitions from base interfaces.
-If two base interfaces define the same attribute, the attribute is
-inherited from the most specific interface. For example, with::
-
-  >>> class IBase(zope.interface.Interface):
-  ...
-  ...     def foo():
-  ...         "base foo doc"
-
-  >>> class IBase1(IBase):
-  ...     pass
-
-  >>> class IBase2(IBase):
-  ...
-  ...     def foo():
-  ...         "base2 foo doc"
-
-  >>> class ISub(IBase1, IBase2):
-  ...     pass
-
-ISub's definition of foo is the one from IBase2, since IBase2 is more
-specific that IBase::
-
-  >>> ISub['foo'].__doc__
-  'base2 foo doc'
-
-Note that this differs from a depth-first search.
-
-Sometimes, it's useful to ask whether an interface defines an
-attribute directly.  You can use the direct method to get a directly
-defined definitions::
-
-  >>> IBase.direct('foo').__doc__
-  'base foo doc'
-
-  >>> ISub.direct('foo')
-
-Specifications
---------------
-
-Interfaces and declarations are both special cases of specifications.
-What we described above for interface inheritance applies to both
-declarations and specifications.  Declarations actually extend the
-interfaces that they declare::
-
-  >>> class Baz(object):
-  ...     zope.interface.implements(IBaz)
-
-  >>> baz_implements = zope.interface.implementedBy(Baz)
-  >>> baz_implements.__bases__
-  (<InterfaceClass __main__.IBaz>, <implementedBy ...object>)
-
-  >>> baz_implements.extends(IFoo)
-  True
-
-  >>> baz_implements.isOrExtends(IFoo)
-  True
-  >>> baz_implements.isOrExtends(baz_implements)
-  True
-
-Specifications (interfaces and declarations) provide an `__sro__`
-that lists the specification and all of it's ancestors::
-
-  >>> baz_implements.__sro__
-  (<implementedBy __main__.Baz>,
-   <InterfaceClass __main__.IBaz>,
-   <InterfaceClass __main__.IFoo>,
-   <InterfaceClass __main__.IBlat>,
-   <InterfaceClass zope.interface.Interface>,
-   <implementedBy ...object>)
-
-
-Tagged Values
-=============
-
-Interfaces and attribute descriptions support an extension mechanism,
-borrowed from UML, called "tagged values" that lets us store extra
-data::
-
-  >>> IFoo.setTaggedValue('date-modified', '2004-04-01')
-  >>> IFoo.setTaggedValue('author', 'Jim Fulton')
-  >>> IFoo.getTaggedValue('date-modified')
-  '2004-04-01'
-  >>> IFoo.queryTaggedValue('date-modified')
-  '2004-04-01'
-  >>> IFoo.queryTaggedValue('datemodified')
-  >>> tags = list(IFoo.getTaggedValueTags())
-  >>> tags.sort()
-  >>> tags
-  ['author', 'date-modified']
-
-Function attributes are converted to tagged values when method
-attribute definitions are created::
-
-  >>> class IBazFactory(zope.interface.Interface):
-  ...     def __call__():
-  ...         "create one"
-  ...     __call__.return_type = IBaz
-
-  >>> IBazFactory['__call__'].getTaggedValue('return_type')
-  <InterfaceClass __main__.IBaz>
-
-Tagged values can also be defined from within an interface definition::
-
-  >>> class IWithTaggedValues(zope.interface.Interface):
-  ...     zope.interface.taggedValue('squish', 'squash')
-  >>> IWithTaggedValues.getTaggedValue('squish')
-  'squash'
-
-Invariants
-==========
-
-Interfaces can express conditions that must hold for objects that
-provide them. These conditions are expressed using one or more
-invariants.  Invariants are callable objects that will be called with
-an object that provides an interface. An invariant raises an `Invalid`
-exception if the condition doesn't hold.  Here's an example::
-
-  >>> class RangeError(zope.interface.Invalid):
-  ...     """A range has invalid limits"""
-  ...     def __repr__(self):
-  ...         return "RangeError(%r)" % self.args
-
-  >>> def range_invariant(ob):
-  ...     if ob.max < ob.min:
-  ...         raise RangeError(ob)
-
-Given this invariant, we can use it in an interface definition::
-
-  >>> class IRange(zope.interface.Interface):
-  ...     min = zope.interface.Attribute("Lower bound")
-  ...     max = zope.interface.Attribute("Upper bound")
-  ...
-  ...     zope.interface.invariant(range_invariant)
-
-Interfaces have a method for checking their invariants::
-
-  >>> class Range(object):
-  ...     zope.interface.implements(IRange)
-  ...
-  ...     def __init__(self, min, max):
-  ...         self.min, self.max = min, max
-  ...
-  ...     def __repr__(self):
-  ...         return "Range(%s, %s)" % (self.min, self.max)
-
-  >>> IRange.validateInvariants(Range(1,2))
-  >>> IRange.validateInvariants(Range(1,1))
-  >>> IRange.validateInvariants(Range(2,1))
-  Traceback (most recent call last):
-  ...
-  RangeError: Range(2, 1)
-
-If you have multiple invariants, you may not want to stop checking
-after the first error.  If you pass a list to `validateInvariants`,
-then a single `Invalid` exception will be raised with the list of
-exceptions as it's argument::
-
-  >>> from zope.interface.exceptions import Invalid
-  >>> errors = []
-  >>> try:
-  ...     IRange.validateInvariants(Range(2,1), errors)
-  ... except Invalid, e:
-  ...     str(e)
-  '[RangeError(Range(2, 1))]'
-  
-And the list will be filled with the individual exceptions::
-
-  >>> errors
-  [RangeError(Range(2, 1))]
-
-
-  >>> del errors[:]
-
-Adaptation
-==========
-
-Interfaces can be called to perform adaptation.
-
-The semantics are based on those of the PEP 246 adapt function.
-
-If an object cannot be adapted, then a TypeError is raised::
-
-  >>> class I(zope.interface.Interface):
-  ...     pass
-
-  >>> I(0)
-  Traceback (most recent call last):
-  ...
-  TypeError: ('Could not adapt', 0, <InterfaceClass __main__.I>)
-
-
-
-unless an alternate value is provided as a second positional argument::
-
-  >>> I(0, 'bob')
-  'bob'
-
-If an object already implements the interface, then it will be returned::
-
-  >>> class C(object):
-  ...     zope.interface.implements(I)
-
-  >>> obj = C()
-  >>> I(obj) is obj
-  True
-
-If an object implements __conform__, then it will be used::
-
-  >>> class C(object):
-  ...     zope.interface.implements(I)
-  ...     def __conform__(self, proto):
-  ...          return 0
-
-  >>> I(C())
-  0
-
-Adapter hooks (see __adapt__) will also be used, if present::
-
-  >>> from zope.interface.interface import adapter_hooks
-  >>> def adapt_0_to_42(iface, obj):
-  ...     if obj == 0:
-  ...         return 42
-
-  >>> adapter_hooks.append(adapt_0_to_42)
-  >>> I(0)
-  42
-
-  >>> adapter_hooks.remove(adapt_0_to_42)
-  >>> I(0)
-  Traceback (most recent call last):
-  ...
-  TypeError: ('Could not adapt', 0, <InterfaceClass __main__.I>)
-
-__adapt__
----------
-
-  >>> class I(zope.interface.Interface):
-  ...     pass
-
-Interfaces implement the PEP 246 __adapt__ method.
-
-This method is normally not called directly. It is called by the PEP
-246 adapt framework and by the interface __call__ operator.
-
-The adapt method is responsible for adapting an object to the
-reciever.
-
-The default version returns None::
-
-  >>> I.__adapt__(0)
-
-unless the object given provides the interface::
-
-  >>> class C(object):
-  ...     zope.interface.implements(I)
-
-  >>> obj = C()
-  >>> I.__adapt__(obj) is obj
-  True
-
-Adapter hooks can be provided (or removed) to provide custom
-adaptation. We'll install a silly hook that adapts 0 to 42.
-We install a hook by simply adding it to the adapter_hooks
-list::
-
-  >>> from zope.interface.interface import adapter_hooks
-  >>> def adapt_0_to_42(iface, obj):
-  ...     if obj == 0:
-  ...         return 42
-
-  >>> adapter_hooks.append(adapt_0_to_42)
-  >>> I.__adapt__(0)
-  42
-
-Hooks must either return an adapter, or None if no adapter can
-be found.
-
-Hooks can be uninstalled by removing them from the list::
-
-  >>> adapter_hooks.remove(adapt_0_to_42)
-  >>> I.__adapt__(0)
-
-
-.. [#create] The main reason we subclass `Interface` is to cause the
-             Python class statement to create an interface, rather
-             than a class.
-
-             It's possible to create interfaces by calling a special
-             interface class directly.  Doing this, it's possible
-             (and, on rare occasions, useful) to create interfaces
-             that don't descend from `Interface`.  Using this
-             technique is beyond the scope of this document.
-
-.. [#factory] Classes are factories.  They can be called to create
-              their instances.  We expect that we will eventually
-              extend the concept of implementation to other kinds of
-              factories, so that we can declare the interfaces
-              provided by the objects created.
-
-.. [#compat] The goal is substitutability.  An object that provides an
-             extending interface should be substitutable for an object
-             that provides the extended interface.  In our example, an
-             object that provides IBaz should be usable whereever an
-             object that provides IBlat is expected.
-
-             The interface implementation doesn't enforce this.
-             but maybe it should do some checks.

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/__init__.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/__init__.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/__init__.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -50,23 +50,33 @@
 """
 __docformat__ = 'restructuredtext'
 
-from zope.interface.interface import Interface, _wire
+from zope.interface.interface import Interface
+from zope.interface.interface import _wire
 
 # Need to actually get the interface elements to implement the right interfaces
 _wire()
 del _wire
 
-from zope.interface.interface import Attribute, invariant, taggedValue
-
-from zope.interface.declarations import providedBy, implementedBy
-from zope.interface.declarations import classImplements, classImplementsOnly
-from zope.interface.declarations import directlyProvidedBy, directlyProvides
-from zope.interface.declarations import alsoProvides, provider
-from zope.interface.declarations import implementer, implementer_only
-from zope.interface.declarations import implements, implementsOnly
-from zope.interface.declarations import classProvides, moduleProvides
-from zope.interface.declarations import noLongerProvides, Declaration
+from zope.interface.declarations import Declaration
+from zope.interface.declarations import alsoProvides
+from zope.interface.declarations import classImplements
+from zope.interface.declarations import classImplementsOnly
+from zope.interface.declarations import classProvides
+from zope.interface.declarations import directlyProvidedBy
+from zope.interface.declarations import directlyProvides
+from zope.interface.declarations import implementedBy
+from zope.interface.declarations import implementer
+from zope.interface.declarations import implementer_only
+from zope.interface.declarations import implements
+from zope.interface.declarations import implementsOnly
+from zope.interface.declarations import moduleProvides
+from zope.interface.declarations import noLongerProvides
+from zope.interface.declarations import providedBy
+from zope.interface.declarations import provider
 from zope.interface.exceptions import Invalid
+from zope.interface.interface import Attribute
+from zope.interface.interface import invariant
+from zope.interface.interface import taggedValue
 
 # The following are to make spec pickles cleaner
 from zope.interface.declarations import Provides

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/_zope_interface_coptimizations.c
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/_zope_interface_coptimizations.c	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/_zope_interface_coptimizations.c	2012-03-26 20:56:58 UTC (rev 124742)
@@ -979,7 +979,13 @@
       Py_DECREF(tup);
     }
   else
-    Py_INCREF(result);
+    {
+      if (result == Py_None && default_ != NULL)
+        {
+          result = default_;
+        }
+      Py_INCREF(result);
+    }
 
   return result;
 }

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -13,11 +13,12 @@
 ##############################################################################
 """Adapter management
 """
-
 import weakref
-from zope.interface import providedBy, Interface, ro
 
-_marker = object
+from zope.interface import providedBy
+from zope.interface import Interface
+from zope.interface import ro
+
 class BaseAdapterRegistry(object):
 
     # List of methods copied from lookup sub-objects:
@@ -62,7 +63,7 @@
         #   Invalidating registries have caches that are invalidated
         #     when they or their base registies change.  An invalidating
         #     registry can only have invalidating registries as bases.
-        #     See LookupBasePy below for the pertinent logic.
+        #     See LookupBaseFallback below for the pertinent logic.
 
         #   Verifying registies can't rely on getting invalidation messages,
         #     so have to check the generations of base registries to determine
@@ -245,7 +246,8 @@
 
         old = components.get(u'')
         if not old:
-            return
+            # this is belt-and-suspenders against the failure of cleanup below
+            return  #pragma NO COVERAGE 
 
         if value is None:
             new = ()
@@ -285,14 +287,14 @@
 
     # XXX hack to fake out twisted's use of a private api.  We need to get them
     # to use the new registed method.
-    def get(self, _):
+    def get(self, _): #pragma NO COVER
         class XXXTwistedFakeOut:
             selfImplied = {}
         return XXXTwistedFakeOut
 
 
 _not_in_mapping = object()
-class LookupBasePy(object):
+class LookupBaseFallback(object):
 
     def __init__(self):
         self._cache = {}
@@ -393,12 +395,22 @@
 
         return result
 
-LookupBase = LookupBasePy
+LookupBasePy = LookupBaseFallback # BBB
 
-class VerifyingBasePy(LookupBasePy):
+try:
+    from _zope_interface_coptimizations import LookupBase
+except ImportError: #pragma NO COVER
+    LookupBase = LookupBaseFallback
 
+
+class VerifyingBaseFallback(LookupBaseFallback):
+    # Mixin for lookups against registries which "chain" upwards, and
+    # whose lookups invalidate their own caches whenever a parent registry
+    # bumps its own '_generation' counter.  E.g., used by 
+    # zope.component.persistentregistry
+
     def changed(self, originally_changed):
-        LookupBasePy.changed(self, originally_changed)
+        LookupBaseFallback.changed(self, originally_changed)
         self._verify_ro = self._registry.ro[1:]
         self._verify_generations = [r._generation for r in self._verify_ro]
 
@@ -409,26 +421,24 @@
 
     def _getcache(self, provided, name):
         self._verify()
-        return LookupBasePy._getcache(self, provided, name)
+        return LookupBaseFallback._getcache(self, provided, name)
 
     def lookupAll(self, required, provided):
         self._verify()
-        return LookupBasePy.lookupAll(self, required, provided)
+        return LookupBaseFallback.lookupAll(self, required, provided)
 
     def subscriptions(self, required, provided):
         self._verify()
-        return LookupBasePy.subscriptions(self, required, provided)
+        return LookupBaseFallback.subscriptions(self, required, provided)
 
-VerifyingBase = VerifyingBasePy
+VerifyingBasePy = VerifyingBaseFallback #BBB
 
-
 try:
-    import _zope_interface_coptimizations
-except ImportError:
-    pass
-else:
-    from _zope_interface_coptimizations import LookupBase, VerifyingBase
+    from _zope_interface_coptimizations import VerifyingBase
+except ImportError: #pragma NO COVER
+    VerifyingBase = VerifyingBaseFallback
 
+
 class AdapterLookupBase(object):
 
     def __init__(self, registry):

Deleted: zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.ru.txt
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.ru.txt	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.ru.txt	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,540 +0,0 @@
-================
-Реестр адаптеров
-================
-
-.. contents::
-
-Реестры адаптеров предоставляют возможность для регистрации объектов которые
-зависят от одной, или нескольких спецификаций интерфейсов и предоставляют
-(возможно не напрямую) какой-либо интерфейс. В дополнение, регистрации имеют
-имена. (Можно думать об именах как о спецификаторах предоставляемого
-интерфейса.)
-
-Термин "спецификация интерфейса" ссылается и на интерфейсы и на определения
-интерфейсов, такие как определения интерфейсов реализованных некоторым классом.
-
-Одиночные адаптеры
-==================
-
-Давайте рассмотрим простой пример использующий единственную требуемую
-спецификацию::
-
-  >>> from zope.interface.adapter import AdapterRegistry
-  >>> import zope.interface
-
-  >>> class IR1(zope.interface.Interface):
-  ...     pass
-  >>> class IP1(zope.interface.Interface):
-  ...     pass
-  >>> class IP2(IP1):
-  ...     pass
-
-  >>> registry = AdapterRegistry()
-
-Мы зарегистрируем объект который зависит от IR1 и "предоставляет" IP2::
-
-  >>> registry.register([IR1], IP2, '', 12)
-
-После регистрации мы можем запросить объект снова::
-
-  >>> registry.lookup([IR1], IP2, '')
-  12
-
-Заметьте, что мы используем целое в этом примере. В реальных приложениях вы
-можете использовать объекты которые на самом деле зависят или предоставляют
-интерфейсы. Реестр не заботиться о том, что регистрируется и таким образом мы
-можем использовать целые, или строки что бы упростить наши примеры. Здесь есть
-одно исключение. Регистрация значения None удаляет регистрацию для любого
-зарегистрированного прежде значения.
-
-Если объект зависит от спецификации он может быть запрошен с помощью
-спецификации которая расширяет спецификацию от которой он зависит::
-
-  >>> class IR2(IR1):
-  ...     pass
-  >>> registry.lookup([IR2], IP2, '')
-  12
-
-Мы можем использовать класс реализующий спецификацию для запроса объекта::
-
-  >>> class C2:
-  ...     zope.interface.implements(IR2)
-
-  >>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
-  12
-
-и объект может быть запрошен для интерфейсов которые предоставляемый объектом
-интерфейс расширяет::
-
-  >>> registry.lookup([IR1], IP1, '')
-  12
-  >>> registry.lookup([IR2], IP1, '')
-  12
-
-Но если вы требуете спецификацию которая не расширяет спецификацию от которой
-зависит объект, вы не получите ничего::
-
-  >>> registry.lookup([zope.interface.Interface], IP1, '')
-
-Между прочим, вы можете передать значение по умолчанию при запросе::
-
-  >>> registry.lookup([zope.interface.Interface], IP1, '', 42)
-  42
-
-Если вы пробуете получить интерфейс который объект не предоставляет вы также
-не получите ничего::
-
-  >>> class IP3(IP2):
-  ...     pass
-  >>> registry.lookup([IR1], IP3, '')
-
-Вы также не получите ничего если вы используете неверное имя::
-
-  >>> registry.lookup([IR1], IP1, 'bob')
-  >>> registry.register([IR1], IP2, 'bob', "Bob's 12")
-  >>> registry.lookup([IR1], IP1, 'bob')
-  "Bob's 12"
-
-Вы можете не использовать имя при запросе::
-
-  >>> registry.lookup([IR1], IP1)
-  12
-
-Если мы регистрируем объект который предоставляет IP1::
-
-  >>> registry.register([IR1], IP1, '', 11)
-
-тогда этот объект будет иметь преимущество перед O(12)::
-
-  >>> registry.lookup([IR1], IP1, '')
-  11
-
-Также, если мы регистрируем объект для IR2 тогда он будет иметь преимущество
-когда используется IR2::
-
-  >>> registry.register([IR2], IP1, '', 21)
-  >>> registry.lookup([IR2], IP1, '')
-  21
-
-Поиск того, что (если вообще что-то) зарегистрировано
------------------------------------------------------
-
-Мы можем спросить есть-ли адаптер зарегистрированный для набора интерфейсов.
-Это отличается от обычного запроса так как здесь мы ищем точное совпадение::
-
-  >>> print registry.registered([IR1], IP1)
-  11
-
-  >>> print registry.registered([IR1], IP2)
-  12
-
-  >>> print registry.registered([IR1], IP2, 'bob')
-  Bob's 12
-  
-
-  >>> print registry.registered([IR2], IP1)
-  21
-
-  >>> print registry.registered([IR2], IP2)
-  None
-
-В последнем примере, None был возвращен потому, что для данного интерфейса
-ничего не было зарегистрировано.
-
-lookup1
--------
-
-Запрос одиночного адаптера - это наиболее частая операция и для нее есть
-специализированная версия запроса которая получает на вход единственный
-требуемый интерфейс::
-
-  >>> registry.lookup1(IR2, IP1, '')
-  21
-  >>> registry.lookup1(IR2, IP1)
-  21
-
-Адаптация на практике
----------------------
-
-Реестр адаптеров предназначен для поддержки адаптации когда один объект
-реализующий интерфейс адаптируется к другому объекту который поддерживает
-другой интерфейс. Реестр адаптеров также поддерживает вычисление адаптеров. В
-этом случае мы должны регистрировать фабрики для адаптеров::
-
-   >>> class IR(zope.interface.Interface):
-   ...     pass
-
-   >>> class X:
-   ...     zope.interface.implements(IR)
-           
-   >>> class Y:
-   ...     zope.interface.implements(IP1)
-   ...     def __init__(self, context):
-   ...         self.context = context
-
-  >>> registry.register([IR], IP1, '', Y)
-
-В этом случае мы регистрируем класс как фабрику. Теперь мы можем вызвать
-`queryAdapter` для получения адаптированного объекта::
-
-  >>> x = X()
-  >>> y = registry.queryAdapter(x, IP1)
-  >>> y.__class__.__name__
-  'Y'
-  >>> y.context is x
-  True
-
-Мы также можем регистрировать и запрашивать по имени::
-
-  >>> class Y2(Y):
-  ...     pass
-
-  >>> registry.register([IR], IP1, 'bob', Y2)
-  >>> y = registry.queryAdapter(x, IP1, 'bob')
-  >>> y.__class__.__name__
-  'Y2'
-  >>> y.context is x
-  True
-
-Когда фабрика для адаптера возвращает `None` - это рассматривается как если бы
-адаптер не был найден. Это позволяет нам избежать адаптации (по желанию) и дает
-возможность фабрике адаптера определить возможна ли адаптация основываясь на
-состоянии объекта который адаптируется::
-
-  >>> def factory(context):
-  ...     if context.name == 'object':
-  ...         return 'adapter'
-  ...     return None
-
-  >>> class Object(object):
-  ...     zope.interface.implements(IR)
-  ...     name = 'object'
-
-  >>> registry.register([IR], IP1, 'conditional', factory) 
-  >>> obj = Object()
-  >>> registry.queryAdapter(obj, IP1, 'conditional')
-  'adapter'
-  >>> obj.name = 'no object'
-  >>> registry.queryAdapter(obj, IP1, 'conditional') is None
-  True
-  >>> registry.queryAdapter(obj, IP1, 'conditional', 'default')
-  'default'
-
-Альтернативный метод для предоставления такой же функциональности как и
-`queryAdapter()` - это `adapter_hook()`::
-
-  >>> y = registry.adapter_hook(IP1, x)
-  >>> y.__class__.__name__
-  'Y'
-  >>> y.context is x
-  True
-  >>> y = registry.adapter_hook(IP1, x, 'bob')
-  >>> y.__class__.__name__
-  'Y2'
-  >>> y.context is x
-  True
-
-`adapter_hook()` просто меняет порядок аргументов для объекта и интерфейса. Это
-используется для встраивания в механизм вызовов интерфейсов.
-
-Адаптеры по умолчанию
----------------------
-
-Иногда вы можете захотеть предоставить адаптер который не будет ничего
-адаптировать. Для этого нужно передать None как требуемый интерфейс::
-
-  >>> registry.register([None], IP1, '', 1)
-
-после этого вы можете использовать этот адаптер для интерфейсов для которых у
-вас нет конкретного адаптера::
-
-  >>> class IQ(zope.interface.Interface):
-  ...     pass
-  >>> registry.lookup([IQ], IP1, '')
-  1
-
-Конечно, конкретные адаптеры все еще используются когда необходимо::
-
-  >>> registry.lookup([IR2], IP1, '')
-  21
-
-Адаптеры классов
-----------------
-
-Вы можете регистрировать адаптеры для определений классов, что будет похоже на
-регистрацию их для классов::
-
-  >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
-  >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
-  'C21'
-
-Адаптеры для словарей
----------------------
-
-В какой-то момент было невозможно регистрировать адаптеры основанные на
-словарях из-за ошибки. Давайте удостоверимся что это теперь работает::
-
-  >>> adapter = {}
-  >>> registry.register((), IQ, '', adapter)
-  >>> registry.lookup((), IQ, '') is adapter
-  True
-
-Удаление регистрации
---------------------
-
-Вы можете удалить регистрацию регистрируя None вместо объекта::
-
-  >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
-  >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
-  21
-
-Конечно это значит, что None не может быть зарегистрирован. Это исключение к
-утверждению выше о том, что реестр не заботиться о том, что регистрируется.
-
-Мульти-адаптеры
-===============
-
-Вы можете адаптировать несколько спецификаций::
-
-  >>> registry.register([IR1, IQ], IP2, '', '1q2')
-  >>> registry.lookup([IR1, IQ], IP2, '')
-  '1q2'
-  >>> registry.lookup([IR2, IQ], IP1, '')
-  '1q2'
-
-  >>> class IS(zope.interface.Interface):
-  ...     pass
-  >>> registry.lookup([IR2, IS], IP1, '')
-
-  >>> class IQ2(IQ):
-  ...     pass
-
-  >>> registry.lookup([IR2, IQ2], IP1, '')
-  '1q2'
-
-  >>> registry.register([IR1, IQ2], IP2, '', '1q22')
-  >>> registry.lookup([IR2, IQ2], IP1, '')
-  '1q22'
-
-Мульти-адаптация
-----------------
-
-Вы можете адаптировать несколько объектов::
-
-  >>> class Q:
-  ...     zope.interface.implements(IQ)
-
-Как и с одиночными адаптерами, мы регистрируем фабрику которая возвращает
-класс::
-
-  >>> class IM(zope.interface.Interface):
-  ...     pass
-  >>> class M:
-  ...     zope.interface.implements(IM)
-  ...     def __init__(self, x, q):
-  ...         self.x, self.q = x, q
-  >>> registry.register([IR, IQ], IM, '', M)
-
-И затем мы можем вызвать `queryMultiAdapter` для вычисления адаптера::
-
-  >>> q = Q()
-  >>> m = registry.queryMultiAdapter((x, q), IM)
-  >>> m.__class__.__name__
-  'M'
-  >>> m.x is x and m.q is q
-  True
-
-и, конечно, мы можем использовать имена::
-
-  >>> class M2(M):
-  ...     pass
-  >>> registry.register([IR, IQ], IM, 'bob', M2)
-  >>> m = registry.queryMultiAdapter((x, q), IM, 'bob')
-  >>> m.__class__.__name__
-  'M2'
-  >>> m.x is x and m.q is q
-  True
-
-Адаптеры по умолчанию
----------------------
-
-Как и для одиночных адаптеров вы можете определить адаптер по умолчанию передав
-None вместо *первой* спецификации::
-
-  >>> registry.register([None, IQ], IP2, '', 'q2')
-  >>> registry.lookup([IS, IQ], IP2, '')
-  'q2'
-
-Нулевые адаптеры
-================
-
-Вы можете также адаптировать без спецификации::
-
-  >>> registry.register([], IP2, '', 2)
-  >>> registry.lookup([], IP2, '')
-  2
-  >>> registry.lookup([], IP1, '')
-  2
-
-Перечисление именованных адаптеров
-----------------------------------
-
-Адаптеры имеют имена. Иногда это полезно для получения всех именованных
-адаптеров для заданного интерфейса::
-
-  >>> adapters = list(registry.lookupAll([IR1], IP1))
-  >>> adapters.sort()
-  >>> assert adapters == [(u'', 11), (u'bob', "Bob's 12")]
-
-Это работает также и для мульти-адаптеров::
-
-  >>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
-  >>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
-  >>> adapters.sort()
-  >>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]
-
-И даже для нулевых адаптеров::
-
-  >>> registry.register([], IP2, 'bob', 3)
-  >>> adapters = list(registry.lookupAll([], IP1))
-  >>> adapters.sort()
-  >>> assert adapters == [(u'', 2), (u'bob', 3)]
-
-Подписки
-========
-
-Обычно мы хотим запросить объект который наиболее близко соответствует
-спецификации. Иногда мы хотим получить все объекты которые соответствуют
-какой-либо спецификации. Мы используем подписки для этого. Мы подписываем
-объекты для спецификаций и затем позже находим все подписанные объекты::
-
-  >>> registry.subscribe([IR1], IP2, 'sub12 1')
-  >>> registry.subscriptions([IR1], IP2)
-  ['sub12 1']
-
-Заметьте, что в отличие от обычных адаптеров подписки не имеют имен.
-
-Вы можете иметь несколько подписчиков для одной спецификации::
-
-  >>> registry.subscribe([IR1], IP2, 'sub12 2')
-  >>> registry.subscriptions([IR1], IP2)
-  ['sub12 1', 'sub12 2']
-
-Если подписчики зарегистрированы для одних и тех же требуемых интерфейсов, они
-возвращаются в порядке определения.
-
-Вы можете зарегистрировать подписчики для всех спецификаций используя None::
-
-  >>> registry.subscribe([None], IP1, 'sub_1')
-  >>> registry.subscriptions([IR2], IP1)
-  ['sub_1', 'sub12 1', 'sub12 2']
-
-Заметьте, что новый подписчик возвращается первым. Подписчики определенные
-для менее общих требуемых интерфейсов возвращаются перед подписчиками
-для более общих интерфейсов.
-
-Подписки могут смешиваться между несколькими совместимыми спецификациями::
-
-  >>> registry.subscriptions([IR2], IP1)
-  ['sub_1', 'sub12 1', 'sub12 2']
-  >>> registry.subscribe([IR1], IP1, 'sub11')
-  >>> registry.subscriptions([IR2], IP1)
-  ['sub_1', 'sub12 1', 'sub12 2', 'sub11']
-  >>> registry.subscribe([IR2], IP2, 'sub22')
-  >>> registry.subscriptions([IR2], IP1)
-  ['sub_1', 'sub12 1', 'sub12 2', 'sub11', 'sub22']
-  >>> registry.subscriptions([IR2], IP2)
-  ['sub12 1', 'sub12 2', 'sub22']
-
-Подписки могут существовать для нескольких спецификаций::
-
-  >>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
-  >>> registry.subscriptions([IR1, IQ], IP2)
-  ['sub1q2']
-
-Как и с одиночными подписчиками и адаптерами без подписок, вы можете определить
-None для первого требуемого интерфейса, что бы задать значение по умолчанию::
-
-  >>> registry.subscribe([None, IQ], IP2, 'sub_q2')
-  >>> registry.subscriptions([IS, IQ], IP2)
-  ['sub_q2']
-  >>> registry.subscriptions([IR1, IQ], IP2)
-  ['sub_q2', 'sub1q2']
-
-Вы можете создать подписки которые независимы от любых спецификаций::
-
-  >>> list(registry.subscriptions([], IP1))
-  []
-
-  >>> registry.subscribe([], IP2, 'sub2')
-  >>> registry.subscriptions([], IP1)
-  ['sub2']
-  >>> registry.subscribe([], IP1, 'sub1')
-  >>> registry.subscriptions([], IP1)
-  ['sub2', 'sub1']
-  >>> registry.subscriptions([], IP2)
-  ['sub2']
-
-Удаление регистрации подписчиков
---------------------------------
-
-Мы можем удалять регистрацию подписчиков. При удалении регистрации подписчика
-мы можем удалить регистрацию заданного адаптера::
-
-  >>> registry.unsubscribe([IR1], IP1, 'sub11')
-  >>> registry.subscriptions([IR1], IP1)
-  ['sub_1', 'sub12 1', 'sub12 2']
-
-Если мы не задаем никакого значения тогда подписки будут удалены для всех
-подписчиков совпадающих с заданным интерфейсом::
-
-  >>> registry.unsubscribe([IR1], IP2)
-  >>> registry.subscriptions([IR1], IP1)
-  ['sub_1']
-
-Адаптеры подписки
------------------
-
-Обычно мы регистрируем фабрики для адаптеров которые затем позволяют нам
-вычислять адаптеры, но с подписками мы получаем несколько адаптеров. Это пример
-подписчика для нескольких объектов::
-
-  >>> registry.subscribe([IR, IQ], IM, M)
-  >>> registry.subscribe([IR, IQ], IM, M2)
-
-  >>> subscribers = registry.subscribers((x, q), IM)
-  >>> len(subscribers)
-  2
-  >>> class_names = [s.__class__.__name__ for s in subscribers]
-  >>> class_names.sort()
-  >>> class_names
-  ['M', 'M2']
-  >>> [(s.x is x and s.q is q) for s in subscribers]
-  [True, True]
-
-подписчики фабрик адаптеров не могут возвращать None::
-
-  >>> def M3(x, y):
-  ...     return None
-
-  >>> registry.subscribe([IR, IQ], IM, M3)
-  >>> subscribers = registry.subscribers((x, q), IM)
-  >>> len(subscribers)
-  2
-
-Обработчики
------------
-
-Обработчик - это подписанная фабрика которая не возвращает нормального
-значения. Она возвращает None. Обработчик отличается от адаптеров тем, что он
-делает всю работу когда вызывается фабрика.
-
-Для регистрации обработчика надо просто передать None как предоставляемый
-интерфейс::
-
-  >>> def handler(event):
-  ...     print 'handler', event
-
-  >>> registry.subscribe([IR1], None, handler)
-  >>> registry.subscriptions([IR1], None) == [handler]
-  True

Deleted: zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.txt
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.txt	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/adapter.txt	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,543 +0,0 @@
-================
-Adapter Registry
-================
-
-Adapter registries provide a way to register objects that depend on
-one or more interface specifications and provide (perhaps indirectly)
-some interface.  In addition, the registrations have names. (You can
-think of the names as qualifiers of the provided interfaces.)
-
-The term "interface specification" refers both to interfaces and to
-interface declarations, such as declarations of interfaces implemented
-by a class.
-
-
-Single Adapters
-===============
-
-Let's look at a simple example, using a single required specification::
-
-  >>> from zope.interface.adapter import AdapterRegistry
-  >>> import zope.interface
-
-  >>> class IR1(zope.interface.Interface):
-  ...     pass
-  >>> class IP1(zope.interface.Interface):
-  ...     pass
-  >>> class IP2(IP1):
-  ...     pass
-
-  >>> registry = AdapterRegistry()
-
-We'll register an object that depends on IR1 and "provides" IP2::
-
-  >>> registry.register([IR1], IP2, '', 12)
-
-Given the registration, we can look it up again::
-
-  >>> registry.lookup([IR1], IP2, '')
-  12
-
-Note that we used an integer in the example.  In real applications,
-one would use some objects that actually depend on or provide
-interfaces. The registry doesn't care about what gets registered, so
-we'll use integers and strings to keep the examples simple. There is
-one exception.  Registering a value of None unregisters any
-previously-registered value.
-
-If an object depends on a specification, it can be looked up with a
-specification that extends the specification that it depends on::
-
-  >>> class IR2(IR1):
-  ...     pass
-  >>> registry.lookup([IR2], IP2, '')
-  12
-
-We can use a class implementation specification to look up the object::
-
-  >>> class C2:
-  ...     zope.interface.implements(IR2)
-
-  >>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
-  12
-
-
-and it can be looked up for interfaces that its provided interface
-extends::
-
-  >>> registry.lookup([IR1], IP1, '')
-  12
-  >>> registry.lookup([IR2], IP1, '')
-  12
-
-But if you require a specification that doesn't extend the specification the
-object depends on, you won't get anything::
-
-  >>> registry.lookup([zope.interface.Interface], IP1, '')
-
-By the way, you can pass a default value to lookup::
-
-  >>> registry.lookup([zope.interface.Interface], IP1, '', 42)
-  42
-
-If you try to get an interface the object doesn't provide, you also
-won't get anything::
-
-  >>> class IP3(IP2):
-  ...     pass
-  >>> registry.lookup([IR1], IP3, '')
-
-You also won't get anything if you use the wrong name::
-
-  >>> registry.lookup([IR1], IP1, 'bob')
-  >>> registry.register([IR1], IP2, 'bob', "Bob's 12")
-  >>> registry.lookup([IR1], IP1, 'bob')
-  "Bob's 12"
-
-You can leave the name off when doing a lookup::
-
-  >>> registry.lookup([IR1], IP1)
-  12
-
-If we register an object that provides IP1::
-
-  >>> registry.register([IR1], IP1, '', 11)
-
-then that object will be prefered over O(12)::
-
-  >>> registry.lookup([IR1], IP1, '')
-  11
-
-Also, if we register an object for IR2, then that will be prefered
-when using IR2::
-
-  >>> registry.register([IR2], IP1, '', 21)
-  >>> registry.lookup([IR2], IP1, '')
-  21
-
-Finding out what, if anything, is registered
---------------------------------------------
-
-We can ask if there is an adapter registered for a collection of
-interfaces. This is different than lookup, because it looks for an
-exact match.
-
-  >>> print registry.registered([IR1], IP1)
-  11
-
-  >>> print registry.registered([IR1], IP2)
-  12
-
-  >>> print registry.registered([IR1], IP2, 'bob')
-  Bob's 12
-  
-
-  >>> print registry.registered([IR2], IP1)
-  21
-
-  >>> print registry.registered([IR2], IP2)
-  None
-
-In the last example, None was returned because nothing was registered
-exactly for the given interfaces.
-
-lookup1
--------
-
-Lookup of single adapters is common enough that there is a specialized
-version of lookup that takes a single required interface::
-
-  >>> registry.lookup1(IR2, IP1, '')
-  21
-  >>> registry.lookup1(IR2, IP1)
-  21
-
-Actual Adaptation
------------------
-
-The adapter registry is intended to support adaptation, where one
-object that implements an interface is adapted to another object that
-supports a different interface.  The adapter registry supports the
-computation of adapters. In this case, we have to register adapter
-factories::
-
-   >>> class IR(zope.interface.Interface):
-   ...     pass
-
-   >>> class X:
-   ...     zope.interface.implements(IR)
-           
-   >>> class Y:
-   ...     zope.interface.implements(IP1)
-   ...     def __init__(self, context):
-   ...         self.context = context
-
-  >>> registry.register([IR], IP1, '', Y)
-
-In this case, we registered a class as the factory. Now we can call
-`queryAdapter` to get the adapted object::
-
-  >>> x = X()
-  >>> y = registry.queryAdapter(x, IP1)
-  >>> y.__class__.__name__
-  'Y'
-  >>> y.context is x
-  True
-
-We can register and lookup by name too::
-
-  >>> class Y2(Y):
-  ...     pass
-
-  >>> registry.register([IR], IP1, 'bob', Y2)
-  >>> y = registry.queryAdapter(x, IP1, 'bob')
-  >>> y.__class__.__name__
-  'Y2'
-  >>> y.context is x
-  True
-
-When the adapter factory produces `None`, then this is treated as if no
-adapter has been found. This allows us to prevent adaptation (when desired)
-and let the adapter factory determine whether adaptation is possible based on
-the state of the object being adapted.
-
-  >>> def factory(context):
-  ...     if context.name == 'object':
-  ...         return 'adapter'
-  ...     return None
-
-  >>> class Object(object):
-  ...     zope.interface.implements(IR)
-  ...     name = 'object'
-
-  >>> registry.register([IR], IP1, 'conditional', factory) 
-  >>> obj = Object()
-  >>> registry.queryAdapter(obj, IP1, 'conditional')
-  'adapter'
-  >>> obj.name = 'no object'
-  >>> registry.queryAdapter(obj, IP1, 'conditional') is None
-  True
-  >>> registry.queryAdapter(obj, IP1, 'conditional', 'default')
-  'default'
-
-An alternate method that provides the same function as `queryAdapter()` is
-`adapter_hook()`::
-
-  >>> y = registry.adapter_hook(IP1, x)
-  >>> y.__class__.__name__
-  'Y'
-  >>> y.context is x
-  True
-  >>> y = registry.adapter_hook(IP1, x, 'bob')
-  >>> y.__class__.__name__
-  'Y2'
-  >>> y.context is x
-  True
-
-The `adapter_hook()` simply switches the order of the object and
-interface arguments.  It is used to hook into the interface call
-mechanism.
-
-
-Default Adapters
-----------------
-  
-Sometimes, you want to provide an adapter that will adapt anything.
-For that, provide None as the required interface::
-
-  >>> registry.register([None], IP1, '', 1)
-  
-then we can use that adapter for interfaces we don't have specific
-adapters for::
-
-  >>> class IQ(zope.interface.Interface):
-  ...     pass
-  >>> registry.lookup([IQ], IP1, '')
-  1
-
-Of course, specific adapters are still used when applicable::
-
-  >>> registry.lookup([IR2], IP1, '')
-  21
-
-Class adapters
---------------
-
-You can register adapters for class declarations, which is almost the
-same as registering them for a class::
-
-  >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
-  >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
-  'C21'
-
-Dict adapters
--------------
-
-At some point it was impossible to register dictionary-based adapters due a
-bug. Let's make sure this works now:
-
-  >>> adapter = {}
-  >>> registry.register((), IQ, '', adapter)
-  >>> registry.lookup((), IQ, '') is adapter
-  True
-
-Unregistering
--------------
-
-You can unregister by registering None, rather than an object::
-
-  >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
-  >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
-  21
-
-Of course, this means that None can't be registered. This is an
-exception to the statement, made earlier, that the registry doesn't
-care what gets registered.
-
-Multi-adapters
-==============
-
-You can adapt multiple specifications::
-
-  >>> registry.register([IR1, IQ], IP2, '', '1q2')
-  >>> registry.lookup([IR1, IQ], IP2, '')
-  '1q2'
-  >>> registry.lookup([IR2, IQ], IP1, '')
-  '1q2'
-
-  >>> class IS(zope.interface.Interface):
-  ...     pass
-  >>> registry.lookup([IR2, IS], IP1, '')
-
-  >>> class IQ2(IQ):
-  ...     pass
-
-  >>> registry.lookup([IR2, IQ2], IP1, '')
-  '1q2'
-
-  >>> registry.register([IR1, IQ2], IP2, '', '1q22')
-  >>> registry.lookup([IR2, IQ2], IP1, '')
-  '1q22'
-
-Multi-adaptation
-----------------
-
-You can adapt multiple objects::
-
-  >>> class Q:
-  ...     zope.interface.implements(IQ)
-
-As with single adapters, we register a factory, which is often a class::
-
-  >>> class IM(zope.interface.Interface):
-  ...     pass
-  >>> class M:
-  ...     zope.interface.implements(IM)
-  ...     def __init__(self, x, q):
-  ...         self.x, self.q = x, q
-  >>> registry.register([IR, IQ], IM, '', M)
-
-And then we can call `queryMultiAdapter` to compute an adapter::
-
-  >>> q = Q()
-  >>> m = registry.queryMultiAdapter((x, q), IM)
-  >>> m.__class__.__name__
-  'M'
-  >>> m.x is x and m.q is q
-  True
-
-and, of course, we can use names::
-
-  >>> class M2(M):
-  ...     pass
-  >>> registry.register([IR, IQ], IM, 'bob', M2)
-  >>> m = registry.queryMultiAdapter((x, q), IM, 'bob')
-  >>> m.__class__.__name__
-  'M2'
-  >>> m.x is x and m.q is q
-  True
-  
-Default Adapters
-----------------
-
-As with single adapters, you can define default adapters by specifying
-None for the *first* specification::
-
-  >>> registry.register([None, IQ], IP2, '', 'q2')
-  >>> registry.lookup([IS, IQ], IP2, '')
-  'q2'
-
-Null Adapters
-=============
-
-You can also adapt no specification::
-
-  >>> registry.register([], IP2, '', 2)
-  >>> registry.lookup([], IP2, '')
-  2
-  >>> registry.lookup([], IP1, '')
-  2
-
-Listing named adapters
-----------------------
-
-Adapters are named. Sometimes, it's useful to get all of the named
-adapters for given interfaces::
-
-  >>> adapters = list(registry.lookupAll([IR1], IP1))
-  >>> adapters.sort()
-  >>> assert adapters == [(u'', 11), (u'bob', "Bob's 12")]
-
-This works for multi-adapters too::
-
-  >>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
-  >>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
-  >>> adapters.sort()
-  >>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]
-
-And even null adapters::
-
-  >>> registry.register([], IP2, 'bob', 3)
-  >>> adapters = list(registry.lookupAll([], IP1))
-  >>> adapters.sort()
-  >>> assert adapters == [(u'', 2), (u'bob', 3)]
-
-Subscriptions
-=============
-
-Normally, we want to look up an object that most-closely matches a
-specification.  Sometimes, we want to get all of the objects that
-match some specification.  We use subscriptions for this.  We
-subscribe objects against specifications and then later find all of
-the subscribed objects::
-
-  >>> registry.subscribe([IR1], IP2, 'sub12 1')
-  >>> registry.subscriptions([IR1], IP2)
-  ['sub12 1']
-
-Note that, unlike regular adapters, subscriptions are unnamed.
-
-You can have multiple subscribers for the same specification::
-
-  >>> registry.subscribe([IR1], IP2, 'sub12 2')
-  >>> registry.subscriptions([IR1], IP2)
-  ['sub12 1', 'sub12 2']
-
-If subscribers are registered for the same required interfaces, they
-are returned in the order of definition.
-
-You can register subscribers for all specifications using None::
-
-  >>> registry.subscribe([None], IP1, 'sub_1')
-  >>> registry.subscriptions([IR2], IP1)
-  ['sub_1', 'sub12 1', 'sub12 2']
-
-Note that the new subscriber is returned first.  Subscribers defined
-for less general required interfaces are returned before subscribers
-for more general interfaces.
-
-Subscriptions may be combined over multiple compatible specifications::
-
-  >>> registry.subscriptions([IR2], IP1)
-  ['sub_1', 'sub12 1', 'sub12 2']
-  >>> registry.subscribe([IR1], IP1, 'sub11')
-  >>> registry.subscriptions([IR2], IP1)
-  ['sub_1', 'sub12 1', 'sub12 2', 'sub11']
-  >>> registry.subscribe([IR2], IP2, 'sub22')
-  >>> registry.subscriptions([IR2], IP1)
-  ['sub_1', 'sub12 1', 'sub12 2', 'sub11', 'sub22']
-  >>> registry.subscriptions([IR2], IP2)
-  ['sub12 1', 'sub12 2', 'sub22']
-
-Subscriptions can be on multiple specifications::
-
-  >>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
-  >>> registry.subscriptions([IR1, IQ], IP2)
-  ['sub1q2']
-  
-As with single subscriptions and non-subscription adapters, you can
-specify None for the first required interface, to specify a default::
-
-  >>> registry.subscribe([None, IQ], IP2, 'sub_q2')
-  >>> registry.subscriptions([IS, IQ], IP2)
-  ['sub_q2']
-  >>> registry.subscriptions([IR1, IQ], IP2)
-  ['sub_q2', 'sub1q2']
-
-You can have subscriptions that are indepenent of any specifications::
-  
-  >>> list(registry.subscriptions([], IP1))
-  []
-
-  >>> registry.subscribe([], IP2, 'sub2')
-  >>> registry.subscriptions([], IP1)
-  ['sub2']
-  >>> registry.subscribe([], IP1, 'sub1')
-  >>> registry.subscriptions([], IP1)
-  ['sub2', 'sub1']
-  >>> registry.subscriptions([], IP2)
-  ['sub2']
-
-Unregistering subscribers
--------------------------
-
-We can unregister subscribers.  When unregistering a subscriber, we
-can unregister a specific subscriber::
-
-  >>> registry.unsubscribe([IR1], IP1, 'sub11')
-  >>> registry.subscriptions([IR1], IP1)
-  ['sub_1', 'sub12 1', 'sub12 2']
-
-If we don't specify a value, then all subscribers matching the given
-interfaces will be unsubscribed:
-
-  >>> registry.unsubscribe([IR1], IP2)
-  >>> registry.subscriptions([IR1], IP1)
-  ['sub_1']
-
-
-Subscription adapters
----------------------
-
-We normally register adapter factories, which then allow us to compute
-adapters, but with subscriptions, we get multiple adapters.  Here's an
-example of multiple-object subscribers::
-
-  >>> registry.subscribe([IR, IQ], IM, M)
-  >>> registry.subscribe([IR, IQ], IM, M2)
-
-  >>> subscribers = registry.subscribers((x, q), IM)
-  >>> len(subscribers)
-  2
-  >>> class_names = [s.__class__.__name__ for s in subscribers]
-  >>> class_names.sort()
-  >>> class_names
-  ['M', 'M2']
-  >>> [(s.x is x and s.q is q) for s in subscribers]
-  [True, True]
-
-adapter factory subcribers can't return None values::
-
-  >>> def M3(x, y):
-  ...     return None
-
-  >>> registry.subscribe([IR, IQ], IM, M3)
-  >>> subscribers = registry.subscribers((x, q), IM)
-  >>> len(subscribers)
-  2
-
-Handlers
---------
-
-A handler is a subscriber factory that doesn't produce any normal
-output.  It returns None.  A handler is unlike adapters in that it does
-all of its work when the factory is called.
-
-To register a handler, simply provide None as the provided interface::
-
-  >>> def handler(event):
-  ...     print 'handler', event
-
-  >>> registry.subscribe([IR1], None, handler)
-  >>> registry.subscriptions([IR1], None) == [handler]
-  True

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/advice.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/advice.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/advice.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -29,7 +29,7 @@
 try:
     from types import ClassType
     __python3 = False
-except ImportError:
+except ImportError:  #pragma NO COVER
     __python3 = True
     
 import sys
@@ -63,7 +63,7 @@
         kind = "class"
     elif not sameNamespace:
         kind = "function call"
-    else:
+    else:   # pragma NO COVER
         # How can you have f_locals is f_globals, and have '__module__' set?
         # This is probably module-level code, but with a '__module__' variable.
         kind = "unknown"
@@ -106,7 +106,7 @@
     #    )
 
     previousMetaclass = caller_locals.get('__metaclass__')
-    if __python3:
+    if __python3:   # pragma NO COVER
         defaultMetaclass  = caller_globals.get('__metaclass__', type)
     else:
         defaultMetaclass  = caller_globals.get('__metaclass__', ClassType)
@@ -167,7 +167,7 @@
 
     candidates = minimalBases(meta) # minimal set of metaclasses
 
-    if not candidates:
+    if not candidates: #pragma NO COVER
         # they're all "classic" classes
         assert(not __python3) # This should not happen under Python 3
         return ClassType

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/common/interfaces.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/common/interfaces.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/common/interfaces.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -77,14 +77,14 @@
 classImplements(OverflowError, IOverflowError)
 try:
     classImplements(OverflowWarning, IOverflowWarning)
-except NameError:
+except NameError:  #pragma NO COVER
     pass # OverflowWarning was removed in Python 2.5
 classImplements(ReferenceError, IReferenceError)
 classImplements(RuntimeError, IRuntimeError)
 classImplements(RuntimeWarning, IRuntimeWarning)
 try:
     classImplements(StandardError, IStandardError)
-except NameError:
+except NameError:  #pragma NO COVER
     pass # StandardError does not exist in Python 3
 classImplements(StopIteration, IStopIteration)
 classImplements(SyntaxError, ISyntaxError)

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/declarations.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/declarations.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/declarations.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -27,11 +27,15 @@
 __docformat__ = 'restructuredtext'
 
 import sys
+from types import FunctionType
+from types import MethodType
+from types import ModuleType
 import weakref
-from zope.interface.interface import InterfaceClass, Specification
+
+from zope.interface.advice import addClassAdvisor
+from zope.interface.interface import InterfaceClass
 from zope.interface.interface import SpecificationBase
-from types import ModuleType, MethodType, FunctionType
-from zope.interface.advice import addClassAdvisor
+from zope.interface.interface import Specification
 
 # Registry of class-implementation specifications
 BuiltinImplementationSpecifications = {}
@@ -760,7 +764,7 @@
 try:
     from types import ClassType
     DescriptorAwareMetaClasses = ClassType, type
-except ImportError: # Python 3
+except ImportError:  #pragma NO COVERAGE  (Python 3)
     DescriptorAwareMetaClasses = (type,)
     
 def directlyProvides(object, *interfaces):
@@ -973,7 +977,7 @@
     if interface.providedBy(object):
         raise ValueError("Can only remove directly provided interfaces.")
 
-class ClassProvidesBasePy(object):
+class ClassProvidesBaseFallback(object):
 
     def __get__(self, inst, cls):
         if cls is self._cls:
@@ -988,14 +992,15 @@
 
         raise AttributeError('__provides__')
 
-ClassProvidesBase = ClassProvidesBasePy
+ClassProvidesBasePy = ClassProvidesBaseFallback # BBB
+ClassProvidesBase = ClassProvidesBaseFallback
 
 # Try to get C base:
 try:
     import _zope_interface_coptimizations
-except ImportError:
+except ImportError:  #pragma NO COVERAGE
     pass
-else:
+else:  #pragma NO COVERAGE
     from _zope_interface_coptimizations import ClassProvidesBase
 
 
@@ -1185,6 +1190,8 @@
 #
 # Declaration querying support
 
+# XXX:  is this a fossil?  Nobody calls it, no unit tests exercise it, no
+#       doctests import it, and the package __init__ doesn't import it.
 def ObjectSpecification(direct, cls):
     """Provide object specifications
 
@@ -1251,9 +1258,9 @@
       1
     """
 
-    return Provides(cls, direct)
+    return Provides(cls, direct) #pragma NO COVER fossil
 
-def getObjectSpecification(ob):
+def getObjectSpecificationFallback(ob):
 
     provides = getattr(ob, '__provides__', None)
     if provides is not None:
@@ -1268,8 +1275,10 @@
 
     return implementedBy(cls)
 
-def providedBy(ob):
+getObjectSpecification = getObjectSpecificationFallback
 
+def providedByFallback(ob):
+
     # Here we have either a special object, an old-style declaration
     # or a descriptor
 
@@ -1317,8 +1326,9 @@
             return implementedBy(ob.__class__)
 
     return r
+providedBy = providedByFallback
 
-class ObjectSpecificationDescriptorPy(object):
+class ObjectSpecificationDescriptorFallback(object):
     """Implement the `__providedBy__` attribute
 
     The `__providedBy__` attribute computes the interfaces peovided by
@@ -1357,7 +1367,7 @@
 
         return implementedBy(cls)
 
-ObjectSpecificationDescriptor = ObjectSpecificationDescriptorPy
+ObjectSpecificationDescriptor = ObjectSpecificationDescriptorFallback
 
 ##############################################################################
 
@@ -1385,10 +1395,11 @@
 
 try:
     import _zope_interface_coptimizations
-except ImportError:
+except ImportError: #pragma NO COVER
     pass
 else:
-    from _zope_interface_coptimizations import implementedBy, providedBy
+    from _zope_interface_coptimizations import implementedBy
+    from _zope_interface_coptimizations import providedBy
     from _zope_interface_coptimizations import getObjectSpecification
     from _zope_interface_coptimizations import ObjectSpecificationDescriptor
 

Deleted: zope.interface/branches/tseaver-better_unittests/src/zope/interface/human.ru.txt
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/human.ru.txt	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/human.ru.txt	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,156 +0,0 @@
-===============================
-Использование реестра адаптеров
-===============================
-
-Данный документ содержит небольшую демонстрацию пакета ``zope.interface`` и его
-реестра адаптеров. Документ рассчитывался как конкретный, но более узкий пример
-того как использовать интерфейсы и адаптеры вне Zope 3.
-
-Сначала нам необходимо импортировать пакет для работы с интерфейсами::
-
-  >>> import zope.interface
-
-Теперь мы разработаем интерфейс для нашего объекта - простого файла. Наш файл
-будет содержать всего один атрибут - body, в котором фактически будет сохранено
-содержимое файла::
-
-  >>> class IFile(zope.interface.Interface):
-  ...
-  ...     body = zope.interface.Attribute(u'Содержимое файла.')
-  ...
-
-Для статистики нам часто необходимо знать размер файла. Но было бы несколько
-топорно реализовывать определение размера прямо для объекта файла, т.к. размер
-больше относится к мета-данным. Таким образом мы создаем еще один интерфейс для
-представления размера какого-либо объекта::
-
-  >>> class ISize(zope.interface.Interface):
-  ...
-  ...     def getSize():
-  ...         'Return the size of an object.'
-  ...
-
-Теперь мы должны создать класс реализующий наш файл. Необходимо что бы наш
-объект хранил информацию о том, что он реализует интерфейс `IFile`. Мы также
-создаем атрибут с содержимым файла по умолчанию (для упрощения нашего
-примера)::
-
-  >>> class File(object):
-  ...
-  ...      zope.interface.implements(IFile)
-  ...      body = 'foo bar'
-  ...
-
-Дальше мы создаем адаптер, который будет предоставлять интерфейс `ISize`
-получая любой объект предоставляющий интерфейс `IFile`. По соглашению мы
-используем атрибут `__used_for__` для указания интерфейса который как мы
-ожидаем предоставляет адаптируемый объект, `IFile` в нашем случае. На самом
-деле этот атрибут используется только для документирования. В случае если
-адаптер используется для нескольких интерфейсов можно указать их все в виде
-кортежа.
-
-Опять же по соглашению конструктор адаптера получает один аргумент - context
-(контекст). В нашем случае контекст - это экземпляр `IFile` (объект,
-предоставляющий `IFile`) который используется для получения из него размера.
-Так же по соглашению контекст сохраняется а адаптере в атрибуте с именем
-`context`. Twisted комьюнити ссылается на контекст как на объект `original`.
-Таким образом можно также дать аргументу любое подходящее имя, например
-`file`::
-
-  >>> class FileSize(object):
-  ...
-  ...      zope.interface.implements(ISize)
-  ...      __used_for__ = IFile
-  ...
-  ...      def __init__(self, context):
-  ...          self.context = context
-  ...
-  ...      def getSize(self):
-  ...          return len(self.context.body)
-  ...
-
-Теперь когда мы написали наш адаптер мы должны зарегистрировать его в реестре
-адаптеров, что бы его можно было запросить когда он понадобится. Здесь нет
-какого-либо глобального реестра адаптеров, таким образом мы должны
-самостоятельно создать для нашего примера реестр::
-
-  >>> from zope.interface.adapter import AdapterRegistry
-  >>> registry = AdapterRegistry()
-
-Реестр содержит отображение того, что адаптер реализует на основе другого
-интерфейса который предоставляет объект. Поэтому дальше мы регистрируем адаптер
-который адаптирует интерфейс `IFile` к интерфейсу `ISize`. Первый аргумент к
-методу `register()` реестра - это список адаптируемых интерфейсов. В нашем
-случае мы имеем только один адаптируемый интерфейс - `IFile`. Список
-интерфейсов имеет смысл для использования концепции мульти-адаптеров, которые
-требуют нескольких оригинальных объектов для адаптации к новому интерфейсу. В
-этой ситуации конструктор адаптера будет требовать новый аргумент для каждого
-оригинального интерфейса.
-
-Второй аргумент метода `register()` - это интерфейс который предоставляет
-адаптер, в нашем случае `ISize`. Третий аргумент - имя адаптера. Сейчас нам не
-важно имя адаптера и мы передаем его как пустую строку. Обычно имена полезны
-если используются адаптеры для одинакового набора интерфейсов, но в различных
-ситуациях. Последний аргумент - это класс адаптера::
-
-  >>> registry.register([IFile], ISize, '', FileSize)
-
-Теперь мы можем использовать реестр для запроса адаптера::
-
-  >>> registry.lookup1(IFile, ISize, '')
-  <class '__main__.FileSize'>
-
-Попробуем более практичный пример. Создадим экземпляр `File` и создадим адаптер
-использующий запрос реестра. Затем мы увидим возвращает ли адаптер корректный
-размер при вызове `getSize()`::
-
-  >>> file = File()
-  >>> size = registry.lookup1(IFile, ISize, '')(file)
-  >>> size.getSize()
-  7
-
-На самом деле это не очень практично, т.к. нам нужно самим передавать все
-аргументы методу запроса. Существует некоторый синтаксический леденец который
-позволяет нам получить экземпляр адаптера просто вызвав `ISize(file)`. Что бы
-использовать эту функциональность нам понадобится добавить наш реестр к списку
-adapter_hooks, который находится в модуле с адаптерами. Этот список хранит
-коллекцию вызываемых объектов которые вызываются автоматически когда вызывается
-IFoo(obj); их предназначение - найти адаптеры которые реализуют интерфейс для
-определенного экземпляра контекста.
-
-Необходимо реализовать свою собственную функцию для поиска адаптера; данный
-пример описывает одну из простейших функций для использования с реестром, но
-также можно реализовать поисковые функции которые, например, используют
-кэширование, или адаптеры сохраняемые в базе. Функция поиска должна принимать
-желаемый на выходе интерфейс (в нашем случае `ISize`) как первый аргумент и
-контекст для адаптации (`file`) как второй. Функция должна вернуть адаптер,
-т.е. экземпляр `FileSize`::
-
-  >>> def hook(provided, object):
-  ...     adapter = registry.lookup1(zope.interface.providedBy(object),
-  ...                                provided, '')
-  ...     return adapter(object)
-  ...
-
-Теперь мы просто добавляем нашу функцию к списку `adapter_hooks`::
-
-  >>> from zope.interface.interface import adapter_hooks
-  >>> adapter_hooks.append(hook)
-
-Как только функция зарегистрирована мы можем использовать желаемый синтаксис::
-
-  >>> size = ISize(file)
-  >>> size.getSize()
-  7
-
-После нам нужно прибраться за собой, что бы другие получили чистый список
-`adaper_hooks` после нас::
-
-  >>> adapter_hooks.remove(hook)
-
-Это все. Здесь намеренно отложена дискуссия об именованных и мульти-адаптерах,
-т.к. данный текст рассчитан как практическое и простое введение в интерфейсы и
-адаптеры Zope 3. Для более подробной информации имеет смысл прочитать
-`adapter.txt` из пакета `zope.interface`, что бы получить более формальное,
-справочное и полное трактование пакета. Внимание: многие жаловались, что
-`adapter.txt` приводит их мозг к расплавленному состоянию!

Deleted: zope.interface/branches/tseaver-better_unittests/src/zope/interface/human.txt
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/human.txt	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/human.txt	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,152 +0,0 @@
-==========================
-Using the Adapter Registry
-==========================
-
-This is a small demonstration of the ``zope.interface`` package including its
-adapter registry. It is intended to provide a concrete but narrow example on
-how to use interfaces and adapters outside of Zope 3.
-
-First we have to import the interface package::
-
-  >>> import zope.interface
-
-We now develop an interface for our object, which is a simple file in this
-case. For now we simply support one attribute, the body, which contains the
-actual file contents::
-
-  >>> class IFile(zope.interface.Interface):
-  ...
-  ...     body = zope.interface.Attribute('Contents of the file.')
-  ...
-
-For statistical reasons we often want to know the size of a file. However, it
-would be clumsy to implement the size directly in the file object, since the
-size really represents meta-data. Thus we create another interface that
-provides the size of something::
-
-  >>> class ISize(zope.interface.Interface):
-  ...
-  ...     def getSize():
-  ...         'Return the size of an object.'
-  ...
-
-Now we need to implement the file. It is essential that the object states
-that it implements the `IFile` interface. We also provide a default body
-value (just to make things simpler for this example)::
-
-  >>> class File(object):
-  ...
-  ...      zope.interface.implements(IFile)
-  ...      body = 'foo bar'
-  ...
-
-Next we implement an adapter that can provide the `ISize` interface given any
-object providing `IFile`. By convention we use `__used_for__` to specify the
-interface that we expect the adapted object to provide, in our case
-`IFile`. However, this attribute is not used for anything. If you have
-multiple interfaces for which an adapter is used, just specify the interfaces
-via a tuple.
-
-Again by convention, the constructor of an adapter takes one argument, the
-context. The context in this case is an instance of `File` (providing `IFile`)
-that is used to extract the size from. Also by convention the context is
-stored in an attribute named `context` on the adapter. The twisted community
-refers to the context as the `original` object. However, you may feel free to
-use a specific argument name, such as `file`::
-
-  >>> class FileSize(object):
-  ...
-  ...      zope.interface.implements(ISize)
-  ...      __used_for__ = IFile
-  ...
-  ...      def __init__(self, context):
-  ...          self.context = context
-  ...
-  ...      def getSize(self):
-  ...          return len(self.context.body)
-  ...
-
-Now that we have written our adapter, we have to register it with an adapter
-registry, so that it can be looked up when needed. There is no such thing as a
-global registry; thus we have to instantiate one for our example manually::
-
-  >>> from zope.interface.adapter import AdapterRegistry
-  >>> registry = AdapterRegistry()
-
-
-The registry keeps a map of what adapters implement based on another
-interface, the object already provides. Therefore, we next have to register an
-adapter that adapts from `IFile` to `ISize`. The first argument to
-the registry's `register()` method is a list of original interfaces.In our
-cause we have only one original interface, `IFile`. A list makes sense, since
-the interface package has the concept of multi-adapters, which are adapters
-that require multiple objects to adapt to a new interface. In these
-situations, your adapter constructor will require an argument for each
-specified interface.
-
-The second argument is the interface the adapter provides, in our case
-`ISize`. The third argument is the name of the adapter. Since we do not care
-about names, we simply leave it as an empty string. Names are commonly useful,
-if you have adapters for the same set of interfaces, but they are useful in
-different situations. The last argument is simply the adapter class::
-
-  >>> registry.register([IFile], ISize, '', FileSize)
-
-You can now use the the registry to lookup the adapter::
-
-  >>> registry.lookup1(IFile, ISize, '')
-  <class '__main__.FileSize'>
-
-Let's get a little bit more practical. Let's create a `File` instance and
-create the adapter using a registry lookup. Then we see whether the adapter
-returns the correct size by calling `getSize()`::
-
-  >>> file = File()
-  >>> size = registry.lookup1(IFile, ISize, '')(file)
-  >>> size.getSize()
-  7
-
-However, this is not very practical, since I have to manually pass in the
-arguments to the lookup method. There is some syntactic candy that will allow
-us to get an adapter instance by simply calling `ISize(file)`. To make use of
-this functionality, we need to add our registry to the adapter_hooks list,
-which is a member of the adapters module. This list stores a collection of
-callables that are automatically invoked when IFoo(obj) is called; their
-purpose is to locate adapters that implement an interface for a certain
-context instance.
-
-You are required to implement your own adapter hook; this example covers one
-of the simplest hooks that use the registry, but you could implement one that
-used an adapter cache or persistent adapters, for instance. The helper hook is
-required to expect as first argument the desired output interface (for us
-`ISize`) and as the second argument the context of the adapter (here
-`file`). The function returns an adapter, i.e. a `FileSize` instance::
-
-  >>> def hook(provided, object):
-  ...     adapter = registry.lookup1(zope.interface.providedBy(object),
-  ...                                provided, '')
-  ...     return adapter(object)
-  ...
-
-We now just add the hook to an `adapter_hooks` list::
-
-  >>> from zope.interface.interface import adapter_hooks
-  >>> adapter_hooks.append(hook)
-
-Once the hook is registered, you can use the desired syntax::
-
-  >>> size = ISize(file)
-  >>> size.getSize()
-  7
-
-Now we have to cleanup after ourselves, so that others after us have a clean
-`adapter_hooks` list::
-
-  >>> adapter_hooks.remove(hook)
-
-That's it. I have intentionally left out a discussion of named adapters and
-multi-adapters, since this text is intended as a practical and simple
-introduction to Zope 3 interfaces and adapters. You might want to read the
-`adapter.txt` in the `zope.interface` package for a more formal, referencial
-and complete treatment of the package. Warning: People have reported that
-`adapter.txt` makes their brain feel soft!

Deleted: zope.interface/branches/tseaver-better_unittests/src/zope/interface/index.txt
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/index.txt	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/index.txt	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,29 +0,0 @@
-Welcome to zope.interface's documentation!
-==========================================
-
-Contents:
-
-.. toctree::
-   :maxdepth: 2
-
-   README
-   adapter
-   human
-   verify
-
-По-русски
-=========
-
-.. toctree::
-   :maxdepth: 2
-
-   README.ru
-   adapter.ru
-   human.ru
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/interface.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/interface.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/interface.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -163,7 +163,7 @@
 SpecificationBase = SpecificationBasePy
 try:
     from _zope_interface_coptimizations import SpecificationBase
-except ImportError:
+except ImportError: #pragma NO COVER
     pass
 
 _marker = object()
@@ -204,14 +204,14 @@
 InterfaceBase = InterfaceBasePy
 try:
     from _zope_interface_coptimizations import InterfaceBase
-except ImportError:
+except ImportError: #pragma NO COVER
     pass
 
 
 adapter_hooks = []
 try:
     from _zope_interface_coptimizations import adapter_hooks
-except ImportError:
+except ImportError: #pragma NO COVER
     pass
 
 
@@ -224,7 +224,7 @@
     This class is a base class for both interfaces themselves and for
     interface specifications (declarations).
 
-    Specifications are mutable.  If you reassign their cases, their
+    Specifications are mutable.  If you reassign their bases, their
     relations with other specifications are adjusted accordingly.
 
     For example:
@@ -450,7 +450,7 @@
                     # This is how cPython figures out the module of
                     # a class, but of course it does it in C. :-/
                     __module__ = sys._getframe(1).f_globals['__name__']
-                except (AttributeError, KeyError):
+                except (AttributeError, KeyError): #pragma NO COVERAGE
                     pass
 
         self.__module__ = __module__
@@ -605,9 +605,10 @@
         if errors:
             raise Invalid(errors)
 
-    def _getInterface(self, ob, name):
-        """Retrieve a named interface."""
-        return None
+    #XXX I believe this is a fossil:  nobody calls it anywhere.
+    #def _getInterface(self, ob, name):
+    #    """Retrieve a named interface."""
+    #    return None
 
     def __d(self, klass):
         for k, v in self.__attrs.items():
@@ -632,7 +633,7 @@
     def _call_conform(self, conform):
         try:
             return conform(self)
-        except TypeError:
+        except TypeError: #pragma NO COVER
             # We got a TypeError. It might be an error raised by
             # the __conform__ implementation, or *we* may have
             # made the TypeError by calling an unbound method
@@ -646,12 +647,12 @@
                 raise
             # This clever trick is from Phillip Eby
 
-        return None
+        return None #pragma NO COVER
 
     def __reduce__(self):
         return self.__name__
 
-    def __cmp(self, o1, o2):
+    def __cmp(self, other):
         # Yes, I did mean to name this __cmp, rather than __cmp__.
         # It is a private method used by __lt__ and __gt__.
         # I don't want to override __eq__ because I want the default
@@ -673,46 +674,44 @@
         sort before None.
 
         """
-        if o1 is None:
-            return 1
-        if o2 is None:
+        if other is None:
             return -1
 
-        n1 = (getattr(o1, '__name__', ''), getattr(o1,  '__module__', ''))
-        n2 = (getattr(o2, '__name__', ''), getattr(o2,  '__module__', ''))
+        n1 = (getattr(self, '__name__', ''), getattr(self,  '__module__', ''))
+        n2 = (getattr(other, '__name__', ''), getattr(other,  '__module__', ''))
 
         # This spelling works under Python3, which doesn't have cmp().
         return (n1 > n2) - (n1 < n2)
 
     def __hash__(self):
         d = self.__dict__
-        if '__module__' not in d or '__name__' not in d:
+        if '__module__' not in d or '__name__' not in d: #pragma NO COVER
             warnings.warn('Hashing uninitialized InterfaceClass instance')
             return 1
         return hash((self.__name__, self.__module__))
 
     def __eq__(self, other):
-        c = self.__cmp(self, other)
+        c = self.__cmp(other)
         return c == 0
 
     def __ne__(self, other):
-        c = self.__cmp(self, other)
+        c = self.__cmp(other)
         return c != 0
 
     def __lt__(self, other):
-        c = self.__cmp(self, other)
+        c = self.__cmp(other)
         return c < 0
 
     def __le__(self, other):
-        c = self.__cmp(self, other)
+        c = self.__cmp(other)
         return c <= 0
 
     def __gt__(self, other):
-        c = self.__cmp(self, other)
+        c = self.__cmp(other)
         return c > 0
 
     def __ge__(self, other):
-        c = self.__cmp(self, other)
+        c = self.__cmp(other)
         return c >= 0
 
 
@@ -742,6 +741,18 @@
     #
     # implements(IMethod)
 
+    positional = required = ()
+    _optional = varargs = kwargs = None
+    def _get_optional(self):
+        if self._optional is None:
+            return {}
+        return self._optional
+    def _set_optional(self, opt):
+        self._optional = opt
+    def _del_optional(self):
+        self._optional = None
+    optional = property(_get_optional, _set_optional, _del_optional)
+
     def __call__(self, *args, **kw):
         raise BrokenImplementation(self.interface, self.__name__)
 
@@ -758,7 +769,7 @@
         for v in self.positional:
             sig.append(v)
             if v in self.optional.keys():
-                sig[-1] += "=" + `self.optional[v]`
+                sig[-1] += "=" + repr(self.optional[v])
         if self.varargs:
             sig.append("*" + self.varargs)
         if self.kwargs:

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/registry.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/registry.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/registry.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -18,7 +18,7 @@
 
 try:
     from zope.event import notify
-except ImportError:
+except ImportError: #pragma NO COVER
     def notify(*arg, **kw): pass
 
 from zope.interface.interfaces import ISpecification
@@ -40,7 +40,7 @@
 from zope.interface.declarations import implementer_only # req by py3k fixers
 from zope.interface.adapter import AdapterRegistry
 
-if sys.version_info[0] == 3:
+if sys.version_info[0] == 3: #pragma NO COVER
     def _u(s):
         return s
     class_types = type

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/ro.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/ro.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/ro.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -30,7 +30,7 @@
 
     For example:
 
-    >>> _mergeOrderings([
+    >>> mergeOrderings([
     ... ['x', 'y', 'z'],
     ... ['q', 'z'],
     ... [1, 3, 5],

Added: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/advisory_testing.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/advisory_testing.py	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/advisory_testing.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,42 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import sys
+
+from zope.interface.advice import addClassAdvisor
+from zope.interface.advice import getFrameInfo
+
+my_globals = globals()
+
+def ping(log, value):
+
+    def pong(klass):
+        log.append((value,klass))
+        return [klass]
+
+    addClassAdvisor(pong)
+
+try:
+    from types import ClassType
+    
+    class ClassicClass:
+        __metaclass__ = ClassType
+        classLevelFrameInfo = getFrameInfo(sys._getframe())
+except ImportError:
+    ClassicClass = None
+
+class NewStyleClass:
+    __metaclass__ = type
+    classLevelFrameInfo = getFrameInfo(sys._getframe())
+
+moduleLevelFrameInfo = getFrameInfo(sys._getframe())

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/dummy.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/dummy.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/dummy.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -11,12 +11,13 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Dummy Module
+""" Dummy Module
 """
 from zope.interface import moduleProvides
-from zope.interface.tests.ifoo import IFoo
+from zope.interface.tests.idummy import IDummyModule
 
-moduleProvides(IFoo)
+moduleProvides(IDummyModule)
 
 def bar(baz):
+    # Note:  no 'self', because the module provides the interface directly.
     pass

Deleted: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/foodforthought.txt
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/foodforthought.txt	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/foodforthought.txt	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,61 +0,0 @@
-================================
-Food-based subscription examples
-================================
-
-
-This file gives more subscription examples using a cooking-based example::
-
-    >>> from zope.interface.adapter import AdapterRegistry
-    >>> registry = AdapterRegistry()
-
-    >>> import zope.interface
-    >>> class IAnimal(zope.interface.Interface):
-    ...     pass
-    >>> class IPoultry(IAnimal):
-    ...     pass
-    >>> class IChicken(IPoultry):
-    ...     pass
-    >>> class ISeafood(IAnimal):
-    ...     pass
-
-Adapting to some other interface for which there is no
-subscription adapter returns an empty sequence::
-
-    >>> class IRecipe(zope.interface.Interface):
-    ...     pass
-    >>> class ISausages(IRecipe):
-    ...     pass
-    >>> class INoodles(IRecipe):
-    ...     pass
-    >>> class IKFC(IRecipe):
-    ...     pass
-
-    >>> list(registry.subscriptions([IPoultry], IRecipe))
-    []
-
-unless we define a subscription::
-
-    >>> registry.subscribe([IAnimal], ISausages, 'sausages')
-    >>> list(registry.subscriptions([IPoultry], ISausages))
-    ['sausages']
-
-And define another subscription adapter::
-
-    >>> registry.subscribe([IPoultry], INoodles, 'noodles')
-    >>> meals = list(registry.subscriptions([IPoultry], IRecipe))
-    >>> meals.sort()
-    >>> meals
-    ['noodles', 'sausages']
-
-    >>> registry.subscribe([IChicken], IKFC, 'kfc')
-    >>> meals = list(registry.subscriptions([IChicken], IRecipe))
-    >>> meals.sort()
-    >>> meals
-    ['kfc', 'noodles', 'sausages']
-
-And the answer for poultry hasn't changed::
-
-    >>> meals = list(registry.subscriptions([IPoultry], IRecipe))
-    >>> meals.sort()
-    >>> meals
-    ['noodles', 'sausages']

Copied: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/idummy.py (from rev 124741, zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/ifoo.py)
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/idummy.py	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/idummy.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,23 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Interface describing API of zope.interface.tests.dummy test module
+"""
+from zope.interface import Interface
+
+class IDummyModule(Interface):
+    """ Dummy interface for unit tests.
+    """
+    def bar(baz):
+        """ Just a note.
+        """

Deleted: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/ifoo.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/ifoo.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/ifoo.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,26 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""IFoo test module
-"""
-from zope.interface import Interface
-
-class IFoo(Interface):
-    """
-        Dummy interface for unit tests.
-    """
-
-    def bar(baz):
-        """
-            Just a note.
-        """

Added: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/ifoo.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/ifoo.py	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/ifoo.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,26 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""IFoo test module
+"""
+from zope.interface import Interface
+
+class IFoo(Interface):
+    """
+        Dummy interface for unit tests.
+    """
+
+    def bar(baz):
+        """
+            Just a note.
+        """

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_adapter.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_adapter.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_adapter.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -13,400 +13,1260 @@
 ##############################################################################
 """Adapter registry tests
 """
-import doctest
 import unittest
-import zope.interface
-from zope.interface.adapter import AdapterRegistry
 
+class _SilencePy3Deprecations(unittest.TestCase):
+    # silence deprecation warnings under py3
 
-class IF0(zope.interface.Interface):
-    pass
-class IF1(IF0):
-    pass
+    def failUnless(self, expr):
+        # St00pid speling.
+        return self.assertTrue(expr)
 
-class IB0(zope.interface.Interface):
-    pass
-class IB1(IB0):
-    pass
+    def failIf(self, expr):
+        # St00pid speling.
+        return self.assertFalse(expr)
 
-class IR0(zope.interface.Interface):
-    pass
-class IR1(IR0):
-    pass
 
-def test_multi_adapter_get_best_match():
-    """
-    >>> registry = AdapterRegistry()
+def _makeInterfaces():
+    from zope.interface import Interface
 
-    >>> class IB2(IB0):
-    ...     pass
-    >>> class IB3(IB2, IB1):
-    ...     pass
-    >>> class IB4(IB1, IB2):
-    ...     pass
+    class IB0(Interface): pass
+    class IB1(IB0): pass
+    class IB2(IB0): pass
+    class IB3(IB2, IB1): pass
+    class IB4(IB1, IB2): pass
 
-    >>> registry.register([None, IB1], IR0, '', 'A1')
-    >>> registry.register([None, IB0], IR0, '', 'A0')
-    >>> registry.register([None, IB2], IR0, '', 'A2')
+    class IF0(Interface): pass
+    class IF1(IF0): pass
 
-    >>> registry.lookup((IF1, IB1), IR0, '')
-    'A1'
-    >>> registry.lookup((IF1, IB2), IR0, '')
-    'A2'
-    >>> registry.lookup((IF1, IB0), IR0, '')
-    'A0'
-    >>> registry.lookup((IF1, IB3), IR0, '')
-    'A2'
-    >>> registry.lookup((IF1, IB4), IR0, '')
-    'A1'
-    """
+    class IR0(Interface): pass
+    class IR1(IR0): pass
 
-def test_multi_adapter_lookupAll_get_best_matches():
-    """
-    >>> registry = AdapterRegistry()
+    return IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1
 
-    >>> class IB2(IB0):
-    ...     pass
-    >>> class IB3(IB2, IB1):
-    ...     pass
-    >>> class IB4(IB1, IB2):
-    ...     pass
 
-    >>> registry.register([None, IB1], IR0, '', 'A1')
-    >>> registry.register([None, IB0], IR0, '', 'A0')
-    >>> registry.register([None, IB2], IR0, '', 'A2')
+class BaseAdapterRegistryTests(_SilencePy3Deprecations):
 
-    >>> tuple(registry.lookupAll((IF1, IB1), IR0))[0][1]
-    'A1'
-    >>> tuple(registry.lookupAll((IF1, IB2), IR0))[0][1]
-    'A2'
-    >>> tuple(registry.lookupAll((IF1, IB0), IR0))[0][1]
-    'A0'
-    >>> tuple(registry.lookupAll((IF1, IB3), IR0))[0][1]
-    'A2'
-    >>> tuple(registry.lookupAll((IF1, IB4), IR0))[0][1]
-    'A1'
-    """
+    def _getTargetClass(self):
+        from zope.interface.adapter import BaseAdapterRegistry
+        class _CUT(BaseAdapterRegistry):
+            class LookupClass(object):
+                _changed = _extendors = ()
+                def __init__(self, reg):
+                    pass
+                def changed(self, orig):
+                    self._changed += (orig,)
+                def add_extendor(self, provided):
+                    self._extendors += (provided,)
+                def remove_extendor(self, provided):
+                    self._extendors = tuple([x for x in self._extendors
+                                                    if x != provided])
+        for name in BaseAdapterRegistry._delegated:
+            setattr(_CUT.LookupClass, name, object())
+        return _CUT
 
+    def _makeOne(self):
+        return self._getTargetClass()()
 
-def test_multi_adapter_w_default():
-    """
-    >>> registry = AdapterRegistry()
-    
-    >>> registry.register([None, None], IB1, 'bob', 'A0')
+    def test_lookup_delegation(self):
+        CUT = self._getTargetClass()
+        registry = CUT()
+        for name in CUT._delegated:
+            self.failUnless(
+                getattr(registry, name) is getattr(registry._v_lookup, name))
 
-    >>> registry.lookup((IF1, IR1), IB0, 'bob')
-    'A0'
-    
-    >>> registry.register([None, IR0], IB1, 'bob', 'A1')
+    def test__generation_on_first_creation(self):
+        registry = self._makeOne()
+        # Bumped to 1 in BaseAdapterRegistry.__init__
+        self.assertEqual(registry._generation, 1)
 
-    >>> registry.lookup((IF1, IR1), IB0, 'bob')
-    'A1'
-    
-    >>> registry.lookup((IF1, IR1), IB0, 'bruce')
+    def test__generation_after_calling_changed(self):
+        registry = self._makeOne()
+        orig = object()
+        registry.changed(orig)
+        # Bumped to 1 in BaseAdapterRegistry.__init__
+        self.assertEqual(registry._generation, 2)
+        self.assertEqual(registry._v_lookup._changed, (registry, orig,))
 
-    >>> registry.register([None, IR1], IB1, 'bob', 'A2')
-    >>> registry.lookup((IF1, IR1), IB0, 'bob')
-    'A2'
-    """
+    def test__generation_after_changing___bases__(self):
+        class _Base(object): pass
+        registry = self._makeOne()
+        registry.__bases__ = (_Base,)
+        self.assertEqual(registry._generation, 2)
 
-def test_multi_adapter_w_inherited_and_multiple_registrations():
-    """
-    >>> registry = AdapterRegistry()
+    def test_register(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        registry.register([IB0], IR0, '', 'A1')
+        self.assertEqual(registry.registered([IB0], IR0, ''), 'A1')
+        self.assertEqual(len(registry._adapters), 2) #order 0 and order 1
+        self.assertEqual(registry._generation, 2)
 
-    >>> class IX(zope.interface.Interface):
-    ...    pass
+    def test_register_with_value_None_unregisters(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        registry.register([None], IR0, '', 'A1')
+        registry.register([None], IR0, '', None)
+        self.assertEqual(len(registry._adapters), 0)
 
-    >>> registry.register([IF0, IR0], IB1, 'bob', 'A1')
-    >>> registry.register([IF1, IX], IB1, 'bob', 'AX')
+    def test_register_with_same_value(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        _value = object()
+        registry.register([None], IR0, '', _value)
+        _before = registry._generation
+        registry.register([None], IR0, '', _value)
+        self.assertEqual(registry._generation, _before) # skipped changed()
 
-    >>> registry.lookup((IF1, IR1), IB0, 'bob')
-    'A1'
-    """
+    def test_registered_empty(self):
+        registry = self._makeOne()
+        self.assertEqual(registry.registered([None], None, ''), None)
 
-def test_named_adapter_with_default():
-    """Query a named simple adapter
+    def test_registered_non_empty_miss(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        registry.register([IB1], None, '', 'A1')
+        self.assertEqual(registry.registered([IB2], None, ''), None)
 
-    >>> registry = AdapterRegistry()
+    def test_registered_non_empty_hit(self):
+        registry = self._makeOne()
+        registry.register([None], None, '', 'A1')
+        self.assertEqual(registry.registered([None], None, ''), 'A1')
 
-    If we ask for a named adapter, we won't get a result unless there
-    is a named adapter, even if the object implements the interface:
+    def test_unregister_empty(self):
+        registry = self._makeOne()
+        registry.unregister([None], None, '') #doesn't raise
+        self.assertEqual(registry.registered([None], None, ''), None)
 
-    >>> registry.lookup([IF1], IF0, 'bob')
+    def test_unregister_non_empty_miss_on_required(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        registry.register([IB1], None, '', 'A1')
+        registry.unregister([IB2], None, '') #doesn't raise
+        self.assertEqual(registry.registered([IB1], None, ''), 'A1')
 
-    >>> registry.register([None], IB1, 'bob', 'A1')
-    >>> registry.lookup([IF1], IB0, 'bob')
-    'A1'
+    def test_unregister_non_empty_miss_on_name(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        registry.register([IB1], None, '', 'A1')
+        registry.unregister([IB1], None, 'nonesuch') #doesn't raise
+        self.assertEqual(registry.registered([IB1], None, ''), 'A1')
 
-    >>> registry.lookup([IF1], IB0, 'bruce')
+    def test_unregister_with_value_not_None_miss(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        orig = object()
+        nomatch = object()
+        registry.register([IB1], None, '', orig)
+        registry.unregister([IB1], None, '', nomatch) #doesn't raise
+        self.failUnless(registry.registered([IB1], None, '') is orig)
 
-    >>> registry.register([None], IB0, 'bob', 'A2')
-    >>> registry.lookup([IF1], IB0, 'bob')
-    'A2'
-    """
+    def test_unregister_hit_clears_empty_subcomponents(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        one = object()
+        another = object()
+        registry.register([IB1, IB2], None, '', one)
+        registry.register([IB1, IB3], None, '', another)
+        self.failUnless(IB2 in registry._adapters[2][IB1])
+        self.failUnless(IB3 in registry._adapters[2][IB1])
+        registry.unregister([IB1, IB3], None, '', another)
+        self.failUnless(IB2 in registry._adapters[2][IB1])
+        self.failIf(IB3 in registry._adapters[2][IB1])
 
-def test_multi_adapter_gets_closest_provided():
-    """
-    >>> registry = AdapterRegistry()
-    >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
-    >>> registry.register((IF1, IR0), IB1, 'bob', 'A2')
-    >>> registry.lookup((IF1, IR1), IB0, 'bob')
-    'A1'
+    def test_unsubscribe_empty(self):
+        registry = self._makeOne()
+        registry.unsubscribe([None], None, '') #doesn't raise
+        self.assertEqual(registry.registered([None], None, ''), None)
 
-    >>> registry = AdapterRegistry()
-    >>> registry.register([IF1, IR0], IB1, 'bob', 'A2')
-    >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
-    >>> registry.lookup([IF1, IR0], IB0, 'bob')
-    'A1'
+    def test_unsubscribe_hit(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        orig = object()
+        registry.subscribe([IB1], None, orig)
+        registry.unsubscribe([IB1], None, orig) #doesn't raise
+        self.assertEqual(len(registry._subscribers), 0)
 
-    >>> registry = AdapterRegistry()
-    >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
-    >>> registry.register([IF1, IR1], IB1, 'bob', 'A2')
-    >>> registry.lookup([IF1, IR1], IB0, 'bob')
-    'A2'
+    def test_unsubscribe_after_multiple(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        first = object()
+        second = object()
+        third = object()
+        registry.subscribe([IB1], None, first)
+        registry.subscribe([IB1], None, second)
+        registry.subscribe([IB1], IR0, third)
+        registry.unsubscribe([IB1], IR0, third)
+        registry.unsubscribe([IB1], None, second)
+        registry.unsubscribe([IB1], None, first)
+        self.assertEqual(len(registry._subscribers), 0)
 
-    >>> registry = AdapterRegistry()
-    >>> registry.register([IF1, IR1], IB1, 'bob', 2)
-    >>> registry.register([IF1, IR0], IB0, 'bob', 1)
-    >>> registry.lookup([IF1, IR1], IB0, 'bob')
-    2
-    """
+    def test_unsubscribe_w_None_after_multiple(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        first = object()
+        second = object()
+        third = object()
+        registry.subscribe([IB1], None, first)
+        registry.subscribe([IB1], None, second)
+        registry.unsubscribe([IB1], None)
+        self.assertEqual(len(registry._subscribers), 0)
 
-def test_multi_adapter_check_non_default_dont_hide_default():
-    """
-    >>> registry = AdapterRegistry()
+    def test_unsubscribe_non_empty_miss_on_required(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        registry.subscribe([IB1], None, 'A1')
+        self.assertEqual(len(registry._subscribers), 2)
+        registry.unsubscribe([IB2], None, '') #doesn't raise
+        self.assertEqual(len(registry._subscribers), 2)
 
-    >>> class IX(zope.interface.Interface):
-    ...     pass
+    def test_unsubscribe_non_empty_miss_on_value(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        registry.subscribe([IB1], None, 'A1')
+        self.assertEqual(len(registry._subscribers), 2)
+        registry.unsubscribe([IB1], None, 'A2') #doesn't raise
+        self.assertEqual(len(registry._subscribers), 2)
 
+    def test_unsubscribe_with_value_not_None_miss(self):
+        IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces()
+        registry = self._makeOne()
+        orig = object()
+        nomatch = object()
+        registry.subscribe([IB1], None, orig)
+        registry.unsubscribe([IB1], None, nomatch) #doesn't raise
+        self.assertEqual(len(registry._subscribers), 2)
 
-    >>> registry.register([None, IR0], IB0, 'bob', 1)
-    >>> registry.register([IF1,   IX], IB0, 'bob', 2)
-    >>> registry.lookup([IF1, IR1], IB0, 'bob')
-    1
-    """
 
-def test_adapter_hook_with_factory_producing_None():
-    """
-    >>> registry = AdapterRegistry()
-    >>> default = object()
-    
-    >>> class Object1(object):
-    ...     zope.interface.implements(IF0)
-    >>> class Object2(object):
-    ...     zope.interface.implements(IF0)
+class LookupBaseFallbackTests(_SilencePy3Deprecations):
 
-    >>> def factory(context):
-    ...     if isinstance(context, Object1):
-    ...         return 'adapter'
-    ...     return None
+    def _getTargetClass(self):
+        from zope.interface.adapter import LookupBaseFallback
+        return LookupBaseFallback
 
-    >>> registry.register([IF0], IB0, '', factory)
+    def _makeOne(self, uc_lookup=None, uc_lookupAll=None,
+                 uc_subscriptions=None):
+        if uc_lookup is None:
+            def uc_lookup(self, required, provided, name):
+                pass
+        if uc_lookupAll is None:
+            def uc_lookupAll(self, required, provided):
+                pass
+        if uc_subscriptions is None:
+            def uc_subscriptions(self, required, provided):
+                pass
+        class Derived(self._getTargetClass()):
+            _uncached_lookup = uc_lookup
+            _uncached_lookupAll = uc_lookupAll
+            _uncached_subscriptions = uc_subscriptions
+        return Derived()
 
-    >>> registry.adapter_hook(IB0, Object1())
-    'adapter'
-    >>> registry.adapter_hook(IB0, Object2()) is None
-    True
-    >>> registry.adapter_hook(IB0, Object2(), default=default) is default
-    True
-    """
+    def test_lookup_miss_no_default(self):
+        _called_with = []
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return None
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup(('A',), 'B', 'C')
+        self.failUnless(found is None)
+        self.assertEqual(_called_with, [(('A',), 'B', 'C')])
 
-def test_adapter_registry_update_upon_interface_bases_change():
-    """
-    Let's first create a adapter registry and a simple adaptation hook:
+    def test_lookup_miss_w_default(self):
+        _called_with = []
+        _default = object()
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return None
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup(('A',), 'B', 'C', _default)
+        self.failUnless(found is _default)
+        self.assertEqual(_called_with, [(('A',), 'B', 'C')])
 
-    >>> globalRegistry = AdapterRegistry()
+    def test_lookup_not_cached(self):
+        _called_with = []
+        a, b, c = object(), object(), object()
+        _results = [a, b, c]
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return _results.pop(0)
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup(('A',), 'B', 'C')
+        self.failUnless(found is a)
+        self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+        self.assertEqual(_results, [b, c])
 
-    >>> def _hook(iface, ob, lookup=globalRegistry.lookup1):
-    ...     factory = lookup(zope.interface.providedBy(ob), iface)
-    ...     if factory is None:
-    ...         return None
-    ...     else:
-    ...         return factory(ob)
+    def test_lookup_cached(self):
+        _called_with = []
+        a, b, c = object(), object(), object()
+        _results = [a, b, c]
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return _results.pop(0)
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup(('A',), 'B', 'C')
+        found = lb.lookup(('A',), 'B', 'C')
+        self.failUnless(found is a)
+        self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+        self.assertEqual(_results, [b, c])
 
-    >>> zope.interface.interface.adapter_hooks.append(_hook)
+    def test_lookup_not_cached_multi_required(self):
+        _called_with = []
+        a, b, c = object(), object(), object()
+        _results = [a, b, c]
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return _results.pop(0)
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup(('A', 'D'), 'B', 'C')
+        self.failUnless(found is a)
+        self.assertEqual(_called_with, [(('A', 'D'), 'B', 'C')])
+        self.assertEqual(_results, [b, c])
 
-    Now we create some interfaces and an implementation:
+    def test_lookup_cached_multi_required(self):
+        _called_with = []
+        a, b, c = object(), object(), object()
+        _results = [a, b, c]
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return _results.pop(0)
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup(('A', 'D'), 'B', 'C')
+        found = lb.lookup(('A', 'D'), 'B', 'C')
+        self.failUnless(found is a)
+        self.assertEqual(_called_with, [(('A', 'D'), 'B', 'C')])
+        self.assertEqual(_results, [b, c])
 
-    >>> class IX(zope.interface.Interface):
-    ...   pass
+    def test_lookup_not_cached_after_changed(self):
+        _called_with = []
+        a, b, c = object(), object(), object()
+        _results = [a, b, c]
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return _results.pop(0)
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup(('A',), 'B', 'C')
+        lb.changed(lb)
+        found = lb.lookup(('A',), 'B', 'C')
+        self.failUnless(found is b)
+        self.assertEqual(_called_with,
+                         [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
+        self.assertEqual(_results, [c])
 
-    >>> class IY(zope.interface.Interface):
-    ...   pass
+    def test_lookup1_miss_no_default(self):
+        _called_with = []
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return None
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup1('A', 'B', 'C')
+        self.failUnless(found is None)
+        self.assertEqual(_called_with, [(('A',), 'B', 'C')])
 
-    >>> class X(object):
-    ...  pass
+    def test_lookup1_miss_w_default(self):
+        _called_with = []
+        _default = object()
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return None
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup1('A', 'B', 'C', _default)
+        self.failUnless(found is _default)
+        self.assertEqual(_called_with, [(('A',), 'B', 'C')])
 
-    >>> class Y(object):
-    ...  zope.interface.implements(IY)
-    ...  def __init__(self, original):
-    ...   self.original=original
+    def test_lookup1_miss_w_default_negative_cache(self):
+        _called_with = []
+        _default = object()
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return None
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup1('A', 'B', 'C', _default)
+        self.failUnless(found is _default)
+        found = lb.lookup1('A', 'B', 'C', _default)
+        self.failUnless(found is _default)
+        self.assertEqual(_called_with, [(('A',), 'B', 'C')])
 
-    and register an adapter:
+    def test_lookup1_not_cached(self):
+        _called_with = []
+        a, b, c = object(), object(), object()
+        _results = [a, b, c]
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return _results.pop(0)
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup1('A', 'B', 'C')
+        self.failUnless(found is a)
+        self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+        self.assertEqual(_results, [b, c])
 
-    >>> globalRegistry.register((IX,), IY, '', Y)
+    def test_lookup1_cached(self):
+        _called_with = []
+        a, b, c = object(), object(), object()
+        _results = [a, b, c]
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return _results.pop(0)
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup1('A', 'B', 'C')
+        found = lb.lookup1('A', 'B', 'C')
+        self.failUnless(found is a)
+        self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+        self.assertEqual(_results, [b, c])
 
-    at first, we still expect the adapter lookup from `X` to `IY` to fail:
+    def test_lookup1_not_cached_after_changed(self):
+        _called_with = []
+        a, b, c = object(), object(), object()
+        _results = [a, b, c]
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return _results.pop(0)
+        lb = self._makeOne(uc_lookup=_lookup)
+        found = lb.lookup1('A', 'B', 'C')
+        lb.changed(lb)
+        found = lb.lookup1('A', 'B', 'C')
+        self.failUnless(found is b)
+        self.assertEqual(_called_with,
+                         [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
+        self.assertEqual(_results, [c])
 
-    >>> IY(X()) #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
-    Traceback (most recent call last):
-    ...
-    TypeError: ('Could not adapt',
-                <zope.interface.tests.test_adapter.X object at ...>,
-                <InterfaceClass zope.interface.tests.test_adapter.IY>)
+    def test_adapter_hook_miss_no_default(self):
+        req, prv = object(), object()
+        lb = self._makeOne()
+        found = lb.adapter_hook(prv, req, '')
+        self.failUnless(found is None)
 
-    But after we declare an interface on the class `X`, it should pass:
+    def test_adapter_hook_miss_w_default(self):
+        req, prv, _default = object(), object(), object()
+        lb = self._makeOne()
+        found = lb.adapter_hook(prv, req, '', _default)
+        self.failUnless(found is _default)
 
-    >>> zope.interface.classImplementsOnly(X, IX)
+    def test_adapter_hook_hit_factory_returns_None(self):
+        _f_called_with = []
+        def _factory(context):
+            _f_called_with.append(context)
+            return None
+        def _lookup(self, required, provided, name):
+            return _factory
+        req, prv, _default = object(), object(), object()
+        lb = self._makeOne(uc_lookup=_lookup)
+        adapted = lb.adapter_hook(prv, req, 'C', _default)
+        self.failUnless(adapted is _default)
+        self.assertEqual(_f_called_with, [req])
 
-    >>> IY(X()) #doctest: +ELLIPSIS
-    <zope.interface.tests.test_adapter.Y object at ...>
+    def test_adapter_hook_hit_factory_returns_adapter(self):
+        _f_called_with = []
+        _adapter = object()
+        def _factory(context):
+            _f_called_with.append(context)
+            return _adapter
+        def _lookup(self, required, provided, name):
+            return _factory
+        req, prv, _default = object(), object(), object()
+        lb = self._makeOne(uc_lookup=_lookup)
+        adapted = lb.adapter_hook(prv, req, 'C', _default)
+        self.failUnless(adapted is _adapter)
+        self.assertEqual(_f_called_with, [req])
 
-    >>> hook = zope.interface.interface.adapter_hooks.pop()
-    """
+    def test_queryAdapter(self):
+        _f_called_with = []
+        _adapter = object()
+        def _factory(context):
+            _f_called_with.append(context)
+            return _adapter
+        def _lookup(self, required, provided, name):
+            return _factory
+        req, prv, _default = object(), object(), object()
+        lb = self._makeOne(uc_lookup=_lookup)
+        adapted = lb.queryAdapter(req, prv, 'C', _default)
+        self.failUnless(adapted is _adapter)
+        self.assertEqual(_f_called_with, [req])
 
+    def test_lookupAll_uncached(self):
+        _called_with = []
+        _results = [object(), object(), object()]
+        def _lookupAll(self, required, provided):
+            _called_with.append((required, provided))
+            return tuple(_results)
+        lb = self._makeOne(uc_lookupAll=_lookupAll)
+        found = lb.lookupAll('A', 'B')
+        self.assertEqual(found, tuple(_results))
+        self.assertEqual(_called_with, [(('A',), 'B')])
 
-def test_changing_declarations():
-    """
+    def test_lookupAll_cached(self):
+        _called_with = []
+        _results = [object(), object(), object()]
+        def _lookupAll(self, required, provided):
+            _called_with.append((required, provided))
+            return tuple(_results)
+        lb = self._makeOne(uc_lookupAll=_lookupAll)
+        found = lb.lookupAll('A', 'B')
+        found = lb.lookupAll('A', 'B')
+        self.assertEqual(found, tuple(_results))
+        self.assertEqual(_called_with, [(('A',), 'B')])
 
-    If we change declarations for a class, those adapter lookup should
-    eflect the changes:
+    def test_subscriptions_uncached(self):
+        _called_with = []
+        _results = [object(), object(), object()]
+        def _subscriptions(self, required, provided):
+            _called_with.append((required, provided))
+            return tuple(_results)
+        lb = self._makeOne(uc_subscriptions=_subscriptions)
+        found = lb.subscriptions('A', 'B')
+        self.assertEqual(found, tuple(_results))
+        self.assertEqual(_called_with, [(('A',), 'B')])
 
-    >>> class I1(zope.interface.Interface):
-    ...     pass
-    >>> class I2(zope.interface.Interface):
-    ...     pass
+    def test_subscriptions_cached(self):
+        _called_with = []
+        _results = [object(), object(), object()]
+        def _subscriptions(self, required, provided):
+            _called_with.append((required, provided))
+            return tuple(_results)
+        lb = self._makeOne(uc_subscriptions=_subscriptions)
+        found = lb.subscriptions('A', 'B')
+        found = lb.subscriptions('A', 'B')
+        self.assertEqual(found, tuple(_results))
+        self.assertEqual(_called_with, [(('A',), 'B')])
 
-    >>> registry = AdapterRegistry()
-    >>> registry.register([I1], I2, '', 42)
 
-    >>> class C:
-    ...     pass
+class LookupBaseTests(LookupBaseFallbackTests):
 
-    >>> registry.lookup([zope.interface.implementedBy(C)], I2, '')
+    def _getTargetClass(self):
+        from zope.interface.adapter import LookupBase
+        return LookupBase
 
-    >>> zope.interface.classImplements(C, I1)
 
-    >>> registry.lookup([zope.interface.implementedBy(C)], I2, '')
-    42
-    """
+class VerifyingBaseFallbackTests(_SilencePy3Deprecations):
 
-def test_correct_multi_adapter_lookup():
-    """
-    >>> registry = AdapterRegistry()
-    >>> registry.register([IF0, IB1], IR0, '', 'A01')
-    >>> registry.register([IF1, IB0], IR0, '', 'A10')
-    >>> registry.lookup((IF1, IB1), IR0, '')
-    'A10'
-    """
+    def _getTargetClass(self):
+        from zope.interface.adapter import VerifyingBaseFallback
+        return VerifyingBaseFallback
 
-def test_duplicate_bases():
-    """
-There was a bug that caused problems if a spec had multiple bases:
+    def _makeOne(self, registry, uc_lookup=None, uc_lookupAll=None,
+                 uc_subscriptions=None):
+        if uc_lookup is None:
+            def uc_lookup(self, required, provided, name):
+                pass
+        if uc_lookupAll is None:
+            def uc_lookupAll(self, required, provided):
+                pass
+        if uc_subscriptions is None:
+            def uc_subscriptions(self, required, provided):
+                pass
+        class Derived(self._getTargetClass()):
+            _uncached_lookup = uc_lookup
+            _uncached_lookupAll = uc_lookupAll
+            _uncached_subscriptions = uc_subscriptions
+            def __init__(self, registry):
+                super(Derived, self).__init__()
+                self._registry = registry
+        derived = Derived(registry)
+        derived.changed(derived) # init. '_verify_ro' / '_verify_generations'
+        return derived
 
-    >>> class I(zope.interface.Interface):
-    ...     pass
-    >>> class I2(I, I):
-    ...     pass
-    >>> registry = AdapterRegistry()
-    >>> registry.register([I2], IR0, 'x', 'X')
-    >>> registry.lookup((I2, ), IR0, 'x')
-    'X'
-    >>> registry.register([I2], IR0, 'y', 'Y')
-    >>> registry.lookup((I2, ), IR0, 'x')
-    'X'
-    >>> registry.lookup((I2, ), IR0, 'y')
-    'Y'
-"""
+    def _makeRegistry(self, depth):
+        class WithGeneration(object):
+            _generation = 1
+        class Registry:
+            def __init__(self, depth):
+                self.ro = [WithGeneration() for i in range(depth)]
+        return Registry(depth)
 
-def test_register_objects_with_cmp():
-    """
-    The registry should never use == as that will tend to fail when
-    objects are picky about what they are compared with:
+    def test_lookup(self):
+        _called_with = []
+        a, b, c = object(), object(), object()
+        _results = [a, b, c]
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return _results.pop(0)
+        reg = self._makeRegistry(3)
+        lb = self._makeOne(reg, uc_lookup=_lookup)
+        found = lb.lookup(('A',), 'B', 'C')
+        found = lb.lookup(('A',), 'B', 'C')
+        self.failUnless(found is a)
+        self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+        self.assertEqual(_results, [b, c])
+        reg.ro[1]._generation += 1
+        found = lb.lookup(('A',), 'B', 'C')
+        self.failUnless(found is b)
+        self.assertEqual(_called_with,
+                        [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
+        self.assertEqual(_results, [c])
 
-    >>> class Picky:
-    ...     def __cmp__(self, other):
-    ...         raise TypeError("I\'m too picky for comparison!")
-    >>> class I(zope.interface.Interface):
-    ...     pass
-    >>> class I2(I, I):
-    ...     pass
+    def test_lookup1(self):
+        _called_with = []
+        a, b, c = object(), object(), object()
+        _results = [a, b, c]
+        def _lookup(self, required, provided, name):
+            _called_with.append((required, provided, name))
+            return _results.pop(0)
+        reg = self._makeRegistry(3)
+        lb = self._makeOne(reg, uc_lookup=_lookup)
+        found = lb.lookup1('A', 'B', 'C')
+        found = lb.lookup1('A', 'B', 'C')
+        self.failUnless(found is a)
+        self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+        self.assertEqual(_results, [b, c])
+        reg.ro[1]._generation += 1
+        found = lb.lookup1('A', 'B', 'C')
+        self.failUnless(found is b)
+        self.assertEqual(_called_with,
+                        [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
+        self.assertEqual(_results, [c])
 
-    >>> registry = AdapterRegistry()
-    >>> picky = Picky()
-    >>> registry.register([I2], IR0, '', picky)
-    >>> registry.unregister([I2], IR0, '', picky)
+    def test_adapter_hook(self):
+        a, b, c = [object(), object(), object()]
+        def _factory1(context):
+            return a
+        def _factory2(context):
+            return b
+        def _factory3(context):
+            return c
+        _factories = [_factory1, _factory2, _factory3]
+        def _lookup(self, required, provided, name):
+            return _factories.pop(0)
+        req, prv, _default = object(), object(), object()
+        reg = self._makeRegistry(3)
+        lb = self._makeOne(reg, uc_lookup=_lookup)
+        adapted = lb.adapter_hook(prv, req, 'C', _default)
+        self.failUnless(adapted is a)
+        adapted = lb.adapter_hook(prv, req, 'C', _default)
+        self.failUnless(adapted is a)
+        reg.ro[1]._generation += 1
+        adapted = lb.adapter_hook(prv, req, 'C', _default)
+        self.failUnless(adapted is b)
 
-    >>> registry.subscribe([I2], IR0, picky)
-    >>> registry.unsubscribe([I2], IR0, picky)
+    def test_queryAdapter(self):
+        a, b, c = [object(), object(), object()]
+        def _factory1(context):
+            return a
+        def _factory2(context):
+            return b
+        def _factory3(context):
+            return c
+        _factories = [_factory1, _factory2, _factory3]
+        def _lookup(self, required, provided, name):
+            return _factories.pop(0)
+        req, prv, _default = object(), object(), object()
+        reg = self._makeRegistry(3)
+        lb = self._makeOne(reg, uc_lookup=_lookup)
+        adapted = lb.queryAdapter(req, prv, 'C', _default)
+        self.failUnless(adapted is a)
+        adapted = lb.queryAdapter(req, prv, 'C', _default)
+        self.failUnless(adapted is a)
+        reg.ro[1]._generation += 1
+        adapted = lb.adapter_hook(prv, req, 'C', _default)
+        self.failUnless(adapted is b)
 
-    """
+    def test_lookupAll(self):
+        _results_1 = [object(), object(), object()]
+        _results_2 = [object(), object(), object()]
+        _results = [_results_1, _results_2]
+        def _lookupAll(self, required, provided):
+            return tuple(_results.pop(0))
+        reg = self._makeRegistry(3)
+        lb = self._makeOne(reg, uc_lookupAll=_lookupAll)
+        found = lb.lookupAll('A', 'B')
+        self.assertEqual(found, tuple(_results_1))
+        found = lb.lookupAll('A', 'B')
+        self.assertEqual(found, tuple(_results_1))
+        reg.ro[1]._generation += 1
+        found = lb.lookupAll('A', 'B')
+        self.assertEqual(found, tuple(_results_2))
 
-def test_unregister_cleans_up_empties():
-    """
-    >>> class I(zope.interface.Interface):
-    ...     pass
-    >>> class IP(zope.interface.Interface):
-    ...     pass
-    >>> class C(object):
-    ...     pass
+    def test_subscriptions(self):
+        _results_1 = [object(), object(), object()]
+        _results_2 = [object(), object(), object()]
+        _results = [_results_1, _results_2]
+        def _subscriptions(self, required, provided):
+            return tuple(_results.pop(0))
+        reg = self._makeRegistry(3)
+        lb = self._makeOne(reg, uc_subscriptions=_subscriptions)
+        found = lb.subscriptions('A', 'B')
+        self.assertEqual(found, tuple(_results_1))
+        found = lb.subscriptions('A', 'B')
+        self.assertEqual(found, tuple(_results_1))
+        reg.ro[1]._generation += 1
+        found = lb.subscriptions('A', 'B')
+        self.assertEqual(found, tuple(_results_2))
 
-    >>> registry = AdapterRegistry()
 
-    >>> registry.register([], IP, '', C)
-    >>> registry.register([I], IP, '', C)
-    >>> registry.register([I], IP, 'name', C)
-    >>> registry.register([I, I], IP, '', C)
-    >>> len(registry._adapters)
-    3
-    >>> map(len, registry._adapters)
-    [1, 1, 1]
+class VerifyingBaseTests(VerifyingBaseFallbackTests):
 
-    >>> registry.unregister([], IP, '', C)
-    >>> registry.unregister([I], IP, '', C)
-    >>> registry.unregister([I], IP, 'name', C)
-    >>> registry.unregister([I, I], IP, '', C)
-    >>> registry._adapters
-    []
+    def _getTargetClass(self):
+        from zope.interface.adapter import VerifyingBase
+        return VerifyingBase
 
-    """
 
-def test_unsubscribe_cleans_up_empties():
-    """
-    >>> class I1(zope.interface.Interface):
-    ...     pass
-    >>> class I2(zope.interface.Interface):
-    ...     pass
-    >>> class IP(zope.interface.Interface):
-    ...     pass
+class AdapterLookupBaseTests(_SilencePy3Deprecations):
 
-    >>> registry = AdapterRegistry()
-    >>> def handler(event):
-    ...     pass
+    def _getTargetClass(self):
+        from zope.interface.adapter import AdapterLookupBase
+        return AdapterLookupBase
 
-    >>> registry.subscribe([I1], I1, handler)
-    >>> registry.subscribe([I2], I1, handler)
-    >>> len(registry._subscribers)
-    2
-    >>> map(len, registry._subscribers)
-    [0, 2]
+    def _makeOne(self, registry):
+        return self._getTargetClass()(registry)
 
-    >>> registry.unsubscribe([I1], I1, handler)
-    >>> registry.unsubscribe([I2], I1, handler)
-    >>> registry._subscribers
-    []
+    def _makeSubregistry(self, *provided):
+        class Subregistry:
+            def __init__(self):
+                self._adapters = []
+                self._subscribers = []
+        return Subregistry()
 
-    """
+    def _makeRegistry(self, *provided):
+        class Registry:
+            def __init__(self, provided):
+                self._provided = provided
+                self.ro = []
+        return Registry(provided)
 
+    def test_ctor_empty_registry(self):
+        registry = self._makeRegistry()
+        alb = self._makeOne(registry)
+        self.assertEqual(alb._extendors, {})
 
+    def test_ctor_w_registry_provided(self):
+        from zope.interface import Interface
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        alb = self._makeOne(registry)
+        self.assertEqual(sorted(alb._extendors.keys()),
+                         sorted([IBar, IFoo, Interface]))
+        self.assertEqual(alb._extendors[IFoo], [IFoo])
+        self.assertEqual(alb._extendors[IBar], [IBar])
+        self.assertEqual(sorted(alb._extendors[Interface]),
+                         sorted([IFoo, IBar]))
+
+    def test_changed_empty_required(self):
+        # ALB.changed expects to call a mixed in changed.
+        class Mixin(object):
+            def changed(self, *other):
+                pass
+        class Derived(self._getTargetClass(), Mixin):
+            pass
+        registry = self._makeRegistry()
+        alb = Derived(registry)
+        alb.changed(alb)
+
+    def test_changed_w_required(self):
+        # ALB.changed expects to call a mixed in changed.
+        class Mixin(object):
+            def changed(self, *other):
+                pass
+        class Derived(self._getTargetClass(), Mixin):
+            pass
+        class FauxWeakref(object):
+            _unsub = None
+            def __init__(self, here):
+                self._here = here
+            def __call__(self):
+                if self._here:
+                    return self
+            def unsubscribe(self, target):
+                self._unsub = target
+        gone = FauxWeakref(False)
+        here = FauxWeakref(True)
+        registry = self._makeRegistry()
+        alb = Derived(registry)
+        alb._required[gone] = 1
+        alb._required[here] = 1
+        alb.changed(alb)
+        self.assertEqual(len(alb._required), 0)
+        self.assertEqual(gone._unsub, None)
+        self.assertEqual(here._unsub, alb)
+
+    def test_init_extendors_after_registry_update(self):
+        from zope.interface import Interface
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry()
+        alb = self._makeOne(registry)
+        registry._provided = [IFoo, IBar]
+        alb.init_extendors()
+        self.assertEqual(sorted(alb._extendors.keys()),
+                         sorted([IBar, IFoo, Interface]))
+        self.assertEqual(alb._extendors[IFoo], [IFoo])
+        self.assertEqual(alb._extendors[IBar], [IBar])
+        self.assertEqual(sorted(alb._extendors[Interface]),
+                         sorted([IFoo, IBar]))
+
+    def test_add_extendor(self):
+        from zope.interface import Interface
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry()
+        alb = self._makeOne(registry)
+        alb.add_extendor(IFoo)
+        alb.add_extendor(IBar)
+        self.assertEqual(sorted(alb._extendors.keys()),
+                         sorted([IBar, IFoo, Interface]))
+        self.assertEqual(alb._extendors[IFoo], [IFoo])
+        self.assertEqual(alb._extendors[IBar], [IBar])
+        self.assertEqual(sorted(alb._extendors[Interface]),
+                         sorted([IFoo, IBar]))
+
+    def test_remove_extendor(self):
+        from zope.interface import Interface
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        alb = self._makeOne(registry)
+        alb.remove_extendor(IFoo)
+        self.assertEqual(sorted(alb._extendors.keys()),
+                         sorted([IFoo, IBar, Interface]))
+        self.assertEqual(alb._extendors[IFoo], [])
+        self.assertEqual(alb._extendors[IBar], [IBar])
+        self.assertEqual(sorted(alb._extendors[Interface]),
+                         sorted([IBar]))
+
+    # test '_subscribe' via its callers, '_uncached_lookup', etc.
+
+    def test__uncached_lookup_empty_ro(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry()
+        alb = self._makeOne(registry)
+        result = alb._uncached_lookup((IFoo,), IBar)
+        self.assertEqual(result, None)
+        self.assertEqual(len(alb._required), 1)
+        self.failUnless(IFoo.weakref() in alb._required)
+
+    def test__uncached_lookup_order_miss(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        result = alb._uncached_lookup((IFoo,), IBar)
+        self.assertEqual(result, None)
+
+    def test__uncached_lookup_extendors_miss(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry()
+        subr = self._makeSubregistry()
+        subr._adapters = [{}, {}] #utilities, single adapters
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        subr._v_lookup = alb
+        result = alb._uncached_lookup((IFoo,), IBar)
+        self.assertEqual(result, None)
+
+    def test__uncached_lookup_components_miss(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        subr._adapters = [{}, {}] #utilities, single adapters
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        subr._v_lookup = alb
+        result = alb._uncached_lookup((IFoo,), IBar)
+        self.assertEqual(result, None)
+
+    def test__uncached_lookup_simple_hit(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        _expected = object()
+        subr._adapters = [ #utilities, single adapters
+            {},
+            {IFoo: {IBar: {'': _expected}}},
+        ]
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        subr._v_lookup = alb
+        result = alb._uncached_lookup((IFoo,), IBar)
+        self.failUnless(result is _expected)
+
+    def test_queryMultiAdaptor_lookup_miss(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        class Foo(object):
+            implements(IFoo)
+        foo = Foo()
+        registry = self._makeRegistry()
+        subr = self._makeSubregistry()
+        subr._adapters = [ #utilities, single adapters
+            {},
+            {},
+        ]
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        alb.lookup = alb._uncached_lookup # provided by derived
+        subr._v_lookup = alb
+        _default = object()
+        result = alb.queryMultiAdapter((foo,), IBar, default=_default)
+        self.failUnless(result is _default)
+
+    def test_queryMultiAdaptor_factory_miss(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        class Foo(object):
+            implements(IFoo)
+        foo = Foo()
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        _expected = object()
+        _called_with = []
+        def _factory(context):
+            _called_with.append(context)
+            return None
+        subr._adapters = [ #utilities, single adapters
+            {},
+            {IFoo: {IBar: {'': _factory}}},
+        ]
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        alb.lookup = alb._uncached_lookup # provided by derived
+        subr._v_lookup = alb
+        _default = object()
+        result = alb.queryMultiAdapter((foo,), IBar, default=_default)
+        self.failUnless(result is _default)
+        self.assertEqual(_called_with, [foo])
+
+    def test_queryMultiAdaptor_factory_hit(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        class Foo(object):
+            implements(IFoo)
+        foo = Foo()
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        _expected = object()
+        _called_with = []
+        def _factory(context):
+            _called_with.append(context)
+            return _expected
+        subr._adapters = [ #utilities, single adapters
+            {},
+            {IFoo: {IBar: {'': _factory}}},
+        ]
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        alb.lookup = alb._uncached_lookup # provided by derived
+        subr._v_lookup = alb
+        _default = object()
+        result = alb.queryMultiAdapter((foo,), IBar, default=_default)
+        self.failUnless(result is _expected)
+        self.assertEqual(_called_with, [foo])
+
+    def test__uncached_lookupAll_empty_ro(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry()
+        alb = self._makeOne(registry)
+        result = alb._uncached_lookupAll((IFoo,), IBar)
+        self.assertEqual(result, ())
+        self.assertEqual(len(alb._required), 1)
+        self.failUnless(IFoo.weakref() in alb._required)
+
+    def test__uncached_lookupAll_order_miss(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        subr._v_lookup = alb
+        result = alb._uncached_lookupAll((IFoo,), IBar)
+        self.assertEqual(result, ())
+
+    def test__uncached_lookupAll_extendors_miss(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry()
+        subr = self._makeSubregistry()
+        subr._adapters = [{}, {}] #utilities, single adapters
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        subr._v_lookup = alb
+        result = alb._uncached_lookupAll((IFoo,), IBar)
+        self.assertEqual(result, ())
+
+    def test__uncached_lookupAll_components_miss(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        subr._adapters = [{}, {}] #utilities, single adapters
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        subr._v_lookup = alb
+        result = alb._uncached_lookupAll((IFoo,), IBar)
+        self.assertEqual(result, ())
+
+    def test__uncached_lookupAll_simple_hit(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        _expected = object()
+        _named = object()
+        subr._adapters = [ #utilities, single adapters
+            {},
+            {IFoo: {IBar: {'': _expected, 'named': _named}}},
+        ]
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        subr._v_lookup = alb
+        result = alb._uncached_lookupAll((IFoo,), IBar)
+        self.assertEqual(sorted(result), [('', _expected), ('named', _named)])
+
+    def test_names(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        _expected = object()
+        _named = object()
+        subr._adapters = [ #utilities, single adapters
+            {},
+            {IFoo: {IBar: {'': _expected, 'named': _named}}},
+        ]
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        alb.lookupAll = alb._uncached_lookupAll
+        subr._v_lookup = alb
+        result = alb.names((IFoo,), IBar)
+        self.assertEqual(sorted(result), ['', 'named'])
+
+    def test__uncached_subscriptions_empty_ro(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry()
+        alb = self._makeOne(registry)
+        result = alb._uncached_subscriptions((IFoo,), IBar)
+        self.assertEqual(result, [])
+        self.assertEqual(len(alb._required), 1)
+        self.failUnless(IFoo.weakref() in alb._required)
+
+    def test__uncached_subscriptions_order_miss(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        subr._v_lookup = alb
+        result = alb._uncached_subscriptions((IFoo,), IBar)
+        self.assertEqual(result, [])
+
+    def test__uncached_subscriptions_extendors_miss(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry()
+        subr = self._makeSubregistry()
+        subr._subscribers = [{}, {}] #utilities, single adapters
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        subr._v_lookup = alb
+        result = alb._uncached_subscriptions((IFoo,), IBar)
+        self.assertEqual(result, [])
+
+    def test__uncached_subscriptions_components_miss(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        subr._subscribers = [{}, {}] #utilities, single adapters
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        subr._v_lookup = alb
+        result = alb._uncached_subscriptions((IFoo,), IBar)
+        self.assertEqual(result, [])
+
+    def test__uncached_subscriptions_simple_hit(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        _exp1, _exp2 = object(), object()
+        subr._subscribers = [ #utilities, single adapters
+            {},
+            {IFoo: {IBar: {'': (_exp1, _exp2)}}},
+        ]
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        subr._v_lookup = alb
+        result = alb._uncached_subscriptions((IFoo,), IBar)
+        self.assertEqual(sorted(result), sorted([_exp1, _exp2]))
+
+    def test_subscribers_wo_provided(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        class Foo(object):
+            implements(IFoo)
+        foo = Foo()
+        registry = self._makeRegistry(IFoo, IBar)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        _called = {}
+        def _factory1(context):
+            _called.setdefault('_factory1', []).append(context)
+        def _factory2(context):
+            _called.setdefault('_factory2', []).append(context)
+        subr._subscribers = [ #utilities, single adapters
+            {},
+            {IFoo: {None: {'': (_factory1, _factory2)}}},
+        ]
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        alb.subscriptions = alb._uncached_subscriptions
+        subr._v_lookup = alb
+        result = alb.subscribers((foo,), None)
+        self.assertEqual(result, ())
+        self.assertEqual(_called, {'_factory1': [foo], '_factory2': [foo]})
+
+    def test_subscribers_w_provided(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', IFoo)
+        class Foo(object):
+            implements(IFoo)
+        foo = Foo()
+        registry = self._makeRegistry(IFoo, IBar)
+        registry = self._makeRegistry(IFoo, IBar)
+        subr = self._makeSubregistry()
+        _called = {}
+        _exp1, _exp2 = object(), object()
+        def _factory1(context):
+            _called.setdefault('_factory1', []).append(context)
+            return _exp1
+        def _factory2(context):
+            _called.setdefault('_factory2', []).append(context)
+            return _exp2
+        subr._subscribers = [ #utilities, single adapters
+            {},
+            {IFoo: {IBar: {'': (_factory1, _factory2)}}},
+        ]
+        registry.ro.append(subr)
+        alb = self._makeOne(registry)
+        alb.subscriptions = alb._uncached_subscriptions
+        subr._v_lookup = alb
+        result = alb.subscribers((foo,), IBar)
+        self.assertEqual(result, [_exp1, _exp2])
+        self.assertEqual(_called, {'_factory1': [foo], '_factory2': [foo]})
+
+
+class AdapterRegistryTests(_SilencePy3Deprecations):
+
+    def _getTargetClass(self):
+        from zope.interface.adapter import AdapterRegistry
+        return AdapterRegistry
+
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
+
+    def test_ctor_no_bases(self):
+        ar = self._makeOne()
+        self.assertEqual(len(ar._v_subregistries), 0)
+
+    def test_ctor_w_bases(self):
+        base = self._makeOne()
+        sub = self._makeOne([base])
+        self.assertEqual(len(sub._v_subregistries), 0)
+        self.assertEqual(len(base._v_subregistries), 1)
+        self.failUnless(sub in base._v_subregistries)
+
+    # test _addSubregistry / _removeSubregistry via only caller, _setBases
+
+    def test__setBases_removing_existing_subregistry(self):
+        before = self._makeOne()
+        after = self._makeOne()
+        sub = self._makeOne([before])
+        sub.__bases__ = [after]
+        self.assertEqual(len(before._v_subregistries), 0)
+        self.assertEqual(len(after._v_subregistries), 1)
+        self.failUnless(sub in after._v_subregistries)
+
+    def test_changed_w_subregistries(self):
+        base = self._makeOne()
+        class Derived(object):
+            _changed = None
+            def changed(self, originally_changed):
+                self._changed = originally_changed
+        derived1, derived2 = Derived(), Derived()
+        base._addSubregistry(derived1)
+        base._addSubregistry(derived2)
+        orig = object()
+        base.changed(orig)
+        self.failUnless(derived1._changed is orig)
+        self.failUnless(derived2._changed is orig)
+
+
+class Test_utils(unittest.TestCase):
+
+    def test__convert_None_to_Interface_w_None(self):
+        from zope.interface.adapter import _convert_None_to_Interface
+        from zope.interface.interface import Interface
+        self.failUnless(_convert_None_to_Interface(None) is Interface)
+
+    def test__convert_None_to_Interface_w_other(self):
+        from zope.interface.adapter import _convert_None_to_Interface
+        other = object()
+        self.failUnless(_convert_None_to_Interface(other) is other)
+
+    def test__normalize_name_str(self):
+        from zope.interface.adapter import _normalize_name
+        STR = 'str'
+        self.assertEqual(_normalize_name(STR), unicode(STR))
+
+    def test__normalize_name_unicode(self):
+        from zope.interface.adapter import _normalize_name
+        USTR = u'ustr'
+        self.assertEqual(_normalize_name(USTR), USTR)
+
+    def test__normalize_name_other(self):
+        from zope.interface.adapter import _normalize_name
+        for other in 1, 1.0, (), [], {}, object():
+            self.assertRaises(TypeError, _normalize_name, other)
+
+    # _lookup, _lookupAll, and _subscriptions tested via their callers
+    # (AdapterLookupBase.{lookup,lookupAll,subscriptions}).
+
+
 def test_suite():
     return unittest.TestSuite((
-        doctest.DocFileSuite('../adapter.txt', '../adapter.ru.txt',
-                                 '../human.txt', '../human.ru.txt',
-                                 'foodforthought.txt',
-                                 globs={'__name__': '__main__'}),
-        doctest.DocTestSuite(),
+        unittest.makeSuite(BaseAdapterRegistryTests),
+        unittest.makeSuite(LookupBaseFallbackTests),
+        unittest.makeSuite(LookupBaseTests),
+        unittest.makeSuite(VerifyingBaseFallbackTests),
+        unittest.makeSuite(VerifyingBaseTests),
+        unittest.makeSuite(AdapterLookupBaseTests),
+        unittest.makeSuite(AdapterRegistryTests),
+        unittest.makeSuite(Test_utils),
         ))
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_advice.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_advice.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_advice.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,4 +1,3 @@
-
 ##############################################################################
 #
 # Copyright (c) 2003 Zope Foundation and Contributors.
@@ -27,70 +26,71 @@
 """
 
 import unittest
-from unittest import TestCase, makeSuite, TestSuite
-from zope.interface.advice import addClassAdvisor, determineMetaclass
-from zope.interface.advice import getFrameInfo
 import sys
 
-def ping(log, value):
+class FrameInfoTest(unittest.TestCase):
 
-    def pong(klass):
-        log.append((value,klass))
-        return [klass]
-
-    addClassAdvisor(pong)
-
-try:
-    from types import ClassType
-    
-    class ClassicClass:
-        __metaclass__ = ClassType
-        classLevelFrameInfo = getFrameInfo(sys._getframe())
-except ImportError:
-    pass
-
-class NewStyleClass:
-    __metaclass__ = type
-    classLevelFrameInfo = getFrameInfo(sys._getframe())
-
-moduleLevelFrameInfo = getFrameInfo(sys._getframe())
-
-class FrameInfoTest(TestCase):
-
-    classLevelFrameInfo = getFrameInfo(sys._getframe())
-
-    def checkModuleInfo(self):
-        kind, module, f_locals, f_globals = moduleLevelFrameInfo
+    def test_w_module(self):
+        from zope.interface.tests import advisory_testing
+        (kind, module,
+         f_locals, f_globals) = advisory_testing.moduleLevelFrameInfo
         self.assertEquals(kind, "module")
         for d in module.__dict__, f_locals, f_globals:
-            self.assert_(d is globals())
+            self.assert_(d is advisory_testing.my_globals)
 
-    def checkClassicClassInfo(self):
-        kind, module, f_locals, f_globals = ClassicClass.classLevelFrameInfo
+    def test_w_ClassicClass(self):
+        from zope.interface.tests import advisory_testing
+        if advisory_testing.ClassicClass is None:
+            return
+        (kind,
+         module,
+         f_locals,
+         f_globals) = advisory_testing.ClassicClass.classLevelFrameInfo
         self.assertEquals(kind, "class")
 
-        self.assert_(f_locals is ClassicClass.__dict__)  # ???
+        self.assert_(f_locals is advisory_testing.ClassicClass.__dict__)  # ???
         for d in module.__dict__, f_globals:
-            self.assert_(d is globals())
+            self.assert_(d is advisory_testing.my_globals)
 
-    def checkNewStyleClassInfo(self):
-        kind, module, f_locals, f_globals = NewStyleClass.classLevelFrameInfo
+    def test_w_NewStyleClass(self):
+        from zope.interface.tests import advisory_testing
+        (kind,
+         module,
+         f_locals,
+         f_globals) = advisory_testing.NewStyleClass.classLevelFrameInfo
         self.assertEquals(kind, "class")
 
         for d in module.__dict__, f_globals:
-            self.assert_(d is globals())
+            self.assert_(d is advisory_testing.my_globals)
 
-    def checkCallInfo(self):
+    def test_inside_function_call(self):
+        from zope.interface.advice import getFrameInfo
         kind, module, f_locals, f_globals = getFrameInfo(sys._getframe())
         self.assertEquals(kind, "function call")
         self.assert_(f_locals is locals()) # ???
         for d in module.__dict__, f_globals:
             self.assert_(d is globals())
 
+    def test_inside_exec(self):
+        from zope.interface.advice import getFrameInfo
+        _globals = {'getFrameInfo': getFrameInfo}
+        _locals = {}
+        exec _FUNKY_EXEC in _globals, _locals
+        self.assertEquals(_locals['kind'], "exec")
+        self.assert_(_locals['f_locals'] is _locals)
+        self.assert_(_locals['module'] is None)
+        self.assert_(_locals['f_globals'] is _globals)
 
-class AdviceTests(TestCase):
 
-    def checkOrder(self):
+_FUNKY_EXEC = """\
+import sys
+kind, module, f_locals, f_globals = getFrameInfo(sys._getframe())
+"""
+
+class AdviceTests(unittest.TestCase):
+
+    def test_order(self):
+        from zope.interface.tests.advisory_testing import ping
         log = []
         class Foo(object):
             ping(log, 1)
@@ -98,13 +98,14 @@
             ping(log, 3)
 
         # Strip the list nesting
-        for i in 1,2,3:
+        for i in 1, 2, 3:
             self.assert_(isinstance(Foo, list))
             Foo, = Foo
 
         self.assertEquals(log, [(1, Foo), (2, [Foo]), (3, [[Foo]])])
 
-    def TODOcheckOutside(self):
+    def TODOtest_outside(self):
+        from zope.interface.tests.advisory_testing import ping
         # Disabled because the check does not work with doctest tests.
         try:
             ping([], 1)
@@ -115,71 +116,73 @@
                 "Should have detected advice outside class body"
             )
 
-    def checkDoubleType(self):
-        if sys.hexversion >= 0x02030000:
-            return  # you can't duplicate bases in 2.3
-        class aType(type,type):
-            ping([],1)
-        aType, = aType
-        self.assert_(aType.__class__ is type)
+    def test_single_explicit_meta(self):
+        from zope.interface.tests.advisory_testing import ping
 
-    def checkSingleExplicitMeta(self):
-
-        class M(type):
+        class Metaclass(type):
             pass
 
-        class C(M):
-            __metaclass__ = M
+        class Concrete(Metaclass):
+            __metaclass__ = Metaclass
             ping([],1)
 
-        C, = C
-        self.assert_(C.__class__ is M)
+        Concrete, = Concrete
+        self.assert_(Concrete.__class__ is Metaclass)
 
 
-    def checkMixedMetas(self):
+    def test_mixed_metas(self):
+        from zope.interface.tests.advisory_testing import ping
 
-        class M1(type): pass
-        class M2(type): pass
+        class Metaclass1(type):
+            pass
 
-        class B1: __metaclass__ = M1
-        class B2: __metaclass__ = M2
+        class Metaclass2(type):
+            pass
 
+        class Base1:
+            __metaclass__ = Metaclass1
+
+        class Base2:
+            __metaclass__ = Metaclass2
+
         try:
-            class C(B1,B2):
-                ping([],1)
+            class Derived(Base1, Base2):
+                ping([], 1)
+
         except TypeError:
             pass
         else:
             raise AssertionError("Should have gotten incompatibility error")
 
-        class M3(M1,M2): pass
+        class Metaclass3(Metaclass1, Metaclass2):
+            pass
 
-        class C(B1,B2):
-            __metaclass__ = M3
-            ping([],1)
+        class Derived(Base1, Base2):
+            __metaclass__ = Metaclass3
+            ping([], 1)
 
-        self.assert_(isinstance(C,list))
-        C, = C
-        self.assert_(isinstance(C,M3))
+        self.assert_(isinstance(Derived, list))
+        Derived, = Derived
+        self.assert_(isinstance(Derived, Metaclass3))
 
-    def checkMetaOfClass(self):
+    def test_meta_of_class(self):
+        from zope.interface.advice import determineMetaclass
 
-        class metameta(type):
+        class Metameta(type):
             pass
 
-        class meta(type):
-            __metaclass__ = metameta
+        class Meta(type):
+            __metaclass__ = Metameta
 
-        self.assertEquals(determineMetaclass((meta, type)), metameta)
+        self.assertEquals(determineMetaclass((Meta, type)), Metameta)
 
-TestClasses = (AdviceTests, FrameInfoTest)
 
 def test_suite():
     if sys.version[0] == '2':
-        return TestSuite([makeSuite(t,'check') for t in TestClasses])
+        return unittest.TestSuite((
+            unittest.makeSuite(FrameInfoTest),
+            unittest.makeSuite(AdviceTests),
+        ))
     else:
         # Advise metaclasses doesn't work in Python 3
         return TestSuite([])
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_declarations.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_declarations.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_declarations.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -13,422 +13,1464 @@
 ##############################################################################
 """Test the new API for making and checking interface declarations
 """
-import doctest
 import unittest
 
-from zope.interface import Interface, implements
-from zope.interface import directlyProvides, providedBy
-from zope.interface import classImplements, implementedBy, implementsOnly
 
-class I1(Interface): pass
-class I2(Interface): pass
-class I3(Interface): pass
-class I4(Interface): pass
-class I5(Interface): pass
+class _SilencePy3Deprecations(unittest.TestCase):
+    # silence deprecation warnings under py3
 
-class A(object):
-    implements(I1)
-class B(object):
-    implements(I2)
-class C(A, B):
-    implements(I3)
+    def failUnless(self, expr):
+        # St00pid speling.
+        return self.assertTrue(expr)
 
-class COnly(A, B):
-    implementsOnly(I3)
+    def failIf(self, expr):
+        # St00pid speling.
+        return self.assertFalse(expr)
+ 
 
-class COnly_old(A, B):
-    __implemented__ = I3
+class DeclarationTests(_SilencePy3Deprecations):
 
-class D(COnly):
-    implements(I5)
+    def _getTargetClass(self):
+        from zope.interface.declarations import Declaration
+        return Declaration
 
-def test_ObjectSpecification_Simple():
-    """
-    >>> c = C()
-    >>> directlyProvides(c, I4)
-    >>> [i.__name__ for i in providedBy(c)]
-    ['I4', 'I3', 'I1', 'I2']
-    """
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
+ 
+    def test_ctor_no_bases(self):
+        decl = self._makeOne()
+        self.assertEqual(list(decl.__bases__), [])
 
-def test_ObjectSpecification_Simple_w_only():
-    """
-    >>> c = COnly()
-    >>> directlyProvides(c, I4)
-    >>> [i.__name__ for i in providedBy(c)]
-    ['I4', 'I3']
-    """
+    def test_ctor_w_interface_in_bases(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        decl = self._makeOne(IFoo)
+        self.assertEqual(list(decl.__bases__), [IFoo])
 
-def test_ObjectSpecification_Simple_old_style():
-    """
-    >>> c = COnly_old()
-    >>> directlyProvides(c, I4)
-    >>> [i.__name__ for i in providedBy(c)]
-    ['I4', 'I3']
-    """
+    def test_ctor_w_implements_in_bases(self):
+        from zope.interface.declarations import Implements
+        impl = Implements()
+        decl = self._makeOne(impl)
+        self.assertEqual(list(decl.__bases__), [impl])
 
+    def test_changed_wo_existing__v_attrs(self):
+        decl = self._makeOne()
+        decl.changed(decl) # doesn't raise
+        self.failIf('_v_attrs' in decl.__dict__)
 
-class Test(unittest.TestCase):
+    def test_changed_w_existing__v_attrs(self):
+        decl = self._makeOne()
+        decl._v_attrs = object()
+        decl.changed(decl)
+        self.failIf('_v_attrs' in decl.__dict__)
 
-    # Note that most of the tests are in the doc strings of the
-    # declarations module.
+    def test___contains__w_self(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        decl = self._makeOne()
+        self.failIf(decl in decl)
 
-    def failUnless(self, expr): # silence deprecation warnings under py3
-        return self.assertTrue(expr)
+    def test___contains__w_unrelated_iface(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        decl = self._makeOne()
+        self.failIf(IFoo in decl)
 
-    def failIf(self, expr): # silence deprecation warnings under py3
-        return self.assertFalse(expr)
+    def test___contains__w_base_interface(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        decl = self._makeOne(IFoo)
+        self.failUnless(IFoo in decl)
 
-    def test_backward_compat(self):
+    def test___iter___empty(self):
+        decl = self._makeOne()
+        self.assertEqual(list(decl), [])
 
-        class C1(object): __implemented__ = I1
-        class C2(C1): __implemented__ = I2, I5
-        class C3(C2): __implemented__ = I3, C2.__implemented__
+    def test___iter___single_base(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        decl = self._makeOne(IFoo)
+        self.assertEqual(list(decl), [IFoo])
 
-        self.failUnless(C3.__implemented__.__class__ is tuple)
+    def test___iter___multiple_bases(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        decl = self._makeOne(IFoo, IBar)
+        self.assertEqual(list(decl), [IFoo, IBar])
 
-        self.assertEqual(
-            [i.getName() for i in providedBy(C3())],
-            ['I3', 'I2', 'I5'],
-            )
+    def test___iter___inheritance(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', (IFoo,))
+        decl = self._makeOne(IBar)
+        self.assertEqual(list(decl), [IBar]) #IBar.interfaces() omits bases
 
-        class C4(C3):
-            implements(I4)
+    def test___iter___w_nested_sequence_overlap(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        decl = self._makeOne(IBar, (IFoo, IBar))
+        self.assertEqual(list(decl), [IBar, IFoo])
 
-        self.assertEqual(
-            [i.getName() for i in providedBy(C4())],
-            ['I4', 'I3', 'I2', 'I5'],
-            )
+    def test_flattened_empty(self):
+        from zope.interface.interface import Interface
+        decl = self._makeOne()
+        self.assertEqual(list(decl.flattened()), [Interface])
 
-        self.assertEqual(
-            [i.getName() for i in C4.__implemented__],
-            ['I4', 'I3', 'I2', 'I5'],
-            )
+    def test_flattened_single_base(self):
+        from zope.interface.interface import Interface
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        decl = self._makeOne(IFoo)
+        self.assertEqual(list(decl.flattened()), [IFoo, Interface])
 
-        # Note that C3.__implemented__ should now be a sequence of interfaces
-        self.assertEqual(
-            [i.getName() for i in C3.__implemented__],
-            ['I3', 'I2', 'I5'],
-            )
-        self.failIf(C3.__implemented__.__class__ is tuple)
+    def test_flattened_multiple_bases(self):
+        from zope.interface.interface import Interface
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        decl = self._makeOne(IFoo, IBar)
+        self.assertEqual(list(decl.flattened()), [IFoo, IBar, Interface])
 
-    def test_module(self):
-        from zope.interface.tests import m1, m2
-        #import zope.interface.tests.m2
-        directlyProvides(m2,
-                         m1.I1,
-                         m1.I2,
-                         )
-        self.assertEqual(list(providedBy(m1)),
-                         list(providedBy(m2)),
-                         )
+    def test_flattened_inheritance(self):
+        from zope.interface.interface import Interface
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', (IFoo,))
+        decl = self._makeOne(IBar)
+        self.assertEqual(list(decl.flattened()), [IBar, IFoo, Interface])
 
-    def test_builtins(self):
-        # Setup
+    def test_flattened_w_nested_sequence_overlap(self):
+        from zope.interface.interface import Interface
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        decl = self._makeOne(IBar, (IFoo, IBar))
+        # Note that decl.__iro__ has IFoo first.
+        self.assertEqual(list(decl.flattened()), [IFoo, IBar, Interface])
 
-        intspec = implementedBy(int)
-        olddeclared = intspec.declared
+    def test___sub___unrelated_interface(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        before = self._makeOne(IFoo)
+        after = before - IBar
+        self.failUnless(isinstance(after, self._getTargetClass()))
+        self.assertEqual(list(after), [IFoo])
 
-        classImplements(int, I1)
-        class myint(int):
-            implements(I2)
+    def test___sub___related_interface(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        before = self._makeOne(IFoo)
+        after = before - IFoo
+        self.assertEqual(list(after), [])
 
-        x = 42
-        self.assertEqual([i.getName() for i in providedBy(x)],
-                         ['I1'])
+    def test___sub___related_interface_by_inheritance(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar', (IFoo,))
+        before = self._makeOne(IBar)
+        after = before - IBar
+        self.assertEqual(list(after), [])
 
-        x = myint(42)
-        directlyProvides(x, I3)
-        self.assertEqual([i.getName() for i in providedBy(x)],
-                         ['I3', 'I2', 'I1'])
+    def test___add___unrelated_interface(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        before = self._makeOne(IFoo)
+        after = before + IBar
+        self.failUnless(isinstance(after, self._getTargetClass()))
+        self.assertEqual(list(after), [IFoo, IBar])
 
-        # cleanup
-        intspec.declared = olddeclared
-        classImplements(int)
+    def test___add___related_interface(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        IBaz = InterfaceClass('IBaz')
+        before = self._makeOne(IFoo, IBar)
+        other = self._makeOne(IBar, IBaz)
+        after = before + other
+        self.assertEqual(list(after), [IFoo, IBar, IBaz])
+ 
 
-        x = 42
-        self.assertEqual([i.getName() for i in providedBy(x)],
-                         [])
+class ImplementsTests(_SilencePy3Deprecations):
 
+    def _getTargetClass(self):
+        from zope.interface.declarations import Implements
+        return Implements
 
-def test_signature_w_no_class_interfaces():
-    """
-    >>> from zope.interface import *
-    >>> class C(object):
-    ...     pass
-    >>> c = C()
-    >>> list(providedBy(c))
-    []
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
+ 
+    def test_ctor_no_bases(self):
+        impl = self._makeOne()
+        self.assertEqual(impl.inherit, None)
+        self.assertEqual(impl.declared, ())
+        self.assertEqual(impl.__name__, '?')
+        self.assertEqual(list(impl.__bases__), [])
+ 
+    def test___repr__(self):
+        impl = self._makeOne()
+        impl.__name__ = 'Testing'
+        self.assertEqual(repr(impl), '<implementedBy Testing>')
+ 
+    def test___reduce__(self):
+        from zope.interface.declarations import implementedBy
+        impl = self._makeOne()
+        self.assertEqual(impl.__reduce__(), (implementedBy, (None,)))
 
-    >>> class I(Interface):
-    ...    pass
-    >>> directlyProvides(c, I)
-    >>> list(providedBy(c))  == list(directlyProvidedBy(c))
-    1
-    """
 
-def test_classImplement_on_deeply_nested_classes():
-    """This test is in response to a bug found, which is why it's a bit
-    contrived
+class Test_implementedByFallback(_SilencePy3Deprecations):
 
-    >>> from zope.interface import *
-    >>> class B1(object):
-    ...     pass
-    >>> class B2(B1):
-    ...     pass
-    >>> class B3(B2):
-    ...     pass
-    >>> class D(object):
-    ...     implements()
-    >>> class S(B3, D):
-    ...     implements()
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import implementedByFallback
+        return implementedByFallback(*args, **kw)
 
-    This failed due to a bug in the code for finding __providedBy__
-    descriptors for old-style classes.
+    def test_dictless_wo_existing_Implements_wo_registrations(self):
+        class Foo(object):
+            __slots__ = ('__implemented__',)
+        foo = Foo()
+        foo.__implemented__ = None
+        self.assertEqual(list(self._callFUT(foo)), [])
 
-    """
+    def test_dictless_wo_existing_Implements_cant_assign___implemented__(self):
+        class Foo(object):
+            def _get_impl(self): return None
+            def _set_impl(self, val): raise TypeError
+            __implemented__ = property(_get_impl, _set_impl)
+            def __call__(self): pass  #act like a factory
+        foo = Foo()
+        self.assertRaises(TypeError, self._callFUT, foo)
 
-def test_pickle_provides_specs():
-    """
-    >>> from pickle import dumps, loads
-    >>> a = A()
-    >>> I2.providedBy(a)
-    0
-    >>> directlyProvides(a, I2)
-    >>> I2.providedBy(a)
-    1
-    >>> a2 = loads(dumps(a))
-    >>> I2.providedBy(a2)
-    1
+    def test_dictless_wo_existing_Implements_w_registrations(self):
+        from zope.interface import declarations
+        class Foo(object):
+            __slots__ = ('__implemented__',)
+        foo = Foo()
+        foo.__implemented__ = None
+        reg = object()
+        specs = {foo: reg}
+        with _Monkey(declarations, BuiltinImplementationSpecifications=specs):
+            self.failUnless(self._callFUT(foo) is reg)
 
-    """
+    def test_dictless_w_existing_Implements(self):
+        from zope.interface.declarations import Implements
+        impl = Implements()
+        class Foo(object):
+            __slots__ = ('__implemented__',)
+        foo = Foo()
+        foo.__implemented__ = impl
+        self.failUnless(self._callFUT(foo) is impl)
 
-def test_that_we_dont_inherit_class_provides():
-    """
-    >>> from zope.interface import classProvides
-    >>> class X(object):
-    ...     classProvides(I1)
-    >>> class Y(X):
-    ...     pass
-    >>> [i.__name__ for i in X.__provides__]
-    ['I1']
-    >>> Y.__provides__
-    Traceback (most recent call last):
-    ...
-    AttributeError: __provides__
+    def test_dictless_w_existing_not_Implements(self):
+        from zope.interface.interface import InterfaceClass
+        class Foo(object):
+            __slots__ = ('__implemented__',)
+        foo = Foo()
+        IFoo = InterfaceClass('IFoo')
+        foo.__implemented__ = (IFoo,)
+        self.assertEqual(list(self._callFUT(foo)), [IFoo])
 
-    """
+    def test_w_existing_attr_as_Implements(self):
+        from zope.interface.declarations import Implements
+        impl = Implements()
+        class Foo(object):
+            __implemented__ = impl
+        self.failUnless(self._callFUT(Foo) is impl)
 
-def test_that_we_dont_inherit_provides_optimizations():
-    """
+    def test_builtins_added_to_cache(self):
+        from zope.interface import declarations
+        from zope.interface.declarations import Implements
+        specs = {}
+        with _Monkey(declarations, BuiltinImplementationSpecifications=specs):
+            self.assertEqual(list(self._callFUT(tuple)), [])
+            self.assertEqual(list(self._callFUT(list)), [])
+            self.assertEqual(list(self._callFUT(dict)), [])
+        for typ in (tuple, list, dict):
+            spec = specs[typ]
+            self.failUnless(isinstance(spec, Implements))
+            self.assertEqual(repr(spec),
+                             '<implementedBy __builtin__.%s>' % typ.__name__)
 
-    When we make a declaration for a class, we install a __provides__
-    descriptors that provides a default for instances that don't have
-    instance-specific declarations:
+    def test_builtins_w_existing_cache(self):
+        from zope.interface import declarations
+        t_spec, l_spec, d_spec = object(), object(), object()
+        specs = {tuple: t_spec, list: l_spec, dict: d_spec}
+        with _Monkey(declarations, BuiltinImplementationSpecifications=specs):
+            self.failUnless(self._callFUT(tuple) is t_spec)
+            self.failUnless(self._callFUT(list) is l_spec)
+            self.failUnless(self._callFUT(dict) is d_spec)
 
-    >>> class A(object):
-    ...     implements(I1)
+    def test_oldstyle_class_no_assertions(self):
+        # TODO: Figure out P3 story
+        class Foo:
+            pass
+        self.assertEqual(list(self._callFUT(Foo)), [])
 
-    >>> class B(object):
-    ...     implements(I2)
+    def test_no_assertions(self):
+        # TODO: Figure out P3 story
+        class Foo(object):
+            pass
+        self.assertEqual(list(self._callFUT(Foo)), [])
 
-    >>> [i.__name__ for i in A().__provides__]
-    ['I1']
-    >>> [i.__name__ for i in B().__provides__]
-    ['I2']
+    def test_w_None_no_bases_not_factory(self):
+        class Foo(object):
+            __implemented__ = None
+        foo = Foo()
+        self.assertRaises(TypeError, self._callFUT, foo)
 
-    But it's important that we don't use this for subclasses without
-    declarations.  This would cause incorrect results:
+    def test_w_None_no_bases_w_factory(self):
+        from zope.interface.declarations import objectSpecificationDescriptor
+        class Foo(object):
+            __implemented__ = None
+            def __call__(self):
+                pass
+        foo = Foo()
+        foo.__name__ = 'foo'
+        spec = self._callFUT(foo)
+        self.assertEqual(spec.__name__,
+                         'zope.interface.tests.test_declarations.foo')
+        self.failUnless(spec.inherit is foo)
+        self.failUnless(foo.__implemented__ is spec)
+        self.failUnless(foo.__providedBy__ is objectSpecificationDescriptor)
+        self.failIf('__provides__' in foo.__dict__)
 
-    >>> class X(A, B):
-    ...     pass
+    def test_w_None_no_bases_w_class(self):
+        from zope.interface.declarations import ClassProvides
+        class Foo(object):
+            __implemented__ = None
+        spec = self._callFUT(Foo)
+        self.assertEqual(spec.__name__,
+                         'zope.interface.tests.test_declarations.Foo')
+        self.failUnless(spec.inherit is Foo)
+        self.failUnless(Foo.__implemented__ is spec)
+        self.failUnless(isinstance(Foo.__providedBy__, ClassProvides))
+        self.failUnless(isinstance(Foo.__provides__, ClassProvides))
+        self.assertEqual(Foo.__provides__, Foo.__providedBy__)
 
-    >>> X().__provides__
-    Traceback (most recent call last):
-    ...
-    AttributeError: __provides__
+    def test_w_existing_Implements(self):
+        from zope.interface.declarations import Implements
+        impl = Implements()
+        class Foo(object):
+            __implemented__ = impl
+        self.failUnless(self._callFUT(Foo) is impl)
 
-    However, if we "induce" a declaration, by calling implementedBy
-    (even indirectly through providedBy):
 
-    >>> [i.__name__ for i in providedBy(X())]
-    ['I1', 'I2']
+class Test_implementedBy(Test_implementedByFallback):
+    # Repeat tests for C optimizations
 
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import implementedBy
+        return implementedBy(*args, **kw)
 
-    then the optimization will work:
 
-    >>> [i.__name__ for i in X().__provides__]
-    ['I1', 'I2']
+class Test_classImplementsOnly(_SilencePy3Deprecations):
 
-    """
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import classImplementsOnly
+        return classImplementsOnly(*args, **kw)
 
-def test_classProvides_before_implements():
-    """Special descriptor for class __provides__
+    def test_no_existing(self):
+        from zope.interface.declarations import ClassProvides
+        from zope.interface.interface import InterfaceClass
+        class Foo(object):
+            pass
+        ifoo = InterfaceClass('IFoo')
+        self._callFUT(Foo, ifoo)
+        spec = Foo.__implemented__
+        self.assertEqual(spec.__name__,
+                         'zope.interface.tests.test_declarations.Foo')
+        self.failUnless(spec.inherit is None)
+        self.failUnless(Foo.__implemented__ is spec)
+        self.failUnless(isinstance(Foo.__providedBy__, ClassProvides))
+        self.failUnless(isinstance(Foo.__provides__, ClassProvides))
+        self.assertEqual(Foo.__provides__, Foo.__providedBy__)
 
-    The descriptor caches the implementedBy info, so that
-    we can get declarations for objects without instance-specific
-    interfaces a bit quicker.
+    def test_w_existing_Implements(self):
+        from zope.interface.declarations import Implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        impl = Implements(IFoo)
+        impl.declared = (IFoo,)
+        class Foo(object):
+            __implemented__ = impl
+        impl.inherit = Foo
+        self._callFUT(Foo, IBar)
+        # Same spec, now different values
+        self.failUnless(Foo.__implemented__ is impl)
+        self.assertEqual(impl.inherit, None)
+        self.assertEqual(impl.declared, (IBar,))
 
-        For example::
 
-          >>> from zope.interface import Interface, classProvides
-          >>> class IFooFactory(Interface):
-          ...     pass
-          >>> class IFoo(Interface):
-          ...     pass
-          >>> class C(object):
-          ...     classProvides(IFooFactory)
-          ...     implements(IFoo)
-          >>> [i.getName() for i in C.__provides__]
-          ['IFooFactory']
+class Test_classImplements(_SilencePy3Deprecations):
 
-          >>> [i.getName() for i in C().__provides__]
-          ['IFoo']
-    """
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import classImplements
+        return classImplements(*args, **kw)
 
-def test_getting_spec_for_proxied_builtin_class():
-    """
+    def test_no_existing(self):
+        from zope.interface.declarations import ClassProvides
+        from zope.interface.interface import InterfaceClass
+        class Foo(object):
+            pass
+        IFoo = InterfaceClass('IFoo')
+        self._callFUT(Foo, IFoo)
+        spec = Foo.__implemented__
+        self.assertEqual(spec.__name__,
+                         'zope.interface.tests.test_declarations.Foo')
+        self.failUnless(spec.inherit is Foo)
+        self.failUnless(Foo.__implemented__ is spec)
+        self.failUnless(isinstance(Foo.__providedBy__, ClassProvides))
+        self.failUnless(isinstance(Foo.__provides__, ClassProvides))
+        self.assertEqual(Foo.__provides__, Foo.__providedBy__)
 
-    In general, we should be able to get a spec
-    for a proxied class if someone has declared or
-    asked for a spec before.
+    def test_w_existing_Implements(self):
+        from zope.interface.declarations import Implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        impl = Implements(IFoo)
+        impl.declared = (IFoo,)
+        class Foo(object):
+            __implemented__ = impl
+        impl.inherit = Foo
+        self._callFUT(Foo, IBar)
+        # Same spec, now different values
+        self.failUnless(Foo.__implemented__ is impl)
+        self.assertEqual(impl.inherit, Foo)
+        self.assertEqual(impl.declared, (IFoo, IBar,))
 
-    We don't want to depend on proxies in this (zope.interface)
-    package, but we do want to work with proxies.  Proxies have the
-    effect that a class's __dict__ cannot be gotten. Further, for
-    built-in classes, we can't save, and thus, cannot get, any class
-    attributes.  We'll emulate this by treating a plain object as a class:
+    def test_w_existing_Implements_w_bases(self):
+        from zope.interface.declarations import Implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        IBaz = InterfaceClass('IBar')
+        b_impl = Implements(IBaz)
+        impl = Implements(IFoo)
+        impl.declared = (IFoo,)
+        class Base(object):
+            __implemented__ = b_impl
+        class Foo(Base):
+            __implemented__ = impl
+        impl.inherit = Foo
+        self._callFUT(Foo, IBar)
+        # Same spec, now different values
+        self.failUnless(Foo.__implemented__ is impl)
+        self.assertEqual(impl.inherit, Foo)
+        self.assertEqual(impl.declared, (IFoo, IBar,))
+        self.assertEqual(impl.__bases__, (IFoo, IBar, b_impl))
 
-      >>> cls = object()
 
-    We'll create an implements specification:
+class Test__implements_advice(_SilencePy3Deprecations):
 
-      >>> import zope.interface.declarations
-      >>> impl = zope.interface.declarations.Implements(I1, I2)
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import _implements_advice
+        return _implements_advice(*args, **kw)
 
-    Now, we'll emulate a declaration for a built-in type by putting
-    it in BuiltinImplementationSpecifications:
+    def test_no_existing_implements(self):
+        from zope.interface.declarations import classImplements
+        from zope.interface.declarations import Implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        class Foo(object):
+            __implements_advice_data__ = ((IFoo,), classImplements)
+        self._callFUT(Foo)
+        self.failIf('__implements_advice_data__' in Foo.__dict__)
+        self.failUnless(isinstance(Foo.__implemented__, Implements))
+        self.assertEqual(list(Foo.__implemented__), [IFoo])
 
-      >>> zope.interface.declarations.BuiltinImplementationSpecifications[
-      ...   cls] = impl
 
-    Now, we should be able to get it back:
+class Test_implementer(_SilencePy3Deprecations):
 
-      >>> implementedBy(cls) is impl
-      True
+    def _getTargetClass(self):
+        from zope.interface.declarations import implementer
+        return implementer
 
-    Of course, we don't want to leave it there. :)
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
 
-      >>> del zope.interface.declarations.BuiltinImplementationSpecifications[
-      ...   cls]
+    def test_oldstyle_class(self):
+        # TODO Py3 story
+        from zope.interface.declarations import ClassProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        class Foo:
+            pass
+        decorator = self._makeOne(IFoo)
+        returned = decorator(Foo)
+        self.failUnless(returned is Foo)
+        spec = Foo.__implemented__
+        self.assertEqual(spec.__name__,
+                         'zope.interface.tests.test_declarations.Foo')
+        self.failUnless(spec.inherit is Foo)
+        self.failUnless(Foo.__implemented__ is spec)
+        self.failUnless(isinstance(Foo.__providedBy__, ClassProvides))
+        self.failUnless(isinstance(Foo.__provides__, ClassProvides))
+        self.assertEqual(Foo.__provides__, Foo.__providedBy__)
 
-    """
+    def test_newstyle_class(self):
+        from zope.interface.declarations import ClassProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        class Foo(object):
+            pass
+        decorator = self._makeOne(IFoo)
+        returned = decorator(Foo)
+        self.failUnless(returned is Foo)
+        spec = Foo.__implemented__
+        self.assertEqual(spec.__name__,
+                         'zope.interface.tests.test_declarations.Foo')
+        self.failUnless(spec.inherit is Foo)
+        self.failUnless(Foo.__implemented__ is spec)
+        self.failUnless(isinstance(Foo.__providedBy__, ClassProvides))
+        self.failUnless(isinstance(Foo.__provides__, ClassProvides))
+        self.assertEqual(Foo.__provides__, Foo.__providedBy__)
 
-def test_declaration_get():
-    """
-    We can get definitions from a declaration:
+    def test_nonclass_cannot_assign_attr(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        decorator = self._makeOne(IFoo)
+        self.assertRaises(TypeError, decorator, object())
 
-        >>> import zope.interface
-        >>> class I1(zope.interface.Interface):
-        ...    a11 = zope.interface.Attribute('a11')
-        ...    a12 = zope.interface.Attribute('a12')
-        >>> class I2(zope.interface.Interface):
-        ...    a21 = zope.interface.Attribute('a21')
-        ...    a22 = zope.interface.Attribute('a22')
-        ...    a12 = zope.interface.Attribute('a212')
-        >>> class I11(I1):
-        ...    a11 = zope.interface.Attribute('a111')
+    def test_nonclass_can_assign_attr(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        class Foo(object):
+            pass
+        foo = Foo()
+        decorator = self._makeOne(IFoo)
+        returned = decorator(foo)
+        self.failUnless(returned is foo)
+        spec = foo.__implemented__
+        self.assertEqual(spec.__name__, '?')
+        self.failUnless(spec.inherit is None)
+        self.failUnless(foo.__implemented__ is spec)
 
-        >>> decl = zope.interface.Declaration(I11, I2)
-        >>> decl.get('a11') is I11.get('a11')
-        True
-        >>> decl.get('a12') is I1.get('a12')
-        True
-        >>> decl.get('a21') is I2.get('a21')
-        True
-        >>> decl.get('a22') is I2.get('a22')
-        True
-        >>> decl.get('a')
-        >>> decl.get('a', 42)
-        42
 
-    We get None even with no interfaces:
+class Test_implementer_only(_SilencePy3Deprecations):
 
-        >>> decl = zope.interface.Declaration()
-        >>> decl.get('a11')
-        >>> decl.get('a11', 42)
-        42
+    def _getTargetClass(self):
+        from zope.interface.declarations import implementer_only
+        return implementer_only
 
-    We get new data if e change interface bases:
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
 
-        >>> decl.__bases__ = I11, I2
-        >>> decl.get('a11') is I11.get('a11')
-        True
-    """
+    def test_function(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        decorator = self._makeOne(IFoo)
+        def _function(): pass
+        self.assertRaises(ValueError, decorator, _function)
 
-def test_classImplements_after_classImplementsOnly_issue_402():
-    """http://www.zope.org/Collectors/Zope3-dev/402
+    def test_method(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        decorator = self._makeOne(IFoo)
+        class Bar:
+            def _method(): pass
+        self.assertRaises(ValueError, decorator, Bar._method)
 
->>> from zope.interface import *
->>> class I1(Interface):
-...     pass
->>> class I2(Interface):
-...     pass
->>> class C:
-...     implements(I1)
->>> class C2:
-...     implementsOnly(I2)
->>> class I3(Interface):
-...     pass
+    def test_oldstyle_class(self):
+        # TODO Py3 story
+        from zope.interface.declarations import Implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        old_spec = Implements(IBar)
+        class Foo:
+            __implemented__ = old_spec
+        decorator = self._makeOne(IFoo)
+        returned = decorator(Foo)
+        self.failUnless(returned is Foo)
+        spec = Foo.__implemented__
+        self.assertEqual(spec.__name__, '?')
+        self.failUnless(spec.inherit is None)
+        self.failUnless(Foo.__implemented__ is spec)
 
->>> [i.__name__ for i in providedBy(C2()).__iro__]
-['I2', 'Interface']
+    def test_newstyle_class(self):
+        from zope.interface.declarations import Implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass('IFoo')
+        IBar = InterfaceClass('IBar')
+        old_spec = Implements(IBar)
+        class Foo(object):
+            __implemented__ = old_spec
+        decorator = self._makeOne(IFoo)
+        returned = decorator(Foo)
+        self.failUnless(returned is Foo)
+        spec = Foo.__implemented__
+        self.assertEqual(spec.__name__, '?')
+        self.failUnless(spec.inherit is None)
+        self.failUnless(Foo.__implemented__ is spec)
 
->>> classImplements(C2, I3)
->>> [i.__name__ for i in providedBy(C2()).__iro__]
-['I2', 'I3', 'Interface']
 
->>> class I4(Interface):
-...     pass
->>> classImplements(C2, I4)
->>> [i.__name__ for i in providedBy(C2()).__iro__]
-['I2', 'I3', 'I4', 'Interface']
+# Test '_implements' by way of 'implements{,Only}', its only callers.
 
+class Test_implementsOnly(_SilencePy3Deprecations):
 
-"""
+    def _getFUT(self):
+        from zope.interface.declarations import implementsOnly
+        return implementsOnly
 
-def test_picklability_of_implements_specifications():
-    """
+    def test_called_once_from_class_w_bases(self):
+        from zope.interface.declarations import implements
+        from zope.interface.declarations import implementsOnly
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        IBar = InterfaceClass("IBar")
+        globs = {'implements': implements,
+                 'implementsOnly': implementsOnly,
+                 'IFoo': IFoo,
+                 'IBar': IBar,
+                }
+        locs = {}
+        CODE = "\n".join([
+            'class Foo(object):',
+            '    implements(IFoo)',
+            'class Bar(Foo):'
+            '    implementsOnly(IBar)',
+            ])
+        # XXX need six-ish majyk here :(
+        exec CODE in globs, locs
+        Bar = locs['Bar']
+        spec = Bar.__implemented__
+        self.assertEqual(list(spec), [IBar])
 
-    Sometimes, we need to pickle implements specs.  We should be able
-    to do so as long as the class is picklable.
+class Test_implements(_SilencePy3Deprecations):
 
-    >>> import pickle
-    >>> pickle.loads(pickle.dumps(implementedBy(C))) is implementedBy(C)
-    True
+    def _getFUT(self):
+        from zope.interface.declarations import implements
+        return implements
 
+    def test_called_from_function(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        globs = {'implements': implements, 'IFoo': IFoo}
+        locs = {}
+        CODE = "\n".join([
+            'def foo():',
+            '    implements(IFoo)'
+            ])
+        # XXX need six-ish majyk here :(
+        exec CODE in globs, locs
+        foo = locs['foo']
+        self.assertRaises(TypeError, foo)
 
-    """
+    def test_called_twice_from_class(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        IBar = InterfaceClass("IBar")
+        globs = {'implements': implements, 'IFoo': IFoo, 'IBar': IBar}
+        locs = {}
+        CODE = "\n".join([
+            'class Foo(object):',
+            '    implements(IFoo)',
+            '    implements(IBar)',
+            ])
+        # XXX need six-ish majyk here :(
+        try:
+            exec CODE in globs, locs
+        except TypeError:
+            pass
+        else:
+            self.fail("Didn't raise TypeError")
 
-def test_provided_by_with_slots():
-    """
+    def test_called_once_from_class(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        globs = {'implements': implements, 'IFoo': IFoo}
+        locs = {}
+        CODE = "\n".join([
+            'class Foo(object):',
+            '    implements(IFoo)',
+            ])
+        # XXX need six-ish majyk here :(
+        exec CODE in globs, locs
+        Foo = locs['Foo']
+        spec = Foo.__implemented__
+        self.assertEqual(list(spec), [IFoo])
 
-    This is an edge case: if the __slots__ of a class contain '__provides__',
-    using providedBy() on that class should still work (this occurs, for
-    example, when providing an adapter for a concrete class.)
 
-    >>> import zope.interface
-    >>> class Slotted(object):
-    ...     __slots__ = ('__provides__')
-    >>> class IFoo(zope.interface.Interface):
-    ...     pass
-    >>> IFoo.providedBy(Slotted)
-    False
+class ProvidesClassTests(_SilencePy3Deprecations):
 
-    """
+    def _getTargetClass(self):
+        from zope.interface.declarations import ProvidesClass
+        return ProvidesClass
 
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
+
+    def test_simple_class_one_interface(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        spec = self._makeOne(Foo, IFoo)
+        self.assertEqual(list(spec), [IFoo])
+
+    def test___reduce__(self):
+        from zope.interface.declarations import Provides # the function
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        spec = self._makeOne(Foo, IFoo)
+        klass, args = spec.__reduce__()
+        self.failUnless(klass is Provides)
+        self.assertEqual(args, (Foo, IFoo))
+
+    def test___get___class(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        spec = self._makeOne(Foo, IFoo)
+        Foo.__provides__ = spec
+        self.failUnless(Foo.__provides__ is spec)
+
+    def test___get___instance(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        spec = self._makeOne(Foo, IFoo)
+        Foo.__provides__ = spec
+        def _test():
+            foo = Foo()
+            return foo.__provides__
+        self.assertRaises(AttributeError, _test)
+
+
+class Test_Provides(_SilencePy3Deprecations):
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import Provides
+        return Provides(*args, **kw)
+
+    def test_no_cached_spec(self):
+        from zope.interface import declarations
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        cache = {}
+        class Foo(object):
+            pass
+        with _Monkey(declarations, InstanceDeclarations=cache):
+            spec = self._callFUT(Foo, IFoo)
+        self.assertEqual(list(spec), [IFoo])
+        self.failUnless(cache[(Foo, IFoo)] is spec)
+
+    def test_w_cached_spec(self):
+        from zope.interface import declarations
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        prior = object()
+        class Foo(object):
+            pass
+        cache = {(Foo, IFoo): prior}
+        with _Monkey(declarations, InstanceDeclarations=cache):
+            spec = self._callFUT(Foo, IFoo)
+        self.failUnless(spec is prior)
+
+
+class Test_directlyProvides(_SilencePy3Deprecations):
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import directlyProvides
+        return directlyProvides(*args, **kw)
+
+    def test_w_normal_object(self):
+        from zope.interface.declarations import ProvidesClass
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        obj = Foo()
+        self._callFUT(obj, IFoo)
+        self.failUnless(isinstance(obj.__provides__, ProvidesClass))
+        self.assertEqual(list(obj.__provides__), [IFoo])
+
+    def test_w_class(self):
+        from zope.interface.declarations import ClassProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        self._callFUT(Foo, IFoo)
+        self.failUnless(isinstance(Foo.__provides__, ClassProvides))
+        self.assertEqual(list(Foo.__provides__), [IFoo])
+
+    def test_w_non_descriptor_aware_metaclass(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class MetaClass(type):
+            def __getattribute__(self, name):
+                # Emulate metaclass whose base is not the type object.
+                if name == '__class__':
+                    return self
+                return type.__getattribute__(self, name)
+        class Foo(object):
+            __metaclass__ = MetaClass
+        obj = Foo()
+        self.assertRaises(TypeError, self._callFUT, obj, IFoo)
+
+    def test_w_classless_object(self):
+        from zope.interface.declarations import ProvidesClass
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        the_dict = {}
+        class Foo(object):
+            def __getattribute__(self, name):
+                # Emulate object w/o any class
+                if name == '__class__':
+                    return None
+                try:
+                    return the_dict[name]
+                except KeyError:
+                    raise AttributeError(name)
+            def __setattr__(self, name, value):
+                the_dict[name] = value
+        obj = Foo()
+        self._callFUT(obj, IFoo)
+        self.failUnless(isinstance(the_dict['__provides__'], ProvidesClass))
+        self.assertEqual(list(the_dict['__provides__']), [IFoo])
+
+
+class Test_alsoProvides(_SilencePy3Deprecations):
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import alsoProvides
+        return alsoProvides(*args, **kw)
+
+    def test_wo_existing_provides(self):
+        from zope.interface.declarations import ProvidesClass
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        obj = Foo()
+        self._callFUT(obj, IFoo)
+        self.failUnless(isinstance(obj.__provides__, ProvidesClass))
+        self.assertEqual(list(obj.__provides__), [IFoo])
+
+    def test_w_existing_provides(self):
+        from zope.interface.declarations import directlyProvides
+        from zope.interface.declarations import ProvidesClass
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        IBar = InterfaceClass("IBar")
+        class Foo(object):
+            pass
+        obj = Foo()
+        directlyProvides(obj, IFoo)
+        self._callFUT(obj, IBar)
+        self.failUnless(isinstance(obj.__provides__, ProvidesClass))
+        self.assertEqual(list(obj.__provides__), [IFoo, IBar])
+
+
+class Test_noLongerProvides(_SilencePy3Deprecations):
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import noLongerProvides
+        return noLongerProvides(*args, **kw)
+
+    def test_wo_existing_provides(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        obj = Foo()
+        self._callFUT(obj, IFoo)
+        self.assertEqual(list(obj.__provides__), [])
+
+    def test_w_existing_provides_hit(self):
+        from zope.interface.declarations import directlyProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        obj = Foo()
+        directlyProvides(obj, IFoo)
+        self._callFUT(obj, IFoo)
+        self.assertEqual(list(obj.__provides__), [])
+
+    def test_w_existing_provides_miss(self):
+        from zope.interface.declarations import directlyProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        IBar = InterfaceClass("IBar")
+        class Foo(object):
+            pass
+        obj = Foo()
+        directlyProvides(obj, IFoo)
+        self._callFUT(obj, IBar)
+        self.assertEqual(list(obj.__provides__), [IFoo])
+
+    def test_w_iface_implemented_by_class(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            implements(IFoo)
+        obj = Foo()
+        self.assertRaises(ValueError, self._callFUT, obj, IFoo)
+
+
+class ClassProvidesBaseFallbackTests(_SilencePy3Deprecations):
+
+    def _getTargetClass(self):
+        from zope.interface.declarations import ClassProvidesBaseFallback
+        return ClassProvidesBaseFallback
+
+    def _makeOne(self, klass, implements):
+        # Don't instantiate directly:  the C version can't have attributes
+        # assigned.
+        class Derived(self._getTargetClass()):
+            def __init__(self, k, i):
+                self._cls = k
+                self._implements = i
+        return Derived(klass, implements)
+
+    def test_w_same_class_via_class(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        cpbp = Foo.__provides__ = self._makeOne(Foo, IFoo)
+        self.failUnless(Foo.__provides__ is cpbp)
+
+    def test_w_same_class_via_instance(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        foo = Foo()
+        cpbp = Foo.__provides__ = self._makeOne(Foo, IFoo)
+        self.failUnless(foo.__provides__ is IFoo)
+
+    def test_w_different_class(self):
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        class Bar(Foo):
+            pass
+        bar = Bar()
+        cpbp = Foo.__provides__ = self._makeOne(Foo, IFoo)
+        self.assertRaises(AttributeError, getattr, Bar, '__provides__')
+        self.assertRaises(AttributeError, getattr, bar, '__provides__')
+
+
+class ClassProvidesBaseTests(ClassProvidesBaseFallbackTests):
+    # Repeat tests for C optimizations
+
+    def _getTargetClass(self):
+        from zope.interface.declarations import ClassProvidesBase
+        return ClassProvidesBase
+
+
+class ClassProvidesTests(_SilencePy3Deprecations):
+
+    def _getTargetClass(self):
+        from zope.interface.declarations import ClassProvides
+        return ClassProvides
+
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
+
+    def test_w_simple_metaclass(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        IBar = InterfaceClass("IBar")
+        class Foo(object):
+            implements(IFoo)
+        cp = Foo.__provides__ = self._makeOne(Foo, type(Foo), IBar)
+        self.failUnless(Foo.__provides__ is cp)
+        self.assertEqual(list(Foo().__provides__), [IFoo])
+
+    def test___reduce__(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        IBar = InterfaceClass("IBar")
+        class Foo(object):
+            implements(IFoo)
+        cp = Foo.__provides__ = self._makeOne(Foo, type(Foo), IBar)
+        self.assertEqual(cp.__reduce__(),
+                         (self._getTargetClass(), (Foo, type(Foo), IBar)))
+
+
+class Test_directlyProvidedBy(_SilencePy3Deprecations):
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import directlyProvidedBy
+        return directlyProvidedBy(*args, **kw)
+
+    def test_wo_declarations_in_class_or_instance(self):
+        class Foo(object):
+            pass
+        foo = Foo()
+        self.assertEqual(list(self._callFUT(foo)), [])
+
+    def test_w_declarations_in_class_but_not_instance(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            implements(IFoo)
+        foo = Foo()
+        self.assertEqual(list(self._callFUT(foo)), [])
+
+    def test_w_declarations_in_instance_but_not_class(self):
+        from zope.interface.declarations import directlyProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        foo = Foo()
+        directlyProvides(foo, IFoo)
+        self.assertEqual(list(self._callFUT(foo)), [IFoo])
+
+    def test_w_declarations_in_instance_and_class(self):
+        from zope.interface.declarations import directlyProvides
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        IBar = InterfaceClass("IBar")
+        class Foo(object):
+            implements(IFoo)
+        foo = Foo()
+        directlyProvides(foo, IBar)
+        self.assertEqual(list(self._callFUT(foo)), [IBar])
+
+
+class Test_classProvides(_SilencePy3Deprecations):
+
+    def _getFUT(self):
+        from zope.interface.declarations import classProvides
+        return classProvides
+
+    def test_called_from_function(self):
+        from zope.interface.declarations import classProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        globs = {'classProvides': classProvides, 'IFoo': IFoo}
+        locs = {}
+        CODE = "\n".join([
+            'def foo():',
+            '    classProvides(IFoo)'
+            ])
+        # XXX need six-ish majyk here :(
+        exec CODE in globs, locs
+        foo = locs['foo']
+        self.assertRaises(TypeError, foo)
+
+    def test_called_twice_from_class(self):
+        from zope.interface.declarations import classProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        IBar = InterfaceClass("IBar")
+        globs = {'classProvides': classProvides, 'IFoo': IFoo, 'IBar': IBar}
+        locs = {}
+        CODE = "\n".join([
+            'class Foo(object):',
+            '    classProvides(IFoo)',
+            '    classProvides(IBar)',
+            ])
+        # XXX need six-ish majyk here :(
+        try:
+            exec CODE in globs, locs
+        except TypeError:
+            pass
+        else:
+            self.fail("Didn't raise TypeError")
+
+    def test_called_once_from_class(self):
+        from zope.interface.declarations import classProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        globs = {'classProvides': classProvides, 'IFoo': IFoo}
+        locs = {}
+        CODE = "\n".join([
+            'class Foo(object):',
+            '    classProvides(IFoo)',
+            ])
+        # XXX need six-ish majyk here :(
+        exec CODE in globs, locs
+        Foo = locs['Foo']
+        spec = Foo.__providedBy__
+        self.assertEqual(list(spec), [IFoo])
+
+
+# Test _classProvides_advice through classProvides, its only caller.
+
+
+class Test_provider(_SilencePy3Deprecations):
+
+    def _getTargetClass(self):
+        from zope.interface.declarations import provider
+        return provider
+
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
+
+    def test_w_class(self):
+        from zope.interface.declarations import ClassProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        @self._makeOne(IFoo)
+        class Foo(object):
+            pass
+        self.failUnless(isinstance(Foo.__provides__, ClassProvides))
+        self.assertEqual(list(Foo.__provides__), [IFoo])
+
+
+class Test_moduleProvides(_SilencePy3Deprecations):
+
+    def _getFUT(self):
+        from zope.interface.declarations import moduleProvides
+        return moduleProvides
+
+    def test_called_from_function(self):
+        from zope.interface.declarations import moduleProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        globs = {'__name__': 'zope.interface.tests.foo',
+                 'moduleProvides': moduleProvides, 'IFoo': IFoo}
+        locs = {}
+        CODE = "\n".join([
+            'def foo():',
+            '    moduleProvides(IFoo)'
+            ])
+        # XXX need six-ish majyk here :(
+        exec CODE in globs, locs
+        foo = locs['foo']
+        self.assertRaises(TypeError, foo)
+
+    def test_called_from_class(self):
+        from zope.interface.declarations import moduleProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        globs = {'__name__': 'zope.interface.tests.foo',
+                 'moduleProvides': moduleProvides, 'IFoo': IFoo}
+        CODE = "\n".join([
+            'class Foo(object):',
+            '    moduleProvides(IFoo)',
+            ])
+        try:
+            # XXX need six-ish majyk here :(
+            exec CODE in globs
+        except TypeError:
+            pass
+        else:
+            assert False, 'TypeError not raised'
+
+    def test_called_once_from_module_scope(self):
+        from zope.interface.declarations import moduleProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        globs = {'__name__': 'zope.interface.tests.foo',
+                 'moduleProvides': moduleProvides, 'IFoo': IFoo}
+        CODE = "\n".join([
+            'moduleProvides(IFoo)',
+            ])
+        # XXX need six-ish majyk here :(
+        exec CODE in globs
+        spec = globs['__provides__']
+        self.assertEqual(list(spec), [IFoo])
+
+    def test_called_twice_from_module_scope(self):
+        from zope.interface.declarations import moduleProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        globs = {'__name__': 'zope.interface.tests.foo',
+                 'moduleProvides': moduleProvides, 'IFoo': IFoo}
+        CODE = "\n".join([
+            'moduleProvides(IFoo)',
+            'moduleProvides(IFoo)',
+            ])
+        try:
+            # XXX need six-ish majyk here :(
+            exec CODE in globs
+        except TypeError:
+            pass
+        else:
+            assert False, 'TypeError not raised'
+
+
+class Test_getObjectSpecificationFallback(_SilencePy3Deprecations):
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import getObjectSpecificationFallback
+        return getObjectSpecificationFallback(*args, **kw)
+
+    def test_wo_existing_provides_classless(self):
+        the_dict = {}
+        class Foo(object):
+            def __getattribute__(self, name):
+                # Emulate object w/o any class
+                if name == '__class__':
+                    raise AttributeError(name)
+                try:
+                    return the_dict[name]
+                except KeyError:
+                    raise AttributeError(name)
+            def __setattr__(self, name, value):
+                the_dict[name] = value
+        foo = Foo()
+        spec = self._callFUT(foo)
+        self.assertEqual(list(spec), [])
+
+    def test_existing_provides_is_spec(self):
+        from zope.interface.declarations import directlyProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        def foo():
+            pass
+        directlyProvides(foo, IFoo)
+        spec = self._callFUT(foo)
+        self.failUnless(spec is foo.__provides__)
+
+    def test_existing_provides_is_not_spec(self):
+        def foo():
+            pass
+        foo.__provides__ = object() # not a valid spec
+        spec = self._callFUT(foo)
+        self.assertEqual(list(spec), [])
+
+    def test_existing_provides(self):
+        from zope.interface.declarations import directlyProvides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        foo = Foo()
+        directlyProvides(foo, IFoo)
+        spec = self._callFUT(foo)
+        self.assertEqual(list(spec), [IFoo])
+
+    def test_wo_provides_on_class_w_implements(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            implements(IFoo)
+        foo = Foo()
+        spec = self._callFUT(foo)
+        self.assertEqual(list(spec), [IFoo])
+
+    def test_wo_provides_on_class_wo_implements(self):
+        class Foo(object):
+            pass
+        foo = Foo()
+        spec = self._callFUT(foo)
+        self.assertEqual(list(spec), [])
+
+
+class Test_getObjectSpecification(Test_getObjectSpecificationFallback):
+    # Repeat tests for C optimizations
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import getObjectSpecification
+        return getObjectSpecification(*args, **kw)
+
+
+class Test_providedByFallback(_SilencePy3Deprecations):
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import providedByFallback
+        return providedByFallback(*args, **kw)
+
+    def test_wo_providedBy_on_class_wo_implements(self):
+        class Foo(object):
+            pass
+        foo = Foo()
+        spec = self._callFUT(foo)
+        self.assertEqual(list(spec), [])
+
+    def test_w_providedBy_valid_spec(self):
+        from zope.interface.declarations import Provides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        foo = Foo()
+        foo.__providedBy__ = Provides(Foo, IFoo)
+        spec = self._callFUT(foo)
+        self.assertEqual(list(spec), [IFoo])
+
+    def test_w_providedBy_invalid_spec(self):
+        class Foo(object):
+            pass
+        foo = Foo()
+        foo.__providedBy__ = object()
+        spec = self._callFUT(foo)
+        self.assertEqual(list(spec), [])
+
+    def test_w_providedBy_invalid_spec_class_w_implements(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            implements(IFoo)
+        foo = Foo()
+        foo.__providedBy__ = object()
+        spec = self._callFUT(foo)
+        self.assertEqual(list(spec), [IFoo])
+
+    def test_w_providedBy_invalid_spec_w_provides_no_provides_on_class(self):
+        class Foo(object):
+            pass
+        foo = Foo()
+        foo.__providedBy__ = object()
+        expected = foo.__provides__ = object()
+        spec = self._callFUT(foo)
+        self.failUnless(spec is expected)
+
+    def test_w_providedBy_invalid_spec_w_provides_diff_provides_on_class(self):
+        class Foo(object):
+            pass
+        foo = Foo()
+        foo.__providedBy__ = object()
+        expected = foo.__provides__ = object()
+        Foo.__provides__ = object()
+        spec = self._callFUT(foo)
+        self.failUnless(spec is expected)
+
+    def test_w_providedBy_invalid_spec_w_provides_same_provides_on_class(self):
+        from zope.interface.declarations import implements
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            implements(IFoo)
+        foo = Foo()
+        foo.__providedBy__ = object()
+        foo.__provides__ = Foo.__provides__ = object()
+        spec = self._callFUT(foo)
+        self.assertEqual(list(spec), [IFoo])
+
+
+class Test_providedBy(Test_providedByFallback):
+    # Repeat tests for C optimizations
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.declarations import providedBy
+        return providedBy(*args, **kw)
+
+
+class ObjectSpecificationDescriptorFallbackTests(_SilencePy3Deprecations):
+
+    def _getTargetClass(self):
+        from zope.interface.declarations \
+            import ObjectSpecificationDescriptorFallback
+        return ObjectSpecificationDescriptorFallback
+
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
+
+    def test_accessed_via_class(self):
+        from zope.interface.declarations import Provides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        class Foo(object):
+            pass
+        Foo.__provides__ = Provides(Foo, IFoo)
+        Foo.__providedBy__ = self._makeOne()
+        self.assertEqual(list(Foo.__providedBy__), [IFoo])
+
+    def test_accessed_via_inst_wo_provides(self):
+        from zope.interface.declarations import implements
+        from zope.interface.declarations import Provides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        IBar = InterfaceClass("IBar")
+        class Foo(object):
+            implements(IFoo)
+        Foo.__provides__ = Provides(Foo, IBar)
+        Foo.__providedBy__ = self._makeOne()
+        foo = Foo()
+        self.assertEqual(list(foo.__providedBy__), [IFoo])
+
+    def test_accessed_via_inst_w_provides(self):
+        from zope.interface.declarations import directlyProvides
+        from zope.interface.declarations import implements
+        from zope.interface.declarations import Provides
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        IBar = InterfaceClass("IBar")
+        IBaz = InterfaceClass("IBaz")
+        class Foo(object):
+            implements(IFoo)
+        Foo.__provides__ = Provides(Foo, IBar)
+        Foo.__providedBy__ = self._makeOne()
+        foo = Foo()
+        directlyProvides(foo, IBaz)
+        self.assertEqual(list(foo.__providedBy__), [IBaz, IFoo])
+
+
+class ObjectSpecificationDescriptorTests(
+                ObjectSpecificationDescriptorFallbackTests):
+    # Repeat tests for C optimizations
+
+    def _getTargetClass(self):
+        from zope.interface.declarations import ObjectSpecificationDescriptor
+        return ObjectSpecificationDescriptor
+
+
+# Test _normalizeargs through its callers.
+
+
+class _Monkey(object):
+    # context-manager for replacing module names in the scope of a test.
+    def __init__(self, module, **kw):
+        self.module = module
+        self.to_restore = dict([(key, getattr(module, key)) for key in kw])
+        for key, value in kw.items():
+            setattr(module, key, value)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        for key, value in self.to_restore.items():
+            setattr(self.module, key, value)
+
+
 def test_suite():
     return unittest.TestSuite((
-        unittest.makeSuite(Test),
-        doctest.DocTestSuite("zope.interface.declarations"),
-        doctest.DocTestSuite(),
+        unittest.makeSuite(DeclarationTests),
+        unittest.makeSuite(ImplementsTests),
+        unittest.makeSuite(Test_implementedByFallback),
+        unittest.makeSuite(Test_implementedBy),
+        unittest.makeSuite(Test_classImplementsOnly),
+        unittest.makeSuite(Test_classImplements),
+        unittest.makeSuite(Test__implements_advice),
+        unittest.makeSuite(Test_implementer),
+        unittest.makeSuite(Test_implementer_only),
+        unittest.makeSuite(Test_implements),
+        unittest.makeSuite(Test_implementsOnly),
+        unittest.makeSuite(ProvidesClassTests),
+        unittest.makeSuite(Test_Provides),
+        unittest.makeSuite(Test_directlyProvides),
+        unittest.makeSuite(Test_alsoProvides),
+        unittest.makeSuite(Test_noLongerProvides),
+        unittest.makeSuite(ClassProvidesBaseFallbackTests),
+        unittest.makeSuite(ClassProvidesTests),
+        unittest.makeSuite(Test_directlyProvidedBy),
+        unittest.makeSuite(Test_classProvides),
+        unittest.makeSuite(Test_provider),
+        unittest.makeSuite(Test_moduleProvides),
+        unittest.makeSuite(Test_getObjectSpecificationFallback),
+        unittest.makeSuite(Test_getObjectSpecification),
+        unittest.makeSuite(Test_providedByFallback),
+        unittest.makeSuite(Test_providedBy),
+        unittest.makeSuite(ObjectSpecificationDescriptorFallbackTests),
+        unittest.makeSuite(ObjectSpecificationDescriptorTests),
     ))

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_document.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_document.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_document.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -13,57 +13,274 @@
 ##############################################################################
 """Documentation tests.
 """
-from unittest import TestCase, main, makeSuite
+import unittest 
 
-from zope.interface import Interface, Attribute
 
-class Test(TestCase):
+class Test_asStructuredText(unittest.TestCase):
 
-    def testBlech(self):
+    def _callFUT(self, iface):
         from zope.interface.document import asStructuredText
+        return asStructuredText(iface)
 
-        self.assertEqual(asStructuredText(I2), '''\
-I2
+    def test_asStructuredText_no_docstring(self):
+        from zope.interface import Interface
+        EXPECTED = '\n\n'.join([
+            "INoDocstring",
+            " Attributes:",
+            " Methods:",
+            ""
+        ])
+        class INoDocstring(Interface):
+            pass
+        self.assertEqual(self._callFUT(INoDocstring), EXPECTED)
 
- I2 doc
+    def test_asStructuredText_empty_with_docstring(self):
+        from zope.interface import Interface
+        EXPECTED = '\n\n'.join([
+            "IEmpty",
+            " This is an empty interface.",
+            " Attributes:",
+            " Methods:",
+            ""
+        ])
+        class IEmpty(Interface):
+            """ This is an empty interface.
+            """
+        self.assertEqual(self._callFUT(IEmpty), EXPECTED)
 
- This interface extends:
+    def test_asStructuredText_empty_with_multiline_docstring(self):
+        from zope.interface import Interface
+        EXPECTED = '\n'.join([
+            "IEmpty",
+            "",
+            " This is an empty interface.",
+            " ",
+            ("             It can be used to annotate any class or object, "
+                             "because it promises"),
+            "             nothing.",
+            "",
+            " Attributes:",
+            "",
+            " Methods:",
+            "",
+            ""
+        ])
+        class IEmpty(Interface):
+            """ This is an empty interface.
 
-  o _I1
+            It can be used to annotate any class or object, because it promises
+            nothing.
+            """
+        self.assertEqual(self._callFUT(IEmpty), EXPECTED)
 
- Attributes:
+    def test_asStructuredText_with_attribute_no_docstring(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+        EXPECTED = '\n\n'.join([
+            "IHasAttribute",
+            " This interface has an attribute.",
+            " Attributes:",
+            "  an_attribute -- no documentation",
+            " Methods:",
+            ""
+        ])
+        class IHasAttribute(Interface):
+            """ This interface has an attribute.
+            """
+            an_attribute = Attribute('an_attribute')
 
-  a1 -- no documentation
+        self.assertEqual(self._callFUT(IHasAttribute), EXPECTED)
 
-  a2 -- a2 doc
+    def test_asStructuredText_with_attribute_with_docstring(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+        EXPECTED = '\n\n'.join([
+            "IHasAttribute",
+            " This interface has an attribute.",
+            " Attributes:",
+            "  an_attribute -- This attribute is documented.",
+            " Methods:",
+            ""
+        ])
+        class IHasAttribute(Interface):
+            """ This interface has an attribute.
+            """
+            an_attribute = Attribute('an_attribute',
+                                     'This attribute is documented.')
 
- Methods:
+        self.assertEqual(self._callFUT(IHasAttribute), EXPECTED)
 
-  f21() -- f21 doc
+    def test_asStructuredText_with_method_no_args_no_docstring(self):
+        from zope.interface import Interface
+        EXPECTED = '\n\n'.join([
+            "IHasMethod",
+            " This interface has a method.",
+            " Attributes:",
+            " Methods:",
+            "  aMethod() -- no documentation",
+            ""
+        ])
+        class IHasMethod(Interface):
+            """ This interface has a method.
+            """
+            def aMethod():
+                pass
 
-  f22() -- no documentation
+        self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
 
-  f23() -- f23 doc
+    def test_asStructuredText_with_method_positional_args_no_docstring(self):
+        from zope.interface import Interface
+        EXPECTED = '\n\n'.join([
+            "IHasMethod",
+            " This interface has a method.",
+            " Attributes:",
+            " Methods:",
+            "  aMethod(first, second) -- no documentation",
+            ""
+        ])
+        class IHasMethod(Interface):
+            """ This interface has a method.
+            """
+            def aMethod(first, second):
+                pass
 
-''')
+        self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
 
+    def test_asStructuredText_with_method_starargs_no_docstring(self):
+        from zope.interface import Interface
+        EXPECTED = '\n\n'.join([
+            "IHasMethod",
+            " This interface has a method.",
+            " Attributes:",
+            " Methods:",
+            "  aMethod(first, second, *rest) -- no documentation",
+            ""
+        ])
+        class IHasMethod(Interface):
+            """ This interface has a method.
+            """
+            def aMethod(first, second, *rest):
+                pass
 
-def test_suite():
-    return makeSuite(Test)
+        self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
 
-class _I1(Interface):
-    def f11(): pass
-    def f12(): pass
+    def test_asStructuredText_with_method_kwargs_no_docstring(self):
+        from zope.interface import Interface
+        EXPECTED = '\n\n'.join([
+            "IHasMethod",
+            " This interface has a method.",
+            " Attributes:",
+            " Methods:",
+            "  aMethod(first, second, **kw) -- no documentation",
+            ""
+        ])
+        class IHasMethod(Interface):
+            """ This interface has a method.
+            """
+            def aMethod(first, second, **kw):
+                pass
 
-class I2(_I1):
-    "I2 doc"
+        self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
 
-    a1 = Attribute('a1')
-    a2 = Attribute('a2', 'a2 doc')
+    def test_asStructuredText_with_method_with_docstring(self):
+        from zope.interface import Interface
+        EXPECTED = '\n\n'.join([
+            "IHasMethod",
+            " This interface has a method.",
+            " Attributes:",
+            " Methods:",
+            "  aMethod() -- This method is documented.",
+            ""
+        ])
+        class IHasMethod(Interface):
+            """ This interface has a method.
+            """
+            def aMethod():
+                """This method is documented.
+                """
 
-    def f21(): "f21 doc"
-    def f22(): pass
-    def f23(): "f23 doc"
+        self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
 
-if __name__=='__main__':
-    main(defaultTest='test_suite')
+    def test_asStructuredText_derived_ignores_base(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+        EXPECTED = '\n\n'.join([
+            "IDerived",
+            " IDerived doc",
+            " This interface extends:",
+            "  o IBase",
+            " Attributes:",
+            "  attr1 -- no documentation",
+            "  attr2 -- attr2 doc",
+            " Methods:",
+            "  method3() -- method3 doc",
+            "  method4() -- no documentation",
+            "  method5() -- method5 doc",
+            "",
+        ])
+
+        class IBase(Interface):
+            def method1():
+                pass
+            def method2():
+                pass
+
+        class IDerived(IBase):
+            "IDerived doc"
+            attr1 = Attribute('attr1')
+            attr2 = Attribute('attr2', 'attr2 doc')
+
+            def method3():
+                "method3 doc"
+            def method4():
+                pass
+            def method5():
+                "method5 doc"
+
+        self.assertEqual(self._callFUT(IDerived), EXPECTED)
+
+class Test__justify_and_indent(unittest.TestCase):
+
+    def _callFUT(self, text, level, **kw):
+        from zope.interface.document import _justify_and_indent
+        return _justify_and_indent(text, level, **kw)
+
+    def test_simple_level_0(self):
+        LINES = ['Three blind mice', 'See how they run']
+        text = '\n'.join(LINES)
+        self.assertEqual(self._callFUT(text, 0), text)
+
+    def test_simple_level_1(self):
+        LINES = ['Three blind mice', 'See how they run']
+        text = '\n'.join(LINES)
+        self.assertEqual(self._callFUT(text, 1),
+                         '\n'.join([' ' + line for line in LINES]))
+
+    def test_simple_level_2(self):
+        LINES = ['Three blind mice', 'See how they run']
+        text = '\n'.join(LINES)
+        self.assertEqual(self._callFUT(text, 1),
+                         '\n'.join([' ' + line for line in LINES]))
+
+    def test_simple_w_CRLF(self):
+        LINES = ['Three blind mice', 'See how they run']
+        text = '\r\n'.join(LINES)
+        self.assertEqual(self._callFUT(text, 1),
+                         '\n'.join([' ' + line for line in LINES]))
+
+    def test_with_munge(self):
+        TEXT = ("This is a piece of text longer than 15 characters, \n"
+                "and split across multiple lines.")
+        EXPECTED = ("  This is a piece\n"
+                    "  of text longer\n"
+                    "  than 15 characters,\n"
+                    "  and split across\n"
+                    "  multiple lines.\n"
+                    " ")
+        self.assertEqual(self._callFUT(TEXT, 1, munge=1, width=15), EXPECTED)
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(Test_asStructuredText),
+        unittest.makeSuite(Test__justify_and_indent),
+    ))

Added: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_exceptions.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_exceptions.py	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_exceptions.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,75 @@
+##############################################################################
+#
+# Copyright (c) 2010 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" zope.interface.exceptions unit tests
+"""
+import unittest
+
+def _makeIface():
+    from zope.interface import Interface
+    class IDummy(Interface):
+        pass
+    return IDummy
+
+class DoesNotImplementTests(unittest.TestCase):
+
+    def _getTargetClass(self):
+        from zope.interface.exceptions import DoesNotImplement
+        return DoesNotImplement
+
+    def _makeOne(self, iface=None):
+        if iface is None:
+            iface = _makeIface()
+        return self._getTargetClass()(iface)
+
+    def test___str__(self):
+        dni = self._makeOne()
+        # XXX The trailing newlines and blank spaces are a stupid artifact.
+        self.assertEqual(str(dni),
+            'An object does not implement interface <InterfaceClass '
+               'zope.interface.tests.test_exceptions.IDummy>\n\n        ')
+
+class BrokenImplementationTests(unittest.TestCase):
+
+    def _getTargetClass(self):
+        from zope.interface.exceptions import BrokenImplementation
+        return BrokenImplementation
+
+    def _makeOne(self, iface=None, name='missing'):
+        if iface is None:
+            iface = _makeIface()
+        return self._getTargetClass()(iface, name)
+
+    def test___str__(self):
+        dni = self._makeOne()
+        # XXX The trailing newlines and blank spaces are a stupid artifact.
+        self.assertEqual(str(dni),
+            'An object has failed to implement interface <InterfaceClass '
+               'zope.interface.tests.test_exceptions.IDummy>\n\n'
+               '        The missing attribute was not provided.\n        ')
+
+class BrokenMethodImplementationTests(unittest.TestCase):
+
+    def _getTargetClass(self):
+        from zope.interface.exceptions import BrokenMethodImplementation
+        return BrokenMethodImplementation
+
+    def _makeOne(self, method='aMethod', mess='I said so'):
+        return self._getTargetClass()(method, mess)
+
+    def test___str__(self):
+        dni = self._makeOne()
+        self.assertEqual(str(dni),
+            'The implementation of aMethod violates its contract\n'
+             '        because I said so.\n        ')
+

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_interface.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_interface.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_interface.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -13,316 +13,1597 @@
 ##############################################################################
 """Test Interface implementation
 """
-from __future__ import with_statement
-
-import doctest
 import unittest
-import sys
 
-class InterfaceTests(unittest.TestCase):
+_marker = object()
 
-    def failUnless(self, expr): # silence deprecation warnings under py3
+class _SilencePy3Deprecations(unittest.TestCase):
+    # silence deprecation warnings under py3
+
+    def failUnless(self, expr):
+        # St00pid speling.
         return self.assertTrue(expr)
 
-    def failIf(self, expr): # silence deprecation warnings under py3
+    def failIf(self, expr):
+        # St00pid speling.
         return self.assertFalse(expr)
 
-    def _makeDerivedInterface(self):
+
+class Test_invariant(unittest.TestCase):
+
+    def test_w_single(self):
+        from zope.interface.interface import invariant
+        from zope.interface.interface import TAGGED_DATA
+
+        def _check(*args, **kw):
+            pass
+
+        class Foo(object):
+            invariant(_check)
+
+        self.assertEqual(getattr(Foo, TAGGED_DATA, None),
+                         {'invariants': [_check]})
+
+    def test_w_multiple(self):
+        from zope.interface.interface import invariant
+        from zope.interface.interface import TAGGED_DATA
+
+        def _check(*args, **kw):
+            pass
+
+        def _another_check(*args, **kw):
+            pass
+
+        class Foo(object):
+            invariant(_check)
+            invariant(_another_check)
+
+        self.assertEqual(getattr(Foo, TAGGED_DATA, None),
+                         {'invariants': [_check, _another_check]})
+
+
+class Test_taggedValue(unittest.TestCase):
+
+    def test_w_single(self):
+        from zope.interface.interface import taggedValue
+        from zope.interface.interface import TAGGED_DATA
+
+        class Foo(object):
+            taggedValue('bar', ['baz'])
+
+        self.assertEqual(getattr(Foo, TAGGED_DATA, None),
+                         {'bar': ['baz']})
+
+    def test_w_multiple(self):
+        from zope.interface.interface import taggedValue
+        from zope.interface.interface import TAGGED_DATA
+
+        class Foo(object):
+            taggedValue('bar', ['baz'])
+            taggedValue('qux', 'spam')
+
+        self.assertEqual(getattr(Foo, TAGGED_DATA, None),
+                         {'bar': ['baz'], 'qux': 'spam'})
+
+    def test_w_multiple_overwriting(self):
+        from zope.interface.interface import taggedValue
+        from zope.interface.interface import TAGGED_DATA
+
+        class Foo(object):
+            taggedValue('bar', ['baz'])
+            taggedValue('qux', 'spam')
+            taggedValue('bar', 'frob')
+
+        self.assertEqual(getattr(Foo, TAGGED_DATA, None),
+                         {'bar': 'frob', 'qux': 'spam'})
+
+
+class ElementTests(unittest.TestCase):
+
+    DEFAULT_NAME = 'AnElement'
+
+    def _getTargetClass(self):
+        from zope.interface.interface import Element
+        return Element
+
+    def _makeOne(self,  name=None, __doc__=_marker):
+        if name is None:
+            name = self.DEFAULT_NAME
+        if __doc__ is _marker:
+            return self._getTargetClass()(name)
+        return self._getTargetClass()(name, __doc__)
+
+    def test_ctor_defaults(self):
+        element = self._makeOne()
+        self.assertEqual(element.__name__, self.DEFAULT_NAME)
+        self.assertEqual(element.getName(), self.DEFAULT_NAME)
+        self.assertEqual(element.__doc__, '')
+        self.assertEqual(element.getDoc(), '')
+        self.assertEqual(element.getTaggedValueTags(), [])
+
+    def test_ctor_no_doc_space_in_name(self):
+        element = self._makeOne('An Element')
+        self.assertEqual(element.__name__, None)
+        self.assertEqual(element.__doc__, 'An Element')
+
+    def test_getTaggedValue_miss(self):
+        element = self._makeOne()
+        self.assertRaises(KeyError, element.getTaggedValue, 'nonesuch')
+
+    def test_queryTaggedValue_miss(self):
+        element = self._makeOne()
+        self.assertEqual(element.queryTaggedValue('nonesuch'), None)
+
+    def test_queryTaggedValue_miss_w_default(self):
+        element = self._makeOne()
+        self.assertEqual(element.queryTaggedValue('nonesuch', 'bar'), 'bar')
+
+    def test_setTaggedValue(self):
+        element = self._makeOne()
+        element.setTaggedValue('foo', 'bar')
+        self.assertEqual(element.getTaggedValueTags(), ['foo'])
+        self.assertEqual(element.getTaggedValue('foo'), 'bar')
+        self.assertEqual(element.queryTaggedValue('foo'), 'bar')
+
+
+class SpecificationBasePyTests(_SilencePy3Deprecations):
+
+    def _getTargetClass(self):
+        from zope.interface.interface import SpecificationBasePy
+        return SpecificationBasePy
+
+    def _makeOne(self):
+        return self._getTargetClass()()
+
+    def test_providedBy_miss(self):
+        from zope.interface import interface
+        from zope.interface.declarations import _empty
+        sb = self._makeOne()
+        def _providedBy(obj):
+            return _empty
+        with _Monkey(interface, providedBy=_providedBy):
+            self.failIf(sb.providedBy(object()))
+
+    def test_providedBy_hit(self):
+        from zope.interface import interface
+        sb = self._makeOne()
+        class _Decl(object):
+            _implied = {sb: {},}
+        def _providedBy(obj):
+            return _Decl()
+        with _Monkey(interface, providedBy=_providedBy):
+            self.failUnless(sb.providedBy(object()))
+
+    def test_implementedBy_miss(self):
+        from zope.interface import interface
+        from zope.interface.declarations import _empty
+        sb = self._makeOne()
+        def _implementedBy(obj):
+            return _empty
+        with _Monkey(interface, implementedBy=_implementedBy):
+            self.failIf(sb.implementedBy(object()))
+
+    def test_implementedBy_hit(self):
+        from zope.interface import interface
+        sb = self._makeOne()
+        class _Decl(object):
+            _implied = {sb: {},}
+        def _implementedBy(obj):
+            return _Decl()
+        with _Monkey(interface, implementedBy=_implementedBy):
+            self.failUnless(sb.implementedBy(object()))
+
+    def test_isOrExtends_miss(self):
+        sb = self._makeOne()
+        sb._implied = {}  # not defined by SpecificationBasePy 
+        self.failIf(sb.isOrExtends(object()))
+
+    def test_isOrExtends_hit(self):
+        sb = self._makeOne()
+        testing = object()
+        sb._implied = {testing: {}}  # not defined by SpecificationBasePy 
+        self.failUnless(sb(testing))
+
+    def test___call___miss(self):
+        sb = self._makeOne()
+        sb._implied = {}  # not defined by SpecificationBasePy 
+        self.failIf(sb.isOrExtends(object()))
+
+    def test___call___hit(self):
+        sb = self._makeOne()
+        testing = object()
+        sb._implied = {testing: {}}  # not defined by SpecificationBasePy 
+        self.failUnless(sb(testing))
+
+
+class InterfaceBasePyTests(_SilencePy3Deprecations):
+
+    def _getTargetClass(self):
+        from zope.interface.interface import InterfaceBasePy
+        return InterfaceBasePy
+
+    def _makeOne(self, object_should_provide):
+        class IB(self._getTargetClass()):
+            def _call_conform(self, conform):
+                return conform(self)
+            def providedBy(self, obj):
+                return object_should_provide
+        return IB()
+
+    def test___call___w___conform___returning_value(self):
+        ib = self._makeOne(False)
+        conformed = object()
+        class _Adapted(object):
+            def __conform__(self, iface):
+                return conformed
+        self.failUnless(ib(_Adapted()) is conformed)
+
+    def test___call___w___conform___miss_ob_provides(self):
+        ib = self._makeOne(True)
+        class _Adapted(object):
+            def __conform__(self, iface):
+                return None
+        adapted = _Adapted()
+        self.failUnless(ib(adapted) is adapted)
+
+    def test___call___wo___conform___ob_no_provides_w_alternate(self):
+        ib = self._makeOne(False)
+        adapted = object()
+        alternate = object()
+        self.failUnless(ib(adapted, alternate) is alternate)
+
+    def test___call___w___conform___ob_no_provides_wo_alternate(self):
+        ib = self._makeOne(False)
+        adapted = object()
+        self.assertRaises(TypeError, ib, adapted)
+
+    def test___adapt___ob_provides(self):
+        ib = self._makeOne(True)
+        adapted = object()
+        self.failUnless(ib.__adapt__(adapted) is adapted)
+
+    def test___adapt___ob_no_provides_uses_hooks(self):
+        from zope.interface import interface
+        ib = self._makeOne(False)
+        adapted = object()
+        _missed = []
+        def _hook_miss(iface, obj):
+            _missed.append((iface, obj))
+            return None
+        def _hook_hit(iface, obj):
+            return obj
+        with _Monkey(interface, adapter_hooks=[_hook_miss, _hook_hit]):
+            self.failUnless(ib.__adapt__(adapted) is adapted)
+            self.assertEqual(_missed, [(ib, adapted)])
+
+
+class SpecificationTests(_SilencePy3Deprecations):
+
+    def _getTargetClass(self):
+        from zope.interface.interface import Specification
+        return Specification
+
+    def _makeOne(self, bases=_marker):
+        if bases is _marker:
+            return self._getTargetClass()()
+        return self._getTargetClass()(bases)
+
+    def test_ctor(self):
+        from zope.interface.interface import Interface
+        spec = self._makeOne()
+        self.assertEqual(spec.__bases__, ())
+        self.assertEqual(len(spec._implied), 2)
+        self.failUnless(spec in spec._implied)
+        self.failUnless(Interface in spec._implied)
+        self.assertEqual(len(spec.dependents), 0)
+
+    def test_subscribe_first_time(self):
+        spec = self._makeOne()
+        dep = DummyDependent()
+        spec.subscribe(dep)
+        self.assertEqual(len(spec.dependents), 1)
+        self.assertEqual(spec.dependents[dep], 1)
+
+    def test_subscribe_again(self):
+        spec = self._makeOne()
+        dep = DummyDependent()
+        spec.subscribe(dep)
+        spec.subscribe(dep)
+        self.assertEqual(spec.dependents[dep], 2)
+
+    def test_unsubscribe_miss(self):
+        spec = self._makeOne()
+        dep = DummyDependent()
+        self.assertRaises(KeyError, spec.unsubscribe, dep)
+
+    def test_unsubscribe(self):
+        spec = self._makeOne()
+        dep = DummyDependent()
+        spec.subscribe(dep)
+        spec.subscribe(dep)
+        spec.unsubscribe(dep)
+        self.assertEqual(spec.dependents[dep], 1)
+        spec.unsubscribe(dep)
+        self.failIf(dep in spec.dependents)
+
+    def test___setBases_subscribes_bases_and_notifies_dependents(self):
+        from zope.interface.interface import Interface
+        spec = self._makeOne()
+        dep = DummyDependent()
+        spec.subscribe(dep)
+        class I(Interface):
+            pass
+        class J(Interface):
+            pass
+        spec.__bases__ = (I,)
+        self.assertEqual(dep._changed, [spec])
+        self.assertEqual(I.dependents[spec], 1)
+        spec.__bases__ = (J,)
+        self.assertEqual(I.dependents.get(spec), None)
+        self.assertEqual(J.dependents[spec], 1)
+
+    def test_changed_clears_volatiles_and_implied(self):
+        from zope.interface.interface import Interface
+        class I(Interface):
+            pass
+        spec = self._makeOne()
+        spec._v_attrs = 'Foo'
+        spec._implied[I] = ()
+        spec.changed(spec)
+        self.assert_(getattr(spec, '_v_attrs', self) is self)
+        self.failIf(I in spec._implied)
+
+
+class InterfaceClassTests(_SilencePy3Deprecations):
+
+    def _getTargetClass(self):
+        from zope.interface.interface import InterfaceClass
+        return InterfaceClass
+
+    def _makeOne(self,  name='ITest', bases=(), attrs=None, __doc__=None,
+                 __module__=None):
+        return self._getTargetClass()(name, bases, attrs, __doc__, __module__)
+
+    def test_ctor_defaults(self):
+        klass = self._getTargetClass()
+        inst = klass('ITesting')
+        self.assertEqual(inst.__name__, 'ITesting')
+        self.assertEqual(inst.__doc__, '')
+        self.assertEqual(inst.__bases__, ())
+        self.assertEqual(inst.getBases(), ())
+
+    def test_ctor_bad_bases(self):
+        klass = self._getTargetClass()
+        self.assertRaises(TypeError, klass, 'ITesting', (object(),))
+
+    def test_ctor_w_attrs_attrib_methods(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        ATTRS = {'foo': Attribute('Foo', ''),
+                 'bar': fromFunction(_bar),
+                }
+        klass = self._getTargetClass()
+        inst = klass('ITesting', attrs=ATTRS)
+        self.assertEqual(inst.__name__, 'ITesting')
+        self.assertEqual(inst.__doc__, '')
+        self.assertEqual(inst.__bases__, ())
+        self.assertEqual(inst.names(), ATTRS.keys())
+
+    def test_ctor_attrs_w___locals__(self):
+        ATTRS = {'__locals__': {}}
+        klass = self._getTargetClass()
+        inst = klass('ITesting', attrs=ATTRS)
+        self.assertEqual(inst.__name__, 'ITesting')
+        self.assertEqual(inst.__doc__, '')
+        self.assertEqual(inst.__bases__, ())
+        self.assertEqual(inst.names(), ATTRS.keys())
+
+    def test_ctor_attrs_w__decorator_non_return(self):
+        from zope.interface.interface import _decorator_non_return
+        ATTRS = {'dropme': _decorator_non_return}
+        klass = self._getTargetClass()
+        inst = klass('ITesting', attrs=ATTRS)
+        self.assertEqual(inst.__name__, 'ITesting')
+        self.assertEqual(inst.__doc__, '')
+        self.assertEqual(inst.__bases__, ())
+        self.assertEqual(inst.names(), [])
+
+    def test_ctor_attrs_w_invalide_attr_type(self):
+        from zope.interface.exceptions import InvalidInterface
+        ATTRS = {'invalid': object()}
+        klass = self._getTargetClass()
+        self.assertRaises(InvalidInterface, klass, 'ITesting', attrs=ATTRS)
+
+    def test_interfaces(self):
+        iface = self._makeOne()
+        self.assertEqual(list(iface.interfaces()), [iface])
+
+    def test_getBases(self):
+        iface = self._makeOne()
+        sub = self._makeOne('ISub', bases=(iface,))
+        self.assertEqual(sub.getBases(), (iface,))
+
+    def test_isEqualOrExtendedBy_identity(self):
+        iface = self._makeOne()
+        self.failUnless(iface.isEqualOrExtendedBy(iface))
+
+    def test_isEqualOrExtendedBy_subiface(self):
+        iface = self._makeOne()
+        sub = self._makeOne('ISub', bases=(iface,))
+        self.failUnless(iface.isEqualOrExtendedBy(sub))
+        self.failIf(sub.isEqualOrExtendedBy(iface))
+
+    def test_isEqualOrExtendedBy_unrelated(self):
+        one = self._makeOne('One')
+        another = self._makeOne('Another')
+        self.failIf(one.isEqualOrExtendedBy(another))
+        self.failIf(another.isEqualOrExtendedBy(one))
+
+    def test_names_w_all_False_ignores_bases(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        BASE_ATTRS = {'foo': Attribute('Foo', ''),
+                      'bar': fromFunction(_bar),
+                     }
+        DERIVED_ATTRS = {'baz': Attribute('Baz', ''),
+                        }
+        base = self._makeOne('IBase', attrs=BASE_ATTRS)
+        derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+        self.assertEqual(sorted(derived.names(all=False)), ['baz'])
+
+    def test_names_w_all_True_no_bases(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        ATTRS = {'foo': Attribute('Foo', ''),
+                 'bar': fromFunction(_bar),
+                }
+        one = self._makeOne(attrs=ATTRS)
+        self.assertEqual(sorted(one.names(all=True)), ['bar', 'foo'])
+
+    def test_names_w_all_True_w_bases_simple(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        BASE_ATTRS = {'foo': Attribute('Foo', ''),
+                      'bar': fromFunction(_bar),
+                     }
+        DERIVED_ATTRS = {'baz': Attribute('Baz', ''),
+                        }
+        base = self._makeOne('IBase', attrs=BASE_ATTRS)
+        derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+        self.assertEqual(sorted(derived.names(all=True)), ['bar', 'baz', 'foo'])
+
+    def test_names_w_all_True_bases_w_same_names(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        def _foo():
+            """DOCSTRING"""
+        BASE_ATTRS = {'foo': Attribute('Foo', ''),
+                      'bar': fromFunction(_bar),
+                     }
+        DERIVED_ATTRS = {'foo': fromFunction(_foo),
+                         'baz': Attribute('Baz', ''),
+                        }
+        base = self._makeOne('IBase', attrs=BASE_ATTRS)
+        derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+        self.assertEqual(sorted(derived.names(all=True)), ['bar', 'baz', 'foo'])
+
+    def test___iter__(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        def _foo():
+            """DOCSTRING"""
+        BASE_ATTRS = {'foo': Attribute('Foo', ''),
+                      'bar': fromFunction(_bar),
+                     }
+        DERIVED_ATTRS = {'foo': fromFunction(_foo),
+                         'baz': Attribute('Baz', ''),
+                        }
+        base = self._makeOne('IBase', attrs=BASE_ATTRS)
+        derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+        self.assertEqual(sorted(derived), ['bar', 'baz', 'foo'])
+
+    def test_namesAndDescriptions_w_all_False_ignores_bases(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        BASE_ATTRS = {'foo': Attribute('Foo', ''),
+                      'bar': fromFunction(_bar),
+                     }
+        DERIVED_ATTRS = {'baz': Attribute('Baz', ''),
+                        }
+        base = self._makeOne('IBase', attrs=BASE_ATTRS)
+        derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+        self.assertEqual(sorted(derived.namesAndDescriptions(all=False)),
+                        [('baz', DERIVED_ATTRS['baz']),
+                        ])
+
+    def test_namesAndDescriptions_w_all_True_no_bases(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        ATTRS = {'foo': Attribute('Foo', ''),
+                 'bar': fromFunction(_bar),
+                }
+        one = self._makeOne(attrs=ATTRS)
+        self.assertEqual(sorted(one.namesAndDescriptions(all=False)),
+                        [('bar', ATTRS['bar']),
+                         ('foo', ATTRS['foo']),
+                        ])
+
+    def test_namesAndDescriptions_w_all_True_simple(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        BASE_ATTRS = {'foo': Attribute('Foo', ''),
+                      'bar': fromFunction(_bar),
+                     }
+        DERIVED_ATTRS = {'baz': Attribute('Baz', ''),
+                        }
+        base = self._makeOne('IBase', attrs=BASE_ATTRS)
+        derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+        self.assertEqual(sorted(derived.namesAndDescriptions(all=True)),
+                        [('bar', BASE_ATTRS['bar']),
+                         ('baz', DERIVED_ATTRS['baz']),
+                         ('foo', BASE_ATTRS['foo']),
+                        ])
+
+    def test_namesAndDescriptions_w_all_True_bases_w_same_names(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        def _foo():
+            """DOCSTRING"""
+        BASE_ATTRS = {'foo': Attribute('Foo', ''),
+                      'bar': fromFunction(_bar),
+                     }
+        DERIVED_ATTRS = {'foo': fromFunction(_foo),
+                         'baz': Attribute('Baz', ''),
+                        }
+        base = self._makeOne('IBase', attrs=BASE_ATTRS)
+        derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+        self.assertEqual(sorted(derived.namesAndDescriptions(all=True)),
+                        [('bar', BASE_ATTRS['bar']),
+                         ('baz', DERIVED_ATTRS['baz']),
+                         ('foo', DERIVED_ATTRS['foo']),
+                        ])
+
+    def test_getDescriptionFor_miss(self):
+        one = self._makeOne()
+        self.assertRaises(KeyError, one.getDescriptionFor, 'nonesuch')
+
+    def test_getDescriptionFor_hit(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        ATTRS = {'foo': Attribute('Foo', ''),
+                 'bar': fromFunction(_bar),
+                }
+        one = self._makeOne(attrs=ATTRS)
+        self.assertEqual(one.getDescriptionFor('foo'), ATTRS['foo'])
+        self.assertEqual(one.getDescriptionFor('bar'), ATTRS['bar'])
+
+    def test___getitem___miss(self):
+        one = self._makeOne()
+        def _test():
+            return one['nonesuch']
+        self.assertRaises(KeyError, _test)
+
+    def test___getitem___hit(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        ATTRS = {'foo': Attribute('Foo', ''),
+                 'bar': fromFunction(_bar),
+                }
+        one = self._makeOne(attrs=ATTRS)
+        self.assertEqual(one['foo'], ATTRS['foo'])
+        self.assertEqual(one['bar'], ATTRS['bar'])
+
+    def test___contains___miss(self):
+        one = self._makeOne()
+        self.failIf('nonesuch' in one)
+
+    def test___contains___hit(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        ATTRS = {'foo': Attribute('Foo', ''),
+                 'bar': fromFunction(_bar),
+                }
+        one = self._makeOne(attrs=ATTRS)
+        self.failUnless('foo' in one)
+        self.failUnless('bar' in one)
+
+    def test_direct_miss(self):
+        one = self._makeOne()
+        self.assertEqual(one.direct('nonesuch'), None)
+
+    def test_direct_hit_local_miss_bases(self):
+        from zope.interface.interface import Attribute
+        from zope.interface.interface import fromFunction
+        def _bar():
+            """DOCSTRING"""
+        def _foo():
+            """DOCSTRING"""
+        BASE_ATTRS = {'foo': Attribute('Foo', ''),
+                      'bar': fromFunction(_bar),
+                     }
+        DERIVED_ATTRS = {'foo': fromFunction(_foo),
+                         'baz': Attribute('Baz', ''),
+                        }
+        base = self._makeOne('IBase', attrs=BASE_ATTRS)
+        derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+        self.assertEqual(derived.direct('foo'), DERIVED_ATTRS['foo'])
+        self.assertEqual(derived.direct('baz'), DERIVED_ATTRS['baz'])
+        self.assertEqual(derived.direct('bar'), None)
+
+    def test_queryDescriptionFor_miss(self):
+        iface = self._makeOne()
+        self.assertEqual(iface.queryDescriptionFor('nonesuch'), None)
+
+    def test_queryDescriptionFor_hit(self):
+        from zope.interface import Attribute
+        ATTRS = {'attr': Attribute('Title', 'Description')}
+        iface = self._makeOne(attrs=ATTRS)
+        self.assertEqual(iface.queryDescriptionFor('attr'), ATTRS['attr'])
+
+
+    #TODO  (or not:  'deferred' looks like a fossil to me.
+    #def test_deferred_cache_hit(self):
+    #def test_deferred_cache_miss(self):
+    #def test_deferred_cache_miss_w_bases(self):
+
+    def test_validateInvariants_pass(self):
+        _called_with = []
+        def _passable(*args, **kw):
+            _called_with.append((args, kw))
+            return True
+        iface = self._makeOne()
+        obj = object()
+        iface.setTaggedValue('invariants', [_passable])
+        self.assertEqual(iface.validateInvariants(obj), None)
+        self.assertEqual(_called_with, [((obj,), {})])
+
+    def test_validateInvariants_fail_wo_errors_passed(self):
+        from zope.interface.exceptions import Invalid
+        _passable_called_with = []
+        def _passable(*args, **kw):
+            _passable_called_with.append((args, kw))
+            return True
+        _fail_called_with = []
+        def _fail(*args, **kw):
+            _fail_called_with.append((args, kw))
+            raise Invalid
+        iface = self._makeOne()
+        obj = object()
+        iface.setTaggedValue('invariants', [_passable, _fail])
+        self.assertRaises(Invalid, iface.validateInvariants, obj)
+        self.assertEqual(_passable_called_with, [((obj,), {})])
+        self.assertEqual(_fail_called_with, [((obj,), {})])
+
+    def test_validateInvariants_fail_w_errors_passed(self):
+        from zope.interface.exceptions import Invalid
+        _errors = []
+        _fail_called_with = []
+        def _fail(*args, **kw):
+            _fail_called_with.append((args, kw))
+            raise Invalid
+        iface = self._makeOne()
+        obj = object()
+        iface.setTaggedValue('invariants', [_fail])
+        self.assertRaises(Invalid, iface.validateInvariants, obj, _errors)
+        self.assertEqual(_fail_called_with, [((obj,), {})])
+        self.assertEqual(len(_errors), 1)
+        self.failUnless(isinstance(_errors[0], Invalid))
+
+    def test_validateInvariants_fail_in_base_wo_errors_passed(self):
+        from zope.interface.exceptions import Invalid
+        _passable_called_with = []
+        def _passable(*args, **kw):
+            _passable_called_with.append((args, kw))
+            return True
+        _fail_called_with = []
+        def _fail(*args, **kw):
+            _fail_called_with.append((args, kw))
+            raise Invalid
+        base = self._makeOne('IBase')
+        derived = self._makeOne('IDerived', (base,))
+        obj = object()
+        base.setTaggedValue('invariants', [_fail])
+        derived.setTaggedValue('invariants', [_passable])
+        self.assertRaises(Invalid, derived.validateInvariants, obj)
+        self.assertEqual(_passable_called_with, [((obj,), {})])
+        self.assertEqual(_fail_called_with, [((obj,), {})])
+
+    #TODO
+    def test_validateInvariants_fail_in_base_w_errors_passed(self):
+        from zope.interface.exceptions import Invalid
+        _errors = []
+        _passable_called_with = []
+        def _passable(*args, **kw):
+            _passable_called_with.append((args, kw))
+            return True
+        _fail_called_with = []
+        def _fail(*args, **kw):
+            _fail_called_with.append((args, kw))
+            raise Invalid
+        base = self._makeOne('IBase')
+        derived = self._makeOne('IDerived', (base,))
+        obj = object()
+        base.setTaggedValue('invariants', [_fail])
+        derived.setTaggedValue('invariants', [_passable])
+        self.assertRaises(Invalid, derived.validateInvariants, obj, _errors)
+        self.assertEqual(_passable_called_with, [((obj,), {})])
+        self.assertEqual(_fail_called_with, [((obj,), {})])
+        self.assertEqual(len(_errors), 1)
+        self.failUnless(isinstance(_errors[0], Invalid))
+
+    def test___reduce__(self):
+        iface = self._makeOne('PickleMe')
+        self.assertEqual(iface.__reduce__(), 'PickleMe')
+
+    def test___hash___normal(self):
+        iface = self._makeOne('HashMe')
+        self.assertEqual(hash(iface),
+                         hash((('HashMe',
+                                'zope.interface.tests.test_interface'))))
+
+    def test___hash___missing_required_attrs(self):
+        import warnings
+        try:
+            from warnings import catch_warnings
+        except ImportError:  # Python 2.5
+            return
+        class Derived(self._getTargetClass()):
+            def __init__(self):
+                pass # Don't call base class.
+        derived = Derived()
+        with catch_warnings(record=True) as warned:
+            warnings.simplefilter('always') # see LP #825249 
+            self.assertEqual(hash(derived), 1)
+            self.assertEqual(len(warned), 1)
+            self.failUnless(warned[0].category is UserWarning)
+            self.assertEqual(str(warned[0].message),
+                             'Hashing uninitialized InterfaceClass instance')
+
+    def test_comparison_with_None(self):
+        iface = self._makeOne()
+        self.failUnless(iface < None)
+        self.failUnless(iface <= None)
+        self.failIf(iface == None)
+        self.failUnless(iface != None)
+        self.failIf(iface >= None)
+        self.failIf(iface > None)
+
+        self.failIf(None < iface)
+        self.failIf(None <= iface)
+        self.failIf(None == iface)
+        self.failUnless(None != iface)
+        self.failUnless(None >= iface)
+        self.failUnless(None > iface)
+
+    def test_comparison_with_same_instance(self):
+        iface = self._makeOne()
+
+        self.failIf(iface < iface)
+        self.failUnless(iface <= iface)
+        self.failUnless(iface == iface)
+        self.failIf(iface != iface)
+        self.failUnless(iface >= iface)
+        self.failIf(iface > iface)
+
+    def test_comparison_with_same_named_instance_in_other_module(self):
+
+        one = self._makeOne('IName', __module__='zope.interface.tests.one')
+        other = self._makeOne('IName', __module__='zope.interface.tests.other')
+
+        self.failUnless(one < other)
+        self.failIf(other < one)
+        self.failUnless(one <= other)
+        self.failIf(other <= one)
+        self.failIf(one == other)
+        self.failIf(other == one)
+        self.failUnless(one != other)
+        self.failUnless(other != one)
+        self.failIf(one >= other)
+        self.failUnless(other >= one)
+        self.failIf(one > other)
+        self.failUnless(other > one)
+
+
+class InterfaceTests(_SilencePy3Deprecations):
+
+    def test_attributes_link_to_interface(self):
         from zope.interface import Interface
         from zope.interface import Attribute
-        class _I1(Interface):
 
-            a1 = Attribute("This is an attribute")
+        class I1(Interface):
+            attr = Attribute("My attr")
 
-            def f11():
+        self.failUnless(I1['attr'].interface is I1)
+
+    def test_methods_link_to_interface(self):
+        from zope.interface import Interface
+
+        class I1(Interface):
+
+            def method(foo, bar, bingo):
                 pass
-            def f12():
+
+        self.failUnless(I1['method'].interface is I1)
+
+    def test_classImplements_simple(self):
+        from zope.interface import Interface
+        from zope.interface import implementedBy
+        from zope.interface import providedBy
+
+        class ICurrent(Interface):
+            def method1(a, b):
                 pass
-            f12.optional = 1
+            def method2(a, b):
+                pass
 
-        class _I1_(_I1):
+        class IOther(Interface):
             pass
 
-        class _I1__(_I1_):
+        class Current(object):
+            __implemented__ = ICurrent
+            def method1(self, a, b):
+                return 1
+            def method2(self, a, b):
+                return 2
+
+        current = Current()
+
+        self.failUnless(ICurrent.implementedBy(Current))
+        self.failIf(IOther.implementedBy(Current))
+        self.failUnless(ICurrent in implementedBy(Current))
+        self.failIf(IOther in implementedBy(Current))
+        self.failUnless(ICurrent in providedBy(current))
+        self.failIf(IOther in providedBy(current))
+
+    def test_classImplements_base_not_derived(self):
+        from zope.interface import Interface
+        from zope.interface import implementedBy
+        from zope.interface import providedBy
+        class IBase(Interface):
+            def method():
+                pass
+        class IDerived(IBase):
             pass
+        class Current():
+            __implemented__ = IBase
+            def method(self):
+                pass
+        current = Current()
 
-        class _I2(_I1__):
-            def f21():
+        self.failUnless(IBase.implementedBy(Current))
+        self.failIf(IDerived.implementedBy(Current))
+        self.failUnless(IBase in implementedBy(Current))
+        self.failIf(IDerived in implementedBy(Current))
+        self.failUnless(IBase in providedBy(current))
+        self.failIf(IDerived in providedBy(current))
+
+    def test_classImplements_base_and_derived(self):
+        from zope.interface import Interface
+        from zope.interface import implementedBy
+        from zope.interface import providedBy
+
+        class IBase(Interface):
+            def method():
                 pass
-            def f22():
+
+        class IDerived(IBase):
+            pass
+
+        class Current(object):
+            __implemented__ = IDerived
+            def method(self):
                 pass
-            f23 = f22
 
-        return _I2
+        current = Current()
 
-    def testInterfaceSetOnAttributes(self):
-        from zope.interface.tests.unitfixtures import FooInterface
-        self.assertEqual(FooInterface['foobar'].interface,
-                         FooInterface)
-        self.assertEqual(FooInterface['aMethod'].interface,
-                         FooInterface)
+        self.failUnless(IBase.implementedBy(Current))
+        self.failUnless(IDerived.implementedBy(Current))
+        self.failIf(IBase in implementedBy(Current))
+        self.failUnless(IBase in implementedBy(Current).flattened())
+        self.failUnless(IDerived in implementedBy(Current))
+        self.failIf(IBase in providedBy(current))
+        self.failUnless(IBase in providedBy(current).flattened())
+        self.failUnless(IDerived in providedBy(current))
 
-    def testClassImplements(self):
-        from zope.interface.tests.unitfixtures import A
-        from zope.interface.tests.unitfixtures import B
-        from zope.interface.tests.unitfixtures import C
-        from zope.interface.tests.unitfixtures import D
-        from zope.interface.tests.unitfixtures import E
-        from zope.interface.tests.unitfixtures import I1
-        from zope.interface.tests.unitfixtures import I2
-        from zope.interface.tests.unitfixtures import IC
-        self.failUnless(IC.implementedBy(C))
+    def test_classImplements_multiple(self):
+        from zope.interface import Interface
+        from zope.interface import implementedBy
+        from zope.interface import providedBy
 
-        self.failUnless(I1.implementedBy(A))
-        self.failUnless(I1.implementedBy(B))
-        self.failUnless(not I1.implementedBy(C))
-        self.failUnless(I1.implementedBy(D))
-        self.failUnless(I1.implementedBy(E))
+        class ILeft(Interface):
+            def method():
+                pass
 
-        self.failUnless(not I2.implementedBy(A))
-        self.failUnless(I2.implementedBy(B))
-        self.failUnless(not I2.implementedBy(C))
+        class IRight(ILeft):
+            pass
 
-        # No longer after interfacegeddon
-        # self.failUnless(not I2.implementedBy(D))
+        class Left(object):
+            __implemented__ = ILeft
 
-        self.failUnless(not I2.implementedBy(E))
+            def method(self):
+                pass
 
-    def testUtil(self):
+        class Right(object):
+            __implemented__ = IRight
+
+        class Ambi(Left, Right):
+            pass
+
+        ambi = Ambi()
+
+        self.failUnless(ILeft.implementedBy(Ambi))
+        self.failUnless(IRight.implementedBy(Ambi))
+        self.failUnless(ILeft in implementedBy(Ambi))
+        self.failUnless(IRight in implementedBy(Ambi))
+        self.failUnless(ILeft in providedBy(ambi))
+        self.failUnless(IRight in providedBy(ambi))
+
+    def test_classImplements_multiple_w_explict_implements(self):
+        from zope.interface import Interface
         from zope.interface import implementedBy
         from zope.interface import providedBy
-        from zope.interface.tests.unitfixtures import A
-        from zope.interface.tests.unitfixtures import B
-        from zope.interface.tests.unitfixtures import C
-        from zope.interface.tests.unitfixtures import I1
-        from zope.interface.tests.unitfixtures import I2
-        from zope.interface.tests.unitfixtures import IC
-        self.failUnless(IC in implementedBy(C))
-        self.failUnless(I1 in implementedBy(A))
-        self.failUnless(not I1 in implementedBy(C))
-        self.failUnless(I2 in implementedBy(B))
-        self.failUnless(not I2 in implementedBy(C))
 
-        self.failUnless(IC in providedBy(C()))
-        self.failUnless(I1 in providedBy(A()))
-        self.failUnless(not I1 in providedBy(C()))
-        self.failUnless(I2 in providedBy(B()))
-        self.failUnless(not I2 in providedBy(C()))
+        class ILeft(Interface):
 
+            def method():
+                pass
 
-    def testObjectImplements(self):
-        from zope.interface.tests.unitfixtures import A
-        from zope.interface.tests.unitfixtures import B
-        from zope.interface.tests.unitfixtures import C
-        from zope.interface.tests.unitfixtures import D
-        from zope.interface.tests.unitfixtures import E
-        from zope.interface.tests.unitfixtures import I1
-        from zope.interface.tests.unitfixtures import I2
-        from zope.interface.tests.unitfixtures import IC
-        self.failUnless(IC.providedBy(C()))
+        class IRight(ILeft):
+            pass
 
-        self.failUnless(I1.providedBy(A()))
-        self.failUnless(I1.providedBy(B()))
-        self.failUnless(not I1.providedBy(C()))
-        self.failUnless(I1.providedBy(D()))
-        self.failUnless(I1.providedBy(E()))
+        class IOther(Interface):
+            pass
 
-        self.failUnless(not I2.providedBy(A()))
-        self.failUnless(I2.providedBy(B()))
-        self.failUnless(not I2.providedBy(C()))
+        class Left():
+            __implemented__ = ILeft
 
-        # Not after interface geddon
-        # self.failUnless(not I2.providedBy(D()))
+            def method(self):
+                pass
 
-        self.failUnless(not I2.providedBy(E()))
+        class Right(object):
+            __implemented__ = IRight
 
-    def testDeferredClass(self):
-        from zope.interface.tests.unitfixtures import A
+        class Other(object):
+            __implemented__ = IOther
+
+        class Mixed(Left, Right):
+            __implemented__ = Left.__implemented__, Other.__implemented__
+
+        mixed = Mixed()
+
+        self.failUnless(ILeft.implementedBy(Mixed))
+        self.failIf(IRight.implementedBy(Mixed))
+        self.failUnless(IOther.implementedBy(Mixed))
+        self.failUnless(ILeft in implementedBy(Mixed))
+        self.failIf(IRight in implementedBy(Mixed))
+        self.failUnless(IOther in implementedBy(Mixed))
+        self.failUnless(ILeft in providedBy(mixed))
+        self.failIf(IRight in providedBy(mixed))
+        self.failUnless(IOther in providedBy(mixed))
+
+    def test_interface_deferred_class_method_broken(self):
+        from zope.interface import Interface
         from zope.interface.exceptions import BrokenImplementation
-        a = A()
-        self.assertRaises(BrokenImplementation, a.ma)
 
+        class IDeferring(Interface):
+            def method():
+                pass
 
+        class Deferring(IDeferring.deferred()):
+            __implemented__ = IDeferring
+
+        deferring = Deferring()
+
+        self.assertRaises(BrokenImplementation, deferring.method)
+
     def testInterfaceExtendsInterface(self):
-        from zope.interface.tests.unitfixtures import BazInterface
-        from zope.interface.tests.unitfixtures import BarInterface
-        from zope.interface.tests.unitfixtures import BobInterface
-        from zope.interface.tests.unitfixtures import FunInterface
+        from zope.interface import Interface
+
+        new = Interface.__class__
+        FunInterface = new('FunInterface')
+        BarInterface = new('BarInterface', [FunInterface])
+        BobInterface = new('BobInterface')
+        BazInterface = new('BazInterface', [BobInterface, BarInterface])
+
         self.failUnless(BazInterface.extends(BobInterface))
         self.failUnless(BazInterface.extends(BarInterface))
         self.failUnless(BazInterface.extends(FunInterface))
-        self.failUnless(not BobInterface.extends(FunInterface))
-        self.failUnless(not BobInterface.extends(BarInterface))
+        self.failIf(BobInterface.extends(FunInterface))
+        self.failIf(BobInterface.extends(BarInterface))
         self.failUnless(BarInterface.extends(FunInterface))
-        self.failUnless(not BarInterface.extends(BazInterface))
+        self.failIf(BarInterface.extends(BazInterface))
 
-    def testVerifyImplementation(self):
+    def test_verifyClass(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
         from zope.interface.verify import verifyClass
+
+        class ICheckMe(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                pass
+
+        class CheckMe(object):
+            __implemented__ = ICheckMe
+            attr = 'value'
+
+            def method(self):
+                pass
+
+        self.failUnless(verifyClass(ICheckMe, CheckMe))
+
+    def test_verifyObject(self):
+        from zope.interface import Attribute
         from zope.interface import Interface
-        from zope.interface.tests.unitfixtures import Foo
-        from zope.interface.tests.unitfixtures import FooInterface
-        from zope.interface.tests.unitfixtures import I1
-        self.failUnless(verifyClass(FooInterface, Foo))
-        self.failUnless(Interface.providedBy(I1))
+        from zope.interface.verify import verifyObject
 
-    def test_names(self):
-        iface = self._makeDerivedInterface()
-        names = list(iface.names())
-        names.sort()
-        self.assertEqual(names, ['f21', 'f22', 'f23'])
-        all = list(iface.names(all=True))
-        all.sort()
-        self.assertEqual(all, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23'])
+        class ICheckMe(Interface):
+            attr = Attribute(u'My attr')
 
-    def test_namesAndDescriptions(self):
-        iface = self._makeDerivedInterface()
-        names = [nd[0] for nd in iface.namesAndDescriptions()]
-        names.sort()
-        self.assertEqual(names, ['f21', 'f22', 'f23'])
-        names = [nd[0] for nd in iface.namesAndDescriptions(1)]
-        names.sort()
-        self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23'])
+            def method():
+                pass
 
-        for name, d in iface.namesAndDescriptions(1):
-            self.assertEqual(name, d.__name__)
+        class CheckMe(object):
+            __implemented__ = ICheckMe
+            attr = 'value'
 
-    def test_getDescriptionFor(self):
-        iface = self._makeDerivedInterface()
-        self.assertEqual(iface.getDescriptionFor('f11').__name__, 'f11')
-        self.assertEqual(iface.getDescriptionFor('f22').__name__, 'f22')
-        self.assertEqual(iface.queryDescriptionFor('f33', self), self)
-        self.assertRaises(KeyError, iface.getDescriptionFor, 'f33')
+            def method(self):
+                pass
 
-    def test___getitem__(self):
-        iface = self._makeDerivedInterface()
-        self.assertEqual(iface['f11'].__name__, 'f11')
-        self.assertEqual(iface['f22'].__name__, 'f22')
-        self.assertEqual(iface.get('f33', self), self)
-        self.assertRaises(KeyError, iface.__getitem__, 'f33')
+        check_me = CheckMe()
 
-    def test___contains__(self):
-        iface = self._makeDerivedInterface()
-        self.failUnless('f11' in iface)
-        self.failIf('f33' in iface)
+        self.failUnless(verifyObject(ICheckMe, check_me))
 
-    def test___iter__(self):
-        iface = self._makeDerivedInterface()
-        names = list(iter(iface))
-        names.sort()
-        self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23'])
+    def test_interface_object_provides_Interface(self):
+        from zope.interface import Interface
 
-    def testAttr(self):
-        iface = self._makeDerivedInterface()
-        description = iface.getDescriptionFor('a1')
-        self.assertEqual(description.__name__, 'a1')
-        self.assertEqual(description.__doc__, 'This is an attribute')
+        class AnInterface(Interface):
+            pass
 
-    def testFunctionAttributes(self):
-        # Make sure function attributes become tagged values.
+        self.assert_(Interface.providedBy(AnInterface))
+
+    def test_names_simple(self):
+        from zope.interface import Attribute
         from zope.interface import Interface
-        class ITest(Interface):
+
+        class ISimple(Interface):
+            attr = Attribute(u'My attr')
+
             def method():
                 pass
+
+        self.assertEqual(sorted(ISimple.names()), ['attr', 'method'])
+
+    def test_names_derived(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+
+        class IBase(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                pass
+
+        class IDerived(IBase):
+            attr2 = Attribute(u'My attr')
+
+            def method():
+                pass
+
+            def method2():
+                pass
+
+        self.assertEqual(sorted(IDerived.names()),
+                         ['attr2', 'method', 'method2'])
+        self.assertEqual(sorted(IDerived.names(all=True)),
+                         ['attr', 'attr2', 'method', 'method2'])
+
+    def test_namesAndDescriptions_simple(self):
+        from zope.interface import Attribute
+        from zope.interface.interface import Method
+        from zope.interface import Interface
+
+        class ISimple(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                "My method"
+
+        name_values = sorted(ISimple.namesAndDescriptions())
+
+        self.assertEqual(len(name_values), 2)
+        self.assertEqual(name_values[0][0], 'attr')
+        self.failUnless(isinstance(name_values[0][1], Attribute))
+        self.assertEqual(name_values[0][1].__name__, 'attr')
+        self.assertEqual(name_values[0][1].__doc__, 'My attr')
+        self.assertEqual(name_values[1][0], 'method')
+        self.failUnless(isinstance(name_values[1][1], Method))
+        self.assertEqual(name_values[1][1].__name__, 'method')
+        self.assertEqual(name_values[1][1].__doc__, 'My method')
+
+    def test_namesAndDescriptions_derived(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+        from zope.interface.interface import Method
+
+        class IBase(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                "My method"
+
+        class IDerived(IBase):
+            attr2 = Attribute(u'My attr2')
+
+            def method():
+                "My method, overridden"
+
+            def method2():
+                "My method2"
+
+        name_values = sorted(IDerived.namesAndDescriptions())
+
+        self.assertEqual(len(name_values), 3)
+        self.assertEqual(name_values[0][0], 'attr2')
+        self.failUnless(isinstance(name_values[0][1], Attribute))
+        self.assertEqual(name_values[0][1].__name__, 'attr2')
+        self.assertEqual(name_values[0][1].__doc__, 'My attr2')
+        self.assertEqual(name_values[1][0], 'method')
+        self.failUnless(isinstance(name_values[1][1], Method))
+        self.assertEqual(name_values[1][1].__name__, 'method')
+        self.assertEqual(name_values[1][1].__doc__, 'My method, overridden')
+        self.assertEqual(name_values[2][0], 'method2')
+        self.failUnless(isinstance(name_values[2][1], Method))
+        self.assertEqual(name_values[2][1].__name__, 'method2')
+        self.assertEqual(name_values[2][1].__doc__, 'My method2')
+
+        name_values = sorted(IDerived.namesAndDescriptions(all=True))
+
+        self.assertEqual(len(name_values), 4)
+        self.assertEqual(name_values[0][0], 'attr')
+        self.failUnless(isinstance(name_values[0][1], Attribute))
+        self.assertEqual(name_values[0][1].__name__, 'attr')
+        self.assertEqual(name_values[0][1].__doc__, 'My attr')
+        self.assertEqual(name_values[1][0], 'attr2')
+        self.failUnless(isinstance(name_values[1][1], Attribute))
+        self.assertEqual(name_values[1][1].__name__, 'attr2')
+        self.assertEqual(name_values[1][1].__doc__, 'My attr2')
+        self.assertEqual(name_values[2][0], 'method')
+        self.failUnless(isinstance(name_values[2][1], Method))
+        self.assertEqual(name_values[2][1].__name__, 'method')
+        self.assertEqual(name_values[2][1].__doc__, 'My method, overridden')
+        self.assertEqual(name_values[3][0], 'method2')
+        self.failUnless(isinstance(name_values[3][1], Method))
+        self.assertEqual(name_values[3][1].__name__, 'method2')
+        self.assertEqual(name_values[3][1].__doc__, 'My method2')
+
+    def test_getDescriptionFor_nonesuch_no_default(self):
+        from zope.interface import Interface
+
+        class IEmpty(Interface):
+            pass
+
+        self.assertRaises(KeyError, IEmpty.getDescriptionFor, 'nonesuch')
+
+    def test_getDescriptionFor_simple(self):
+        from zope.interface import Attribute
+        from zope.interface.interface import Method
+        from zope.interface import Interface
+
+        class ISimple(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                "My method"
+
+        a_desc = ISimple.getDescriptionFor('attr')
+        self.failUnless(isinstance(a_desc, Attribute))
+        self.assertEqual(a_desc.__name__, 'attr')
+        self.assertEqual(a_desc.__doc__, 'My attr')
+
+        m_desc = ISimple.getDescriptionFor('method')
+        self.failUnless(isinstance(m_desc, Method))
+        self.assertEqual(m_desc.__name__, 'method')
+        self.assertEqual(m_desc.__doc__, 'My method')
+
+    def test_getDescriptionFor_derived(self):
+        from zope.interface import Attribute
+        from zope.interface.interface import Method
+        from zope.interface import Interface
+
+        class IBase(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                "My method"
+
+        class IDerived(IBase):
+            attr2 = Attribute(u'My attr2')
+
+            def method():
+                "My method, overridden"
+
+            def method2():
+                "My method2"
+
+        a_desc = IDerived.getDescriptionFor('attr')
+        self.failUnless(isinstance(a_desc, Attribute))
+        self.assertEqual(a_desc.__name__, 'attr')
+        self.assertEqual(a_desc.__doc__, 'My attr')
+
+        m_desc = IDerived.getDescriptionFor('method')
+        self.failUnless(isinstance(m_desc, Method))
+        self.assertEqual(m_desc.__name__, 'method')
+        self.assertEqual(m_desc.__doc__, 'My method, overridden')
+
+        a2_desc = IDerived.getDescriptionFor('attr2')
+        self.failUnless(isinstance(a2_desc, Attribute))
+        self.assertEqual(a2_desc.__name__, 'attr2')
+        self.assertEqual(a2_desc.__doc__, 'My attr2')
+
+        m2_desc = IDerived.getDescriptionFor('method2')
+        self.failUnless(isinstance(m2_desc, Method))
+        self.assertEqual(m2_desc.__name__, 'method2')
+        self.assertEqual(m2_desc.__doc__, 'My method2')
+
+    def test___getitem__nonesuch(self):
+        from zope.interface import Interface
+
+        class IEmpty(Interface):
+            pass
+
+        self.assertRaises(KeyError, IEmpty.__getitem__, 'nonesuch')
+
+    def test___getitem__simple(self):
+        from zope.interface import Attribute
+        from zope.interface.interface import Method
+        from zope.interface import Interface
+
+        class ISimple(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                "My method"
+
+        a_desc = ISimple['attr']
+        self.failUnless(isinstance(a_desc, Attribute))
+        self.assertEqual(a_desc.__name__, 'attr')
+        self.assertEqual(a_desc.__doc__, 'My attr')
+
+        m_desc = ISimple['method']
+        self.failUnless(isinstance(m_desc, Method))
+        self.assertEqual(m_desc.__name__, 'method')
+        self.assertEqual(m_desc.__doc__, 'My method')
+
+    def test___getitem___derived(self):
+        from zope.interface import Attribute
+        from zope.interface.interface import Method
+        from zope.interface import Interface
+
+        class IBase(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                "My method"
+
+        class IDerived(IBase):
+            attr2 = Attribute(u'My attr2')
+
+            def method():
+                "My method, overridden"
+
+            def method2():
+                "My method2"
+
+        a_desc = IDerived['attr']
+        self.failUnless(isinstance(a_desc, Attribute))
+        self.assertEqual(a_desc.__name__, 'attr')
+        self.assertEqual(a_desc.__doc__, 'My attr')
+
+        m_desc = IDerived['method']
+        self.failUnless(isinstance(m_desc, Method))
+        self.assertEqual(m_desc.__name__, 'method')
+        self.assertEqual(m_desc.__doc__, 'My method, overridden')
+
+        a2_desc = IDerived['attr2']
+        self.failUnless(isinstance(a2_desc, Attribute))
+        self.assertEqual(a2_desc.__name__, 'attr2')
+        self.assertEqual(a2_desc.__doc__, 'My attr2')
+
+        m2_desc = IDerived['method2']
+        self.failUnless(isinstance(m2_desc, Method))
+        self.assertEqual(m2_desc.__name__, 'method2')
+        self.assertEqual(m2_desc.__doc__, 'My method2')
+
+    def test___contains__nonesuch(self):
+        from zope.interface import Interface
+
+        class IEmpty(Interface):
+            pass
+
+        self.failIf('nonesuch' in IEmpty)
+
+    def test___contains__simple(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+
+        class ISimple(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                "My method"
+
+        self.failUnless('attr' in ISimple)
+        self.failUnless('method' in ISimple)
+
+    def test___contains__derived(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+
+        class IBase(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                "My method"
+
+        class IDerived(IBase):
+            attr2 = Attribute(u'My attr2')
+
+            def method():
+                "My method, overridden"
+
+            def method2():
+                "My method2"
+
+        self.failUnless('attr' in IDerived)
+        self.failUnless('method' in IDerived)
+        self.failUnless('attr2' in IDerived)
+        self.failUnless('method2' in IDerived)
+
+    def test___iter__empty(self):
+        from zope.interface import Interface
+
+        class IEmpty(Interface):
+            pass
+
+        self.assertEqual(list(IEmpty), [])
+
+    def test___iter__simple(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+
+        class ISimple(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                "My method"
+
+        self.assertEqual(sorted(list(ISimple)), ['attr', 'method'])
+
+    def test___iter__derived(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+
+        class IBase(Interface):
+            attr = Attribute(u'My attr')
+
+            def method():
+                "My method"
+
+        class IDerived(IBase):
+            attr2 = Attribute(u'My attr2')
+
+            def method():
+                "My method, overridden"
+
+            def method2():
+                "My method2"
+
+        self.assertEqual(sorted(list(IDerived)),
+                         ['attr', 'attr2', 'method', 'method2'])
+
+    def test_function_attributes_become_tagged_values(self):
+        from zope.interface import Interface
+
+        class ITagMe(Interface):
+            def method():
+                pass
             method.optional = 1
 
-        method = ITest['method']
+        method = ITagMe['method']
         self.assertEqual(method.getTaggedValue('optional'), 1)
 
-    def testInvariant(self):
+    def test___doc___non_element(self):
+        from zope.interface import Interface
+
+        class IHaveADocString(Interface):
+            "xxx"
+
+        self.assertEqual(IHaveADocString.__doc__, "xxx")
+        self.assertEqual(list(IHaveADocString), [])
+
+    def test___doc___as_element(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+
+        class IHaveADocString(Interface):
+            "xxx"
+            __doc__ = Attribute('the doc')
+
+        self.assertEqual(IHaveADocString.__doc__, "")
+        self.assertEqual(list(IHaveADocString), ['__doc__'])
+
+    def _errorsEqual(self, has_invariant, error_len, error_msgs, iface):
         from zope.interface.exceptions import Invalid
+        self.assertRaises(Invalid, iface.validateInvariants, has_invariant)
+        e = []
+        try:
+            iface.validateInvariants(has_invariant, e)
+        except Invalid, error:
+            self.assertEquals(error.args[0], e)
+        else:
+            self._assert(0) # validateInvariants should always raise
+            # Invalid
+        self.assertEquals(len(e), error_len)
+        msgs = [error.args[0] for error in e]
+        msgs.sort()
+        for msg in msgs:
+            self.assertEquals(msg, error_msgs.pop(0))
+
+    def test_invariant_simple(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
         from zope.interface import directlyProvides
-        from zope.interface.tests.unitfixtures import BarGreaterThanFoo
-        from zope.interface.tests.unitfixtures import ifFooThenBar
-        from zope.interface.tests.unitfixtures import IInvariant
-        from zope.interface.tests.unitfixtures import InvariantC
-        from zope.interface.tests.unitfixtures import ISubInvariant
+        from zope.interface import invariant
+
+        class IInvariant(Interface):
+            foo = Attribute('foo')
+            bar = Attribute('bar; must eval to Boolean True if foo does')
+            invariant(_ifFooThenBar)
+
+        class HasInvariant(object):
+            pass
+
         # set up
-        o = InvariantC()
-        directlyProvides(o, IInvariant)
-        # a helper
-        def errorsEqual(self, o, error_len, error_msgs, iface=None):
-            if iface is None:
-                iface = IInvariant
-            self.assertRaises(Invalid, iface.validateInvariants, o)
-            e = []
-            try:
-                iface.validateInvariants(o, e)
-            except Invalid, error:
-                self.assertEqual(error.args[0], e)
-            else:
-                self._assert(0) # validateInvariants should always raise
-                # Invalid
-            self.assertEqual(len(e), error_len)
-            msgs = [error.args[0] for error in e]
-            msgs.sort()
-            for msg in msgs:
-                self.assertEqual(msg, error_msgs.pop(0))
+        has_invariant = HasInvariant()
+        directlyProvides(has_invariant, IInvariant)
+
         # the tests
         self.assertEqual(IInvariant.getTaggedValue('invariants'),
-                          [ifFooThenBar])
-        self.assertEqual(IInvariant.validateInvariants(o), None)
-        o.bar = 27
-        self.assertEqual(IInvariant.validateInvariants(o), None)
-        o.foo = 42
-        self.assertEqual(IInvariant.validateInvariants(o), None)
-        del o.bar
-        errorsEqual(self, o, 1, ['If Foo, then Bar!'])
+                         [_ifFooThenBar])
+        self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
+        has_invariant.bar = 27
+        self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
+        has_invariant.foo = 42
+        self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
+        del has_invariant.bar
+        self._errorsEqual(has_invariant, 1, ['If Foo, then Bar!'],
+                          IInvariant)
+
+    def test_invariant_nested(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+        from zope.interface import directlyProvides
+        from zope.interface import invariant
+
+        class IInvariant(Interface):
+            foo = Attribute('foo')
+            bar = Attribute('bar; must eval to Boolean True if foo does')
+            invariant(_ifFooThenBar)
+
+        class ISubInvariant(IInvariant):
+            invariant(_barGreaterThanFoo)
+
+        class HasInvariant(object):
+            pass
+
         # nested interfaces with invariants:
         self.assertEqual(ISubInvariant.getTaggedValue('invariants'),
-                          [BarGreaterThanFoo])
-        o = InvariantC()
-        directlyProvides(o, ISubInvariant)
-        o.foo = 42
+                         [_barGreaterThanFoo])
+        has_invariant = HasInvariant()
+        directlyProvides(has_invariant, ISubInvariant)
+        has_invariant.foo = 42
         # even though the interface has changed, we should still only have one
         # error.
-        errorsEqual(self, o, 1, ['If Foo, then Bar!'], ISubInvariant)
+        self._errorsEqual(has_invariant, 1, ['If Foo, then Bar!'],
+                          ISubInvariant)
         # however, if we set foo to 0 (Boolean False) and bar to a negative
         # number then we'll get the new error
-        o.foo = 2
-        o.bar = 1
-        errorsEqual(self, o, 1, ['Please, Boo MUST be greater than Foo!'],
-                    ISubInvariant)
+        has_invariant.foo = 2
+        has_invariant.bar = 1
+        self._errorsEqual(has_invariant, 1,
+                          ['Please, Boo MUST be greater than Foo!'],
+                          ISubInvariant)
         # and if we set foo to a positive number and boo to 0, we'll
         # get both errors!
-        o.foo = 1
-        o.bar = 0
-        errorsEqual(self, o, 2, ['If Foo, then Bar!',
-                                 'Please, Boo MUST be greater than Foo!'],
-                    ISubInvariant)
+        has_invariant.foo = 1
+        has_invariant.bar = 0
+        self._errorsEqual(has_invariant, 2,
+                          ['If Foo, then Bar!',
+                           'Please, Boo MUST be greater than Foo!'],
+                          ISubInvariant)
         # for a happy ending, we'll make the invariants happy
-        o.foo = 1
-        o.bar = 2
-        self.assertEqual(IInvariant.validateInvariants(o), None) # woohoo
+        has_invariant.foo = 1
+        has_invariant.bar = 2
+        self.assertEquals(IInvariant.validateInvariants(has_invariant), None)
+
+    def test_invariant_mutandis(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+        from zope.interface import directlyProvides
+        from zope.interface import invariant
+
+        class IInvariant(Interface):
+            foo = Attribute('foo')
+            bar = Attribute('bar; must eval to Boolean True if foo does')
+            invariant(_ifFooThenBar)
+
+        class HasInvariant(object):
+            pass
+
         # now we'll do two invariants on the same interface,
         # just to make sure that a small
         # multi-invariant interface is at least minimally tested.
-        o = InvariantC()
-        directlyProvides(o, IInvariant)
-        o.foo = 42
+        has_invariant = HasInvariant()
+        directlyProvides(has_invariant, IInvariant)
+        has_invariant.foo = 42
+
+        # if you really need to mutate, then this would be the way to do it.
+        # Probably a bad idea, though. :-)
         old_invariants = IInvariant.getTaggedValue('invariants')
         invariants = old_invariants[:]
-        invariants.append(BarGreaterThanFoo) # if you really need to mutate,
-        # then this would be the way to do it.  Probably a bad idea, though. :-)
+        invariants.append(_barGreaterThanFoo)
         IInvariant.setTaggedValue('invariants', invariants)
-        #
+
         # even though the interface has changed, we should still only have one
         # error.
-        errorsEqual(self, o, 1, ['If Foo, then Bar!'])
+        self._errorsEqual(has_invariant, 1, ['If Foo, then Bar!'],
+                          IInvariant)
         # however, if we set foo to 0 (Boolean False) and bar to a negative
         # number then we'll get the new error
-        o.foo = 2
-        o.bar = 1
-        errorsEqual(self, o, 1, ['Please, Boo MUST be greater than Foo!'])
+        has_invariant.foo = 2
+        has_invariant.bar = 1
+        self._errorsEqual(has_invariant, 1,
+                         ['Please, Boo MUST be greater than Foo!'], IInvariant)
         # and if we set foo to a positive number and boo to 0, we'll
         # get both errors!
-        o.foo = 1
-        o.bar = 0
-        errorsEqual(self, o, 2, ['If Foo, then Bar!',
-                                 'Please, Boo MUST be greater than Foo!'])
+        has_invariant.foo = 1
+        has_invariant.bar = 0
+        self._errorsEqual(has_invariant, 2,
+                          ['If Foo, then Bar!',
+                           'Please, Boo MUST be greater than Foo!'],
+                          IInvariant)
         # for another happy ending, we'll make the invariants happy again
-        o.foo = 1
-        o.bar = 2
-        self.assertEqual(IInvariant.validateInvariants(o), None) # bliss
+        has_invariant.foo = 1
+        has_invariant.bar = 2
+        self.assertEquals(IInvariant.validateInvariants(has_invariant), None)
         # clean up
         IInvariant.setTaggedValue('invariants', old_invariants)
 
@@ -344,164 +1625,431 @@
         self.assertEqual(list(I), ['__doc__'])
 
     def testIssue228(self):
-        from zope.interface import Interface
         # Test for http://collector.zope.org/Zope3-dev/228
-        if sys.version[0] == '3':
+        # Old style classes don't have a '__class__' attribute
+        import sys
+        if sys.version[0] < '3':
             # No old style classes in Python 3, so the test becomes moot.
-            return
+            from zope.interface import Interface
+
+            class I(Interface):
+                "xxx"
+
+            class OldStyle:
+                __providedBy__ = None
+
+            self.assertRaises(AttributeError, I.providedBy, OldStyle)
+
+    def test_invariant_as_decorator(self):
+        from zope.interface import Interface
+        from zope.interface import Attribute
+        from zope.interface import implements
+        from zope.interface import invariant
+        from zope.interface.exceptions import Invalid
+
+        class IRange(Interface):
+            min = Attribute("Lower bound")
+            max = Attribute("Upper bound")
+            
+            @invariant
+            def range_invariant(ob):
+                if ob.max < ob.min:
+                    raise Invalid('max < min')
+
+        class Range(object):
+            implements(IRange)
+
+            def __init__(self, min, max):
+                self.min, self.max = min, max
+
+        IRange.validateInvariants(Range(1,2))
+        IRange.validateInvariants(Range(1,1))
+        try:
+            IRange.validateInvariants(Range(2,1))
+        except Invalid, e:
+            self.assertEqual(str(e), 'max < min')
+
+    def test_taggedValue(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+        from zope.interface import taggedValue
+
+        class ITagged(Interface):
+            foo = Attribute('foo')
+            bar = Attribute('bar; must eval to Boolean True if foo does')
+            taggedValue('qux', 'Spam')
+
+        class HasInvariant(object):
+            pass
+
+        self.assertEquals(ITagged.getTaggedValue('qux'), 'Spam')
+        self.assert_('qux' in ITagged.getTaggedValueTags())
+
+    def test_description_cache_management(self):
+        # See https://bugs.launchpad.net/zope.interface/+bug/185974
+        # There was a bug where the cache used by Specification.get() was not
+        # cleared when the bases were changed.
+        from zope.interface import Interface
+        from zope.interface import Attribute
+
+        class I1(Interface):
+            a = Attribute('a')
+
+        class I2(I1):
+            pass
+
+        class I3(I2):
+            pass
+
+        self.failUnless(I3.get('a') is I1.get('a'))
+
+        I2.__bases__ = (Interface,)
+        self.failUnless(I3.get('a') is None)
+
+    def test___call___defers_to___conform___(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+
         class I(Interface):
-            "xxx"
-        class Bad:
-            __providedBy__ = None
-        # Old style classes don't have a '__class__' attribute
-        self.failUnlessRaises(AttributeError, I.providedBy, Bad)
+            pass
 
-    def test_comparison_with_None(self):
+        class C(object):
+            implements(I)
+            def __conform__(self, proto):
+                return 0
+
+        self.assertEqual(I(C()), 0)
+
+    def test___call___object_implements(self):
         from zope.interface import Interface
+        from zope.interface import implements
 
-        class IEmpty(Interface):
+        class I(Interface):
             pass
 
-        self.failUnless(IEmpty < None)
-        self.failUnless(IEmpty <= None)
-        self.failIf(IEmpty == None)
-        self.failUnless(IEmpty != None)
-        self.failIf(IEmpty >= None)
-        self.failIf(IEmpty > None)
+        class C(object):
+            implements(I)
 
-        self.failIf(None < IEmpty)
-        self.failIf(None <= IEmpty)
-        self.failIf(None == IEmpty)
-        self.failUnless(None != IEmpty)
-        self.failUnless(None >= IEmpty)
-        self.failUnless(None > IEmpty)
+        c = C()
+        self.assert_(I(c) is c)
 
-    def test_comparison_with_same_instance(self):
+    def test___call___miss_wo_alternate(self):
         from zope.interface import Interface
 
-        class IEmpty(Interface):
+        class I(Interface):
             pass
 
-        self.failIf(IEmpty < IEmpty)
-        self.failUnless(IEmpty <= IEmpty)
-        self.failUnless(IEmpty == IEmpty)
-        self.failIf(IEmpty != IEmpty)
-        self.failUnless(IEmpty >= IEmpty)
-        self.failIf(IEmpty > IEmpty)
+        class C(object):
+            pass
 
-    def test_comparison_with_same_named_instance_in_other_module(self):
-        from zope.interface.tests.ifoo import IFoo as IFoo1
-        from zope.interface.tests.ifoo_other import IFoo as IFoo2
+        c = C()
+        self.assertRaises(TypeError, I, c)
 
-        self.failUnless(IFoo1 < IFoo2)
-        self.failUnless(IFoo1 <= IFoo2)
-        self.failIf(IFoo1 == IFoo2)
-        self.failUnless(IFoo1 != IFoo2)
-        self.failIf(IFoo1 >= IFoo2)
-        self.failIf(IFoo1 > IFoo2)
+    def test___call___miss_w_alternate(self):
+        from zope.interface import Interface
 
-    def test_hash_normal(self):
-        from zope.interface.tests.ifoo import IFoo
-        self.assertEqual(hash(IFoo),
-                         hash((('IFoo', 'zope.interface.tests.ifoo'))))
+        class I(Interface):
+            pass
 
-    def test_hash_missing_required_attrs(self):
-        import warnings
+        class C(object):
+            pass
+
+        c = C()
+        self.assert_(I(c, self) is self)
+
+    def test___call___w_adapter_hook(self):
+        from zope.interface import Interface
+        from zope.interface.interface import adapter_hooks
+        old_hooks = adapter_hooks[:]
+
+        def _miss(iface, obj):
+            pass
+
+        def _hit(iface, obj):
+            return self
+
+        adapter_hooks[:] = [_miss, _hit]
+
+        class I(Interface):
+            pass
+
+        class C(object):
+            pass
+
+        c = C()
+        self.assert_(I(c) is self)
+
+
+class AttributeTests(ElementTests):
+
+    DEFAULT_NAME = 'TestAttribute'
+
+    def _getTargetClass(self):
+        from zope.interface.interface import Attribute
+        return Attribute
+
+
+class MethodTests(AttributeTests):
+
+    DEFAULT_NAME = 'TestMethod'
+
+    def _getTargetClass(self):
+        from zope.interface.interface import Method
+        return Method
+
+    def test_optional_as_property(self):
+        method = self._makeOne()
+        self.assertEqual(method.optional, {})
+        method.optional = {'foo': 'bar'}
+        self.assertEqual(method.optional, {'foo': 'bar'})
+        del method.optional
+        self.assertEqual(method.optional, {})
+
+    def test___call___raises_BrokenImplementation(self):
+        from zope.interface.exceptions import BrokenImplementation
+        method = self._makeOne()
         try:
-            from warnings import catch_warnings
-        except ImportError:  # Python 2.5
-            return
+            method()
+        except BrokenImplementation, e:
+            self.assertEqual(e.interface, None)
+            self.assertEqual(e.name, self.DEFAULT_NAME)
+        else:
+            self.fail('__call__ should raise BrokenImplementation')
+
+    def test_getSignatureInfo_bare(self):
+        method = self._makeOne()
+        info = method.getSignatureInfo()
+        self.assertEqual(list(info['positional']), [])
+        self.assertEqual(list(info['required']), [])
+        self.assertEqual(info['optional'], {})
+        self.assertEqual(info['varargs'], None)
+        self.assertEqual(info['kwargs'], None)
+
+    def test_getSignatureString_bare(self):
+        method = self._makeOne()
+        self.assertEqual(method.getSignatureString(), '()')
+
+    def test_getSignatureString_w_only_required(self):
+        method = self._makeOne()
+        method.positional = method.required = ['foo']
+        self.assertEqual(method.getSignatureString(), '(foo)')
+
+    def test_getSignatureString_w_optional(self):
+        method = self._makeOne()
+        method.positional = method.required = ['foo']
+        method.optional = {'foo': 'bar'}
+        self.assertEqual(method.getSignatureString(), "(foo='bar')")
+
+    def test_getSignatureString_w_varargs(self):
+        method = self._makeOne()
+        method.varargs = 'args'
+        self.assertEqual(method.getSignatureString(), "(*args)")
+
+    def test_getSignatureString_w_kwargs(self):
+        method = self._makeOne()
+        method.kwargs = 'kw'
+        self.assertEqual(method.getSignatureString(), "(**kw)")
+
+
+class Test_fromFunction(unittest.TestCase):
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.interface import fromFunction
+        return fromFunction(*args, **kw)
+
+    def test_bare(self):
+        def _func():
+            "DOCSTRING"
+        method = self._callFUT(_func)
+        self.assertEqual(method.getName(), '_func')
+        self.assertEqual(method.getDoc(), 'DOCSTRING')
+        self.assertEqual(method.interface, None)
+        self.assertEqual(method.getTaggedValueTags(), [])
+        info = method.getSignatureInfo()
+        self.assertEqual(list(info['positional']), [])
+        self.assertEqual(list(info['required']), [])
+        self.assertEqual(info['optional'], {})
+        self.assertEqual(info['varargs'], None)
+        self.assertEqual(info['kwargs'], None)
+
+    def test_w_interface(self):
         from zope.interface.interface import InterfaceClass
-        class Derived(InterfaceClass):
-            def __init__(self):
-                pass # Don't call base class.
-        derived = Derived()
-        with catch_warnings(record=True) as warned:
-            warnings.simplefilter('always') # see LP #825249 
-            self.assertEqual(hash(derived), 1)
-            self.assertEqual(len(warned), 1)
-            self.failUnless(warned[0].category is UserWarning)
-            self.assertEqual(str(warned[0].message),
-                             'Hashing uninitialized InterfaceClass instance')
+        class IFoo(InterfaceClass):
+            pass
+        def _func():
+            "DOCSTRING"
+        method = self._callFUT(_func, interface=IFoo)
+        self.assertEqual(method.interface, IFoo)
 
+    def test_w_name(self):
+        def _func():
+            "DOCSTRING"
+        method = self._callFUT(_func, name='anotherName')
+        self.assertEqual(method.getName(), 'anotherName')
 
-if sys.version_info >= (2, 4):
+    def test_w_only_required(self):
+        def _func(foo):
+            "DOCSTRING"
+        method = self._callFUT(_func)
+        info = method.getSignatureInfo()
+        self.assertEqual(list(info['positional']), ['foo'])
+        self.assertEqual(list(info['required']), ['foo'])
+        self.assertEqual(info['optional'], {})
+        self.assertEqual(info['varargs'], None)
+        self.assertEqual(info['kwargs'], None)
 
-    def test_invariant_as_decorator():
-        """Invaiants can be deined in line
+    def test_w_optional(self):
+        def _func(foo='bar'):
+            "DOCSTRING"
+        method = self._callFUT(_func)
+        info = method.getSignatureInfo()
+        self.assertEqual(list(info['positional']), ['foo'])
+        self.assertEqual(list(info['required']), [])
+        self.assertEqual(info['optional'], {'foo': 'bar'})
+        self.assertEqual(info['varargs'], None)
+        self.assertEqual(info['kwargs'], None)
 
-          >>> from zope.interface.exceptions import Invalid
-          >>> from zope.interface import Interface
-          >>> from zope.interface import Attribute
-          >>> from zope.interface import implements
-          >>> from zope.interface import invariant
-          >>> class IRange(Interface):
-          ...     min = Attribute("Lower bound")
-          ...     max = Attribute("Upper bound")
-          ...
-          ...     @invariant
-          ...     def range_invariant(ob):
-          ...         if ob.max < ob.min:
-          ...             raise Invalid('max < min')
+    def test_w_optional_self(self):
+        # XXX This is a weird case, trying to cover the following code in
+        # FUT::
+        #
+        # nr = na-len(defaults)
+        # if nr < 0:
+        #     defaults=defaults[-nr:]
+        #     nr = 0
+        def _func(self='bar'):
+            "DOCSTRING"
+        method = self._callFUT(_func, imlevel=1)
+        info = method.getSignatureInfo()
+        self.assertEqual(list(info['positional']), [])
+        self.assertEqual(list(info['required']), [])
+        self.assertEqual(info['optional'], {})
+        self.assertEqual(info['varargs'], None)
+        self.assertEqual(info['kwargs'], None)
 
+    def test_w_varargs(self):
+        def _func(*args):
+            "DOCSTRING"
+        method = self._callFUT(_func)
+        info = method.getSignatureInfo()
+        self.assertEqual(list(info['positional']), [])
+        self.assertEqual(list(info['required']), [])
+        self.assertEqual(info['optional'], {})
+        self.assertEqual(info['varargs'], 'args')
+        self.assertEqual(info['kwargs'], None)
 
-          >>> class Range(object):
-          ...     implements(IRange)
-          ...
-          ...     def __init__(self, min, max):
-          ...         self.min, self.max = min, max
+    def test_w_kwargs(self):
+        def _func(**kw):
+            "DOCSTRING"
+        method = self._callFUT(_func)
+        info = method.getSignatureInfo()
+        self.assertEqual(list(info['positional']), [])
+        self.assertEqual(list(info['required']), [])
+        self.assertEqual(info['optional'], {})
+        self.assertEqual(info['varargs'], None)
+        self.assertEqual(info['kwargs'], 'kw')
 
-          >>> from zope.interface.exceptions import Invalid
-          >>> IRange.validateInvariants(Range(1,2))
-          >>> IRange.validateInvariants(Range(1,1))
-          >>> try:
-          ...     IRange.validateInvariants(Range(2,1))
-          ... except Invalid, e:
-          ...     str(e)
-          'max < min'
+    def test_full_spectrum(self):
+        def _func(foo, bar='baz', *args, **kw):
+            "DOCSTRING"
+        method = self._callFUT(_func)
+        info = method.getSignatureInfo()
+        self.assertEqual(list(info['positional']), ['foo', 'bar'])
+        self.assertEqual(list(info['required']), ['foo'])
+        self.assertEqual(info['optional'], {'bar': 'baz'})
+        self.assertEqual(info['varargs'], 'args')
+        self.assertEqual(info['kwargs'], 'kw')
 
 
-        """
+class Test_fromMethod(unittest.TestCase):
 
+    def _callFUT(self, *args, **kw):
+        from zope.interface.interface import fromMethod
+        return fromMethod(*args, **kw)
 
-def test_description_cache_management():
-    """ See https://bugs.launchpad.net/zope.interface/+bug/185974
+    def test_no_args(self):
+        class Foo(object):
+            def bar(self):
+                "DOCSTRING"
+        method = self._callFUT(Foo.bar)
+        self.assertEqual(method.getName(), 'bar')
+        self.assertEqual(method.getDoc(), 'DOCSTRING')
+        self.assertEqual(method.interface, None)
+        self.assertEqual(method.getTaggedValueTags(), [])
+        info = method.getSignatureInfo()
+        self.assertEqual(list(info['positional']), [])
+        self.assertEqual(list(info['required']), [])
+        self.assertEqual(info['optional'], {})
+        self.assertEqual(info['varargs'], None)
+        self.assertEqual(info['kwargs'], None)
 
-There was a bug where the cache used by Specification.get() was not
-cleared when the bases were changed.
+    def test_full_spectrum(self):
+        class Foo(object):
+            def bar(self, foo, bar='baz', *args, **kw):
+                "DOCSTRING"
+        method = self._callFUT(Foo.bar)
+        info = method.getSignatureInfo()
+        self.assertEqual(list(info['positional']), ['foo', 'bar'])
+        self.assertEqual(list(info['required']), ['foo'])
+        self.assertEqual(info['optional'], {'bar': 'baz'})
+        self.assertEqual(info['varargs'], 'args')
+        self.assertEqual(info['kwargs'], 'kw')
 
-    >>> from zope.interface import Interface
-    >>> from zope.interface import Attribute
-    >>> class I1(Interface):
-    ...     a = Attribute('a')
+class DummyDependent(object):
 
-    >>> class I2(I1):
-    ...     pass
+    def __init__(self):
+        self._changed = []
 
-    >>> class I3(I2):
-    ...     pass
+    def changed(self, originally_changed):
+        self._changed.append(originally_changed)
 
-    >>> I3.get('a') is I1.get('a')
-    True
-    >>> I2.__bases__ = (Interface,)
-    >>> I3.get('a') is None
-    True
-    """
 
+def _barGreaterThanFoo(obj):
+    from zope.interface.exceptions import Invalid
+    foo = getattr(obj, 'foo', None)
+    bar = getattr(obj, 'bar', None)
+    if foo is not None and isinstance(foo, type(bar)):
+        # type checking should be handled elsewhere (like, say, 
+        # schema); these invariants should be intra-interface 
+        # constraints.  This is a hacky way to do it, maybe, but you
+        # get the idea
+        if not bar > foo:
+            raise Invalid('Please, Boo MUST be greater than Foo!')
 
+def _ifFooThenBar(obj):
+    from zope.interface.exceptions import Invalid
+    if getattr(obj, 'foo', None) and not getattr(obj, 'bar', None):
+        raise Invalid('If Foo, then Bar!')
+
+
+class _Monkey(object):
+    # context-manager for replacing module names in the scope of a test.
+    def __init__(self, module, **kw):
+        self.module = module
+        self.to_restore = dict([(key, getattr(module, key)) for key in kw])
+        for key, value in kw.items():
+            setattr(module, key, value)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        for key, value in self.to_restore.items():
+            setattr(self.module, key, value)
+
+
 def test_suite():
-    suite = unittest.makeSuite(InterfaceTests)
-    suite.addTest(doctest.DocTestSuite("zope.interface.interface"))
-    if sys.version_info >= (2, 4):
-        suite.addTest(doctest.DocTestSuite())
-    suite.addTest(doctest.DocFileSuite(
-        '../README.txt',
-        globs={'__name__': '__main__'},
-        optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
-        ))
-    suite.addTest(doctest.DocFileSuite(
-        '../README.ru.txt',
-        globs={'__name__': '__main__'},
-        optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
-        ))
-    return suite
+    import doctest
+    return unittest.TestSuite((
+        unittest.makeSuite(ElementTests),
+        unittest.makeSuite(SpecificationBasePyTests),
+        unittest.makeSuite(InterfaceBasePyTests),
+        unittest.makeSuite(SpecificationTests),
+        unittest.makeSuite(InterfaceTests),
+        unittest.makeSuite(AttributeTests),
+        unittest.makeSuite(MethodTests),
+        unittest.makeSuite(Test_fromFunction),
+        #unittest.makeSuite(Test_fromMethod),
+        doctest.DocTestSuite(),
+        doctest.DocTestSuite("zope.interface.interface"),
+    ))

Added: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_interfaces.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_interfaces.py	                        (rev 0)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_interfaces.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -0,0 +1,115 @@
+import unittest
+
+class _SilencePy3Deprecations(unittest.TestCase):
+    # silence deprecation warnings under py3
+
+    def failUnless(self, expr):
+        # St00pid speling.
+        return self.assertTrue(expr)
+
+    def failIf(self, expr):
+        # St00pid speling.
+        return self.assertFalse(expr)
+
+
+class _ConformsToIObjectEvent(object):
+
+    def _makeOne(self, target=None):
+        if target is None:
+            target = object()
+        return self._getTargetClass()(target)
+
+    def test_class_conforms_to_IObjectEvent(self):
+        from zope.interface.interfaces import IObjectEvent
+        from zope.interface.verify import verifyClass
+        verifyClass(IObjectEvent, self._getTargetClass())
+
+    def test_instance_conforms_to_IObjectEvent(self):
+        from zope.interface.interfaces import IObjectEvent
+        from zope.interface.verify import verifyObject
+        verifyObject(IObjectEvent, self._makeOne())
+
+
+class _ConformsToIRegistrationEvent(_ConformsToIObjectEvent):
+
+    def test_class_conforms_to_IRegistrationEvent(self):
+        from zope.interface.interfaces import IRegistrationEvent
+        from zope.interface.verify import verifyClass
+        verifyClass(IRegistrationEvent, self._getTargetClass())
+
+    def test_instance_conforms_to_IRegistrationEvent(self):
+        from zope.interface.interfaces import IRegistrationEvent
+        from zope.interface.verify import verifyObject
+        verifyObject(IRegistrationEvent, self._makeOne())
+
+
+class ObjectEventTests(_SilencePy3Deprecations, _ConformsToIObjectEvent):
+
+    def _getTargetClass(self):
+        from zope.interface.interfaces import ObjectEvent
+        return ObjectEvent
+
+    def test_ctor(self):
+        target = object()
+        event = self._makeOne(target)
+        self.failUnless(event.object is target)
+
+
+class RegistrationEventTests(_SilencePy3Deprecations,
+                             _ConformsToIRegistrationEvent):
+
+    def _getTargetClass(self):
+        from zope.interface.interfaces import RegistrationEvent
+        return RegistrationEvent
+
+    def test___repr__(self):
+        target = object()
+        event = self._makeOne(target)
+        r = repr(event)
+        self.assertEqual(r.splitlines(),
+                         ['RegistrationEvent event:', repr(target)])
+
+
+class RegisteredTests(_SilencePy3Deprecations,
+                      _ConformsToIRegistrationEvent):
+
+    def _getTargetClass(self):
+        from zope.interface.interfaces import Registered
+        return Registered
+
+    def test_class_conforms_to_IRegistered(self):
+        from zope.interface.interfaces import IRegistered
+        from zope.interface.verify import verifyClass
+        verifyClass(IRegistered, self._getTargetClass())
+
+    def test_instance_conforms_to_IRegistered(self):
+        from zope.interface.interfaces import IRegistered
+        from zope.interface.verify import verifyObject
+        verifyObject(IRegistered, self._makeOne())
+
+
+class UnregisteredTests(_SilencePy3Deprecations,
+                        _ConformsToIRegistrationEvent):
+
+    def _getTargetClass(self):
+        from zope.interface.interfaces import Unregistered
+        return Unregistered
+
+    def test_class_conforms_to_IUnregistered(self):
+        from zope.interface.interfaces import IUnregistered
+        from zope.interface.verify import verifyClass
+        verifyClass(IUnregistered, self._getTargetClass())
+
+    def test_instance_conforms_to_IUnregistered(self):
+        from zope.interface.interfaces import IUnregistered
+        from zope.interface.verify import verifyObject
+        verifyObject(IUnregistered, self._makeOne())
+
+
+def test_suite():
+    return unittest.TestSuite((
+            unittest.makeSuite(ObjectEventTests),
+            unittest.makeSuite(RegistrationEventTests),
+            unittest.makeSuite(RegisteredTests),
+            unittest.makeSuite(UnregisteredTests),
+        ))

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_odd_declarations.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_odd_declarations.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_odd_declarations.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -16,13 +16,17 @@
 These tests are to make sure we do something sane in the presence of
 classic ExtensionClass classes and instances.
 """
-import doctest
 import unittest
 
 from zope.interface.tests import odd
-from zope.interface import Interface, implements, classProvides
-from zope.interface import directlyProvides, providedBy, directlyProvidedBy
-from zope.interface import classImplements, classImplementsOnly, implementedBy
+from zope.interface import Interface
+from zope.interface import implements
+from zope.interface import directlyProvides
+from zope.interface import providedBy
+from zope.interface import directlyProvidedBy
+from zope.interface import classImplements
+from zope.interface import classImplementsOnly
+from zope.interface import implementedBy
 
 class I1(Interface): pass
 class I2(Interface): pass
@@ -184,15 +188,15 @@
         self.assertRaises(TypeError, directlyProvides, C, I5)
 
     # see above
-    def TODO_test_classProvides_fails_for_odd_class(self):
-        try:
-            class A(Odd):
-                classProvides(I1)
-        except TypeError:
-            pass # Sucess
-        self.failUnless(False,
-                     "Shouldn't be able to use directlyProvides on odd class."
-                     )
+    #def TODO_test_classProvides_fails_for_odd_class(self):
+    #    try:
+    #        class A(Odd):
+    #            classProvides(I1)
+    #    except TypeError:
+    #        pass # Sucess
+    #    self.assert_(False,
+    #                 "Shouldn't be able to use directlyProvides on odd class."
+    #                 )
 
     def test_implementedBy(self):
         class I2(I1): pass
@@ -208,15 +212,9 @@
         self.assertEqual([i.getName() for i in implementedBy(C2)],
                          ['I3', 'I2'])
 
-
-
-
 def test_suite():
+    import doctest
     suite = unittest.TestSuite()
     suite.addTest(unittest.makeSuite(Test))
     suite.addTest(doctest.DocTestSuite(odd))
     return suite
-
-
-if __name__ == '__main__':
-    unittest.main()

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_registry.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_registry.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_registry.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -12,939 +12,2438 @@
 #
 ##############################################################################
 """Component Registry Tests"""
-
-import types
 import unittest
 
-from zope import interface
-from zope.interface import implementedBy
-from zope.interface.interfaces import ComponentLookupError
-from zope.interface.registry import Components
+class _SilencePy3Deprecations(unittest.TestCase):
+    # silence deprecation warnings under py3
 
-import sys
+    def failUnless(self, expr):
+        # St00pid speling.
+        return self.assertTrue(expr)
 
-# fixtures
+    def failIf(self, expr):
+        # St00pid speling.
+        return self.assertFalse(expr)
 
-if sys.version_info[0] == 3:
-    _class_types = type
-else:
-    _class_types = (type, types.ClassType)
+class ComponentsTests(_SilencePy3Deprecations):
 
-class adapter:
+    def _getTargetClass(self):
+        from zope.interface.registry import Components
+        return Components
 
-    def __init__(self, *interfaces):
-        self.interfaces = interfaces
+    def _makeOne(self, name='test', *args, **kw):
+        return self._getTargetClass()(name, *args, **kw)
 
-    def __call__(self, ob):
-        if isinstance(ob, _class_types):
-            ob.__component_adapts__ = _adapts_descr(self.interfaces)
-        else:
-            ob.__component_adapts__ = self.interfaces
+    def _wrapEvents(self):
+        from zope.interface import registry
+        _events = []
+        def _notify(*args, **kw):
+            _events.append((args, kw))
+        _monkey = _Monkey(registry, notify=_notify)
+        return _monkey, _events
 
-        return ob
+    def test_ctor_no_bases(self):
+        from zope.interface.adapter import AdapterRegistry
+        comp = self._makeOne('testing')
+        self.assertEqual(comp.__name__, 'testing')
+        self.assertEqual(comp.__bases__, ())
+        self.failUnless(isinstance(comp.adapters, AdapterRegistry))
+        self.failUnless(isinstance(comp.utilities, AdapterRegistry))
+        self.assertEqual(comp.adapters.__bases__, ())
+        self.assertEqual(comp.utilities.__bases__, ())
+        self.assertEqual(comp._utility_registrations, {})
+        self.assertEqual(comp._adapter_registrations, {})
+        self.assertEqual(comp._subscription_registrations, [])
+        self.assertEqual(comp._handler_registrations, [])
 
+    def test_ctor_w_base(self):
+        base = self._makeOne('base')
+        comp = self._makeOne('testing', (base,))
+        self.assertEqual(comp.__name__, 'testing')
+        self.assertEqual(comp.__bases__, (base,))
+        self.assertEqual(comp.adapters.__bases__, (base.adapters,))
+        self.assertEqual(comp.utilities.__bases__, (base.utilities,))
 
-def adapts(*interfaces):
-    frame = sys._getframe(1)
-    locals = frame.f_locals
+    def test___repr__(self):
+        comp = self._makeOne('testing')
+        self.assertEqual(repr(comp), '<Components testing>')
 
-    # Try to make sure we were called from a class def. In 2.2.0 we can't
-    # check for __module__ since it doesn't seem to be added to the locals
-    # until later on.
-    if (locals is frame.f_globals) or (
-        ('__module__' not in locals) and sys.version_info[:3] > (2, 2, 0)):
-        raise TypeError("adapts can be used only from a class definition.")
+    # test _init_registries / _init_registrations via only caller, __init__.
 
-    if '__component_adapts__' in locals:
-        raise TypeError("adapts can be used only once in a class definition.")
+    def test_assign_to___bases__(self):
+        base1 = self._makeOne('base1')
+        base2 = self._makeOne('base2')
+        comp = self._makeOne()
+        comp.__bases__ = (base1, base2)
+        self.assertEqual(comp.__bases__, (base1, base2))
+        self.assertEqual(comp.adapters.__bases__,
+                         (base1.adapters, base2.adapters))
+        self.assertEqual(comp.utilities.__bases__,
+                         (base1.utilities, base2.utilities))
 
-    locals['__component_adapts__'] = _adapts_descr(interfaces)
+    def test_registerUtility_both_factory_and_component(self):
+        def _factory():
+            pass
+        _to_reg = object()
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.registerUtility,
+                          component=_to_reg, factory=_factory)
 
-class _adapts_descr(object):
-    def __init__(self, interfaces):
-        self.interfaces = interfaces
+    def test_registerUtility_w_component(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import UtilityRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = object()
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerUtility(_to_reg, ifoo, _name, _info)
+        self.failUnless(comp.utilities._adapters[0][ifoo][_name] is _to_reg)
+        self.assertEqual(comp._utility_registrations[ifoo, _name],
+                         (_to_reg, _info, None))
+        self.assertEqual(comp.utilities._subscribers[0][ifoo][''], (_to_reg,))
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, UtilityRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.component is _to_reg)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is None)
 
-    def __get__(self, inst, cls):
-        if inst is None:
-            return self.interfaces
-        raise AttributeError('__component_adapts__')
+    def test_registerUtility_w_factory(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import UtilityRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = object()
+        def _factory():
+            return _to_reg
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerUtility(None, ifoo, _name, _info, factory=_factory)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, UtilityRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.component is _to_reg)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is _factory)
 
-class I1(interface.Interface):
-    pass
-class I2(interface.Interface):
-    pass
-class I2e(I2):
-    pass
-class I3(interface.Interface):
-    pass
-class IC(interface.Interface):
-    pass
+    def test_registerUtility_no_provided_available(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        class Foo(object):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = Foo()
+        comp = self._makeOne()
+        self.assertRaises(TypeError,
+                          comp.registerUtility, _to_reg, None, _name, _info)
 
-class ITestType(interface.interfaces.IInterface):
-    pass
+    def test_registerUtility_wo_provided(self):
+        from zope.interface.declarations import directlyProvides
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import UtilityRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        class Foo(object):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = Foo()
+        directlyProvides(_to_reg, ifoo)
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerUtility(_to_reg, None, _name, _info)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, UtilityRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.component is _to_reg)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is None)
 
-class U:
+    def test_registerUtility_duplicates_existing_reg(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = object()
+        comp = self._makeOne()
+        comp.registerUtility(_to_reg, ifoo, _name, _info)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerUtility(_to_reg, ifoo, _name, _info)
+        self.assertEqual(len(_events), 0)
 
-    def __init__(self, name):
-        self.__name__ = name
+    def test_registerUtility_replaces_existing_reg(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import UtilityRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name = _u('name')
+        _before, _after = object(), object()
+        comp = self._makeOne()
+        comp.registerUtility(_before, ifoo, _name, _info)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerUtility(_after, ifoo, _name, _info)
+        self.assertEqual(len(_events), 2)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, UtilityRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.component is _before)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is None)
+        args, kw = _events[1]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, UtilityRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.component is _after)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is None)
 
-    def __repr__(self):
-        return "%s(%s)" % (self.__class__.__name__, self.__name__)
+    def test_registerUtility_w_existing_subscr(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name1 = _u('name1')
+        _name2 = _u('name2')
+        _to_reg = object()
+        comp = self._makeOne()
+        comp.registerUtility(_to_reg, ifoo, _name1, _info)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerUtility(_to_reg, ifoo, _name2, _info)
+        self.assertEqual(comp.utilities._subscribers[0][ifoo][''], (_to_reg,))
 
-class U1(U):
-    interface.implements(I1)
+    def test_registerUtility_wo_event(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = object()
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerUtility(_to_reg, ifoo, _name, _info, False)
+        self.assertEqual(len(_events), 0)
 
-class U12(U):
-    interface.implements(I1, I2)
+    def test_unregisterUtility_neither_factory_nor_component_nor_provided(self):
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.unregisterUtility,
+                          component=None, provided=None, factory=None)
 
-class IA1(interface.Interface):
-    pass
+    def test_unregisterUtility_both_factory_and_component(self):
+        def _factory():
+            pass
+        _to_reg = object()
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.unregisterUtility,
+                          component=_to_reg, factory=_factory)
 
-class IA2(interface.Interface):
-    pass
+    def test_unregisterUtility_w_component_miss(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _name = _u('name')
+        _to_reg = object()
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterUtility(_to_reg, ifoo, _name)
+        self.failIf(unreg)
+        self.failIf(_events)
 
-class IA3(interface.Interface):
-    pass
+    def test_unregisterUtility_w_component(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import UtilityRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _name = _u('name')
+        _to_reg = object()
+        comp = self._makeOne()
+        comp.registerUtility(_to_reg, ifoo, _name)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterUtility(_to_reg, ifoo, _name)
+        self.failUnless(unreg)
+        self.failIf(comp.utilities._adapters) # all erased
+        self.failIf((ifoo, _name) in comp._utility_registrations)
+        self.failIf(comp.utilities._subscribers)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, UtilityRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.component is _to_reg)
+        self.failUnless(event.object.factory is None)
 
-class A:
+    def test_unregisterUtility_w_factory(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import UtilityRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = object()
+        def _factory():
+            return _to_reg
+        comp = self._makeOne()
+        comp.registerUtility(None, ifoo, _name, _info, factory=_factory)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterUtility(None, ifoo, _name, factory=_factory)
+        self.failUnless(unreg)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, UtilityRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.component is _to_reg)
+        self.failUnless(event.object.factory is _factory)
 
-    def __init__(self, *context):
-        self.context = context
+    def test_unregisterUtility_wo_explicit_provided(self):
+        from zope.interface.declarations import directlyProvides
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import UtilityRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        class Foo(object):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = Foo()
+        directlyProvides(_to_reg, ifoo)
+        comp = self._makeOne()
+        comp.registerUtility(_to_reg, ifoo, _name, _info)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterUtility(_to_reg, None, _name)
+        self.failUnless(unreg)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, UtilityRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.component is _to_reg)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is None)
 
-    def __repr__(self):
-        return "%s%r" % (self.__class__.__name__, self.context)
+    def test_unregisterUtility_wo_component_or_factory(self):
+        from zope.interface.declarations import directlyProvides
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import UtilityRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        class Foo(object):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = Foo()
+        directlyProvides(_to_reg, ifoo)
+        comp = self._makeOne()
+        comp.registerUtility(_to_reg, ifoo, _name, _info)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            # Just pass the interface / name
+            unreg = comp.unregisterUtility(provided=ifoo, name=_name)
+        self.failUnless(unreg)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, UtilityRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.component is _to_reg)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is None)
 
-class A12_1(A):
-    adapts(I1, I2)
-    interface.implements(IA1)
+    def test_unregisterUtility_w_existing_subscr(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name1 = _u('name1')
+        _name2 = _u('name2')
+        _to_reg = object()
+        comp = self._makeOne()
+        comp.registerUtility(_to_reg, ifoo, _name1, _info)
+        comp.registerUtility(_to_reg, ifoo, _name2, _info)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.unregisterUtility(_to_reg, ifoo, _name2)
+        self.assertEqual(comp.utilities._subscribers[0][ifoo][''], (_to_reg,))
 
-class A12_(A):
-    adapts(I1, I2)
+    def test_registeredUtilities_empty(self):
+        comp = self._makeOne()
+        self.assertEqual(list(comp.registeredUtilities()), [])
 
-class A_2(A):
-    interface.implements(IA2)
+    def test_registeredUtilities_notempty(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        from zope.interface.registry import UtilityRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name1 = _u('name1')
+        _name2 = _u('name2')
+        _to_reg = object()
+        comp = self._makeOne()
+        comp.registerUtility(_to_reg, ifoo, _name1, _info)
+        comp.registerUtility(_to_reg, ifoo, _name2, _info)
+        reg = list(comp.registeredUtilities())
+        self.assertEqual(len(reg), 2)
+        self.failUnless(isinstance(reg[0], UtilityRegistration))
+        self.failUnless(reg[0].registry is comp)
+        self.failUnless(reg[0].provided is ifoo)
+        self.failUnless(reg[0].name is _name1)
+        self.failUnless(reg[0].component is _to_reg)
+        self.failUnless(reg[0].info is _info)
+        self.failUnless(reg[0].factory is None)
+        self.failUnless(isinstance(reg[1], UtilityRegistration))
+        self.failUnless(reg[1].registry is comp)
+        self.failUnless(reg[1].provided is ifoo)
+        self.failUnless(reg[1].name is _name2)
+        self.failUnless(reg[1].component is _to_reg)
+        self.failUnless(reg[1].info is _info)
+        self.failUnless(reg[1].factory is None)
 
-class A_3(A):
-    interface.implements(IA3)
+    def test_queryUtility_miss_no_default(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        self.failUnless(comp.queryUtility(ifoo) is None)
 
-class A1_12(U):
-    adapts(I1)
-    interface.implements(IA1, IA2)
+    def test_queryUtility_miss_w_default(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        _default = object()
+        self.failUnless(comp.queryUtility(ifoo, default=_default) is _default)
 
-class A1_2(U):
-    adapts(I1)
-    interface.implements(IA2)
+    def test_queryUtility_hit(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _to_reg = object()
+        comp = self._makeOne()
+        comp.registerUtility(_to_reg, ifoo)
+        self.failUnless(comp.queryUtility(ifoo) is _to_reg)
 
-class A1_23(U):
-    adapts(I1)
-    interface.implements(IA1, IA3)
+    def test_getUtility_miss(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import ComponentLookupError
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        self.assertRaises(ComponentLookupError, comp.getUtility, ifoo)
 
-def noop(*args):
-    pass
+    def test_getUtility_hit(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _to_reg = object()
+        comp = self._makeOne()
+        comp.registerUtility(_to_reg, ifoo)
+        self.failUnless(comp.getUtility(ifoo) is _to_reg)
 
+    def test_getUtilitiesFor_miss(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        self.assertEqual(list(comp.getUtilitiesFor(ifoo)), [])
 
-# tests
+    def test_getUtilitiesFor_hit(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _name1 = _u('name1')
+        _name2 = _u('name2')
+        _to_reg = object()
+        comp = self._makeOne()
+        comp.registerUtility(_to_reg, ifoo, name=_name1)
+        comp.registerUtility(_to_reg, ifoo, name=_name2)
+        self.assertEqual(sorted(comp.getUtilitiesFor(ifoo)),
+                         [(_name1, _to_reg), (_name2, _to_reg)])
 
-class TestAdapter(unittest.TestCase):
+    def test_getAllUtilitiesRegisteredFor_miss(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        self.assertEqual(list(comp.getAllUtilitiesRegisteredFor(ifoo)), [])
 
-    def setUp(self):
-        self.components = Components('comps')
+    def test_getAllUtilitiesRegisteredFor_hit(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _name1 = _u('name1')
+        _name2 = _u('name2')
+        _to_reg = object()
+        comp = self._makeOne()
+        comp.registerUtility(_to_reg, ifoo, name=_name1)
+        comp.registerUtility(_to_reg, ifoo, name=_name2)
+        self.assertEqual(list(comp.getAllUtilitiesRegisteredFor(ifoo)),
+                         [_to_reg])
 
-    def test_register_and_unregister_adapter(self):
-        self.components.registerAdapter(A12_1)
+    def test_registerAdapter_w_explicit_provided_and_required(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import AdapterRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = object()
+        def _factory(context):
+            return _to_reg
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerAdapter(_factory, (ibar,), ifoo, _name, _info)
+        self.failUnless(comp.adapters._adapters[1][ibar][ifoo][_name]
+                        is _factory)
+        self.assertEqual(comp._adapter_registrations[(ibar,), ifoo, _name],
+                         (_factory, _info))
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, AdapterRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is _factory)
 
-        multi_adapter = self.components.getMultiAdapter(
-            (U1(1), U12(2)), IA1)
-        self.assertEqual(multi_adapter.__class__, A12_1)
-        self.assertEqual(repr(multi_adapter), 'A12_1(U1(1), U12(2))')
+    def test_registerAdapter_no_provided_available(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = object()
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.registerAdapter, _Factory, (ibar,),
+                          name=_name, info=_info)
 
-        self.assertTrue(self.components.unregisterAdapter(A12_1))
-        self.assertRaises(
-            ComponentLookupError,
-            self.components.getMultiAdapter,
-            (U1(1), U12(2)),
-            IA1
-            )
+    def test_registerAdapter_wo_explicit_provided(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import AdapterRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = object()
+        @implementer(ifoo)
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerAdapter(_Factory, (ibar,), name=_name, info=_info)
+        self.failUnless(comp.adapters._adapters[1][ibar][ifoo][_name]
+                        is _Factory)
+        self.assertEqual(comp._adapter_registrations[(ibar,), ifoo, _name],
+                         (_Factory, _info))
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, AdapterRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is _Factory)
 
-    def test_register_and_unregister_adapter_with_two_interfaces(self):
-        self.assertRaises(TypeError, self.components.registerAdapter,
-                          A1_12)
-        self.components.registerAdapter(A1_12,
-                                        provided=IA2)
+    def test_registerAdapter_no_required_available(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _info = _u('info')
+        _name = _u('name')
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.registerAdapter, _Factory,
+                          provided=ifoo, name=_name, info=_info)
 
-        multi_adapter = self.components.getMultiAdapter((U1(1),), IA2)
-        self.assertEqual(multi_adapter.__class__, A1_12)
-        self.assertEqual(repr(multi_adapter), 'A1_12(U1(1))')
+    def test_registerAdapter_w_invalid_required(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _info = _u('info')
+        _name = _u('name')
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.registerAdapter, _Factory,
+                          ibar, provided=ifoo, name=_name, info=_info)
 
-        self.assertRaises(TypeError, self.components.unregisterAdapter, A1_12)
-        self.assertTrue(self.components.unregisterAdapter(A1_12, provided=IA2))
-        self.assertRaises(ComponentLookupError,
-                          self.components.getMultiAdapter, (U1(1),), IA2)
+    def test_registerAdapter_w_required_containing_None(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interface import Interface
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import AdapterRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _name = _u('name')
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerAdapter(_Factory, [None], provided=ifoo,
+                                 name=_name, info=_info)
+        self.failUnless(comp.adapters._adapters[1][Interface][ifoo][_name]
+                        is _Factory)
+        self.assertEqual(comp._adapter_registrations[(Interface,), ifoo, _name],
+                         (_Factory, _info))
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, AdapterRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (Interface,))
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is _Factory)
 
-    def test_register_and_unregister_adapter_with_no_interfaces(self):
-        self.assertRaises(TypeError, self.components.registerAdapter, A12_)
+    def test_registerAdapter_w_required_containing_class(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implements
+        from zope.interface.declarations import implementedBy
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import AdapterRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _info = _u('info')
+        _name = _u('name')
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        class _Context(object):
+            implements(ibar)
+        _ctx_impl = implementedBy(_Context)
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerAdapter(_Factory, [_Context], provided=ifoo,
+                                 name=_name, info=_info)
+        self.failUnless(comp.adapters._adapters[1][_ctx_impl][ifoo][_name]
+                        is _Factory)
+        self.assertEqual(comp._adapter_registrations[(_ctx_impl,), ifoo, _name],
+                         (_Factory, _info))
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, AdapterRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (_ctx_impl,))
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is _Factory)
 
-        self.components.registerAdapter(A12_, provided=IA2)
-        multi_adapter = self.components.getMultiAdapter((U1(1), U12(2)), IA2)
-        self.assertEqual(multi_adapter.__class__, A12_)
-        self.assertEqual(repr(multi_adapter), 'A12_(U1(1), U12(2))')
+    def test_registerAdapter_w_required_containing_junk(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _info = _u('info')
+        _name = _u('name')
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.registerAdapter, _Factory, [object()],
+                          provided=ifoo, name=_name, info=_info)
 
-        self.assertRaises(TypeError, self.components.unregisterAdapter, A12_)
-        self.assertTrue(self.components.unregisterAdapter(A12_, provided=IA2))
-        self.assertRaises(ComponentLookupError,
-                          self.components.getMultiAdapter, (U1(1), U12(2)), IA2)
+    def test_registerAdapter_wo_explicit_required(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import AdapterRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _info = _u('info')
+        _name = _u('name')
+        class _Factory(object):
+            __component_adapts__ = (ibar,)
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerAdapter(_Factory, provided=ifoo, name=_name,
+                                 info=_info)
+        self.failUnless(comp.adapters._adapters[1][ibar][ifoo][_name]
+                        is _Factory)
+        self.assertEqual(comp._adapter_registrations[(ibar,), ifoo, _name],
+                         (_Factory, _info))
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, AdapterRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.failUnless(event.object.name is _name)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is _Factory)
 
-    def test_reg_and_unreg_adp_with_no___component_adapts___attribute(self):
-        self.assertRaises(TypeError, self.components.registerAdapter, A_2)
-        self.components.registerAdapter(A_2, required=[I3])
-        self.assertTrue(self.components.unregisterAdapter(A_2, required=[I3]))
+    def test_registerAdapter_wo_event(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _info = _u('info')
+        _name = _u('name')
+        _to_reg = object()
+        def _factory(context):
+            return _to_reg
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerAdapter(_factory, (ibar,), ifoo, _name, _info,
+                                 event=False)
+        self.assertEqual(len(_events), 0)
 
-    def test_register_and_unregister_class_specific(self):
-        self.components.registerAdapter(A_3, required=[U],
-                                        info=u'Really class specific')
-        self.assertTrue(self.components.unregisterAdapter(required=[U],
-                                                          provided=IA3))
-      
-    def test_registered_adapters_and_sorting(self):
-        self.components.registerAdapter(A12_1)
-        self.components.registerAdapter(A1_12, provided=IA2)
-        self.components.registerAdapter(A12_, provided=IA2)
-        self.components.registerAdapter(A_2, required=[I3])
-        self.components.registerAdapter(A_3, required=[U],
-                                        info=u'Really class specific')
+    def test_unregisterAdapter_neither_factory_nor_provided(self):
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.unregisterAdapter,
+                          factory=None, provided=None)
 
-        sorted_adapters = sorted(self.components.registeredAdapters())
-        sorted_adapters_name = map(lambda x: getattr(x, 'name'),
-                                   sorted_adapters)
-        sorted_adapters_provided = map(lambda x: getattr(x, 'provided'),
-                                       sorted_adapters) 
-        sorted_adapters_required = map(lambda x: getattr(x, 'required'),
-                                       sorted_adapters)
-        sorted_adapters_info = map(lambda x: getattr(x, 'info'),
-                                   sorted_adapters)
+    def test_unregisterAdapter_neither_factory_nor_required(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.unregisterAdapter,
+                          factory=None, provided=ifoo, required=None)
 
-        self.assertEqual(len(sorted_adapters), 5)
-        self.assertEqual(sorted_adapters_name, [u'', u'', u'', u'', u''])
-        self.assertEqual(sorted_adapters_provided, [IA1,
-                                                    IA2,
-                                                    IA2,
-                                                    IA2,
-                                                    IA3])
+    def test_unregisterAdapter_miss(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterAdapter(_Factory, (ibar,), ifoo)
+        self.failIf(unreg)
 
-        self.assertEqual(sorted_adapters_required, [(I1, I2),
-                                                    (I1, I2),
-                                                    (I1,),
-                                                    (I3,),
-                                                    (implementedBy(U),)])
-        self.assertEqual(sorted_adapters_info,
-                         [u'', u'', u'', u'', u'Really class specific'])
+    def test_unregisterAdapter_hit_w_explicit_provided_and_required(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import AdapterRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        comp.registerAdapter(_Factory, (ibar,), ifoo)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterAdapter(_Factory, (ibar,), ifoo)
+        self.failUnless(unreg)
+        self.failIf(comp.adapters._adapters)
+        self.failIf(comp._adapter_registrations)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, AdapterRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.assertEqual(event.object.name, '')
+        self.assertEqual(event.object.info, '')
+        self.failUnless(event.object.factory is _Factory)
 
-    def test_get_none_existing_adapter(self):
-        self.assertRaises(ComponentLookupError,
-                          self.components.getMultiAdapter, (U(1),), IA1)
+    def test_unregisterAdapter_wo_explicit_provided(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import AdapterRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        @implementer(ifoo)
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        comp.registerAdapter(_Factory, (ibar,), ifoo)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterAdapter(_Factory, (ibar,))
+        self.failUnless(unreg)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, AdapterRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.assertEqual(event.object.name, '')
+        self.assertEqual(event.object.info, '')
+        self.failUnless(event.object.factory is _Factory)
 
-    def test_query_none_existing_adapter(self):
-        self.assertTrue(self.components.queryMultiAdapter((U(1),), IA1) is None)
-        self.assertEqual(self.components.queryMultiAdapter((U(1),), IA1,
-                                                           default=42), 42)
+    def test_unregisterAdapter_wo_explicit_required(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import AdapterRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Factory(object):
+            __component_adapts__ = (ibar,)
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        comp.registerAdapter(_Factory, (ibar,), ifoo)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterAdapter(_Factory, provided=ifoo)
+        self.failUnless(unreg)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, AdapterRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.assertEqual(event.object.name, '')
+        self.assertEqual(event.object.info, '')
+        self.failUnless(event.object.factory is _Factory)
 
-    def test_unregister_none_existing_adapter(self):
-        self.assertFalse(self.components.unregisterAdapter(A_2, required=[I3]))
-        self.assertFalse(self.components.unregisterAdapter(A12_1, required=[U]))
+    def test_registeredAdapters_empty(self):
+        comp = self._makeOne()
+        self.assertEqual(list(comp.registeredAdapters()), [])
 
-    def test_unregister_adapter(self):
-        self.components.registerAdapter(A12_1)
-        self.components.registerAdapter(A1_12, provided=IA2)
-        self.components.registerAdapter(A12_, provided=IA2)
-        self.components.registerAdapter(A_2, required=[I3])
-        self.components.registerAdapter(A_3, required=[U],
-                                        info=u'Really class specific')
+    def test_registeredAdapters_notempty(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        from zope.interface.registry import AdapterRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IFoo')
+        _info = _u('info')
+        _name1 = _u('name1')
+        _name2 = _u('name2')
+        class _Factory(object):
+            def __init__(self, context):
+                pass
+        comp = self._makeOne()
+        comp.registerAdapter(_Factory, (ibar,), ifoo, _name1, _info)
+        comp.registerAdapter(_Factory, (ibar,), ifoo, _name2, _info)
+        reg = list(comp.registeredAdapters())
+        self.assertEqual(len(reg), 2)
+        self.failUnless(isinstance(reg[0], AdapterRegistration))
+        self.failUnless(reg[0].registry is comp)
+        self.failUnless(reg[0].provided is ifoo)
+        self.assertEqual(reg[0].required, (ibar,))
+        self.failUnless(reg[0].name is _name1)
+        self.failUnless(reg[0].info is _info)
+        self.failUnless(reg[0].factory is _Factory)
+        self.failUnless(isinstance(reg[1], AdapterRegistration))
+        self.failUnless(reg[1].registry is comp)
+        self.failUnless(reg[1].provided is ifoo)
+        self.assertEqual(reg[1].required, (ibar,))
+        self.failUnless(reg[1].name is _name2)
+        self.failUnless(reg[1].info is _info)
+        self.failUnless(reg[1].factory is _Factory)
 
-        self.assertTrue(self.components.unregisterAdapter(A12_1))
-        self.assertTrue(self.components.unregisterAdapter(
-            required=[U], provided=IA3))
+    def test_queryAdapter_miss_no_default(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        _context = object()
+        self.failUnless(comp.queryAdapter(_context, ifoo) is None)
 
-        sorted_adapters = sorted(self.components.registeredAdapters())
-        sorted_adapters_name = map(lambda x: getattr(x, 'name'),
-                                   sorted_adapters)
-        sorted_adapters_provided = map(lambda x: getattr(x, 'provided'),
-                                       sorted_adapters) 
-        sorted_adapters_required = map(lambda x: getattr(x, 'required'),
-                                       sorted_adapters)
-        sorted_adapters_info = map(lambda x: getattr(x, 'info'),
-                                   sorted_adapters)
+    def test_queryAdapter_miss_w_default(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        _context = object()
+        _default = object()
+        self.failUnless(
+            comp.queryAdapter(_context, ifoo, default=_default) is _default)
 
-        self.assertEqual(len(sorted_adapters), 3)
-        self.assertEqual(sorted_adapters_name, [u'', u'', u''])
-        self.assertEqual(sorted_adapters_provided, [IA2,
-                                                    IA2,
-                                                    IA2])
-        self.assertEqual(sorted_adapters_required, [(I1, I2),
-                                                    (I1,),
-                                                    (I3,)])
-        self.assertEqual(sorted_adapters_info, [u'', u'', u''])
+    def test_queryAdapter_hit(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Factory(object):
+            def __init__(self, context):
+                self.context = context
+        @implementer(ibar)
+        class _Context(object):
+            pass
+        _context = _Context()
+        comp = self._makeOne()
+        comp.registerAdapter(_Factory, (ibar,), ifoo)
+        adapter = comp.queryAdapter(_context, ifoo)
+        self.failUnless(isinstance(adapter, _Factory))
+        self.failUnless(adapter.context is _context)
 
-    def test_register_named_adapter(self):
-        self.components.registerAdapter(A1_12, provided=IA2, name=u'test')
-        self.assertTrue(
-            self.components.queryMultiAdapter((U1(1),), IA2) is None)
-        self.assertEqual(
-            repr(self.components.queryMultiAdapter((U1(1),),IA2,name=u'test')),
-            'A1_12(U1(1))')
+    def test_getAdapter_miss(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        from zope.interface.interfaces import ComponentLookupError
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        @implementer(ibar)
+        class _Context(object):
+            pass
+        _context = _Context()
+        comp = self._makeOne()
+        self.assertRaises(ComponentLookupError,
+                          comp.getAdapter, _context, ifoo)
 
-        self.assertTrue(self.components.queryAdapter(U1(1), IA2) is None)
-        self.assertEqual(
-            repr(self.components.queryAdapter(U1(1), IA2, name=u'test')),
-            'A1_12(U1(1))')
-        self.assertEqual(
-            repr(self.components.getAdapter(U1(1), IA2, name=u'test')),
-            'A1_12(U1(1))')
+    def test_getAdapter_hit(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Factory(object):
+            def __init__(self, context):
+                self.context = context
+        @implementer(ibar)
+        class _Context(object):
+            pass
+        _context = _Context()
+        comp = self._makeOne()
+        comp.registerAdapter(_Factory, (ibar,), ifoo)
+        adapter = comp.getAdapter(_context, ifoo)
+        self.failUnless(isinstance(adapter, _Factory))
+        self.failUnless(adapter.context is _context)
 
-    def test_get_adapters(self):
-        self.components.registerAdapter(A1_12, provided=IA1, name=u'test 1')
-        self.components.registerAdapter(A1_23, provided=IA2, name=u'test 2')
-        self.components.registerAdapter(A1_12, provided=IA2)
-        self.components.registerAdapter(A1_12, provided=IA2)
+    def test_queryMultiAdapter_miss(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        ibaz = IFoo('IBaz')
+        @implementer(ibar)
+        class _Context1(object):
+            pass
+        @implementer(ibaz)
+        class _Context2(object):
+            pass
+        _context1 = _Context1()
+        _context2 = _Context2()
+        comp = self._makeOne()
+        self.assertEqual(comp.queryMultiAdapter((_context1, _context2), ifoo),
+                         None)
 
-        adapters = list(self.components.getAdapters((U1(1),), IA2))
-        self.assertEqual(len(adapters), 2)
-        self.assertEqual(adapters[0][0], u'test 2')
-        self.assertEqual(adapters[1][0], u'')
-        self.assertEqual(repr(adapters[0][1]), 'A1_23(U1(1))')
-        self.assertEqual(repr(adapters[1][1]), 'A1_12(U1(1))')
+    def test_queryMultiAdapter_miss_w_default(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        ibaz = IFoo('IBaz')
+        @implementer(ibar)
+        class _Context1(object):
+            pass
+        @implementer(ibaz)
+        class _Context2(object):
+            pass
+        _context1 = _Context1()
+        _context2 = _Context2()
+        _default = object()
+        comp = self._makeOne()
+        self.failUnless(
+            comp.queryMultiAdapter((_context1, _context2), ifoo,
+                                   default=_default) is _default)
 
-    def test_register_no_factory(self):
-        self.components.registerAdapter(A1_12, provided=IA2)
-        self.components.registerAdapter(noop, 
-                                        required=[IA1], provided=IA2, 
-                                        name=u'test noop')
+    def test_queryMultiAdapter_hit(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        ibaz = IFoo('IBaz')
+        @implementer(ibar)
+        class _Context1(object):
+            pass
+        @implementer(ibaz)
+        class _Context2(object):
+            pass
+        _context1 = _Context1()
+        _context2 = _Context2()
+        class _Factory(object):
+            def __init__(self, context1, context2):
+                self.context = context1, context2
+        comp = self._makeOne()
+        comp.registerAdapter(_Factory, (ibar, ibaz), ifoo)
+        adapter = comp.queryMultiAdapter((_context1, _context2), ifoo)
+        self.failUnless(isinstance(adapter, _Factory))
+        self.assertEqual(adapter.context, (_context1, _context2))
 
-        self.assertTrue(
-            self.components.queryAdapter(U1(9), IA2, name=u'test noop') is None)
-        adapters = list(self.components.getAdapters((U1(1),), IA2))
-        self.assertEqual(len(adapters), 1)
-        self.assertEqual(adapters[0][0], u'')
-        self.assertEqual(repr(adapters[0][1]), 'A1_12(U1(1))')
+    def test_getMultiAdapter_miss(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        from zope.interface.interfaces import ComponentLookupError
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        ibaz = IFoo('IBaz')
+        @implementer(ibar)
+        class _Context1(object):
+            pass
+        @implementer(ibaz)
+        class _Context2(object):
+            pass
+        _context1 = _Context1()
+        _context2 = _Context2()
+        comp = self._makeOne()
+        self.assertRaises(ComponentLookupError,
+                          comp.getMultiAdapter, (_context1, _context2), ifoo)
 
-        self.assertTrue(self.components.unregisterAdapter(A1_12, provided=IA2))
+    def test_getMultiAdapter_hit(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        ibaz = IFoo('IBaz')
+        @implementer(ibar)
+        class _Context1(object):
+            pass
+        @implementer(ibaz)
+        class _Context2(object):
+            pass
+        _context1 = _Context1()
+        _context2 = _Context2()
+        class _Factory(object):
+            def __init__(self, context1, context2):
+                self.context = context1, context2
+        comp = self._makeOne()
+        comp.registerAdapter(_Factory, (ibar, ibaz), ifoo)
+        adapter = comp.getMultiAdapter((_context1, _context2), ifoo)
+        self.failUnless(isinstance(adapter, _Factory))
+        self.assertEqual(adapter.context, (_context1, _context2))
 
-        sorted_adapters = sorted(self.components.registeredAdapters())
-        sorted_adapters_name = map(lambda x: getattr(x, 'name'),
-                                   sorted_adapters)
-        sorted_adapters_provided = map(lambda x: getattr(x, 'provided'),
-                                       sorted_adapters) 
-        sorted_adapters_required = map(lambda x: getattr(x, 'required'),
-                                       sorted_adapters)
-        sorted_adapters_info = map(lambda x: getattr(x, 'info'),
-                                   sorted_adapters)
+    def test_getAdapters_empty(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        ibaz = IFoo('IBaz')
+        @implementer(ibar)
+        class _Context1(object):
+            pass
+        @implementer(ibaz)
+        class _Context2(object):
+            pass
+        _context1 = _Context1()
+        _context2 = _Context2()
+        comp = self._makeOne()
+        self.assertEqual(
+            list(comp.getAdapters((_context1, _context2), ifoo)), [])
 
-        self.assertEqual(len(sorted_adapters), 1)
-        self.assertEqual(sorted_adapters_name, [u'test noop'])
-        self.assertEqual(sorted_adapters_provided, [IA2])
-        self.assertEqual(sorted_adapters_required, [(IA1,)])
-        self.assertEqual(sorted_adapters_info, [u''])
+    def test_getAdapters_non_empty(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        ibaz = IFoo('IBaz')
+        @implementer(ibar)
+        class _Context1(object):
+            pass
+        @implementer(ibaz)
+        class _Context2(object):
+            pass
+        _context1 = _Context1()
+        _context2 = _Context2()
+        class _Factory1(object):
+            def __init__(self, context1, context2):
+                self.context = context1, context2
+        class _Factory2(object):
+            def __init__(self, context1, context2):
+                self.context = context1, context2
+        _name1 = _u('name1')
+        _name2 = _u('name2')
+        comp = self._makeOne()
+        comp.registerAdapter(_Factory1, (ibar, ibaz), ifoo, name=_name1)
+        comp.registerAdapter(_Factory2, (ibar, ibaz), ifoo, name=_name2)
+        found = sorted(comp.getAdapters((_context1, _context2), ifoo))
+        self.assertEqual(len(found), 2)
+        self.assertEqual(found[0][0], _name1)
+        self.failUnless(isinstance(found[0][1], _Factory1))
+        self.assertEqual(found[1][0], _name2)
+        self.failUnless(isinstance(found[1][1], _Factory2))
 
+    def test_registerSubscriptionAdapter_w_nonblank_name(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _name = _u('name')
+        _info = _u('info')
+        _to_reg = object()
+        def _factory(context):
+            return _to_reg
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.registerSubscriptionAdapter,
+                          _factory, (ibar,), ifoo, _name, _info)
 
-class TestExtending(unittest.TestCase):
+    def test_registerSubscriptionAdapter_w_explicit_provided_and_required(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import SubscriptionRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _blank = _u('')
+        _info = _u('info')
+        _to_reg = object()
+        def _factory(context):
+            return _to_reg
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerSubscriptionAdapter(_factory, (ibar,), ifoo,
+                                             info=_info)
+        reg = comp.adapters._subscribers[1][ibar][ifoo][_blank]
+        self.assertEqual(len(reg), 1)
+        self.failUnless(reg[0] is _factory)
+        self.assertEqual(comp._subscription_registrations,
+                         [((ibar,), ifoo, _blank, _factory, _info)])
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, SubscriptionRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.assertEqual(event.object.name, _blank)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is _factory)
 
-    def test_extendning(self):
-        c1 = Components('1')
-        self.assertEqual(c1.__bases__, ())
+    def test_registerSubscriptionAdapter_wo_explicit_provided(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import SubscriptionRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _info = _u('info')
+        _blank = _u('')
+        _to_reg = object()
+        @implementer(ifoo)
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerSubscriptionAdapter(_Factory, (ibar,), info=_info)
+        reg = comp.adapters._subscribers[1][ibar][ifoo][_blank]
+        self.assertEqual(len(reg), 1)
+        self.failUnless(reg[0] is _Factory)
+        self.assertEqual(comp._subscription_registrations,
+                         [((ibar,), ifoo, _blank, _Factory, _info)])
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, SubscriptionRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.assertEqual(event.object.name, _blank)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is _Factory)
 
-        c2 = Components('2', (c1, ))
-        self.assertTrue(c2.__bases__ == (c1, ))
+    def test_registerSubscriptionAdapter_wo_explicit_required(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import SubscriptionRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _info = _u('info')
+        _blank = _u('')
+        class _Factory(object):
+            __component_adapts__ = (ibar,)
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerSubscriptionAdapter(
+                    _Factory, provided=ifoo, info=_info)
+        reg = comp.adapters._subscribers[1][ibar][ifoo][_blank]
+        self.assertEqual(len(reg), 1)
+        self.failUnless(reg[0] is _Factory)
+        self.assertEqual(comp._subscription_registrations,
+                         [((ibar,), ifoo, _blank, _Factory, _info)])
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, SubscriptionRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.assertEqual(event.object.name, _blank)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is _Factory)
 
-        test_object1 = U1(1)
-        test_object2 = U1(2)
-        test_object3 = U12(1)
-        test_object4 = U12(3)
+    def test_registerSubscriptionAdapter_wo_event(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _blank = _u('')
+        _info = _u('info')
+        _to_reg = object()
+        def _factory(context):
+            return _to_reg
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerSubscriptionAdapter(_factory, (ibar,), ifoo,
+                                             info=_info, event=False)
+        self.assertEqual(len(_events), 0)
 
-        self.assertEqual(len(list(c1.registeredUtilities())), 0)
-        self.assertEqual(len(list(c2.registeredUtilities())), 0)
+    def test_registeredSubscriptionAdapters_empty(self):
+        comp = self._makeOne()
+        self.assertEqual(list(comp.registeredSubscriptionAdapters()), [])
 
-        c1.registerUtility(test_object1)
-        self.assertEqual(len(list(c1.registeredUtilities())), 1)
-        self.assertEqual(len(list(c2.registeredUtilities())), 0)
-        self.assertEqual(c1.queryUtility(I1), test_object1)
-        self.assertEqual(c2.queryUtility(I1), test_object1)
+    def test_registeredSubscriptionAdapters_notempty(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        from zope.interface.registry import SubscriptionRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IFoo')
+        _info = _u('info')
+        _blank = _u('')
+        class _Factory(object):
+            def __init__(self, context):
+                pass
+        comp = self._makeOne()
+        comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo, info=_info)
+        comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo, info=_info)
+        reg = list(comp.registeredSubscriptionAdapters())
+        self.assertEqual(len(reg), 2)
+        self.failUnless(isinstance(reg[0], SubscriptionRegistration))
+        self.failUnless(reg[0].registry is comp)
+        self.failUnless(reg[0].provided is ifoo)
+        self.assertEqual(reg[0].required, (ibar,))
+        self.assertEqual(reg[0].name, _blank)
+        self.failUnless(reg[0].info is _info)
+        self.failUnless(reg[0].factory is _Factory)
+        self.failUnless(isinstance(reg[1], SubscriptionRegistration))
+        self.failUnless(reg[1].registry is comp)
+        self.failUnless(reg[1].provided is ifoo)
+        self.assertEqual(reg[1].required, (ibar,))
+        self.assertEqual(reg[1].name, _blank)
+        self.failUnless(reg[1].info is _info)
+        self.failUnless(reg[1].factory is _Factory)
 
-        c1.registerUtility(test_object2)
-        self.assertEqual(len(list(c1.registeredUtilities())), 1)
-        self.assertEqual(len(list(c2.registeredUtilities())), 0)
-        self.assertEqual(c1.queryUtility(I1), test_object2)
-        self.assertEqual(c2.queryUtility(I1), test_object2)
+    def test_unregisterSubscriptionAdapter_w_nonblank_name(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        _nonblank = _u('nonblank')
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.unregisterSubscriptionAdapter,
+                          required=ifoo, provided=ibar, name=_nonblank)
 
+    def test_unregisterSubscriptionAdapter_neither_factory_nor_provided(self):
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.unregisterSubscriptionAdapter,
+                          factory=None, provided=None)
 
-        c3 = Components('3', (c1, ))
-        c4 = Components('4', (c2, c3))
-        self.assertEqual(c4.queryUtility(I1), test_object2)
-    
-        c1.registerUtility(test_object3, I2)
-        self.assertEqual(c4.queryUtility(I2), test_object3)
+    def test_unregisterSubscriptionAdapter_neither_factory_nor_required(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.unregisterSubscriptionAdapter,
+                          factory=None, provided=ifoo, required=None)
 
-        c3.registerUtility(test_object4, I2)
-        self.assertEqual(c4.queryUtility(I2), test_object4)
+    def test_unregisterSubscriptionAdapter_miss(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterSubscriptionAdapter(_Factory, (ibar,), ifoo)
+        self.failIf(unreg)
+        self.failIf(_events)
 
-        @adapter(I1)
-        def handle1(x):
-            self.assertEqual(x, test_object1)
+    def test_unregisterSubscriptionAdapter_hit_wo_factory(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import SubscriptionRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterSubscriptionAdapter(None, (ibar,), ifoo)
+        self.failUnless(unreg)
+        self.failIf(comp.adapters._subscribers)
+        self.failIf(comp._subscription_registrations)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, SubscriptionRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.assertEqual(event.object.name, '')
+        self.assertEqual(event.object.info, '')
+        self.failUnless(event.object.factory is None)
 
-        def handle(*objects):
-            self.assertEqual(objects, (test_object1,))
+    def test_unregisterSubscriptionAdapter_hit_w_factory(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import SubscriptionRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterSubscriptionAdapter(_Factory, (ibar,), ifoo)
+        self.failUnless(unreg)
+        self.failIf(comp.adapters._subscribers)
+        self.failIf(comp._subscription_registrations)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, SubscriptionRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.assertEqual(event.object.name, '')
+        self.assertEqual(event.object.info, '')
+        self.failUnless(event.object.factory is _Factory)
 
-        @adapter(I1)
-        def handle3(x):
-            self.assertEqual(x, test_object1)
+    def test_unregisterSubscriptionAdapter_wo_explicit_provided(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implementer
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import SubscriptionRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        @implementer(ifoo)
+        class _Factory(object):
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterSubscriptionAdapter(_Factory, (ibar,))
+        self.failUnless(unreg)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, SubscriptionRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.assertEqual(event.object.name, '')
+        self.assertEqual(event.object.info, '')
+        self.failUnless(event.object.factory is _Factory)
 
-        @adapter(I1)
-        def handle4(x):
-            self.assertEqual(x, test_object1)
+    def test_unregisterSubscriptionAdapter_wo_explicit_required(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import SubscriptionRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Factory(object):
+            __component_adapts__ = (ibar,)
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterSubscriptionAdapter(_Factory, provided=ifoo)
+        self.failUnless(unreg)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, SubscriptionRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.failUnless(event.object.provided is ifoo)
+        self.assertEqual(event.object.required, (ibar,))
+        self.assertEqual(event.object.name, '')
+        self.assertEqual(event.object.info, '')
+        self.failUnless(event.object.factory is _Factory)
 
-        c1.registerHandler(handle1, info=u'First handler')
-        c2.registerHandler(handle, required=[U])
-        c3.registerHandler(handle3)
-        c4.registerHandler(handle4)
+    def test_subscribers_empty(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implements
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        comp = self._makeOne()
+        class Bar(object):
+            implements(ibar)
+        bar = Bar()
+        self.assertEqual(list(comp.subscribers((bar,), ifoo)), [])
 
-        c4.handle(test_object1)
+    def test_subscribers_non_empty(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implements
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Factory(object):
+            __component_adapts__ = (ibar,)
+            def __init__(self, context):
+                self._context = context
+        class _Derived(_Factory):
+            pass
+        comp = self._makeOne()
+        comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo)
+        comp.registerSubscriptionAdapter(_Derived, (ibar,), ifoo)
+        class Bar(object):
+            implements(ibar)
+        bar = Bar()
+        subscribers = comp.subscribers((bar,), ifoo)
+        def _klassname(x):
+            return x.__class__.__name__
+        subscribers = sorted(subscribers, key=_klassname)
+        self.assertEqual(len(subscribers), 2)
+        self.failUnless(isinstance(subscribers[0], _Derived))
+        self.failUnless(isinstance(subscribers[1], _Factory))
 
-class TestHandler(unittest.TestCase):
+    def test_registerHandler_w_nonblank_name(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _nonblank = _u('nonblank')
+        comp = self._makeOne()
+        def _factory(context):
+            pass
+        self.assertRaises(TypeError, comp.registerHandler, _factory,
+                          required=ifoo, name=_nonblank)
 
-    def setUp(self):
-        self.components = Components('comps')
+    def test_registerHandler_w_explicit_required(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import HandlerRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _blank = _u('')
+        _info = _u('info')
+        _to_reg = object()
+        def _factory(context):
+            return _to_reg
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerHandler(_factory, (ifoo,), info=_info)
+        reg = comp.adapters._subscribers[1][ifoo][None][_blank]
+        self.assertEqual(len(reg), 1)
+        self.failUnless(reg[0] is _factory)
+        self.assertEqual(comp._handler_registrations,
+                         [((ifoo,), _blank, _factory, _info)])
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, HandlerRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.assertEqual(event.object.required, (ifoo,))
+        self.assertEqual(event.object.name, _blank)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is _factory)
 
-    def test_register_handler(self):
-        test_object1 = U1(1)
-        test_object2 = U12(2)
+    def test_registerHandler_wo_explicit_required(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Registered
+        from zope.interface.registry import HandlerRegistration
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _info = _u('info')
+        _blank = _u('')
+        class _Factory(object):
+            __component_adapts__ = (ifoo,)
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            comp.registerHandler(_Factory, info=_info)
+        reg = comp.adapters._subscribers[1][ifoo][None][_blank]
+        self.assertEqual(len(reg), 1)
+        self.failUnless(reg[0] is _Factory)
+        self.assertEqual(comp._handler_registrations,
+                         [((ifoo,), _blank, _Factory, _info)])
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Registered))
+        self.failUnless(isinstance(event.object, HandlerRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.assertEqual(event.object.required, (ifoo,))
+        self.assertEqual(event.object.name, _blank)
+        self.failUnless(event.object.info is _info)
+        self.failUnless(event.object.factory is _Factory)
 
-        @adapter(I1)
-        def handle1(x):
-            self.assertEqual(x, test_object1)
+    def test_registeredHandlers_empty(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        comp = self._makeOne()
+        self.failIf(list(comp.registeredHandlers()))
 
-        self.components.registerHandler(handle1, info=u'First handler')
-        self.components.handle(test_object1)
+    def test_registeredHandlers_non_empty(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import HandlerRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        def _factory1(context):
+            pass
+        def _factory2(context):
+            pass
+        comp = self._makeOne()
+        comp.registerHandler(_factory1, (ifoo,))
+        comp.registerHandler(_factory2, (ifoo,))
+        def _factory_name(x):
+            return x.factory.func_code.co_name
+        subscribers = sorted(comp.registeredHandlers(), key=_factory_name)
+        self.assertEqual(len(subscribers), 2)
+        self.failUnless(isinstance(subscribers[0], HandlerRegistration))
+        self.assertEqual(subscribers[0].required, (ifoo,))
+        self.assertEqual(subscribers[0].name, '')
+        self.assertEqual(subscribers[0].factory, _factory1)
+        self.assertEqual(subscribers[0].info, '')
+        self.failUnless(isinstance(subscribers[1], HandlerRegistration))
+        self.assertEqual(subscribers[1].required, (ifoo,))
+        self.assertEqual(subscribers[1].name, '')
+        self.assertEqual(subscribers[1].factory, _factory2)
+        self.assertEqual(subscribers[1].info, '')
+ 
+    def test_unregisterHandler_w_nonblank_name(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _nonblank = _u('nonblank')
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.unregisterHandler,
+                          required=(ifoo,), name=_nonblank)
 
-        @adapter(I1, I2)
-        def handle12(x, y):
-            self.assertEqual(x, test_object1)
-            self.assertEqual(y, test_object2)
+    def test_unregisterHandler_neither_factory_nor_required(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        self.assertRaises(TypeError, comp.unregisterHandler)
 
-        self.components.registerHandler(handle12)
-        self.components.handle(test_object1, test_object2)
+    def test_unregisterHandler_miss(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        unreg = comp.unregisterHandler(required=(ifoo,))
+        self.failIf(unreg)
 
-    def test_register_noncompliant_handler(self):
-        handle_calls = []
-        def handle(*objects):
-            handle_calls.append(objects)
+    def test_unregisterHandler_hit_w_factory_and_explicit_provided(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import HandlerRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        _to_reg = object()
+        def _factory(context):
+            return _to_reg
+        comp = self._makeOne()
+        comp.registerHandler(_factory, (ifoo,))
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterHandler(_factory, (ifoo,))
+        self.failUnless(unreg)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, HandlerRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.assertEqual(event.object.required, (ifoo,))
+        self.assertEqual(event.object.name, '')
+        self.failUnless(event.object.factory is _factory)
 
-        self.assertRaises(TypeError, self.components.registerHandler, handle)
-        self.components.registerHandler(
-            handle, required=[I1], info=u'a comment')
-        self.components.registerHandler(
-            handle, required=[U], info=u'handle a class')
+    def test_unregisterHandler_hit_w_only_explicit_provided(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import HandlerRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        _to_reg = object()
+        def _factory(context):
+            return _to_reg
+        comp = self._makeOne()
+        comp.registerHandler(_factory, (ifoo,))
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterHandler(required=(ifoo,))
+        self.failUnless(unreg)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, HandlerRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.assertEqual(event.object.required, (ifoo,))
+        self.assertEqual(event.object.name, '')
+        self.failUnless(event.object.factory is None)
 
-        test_object = U1(1)
-        self.components.handle(test_object)
-        self.assertEqual(len(handle_calls), 2)
-        map(self.assertEqual, handle_calls, [(test_object,), (test_object,)])
+    def test_unregisterHandler_wo_explicit_required(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.interfaces import Unregistered
+        from zope.interface.registry import HandlerRegistration
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        class _Factory(object):
+            __component_adapts__ = (ifoo,)
+            def __init__(self, context):
+                self._context = context
+        comp = self._makeOne()
+        comp.registerHandler(_Factory)
+        _monkey, _events = self._wrapEvents()
+        with _monkey:
+            unreg = comp.unregisterHandler(_Factory)
+        self.failUnless(unreg)
+        self.assertEqual(len(_events), 1)
+        args, kw = _events[0]
+        event, = args
+        self.assertEqual(kw, {})
+        self.failUnless(isinstance(event, Unregistered))
+        self.failUnless(isinstance(event.object, HandlerRegistration))
+        self.failUnless(event.object.registry is comp)
+        self.assertEqual(event.object.required, (ifoo,))
+        self.assertEqual(event.object.name, '')
+        self.assertEqual(event.object.info, '')
+        self.failUnless(event.object.factory is _Factory)
 
-    def test_list_handlers(self):
-        test_object1 = U1(1)
-        test_object2 = U12(2)
+    def test_handle_empty(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implements
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        comp = self._makeOne()
+        class Bar(object):
+            implements(ifoo)
+        bar = Bar()
+        comp.handle((bar,)) # doesn't raise
 
-        @adapter(I1)
-        def handle1(x):
-            self.assertEqual(x, test_object1)
+    def test_handle_non_empty(self):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.declarations import implements
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        _called_1 = []
+        def _factory_1(context):
+                _called_1.append(context)
+        _called_2 = []
+        def _factory_2(context):
+                _called_2.append(context)
+        comp = self._makeOne()
+        comp.registerHandler(_factory_1, (ifoo,))
+        comp.registerHandler(_factory_2, (ifoo,))
+        class Bar(object):
+            implements(ifoo)
+        bar = Bar()
+        comp.handle(bar)
+        self.assertEqual(_called_1, [bar])
+        self.assertEqual(_called_2, [bar])
 
-        @adapter(I1, I2)
-        def handle12(x, y):
-            self.assertEqual(x, test_object1)
-            self.assertEqual(y, test_object2)
 
-        handle_calls = []
-        def handle(*objects):
-            handle_calls.append(objects)
+# Test _getUtilityProvided, _getAdapterProvided, _getAdapterRequired via their
+# callers (Component.registerUtility, Component.registerAdapter).
 
-        self.components.registerHandler(handle1, info=u'First handler')
-        self.components.registerHandler(handle12)
-        self.components.registerHandler(
-            handle, required=[I1], info=u'a comment')
-        self.components.registerHandler(
-            handle, required=[U], info=u'handle a class')
 
-        handlers = list(self.components.registeredHandlers())
-        handlers_required = map(lambda x: getattr(x, 'required'), handlers)
-        handlers_handler = map(lambda x: getattr(x, 'handler'), handlers)
-        handlers_info = map(lambda x: getattr(x, 'info'), handlers)
+class UtilityRegistrationTests(unittest.TestCase):
 
-        self.assertEqual(len(handlers), 4)
-        self.assertEqual(handlers_required,
-                         [(I1,), (I1, I2), (I1,), (implementedBy(U),)])
-        self.assertEqual(handlers_handler,
-                         [handle1, handle12, handle, handle])
-        self.assertEqual(
-            handlers_info,
-            [u'First handler', u'', u'a comment', u'handle a class'])
+    def _getTargetClass(self):
+        from zope.interface.registry import UtilityRegistration
+        return UtilityRegistration
 
-    def test_unregister_handler(self):
-        test_object1 = U1(1)
-        test_object2 = U12(2)
+    def _makeOne(self, component=None, factory=None):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        class _Registry(object):
+            def __repr__(self):
+                return '_REGISTRY'
+        registry = _Registry()
+        name = _u('name')
+        doc = 'DOCSTRING'
+        klass = self._getTargetClass()
+        return (klass(registry, ifoo, name, component, doc, factory),
+                registry,
+                name,
+               )
 
-        @adapter(I1)
-        def handle1(x):
-            self.assertEqual(x, test_object1)
+    def test_class_conforms_to_IUtilityRegistration(self):
+        from zope.interface.verify import verifyClass
+        from zope.interface.interfaces import IUtilityRegistration
+        verifyClass(IUtilityRegistration, self._getTargetClass())
 
-        @adapter(I1, I2)
-        def handle12(x, y):
-            self.assertEqual(x, test_object1)
-            self.assertEqual(y, test_object2)
+    def test_instance_conforms_to_IUtilityRegistration(self):
+        from zope.interface.verify import verifyObject
+        from zope.interface.interfaces import IUtilityRegistration
+        ur, _, _ =  self._makeOne()
+        verifyObject(IUtilityRegistration, ur)
 
-        handle_calls = []
-        def handle(*objects):
-            handle_calls.append(objects)
+    def test___repr__(self):
+        class _Component(object):
+            __name__ = 'TEST'
+        _component = _Component()
+        ur, _registry, _name = self._makeOne(_component)
+        self.assertEqual(repr(ur),
+            "UtilityRegistration(_REGISTRY, IFoo, %r, TEST, None, 'DOCSTRING')"
+                            % (_name))
 
-        self.components.registerHandler(handle1, info=u'First handler')
-        self.components.registerHandler(handle12)
-        self.components.registerHandler(
-            handle, required=[I1], info=u'a comment')
-        self.components.registerHandler(
-            handle, required=[U], info=u'handle a class')
+    def test___repr___provided_wo_name(self):
+        class _Component(object):
+            def __repr__(self):
+                return 'TEST'
+        _component = _Component()
+        ur, _registry, _name = self._makeOne(_component)
+        ur.provided = object()
+        self.assertEqual(repr(ur),
+            "UtilityRegistration(_REGISTRY, None, %r, TEST, None, 'DOCSTRING')"
+                            % (_name))
 
-        self.assertEqual(len(list(self.components.registeredHandlers())), 4)
-        self.assertTrue(self.components.unregisterHandler(handle12))
-        self.assertEqual(len(list(self.components.registeredHandlers())), 3)
-        self.assertFalse(self.components.unregisterHandler(handle12))
-        self.assertEqual(len(list(self.components.registeredHandlers())), 3)
-        self.assertRaises(TypeError, self.components.unregisterHandler)
-        self.assertEqual(len(list(self.components.registeredHandlers())), 3)
-        self.assertTrue(
-            self.components.unregisterHandler(handle, required=[I1]))
-        self.assertEqual(len(list(self.components.registeredHandlers())), 2)
-        self.assertTrue(self.components.unregisterHandler(handle, required=[U]))
-        self.assertEqual(len(list(self.components.registeredHandlers())), 1)
+    def test___repr___component_wo_name(self):
+        class _Component(object):
+            def __repr__(self):
+                return 'TEST'
+        _component = _Component()
+        ur, _registry, _name = self._makeOne(_component)
+        ur.provided = object()
+        self.assertEqual(repr(ur),
+            "UtilityRegistration(_REGISTRY, None, %r, TEST, None, 'DOCSTRING')"
+                            % (_name))
 
-    def test_multi_handler_unregistration(self):
-        """
-        There was a bug where multiple handlers for the same required
-        specification would all be removed when one of them was
-        unregistered.
+    def test___hash__(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        self.assertEqual(hash(ur), id(ur))
 
-        """
-        from zope import interface
+    def test___eq___identity(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        self.failUnless(ur == ur)
 
-        calls = []
+    def test___eq___hit(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component)
+        self.failUnless(ur == ur2)
 
-        class I(interface.Interface):
-            pass
+    def test___eq___miss(self):
+        _component = object()
+        _component2 = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component2)
+        self.failIf(ur == ur2)
 
-        def factory1(event):
-            calls.append(2)
+    def test___ne___identity(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        self.failIf(ur != ur)
 
-        def factory2(event):
-            calls.append(3)
+    def test___ne___hit(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component)
+        self.failIf(ur != ur2)
 
-        class Event(object):
-            interface.implements(I)
+    def test___ne___miss(self):
+        _component = object()
+        _component2 = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component2)
+        self.failUnless(ur != ur2)
 
-        self.components.registerHandler(factory1, [I,])
-        self.components.registerHandler(factory2, [I,])
-        self.components.handle(Event())
-        self.assertEqual(sum(calls), 5)
-        self.assertTrue(self.components.unregisterHandler(factory1, [I,]))
-        calls = []
-        self.components.handle(Event())
-        self.assertEqual(sum(calls), 3)
+    def test___lt___identity(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        self.failIf(ur < ur)
 
-class TestSubscriber(unittest.TestCase):
+    def test___lt___hit(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component)
+        self.failIf(ur < ur2)
 
-    def setUp(self):
-        self.components = Components('comps')
+    def test___lt___miss(self):
+        _component = object()
+        _component2 = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component2)
+        ur2.name = _name + '2'
+        self.failUnless(ur < ur2)
 
-    def test_register_subscriber(self):
-        self.components.registerSubscriptionAdapter(A1_2)
-        self.components.registerSubscriptionAdapter(A1_12, provided=IA2)
-        self.components.registerSubscriptionAdapter(
-            A, [I1], IA2, info='a sample comment')
-        subscribers = self.components.subscribers((U1(1),), IA2)
-        self.assertEqual(len(subscribers), 3)
-        self.assertEqual(repr(subscribers[0]), 'A1_2(U1(1))')
-        self.assertEqual(repr(subscribers[1]), 'A1_12(U1(1))')
-        self.assertEqual(repr(subscribers[2]), 'A(U1(1),)') 
+    def test___le___identity(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        self.failUnless(ur <= ur)
 
-    def test_register_noncompliant_subscriber(self):
-        self.assertRaises(TypeError,
-                          self.components.registerSubscriptionAdapter, A1_12)
-        self.assertRaises(TypeError,
-                          self.components.registerSubscriptionAdapter, A)
-        self.assertRaises(
-            TypeError,
-            self.components.registerSubscriptionAdapter, A, required=[IA1])
+    def test___le___hit(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component)
+        self.failUnless(ur <= ur2)
 
-    def test_register_named_subscriber(self):
-        self.components.registerSubscriptionAdapter(
-            A, [I1], IA2, u'', u'a sample comment')
-        self.assertRaises(TypeError,
-                          self.components.registerSubscriptionAdapter, 
-                          A, [I1], IA2, u'oops', u'a sample comment')
-        subscribers = self.components.subscribers((U1(1),), IA2)
-        self.assertEqual(len(subscribers), 1)
-        self.assertEqual(repr(subscribers[0]), 'A(U1(1),)')
+    def test___le___miss(self):
+        _component = object()
+        _component2 = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component2)
+        ur2.name = _name + '2'
+        self.failUnless(ur <= ur2)
 
-    def test_register_no_factory(self):
-        self.components.registerSubscriptionAdapter(noop, [I1], IA2)
-        subscribers = self.components.subscribers((U1(1),), IA2)
-        self.assertEqual(len(subscribers), 0)
+    def test___gt___identity(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        self.failIf(ur > ur)
 
-    def test_sorting_registered_subscription_adapters(self):
-        self.components.registerSubscriptionAdapter(A1_2)
-        self.components.registerSubscriptionAdapter(A1_12, provided=IA2)
-        self.components.registerSubscriptionAdapter(
-            A, [I1], IA2, info=u'a sample comment')
-        self.components.registerSubscriptionAdapter(
-            A, [I1], IA2, u'', u'a sample comment')
-        self.components.registerSubscriptionAdapter(noop, [I1], IA2)
+    def test___gt___hit(self):
+        _component = object()
+        _component2 = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component2)
+        ur2.name = _name + '2'
+        self.failUnless(ur2 > ur)
 
-        sorted_subscribers = sorted(
-            self.components.registeredSubscriptionAdapters())
-        sorted_subscribers_name = map(lambda x: getattr(x, 'name'),
-                                      sorted_subscribers)
-        sorted_subscribers_provided = map(lambda x: getattr(x, 'provided'),
-                                          sorted_subscribers) 
-        sorted_subscribers_required = map(lambda x: getattr(x, 'required'),
-                                          sorted_subscribers)
-        sorted_subscribers_factory = map(lambda x: getattr(x, 'factory'),
-                                         sorted_subscribers)
-        sorted_subscribers_info = map(lambda x: getattr(x, 'info'),
-                                      sorted_subscribers)
+    def test___gt___miss(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component)
+        self.failIf(ur2 > ur)
 
-        self.assertEqual(len(sorted_subscribers), 5)
-        self.assertEqual(sorted_subscribers_name, [u'', u'', u'', u'', u''])
-        self.assertEqual(sorted_subscribers_provided,
-                         [IA2, IA2, IA2, IA2, IA2])
-        self.assertEqual(sorted_subscribers_required,
-                         [(I1,), (I1,), (I1,),(I1,), (I1,)])
-        self.assertEqual(sorted_subscribers_factory,
-                         [A, A, A1_12, A1_2, noop])
-        self.assertEqual(
-            sorted_subscribers_info,
-            [u'a sample comment', u'a sample comment', u'', u'', u''])
+    def test___ge___identity(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        self.failUnless(ur >= ur)
 
-    def test_unregister(self):
-        self.components.registerSubscriptionAdapter(A1_2)
-        self.assertEqual(len(self.components.subscribers((U1(1),), IA2)), 1)
-        self.assertTrue(self.components.unregisterSubscriptionAdapter(A1_2))
-        self.assertEqual(len(self.components.subscribers((U1(1),), IA2)), 0)
+    def test___ge___miss(self):
+        _component = object()
+        _component2 = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component2)
+        ur2.name = _name + '2'
+        self.failIf(ur >= ur2)
 
-    def test_unregister_multiple(self):
-        self.components.registerSubscriptionAdapter(A1_2)
-        self.components.registerSubscriptionAdapter(A1_12, provided=IA2)
-        self.components.registerSubscriptionAdapter(
-            A, [I1], IA2, info=u'a sample comment')
-        self.components.registerSubscriptionAdapter(
-            A, [I1], IA2, u'', u'a sample comment')
-        self.components.registerSubscriptionAdapter(noop, [I1], IA2)
-        self.assertEqual(len(self.components.subscribers((U1(1),), IA2)), 4)
-        self.assertEqual(
-            len(list(self.components.registeredSubscriptionAdapters())), 5)
+    def test___ge___hit(self):
+        _component = object()
+        ur, _registry, _name = self._makeOne(_component)
+        ur2, _, _ = self._makeOne(_component)
+        ur2.name = _name + '2'
+        self.failUnless(ur2 >= ur)
 
-        self.assertTrue(
-            self.components.unregisterSubscriptionAdapter(A, [I1], IA2))
-        self.assertEqual(len(self.components.subscribers((U1(1),), IA2)), 2)
-        self.assertEqual(
-            len(list(self.components.registeredSubscriptionAdapters())), 3)
 
-    def test_unregister_no_factory(self):
-        self.components.registerSubscriptionAdapter(A1_2)
-        self.components.registerSubscriptionAdapter(A1_12, provided=IA2)
-        self.components.registerSubscriptionAdapter(noop, [I1], IA2)
-        self.assertEqual(len(self.components.subscribers((U1(1),), IA2)), 2)
-        self.assertEqual(
-            len(list(self.components.registeredSubscriptionAdapters())), 3)
+class AdapterRegistrationTests(unittest.TestCase):
 
-        self.assertRaises(
-            TypeError,
-            self.components.unregisterSubscriptionAdapter, required=[I1])
-        self.assertRaises(
-            TypeError,
-            self.components.unregisterSubscriptionAdapter, provided=IA2)
-        self.assertTrue(
-            self.components.unregisterSubscriptionAdapter(
-                required=[I1], provided=IA2))
-        self.assertEqual(len(self.components.subscribers((U1(1),), IA2)), 0)
-        self.assertEqual(
-            len(list(self.components.registeredSubscriptionAdapters())), 0)
+    def _getTargetClass(self):
+        from zope.interface.registry import AdapterRegistration
+        return AdapterRegistration
 
-    def test_unregister_noncompliant_subscriber(self):
-        self.assertRaises(
-            TypeError,
-            self.components.unregisterSubscriptionAdapter, A1_12)
-        self.assertRaises(
-            TypeError,
-            self.components.unregisterSubscriptionAdapter, A)
-        self.assertRaises(
-            TypeError,
-            self.components.unregisterSubscriptionAdapter, A, required=[IA1])
+    def _makeOne(self, component=None):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Registry(object):
+            def __repr__(self):
+                return '_REGISTRY'
+        registry = _Registry()
+        name = _u('name')
+        doc = 'DOCSTRING'
+        klass = self._getTargetClass()
+        return (klass(registry, (ibar,), ifoo, name, component, doc),
+                registry,
+                name,
+               )
 
-    def test_unregister_nonexistent_subscriber(self):
-        self.assertFalse(
-            self.components.unregisterSubscriptionAdapter(required=[I1],
-                                                          provided=IA2))
+    def test_class_conforms_to_IAdapterRegistration(self):
+        from zope.interface.verify import verifyClass
+        from zope.interface.interfaces import IAdapterRegistration
+        verifyClass(IAdapterRegistration, self._getTargetClass())
 
-class TestUtility(unittest.TestCase):
+    def test_instance_conforms_to_IAdapterRegistration(self):
+        from zope.interface.verify import verifyObject
+        from zope.interface.interfaces import IAdapterRegistration
+        ar, _, _ =  self._makeOne()
+        verifyObject(IAdapterRegistration, ar)
 
-    def setUp(self):
-        self.components = Components('comps')
+    def test___repr__(self):
+        class _Component(object):
+            __name__ = 'TEST'
+        _component = _Component()
+        ar, _registry, _name = self._makeOne(_component)
+        self.assertEqual(repr(ar),
+            ("AdapterRegistration(_REGISTRY, [IBar], IFoo, %r, TEST, "
+           + "'DOCSTRING')") % (_name))
 
-    def test_register_utility(self):
-        test_object = U1(1)
-        self.components.registerUtility(test_object)
-        self.assertEqual(self.components.getUtility(I1), test_object)
+    def test___repr___provided_wo_name(self):
+        class _Component(object):
+            def __repr__(self):
+                return 'TEST'
+        _component = _Component()
+        ar, _registry, _name = self._makeOne(_component)
+        ar.provided = object()
+        self.assertEqual(repr(ar),
+            ("AdapterRegistration(_REGISTRY, [IBar], None, %r, TEST, "
+           + "'DOCSTRING')") % (_name))
 
-    def test_register_utility_with_factory(self):
-        test_object = U1(1)
-        def factory():
-           return test_object
-        self.components.registerUtility(factory=factory)
-        self.assertEqual(self.components.getUtility(I1), test_object)
-        self.assertTrue(self.components.unregisterUtility(factory=factory))
+    def test___repr___component_wo_name(self):
+        class _Component(object):
+            def __repr__(self):
+                return 'TEST'
+        _component = _Component()
+        ar, _registry, _name = self._makeOne(_component)
+        ar.provided = object()
+        self.assertEqual(repr(ar),
+            ("AdapterRegistration(_REGISTRY, [IBar], None, %r, TEST, "
+           + "'DOCSTRING')") % (_name))
 
-    def test_register_utility_with_component_and_factory(self):
-        def factory():
-            return U1(1)
-        self.assertRaises(
-            TypeError,
-            self.components.registerUtility, U1(1), factory=factory)
+    def test___hash__(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        self.assertEqual(hash(ar), id(ar))
 
-    def test_unregister_utility_with_and_without_component_and_factory(self):
-        def factory():
-            return U1(1)
-        self.assertRaises(
-            TypeError,
-            self.components.unregisterUtility, U1(1), factory=factory)
-        self.assertRaises(TypeError, self.components.unregisterUtility)
+    def test___eq___identity(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        self.failUnless(ar == ar)
 
-    def test_register_utility_with_no_interfaces(self):
-        self.assertRaises(TypeError, self.components.registerUtility, A)
+    def test___eq___hit(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component)
+        self.failUnless(ar == ar2)
 
-    def test_register_utility_with_two_interfaces(self):
-        self.assertRaises(TypeError, self.components.registerUtility, U12(1))
+    def test___eq___miss(self):
+        _component = object()
+        _component2 = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component2)
+        self.failIf(ar == ar2)
 
-    def test_register_utility_with_arguments(self):
-        test_object1 = U12(1)
-        test_object2 = U12(2)
-        self.components.registerUtility(test_object1, I2)
-        self.components.registerUtility(test_object2, I2, 'name')
-        self.assertEqual(self.components.getUtility(I2), test_object1)
-        self.assertEqual(self.components.getUtility(I2, 'name'), test_object2)
+    def test___ne___identity(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        self.failIf(ar != ar)
 
-    def test_get_none_existing_utility(self):
-        from zope.interface.interfaces import ComponentLookupError
-        self.assertRaises(ComponentLookupError, self.components.getUtility, I3)
+    def test___ne___miss(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component)
+        self.failIf(ar != ar2)
 
-    def test_query_none_existing_utility(self):
-        self.assertTrue(self.components.queryUtility(I3) is None)
-        self.assertEqual(self.components.queryUtility(I3, default=42), 42)
+    def test___ne___hit_component(self):
+        _component = object()
+        _component2 = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component2)
+        self.failUnless(ar != ar2)
 
-    def test_registered_utilities_and_sorting(self):
-        test_object1 = U1(1)
-        test_object2 = U12(2)
-        test_object3 = U12(3)
-        self.components.registerUtility(test_object1)
-        self.components.registerUtility(test_object3, I2, u'name')
-        self.components.registerUtility(test_object2, I2)
+    def test___ne___hit_provided(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ibaz = IFoo('IBaz')
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component)
+        ar2.provided = ibaz
+        self.failUnless(ar != ar2)
 
-        sorted_utilities = sorted(self.components.registeredUtilities())
-        sorted_utilities_name = map(lambda x: getattr(x, 'name'),
-                                    sorted_utilities)
-        sorted_utilities_component = map(lambda x: getattr(x, 'component'),
-                                         sorted_utilities)
-        sorted_utilities_provided = map(lambda x: getattr(x, 'provided'),
-                                        sorted_utilities)
+    def test___ne___hit_required(self):
+        from zope.interface.declarations import InterfaceClass
+        class IFoo(InterfaceClass):
+            pass
+        ibaz = IFoo('IBaz')
+        _component = object()
+        _component2 = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component2)
+        ar2.required = (ibaz,)
+        self.failUnless(ar != ar2)
 
-        self.assertEqual(len(sorted_utilities), 3)
-        self.assertEqual(sorted_utilities_name, [u'', u'', u'name'])
-        self.assertEqual(
-            sorted_utilities_component,
-            [test_object1, test_object2, test_object3])
-        self.assertEqual(sorted_utilities_provided, [I1, I2, I2])
+    def test___lt___identity(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        self.failIf(ar < ar)
 
-    def test_duplicate_utility(self):
-        test_object1 = U1(1)
-        test_object2 = U12(2)
-        test_object3 = U12(3)
-        test_object4 = U1(4)
-        self.components.registerUtility(test_object1)
-        self.components.registerUtility(test_object2, I2)
-        self.components.registerUtility(test_object3, I2, u'name')
-        self.assertEqual(self.components.getUtility(I1), test_object1)
+    def test___lt___hit(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component)
+        self.failIf(ar < ar2)
 
-        self.components.registerUtility(test_object4, info=u'use 4 now')
-        self.assertEqual(self.components.getUtility(I1), test_object4)
+    def test___lt___miss(self):
+        _component = object()
+        _component2 = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component2)
+        ar2.name = _name + '2'
+        self.failUnless(ar < ar2)
 
-    def test_unregister_utility(self):
-        test_object = U1(1)
-        self.components.registerUtility(test_object)
-        self.assertEqual(self.components.getUtility(I1), test_object)
-        self.assertTrue(self.components.unregisterUtility(provided=I1))
-        self.assertFalse(self.components.unregisterUtility(provided=I1))
+    def test___le___identity(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        self.failUnless(ar <= ar)
 
-    def test_unregister_utility_extended(self):
-        test_object = U1(1)
-        self.components.registerUtility(test_object)
-        self.assertFalse(self.components.unregisterUtility(U1(1)))
-        self.assertEqual(self.components.queryUtility(I1), test_object)
-        self.assertTrue(self.components.unregisterUtility(test_object))
-        self.assertTrue(self.components.queryUtility(I1) is None)
+    def test___le___hit(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component)
+        self.failUnless(ar <= ar2)
 
-    def test_get_utilities_for(self):
-        test_object1 = U1(1)
-        test_object2 = U12(2)
-        test_object3 = U12(3)
-        self.components.registerUtility(test_object1)
-        self.components.registerUtility(test_object2, I2)
-        self.components.registerUtility(test_object3, I2, u'name')
+    def test___le___miss(self):
+        _component = object()
+        _component2 = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component2)
+        ar2.name = _name + '2'
+        self.failUnless(ar <= ar2)
 
-        sorted_utilities = sorted(self.components.getUtilitiesFor(I2))
-        self.assertEqual(len(sorted_utilities), 2)
-        self.assertEqual(sorted_utilities[0], (u'', test_object2))
-        self.assertEqual(sorted_utilities[1], (u'name', test_object3))
+    def test___gt___identity(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        self.failIf(ar > ar)
 
-    def test_get_all_utilities_registered_for(self):
-        test_object1 = U1(1)
-        test_object2 = U12(2)
-        test_object3 = U12(3)
-        test_object4 = U('ext')
-        self.components.registerUtility(test_object1)
-        self.components.registerUtility(test_object2, I2)
-        self.components.registerUtility(test_object3, I2, u'name')
-        self.components.registerUtility(test_object4, I2e)
+    def test___gt___hit(self):
+        _component = object()
+        _component2 = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component2)
+        ar2.name = _name + '2'
+        self.failUnless(ar2 > ar)
 
-        sorted_utilities = sorted(self.components.getUtilitiesFor(I2))
-        self.assertEqual(len(sorted_utilities), 2)
-        self.assertEqual(sorted_utilities[0], (u'', test_object2))
-        self.assertEqual(sorted_utilities[1], (u'name', test_object3))
+    def test___gt___miss(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component)
+        self.failIf(ar2 > ar)
 
-        all_utilities = self.components.getAllUtilitiesRegisteredFor(I2)
-        self.assertEqual(len(all_utilities), 3)
-        self.assertTrue(test_object2 in all_utilities)
-        self.assertTrue(test_object3 in all_utilities)
-        self.assertTrue(test_object4 in all_utilities)
+    def test___ge___identity(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        self.failUnless(ar >= ar)
 
-        self.assertTrue(self.components.unregisterUtility(test_object4, I2e))
-        self.assertEqual(self.components.getAllUtilitiesRegisteredFor(I2e), [])
+    def test___ge___miss(self):
+        _component = object()
+        _component2 = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component2)
+        ar2.name = _name + '2'
+        self.failIf(ar >= ar2)
 
-    def test_utility_events(self):
-        from zope.event import subscribers
-        old_subscribers = subscribers[:]
-        subscribers[:] = []
+    def test___ge___hit(self):
+        _component = object()
+        ar, _registry, _name = self._makeOne(_component)
+        ar2, _, _ = self._makeOne(_component)
+        ar2.name = _name + '2'
+        self.failUnless(ar2 >= ar)
 
-        test_object = U1(1)
-        def log_event(event):
-            self.assertEqual(event.object.component, test_object)
-        subscribers.append(log_event)
-        self.components.registerUtility(test_object)
 
-        subscribers[:] = old_subscribers
+class SubscriptionRegistrationTests(unittest.TestCase):
 
-    def test_dont_leak_utility_registrations_in__subscribers(self):
-        """
-        We've observed utilities getting left in _subscribers when they
-        get unregistered.
+    def _getTargetClass(self):
+        from zope.interface.registry import SubscriptionRegistration
+        return SubscriptionRegistration
 
-        """
-        class C:
-            def __init__(self, name):
-                self.name = name
+    def _makeOne(self, component=None):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        ibar = IFoo('IBar')
+        class _Registry(object):
             def __repr__(self):
-                return "C(%s)" % self.name
+                return '_REGISTRY'
+        registry = _Registry()
+        name = _u('name')
+        doc = 'DOCSTRING'
+        klass = self._getTargetClass()
+        return (klass(registry, (ibar,), ifoo, name, component, doc),
+                registry,
+                name,
+               )
 
-        c1 = C(1)
-        c2 = C(2)
+    def test_class_conforms_to_ISubscriptionAdapterRegistration(self):
+        from zope.interface.verify import verifyClass
+        from zope.interface.interfaces import ISubscriptionAdapterRegistration
+        verifyClass(ISubscriptionAdapterRegistration, self._getTargetClass())
 
-        self.components.registerUtility(c1, I1)
-        self.components.registerUtility(c1, I1)
-        utilities = list(self.components.getAllUtilitiesRegisteredFor(I1))
-        self.assertEqual(len(utilities), 1)
-        self.assertEqual(utilities[0], c1)
+    def test_instance_conforms_to_ISubscriptionAdapterRegistration(self):
+        from zope.interface.verify import verifyObject
+        from zope.interface.interfaces import ISubscriptionAdapterRegistration
+        sar, _, _ =  self._makeOne()
+        verifyObject(ISubscriptionAdapterRegistration, sar)
 
-        self.assertTrue(self.components.unregisterUtility(provided=I1))
-        utilities = list(self.components.getAllUtilitiesRegisteredFor(I1))
-        self.assertEqual(len(utilities), 0)
 
-        self.components.registerUtility(c1, I1)
-        self.components.registerUtility(c2, I1)
+class HandlerRegistrationTests(unittest.TestCase):
 
-        utilities = list(self.components.getAllUtilitiesRegisteredFor(I1))
-        self.assertEqual(len(utilities), 1)
-        self.assertEqual(utilities[0], c2)
+    def _getTargetClass(self):
+        from zope.interface.registry import HandlerRegistration
+        return HandlerRegistration
 
+    def _makeOne(self, component=None):
+        from zope.interface.declarations import InterfaceClass
+        from zope.interface.registry import _u
+        class IFoo(InterfaceClass):
+            pass
+        ifoo = IFoo('IFoo')
+        class _Registry(object):
+            def __repr__(self):
+                return '_REGISTRY'
+        registry = _Registry()
+        name = _u('name')
+        doc = 'DOCSTRING'
+        klass = self._getTargetClass()
+        return (klass(registry, (ifoo,), name, component, doc),
+                registry,
+                name,
+               )
 
-class TestExtending(unittest.TestCase):
+    def test_class_conforms_to_IHandlerRegistration(self):
+        from zope.interface.verify import verifyClass
+        from zope.interface.interfaces import IHandlerRegistration
+        verifyClass(IHandlerRegistration, self._getTargetClass())
 
-    def test_extendning(self):
-        c1 = Components('1')
-        self.assertEqual(c1.__bases__, ())
+    def test_instance_conforms_to_IHandlerRegistration(self):
+        from zope.interface.verify import verifyObject
+        from zope.interface.interfaces import IHandlerRegistration
+        hr, _, _ =  self._makeOne()
+        verifyObject(IHandlerRegistration, hr)
 
-        c2 = Components('2', (c1, ))
-        self.assertTrue(c2.__bases__ == (c1, ))
+    def test_properties(self):
+        def _factory(context):
+            pass
+        hr, _, _ =  self._makeOne(_factory)
+        self.failUnless(hr.handler is _factory)
+        self.failUnless(hr.factory is hr.handler)
+        self.failUnless(hr.provided is None)
 
-        test_object1 = U1(1)
-        test_object2 = U1(2)
-        test_object3 = U12(1)
-        test_object4 = U12(3)
+    def test___repr___factory_w_name(self):
+        class _Factory(object):
+            __name__ = 'TEST'
+        hr, _registry, _name =  self._makeOne(_Factory())
+        self.assertEqual(repr(hr),
+            ("HandlerRegistration(_REGISTRY, [IFoo], %r, TEST, "
+           + "'DOCSTRING')") % (_name))
 
-        self.assertEqual(len(list(c1.registeredUtilities())), 0)
-        self.assertEqual(len(list(c2.registeredUtilities())), 0)
+    def test___repr___factory_wo_name(self):
+        class _Factory(object):
+            def __repr__(self):
+                return 'TEST'
+        hr, _registry, _name =  self._makeOne(_Factory())
+        self.assertEqual(repr(hr),
+            ("HandlerRegistration(_REGISTRY, [IFoo], %r, TEST, "
+           + "'DOCSTRING')") % (_name))
 
-        c1.registerUtility(test_object1)
-        self.assertEqual(len(list(c1.registeredUtilities())), 1)
-        self.assertEqual(len(list(c2.registeredUtilities())), 0)
-        self.assertEqual(c1.queryUtility(I1), test_object1)
-        self.assertEqual(c2.queryUtility(I1), test_object1)
 
-        c1.registerUtility(test_object2)
-        self.assertEqual(len(list(c1.registeredUtilities())), 1)
-        self.assertEqual(len(list(c2.registeredUtilities())), 0)
-        self.assertEqual(c1.queryUtility(I1), test_object2)
-        self.assertEqual(c2.queryUtility(I1), test_object2)
+class _Monkey(object):
+    # context-manager for replacing module names in the scope of a test.
+    def __init__(self, module, **kw):
+        self.module = module
+        self.to_restore = dict([(key, getattr(module, key)) for key in kw])
+        for key, value in kw.items():
+            setattr(module, key, value)
 
+    def __enter__(self):
+        return self
 
-        c3 = Components('3', (c1, ))
-        c4 = Components('4', (c2, c3))
-        self.assertEqual(c4.queryUtility(I1), test_object2)
-    
-        c1.registerUtility(test_object3, I2)
-        self.assertEqual(c4.queryUtility(I2), test_object3)
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        for key, value in self.to_restore.items():
+            setattr(self.module, key, value)
 
-        c3.registerUtility(test_object4, I2)
-        self.assertEqual(c4.queryUtility(I2), test_object4)
-
-        @adapter(I1)
-        def handle1(x):
-            self.assertEqual(x, test_object1)
-
-        def handle(*objects):
-            self.assertEqual(objects, (test_object1,))
-
-        @adapter(I1)
-        def handle3(x):
-            self.assertEqual(x, test_object1)
-
-        @adapter(I1)
-        def handle4(x):
-            self.assertEqual(x, test_object1)
-
-        c1.registerHandler(handle1, info=u'First handler')
-        c2.registerHandler(handle, required=[U])
-        c3.registerHandler(handle3)
-        c4.registerHandler(handle4)
-
-        c4.handle(test_object1)
-
 def test_suite():
     return unittest.TestSuite((
-            unittest.makeSuite(TestUtility),
-            unittest.makeSuite(TestAdapter),
-            unittest.makeSuite(TestSubscriber),
-            unittest.makeSuite(TestHandler),
-            unittest.makeSuite(TestExtending)
+            unittest.makeSuite(ComponentsTests),
+            unittest.makeSuite(UtilityRegistrationTests),
+            unittest.makeSuite(AdapterRegistrationTests),
+            unittest.makeSuite(SubscriptionRegistrationTests),
+            unittest.makeSuite(AdapterRegistrationTests),
         ))

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_verify.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_verify.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/test_verify.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -11,190 +11,534 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Interface Verify tests
+""" zope.interface.verify unit tests
 """
-import doctest
 import unittest
 
-from zope.interface import Interface, implements, classImplements, Attribute
-from zope.interface.verify import verifyClass, verifyObject
-from zope.interface.exceptions import DoesNotImplement, BrokenImplementation
-from zope.interface.exceptions import BrokenMethodImplementation
 
-class Test(unittest.TestCase):
+class Test_verifyClass(unittest.TestCase):
 
-    def testNotImplemented(self):
+    def _callFUT(self, iface, klass):
+        from zope.interface.verify import verifyClass
+        return verifyClass(iface, klass)
 
-        class C(object): pass
+    def test_class_doesnt_implement(self):
+        from zope.interface import Interface
+        from zope.interface.exceptions import DoesNotImplement
 
-        class I(Interface): pass
+        class ICurrent(Interface):
+            pass
 
-        self.assertRaises(DoesNotImplement, verifyClass, I, C)
+        class Current(object):
+            pass
 
-        classImplements(C, I)
+        self.assertRaises(DoesNotImplement, self._callFUT, ICurrent, Current)
 
-        verifyClass(I, C)
+    def test_class_doesnt_implement_but_classImplements_later(self):
+        from zope.interface import Interface
+        from zope.interface import classImplements
 
-    def testMissingAttr(self):
+        class ICurrent(Interface):
+            pass
 
-        class I(Interface):
-            def f(): pass
+        class Current(object):
+            pass
 
-        class C(object):
-            implements(I)
+        classImplements(Current, ICurrent)
 
-        self.assertRaises(BrokenImplementation, verifyClass, I, C)
+        self._callFUT(ICurrent, Current)
 
-        C.f=lambda self: None
+    def test_class_doesnt_have_required_method_simple(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenImplementation
 
-        verifyClass(I, C)
+        class ICurrent(Interface):
+            def method(): pass
 
-    def testMissingAttr_with_Extended_Interface(self):
+        class Current(object):
+            implements(ICurrent)
 
-        class II(Interface):
-            def f():
+        self.assertRaises(BrokenImplementation,
+                          self._callFUT, ICurrent, Current)
+
+    def test_class_has_required_method_simple(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+
+        class ICurrent(Interface):
+            def method(): pass
+
+        class Current(object):
+            implements(ICurrent)
+
+            def method(self):
                 pass
 
-        class I(II):
+        self._callFUT(ICurrent, Current)
+
+    def test_class_doesnt_have_required_method_derived(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenImplementation
+
+        class IBase(Interface):
+            def method():
+                pass
+
+        class IDerived(IBase):
             pass
 
-        class C(object):
-            implements(I)
+        class Current(object):
+            implements(IDerived)
 
-        self.assertRaises(BrokenImplementation, verifyClass, I, C)
+        self.assertRaises(BrokenImplementation,
+                          self._callFUT, IDerived, Current)
 
-        C.f=lambda self: None
+    def test_class_has_required_method_derived(self):
+        from zope.interface import Interface
+        from zope.interface import implements
 
-        verifyClass(I, C)
+        class IBase(Interface):
+            def method():
+                pass
 
-    def testWrongArgs(self):
+        class IDerived(IBase):
+            pass
 
-        class I(Interface):
-            def f(a): pass
+        class Current(object):
+            implements(IDerived)
 
-        class C(object):
-            def f(self, b): pass
+            def method(self):
+                pass
 
-            implements(I)
+        self._callFUT(IDerived, Current)
 
+    def test_method_takes_wrong_arg_names_but_OK(self):
         # We no longer require names to match.
-        #self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
+        from zope.interface import Interface
+        from zope.interface import implements
 
-        C.f=lambda self, a: None
+        class ICurrent(Interface):
 
-        verifyClass(I, C)
+            def method(a):
+                pass
 
-        C.f=lambda self, **kw: None
+        class Current(object):
+            implements(ICurrent)
 
-        self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
+            def method(self, b):
+                pass
 
-        C.f=lambda self, a, *args: None
+        self._callFUT(ICurrent, Current)
 
-        verifyClass(I, C)
+    def test_method_takes_not_enough_args(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenMethodImplementation
 
-        C.f=lambda self, a, *args, **kw: None
+        class ICurrent(Interface):
 
-        verifyClass(I, C)
+            def method(a):
+                pass
 
-        C.f=lambda self, *args: None
+        class Current(object):
+            implements(ICurrent)
 
-        verifyClass(I, C)
+            def method(self):
+                pass
 
-    def testExtraArgs(self):
+        self.assertRaises(BrokenMethodImplementation,
+                          self._callFUT, ICurrent, Current)
 
-        class I(Interface):
-            def f(a): pass
+    def test_method_doesnt_take_required_starargs(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenMethodImplementation
 
-        class C(object):
-            def f(self, a, b): pass
+        class ICurrent(Interface):
 
-            implements(I)
+            def method(*args):
+                pass
 
-        self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
+        class Current(object):
+            implements(ICurrent)
 
-        C.f=lambda self, a: None
+            def method(self):
+                pass
 
-        verifyClass(I, C)
+        self.assertRaises(BrokenMethodImplementation,
+                          self._callFUT, ICurrent, Current)
 
-        C.f=lambda self, a, b=None: None
+    def test_method_doesnt_take_required_only_kwargs(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenMethodImplementation
 
-        verifyClass(I, C)
+        class ICurrent(Interface):
 
-    def testNoVar(self):
+            def method(**kw):
+                pass
 
-        class I(Interface):
-            def f(a, *args): pass
+        class Current(object):
+            implements(ICurrent)
 
-        class C(object):
-            def f(self, a): pass
+            def method(self):
+                pass
 
-            implements(I)
+        self.assertRaises(BrokenMethodImplementation,
+                          self._callFUT, ICurrent, Current)
 
-        self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
+    def test_method_takes_extra_arg(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenMethodImplementation
 
-        C.f=lambda self, a, *foo: None
+        class ICurrent(Interface):
 
-        verifyClass(I, C)
+            def method(a):
+                pass
 
-    def testNoKW(self):
+        class Current(object):
+            implements(ICurrent)
 
-        class I(Interface):
-            def f(a, **args): pass
+            def method(self, a, b):
+                pass
 
-        class C(object):
-            def f(self, a): pass
+        self.assertRaises(BrokenMethodImplementation,
+                          self._callFUT, ICurrent, Current)
 
-            implements(I)
+    def test_method_takes_extra_arg_with_default(self):
+        from zope.interface import Interface
+        from zope.interface import implements
 
-        self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
+        class ICurrent(Interface):
 
-        C.f=lambda self, a, **foo: None
+            def method(a):
+                pass
 
-        verifyClass(I, C)
+        class Current(object):
+            implements(ICurrent)
 
-    def testModule(self):
+            def method(self, a, b=None):
+                pass
 
-        from zope.interface.tests.ifoo import IFoo
-        from zope.interface.tests import dummy
+        self._callFUT(ICurrent, Current)
 
-        verifyObject(IFoo, dummy)
+    def test_method_takes_only_positional_args(self):
+        from zope.interface import Interface
+        from zope.interface import implements
 
-    def testMethodForAttr(self):
-        
-        class IFoo(Interface):
-             foo = Attribute("The foo Attribute")
+        class ICurrent(Interface):
 
+            def method(a):
+                pass
 
-        class Foo:
-             implements(IFoo)
+        class Current(object):
+            implements(ICurrent)
 
-             def foo(self):
-                 pass
+            def method(self, *args):
+                pass
 
-        verifyClass(IFoo, Foo)
+        self._callFUT(ICurrent, Current)
 
-    def testNonMethodForMethod(self):
+    def test_method_takes_only_kwargs(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenMethodImplementation
 
-        class IBar(Interface):
-             def foo():
-                 pass
+        class ICurrent(Interface):
 
-        class Bar:
-            implements(IBar)
+            def method(a):
+                pass
 
-            foo = 1
+        class Current(object):
+            implements(ICurrent)
 
-        self.assertRaises(BrokenMethodImplementation, verifyClass, IBar, Bar)
-        
+            def method(self, **kw):
+                pass
 
+        self.assertRaises(BrokenMethodImplementation,
+                          self._callFUT, ICurrent, Current)
+
+    def test_method_takes_extra_starargs(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+
+        class ICurrent(Interface):
+
+            def method(a):
+                pass
+
+        class Current(object):
+            implements(ICurrent)
+
+            def method(self, a, *args):
+                pass
+
+        self._callFUT(ICurrent, Current)
+
+    def test_method_takes_extra_starargs_and_kwargs(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+
+        class ICurrent(Interface):
+
+            def method(a):
+                pass
+
+        class Current(object):
+            implements(ICurrent)
+
+            def method(self, a, *args, **kw):
+                pass
+
+        self._callFUT(ICurrent, Current)
+
+    def test_method_doesnt_take_required_positional_and_starargs(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenMethodImplementation
+
+        class ICurrent(Interface):
+
+            def method(a, *args):
+                pass
+
+        class Current(object):
+            implements(ICurrent)
+
+            def method(self, a):
+                pass
+
+        self.assertRaises(BrokenMethodImplementation,
+                          self._callFUT, ICurrent, Current)
+
+    def test_method_takes_required_positional_and_starargs(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+
+        class ICurrent(Interface):
+
+            def method(a, *args):
+                pass
+
+        class Current(object):
+            implements(ICurrent)
+
+            def method(self, a, *args):
+                pass
+
+        self._callFUT(ICurrent, Current)
+
+    def test_method_takes_only_starargs(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+
+        class ICurrent(Interface):
+
+            def method(a, *args):
+                pass
+
+        class Current(object):
+            implements(ICurrent)
+
+            def method(self, *args):
+                pass
+
+        self._callFUT(ICurrent, Current)
+
+    def test_method_takes_required_kwargs(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+
+        class ICurrent(Interface):
+
+            def method(**kwargs):
+                pass
+
+        class Current(object):
+            implements(ICurrent)
+
+            def method(self, **kw):
+                pass
+
+        self._callFUT(ICurrent, Current)
+
+    def test_method_takes_positional_plus_required_starargs(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenMethodImplementation
+
+        class ICurrent(Interface):
+
+            def method(*args):
+                pass
+
+        class Current(object):
+            implements(ICurrent)
+
+            def method(self, a, *args):
+                pass
+
+        self.assertRaises(BrokenMethodImplementation,
+                          self._callFUT, ICurrent, Current)
+
+
+    def test_method_doesnt_take_required_kwargs(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenMethodImplementation
+
+        class ICurrent(Interface):
+
+            def method(**kwargs):
+                pass
+
+        class Current(object):
+            implements(ICurrent)
+
+            def method(self, a):
+                pass
+
+        self.assertRaises(BrokenMethodImplementation,
+                          self._callFUT, ICurrent, Current)
+
+
+    def test_class_has_method_for_iface_attr(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+        from zope.interface import implements
+
+        class ICurrent(Interface):
+            attr = Attribute("The foo Attribute")
+
+        class Current:
+            implements(ICurrent)
+
+            def attr(self):
+                pass
+
+        self._callFUT(ICurrent, Current)
+
+    def test_class_has_nonmethod_for_method(self):
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenMethodImplementation
+
+        class ICurrent(Interface):
+            def method():
+                pass
+
+        class Current:
+            implements(ICurrent)
+            method = 1
+
+        self.assertRaises(BrokenMethodImplementation,
+                          self._callFUT, ICurrent, Current)
+
+    def test_class_has_attribute_for_attribute(self):
+        from zope.interface import Attribute
+        from zope.interface import Interface
+        from zope.interface import implements
+
+        class ICurrent(Interface):
+            attr = Attribute("The foo Attribute")
+
+        class Current:
+            implements(ICurrent)
+
+            attr = 1
+
+        self._callFUT(ICurrent, Current)
+
+    def test_class_misses_attribute_for_attribute(self):
+        # This check *passes* for verifyClass
+        from zope.interface import Attribute
+        from zope.interface import Interface
+        from zope.interface import implements
+
+        class ICurrent(Interface):
+            attr = Attribute("The foo Attribute")
+
+        class Current:
+            implements(ICurrent)
+
+        self._callFUT(ICurrent, Current)
+
+    def test_w_callable_non_func_method(self):
+        from zope.interface.interface import Method
+        from zope.interface import Interface
+        from zope.interface import implements
+
+        class QuasiMethod(Method):
+            def __call__(self, *args, **kw):
+                pass
+
+        class QuasiCallable(object):
+            def __call__(self, *args, **kw):
+                pass
+
+        class ICurrent(Interface):
+            attr = QuasiMethod('This is callable')
+
+        class Current:
+            implements(ICurrent)
+            attr = QuasiCallable()
+
+        self._callFUT(ICurrent, Current)
+
+class Test_verifyObject(Test_verifyClass):
+
+    def _callFUT(self, iface, target):
+        from zope.interface.verify import verifyObject
+        if isinstance(target, (type, type(OldSkool))):
+            target = target()
+        return verifyObject(iface, target)
+
+    def test_class_misses_attribute_for_attribute(self):
+        # This check *fails* for verifyObject
+        from zope.interface import Attribute
+        from zope.interface import Interface
+        from zope.interface import implements
+        from zope.interface.exceptions import BrokenImplementation
+
+        class ICurrent(Interface):
+            attr = Attribute("The foo Attribute")
+
+        class Current:
+            implements(ICurrent)
+
+        self.assertRaises(BrokenImplementation,
+                          self._callFUT, ICurrent, Current)
+
+    def test_module_hit(self):
+        from zope.interface.tests.idummy import IDummyModule
+        from zope.interface.tests import dummy
+
+        self._callFUT(IDummyModule, dummy)
+
+    def test_module_miss(self):
+        from zope.interface import Interface
+        from zope.interface.tests import dummy
+        from zope.interface.exceptions import DoesNotImplement
+
+        # same name, different object
+        class IDummyModule(Interface):
+            pass
+
+        self.assertRaises(DoesNotImplement,
+                          self._callFUT, IDummyModule, dummy)
+
+class OldSkool:
+    pass
+
 def test_suite():
-    loader=unittest.TestLoader()
+    #import doctest
     return unittest.TestSuite((
-        doctest.DocFileSuite(
-            '../verify.txt',
-            optionflags=doctest.NORMALIZE_WHITESPACE),
-        loader.loadTestsFromTestCase(Test),
-        ))
-
-if __name__=='__main__':
-    unittest.TextTestRunner().run(test_suite())
+        unittest.makeSuite(Test_verifyClass),
+        unittest.makeSuite(Test_verifyObject),
+    #   This one needs to turn into just docs.
+    #doctest.DocFileSuite('../verify.txt',
+    #                     optionflags=doctest.NORMALIZE_WHITESPACE),
+    ))

Deleted: zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/unitfixtures.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/unitfixtures.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/tests/unitfixtures.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,140 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Unit Test Fixtures
-"""
-from zope.interface import Interface, invariant
-from zope.interface.interface import Attribute
-from zope.interface.exceptions import Invalid
-
-class mytest(Interface):
-    pass
-
-class C(object):
-    def m1(self, a, b):
-        "return 1"
-        return 1
-
-    def m2(self, a, b):
-        "return 2"
-        return 2
-
-# testInstancesOfClassImplements
-
-#  YAGNI IC=Interface.impliedInterface(C)
-class IC(Interface):
-    def m1(a, b):
-        "return 1"
-
-    def m2(a, b):
-        "return 2"
-
-
-
-C.__implemented__=IC
-
-class I1(Interface):
-    def ma():
-        "blah"
-
-class I2(I1): pass
-
-class I3(Interface): pass
-
-class I4(Interface): pass
-
-class A(I1.deferred()):
-    __implemented__=I1
-
-class B(object):
-    __implemented__=I2, I3
-
-class D(A, B): pass
-
-class E(A, B):
-    __implemented__ = A.__implemented__, C.__implemented__
-
-
-class FooInterface(Interface):
-    """ This is an Abstract Base Class """
-
-    foobar = Attribute("fuzzed over beyond all recognition")
-
-    def aMethod(foo, bar, bingo):
-        """ This is aMethod """
-
-    def anotherMethod(foo=6, bar="where you get sloshed", bingo=(1,3,)):
-        """ This is anotherMethod """
-
-    def wammy(zip, *argues):
-        """ yadda yadda """
-
-    def useless(**keywords):
-        """ useless code is fun! """
-
-class Foo(object):
-    """ A concrete class """
-
-    __implemented__ = FooInterface,
-
-    foobar = "yeah"
-
-    def aMethod(self, foo, bar, bingo):
-        """ This is aMethod """
-        return "barf!"
-
-    def anotherMethod(self, foo=6, bar="where you get sloshed", bingo=(1,3,)):
-        """ This is anotherMethod """
-        return "barf!"
-
-    def wammy(self, zip, *argues):
-        """ yadda yadda """
-        return "barf!"
-
-    def useless(self, **keywords):
-        """ useless code is fun! """
-        return "barf!"
-
-foo_instance = Foo()
-
-class Blah(object):
-    pass
-
-new = Interface.__class__
-FunInterface = new('FunInterface')
-BarInterface = new('BarInterface', [FunInterface])
-BobInterface = new('BobInterface')
-BazInterface = new('BazInterface', [BobInterface, BarInterface])
-
-# fixtures for invariant tests
-def ifFooThenBar(obj):
-    if getattr(obj, 'foo', None) and not getattr(obj, 'bar', None):
-        raise Invalid('If Foo, then Bar!')
-class IInvariant(Interface):
-    foo = Attribute('foo')
-    bar = Attribute('bar; must eval to Boolean True if foo does')
-    invariant(ifFooThenBar)
-def BarGreaterThanFoo(obj):
-    foo = getattr(obj, 'foo', None)
-    bar = getattr(obj, 'bar', None)
-    if foo is not None and isinstance(foo, type(bar)):
-        # type checking should be handled elsewhere (like, say, 
-        # schema); these invariants should be intra-interface 
-        # constraints.  This is a hacky way to do it, maybe, but you
-        # get the idea
-        if not bar > foo:
-            raise Invalid('Please, Boo MUST be greater than Foo!')
-class ISubInvariant(IInvariant):
-    invariant(BarGreaterThanFoo)
-class InvariantC(object):
-    pass

Modified: zope.interface/branches/tseaver-better_unittests/src/zope/interface/verify.py
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/verify.py	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/verify.py	2012-03-26 20:56:58 UTC (rev 124742)
@@ -68,7 +68,8 @@
         if isinstance(attr, FunctionType):
             if sys.version[0] == '3' and isinstance(candidate, type):
                 # This is an "unbound method" in Python 3.
-                meth = fromFunction(attr, iface, name=name, imlevel=1)
+                meth = fromFunction(attr, iface, name=name,
+                                    imlevel=1) #pragma NO COVERAGE
             else:
                 # Nope, just a normal function
                 meth = fromFunction(attr, iface, name=name)
@@ -78,9 +79,9 @@
         else:
             if not callable(attr):
                 raise BrokenMethodImplementation(name, "Not a method")
-            # sigh, it's callable, but we don't know how to intrspect it, so
+            # sigh, it's callable, but we don't know how to introspect it, so
             # we have to give it a pass.
-            continue
+            continue #pragma NO COVERAGE
 
         # Make sure that the required and implemented method signatures are
         # the same.

Deleted: zope.interface/branches/tseaver-better_unittests/src/zope/interface/verify.txt
===================================================================
--- zope.interface/branches/tseaver-better_unittests/src/zope/interface/verify.txt	2012-03-26 20:52:07 UTC (rev 124741)
+++ zope.interface/branches/tseaver-better_unittests/src/zope/interface/verify.txt	2012-03-26 20:56:58 UTC (rev 124742)
@@ -1,127 +0,0 @@
-===================================
-Verifying interface implementations
-===================================
-
-The ``zope.interface.verify`` module provides functions that test whether a
-given interface is implemented by a class or provided by an object, resp.
-
-
-Verifying classes
-=================
-
-This is covered by unit tests defined in ``zope.interface.tests.test_verify``.
-
-
-Verifying objects
-=================
-
-An object provides an interface if
-
-- either its class declares that it implements the interfaces, or the object
-  declares that it directly provides the interface
-
-- the object defines all the methods required by the interface
-
-- all the methods have the correct signature
-
-- the object defines all non-method attributes required by the interface
-
-This doctest currently covers only the latter item.
-
-Testing for attributes
-----------------------
-
-Attributes of the object, be they defined by its class or added by its
-``__init__`` method, will be recognized:
-
->>> from zope.interface import Interface, Attribute, implements
->>> from zope.interface.exceptions import BrokenImplementation
->>> class IFoo(Interface):
-...     x = Attribute("The X attribute")
-...     y = Attribute("The Y attribute")
-
->>> class Foo(object):
-...     implements(IFoo)
-...     x = 1
-...     def __init__(self):
-...         self.y = 2
-
->>> from zope.interface.verify import verifyObject
->>> verifyObject(IFoo, Foo())
-True
-
-If either attribute is missing, verification will fail:
-
->>> class Foo(object):
-...     implements(IFoo)
-...     x = 1
-
->>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
-...     verifyObject(IFoo, Foo())
-... except BrokenImplementation, e:
-...     print str(e)
-An object has failed to implement interface <InterfaceClass ...IFoo>
-<BLANKLINE>
-        The y attribute was not provided.
-<BLANKLINE>
-
->>> class Foo(object):
-...     implements(IFoo)
-...     def __init__(self):
-...         self.y = 2
-
->>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
-...     verifyObject(IFoo, Foo())
-... except BrokenImplementation, e:
-...     print str(e)
-An object has failed to implement interface <InterfaceClass ...IFoo>
-<BLANKLINE>
-        The x attribute was not provided.
-<BLANKLINE>
-
-If an attribute is implemented as a property that raises an AttributeError
-when trying to get its value, the attribute is considered missing:
-
->>> class IFoo(Interface):
-...     x = Attribute('The X attribute')
-
->>> class Foo(object):
-...     implements(IFoo)
-...     @property
-...     def x(self):
-...         raise AttributeError
-
->>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
-...     verifyObject(IFoo, Foo())
-... except BrokenImplementation, e:
-...     print str(e)
-An object has failed to implement interface <InterfaceClass ...IFoo>
-<BLANKLINE>
-        The x attribute was not provided.
-<BLANKLINE>
-
-Any other exception raised by a property will propagate to the caller of
-``verifyObject``:
-
->>> class Foo(object):
-...     implements(IFoo)
-...     @property
-...     def x(self):
-...         raise Exception
-
->>> verifyObject(IFoo, Foo())
-Traceback (most recent call last):
-Exception
-
-Of course, broken properties that are not required by the interface don't do
-any harm:
-
->>> class Foo(object):
-...     implements(IFoo)
-...     x = 1
-...     @property
-...     def y(self):
-...         raise Exception
-
->>> verifyObject(IFoo, Foo())
-True



More information about the checkins mailing list