[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