diff options
| author | Tres Seaver <tseaver@palladion.com> | 2012-03-26 20:56:58 +0000 |
|---|---|---|
| committer | Tres Seaver <tseaver@palladion.com> | 2012-03-26 20:56:58 +0000 |
| commit | bc4d8bc1569c9d4dc28c62272a5acbaebc04cdfe (patch) | |
| tree | 605f4701a12fc03dc084e6115d6f07ef1a152029 | |
| parent | 2fd652d0d095b79e2e6365b00c739f589bf631a5 (diff) | |
| download | zope-interface-bc4d8bc1569c9d4dc28c62272a5acbaebc04cdfe.tar.gz | |
Merge from LP branch.
41 files changed, 8926 insertions, 2572 deletions
@@ -6,3 +6,7 @@ ./parts *.egg-info ./build +.coverage +include +lib +docs/_build diff --git a/README-better_unittest.txt b/README-better_unittest.txt new file mode 100644 index 0000000..16fa6b4 --- /dev/null +++ b/README-better_unittest.txt @@ -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` diff --git a/buildout.cfg b/buildout.cfg index 942c7c4..0830b4d 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -1,6 +1,6 @@ [buildout] develop = . -parts = test python docs +parts = test python [test] recipe = zc.recipe.testrunner @@ -12,10 +12,3 @@ recipe = zc.recipe.egg 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 = diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d34ea74 --- /dev/null +++ b/docs/Makefile @@ -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." diff --git a/src/zope/interface/README.txt b/docs/README.rst index 253d1ed..253d1ed 100644 --- a/src/zope/interface/README.txt +++ b/docs/README.rst diff --git a/src/zope/interface/README.ru.txt b/docs/README.ru.rst index a284c9a..a284c9a 100644 --- a/src/zope/interface/README.ru.txt +++ b/docs/README.ru.rst diff --git a/src/zope/interface/adapter.txt b/docs/adapter.rst index 298a862..298a862 100644 --- a/src/zope/interface/adapter.txt +++ b/docs/adapter.rst diff --git a/src/zope/interface/adapter.ru.txt b/docs/adapter.ru.rst index 30c2782..30c2782 100644 --- a/src/zope/interface/adapter.ru.txt +++ b/docs/adapter.ru.rst diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..581a428 --- /dev/null +++ b/docs/conf.py @@ -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} diff --git a/src/zope/interface/tests/foodforthought.txt b/docs/foodforthought.rst index 45d961b..45d961b 100644 --- a/src/zope/interface/tests/foodforthought.txt +++ b/docs/foodforthought.rst diff --git a/src/zope/interface/human.txt b/docs/human.rst index 749b87d..749b87d 100644 --- a/src/zope/interface/human.txt +++ b/docs/human.rst diff --git a/src/zope/interface/human.ru.txt b/docs/human.ru.rst index a149072..a149072 100644 --- a/src/zope/interface/human.ru.txt +++ b/docs/human.ru.rst diff --git a/src/zope/interface/index.txt b/docs/index.rst index 3c499b5..a44105d 100644 --- a/src/zope/interface/index.txt +++ b/docs/index.rst @@ -1,3 +1,8 @@ +.. 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! ========================================== @@ -10,6 +15,7 @@ Contents: adapter human verify + foodforthought По-русски ========= @@ -21,9 +27,12 @@ Contents: adapter.ru human.ru + + Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` + diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..f59869c --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,190 @@ +@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 diff --git a/src/zope/interface/verify.txt b/docs/verify.rst index 7eec6d2..7eec6d2 100644 --- a/src/zope/interface/verify.txt +++ b/docs/verify.rst diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..d279fa9 --- /dev/null +++ b/setup.cfg @@ -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] @@ -61,14 +61,18 @@ else: 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 @@ try: # Zope setuptools versions 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): diff --git a/src/zope/interface/__init__.py b/src/zope/interface/__init__.py index 8b05f6b..ad0a766 100644 --- a/src/zope/interface/__init__.py +++ b/src/zope/interface/__init__.py @@ -50,23 +50,33 @@ See the module doc strings for more information. """ __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 diff --git a/src/zope/interface/_zope_interface_coptimizations.c b/src/zope/interface/_zope_interface_coptimizations.c index 7b0f816..b2088ee 100644 --- a/src/zope/interface/_zope_interface_coptimizations.c +++ b/src/zope/interface/_zope_interface_coptimizations.c @@ -979,7 +979,13 @@ _lookup1(lookup *self, Py_DECREF(tup); } else - Py_INCREF(result); + { + if (result == Py_None && default_ != NULL) + { + result = default_; + } + Py_INCREF(result); + } return result; } diff --git a/src/zope/interface/adapter.py b/src/zope/interface/adapter.py index 2ad145b..31c1d85 100644 --- a/src/zope/interface/adapter.py +++ b/src/zope/interface/adapter.py @@ -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 @@ class BaseAdapterRegistry(object): # 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 @@ class BaseAdapterRegistry(object): 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 @@ class BaseAdapterRegistry(object): # 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 @@ class LookupBasePy(object): return result -LookupBase = LookupBasePy +LookupBasePy = LookupBaseFallback # BBB + +try: + from _zope_interface_coptimizations import LookupBase +except ImportError: #pragma NO COVER + LookupBase = LookupBaseFallback -class VerifyingBasePy(LookupBasePy): + +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,25 +421,23 @@ class VerifyingBasePy(LookupBasePy): 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) - -VerifyingBase = VerifyingBasePy + return LookupBaseFallback.subscriptions(self, required, provided) +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): diff --git a/src/zope/interface/advice.py b/src/zope/interface/advice.py index d23818e..28f4805 100644 --- a/src/zope/interface/advice.py +++ b/src/zope/interface/advice.py @@ -29,7 +29,7 @@ from types import FunctionType try: from types import ClassType __python3 = False -except ImportError: +except ImportError: #pragma NO COVER __python3 = True import sys @@ -63,7 +63,7 @@ def getFrameInfo(frame): 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 @@ def addClassAdvisor(callback, depth=2): # ) 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 @@ def determineMetaclass(bases, explicit_mc=None): 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 diff --git a/src/zope/interface/common/interfaces.py b/src/zope/interface/common/interfaces.py index 47e9de7..6274e6d 100644 --- a/src/zope/interface/common/interfaces.py +++ b/src/zope/interface/common/interfaces.py @@ -77,14 +77,14 @@ classImplements(OSError, IOSError) 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) diff --git a/src/zope/interface/declarations.py b/src/zope/interface/declarations.py index bafe399..00daa7f 100644 --- a/src/zope/interface/declarations.py +++ b/src/zope/interface/declarations.py @@ -27,11 +27,15 @@ There are three flavors of declarations: __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.interface import SpecificationBase -from types import ModuleType, MethodType, FunctionType + from zope.interface.advice import addClassAdvisor +from zope.interface.interface import InterfaceClass +from zope.interface.interface import SpecificationBase +from zope.interface.interface import Specification # Registry of class-implementation specifications BuiltinImplementationSpecifications = {} @@ -760,7 +764,7 @@ Provides.__safe_for_unpickling__ = True 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 @@ def noLongerProvides(object, interface): 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 @@ class ClassProvidesBasePy(object): 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 @@ def moduleProvides(*interfaces): # # 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 @@ def ObjectSpecification(direct, cls): 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,7 +1275,9 @@ def getObjectSpecification(ob): 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 @@ def providedBy(ob): 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 @@ class ObjectSpecificationDescriptorPy(object): return implementedBy(cls) -ObjectSpecificationDescriptor = ObjectSpecificationDescriptorPy +ObjectSpecificationDescriptor = ObjectSpecificationDescriptorFallback ############################################################################## @@ -1385,10 +1395,11 @@ _empty = Declaration() 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 diff --git a/src/zope/interface/interface.py b/src/zope/interface/interface.py index aec7d85..e7ca1e1 100644 --- a/src/zope/interface/interface.py +++ b/src/zope/interface/interface.py @@ -163,7 +163,7 @@ class SpecificationBasePy(object): SpecificationBase = SpecificationBasePy try: from _zope_interface_coptimizations import SpecificationBase -except ImportError: +except ImportError: #pragma NO COVER pass _marker = object() @@ -204,14 +204,14 @@ class InterfaceBasePy(object): 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 @@ class Specification(SpecificationBase): 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 @@ class InterfaceClass(Element, InterfaceBase, Specification): # 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 @@ class InterfaceClass(Element, InterfaceBase, Specification): 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 @@ class InterfaceClass(Element, InterfaceBase, Specification): 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 @@ class InterfaceClass(Element, InterfaceBase, Specification): 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 @@ class InterfaceClass(Element, InterfaceBase, Specification): 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 @@ class Method(Attribute): # # 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 @@ class Method(Attribute): 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: diff --git a/src/zope/interface/registry.py b/src/zope/interface/registry.py index 6310686..c5009d3 100644 --- a/src/zope/interface/registry.py +++ b/src/zope/interface/registry.py @@ -18,7 +18,7 @@ import types 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 # required by py3k fixers 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 diff --git a/src/zope/interface/ro.py b/src/zope/interface/ro.py index 47a7ea2..ab47a4c 100644 --- a/src/zope/interface/ro.py +++ b/src/zope/interface/ro.py @@ -30,7 +30,7 @@ def mergeOrderings(orderings, seen=None): For example: - >>> _mergeOrderings([ + >>> mergeOrderings([ ... ['x', 'y', 'z'], ... ['q', 'z'], ... [1, 3, 5], diff --git a/src/zope/interface/tests/advisory_testing.py b/src/zope/interface/tests/advisory_testing.py new file mode 100644 index 0000000..f78a550 --- /dev/null +++ b/src/zope/interface/tests/advisory_testing.py @@ -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()) diff --git a/src/zope/interface/tests/dummy.py b/src/zope/interface/tests/dummy.py index f5564da..9057d73 100644 --- a/src/zope/interface/tests/dummy.py +++ b/src/zope/interface/tests/dummy.py @@ -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 diff --git a/src/zope/interface/tests/idummy.py b/src/zope/interface/tests/idummy.py new file mode 100644 index 0000000..1e34fe0 --- /dev/null +++ b/src/zope/interface/tests/idummy.py @@ -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. + """ diff --git a/src/zope/interface/tests/test_adapter.py b/src/zope/interface/tests/test_adapter.py index 30a8598..8322f74 100644 --- a/src/zope/interface/tests/test_adapter.py +++ b/src/zope/interface/tests/test_adapter.py @@ -13,400 +13,1260 @@ ############################################################################## """Adapter registry tests """ -import doctest import unittest -import zope.interface -from zope.interface.adapter import AdapterRegistry - - -class IF0(zope.interface.Interface): - pass -class IF1(IF0): - pass - -class IB0(zope.interface.Interface): - pass -class IB1(IB0): - pass - -class IR0(zope.interface.Interface): - pass -class IR1(IR0): - pass - -def test_multi_adapter_get_best_match(): - """ - >>> registry = AdapterRegistry() - - >>> 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') - - >>> 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' - """ - -def test_multi_adapter_lookupAll_get_best_matches(): - """ - >>> registry = AdapterRegistry() - - >>> 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') - - >>> 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 test_multi_adapter_w_default(): - """ - >>> registry = AdapterRegistry() - - >>> registry.register([None, None], IB1, 'bob', 'A0') - - >>> registry.lookup((IF1, IR1), IB0, 'bob') - 'A0' - - >>> registry.register([None, IR0], IB1, 'bob', 'A1') - - >>> registry.lookup((IF1, IR1), IB0, 'bob') - 'A1' - - >>> registry.lookup((IF1, IR1), IB0, 'bruce') - - >>> registry.register([None, IR1], IB1, 'bob', 'A2') - >>> registry.lookup((IF1, IR1), IB0, 'bob') - 'A2' - """ - -def test_multi_adapter_w_inherited_and_multiple_registrations(): - """ - >>> registry = AdapterRegistry() - - >>> class IX(zope.interface.Interface): - ... pass - - >>> registry.register([IF0, IR0], IB1, 'bob', 'A1') - >>> registry.register([IF1, IX], IB1, 'bob', 'AX') - - >>> registry.lookup((IF1, IR1), IB0, 'bob') - 'A1' - """ - -def test_named_adapter_with_default(): - """Query a named simple adapter - - >>> registry = AdapterRegistry() - - 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: - - >>> registry.lookup([IF1], IF0, 'bob') - - >>> registry.register([None], IB1, 'bob', 'A1') - >>> registry.lookup([IF1], IB0, 'bob') - 'A1' - - >>> registry.lookup([IF1], IB0, 'bruce') - - >>> registry.register([None], IB0, 'bob', 'A2') - >>> registry.lookup([IF1], IB0, 'bob') - 'A2' - """ - -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' - - >>> registry = AdapterRegistry() - >>> registry.register([IF1, IR0], IB1, 'bob', 'A2') - >>> registry.register([IF1, IR0], IB0, 'bob', 'A1') - >>> registry.lookup([IF1, IR0], IB0, 'bob') - 'A1' - - >>> registry = AdapterRegistry() - >>> registry.register([IF1, IR0], IB0, 'bob', 'A1') - >>> registry.register([IF1, IR1], IB1, 'bob', 'A2') - >>> registry.lookup([IF1, IR1], IB0, 'bob') - 'A2' - - >>> 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_multi_adapter_check_non_default_dont_hide_default(): - """ - >>> registry = AdapterRegistry() - - >>> class IX(zope.interface.Interface): - ... pass - - - >>> 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) - - >>> def factory(context): - ... if isinstance(context, Object1): - ... return 'adapter' - ... return None - - >>> registry.register([IF0], IB0, '', factory) - - >>> 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_adapter_registry_update_upon_interface_bases_change(): - """ - Let's first create a adapter registry and a simple adaptation hook: - - >>> globalRegistry = AdapterRegistry() - - >>> def _hook(iface, ob, lookup=globalRegistry.lookup1): - ... factory = lookup(zope.interface.providedBy(ob), iface) - ... if factory is None: - ... return None - ... else: - ... return factory(ob) - - >>> zope.interface.interface.adapter_hooks.append(_hook) - - Now we create some interfaces and an implementation: - - >>> class IX(zope.interface.Interface): - ... pass - - >>> class IY(zope.interface.Interface): - ... pass - - >>> class X(object): - ... pass - - >>> class Y(object): - ... zope.interface.implements(IY) - ... def __init__(self, original): - ... self.original=original - - and register an adapter: - - >>> globalRegistry.register((IX,), IY, '', Y) - - at first, we still expect the adapter lookup from `X` to `IY` to fail: - - >>> 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>) - - But after we declare an interface on the class `X`, it should pass: - - >>> zope.interface.classImplementsOnly(X, IX) - - >>> IY(X()) #doctest: +ELLIPSIS - <zope.interface.tests.test_adapter.Y object at ...> - - >>> hook = zope.interface.interface.adapter_hooks.pop() - """ - - -def test_changing_declarations(): - """ - - If we change declarations for a class, those adapter lookup should - eflect the changes: - - >>> class I1(zope.interface.Interface): - ... pass - >>> class I2(zope.interface.Interface): - ... pass - - >>> registry = AdapterRegistry() - >>> registry.register([I1], I2, '', 42) - - >>> class C: - ... pass - - >>> registry.lookup([zope.interface.implementedBy(C)], I2, '') - - >>> zope.interface.classImplements(C, I1) - - >>> registry.lookup([zope.interface.implementedBy(C)], I2, '') - 42 - """ - -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 test_duplicate_bases(): - """ -There was a bug that caused problems if a spec had multiple bases: - - >>> 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 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: - - >>> 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 - - >>> registry = AdapterRegistry() - >>> picky = Picky() - >>> registry.register([I2], IR0, '', picky) - >>> registry.unregister([I2], IR0, '', picky) - - >>> registry.subscribe([I2], IR0, picky) - >>> registry.unsubscribe([I2], IR0, picky) - - """ - -def test_unregister_cleans_up_empties(): - """ - >>> class I(zope.interface.Interface): - ... pass - >>> class IP(zope.interface.Interface): - ... pass - >>> class C(object): - ... pass - - >>> 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] - - >>> registry.unregister([], IP, '', C) - >>> registry.unregister([I], IP, '', C) - >>> registry.unregister([I], IP, 'name', C) - >>> registry.unregister([I, I], IP, '', C) - >>> registry._adapters - [] - - """ - -def test_unsubscribe_cleans_up_empties(): - """ - >>> class I1(zope.interface.Interface): - ... pass - >>> class I2(zope.interface.Interface): - ... pass - >>> class IP(zope.interface.Interface): - ... pass - - >>> registry = AdapterRegistry() - >>> def handler(event): - ... pass - - >>> registry.subscribe([I1], I1, handler) - >>> registry.subscribe([I2], I1, handler) - >>> len(registry._subscribers) - 2 - >>> map(len, registry._subscribers) - [0, 2] - - >>> registry.unsubscribe([I1], I1, handler) - >>> registry.unsubscribe([I2], I1, handler) - >>> registry._subscribers - [] - - """ +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) + + +def _makeInterfaces(): + from zope.interface import Interface + + class IB0(Interface): pass + class IB1(IB0): pass + class IB2(IB0): pass + class IB3(IB2, IB1): pass + class IB4(IB1, IB2): pass + + class IF0(Interface): pass + class IF1(IF0): pass + + class IR0(Interface): pass + class IR1(IR0): pass + + return IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 + + +class BaseAdapterRegistryTests(_SilencePy3Deprecations): + + 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_lookup_delegation(self): + CUT = self._getTargetClass() + registry = CUT() + for name in CUT._delegated: + self.failUnless( + getattr(registry, name) is getattr(registry._v_lookup, name)) + + def test__generation_on_first_creation(self): + registry = self._makeOne() + # Bumped to 1 in BaseAdapterRegistry.__init__ + self.assertEqual(registry._generation, 1) + + 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,)) + + def test__generation_after_changing___bases__(self): + class _Base(object): pass + registry = self._makeOne() + registry.__bases__ = (_Base,) + self.assertEqual(registry._generation, 2) + + 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) + + 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) + + 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() + + def test_registered_empty(self): + registry = self._makeOne() + self.assertEqual(registry.registered([None], None, ''), None) + + 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) + + def test_registered_non_empty_hit(self): + registry = self._makeOne() + registry.register([None], None, '', 'A1') + self.assertEqual(registry.registered([None], None, ''), 'A1') + + def test_unregister_empty(self): + registry = self._makeOne() + registry.unregister([None], None, '') #doesn't raise + self.assertEqual(registry.registered([None], None, ''), None) + + 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') + + 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') + + 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) + + 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_unsubscribe_empty(self): + registry = self._makeOne() + registry.unsubscribe([None], None, '') #doesn't raise + self.assertEqual(registry.registered([None], None, ''), None) + + 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) + + 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) + + 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_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) + + 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) + + +class LookupBaseFallbackTests(_SilencePy3Deprecations): + + def _getTargetClass(self): + from zope.interface.adapter import LookupBaseFallback + return LookupBaseFallback + + 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() + + 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_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')]) + + 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 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]) + + 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]) + + 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]) + + 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]) + + 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')]) + + 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')]) + + 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')]) + + 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]) + + 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]) + + 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]) + + 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) + + 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) + + 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]) + + 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]) + + 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_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')]) + + 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')]) + + 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')]) + + +class LookupBaseTests(LookupBaseFallbackTests): + + def _getTargetClass(self): + from zope.interface.adapter import LookupBase + return LookupBase + + +class VerifyingBaseFallbackTests(_SilencePy3Deprecations): + + def _getTargetClass(self): + from zope.interface.adapter import VerifyingBaseFallback + return VerifyingBaseFallback + + 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 + + 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_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]) + + 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]) + + 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) + + 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_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)) + + +class VerifyingBaseTests(VerifyingBaseFallbackTests): + + def _getTargetClass(self): + from zope.interface.adapter import VerifyingBase + return VerifyingBase + + +class AdapterLookupBaseTests(_SilencePy3Deprecations): + + def _getTargetClass(self): + from zope.interface.adapter import AdapterLookupBase + return AdapterLookupBase + + def _makeOne(self, registry): + return self._getTargetClass()(registry) + + 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') diff --git a/src/zope/interface/tests/test_advice.py b/src/zope/interface/tests/test_advice.py index f21252e..b7e4dd0 100644 --- a/src/zope/interface/tests/test_advice.py +++ b/src/zope/interface/tests/test_advice.py @@ -1,4 +1,3 @@ - ############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. @@ -27,70 +26,71 @@ Visit the PEAK home page at http://peak.telecommunity.com for more information. """ 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): - - 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): +class FrameInfoTest(unittest.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()) - - def checkClassicClassInfo(self): - kind, module, f_locals, f_globals = ClassicClass.classLevelFrameInfo + self.assert_(d is advisory_testing.my_globals) + + 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()) - - def checkNewStyleClassInfo(self): - kind, module, f_locals, f_globals = NewStyleClass.classLevelFrameInfo + self.assert_(d is advisory_testing.my_globals) + + 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): +_FUNKY_EXEC = """\ +import sys +kind, module, f_locals, f_globals = getFrameInfo(sys._getframe()) +""" - def checkOrder(self): +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 @@ class AdviceTests(TestCase): 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 @@ class AdviceTests(TestCase): "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 test_mixed_metas(self): + from zope.interface.tests.advisory_testing import ping + class Metaclass1(type): + pass - def checkMixedMetas(self): + class Metaclass2(type): + pass - class M1(type): pass - class M2(type): pass + class Base1: + __metaclass__ = Metaclass1 - class B1: __metaclass__ = M1 - class B2: __metaclass__ = M2 + 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') diff --git a/src/zope/interface/tests/test_declarations.py b/src/zope/interface/tests/test_declarations.py index e6f2e14..5d111a6 100644 --- a/src/zope/interface/tests/test_declarations.py +++ b/src/zope/interface/tests/test_declarations.py @@ -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 A(object): - implements(I1) -class B(object): - implements(I2) -class C(A, B): - implements(I3) - -class COnly(A, B): - implementsOnly(I3) - -class COnly_old(A, B): - __implemented__ = I3 - -class D(COnly): - implements(I5) - -def test_ObjectSpecification_Simple(): - """ - >>> c = C() - >>> directlyProvides(c, I4) - >>> [i.__name__ for i in providedBy(c)] - ['I4', 'I3', 'I1', 'I2'] - """ - -def test_ObjectSpecification_Simple_w_only(): - """ - >>> c = COnly() - >>> directlyProvides(c, I4) - >>> [i.__name__ for i in providedBy(c)] - ['I4', 'I3'] - """ - -def test_ObjectSpecification_Simple_old_style(): - """ - >>> c = COnly_old() - >>> directlyProvides(c, I4) - >>> [i.__name__ for i in providedBy(c)] - ['I4', 'I3'] - """ - - -class Test(unittest.TestCase): - - # Note that most of the tests are in the doc strings of the - # declarations module. - - def failUnless(self, expr): # silence deprecation warnings under py3 - return self.assertTrue(expr) - - def failIf(self, expr): # silence deprecation warnings under py3 - return self.assertFalse(expr) - - def test_backward_compat(self): - - class C1(object): __implemented__ = I1 - class C2(C1): __implemented__ = I2, I5 - class C3(C2): __implemented__ = I3, C2.__implemented__ - - self.failUnless(C3.__implemented__.__class__ is tuple) - - self.assertEqual( - [i.getName() for i in providedBy(C3())], - ['I3', 'I2', 'I5'], - ) - - class C4(C3): - implements(I4) - - self.assertEqual( - [i.getName() for i in providedBy(C4())], - ['I4', 'I3', 'I2', 'I5'], - ) - - self.assertEqual( - [i.getName() for i in C4.__implemented__], - ['I4', 'I3', 'I2', 'I5'], - ) - - # 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_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_builtins(self): - # Setup - - intspec = implementedBy(int) - olddeclared = intspec.declared - - classImplements(int, I1) - class myint(int): - implements(I2) - - x = 42 - self.assertEqual([i.getName() for i in providedBy(x)], - ['I1']) - - x = myint(42) - directlyProvides(x, I3) - self.assertEqual([i.getName() for i in providedBy(x)], - ['I3', 'I2', 'I1']) - - # cleanup - intspec.declared = olddeclared - classImplements(int) - - x = 42 - self.assertEqual([i.getName() for i in providedBy(x)], - []) - - -def test_signature_w_no_class_interfaces(): - """ - >>> from zope.interface import * - >>> class C(object): - ... pass - >>> c = C() - >>> list(providedBy(c)) - [] - - >>> 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 - - >>> 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() - - This failed due to a bug in the code for finding __providedBy__ - descriptors for old-style classes. - - """ - -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_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_that_we_dont_inherit_provides_optimizations(): - """ - - 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: - - >>> class A(object): - ... implements(I1) - - >>> class B(object): - ... implements(I2) - - >>> [i.__name__ for i in A().__provides__] - ['I1'] - >>> [i.__name__ for i in B().__provides__] - ['I2'] - - But it's important that we don't use this for subclasses without - declarations. This would cause incorrect results: - - >>> class X(A, B): - ... pass - - >>> X().__provides__ - Traceback (most recent call last): - ... - AttributeError: __provides__ - - However, if we "induce" a declaration, by calling implementedBy - (even indirectly through providedBy): - - >>> [i.__name__ for i in providedBy(X())] - ['I1', 'I2'] - - - then the optimization will work: - - >>> [i.__name__ for i in X().__provides__] - ['I1', 'I2'] - - """ - -def test_classProvides_before_implements(): - """Special descriptor for class __provides__ - - The descriptor caches the implementedBy info, so that - we can get declarations for objects without instance-specific - interfaces a bit quicker. - - 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'] - - >>> [i.getName() for i in C().__provides__] - ['IFoo'] - """ - -def test_getting_spec_for_proxied_builtin_class(): - """ - - In general, we should be able to get a spec - for a proxied class if someone has declared or - asked for a spec before. - - 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: - - >>> cls = object() - - We'll create an implements specification: - - >>> import zope.interface.declarations - >>> impl = zope.interface.declarations.Implements(I1, I2) - - Now, we'll emulate a declaration for a built-in type by putting - it in BuiltinImplementationSpecifications: - - >>> zope.interface.declarations.BuiltinImplementationSpecifications[ - ... cls] = impl - - Now, we should be able to get it back: - - >>> implementedBy(cls) is impl - True - - Of course, we don't want to leave it there. :) - - >>> del zope.interface.declarations.BuiltinImplementationSpecifications[ - ... cls] - - """ -def test_declaration_get(): - """ - We can get definitions from a declaration: +class _SilencePy3Deprecations(unittest.TestCase): + # silence deprecation warnings under py3 - >>> 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') - - >>> 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: - - >>> decl = zope.interface.Declaration() - >>> decl.get('a11') - >>> decl.get('a11', 42) - 42 - - We get new data if e change interface bases: - - >>> decl.__bases__ = I11, I2 - >>> decl.get('a11') is I11.get('a11') - True - """ - -def test_classImplements_after_classImplementsOnly_issue_402(): - """http://www.zope.org/Collectors/Zope3-dev/402 - ->>> from zope.interface import * ->>> class I1(Interface): -... pass ->>> class I2(Interface): -... pass ->>> class C: -... implements(I1) ->>> class C2: -... implementsOnly(I2) ->>> class I3(Interface): -... pass - ->>> [i.__name__ for i in providedBy(C2()).__iro__] -['I2', 'Interface'] - ->>> 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'] - - -""" - -def test_picklability_of_implements_specifications(): - """ - - Sometimes, we need to pickle implements specs. We should be able - to do so as long as the class is picklable. - - >>> import pickle - >>> pickle.loads(pickle.dumps(implementedBy(C))) is implementedBy(C) - True - - - """ - -def test_provided_by_with_slots(): - """ - - 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.) + def failUnless(self, expr): + # St00pid speling. + return self.assertTrue(expr) - >>> import zope.interface - >>> class Slotted(object): - ... __slots__ = ('__provides__') - >>> class IFoo(zope.interface.Interface): - ... pass - >>> IFoo.providedBy(Slotted) - False + def failIf(self, expr): + # St00pid speling. + return self.assertFalse(expr) + + +class DeclarationTests(_SilencePy3Deprecations): + + def _getTargetClass(self): + from zope.interface.declarations import Declaration + return Declaration + + 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_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_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__) + + 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__) + + def test___contains__w_self(self): + from zope.interface.interface import InterfaceClass + IFoo = InterfaceClass('IFoo') + decl = self._makeOne() + self.failIf(decl in decl) + + 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 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___iter___empty(self): + decl = self._makeOne() + self.assertEqual(list(decl), []) + + def test___iter___single_base(self): + from zope.interface.interface import InterfaceClass + IFoo = InterfaceClass('IFoo') + decl = self._makeOne(IFoo) + self.assertEqual(list(decl), [IFoo]) + + 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]) + + 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 + + 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]) + + def test_flattened_empty(self): + from zope.interface.interface import Interface + decl = self._makeOne() + self.assertEqual(list(decl.flattened()), [Interface]) + + 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]) + + 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_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_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]) + + 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]) + + 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), []) + + 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), []) + + 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]) + + 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]) + + +class ImplementsTests(_SilencePy3Deprecations): + + def _getTargetClass(self): + from zope.interface.declarations import Implements + return Implements + + 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 Test_implementedByFallback(_SilencePy3Deprecations): + + def _callFUT(self, *args, **kw): + from zope.interface.declarations import implementedByFallback + return implementedByFallback(*args, **kw) + + 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_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_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_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__) + + 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) + + def test_oldstyle_class_no_assertions(self): + # TODO: Figure out P3 story + class Foo: + pass + self.assertEqual(list(self._callFUT(Foo)), []) + + def test_no_assertions(self): + # TODO: Figure out P3 story + class Foo(object): + pass + self.assertEqual(list(self._callFUT(Foo)), []) + + def test_w_None_no_bases_not_factory(self): + class Foo(object): + __implemented__ = None + foo = Foo() + self.assertRaises(TypeError, self._callFUT, foo) + + 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__) + + 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__) + + 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) + + +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) + + +class Test_classImplementsOnly(_SilencePy3Deprecations): + + def _callFUT(self, *args, **kw): + from zope.interface.declarations import classImplementsOnly + return classImplementsOnly(*args, **kw) + + 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__) + + 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,)) + + +class Test_classImplements(_SilencePy3Deprecations): + + def _callFUT(self, *args, **kw): + from zope.interface.declarations import classImplements + return classImplements(*args, **kw) + + 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__) + + 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,)) + + 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)) + + +class Test__implements_advice(_SilencePy3Deprecations): + + def _callFUT(self, *args, **kw): + from zope.interface.declarations import _implements_advice + return _implements_advice(*args, **kw) + + 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]) + + +class Test_implementer(_SilencePy3Deprecations): + + def _getTargetClass(self): + from zope.interface.declarations import implementer + return implementer + + def _makeOne(self, *args, **kw): + return self._getTargetClass()(*args, **kw) + + 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_nonclass_cannot_assign_attr(self): + from zope.interface.interface import InterfaceClass + IFoo = InterfaceClass('IFoo') + decorator = self._makeOne(IFoo) + self.assertRaises(TypeError, decorator, object()) + + 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) + + +class Test_implementer_only(_SilencePy3Deprecations): + + def _getTargetClass(self): + from zope.interface.declarations import implementer_only + return implementer_only + + def _makeOne(self, *args, **kw): + return self._getTargetClass()(*args, **kw) + + 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_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) + + 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) + + 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) + + +# 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_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]) + +class Test_implements(_SilencePy3Deprecations): + + 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_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]) + + +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), )) diff --git a/src/zope/interface/tests/test_document.py b/src/zope/interface/tests/test_document.py index a2653b3..6a1b0b2 100644 --- a/src/zope/interface/tests/test_document.py +++ b/src/zope/interface/tests/test_document.py @@ -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) + + 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 + + self.assertEqual(self._callFUT(IHasMethod), EXPECTED) + + 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. + """ + + self.assertEqual(self._callFUT(IHasMethod), EXPECTED) + + 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 _I1(Interface): - def f11(): pass - def f12(): pass + class IDerived(IBase): + "IDerived doc" + attr1 = Attribute('attr1') + attr2 = Attribute('attr2', 'attr2 doc') -class I2(_I1): - "I2 doc" + def method3(): + "method3 doc" + def method4(): + pass + def method5(): + "method5 doc" - a1 = Attribute('a1') - a2 = Attribute('a2', 'a2 doc') + self.assertEqual(self._callFUT(IDerived), EXPECTED) - def f21(): "f21 doc" - def f22(): pass - def f23(): "f23 doc" +class Test__justify_and_indent(unittest.TestCase): -if __name__=='__main__': - main(defaultTest='test_suite') + 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), + )) diff --git a/src/zope/interface/tests/test_exceptions.py b/src/zope/interface/tests/test_exceptions.py new file mode 100644 index 0000000..94009f6 --- /dev/null +++ b/src/zope/interface/tests/test_exceptions.py @@ -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 ') + diff --git a/src/zope/interface/tests/test_interface.py b/src/zope/interface/tests/test_interface.py index 78398a1..458c011 100644 --- a/src/zope/interface/tests/test_interface.py +++ b/src/zope/interface/tests/test_interface.py @@ -13,316 +13,1597 @@ ############################################################################## """Test Interface implementation """ -from __future__ import with_statement - -import doctest import unittest -import sys -class InterfaceTests(unittest.TestCase): +_marker = object() + +class _SilencePy3Deprecations(unittest.TestCase): + # silence deprecation warnings under py3 - def failUnless(self, expr): # 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") + + self.failUnless(I1['attr'].interface is I1) + + def test_methods_link_to_interface(self): + from zope.interface import Interface - def f11(): + 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 IOther(Interface): + pass + + 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)) - class _I1_(_I1): + 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() + + 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 - class _I1__(_I1_): + class IDerived(IBase): pass - class _I2(_I1__): - def f21(): + class Current(object): + __implemented__ = IDerived + def method(self): pass - def f22(): + + current = Current() + + 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 test_classImplements_multiple(self): + from zope.interface import Interface + from zope.interface import implementedBy + from zope.interface import providedBy + + class ILeft(Interface): + def method(): + pass + + class IRight(ILeft): + pass + + class Left(object): + __implemented__ = ILeft + + def method(self): pass - f23 = f22 - - return _I2 - - def testInterfaceSetOnAttributes(self): - from zope.interface.tests.unitfixtures import FooInterface - self.assertEqual(FooInterface['foobar'].interface, - FooInterface) - self.assertEqual(FooInterface['aMethod'].interface, - FooInterface) - - 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)) - - 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)) - - self.failUnless(not I2.implementedBy(A)) - self.failUnless(I2.implementedBy(B)) - self.failUnless(not I2.implementedBy(C)) - - # No longer after interfacegeddon - # self.failUnless(not I2.implementedBy(D)) - - self.failUnless(not I2.implementedBy(E)) - - 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())) - - - 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())) - - 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())) - - self.failUnless(not I2.providedBy(A())) - self.failUnless(I2.providedBy(B())) - self.failUnless(not I2.providedBy(C())) - - # Not after interface geddon - # self.failUnless(not I2.providedBy(D())) - - self.failUnless(not I2.providedBy(E())) - - def testDeferredClass(self): - from zope.interface.tests.unitfixtures import A + + class ILeft(Interface): + + def method(): + pass + + class IRight(ILeft): + pass + + class IOther(Interface): + pass + + class Left(): + __implemented__ = ILeft + + def method(self): + pass + + class Right(object): + __implemented__ = IRight + + 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)) - - 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']) - - 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']) - - for name, d in iface.namesAndDescriptions(1): - self.assertEqual(name, d.__name__) - - 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 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') - - def test___contains__(self): - iface = self._makeDerivedInterface() - self.failUnless('f11' in iface) - self.failIf('f33' in iface) + from zope.interface.verify import verifyObject - def test___iter__(self): - iface = self._makeDerivedInterface() - names = list(iter(iface)) - names.sort() - self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23']) + class ICheckMe(Interface): + attr = Attribute(u'My attr') + + def method(): + pass + + class CheckMe(object): + __implemented__ = ICheckMe + attr = 'value' + + def method(self): + pass + + check_me = CheckMe() + + self.failUnless(verifyObject(ICheckMe, check_me)) - def testAttr(self): - iface = self._makeDerivedInterface() - description = iface.getDescriptionFor('a1') - self.assertEqual(description.__name__, 'a1') - self.assertEqual(description.__doc__, 'This is an attribute') + def test_interface_object_provides_Interface(self): + from zope.interface import Interface + + class AnInterface(Interface): + pass + + self.assert_(Interface.providedBy(AnInterface)) - def testFunctionAttributes(self): - # Make sure function attributes become tagged values. + 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 @@ class InterfaceTests(unittest.TestCase): 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 - - 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_hash_normal(self): - from zope.interface.tests.ifoo import IFoo - self.assertEqual(hash(IFoo), - hash((('IFoo', 'zope.interface.tests.ifoo')))) - - def test_hash_missing_required_attrs(self): - import warnings - try: - from warnings import catch_warnings - except ImportError: # Python 2.5 - return - 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') + c = C() + self.assertRaises(TypeError, I, c) + + def test___call___miss_w_alternate(self): + from zope.interface import Interface + + class I(Interface): + pass + + class C(object): + pass + c = C() + self.assert_(I(c, self) is self) -if sys.version_info >= (2, 4): + def test___call___w_adapter_hook(self): + from zope.interface import Interface + from zope.interface.interface import adapter_hooks + old_hooks = adapter_hooks[:] - def test_invariant_as_decorator(): - """Invaiants can be deined in line + def _miss(iface, obj): + pass - >>> 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 _hit(iface, obj): + return self + adapter_hooks[:] = [_miss, _hit] - >>> class Range(object): - ... implements(IRange) - ... - ... def __init__(self, min, max): - ... self.min, self.max = min, max + class I(Interface): + pass + + class C(object): + pass - >>> 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' + c = C() + self.assert_(I(c) is self) - """ +class AttributeTests(ElementTests): + DEFAULT_NAME = 'TestAttribute' -def test_description_cache_management(): - """ See https://bugs.launchpad.net/zope.interface/+bug/185974 + def _getTargetClass(self): + from zope.interface.interface import Attribute + return Attribute -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 MethodTests(AttributeTests): - >>> class I2(I1): - ... pass + DEFAULT_NAME = 'TestMethod' - >>> class I3(I2): - ... pass + def _getTargetClass(self): + from zope.interface.interface import Method + return Method - >>> I3.get('a') is I1.get('a') - True - >>> I2.__bases__ = (Interface,) - >>> I3.get('a') is None - True - """ + 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: + 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 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') + + 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_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) + + 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) + + 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') + + 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_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) + + 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') + +class DummyDependent(object): + + def __init__(self): + self._changed = [] + + def changed(self, originally_changed): + self._changed.append(originally_changed) + + +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"), + )) diff --git a/src/zope/interface/tests/test_interfaces.py b/src/zope/interface/tests/test_interfaces.py new file mode 100644 index 0000000..7bc5807 --- /dev/null +++ b/src/zope/interface/tests/test_interfaces.py @@ -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), + )) diff --git a/src/zope/interface/tests/test_odd_declarations.py b/src/zope/interface/tests/test_odd_declarations.py index cbafa22..e8ebe47 100644 --- a/src/zope/interface/tests/test_odd_declarations.py +++ b/src/zope/interface/tests/test_odd_declarations.py @@ -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 @@ class Test(unittest.TestCase): 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 @@ class Test(unittest.TestCase): 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() diff --git a/src/zope/interface/tests/test_registry.py b/src/zope/interface/tests/test_registry.py index a151001..e132e77 100644 --- a/src/zope/interface/tests/test_registry.py +++ b/src/zope/interface/tests/test_registry.py @@ -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 - -import sys - -# fixtures - -if sys.version_info[0] == 3: - _class_types = type -else: - _class_types = (type, types.ClassType) - -class adapter: - - def __init__(self, *interfaces): - self.interfaces = interfaces - - def __call__(self, ob): - if isinstance(ob, _class_types): - ob.__component_adapts__ = _adapts_descr(self.interfaces) - else: - ob.__component_adapts__ = self.interfaces - - return ob - - -def adapts(*interfaces): - frame = sys._getframe(1) - locals = frame.f_locals - - # Try to make sure we were called from a class def. In 2.2.0 we can't - # check for __module__ since it doesn't seem to be added to the locals - # until later on. - if (locals is frame.f_globals) or ( - ('__module__' not in locals) and sys.version_info[:3] > (2, 2, 0)): - raise TypeError("adapts can be used only from a class definition.") - - if '__component_adapts__' in locals: - raise TypeError("adapts can be used only once in a class definition.") - - locals['__component_adapts__'] = _adapts_descr(interfaces) - -class _adapts_descr(object): - def __init__(self, interfaces): - self.interfaces = interfaces - - def __get__(self, inst, cls): - if inst is None: - return self.interfaces - raise AttributeError('__component_adapts__') - -class I1(interface.Interface): - pass -class I2(interface.Interface): - pass -class I2e(I2): - pass -class I3(interface.Interface): - pass -class IC(interface.Interface): - pass - -class ITestType(interface.interfaces.IInterface): - pass - -class U: - - def __init__(self, name): - self.__name__ = name - - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, self.__name__) - -class U1(U): - interface.implements(I1) - -class U12(U): - interface.implements(I1, I2) - -class IA1(interface.Interface): - pass - -class IA2(interface.Interface): - pass - -class IA3(interface.Interface): - pass - -class A: - - def __init__(self, *context): - self.context = context - - def __repr__(self): - return "%s%r" % (self.__class__.__name__, self.context) - -class A12_1(A): - adapts(I1, I2) - interface.implements(IA1) - -class A12_(A): - adapts(I1, I2) - -class A_2(A): - interface.implements(IA2) - -class A_3(A): - interface.implements(IA3) - -class A1_12(U): - adapts(I1) - interface.implements(IA1, IA2) - -class A1_2(U): - adapts(I1) - interface.implements(IA2) - -class A1_23(U): - adapts(I1) - interface.implements(IA1, IA3) - -def noop(*args): - pass - - -# tests - -class TestAdapter(unittest.TestCase): - - def setUp(self): - self.components = Components('comps') - - def test_register_and_unregister_adapter(self): - self.components.registerAdapter(A12_1) - - 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))') - - self.assertTrue(self.components.unregisterAdapter(A12_1)) - self.assertRaises( - ComponentLookupError, - self.components.getMultiAdapter, - (U1(1), U12(2)), - IA1 - ) - - 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) +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 ComponentsTests(_SilencePy3Deprecations): + + def _getTargetClass(self): + from zope.interface.registry import Components + return Components + + def _makeOne(self, name='test', *args, **kw): + return self._getTargetClass()(name, *args, **kw) + + 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 + + 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 test___repr__(self): + comp = self._makeOne('testing') + self.assertEqual(repr(comp), '<Components testing>') + + # test _init_registries / _init_registrations via only caller, __init__. + + 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)) + + 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) + + 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 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) + + 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) + + 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) + + 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 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 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,)) + + 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) + + def test_unregisterUtility_neither_factory_nor_component_nor_provided(self): + comp = self._makeOne() + self.assertRaises(TypeError, comp.unregisterUtility, + component=None, provided=None, factory=None) + + 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) + + 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) + + 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) + + 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 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 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) + + 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,)) + + def test_registeredUtilities_empty(self): + comp = self._makeOne() + self.assertEqual(list(comp.registeredUtilities()), []) + + 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) + + 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) - 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_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) + + 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) + + 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) - self.assertRaises(TypeError, self.components.unregisterAdapter, A1_12) - self.assertTrue(self.components.unregisterAdapter(A1_12, provided=IA2)) + 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)), []) + + 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)]) + + 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 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_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) + + 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) + + 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_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) + + 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) + + 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_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) + + 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) + + 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_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_unregisterAdapter_neither_factory_nor_provided(self): + comp = self._makeOne() + self.assertRaises(TypeError, comp.unregisterAdapter, + factory=None, provided=None) + + 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) + + 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) + + 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_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_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_registeredAdapters_empty(self): + comp = self._makeOne() + self.assertEqual(list(comp.registeredAdapters()), []) + + 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) + + 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) + + 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) + + 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_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, - self.components.getMultiAdapter, (U1(1),), IA2) - - def test_register_and_unregister_adapter_with_no_interfaces(self): - self.assertRaises(TypeError, self.components.registerAdapter, A12_) + comp.getAdapter, _context, ifoo) - 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))') - - 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_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_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') - - 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) - - 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]) - - 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_get_none_existing_adapter(self): + 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_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) + + 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_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)) + + 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, - self.components.getMultiAdapter, (U(1),), IA1) - - 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_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_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') - - self.assertTrue(self.components.unregisterAdapter(A12_1)) - self.assertTrue(self.components.unregisterAdapter( - required=[U], provided=IA3)) - - 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) - - 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_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))') - - 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_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) - - 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_register_no_factory(self): - self.components.registerAdapter(A1_12, provided=IA2) - self.components.registerAdapter(noop, - required=[IA1], provided=IA2, - name=u'test noop') - - 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))') - - self.assertTrue(self.components.unregisterAdapter(A1_12, provided=IA2)) - - 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) - - 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'']) - - -class TestExtending(unittest.TestCase): - - def test_extendning(self): - c1 = Components('1') - self.assertEqual(c1.__bases__, ()) - - c2 = Components('2', (c1, )) - self.assertTrue(c2.__bases__ == (c1, )) - - test_object1 = U1(1) - test_object2 = U1(2) - test_object3 = U12(1) - test_object4 = U12(3) - - self.assertEqual(len(list(c1.registeredUtilities())), 0) - self.assertEqual(len(list(c2.registeredUtilities())), 0) - - 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) - - - 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) - - 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) - -class TestHandler(unittest.TestCase): - - def setUp(self): - self.components = Components('comps') - - def test_register_handler(self): - test_object1 = U1(1) - test_object2 = U12(2) - - @adapter(I1) - def handle1(x): - self.assertEqual(x, test_object1) - - self.components.registerHandler(handle1, info=u'First handler') - self.components.handle(test_object1) - - @adapter(I1, I2) - def handle12(x, y): - self.assertEqual(x, test_object1) - self.assertEqual(y, test_object2) - - self.components.registerHandler(handle12) - self.components.handle(test_object1, test_object2) - - def test_register_noncompliant_handler(self): - handle_calls = [] - def handle(*objects): - handle_calls.append(objects) - - 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') - - 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_list_handlers(self): - test_object1 = U1(1) - test_object2 = U12(2) - - @adapter(I1) - def handle1(x): - self.assertEqual(x, test_object1) - - @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) - - 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) - - 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 test_unregister_handler(self): - test_object1 = U1(1) - test_object2 = U12(2) - - @adapter(I1) - def handle1(x): - self.assertEqual(x, test_object1) - - @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) - - 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') - - 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_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. - - """ - from zope import interface - - calls = [] - - class I(interface.Interface): - pass - - def factory1(event): - calls.append(2) - - def factory2(event): - calls.append(3) - - class Event(object): - interface.implements(I) - - 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) - -class TestSubscriber(unittest.TestCase): - - def setUp(self): - self.components = Components('comps') - - 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_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_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_register_no_factory(self): - self.components.registerSubscriptionAdapter(noop, [I1], IA2) - subscribers = self.components.subscribers((U1(1),), IA2) - self.assertEqual(len(subscribers), 0) - - 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) - - 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) - - 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_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_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) - - 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) + comp.getMultiAdapter, (_context1, _context2), ifoo) - 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) - - 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 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 test_unregister_nonexistent_subscriber(self): - self.assertFalse( - self.components.unregisterSubscriptionAdapter(required=[I1], - provided=IA2)) - -class TestUtility(unittest.TestCase): - - def setUp(self): - self.components = Components('comps') - - def test_register_utility(self): - test_object = U1(1) - self.components.registerUtility(test_object) - self.assertEqual(self.components.getUtility(I1), test_object) - - 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_register_utility_with_component_and_factory(self): - def factory(): - return U1(1) - self.assertRaises( - TypeError, - self.components.registerUtility, U1(1), factory=factory) - - 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_register_utility_with_no_interfaces(self): - self.assertRaises(TypeError, self.components.registerUtility, A) - - def test_register_utility_with_two_interfaces(self): - self.assertRaises(TypeError, self.components.registerUtility, U12(1)) - - 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_get_none_existing_utility(self): - from zope.interface.interfaces import ComponentLookupError - self.assertRaises(ComponentLookupError, self.components.getUtility, I3) - - 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_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) - - 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) - - self.assertEqual(len(sorted_utilities), 3) - self.assertEqual(sorted_utilities_name, [u'', u'', u'name']) + 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)) + + 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( - sorted_utilities_component, - [test_object1, test_object2, test_object3]) - self.assertEqual(sorted_utilities_provided, [I1, I2, I2]) - - 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) - - self.components.registerUtility(test_object4, info=u'use 4 now') - self.assertEqual(self.components.getUtility(I1), test_object4) - - 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_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_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') - - 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_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) - - 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)) - - 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) - - self.assertTrue(self.components.unregisterUtility(test_object4, I2e)) - self.assertEqual(self.components.getAllUtilitiesRegisteredFor(I2e), []) - - def test_utility_events(self): - from zope.event import subscribers - old_subscribers = subscribers[:] - subscribers[:] = [] - - 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 - - def test_dont_leak_utility_registrations_in__subscribers(self): - """ - We've observed utilities getting left in _subscribers when they - get unregistered. - - """ - class C: - def __init__(self, name): - self.name = name - def __repr__(self): - return "C(%s)" % self.name - - c1 = C(1) - c2 = C(2) - - 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) - - 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) - - utilities = list(self.components.getAllUtilitiesRegisteredFor(I1)) - self.assertEqual(len(utilities), 1) - self.assertEqual(utilities[0], c2) - - -class TestExtending(unittest.TestCase): - - def test_extendning(self): - c1 = Components('1') - self.assertEqual(c1.__bases__, ()) - - c2 = Components('2', (c1, )) - self.assertTrue(c2.__bases__ == (c1, )) - - test_object1 = U1(1) - test_object2 = U1(2) - test_object3 = U12(1) - test_object4 = U12(3) - - self.assertEqual(len(list(c1.registeredUtilities())), 0) - self.assertEqual(len(list(c2.registeredUtilities())), 0) - - 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) - - - 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) + list(comp.getAdapters((_context1, _context2), ifoo)), []) - c3.registerUtility(test_object4, I2) - self.assertEqual(c4.queryUtility(I2), test_object4) + 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) + + 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_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) + + 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) + + 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) + + def test_registeredSubscriptionAdapters_empty(self): + comp = self._makeOne() + self.assertEqual(list(comp.registeredSubscriptionAdapters()), []) + + 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) + + 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) + + 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) + + 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) + + 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 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) + + 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) + + 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) + + 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)), []) + + 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)) + + 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 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_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) + + def test_registeredHandlers_empty(self): + from zope.interface.declarations import InterfaceClass + class IFoo(InterfaceClass): + pass + comp = self._makeOne() + self.failIf(list(comp.registeredHandlers())) - @adapter(I1) - def handle1(x): - self.assertEqual(x, 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) + + 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) - def handle(*objects): - self.assertEqual(objects, (test_object1,)) + 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_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) + + 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) + + 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_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 + + 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]) + + +# Test _getUtilityProvided, _getAdapterProvided, _getAdapterRequired via their +# callers (Component.registerUtility, Component.registerAdapter). + + +class UtilityRegistrationTests(unittest.TestCase): + + def _getTargetClass(self): + from zope.interface.registry import UtilityRegistration + return UtilityRegistration + + 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, + ) + + def test_class_conforms_to_IUtilityRegistration(self): + from zope.interface.verify import verifyClass + from zope.interface.interfaces import IUtilityRegistration + verifyClass(IUtilityRegistration, self._getTargetClass()) + + 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) + + 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)) + + 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)) + + 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___hash__(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + self.assertEqual(hash(ur), id(ur)) + + def test___eq___identity(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + self.failUnless(ur == ur) + + def test___eq___hit(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + ur2, _, _ = self._makeOne(_component) + self.failUnless(ur == ur2) + + def test___eq___miss(self): + _component = object() + _component2 = object() + ur, _registry, _name = self._makeOne(_component) + ur2, _, _ = self._makeOne(_component2) + self.failIf(ur == ur2) + + def test___ne___identity(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + self.failIf(ur != ur) + + def test___ne___hit(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + ur2, _, _ = self._makeOne(_component) + self.failIf(ur != ur2) + + def test___ne___miss(self): + _component = object() + _component2 = object() + ur, _registry, _name = self._makeOne(_component) + ur2, _, _ = self._makeOne(_component2) + self.failUnless(ur != ur2) + + def test___lt___identity(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + self.failIf(ur < ur) + + def test___lt___hit(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + ur2, _, _ = self._makeOne(_component) + self.failIf(ur < ur2) + + 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___le___identity(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + self.failUnless(ur <= ur) + + def test___le___hit(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + ur2, _, _ = self._makeOne(_component) + self.failUnless(ur <= ur2) + + 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___gt___identity(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + self.failIf(ur > ur) + + 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) + + def test___gt___miss(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + ur2, _, _ = self._makeOne(_component) + self.failIf(ur2 > ur) + + def test___ge___identity(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + self.failUnless(ur >= ur) + + 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___ge___hit(self): + _component = object() + ur, _registry, _name = self._makeOne(_component) + ur2, _, _ = self._makeOne(_component) + ur2.name = _name + '2' + self.failUnless(ur2 >= ur) + + +class AdapterRegistrationTests(unittest.TestCase): + + def _getTargetClass(self): + from zope.interface.registry import AdapterRegistration + return AdapterRegistration + + 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_class_conforms_to_IAdapterRegistration(self): + from zope.interface.verify import verifyClass + from zope.interface.interfaces import IAdapterRegistration + verifyClass(IAdapterRegistration, self._getTargetClass()) + + 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 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___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___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___hash__(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + self.assertEqual(hash(ar), id(ar)) + + def test___eq___identity(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + self.failUnless(ar == ar) + + def test___eq___hit(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + ar2, _, _ = self._makeOne(_component) + self.failUnless(ar == ar2) + + 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___ne___identity(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + self.failIf(ar != ar) + + def test___ne___miss(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + ar2, _, _ = self._makeOne(_component) + self.failIf(ar != ar2) + + 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___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) + + 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) + + def test___lt___identity(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + self.failIf(ar < ar) + + def test___lt___hit(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + ar2, _, _ = self._makeOne(_component) + self.failIf(ar < ar2) + + 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___le___identity(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + self.failUnless(ar <= ar) + + def test___le___hit(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + ar2, _, _ = self._makeOne(_component) + self.failUnless(ar <= ar2) + + 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) + + def test___gt___identity(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + self.failIf(ar > ar) + + 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) + + def test___gt___miss(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + ar2, _, _ = self._makeOne(_component) + self.failIf(ar2 > ar) + + def test___ge___identity(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + self.failUnless(ar >= ar) + + 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___ge___hit(self): + _component = object() + ar, _registry, _name = self._makeOne(_component) + ar2, _, _ = self._makeOne(_component) + ar2.name = _name + '2' + self.failUnless(ar2 >= ar) + + +class SubscriptionRegistrationTests(unittest.TestCase): + + def _getTargetClass(self): + from zope.interface.registry import SubscriptionRegistration + return SubscriptionRegistration + + 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_class_conforms_to_ISubscriptionAdapterRegistration(self): + from zope.interface.verify import verifyClass + from zope.interface.interfaces import ISubscriptionAdapterRegistration + verifyClass(ISubscriptionAdapterRegistration, self._getTargetClass()) + + 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) + + +class HandlerRegistrationTests(unittest.TestCase): + + 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, + ) + + 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_instance_conforms_to_IHandlerRegistration(self): + from zope.interface.verify import verifyObject + from zope.interface.interfaces import IHandlerRegistration + hr, _, _ = self._makeOne() + verifyObject(IHandlerRegistration, hr) + + 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) + + 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)) + + 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)) - @adapter(I1) - def handle3(x): - self.assertEqual(x, test_object1) - @adapter(I1) - def handle4(x): - self.assertEqual(x, test_object1) +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) - c1.registerHandler(handle1, info=u'First handler') - c2.registerHandler(handle, required=[U]) - c3.registerHandler(handle3) - c4.registerHandler(handle4) + def __enter__(self): + return self - c4.handle(test_object1) + 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(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), )) diff --git a/src/zope/interface/tests/test_verify.py b/src/zope/interface/tests/test_verify.py index 1e2282f..5585f43 100644 --- a/src/zope/interface/tests/test_verify.py +++ b/src/zope/interface/tests/test_verify.py @@ -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 + + class Current(object): + pass + + self.assertRaises(DoesNotImplement, self._callFUT, ICurrent, Current) + + def test_class_doesnt_implement_but_classImplements_later(self): + from zope.interface import Interface + from zope.interface import classImplements + + class ICurrent(Interface): + pass + + class Current(object): + pass - self.assertRaises(DoesNotImplement, verifyClass, I, C) + classImplements(Current, ICurrent) - classImplements(C, I) + self._callFUT(ICurrent, Current) - verifyClass(I, C) + 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 - def testMissingAttr(self): + class ICurrent(Interface): + def method(): pass - class I(Interface): - def f(): pass + class Current(object): + implements(ICurrent) - class C(object): - implements(I) + self.assertRaises(BrokenImplementation, + self._callFUT, ICurrent, Current) - self.assertRaises(BrokenImplementation, verifyClass, I, C) + def test_class_has_required_method_simple(self): + from zope.interface import Interface + from zope.interface import implements - C.f=lambda self: None + class ICurrent(Interface): + def method(): pass - verifyClass(I, C) + class Current(object): + implements(ICurrent) - def testMissingAttr_with_Extended_Interface(self): + def method(self): + pass + + 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 II(Interface): - def f(): + class IBase(Interface): + def method(): pass - class I(II): + 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 + + class ICurrent(Interface): + + def method(a): + pass - C.f=lambda self, a: None + class Current(object): + implements(ICurrent) - verifyClass(I, C) + def method(self, b): + pass + + self._callFUT(ICurrent, Current) - C.f=lambda self, **kw: None + def test_method_takes_not_enough_args(self): + from zope.interface import Interface + from zope.interface import implements + from zope.interface.exceptions import BrokenMethodImplementation - self.assertRaises(BrokenMethodImplementation, verifyClass, I, C) + class ICurrent(Interface): - C.f=lambda self, a, *args: None + def method(a): + pass - verifyClass(I, C) + class Current(object): + implements(ICurrent) + + def method(self): + pass - C.f=lambda self, a, *args, **kw: None + self.assertRaises(BrokenMethodImplementation, + self._callFUT, ICurrent, Current) - verifyClass(I, C) + def test_method_doesnt_take_required_starargs(self): + from zope.interface import Interface + from zope.interface import implements + from zope.interface.exceptions import BrokenMethodImplementation - C.f=lambda self, *args: None + class ICurrent(Interface): - verifyClass(I, C) + def method(*args): + pass + + class Current(object): + implements(ICurrent) + + 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_only_kwargs(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(**kw): + 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_takes_extra_arg(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(a): + 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, a, b): + pass - implements(I) + self.assertRaises(BrokenMethodImplementation, + self._callFUT, ICurrent, Current) - self.assertRaises(BrokenMethodImplementation, verifyClass, I, C) + def test_method_takes_extra_arg_with_default(self): + from zope.interface import Interface + from zope.interface import implements - 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=None): + pass - class C(object): - def f(self, a): pass + self._callFUT(ICurrent, Current) - implements(I) + def test_method_takes_only_positional_args(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, *args): + pass - from zope.interface.tests.ifoo import IFoo - from zope.interface.tests import dummy + self._callFUT(ICurrent, Current) + + def test_method_takes_only_kwargs(self): + from zope.interface import Interface + from zope.interface import implements + from zope.interface.exceptions import BrokenMethodImplementation + + class ICurrent(Interface): + + def method(a): + pass + + class Current(object): + implements(ICurrent) + + 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) - verifyObject(IFoo, dummy) + 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 - def testMethodForAttr(self): - - class IFoo(Interface): - foo = Attribute("The foo Attribute") + self.assertRaises(BrokenMethodImplementation, + self._callFUT, ICurrent, Current) - class Foo: - implements(IFoo) + def test_method_doesnt_take_required_kwargs(self): + from zope.interface import Interface + from zope.interface import implements + from zope.interface.exceptions import BrokenMethodImplementation - def foo(self): - pass + class ICurrent(Interface): - verifyClass(IFoo, Foo) + def method(**kwargs): + pass + + class Current(object): + implements(ICurrent) + + def method(self, a): + pass + + self.assertRaises(BrokenMethodImplementation, + self._callFUT, ICurrent, Current) - def testNonMethodForMethod(self): - class IBar(Interface): - def foo(): - pass + 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 - class Bar: - implements(IBar) + 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 - foo = 1 + self.assertRaises(DoesNotImplement, + self._callFUT, IDummyModule, dummy) - self.assertRaises(BrokenMethodImplementation, verifyClass, IBar, Bar) - +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), + )) diff --git a/src/zope/interface/tests/unitfixtures.py b/src/zope/interface/tests/unitfixtures.py deleted file mode 100644 index c47eaf0..0000000 --- a/src/zope/interface/tests/unitfixtures.py +++ /dev/null @@ -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 diff --git a/src/zope/interface/verify.py b/src/zope/interface/verify.py index da60b6e..0c9369c 100644 --- a/src/zope/interface/verify.py +++ b/src/zope/interface/verify.py @@ -68,7 +68,8 @@ def _verify(iface, candidate, tentative=0, vtype=None): 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 @@ def _verify(iface, candidate, tentative=0, vtype=None): 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. |
