zope.interface-4.3.2/ 0000775 0001750 0001750 00000000000 12763206175 013477 5 ustar mg mg 0000000 0000000 zope.interface-4.3.2/PKG-INFO 0000664 0001750 0001750 00000045340 12763206175 014602 0 ustar mg mg 0000000 0000000 Metadata-Version: 1.1
Name: zope.interface
Version: 4.3.2
Summary: Interfaces for Python
Home-page: https://github.com/zopefoundation/zope.interface
Author: Zope Foundation and Contributors
Author-email: zope-dev@zope.org
License: ZPL 2.1
Description: ``zope.interface``
==================
.. image:: https://img.shields.io/pypi/v/zope.interface.svg
:target: https://pypi.python.org/pypi/zope.interface/
:alt: Latest Version
.. image:: https://travis-ci.org/zopefoundation/zope.interface.png?branch=master
:target: https://travis-ci.org/zopefoundation/zope.interface
.. image:: https://readthedocs.org/projects/zopeinterface/badge/?version=latest
:target: https://zopeinterface.readthedocs.io/en/latest/
:alt: Documentation Status
This package is intended to be independently reusable in any Python
project. It is maintained by the `Zope Toolkit project
`_.
This package provides an implementation of "object interfaces" for Python.
Interfaces are a mechanism for labeling objects as conforming to a given
API or contract. So, this package can be considered as implementation of
the `Design By Contract`_ methodology support in Python.
.. _Design By Contract: http://en.wikipedia.org/wiki/Design_by_contract
For detailed documentation, please see https://zopeinterface.readthedocs.io/en/latest/
Changes
=======
4.3.2 (2016-09-05)
------------------
- Fix equality testing of ``implementedBy`` objects and proxies.
(https://github.com/zopefoundation/zope.interface/issues/55)
4.3.1 (2016-08-31)
------------------
- Support Components subclasses that are not hashable.
(https://github.com/zopefoundation/zope.interface/issues/53)
4.3.0 (2016-08-31)
------------------
- Add the ability to sort the objects returned by ``implementedBy``.
This is compatible with the way interface classes sort so they can
be used together in ordered containers like BTrees.
(https://github.com/zopefoundation/zope.interface/issues/42)
- Make ``setuptools`` a hard dependency of ``setup.py``.
(https://github.com/zopefoundation/zope.interface/issues/13)
- Change a linear algorithm (O(n)) in ``Components.registerUtility`` and
``Components.unregisterUtility`` into a dictionary lookup (O(1)) for
hashable components. This substantially improves the time taken to
manipulate utilities in large registries at the cost of some
additional memory usage. (https://github.com/zopefoundation/zope.interface/issues/46)
4.2.0 (2016-06-10)
------------------
- Add support for Python 3.5
- Drop support for Python 2.6 and 3.2.
4.1.3 (2015-10-05)
------------------
- Fix installation without a C compiler on Python 3.5
(https://github.com/zopefoundation/zope.interface/issues/24).
4.1.2 (2014-12-27)
------------------
- Add support for PyPy3.
- Remove unittest assertions deprecated in Python3.x.
- Add ``zope.interface.document.asReStructuredText``, which formats the
generated text for an interface using ReST double-backtick markers.
4.1.1 (2014-03-19)
------------------
- Add support for Python 3.4.
4.1.0 (2014-02-05)
------------------
- Update ``boostrap.py`` to version 2.2.
- Add ``@named(name)`` declaration, that specifies the component name, so it
does not have to be passed in during registration.
4.0.5 (2013-02-28)
------------------
- Fix a bug where a decorated method caused false positive failures on
``verifyClass()``.
4.0.4 (2013-02-21)
------------------
- Fix a bug that was revealed by porting zope.traversing. During a loop, the
loop body modified a weakref dict causing a ``RuntimeError`` error.
4.0.3 (2012-12-31)
------------------
- Fleshed out PyPI Trove classifiers.
4.0.2 (2012-11-21)
------------------
- Add support for Python 3.3.
- Restored ability to install the package in the absence of ``setuptools``.
- LP #1055223: Fix test which depended on dictionary order and failed randomly
in Python 3.3.
4.0.1 (2012-05-22)
------------------
- Drop explicit ``DeprecationWarnings`` for "class advice" APIS (these
APIs are still deprecated under Python 2.x, and still raise an exception
under Python 3.x, but no longer cause a warning to be emitted under
Python 2.x).
4.0.0 (2012-05-16)
------------------
- Automated build of Sphinx HTML docs and running doctest snippets via tox.
- Deprecate the "class advice" APIs from ``zope.interface.declarations``:
``implements``, ``implementsOnly``, and ``classProvides``. In their place,
prefer the equivalent class decorators: ``@implementer``,
``@implementer_only``, and ``@provider``. Code which uses the deprecated
APIs will not work as expected under Py3k.
- Remove use of '2to3' and associated fixers when installing under Py3k.
The code is now in a "compatible subset" which supports Python 2.6, 2.7,
and 3.2, including PyPy 1.8 (the version compatible with the 2.7 language
spec).
- Drop explicit support for Python 2.4 / 2.5 / 3.1.
- Add support for PyPy.
- Add support for continuous integration using ``tox`` and ``jenkins``.
- Add 'setup.py dev' alias (runs ``setup.py develop`` plus installs
``nose`` and ``coverage``).
- Add 'setup.py docs' alias (installs ``Sphinx`` and dependencies).
- Replace all unittest coverage previously accomplished via doctests with
unittests. The doctests have been moved into a ``docs`` section, managed
as a Sphinx collection.
- LP #910987: Ensure that the semantics of the ``lookup`` method of
``zope.interface.adapter.LookupBase`` are the same in both the C and
Python implementations.
- LP #900906: Avoid exceptions due to tne new ``__qualname__`` attribute
added in Python 3.3 (see PEP 3155 for rationale). Thanks to Antoine
Pitrou for the patch.
3.8.0 (2011-09-22)
------------------
- New module ``zope.interface.registry``. This is code moved from
``zope.component.registry`` which implements a basic nonperistent component
registry as ``zope.interface.registry.Components``. This class was moved
from ``zope.component`` to make porting systems (such as Pyramid) that rely
only on a basic component registry to Python 3 possible without needing to
port the entirety of the ``zope.component`` package. Backwards
compatibility import shims have been left behind in ``zope.component``, so
this change will not break any existing code.
- New ``tests_require`` dependency: ``zope.event`` to test events sent by
Components implementation. The ``zope.interface`` package does not have a
hard dependency on ``zope.event``, but if ``zope.event`` is importable, it
will send component registration events when methods of an instance of
``zope.interface.registry.Components`` are called.
- New interfaces added to support ``zope.interface.registry.Components``
addition: ``ComponentLookupError``, ``Invalid``, ``IObjectEvent``,
``ObjectEvent``, ``IComponentLookup``, ``IRegistration``,
``IUtilityRegistration``, ``IAdapterRegistration``,
``ISubscriptionAdapterRegistration``, ``IHandlerRegistration``,
``IRegistrationEvent``, ``RegistrationEvent``, ``IRegistered``,
``Registered``, ``IUnregistered``, ``Unregistered``,
``IComponentRegistry``, and ``IComponents``.
- No longer Python 2.4 compatible (tested under 2.5, 2.6, 2.7, and 3.2).
3.7.0 (2011-08-13)
------------------
- Move changes from 3.6.2 - 3.6.5 to a new 3.7.x release line.
3.6.7 (2011-08-20)
------------------
- Fix sporadic failures on x86-64 platforms in tests of rich comparisons
of interfaces.
3.6.6 (2011-08-13)
------------------
- LP #570942: Now correctly compare interfaces from different modules but
with the same names.
N.B.: This is a less intrusive / destabilizing fix than the one applied in
3.6.3: we only fix the underlying cmp-alike function, rather than adding
the other "rich comparison" functions.
- Revert to software as released with 3.6.1 for "stable" 3.6 release branch.
3.6.5 (2011-08-11)
------------------
- LP #811792: work around buggy behavior in some subclasses of
``zope.interface.interface.InterfaceClass``, which invoke ``__hash__``
before initializing ``__module__`` and ``__name__``. The workaround
returns a fixed constant hash in such cases, and issues a ``UserWarning``.
- LP #804832: Under PyPy, ``zope.interface`` should not build its C
extension. Also, prevent attempting to build it under Jython.
- Add a tox.ini for easier xplatform testing.
- Fix testing deprecation warnings issued when tested under Py3K.
3.6.4 (2011-07-04)
------------------
- LP 804951: InterfaceClass instances were unhashable under Python 3.x.
3.6.3 (2011-05-26)
------------------
- LP #570942: Now correctly compare interfaces from different modules but
with the same names.
3.6.2 (2011-05-17)
------------------
- Moved detailed documentation out-of-line from PyPI page, linking instead to
http://docs.zope.org/zope.interface .
- Fixes for small issues when running tests under Python 3.2 using
``zope.testrunner``.
- LP # 675064: Specify return value type for C optimizations module init
under Python 3: undeclared value caused warnings, and segfaults on some
64 bit architectures.
- setup.py now raises RuntimeError if you don't have Distutils installed when
running under Python 3.
3.6.1 (2010-05-03)
------------------
- A non-ASCII character in the changelog made 3.6.0 uninstallable on
Python 3 systems with another default encoding than UTF-8.
- Fix compiler warnings under GCC 4.3.3.
3.6.0 (2010-04-29)
------------------
- LP #185974: Clear the cache used by ``Specificaton.get`` inside
``Specification.changed``. Thanks to Jacob Holm for the patch.
- Add support for Python 3.1. Contributors:
Lennart Regebro
Martin v Loewis
Thomas Lotze
Wolfgang Schnerring
The 3.1 support is completely backwards compatible. However, the implements
syntax used under Python 2.X does not work under 3.X, since it depends on
how metaclasses are implemented and this has changed. Instead it now supports
a decorator syntax (also under Python 2.X)::
class Foo:
implements(IFoo)
...
can now also be written::
@implementer(IFoo):
class Foo:
...
There are 2to3 fixers available to do this change automatically in the
zope.fixers package.
- Python 2.3 is no longer supported.
3.5.4 (2009-12-23)
------------------
- Use the standard Python doctest module instead of zope.testing.doctest, which
has been deprecated.
3.5.3 (2009-12-08)
------------------
- Fix an edge case: make providedBy() work when a class has '__provides__' in
its __slots__ (see http://thread.gmane.org/gmane.comp.web.zope.devel/22490)
3.5.2 (2009-07-01)
------------------
- BaseAdapterRegistry.unregister, unsubscribe: Remove empty portions of
the data structures when something is removed. This avoids leaving
references to global objects (interfaces) that may be slated for
removal from the calling application.
3.5.1 (2009-03-18)
------------------
- verifyObject: use getattr instead of hasattr to test for object attributes
in order to let exceptions other than AttributeError raised by properties
propagate to the caller
- Add Sphinx-based documentation building to the package buildout
configuration. Use the ``bin/docs`` command after buildout.
- Improve package description a bit. Unify changelog entries formatting.
- Change package's mailing list address to zope-dev at zope.org as
zope3-dev at zope.org is now retired.
3.5.0 (2008-10-26)
------------------
- Fix declaration of _zope_interface_coptimizations, it's not a top level
package.
- Add a DocTestSuite for odd.py module, so their tests are run.
- Allow to bootstrap on Jython.
- Fix https://bugs.launchpad.net/zope3/3.3/+bug/98388: ISpecification
was missing a declaration for __iro__.
- Add optional code optimizations support, which allows the building
of C code optimizations to fail (Jython).
- Replace `_flatten` with a non-recursive implementation, effectively making
it 3x faster.
3.4.1 (2007-10-02)
------------------
- Fix a setup bug that prevented installation from source on systems
without setuptools.
3.4.0 (2007-07-19)
------------------
- Final release for 3.4.0.
3.4.0b3 (2007-05-22)
--------------------
- When checking whether an object is already registered, use identity
comparison, to allow adding registering with picky custom comparison methods.
3.3.0.1 (2007-01-03)
--------------------
- Made a reference to OverflowWarning, which disappeared in Python
2.5, conditional.
3.3.0 (2007/01/03)
------------------
New Features
++++++++++++
- Refactor the adapter-lookup algorithim to make it much simpler and faster.
Also, implement more of the adapter-lookup logic in C, making
debugging of application code easier, since there is less
infrastructre code to step through.
- Treat objects without interface declarations as if they
declared that they provide ``zope.interface.Interface``.
- Add a number of richer new adapter-registration interfaces
that provide greater control and introspection.
- Add a new interface decorator to zope.interface that allows the
setting of tagged values on an interface at definition time (see
zope.interface.taggedValue).
Bug Fixes
+++++++++
- A bug in multi-adapter lookup sometimes caused incorrect adapters to
be returned.
3.2.0.2 (2006-04-15)
--------------------
- Fix packaging bug: 'package_dir' must be a *relative* path.
3.2.0.1 (2006-04-14)
--------------------
- Packaging change: suppress inclusion of 'setup.cfg' in 'sdist' builds.
3.2.0 (2006-01-05)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope 3.2.0 release.
3.1.0 (2005-10-03)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope 3.1.0 release.
- Made attribute resolution order consistent with component lookup order,
i.e. new-style class MRO semantics.
- Deprecate 'isImplementedBy' and 'isImplementedByInstancesOf' APIs in
favor of 'implementedBy' and 'providedBy'.
3.0.1 (2005-07-27)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope X3.0.1 release.
- Fix a bug reported by James Knight, which caused adapter registries
to fail occasionally to reflect declaration changes.
3.0.0 (2004-11-07)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope X3.0.0 release.
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Zope Public License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Framework :: Zope3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
zope.interface-4.3.2/tox.ini 0000664 0001750 0001750 00000001502 12763206174 015007 0 ustar mg mg 0000000 0000000 [tox]
envlist =
py27,py27-pure,py33,py34,py34-pure,py35,pypy,pypy3,coverage,docs
[testenv]
commands =
python setup.py -q test -q
deps =
zope.event
[testenv:py27-pure]
setenv =
PURE_PYTHON=1
PIP_CACHE_DIR = {envdir}/.cache
[testenv:py34-pure]
setenv =
PURE_PYTHON=1
PIP_CACHE_DIR = {envdir}/.cache
[testenv:py]
commands =
python --version
{[testenv]commands}
[testenv:coverage]
usedevelop = true
basepython =
python2.7
commands =
nosetests --with-xunit --with-xcoverage
deps =
{[testenv]deps}
nose
coverage
nosexcover
[testenv:docs]
basepython =
python2.7
commands =
sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html
sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest
deps =
Sphinx
repoze.sphinx.autointerface
zope.interface-4.3.2/setup.py 0000664 0001750 0001750 00000011457 12763206174 015220 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2004-2007 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.
#
##############################################################################
# This package is developed by the Zope Toolkit project, documented here:
# http://docs.zope.org/zopetoolkit
# When developing and releasing this package, please follow the documented
# Zope Toolkit policies as described by this documentation.
##############################################################################
"""Setup for zope.interface package
"""
import os
import platform
import sys
from setuptools import setup, Extension, Feature
from setuptools.command.build_ext import build_ext
from setuptools import find_packages
from distutils.errors import CCompilerError
from distutils.errors import DistutilsExecError
from distutils.errors import DistutilsPlatformError
class optional_build_ext(build_ext):
"""This class subclasses build_ext and allows
the building of C extensions to fail.
"""
def run(self):
try:
build_ext.run(self)
except DistutilsPlatformError as e:
self._unavailable(e)
def build_extension(self, ext):
try:
build_ext.build_extension(self, ext)
except (CCompilerError, DistutilsExecError, OSError) as e:
self._unavailable(e)
def _unavailable(self, e):
print('*' * 80)
print("""WARNING:
An optional code optimization (C extension) could not be compiled.
Optimizations for this package will not be available!""")
print()
print(e)
print('*' * 80)
codeoptimization_c = os.path.join('src', 'zope', 'interface',
'_zope_interface_coptimizations.c')
codeoptimization = Feature(
"Optional code optimizations",
standard=True,
ext_modules=[
Extension(
"zope.interface._zope_interface_coptimizations",
[os.path.normcase(codeoptimization_c)]
)
])
py_impl = getattr(platform, 'python_implementation', lambda: None)
is_pypy = py_impl() == 'PyPy'
is_jython = 'java' in sys.platform
is_pure = 'PURE_PYTHON' in os.environ
# Jython cannot build the C optimizations, while on PyPy they are
# anti-optimizations (the C extension compatibility layer is known-slow,
# and defeats JIT opportunities).
if is_pypy or is_jython or is_pure:
features = {}
else:
features = {'codeoptimization': codeoptimization}
tests_require = ['zope.event']
testing_extras = tests_require + ['nose', 'coverage']
def read(*rnames):
with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
return f.read()
long_description=(
read('README.rst')
+ '\n' +
read('CHANGES.rst')
)
setup(name='zope.interface',
version='4.3.2',
url='https://github.com/zopefoundation/zope.interface',
license='ZPL 2.1',
description='Interfaces for Python',
author='Zope Foundation and Contributors',
author_email='zope-dev@zope.org',
long_description=long_description,
classifiers=[
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: Zope Public License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Framework :: Zope3",
"Topic :: Software Development :: Libraries :: Python Modules",
],
packages=find_packages('src'),
package_dir={'': 'src'},
namespace_packages=["zope"],
cmdclass={
'build_ext': optional_build_ext,
},
test_suite='zope.interface.tests',
include_package_data=True,
zip_safe=False,
tests_require=tests_require,
install_requires=['setuptools'],
extras_require={
'docs': ['Sphinx', 'repoze.sphinx.autointerface'],
'test': tests_require,
'testing': testing_extras,
},
features=features,
)
zope.interface-4.3.2/setup.cfg 0000664 0001750 0001750 00000000467 12763206175 015327 0 ustar mg mg 0000000 0000000 [nosetests]
nocapture = 1
cover-package = zope.interface
cover-erase = 1
cover-min-percentage = 100
cover-branches = 1
with-doctest = 0
where = src
[aliases]
dev = develop easy_install zope.interface[testing]
docs = easy_install zope.interface[docs]
[egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
zope.interface-4.3.2/rtd.txt 0000664 0001750 0001750 00000000034 12763206174 015025 0 ustar mg mg 0000000 0000000 repoze.sphinx.autointerface
zope.interface-4.3.2/buildout.cfg 0000664 0001750 0001750 00000000327 12763206174 016010 0 ustar mg mg 0000000 0000000 [buildout]
develop = .
parts = test python
[test]
recipe = zc.recipe.testrunner
eggs = zope.interface
zope.event
[python]
recipe = zc.recipe.egg
eggs = zope.interface
zope.event
interpreter = python
zope.interface-4.3.2/build.cmd 0000664 0001750 0001750 00000001506 12763206174 015264 0 ustar mg mg 0000000 0000000 @echo off
:: To build extensions for 64 bit Python 3, we need to configure environment
:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of:
:: MS Windows SDK for Windows 7 and .NET Framework 4
::
:: More details at:
:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows
IF "%DISTUTILS_USE_SDK%"=="1" (
ECHO Configuring environment to build with MSVC on a 64bit architecture
ECHO Using Windows SDK 7.1
"C:\Program Files\Microsoft SDKs\Windows\v7.1\Setup\WindowsSdkVer.exe" -q -version:v7.1
CALL "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 /release
SET MSSdk=1
REM Need the following to allow tox to see the SDK compiler
SET TOX_TESTENV_PASSENV=DISTUTILS_USE_SDK MSSdk INCLUDE LIB
) ELSE (
ECHO Using default MSVC build environment
)
CALL %*
zope.interface-4.3.2/bootstrap.py 0000664 0001750 0001750 00000016442 12763206174 016074 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""Bootstrap a buildout-based project
Simply run this script in a directory containing a buildout.cfg.
The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
"""
import os
import shutil
import sys
import tempfile
from optparse import OptionParser
__version__ = '2015-07-01'
# See zc.buildout's changelog if this version is up to date.
tmpeggs = tempfile.mkdtemp(prefix='bootstrap-')
usage = '''\
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
Bootstraps a buildout-based project.
Simply run this script in a directory containing a buildout.cfg, using the
Python that you want bin/buildout to use.
Note that by using --find-links to point to local resources, you can keep
this script from going over the network.
'''
parser = OptionParser(usage=usage)
parser.add_option("--version",
action="store_true", default=False,
help=("Return bootstrap.py version."))
parser.add_option("-t", "--accept-buildout-test-releases",
dest='accept_buildout_test_releases',
action="store_true", default=False,
help=("Normally, if you do not specify a --version, the "
"bootstrap script and buildout gets the newest "
"*final* versions of zc.buildout and its recipes and "
"extensions for you. If you use this flag, "
"bootstrap and buildout will get the newest releases "
"even if they are alphas or betas."))
parser.add_option("-c", "--config-file",
help=("Specify the path to the buildout configuration "
"file to be used."))
parser.add_option("-f", "--find-links",
help=("Specify a URL to search for buildout releases"))
parser.add_option("--allow-site-packages",
action="store_true", default=False,
help=("Let bootstrap.py use existing site packages"))
parser.add_option("--buildout-version",
help="Use a specific zc.buildout version")
parser.add_option("--setuptools-version",
help="Use a specific setuptools version")
parser.add_option("--setuptools-to-dir",
help=("Allow for re-use of existing directory of "
"setuptools versions"))
options, args = parser.parse_args()
if options.version:
print("bootstrap.py version %s" % __version__)
sys.exit(0)
######################################################################
# load/install setuptools
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
ez = {}
if os.path.exists('ez_setup.py'):
exec(open('ez_setup.py').read(), ez)
else:
exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
if not options.allow_site_packages:
# ez_setup imports site, which adds site packages
# this will remove them from the path to ensure that incompatible versions
# of setuptools are not in the path
import site
# inside a virtualenv, there is no 'getsitepackages'.
# We can't remove these reliably
if hasattr(site, 'getsitepackages'):
for sitepackage_path in site.getsitepackages():
# Strip all site-packages directories from sys.path that
# are not sys.prefix; this is because on Windows
# sys.prefix is a site-package directory.
if sitepackage_path != sys.prefix:
sys.path[:] = [x for x in sys.path
if sitepackage_path not in x]
setup_args = dict(to_dir=tmpeggs, download_delay=0)
if options.setuptools_version is not None:
setup_args['version'] = options.setuptools_version
if options.setuptools_to_dir is not None:
setup_args['to_dir'] = options.setuptools_to_dir
ez['use_setuptools'](**setup_args)
import setuptools
import pkg_resources
# This does not (always?) update the default working set. We will
# do it.
for path in sys.path:
if path not in pkg_resources.working_set.entries:
pkg_resources.working_set.add_entry(path)
######################################################################
# Install buildout
ws = pkg_resources.working_set
setuptools_path = ws.find(
pkg_resources.Requirement.parse('setuptools')).location
# Fix sys.path here as easy_install.pth added before PYTHONPATH
cmd = [sys.executable, '-c',
'import sys; sys.path[0:0] = [%r]; ' % setuptools_path +
'from setuptools.command.easy_install import main; main()',
'-mZqNxd', tmpeggs]
find_links = os.environ.get(
'bootstrap-testing-find-links',
options.find_links or
('http://downloads.buildout.org/'
if options.accept_buildout_test_releases else None)
)
if find_links:
cmd.extend(['-f', find_links])
requirement = 'zc.buildout'
version = options.buildout_version
if version is None and not options.accept_buildout_test_releases:
# Figure out the most recent final version of zc.buildout.
import setuptools.package_index
_final_parts = '*final-', '*final'
def _final_version(parsed_version):
try:
return not parsed_version.is_prerelease
except AttributeError:
# Older setuptools
for part in parsed_version:
if (part[:1] == '*') and (part not in _final_parts):
return False
return True
index = setuptools.package_index.PackageIndex(
search_path=[setuptools_path])
if find_links:
index.add_find_links((find_links,))
req = pkg_resources.Requirement.parse(requirement)
if index.obtain(req) is not None:
best = []
bestv = None
for dist in index[req.project_name]:
distv = dist.parsed_version
if _final_version(distv):
if bestv is None or distv > bestv:
best = [dist]
bestv = distv
elif distv == bestv:
best.append(dist)
if best:
best.sort()
version = best[-1].version
if version:
requirement = '=='.join((requirement, version))
cmd.append(requirement)
import subprocess
if subprocess.call(cmd) != 0:
raise Exception(
"Failed to execute command:\n%s" % repr(cmd)[1:-1])
######################################################################
# Import and run buildout
ws.add_entry(tmpeggs)
ws.require(requirement)
import zc.buildout.buildout
if not [a for a in args if '=' not in a]:
args.append('bootstrap')
# if -c was provided, we push it back into args for buildout' main function
if options.config_file is not None:
args[0:0] = ['-c', options.config_file]
zc.buildout.buildout.main(args)
shutil.rmtree(tmpeggs)
zope.interface-4.3.2/README.rst 0000664 0001750 0001750 00000002135 12763206174 015166 0 ustar mg mg 0000000 0000000 ``zope.interface``
==================
.. image:: https://img.shields.io/pypi/v/zope.interface.svg
:target: https://pypi.python.org/pypi/zope.interface/
:alt: Latest Version
.. image:: https://travis-ci.org/zopefoundation/zope.interface.png?branch=master
:target: https://travis-ci.org/zopefoundation/zope.interface
.. image:: https://readthedocs.org/projects/zopeinterface/badge/?version=latest
:target: https://zopeinterface.readthedocs.io/en/latest/
:alt: Documentation Status
This package is intended to be independently reusable in any Python
project. It is maintained by the `Zope Toolkit project
`_.
This package provides an implementation of "object interfaces" for Python.
Interfaces are a mechanism for labeling objects as conforming to a given
API or contract. So, this package can be considered as implementation of
the `Design By Contract`_ methodology support in Python.
.. _Design By Contract: http://en.wikipedia.org/wiki/Design_by_contract
For detailed documentation, please see https://zopeinterface.readthedocs.io/en/latest/
zope.interface-4.3.2/MANIFEST.in 0000664 0001750 0001750 00000000505 12763206174 015234 0 ustar mg mg 0000000 0000000 include *.rst
include *.txt
include *.py
include .coveragerc
include build.cmd
include buildout.cfg
include tox.ini
recursive-include docs *
recursive-include src *
global-exclude *.dll
global-exclude *.pyc
global-exclude *.pyo
global-exclude *.so
global-exclude coverage.xml
global-exclude appveyor.yml
prune docs/_build
zope.interface-4.3.2/LICENSE.txt 0000664 0001750 0001750 00000004026 12763206174 015323 0 ustar mg mg 0000000 0000000 Zope Public License (ZPL) Version 2.1
A copyright notice accompanies this license document that identifies the
copyright holders.
This license has been certified as open source. It has also been designated as
GPL compatible by the Free Software Foundation (FSF).
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions in source code must retain the accompanying copyright
notice, this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the accompanying copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Names of the copyright holders must not be used to endorse or promote
products derived from this software without prior written permission from the
copyright holders.
4. The right to distribute this software or to use it for any purpose does not
give you the right to use Servicemarks (sm) or Trademarks (tm) of the
copyright
holders. Use of them is covered by separate agreement with the copyright
holders.
5. If any files are modified, you must cause the modified files to carry
prominent notices stating that you changed the files and the date of any
change.
Disclaimer
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
zope.interface-4.3.2/COPYRIGHT.txt 0000664 0001750 0001750 00000000040 12763206174 015601 0 ustar mg mg 0000000 0000000 Zope Foundation and Contributors zope.interface-4.3.2/CHANGES.rst 0000664 0001750 0001750 00000031565 12763206174 015312 0 ustar mg mg 0000000 0000000 Changes
=======
4.3.2 (2016-09-05)
------------------
- Fix equality testing of ``implementedBy`` objects and proxies.
(https://github.com/zopefoundation/zope.interface/issues/55)
4.3.1 (2016-08-31)
------------------
- Support Components subclasses that are not hashable.
(https://github.com/zopefoundation/zope.interface/issues/53)
4.3.0 (2016-08-31)
------------------
- Add the ability to sort the objects returned by ``implementedBy``.
This is compatible with the way interface classes sort so they can
be used together in ordered containers like BTrees.
(https://github.com/zopefoundation/zope.interface/issues/42)
- Make ``setuptools`` a hard dependency of ``setup.py``.
(https://github.com/zopefoundation/zope.interface/issues/13)
- Change a linear algorithm (O(n)) in ``Components.registerUtility`` and
``Components.unregisterUtility`` into a dictionary lookup (O(1)) for
hashable components. This substantially improves the time taken to
manipulate utilities in large registries at the cost of some
additional memory usage. (https://github.com/zopefoundation/zope.interface/issues/46)
4.2.0 (2016-06-10)
------------------
- Add support for Python 3.5
- Drop support for Python 2.6 and 3.2.
4.1.3 (2015-10-05)
------------------
- Fix installation without a C compiler on Python 3.5
(https://github.com/zopefoundation/zope.interface/issues/24).
4.1.2 (2014-12-27)
------------------
- Add support for PyPy3.
- Remove unittest assertions deprecated in Python3.x.
- Add ``zope.interface.document.asReStructuredText``, which formats the
generated text for an interface using ReST double-backtick markers.
4.1.1 (2014-03-19)
------------------
- Add support for Python 3.4.
4.1.0 (2014-02-05)
------------------
- Update ``boostrap.py`` to version 2.2.
- Add ``@named(name)`` declaration, that specifies the component name, so it
does not have to be passed in during registration.
4.0.5 (2013-02-28)
------------------
- Fix a bug where a decorated method caused false positive failures on
``verifyClass()``.
4.0.4 (2013-02-21)
------------------
- Fix a bug that was revealed by porting zope.traversing. During a loop, the
loop body modified a weakref dict causing a ``RuntimeError`` error.
4.0.3 (2012-12-31)
------------------
- Fleshed out PyPI Trove classifiers.
4.0.2 (2012-11-21)
------------------
- Add support for Python 3.3.
- Restored ability to install the package in the absence of ``setuptools``.
- LP #1055223: Fix test which depended on dictionary order and failed randomly
in Python 3.3.
4.0.1 (2012-05-22)
------------------
- Drop explicit ``DeprecationWarnings`` for "class advice" APIS (these
APIs are still deprecated under Python 2.x, and still raise an exception
under Python 3.x, but no longer cause a warning to be emitted under
Python 2.x).
4.0.0 (2012-05-16)
------------------
- Automated build of Sphinx HTML docs and running doctest snippets via tox.
- Deprecate the "class advice" APIs from ``zope.interface.declarations``:
``implements``, ``implementsOnly``, and ``classProvides``. In their place,
prefer the equivalent class decorators: ``@implementer``,
``@implementer_only``, and ``@provider``. Code which uses the deprecated
APIs will not work as expected under Py3k.
- Remove use of '2to3' and associated fixers when installing under Py3k.
The code is now in a "compatible subset" which supports Python 2.6, 2.7,
and 3.2, including PyPy 1.8 (the version compatible with the 2.7 language
spec).
- Drop explicit support for Python 2.4 / 2.5 / 3.1.
- Add support for PyPy.
- Add support for continuous integration using ``tox`` and ``jenkins``.
- Add 'setup.py dev' alias (runs ``setup.py develop`` plus installs
``nose`` and ``coverage``).
- Add 'setup.py docs' alias (installs ``Sphinx`` and dependencies).
- Replace all unittest coverage previously accomplished via doctests with
unittests. The doctests have been moved into a ``docs`` section, managed
as a Sphinx collection.
- LP #910987: Ensure that the semantics of the ``lookup`` method of
``zope.interface.adapter.LookupBase`` are the same in both the C and
Python implementations.
- LP #900906: Avoid exceptions due to tne new ``__qualname__`` attribute
added in Python 3.3 (see PEP 3155 for rationale). Thanks to Antoine
Pitrou for the patch.
3.8.0 (2011-09-22)
------------------
- New module ``zope.interface.registry``. This is code moved from
``zope.component.registry`` which implements a basic nonperistent component
registry as ``zope.interface.registry.Components``. This class was moved
from ``zope.component`` to make porting systems (such as Pyramid) that rely
only on a basic component registry to Python 3 possible without needing to
port the entirety of the ``zope.component`` package. Backwards
compatibility import shims have been left behind in ``zope.component``, so
this change will not break any existing code.
- New ``tests_require`` dependency: ``zope.event`` to test events sent by
Components implementation. The ``zope.interface`` package does not have a
hard dependency on ``zope.event``, but if ``zope.event`` is importable, it
will send component registration events when methods of an instance of
``zope.interface.registry.Components`` are called.
- New interfaces added to support ``zope.interface.registry.Components``
addition: ``ComponentLookupError``, ``Invalid``, ``IObjectEvent``,
``ObjectEvent``, ``IComponentLookup``, ``IRegistration``,
``IUtilityRegistration``, ``IAdapterRegistration``,
``ISubscriptionAdapterRegistration``, ``IHandlerRegistration``,
``IRegistrationEvent``, ``RegistrationEvent``, ``IRegistered``,
``Registered``, ``IUnregistered``, ``Unregistered``,
``IComponentRegistry``, and ``IComponents``.
- No longer Python 2.4 compatible (tested under 2.5, 2.6, 2.7, and 3.2).
3.7.0 (2011-08-13)
------------------
- Move changes from 3.6.2 - 3.6.5 to a new 3.7.x release line.
3.6.7 (2011-08-20)
------------------
- Fix sporadic failures on x86-64 platforms in tests of rich comparisons
of interfaces.
3.6.6 (2011-08-13)
------------------
- LP #570942: Now correctly compare interfaces from different modules but
with the same names.
N.B.: This is a less intrusive / destabilizing fix than the one applied in
3.6.3: we only fix the underlying cmp-alike function, rather than adding
the other "rich comparison" functions.
- Revert to software as released with 3.6.1 for "stable" 3.6 release branch.
3.6.5 (2011-08-11)
------------------
- LP #811792: work around buggy behavior in some subclasses of
``zope.interface.interface.InterfaceClass``, which invoke ``__hash__``
before initializing ``__module__`` and ``__name__``. The workaround
returns a fixed constant hash in such cases, and issues a ``UserWarning``.
- LP #804832: Under PyPy, ``zope.interface`` should not build its C
extension. Also, prevent attempting to build it under Jython.
- Add a tox.ini for easier xplatform testing.
- Fix testing deprecation warnings issued when tested under Py3K.
3.6.4 (2011-07-04)
------------------
- LP 804951: InterfaceClass instances were unhashable under Python 3.x.
3.6.3 (2011-05-26)
------------------
- LP #570942: Now correctly compare interfaces from different modules but
with the same names.
3.6.2 (2011-05-17)
------------------
- Moved detailed documentation out-of-line from PyPI page, linking instead to
http://docs.zope.org/zope.interface .
- Fixes for small issues when running tests under Python 3.2 using
``zope.testrunner``.
- LP # 675064: Specify return value type for C optimizations module init
under Python 3: undeclared value caused warnings, and segfaults on some
64 bit architectures.
- setup.py now raises RuntimeError if you don't have Distutils installed when
running under Python 3.
3.6.1 (2010-05-03)
------------------
- A non-ASCII character in the changelog made 3.6.0 uninstallable on
Python 3 systems with another default encoding than UTF-8.
- Fix compiler warnings under GCC 4.3.3.
3.6.0 (2010-04-29)
------------------
- LP #185974: Clear the cache used by ``Specificaton.get`` inside
``Specification.changed``. Thanks to Jacob Holm for the patch.
- Add support for Python 3.1. Contributors:
Lennart Regebro
Martin v Loewis
Thomas Lotze
Wolfgang Schnerring
The 3.1 support is completely backwards compatible. However, the implements
syntax used under Python 2.X does not work under 3.X, since it depends on
how metaclasses are implemented and this has changed. Instead it now supports
a decorator syntax (also under Python 2.X)::
class Foo:
implements(IFoo)
...
can now also be written::
@implementer(IFoo):
class Foo:
...
There are 2to3 fixers available to do this change automatically in the
zope.fixers package.
- Python 2.3 is no longer supported.
3.5.4 (2009-12-23)
------------------
- Use the standard Python doctest module instead of zope.testing.doctest, which
has been deprecated.
3.5.3 (2009-12-08)
------------------
- Fix an edge case: make providedBy() work when a class has '__provides__' in
its __slots__ (see http://thread.gmane.org/gmane.comp.web.zope.devel/22490)
3.5.2 (2009-07-01)
------------------
- BaseAdapterRegistry.unregister, unsubscribe: Remove empty portions of
the data structures when something is removed. This avoids leaving
references to global objects (interfaces) that may be slated for
removal from the calling application.
3.5.1 (2009-03-18)
------------------
- verifyObject: use getattr instead of hasattr to test for object attributes
in order to let exceptions other than AttributeError raised by properties
propagate to the caller
- Add Sphinx-based documentation building to the package buildout
configuration. Use the ``bin/docs`` command after buildout.
- Improve package description a bit. Unify changelog entries formatting.
- Change package's mailing list address to zope-dev at zope.org as
zope3-dev at zope.org is now retired.
3.5.0 (2008-10-26)
------------------
- Fix declaration of _zope_interface_coptimizations, it's not a top level
package.
- Add a DocTestSuite for odd.py module, so their tests are run.
- Allow to bootstrap on Jython.
- Fix https://bugs.launchpad.net/zope3/3.3/+bug/98388: ISpecification
was missing a declaration for __iro__.
- Add optional code optimizations support, which allows the building
of C code optimizations to fail (Jython).
- Replace `_flatten` with a non-recursive implementation, effectively making
it 3x faster.
3.4.1 (2007-10-02)
------------------
- Fix a setup bug that prevented installation from source on systems
without setuptools.
3.4.0 (2007-07-19)
------------------
- Final release for 3.4.0.
3.4.0b3 (2007-05-22)
--------------------
- When checking whether an object is already registered, use identity
comparison, to allow adding registering with picky custom comparison methods.
3.3.0.1 (2007-01-03)
--------------------
- Made a reference to OverflowWarning, which disappeared in Python
2.5, conditional.
3.3.0 (2007/01/03)
------------------
New Features
++++++++++++
- Refactor the adapter-lookup algorithim to make it much simpler and faster.
Also, implement more of the adapter-lookup logic in C, making
debugging of application code easier, since there is less
infrastructre code to step through.
- Treat objects without interface declarations as if they
declared that they provide ``zope.interface.Interface``.
- Add a number of richer new adapter-registration interfaces
that provide greater control and introspection.
- Add a new interface decorator to zope.interface that allows the
setting of tagged values on an interface at definition time (see
zope.interface.taggedValue).
Bug Fixes
+++++++++
- A bug in multi-adapter lookup sometimes caused incorrect adapters to
be returned.
3.2.0.2 (2006-04-15)
--------------------
- Fix packaging bug: 'package_dir' must be a *relative* path.
3.2.0.1 (2006-04-14)
--------------------
- Packaging change: suppress inclusion of 'setup.cfg' in 'sdist' builds.
3.2.0 (2006-01-05)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope 3.2.0 release.
3.1.0 (2005-10-03)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope 3.1.0 release.
- Made attribute resolution order consistent with component lookup order,
i.e. new-style class MRO semantics.
- Deprecate 'isImplementedBy' and 'isImplementedByInstancesOf' APIs in
favor of 'implementedBy' and 'providedBy'.
3.0.1 (2005-07-27)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope X3.0.1 release.
- Fix a bug reported by James Knight, which caused adapter registries
to fail occasionally to reflect declaration changes.
3.0.0 (2004-11-07)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope X3.0.0 release.
zope.interface-4.3.2/.coveragerc 0000664 0001750 0001750 00000000133 12763206174 015614 0 ustar mg mg 0000000 0000000 [report]
exclude_lines =
pragma: no cover
class I[A-Z]\w+\((Interface|I[A-Z].*)\):
zope.interface-4.3.2/src/ 0000775 0001750 0001750 00000000000 12763206175 014266 5 ustar mg mg 0000000 0000000 zope.interface-4.3.2/src/zope.interface.egg-info/ 0000775 0001750 0001750 00000000000 12763206175 020674 5 ustar mg mg 0000000 0000000 zope.interface-4.3.2/src/zope.interface.egg-info/top_level.txt 0000664 0001750 0001750 00000000005 12763206174 023420 0 ustar mg mg 0000000 0000000 zope
zope.interface-4.3.2/src/zope.interface.egg-info/requires.txt 0000664 0001750 0001750 00000000155 12763206174 023274 0 ustar mg mg 0000000 0000000 setuptools
[docs]
Sphinx
repoze.sphinx.autointerface
[test]
zope.event
[testing]
zope.event
nose
coverage
zope.interface-4.3.2/src/zope.interface.egg-info/not-zip-safe 0000664 0001750 0001750 00000000001 12763206174 023121 0 ustar mg mg 0000000 0000000
zope.interface-4.3.2/src/zope.interface.egg-info/namespace_packages.txt 0000664 0001750 0001750 00000000005 12763206174 025221 0 ustar mg mg 0000000 0000000 zope
zope.interface-4.3.2/src/zope.interface.egg-info/dependency_links.txt 0000664 0001750 0001750 00000000001 12763206174 024741 0 ustar mg mg 0000000 0000000
zope.interface-4.3.2/src/zope.interface.egg-info/SOURCES.txt 0000664 0001750 0001750 00000004576 12763206174 022573 0 ustar mg mg 0000000 0000000 .coveragerc
CHANGES.rst
COPYRIGHT.txt
LICENSE.txt
MANIFEST.in
README.rst
bootstrap.py
build.cmd
buildout.cfg
rtd.txt
setup.cfg
setup.py
tox.ini
docs/Makefile
docs/README.rst
docs/README.ru.rst
docs/adapter.rst
docs/adapter.ru.rst
docs/api.rst
docs/conf.py
docs/foodforthought.rst
docs/hacking.rst
docs/human.rst
docs/human.ru.rst
docs/index.rst
docs/make.bat
docs/verify.rst
docs/_static/.gitignore
src/zope/__init__.py
src/zope.interface.egg-info/PKG-INFO
src/zope.interface.egg-info/SOURCES.txt
src/zope.interface.egg-info/dependency_links.txt
src/zope.interface.egg-info/namespace_packages.txt
src/zope.interface.egg-info/not-zip-safe
src/zope.interface.egg-info/requires.txt
src/zope.interface.egg-info/top_level.txt
src/zope/interface/__init__.py
src/zope/interface/_compat.py
src/zope/interface/_flatten.py
src/zope/interface/_zope_interface_coptimizations.c
src/zope/interface/adapter.py
src/zope/interface/advice.py
src/zope/interface/declarations.py
src/zope/interface/document.py
src/zope/interface/exceptions.py
src/zope/interface/interface.py
src/zope/interface/interfaces.py
src/zope/interface/registry.py
src/zope/interface/ro.py
src/zope/interface/verify.py
src/zope/interface/common/__init__.py
src/zope/interface/common/idatetime.py
src/zope/interface/common/interfaces.py
src/zope/interface/common/mapping.py
src/zope/interface/common/sequence.py
src/zope/interface/common/tests/__init__.py
src/zope/interface/common/tests/basemapping.py
src/zope/interface/common/tests/test_idatetime.py
src/zope/interface/common/tests/test_import_interfaces.py
src/zope/interface/tests/__init__.py
src/zope/interface/tests/advisory_testing.py
src/zope/interface/tests/dummy.py
src/zope/interface/tests/idummy.py
src/zope/interface/tests/ifoo.py
src/zope/interface/tests/ifoo_other.py
src/zope/interface/tests/m1.py
src/zope/interface/tests/m2.py
src/zope/interface/tests/odd.py
src/zope/interface/tests/test_adapter.py
src/zope/interface/tests/test_advice.py
src/zope/interface/tests/test_declarations.py
src/zope/interface/tests/test_document.py
src/zope/interface/tests/test_element.py
src/zope/interface/tests/test_exceptions.py
src/zope/interface/tests/test_interface.py
src/zope/interface/tests/test_interfaces.py
src/zope/interface/tests/test_odd_declarations.py
src/zope/interface/tests/test_registry.py
src/zope/interface/tests/test_ro.py
src/zope/interface/tests/test_sorting.py
src/zope/interface/tests/test_verify.py zope.interface-4.3.2/src/zope.interface.egg-info/PKG-INFO 0000664 0001750 0001750 00000045340 12763206174 021776 0 ustar mg mg 0000000 0000000 Metadata-Version: 1.1
Name: zope.interface
Version: 4.3.2
Summary: Interfaces for Python
Home-page: https://github.com/zopefoundation/zope.interface
Author: Zope Foundation and Contributors
Author-email: zope-dev@zope.org
License: ZPL 2.1
Description: ``zope.interface``
==================
.. image:: https://img.shields.io/pypi/v/zope.interface.svg
:target: https://pypi.python.org/pypi/zope.interface/
:alt: Latest Version
.. image:: https://travis-ci.org/zopefoundation/zope.interface.png?branch=master
:target: https://travis-ci.org/zopefoundation/zope.interface
.. image:: https://readthedocs.org/projects/zopeinterface/badge/?version=latest
:target: https://zopeinterface.readthedocs.io/en/latest/
:alt: Documentation Status
This package is intended to be independently reusable in any Python
project. It is maintained by the `Zope Toolkit project
`_.
This package provides an implementation of "object interfaces" for Python.
Interfaces are a mechanism for labeling objects as conforming to a given
API or contract. So, this package can be considered as implementation of
the `Design By Contract`_ methodology support in Python.
.. _Design By Contract: http://en.wikipedia.org/wiki/Design_by_contract
For detailed documentation, please see https://zopeinterface.readthedocs.io/en/latest/
Changes
=======
4.3.2 (2016-09-05)
------------------
- Fix equality testing of ``implementedBy`` objects and proxies.
(https://github.com/zopefoundation/zope.interface/issues/55)
4.3.1 (2016-08-31)
------------------
- Support Components subclasses that are not hashable.
(https://github.com/zopefoundation/zope.interface/issues/53)
4.3.0 (2016-08-31)
------------------
- Add the ability to sort the objects returned by ``implementedBy``.
This is compatible with the way interface classes sort so they can
be used together in ordered containers like BTrees.
(https://github.com/zopefoundation/zope.interface/issues/42)
- Make ``setuptools`` a hard dependency of ``setup.py``.
(https://github.com/zopefoundation/zope.interface/issues/13)
- Change a linear algorithm (O(n)) in ``Components.registerUtility`` and
``Components.unregisterUtility`` into a dictionary lookup (O(1)) for
hashable components. This substantially improves the time taken to
manipulate utilities in large registries at the cost of some
additional memory usage. (https://github.com/zopefoundation/zope.interface/issues/46)
4.2.0 (2016-06-10)
------------------
- Add support for Python 3.5
- Drop support for Python 2.6 and 3.2.
4.1.3 (2015-10-05)
------------------
- Fix installation without a C compiler on Python 3.5
(https://github.com/zopefoundation/zope.interface/issues/24).
4.1.2 (2014-12-27)
------------------
- Add support for PyPy3.
- Remove unittest assertions deprecated in Python3.x.
- Add ``zope.interface.document.asReStructuredText``, which formats the
generated text for an interface using ReST double-backtick markers.
4.1.1 (2014-03-19)
------------------
- Add support for Python 3.4.
4.1.0 (2014-02-05)
------------------
- Update ``boostrap.py`` to version 2.2.
- Add ``@named(name)`` declaration, that specifies the component name, so it
does not have to be passed in during registration.
4.0.5 (2013-02-28)
------------------
- Fix a bug where a decorated method caused false positive failures on
``verifyClass()``.
4.0.4 (2013-02-21)
------------------
- Fix a bug that was revealed by porting zope.traversing. During a loop, the
loop body modified a weakref dict causing a ``RuntimeError`` error.
4.0.3 (2012-12-31)
------------------
- Fleshed out PyPI Trove classifiers.
4.0.2 (2012-11-21)
------------------
- Add support for Python 3.3.
- Restored ability to install the package in the absence of ``setuptools``.
- LP #1055223: Fix test which depended on dictionary order and failed randomly
in Python 3.3.
4.0.1 (2012-05-22)
------------------
- Drop explicit ``DeprecationWarnings`` for "class advice" APIS (these
APIs are still deprecated under Python 2.x, and still raise an exception
under Python 3.x, but no longer cause a warning to be emitted under
Python 2.x).
4.0.0 (2012-05-16)
------------------
- Automated build of Sphinx HTML docs and running doctest snippets via tox.
- Deprecate the "class advice" APIs from ``zope.interface.declarations``:
``implements``, ``implementsOnly``, and ``classProvides``. In their place,
prefer the equivalent class decorators: ``@implementer``,
``@implementer_only``, and ``@provider``. Code which uses the deprecated
APIs will not work as expected under Py3k.
- Remove use of '2to3' and associated fixers when installing under Py3k.
The code is now in a "compatible subset" which supports Python 2.6, 2.7,
and 3.2, including PyPy 1.8 (the version compatible with the 2.7 language
spec).
- Drop explicit support for Python 2.4 / 2.5 / 3.1.
- Add support for PyPy.
- Add support for continuous integration using ``tox`` and ``jenkins``.
- Add 'setup.py dev' alias (runs ``setup.py develop`` plus installs
``nose`` and ``coverage``).
- Add 'setup.py docs' alias (installs ``Sphinx`` and dependencies).
- Replace all unittest coverage previously accomplished via doctests with
unittests. The doctests have been moved into a ``docs`` section, managed
as a Sphinx collection.
- LP #910987: Ensure that the semantics of the ``lookup`` method of
``zope.interface.adapter.LookupBase`` are the same in both the C and
Python implementations.
- LP #900906: Avoid exceptions due to tne new ``__qualname__`` attribute
added in Python 3.3 (see PEP 3155 for rationale). Thanks to Antoine
Pitrou for the patch.
3.8.0 (2011-09-22)
------------------
- New module ``zope.interface.registry``. This is code moved from
``zope.component.registry`` which implements a basic nonperistent component
registry as ``zope.interface.registry.Components``. This class was moved
from ``zope.component`` to make porting systems (such as Pyramid) that rely
only on a basic component registry to Python 3 possible without needing to
port the entirety of the ``zope.component`` package. Backwards
compatibility import shims have been left behind in ``zope.component``, so
this change will not break any existing code.
- New ``tests_require`` dependency: ``zope.event`` to test events sent by
Components implementation. The ``zope.interface`` package does not have a
hard dependency on ``zope.event``, but if ``zope.event`` is importable, it
will send component registration events when methods of an instance of
``zope.interface.registry.Components`` are called.
- New interfaces added to support ``zope.interface.registry.Components``
addition: ``ComponentLookupError``, ``Invalid``, ``IObjectEvent``,
``ObjectEvent``, ``IComponentLookup``, ``IRegistration``,
``IUtilityRegistration``, ``IAdapterRegistration``,
``ISubscriptionAdapterRegistration``, ``IHandlerRegistration``,
``IRegistrationEvent``, ``RegistrationEvent``, ``IRegistered``,
``Registered``, ``IUnregistered``, ``Unregistered``,
``IComponentRegistry``, and ``IComponents``.
- No longer Python 2.4 compatible (tested under 2.5, 2.6, 2.7, and 3.2).
3.7.0 (2011-08-13)
------------------
- Move changes from 3.6.2 - 3.6.5 to a new 3.7.x release line.
3.6.7 (2011-08-20)
------------------
- Fix sporadic failures on x86-64 platforms in tests of rich comparisons
of interfaces.
3.6.6 (2011-08-13)
------------------
- LP #570942: Now correctly compare interfaces from different modules but
with the same names.
N.B.: This is a less intrusive / destabilizing fix than the one applied in
3.6.3: we only fix the underlying cmp-alike function, rather than adding
the other "rich comparison" functions.
- Revert to software as released with 3.6.1 for "stable" 3.6 release branch.
3.6.5 (2011-08-11)
------------------
- LP #811792: work around buggy behavior in some subclasses of
``zope.interface.interface.InterfaceClass``, which invoke ``__hash__``
before initializing ``__module__`` and ``__name__``. The workaround
returns a fixed constant hash in such cases, and issues a ``UserWarning``.
- LP #804832: Under PyPy, ``zope.interface`` should not build its C
extension. Also, prevent attempting to build it under Jython.
- Add a tox.ini for easier xplatform testing.
- Fix testing deprecation warnings issued when tested under Py3K.
3.6.4 (2011-07-04)
------------------
- LP 804951: InterfaceClass instances were unhashable under Python 3.x.
3.6.3 (2011-05-26)
------------------
- LP #570942: Now correctly compare interfaces from different modules but
with the same names.
3.6.2 (2011-05-17)
------------------
- Moved detailed documentation out-of-line from PyPI page, linking instead to
http://docs.zope.org/zope.interface .
- Fixes for small issues when running tests under Python 3.2 using
``zope.testrunner``.
- LP # 675064: Specify return value type for C optimizations module init
under Python 3: undeclared value caused warnings, and segfaults on some
64 bit architectures.
- setup.py now raises RuntimeError if you don't have Distutils installed when
running under Python 3.
3.6.1 (2010-05-03)
------------------
- A non-ASCII character in the changelog made 3.6.0 uninstallable on
Python 3 systems with another default encoding than UTF-8.
- Fix compiler warnings under GCC 4.3.3.
3.6.0 (2010-04-29)
------------------
- LP #185974: Clear the cache used by ``Specificaton.get`` inside
``Specification.changed``. Thanks to Jacob Holm for the patch.
- Add support for Python 3.1. Contributors:
Lennart Regebro
Martin v Loewis
Thomas Lotze
Wolfgang Schnerring
The 3.1 support is completely backwards compatible. However, the implements
syntax used under Python 2.X does not work under 3.X, since it depends on
how metaclasses are implemented and this has changed. Instead it now supports
a decorator syntax (also under Python 2.X)::
class Foo:
implements(IFoo)
...
can now also be written::
@implementer(IFoo):
class Foo:
...
There are 2to3 fixers available to do this change automatically in the
zope.fixers package.
- Python 2.3 is no longer supported.
3.5.4 (2009-12-23)
------------------
- Use the standard Python doctest module instead of zope.testing.doctest, which
has been deprecated.
3.5.3 (2009-12-08)
------------------
- Fix an edge case: make providedBy() work when a class has '__provides__' in
its __slots__ (see http://thread.gmane.org/gmane.comp.web.zope.devel/22490)
3.5.2 (2009-07-01)
------------------
- BaseAdapterRegistry.unregister, unsubscribe: Remove empty portions of
the data structures when something is removed. This avoids leaving
references to global objects (interfaces) that may be slated for
removal from the calling application.
3.5.1 (2009-03-18)
------------------
- verifyObject: use getattr instead of hasattr to test for object attributes
in order to let exceptions other than AttributeError raised by properties
propagate to the caller
- Add Sphinx-based documentation building to the package buildout
configuration. Use the ``bin/docs`` command after buildout.
- Improve package description a bit. Unify changelog entries formatting.
- Change package's mailing list address to zope-dev at zope.org as
zope3-dev at zope.org is now retired.
3.5.0 (2008-10-26)
------------------
- Fix declaration of _zope_interface_coptimizations, it's not a top level
package.
- Add a DocTestSuite for odd.py module, so their tests are run.
- Allow to bootstrap on Jython.
- Fix https://bugs.launchpad.net/zope3/3.3/+bug/98388: ISpecification
was missing a declaration for __iro__.
- Add optional code optimizations support, which allows the building
of C code optimizations to fail (Jython).
- Replace `_flatten` with a non-recursive implementation, effectively making
it 3x faster.
3.4.1 (2007-10-02)
------------------
- Fix a setup bug that prevented installation from source on systems
without setuptools.
3.4.0 (2007-07-19)
------------------
- Final release for 3.4.0.
3.4.0b3 (2007-05-22)
--------------------
- When checking whether an object is already registered, use identity
comparison, to allow adding registering with picky custom comparison methods.
3.3.0.1 (2007-01-03)
--------------------
- Made a reference to OverflowWarning, which disappeared in Python
2.5, conditional.
3.3.0 (2007/01/03)
------------------
New Features
++++++++++++
- Refactor the adapter-lookup algorithim to make it much simpler and faster.
Also, implement more of the adapter-lookup logic in C, making
debugging of application code easier, since there is less
infrastructre code to step through.
- Treat objects without interface declarations as if they
declared that they provide ``zope.interface.Interface``.
- Add a number of richer new adapter-registration interfaces
that provide greater control and introspection.
- Add a new interface decorator to zope.interface that allows the
setting of tagged values on an interface at definition time (see
zope.interface.taggedValue).
Bug Fixes
+++++++++
- A bug in multi-adapter lookup sometimes caused incorrect adapters to
be returned.
3.2.0.2 (2006-04-15)
--------------------
- Fix packaging bug: 'package_dir' must be a *relative* path.
3.2.0.1 (2006-04-14)
--------------------
- Packaging change: suppress inclusion of 'setup.cfg' in 'sdist' builds.
3.2.0 (2006-01-05)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope 3.2.0 release.
3.1.0 (2005-10-03)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope 3.1.0 release.
- Made attribute resolution order consistent with component lookup order,
i.e. new-style class MRO semantics.
- Deprecate 'isImplementedBy' and 'isImplementedByInstancesOf' APIs in
favor of 'implementedBy' and 'providedBy'.
3.0.1 (2005-07-27)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope X3.0.1 release.
- Fix a bug reported by James Knight, which caused adapter registries
to fail occasionally to reflect declaration changes.
3.0.0 (2004-11-07)
------------------
- Corresponds to the verison of the zope.interface package shipped as part of
the Zope X3.0.0 release.
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Zope Public License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Framework :: Zope3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
zope.interface-4.3.2/src/zope/ 0000775 0001750 0001750 00000000000 12763206175 015243 5 ustar mg mg 0000000 0000000 zope.interface-4.3.2/src/zope/__init__.py 0000664 0001750 0001750 00000000310 12763206174 017345 0 ustar mg mg 0000000 0000000 # this is a namespace package
try:
import pkg_resources
pkg_resources.declare_namespace(__name__)
except ImportError:
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
zope.interface-4.3.2/src/zope/interface/ 0000775 0001750 0001750 00000000000 12763206175 017203 5 ustar mg mg 0000000 0000000 zope.interface-4.3.2/src/zope/interface/verify.py 0000664 0001750 0001750 00000011167 12763206174 021066 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Verify interface implementations
"""
from zope.interface.exceptions import BrokenImplementation, DoesNotImplement
from zope.interface.exceptions import BrokenMethodImplementation
from types import FunctionType, MethodType
from zope.interface.interface import fromMethod, fromFunction, Method
import sys
# This will be monkey-patched when running under Zope 2, so leave this
# here:
MethodTypes = (MethodType, )
def _verify(iface, candidate, tentative=0, vtype=None):
"""Verify that 'candidate' might correctly implements 'iface'.
This involves:
o Making sure the candidate defines all the necessary methods
o Making sure the methods have the correct signature
o Making sure the candidate asserts that it implements the interface
Note that this isn't the same as verifying that the class does
implement the interface.
If optional tentative is true, suppress the "is implemented by" test.
"""
if vtype == 'c':
tester = iface.implementedBy
else:
tester = iface.providedBy
if not tentative and not tester(candidate):
raise DoesNotImplement(iface)
# Here the `desc` is either an `Attribute` or `Method` instance
for name, desc in iface.namesAndDescriptions(1):
try:
attr = getattr(candidate, name)
except AttributeError:
if (not isinstance(desc, Method)) and vtype == 'c':
# We can't verify non-methods on classes, since the
# class may provide attrs in it's __init__.
continue
raise BrokenImplementation(iface, name)
if not isinstance(desc, Method):
# If it's not a method, there's nothing else we can test
continue
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) #pragma NO COVERAGE
else:
# Nope, just a normal function
meth = fromFunction(attr, iface, name=name)
elif (isinstance(attr, MethodTypes)
and type(attr.__func__) is FunctionType):
meth = fromMethod(attr, iface, name)
elif isinstance(attr, property) and vtype == 'c':
# We without an instance we cannot be sure it's not a
# callable.
continue
else:
if not callable(attr):
raise BrokenMethodImplementation(name, "Not a method")
# sigh, it's callable, but we don't know how to introspect it, so
# we have to give it a pass.
continue #pragma NO COVERAGE
# Make sure that the required and implemented method signatures are
# the same.
desc = desc.getSignatureInfo()
meth = meth.getSignatureInfo()
mess = _incompat(desc, meth)
if mess:
raise BrokenMethodImplementation(name, mess)
return True
def verifyClass(iface, candidate, tentative=0):
return _verify(iface, candidate, tentative, vtype='c')
def verifyObject(iface, candidate, tentative=0):
return _verify(iface, candidate, tentative, vtype='o')
def _incompat(required, implemented):
#if (required['positional'] !=
# implemented['positional'][:len(required['positional'])]
# and implemented['kwargs'] is None):
# return 'imlementation has different argument names'
if len(implemented['required']) > len(required['required']):
return 'implementation requires too many arguments'
if ((len(implemented['positional']) < len(required['positional']))
and not implemented['varargs']):
return "implementation doesn't allow enough arguments"
if required['kwargs'] and not implemented['kwargs']:
return "implementation doesn't support keyword arguments"
if required['varargs'] and not implemented['varargs']:
return "implementation doesn't support variable arguments"
zope.interface-4.3.2/src/zope/interface/ro.py 0000664 0001750 0001750 00000003724 12763206174 020202 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Compute a resolution order for an object and its bases
"""
__docformat__ = 'restructuredtext'
def _mergeOrderings(orderings):
"""Merge multiple orderings so that within-ordering order is preserved
Orderings are constrained in such a way that if an object appears
in two or more orderings, then the suffix that begins with the
object must be in both orderings.
For example:
>>> _mergeOrderings([
... ['x', 'y', 'z'],
... ['q', 'z'],
... [1, 3, 5],
... ['z']
... ])
['x', 'y', 'q', 1, 3, 5, 'z']
"""
seen = {}
result = []
for ordering in reversed(orderings):
for o in reversed(ordering):
if o not in seen:
seen[o] = 1
result.insert(0, o)
return result
def _flatten(ob):
result = [ob]
i = 0
for ob in iter(result):
i += 1
# The recursive calls can be avoided by inserting the base classes
# into the dynamically growing list directly after the currently
# considered object; the iterator makes sure this will keep working
# in the future, since it cannot rely on the length of the list
# by definition.
result[i:i] = ob.__bases__
return result
def ro(object):
"""Compute a "resolution order" for an object
"""
return _mergeOrderings([_flatten(object)])
zope.interface-4.3.2/src/zope/interface/registry.py 0000664 0001750 0001750 00000054763 12763206174 021443 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""Basic components support
"""
from collections import defaultdict
import weakref
try:
from zope.event import notify
except ImportError: # pragma: no cover
def notify(*arg, **kw): pass
from zope.interface.interfaces import ISpecification
from zope.interface.interfaces import ComponentLookupError
from zope.interface.interfaces import IAdapterRegistration
from zope.interface.interfaces import IComponents
from zope.interface.interfaces import IHandlerRegistration
from zope.interface.interfaces import ISubscriptionAdapterRegistration
from zope.interface.interfaces import IUtilityRegistration
from zope.interface.interfaces import Registered
from zope.interface.interfaces import Unregistered
from zope.interface.interface import Interface
from zope.interface.declarations import implementedBy
from zope.interface.declarations import implementer
from zope.interface.declarations import implementer_only
from zope.interface.declarations import providedBy
from zope.interface.adapter import AdapterRegistry
from zope.interface._compat import CLASS_TYPES
from zope.interface._compat import STRING_TYPES
class _UnhashableComponentCounter(object):
# defaultdict(int)-like object for unhashable components
def __init__(self, otherdict):
# [(component, count)]
self._data = [item for item in otherdict.items()]
def __getitem__(self, key):
for component, count in self._data:
if component == key:
return count
return 0
def __setitem__(self, component, count):
for i, data in enumerate(self._data):
if data[0] == component:
self._data[i] = component, count
return
self._data.append((component, count))
def __delitem__(self, component):
for i, data in enumerate(self._data):
if data[0] == component:
del self._data[i]
return
raise KeyError(component) # pragma: no cover
class _UtilityRegistrations(object):
_regs_for_components = {}
_weakrefs_for_components = {}
@classmethod
def for_components(cls, components):
# We manage these utility/subscription registrations as associated
# objects with a weakref to avoid making any changes to
# the pickle format. They are keyed off the id of the component because
# Components subclasses are not guaranteed to be hashable.
key = id(components)
try:
regs = cls._regs_for_components[key]
except KeyError:
regs = None
else:
# In case the components have been re-initted, clear the cache
# (zope.component.testing does this between tests)
if (regs._utilities is not components.utilities
or regs._utility_registrations is not components._utility_registrations):
regs = None
if regs is None:
regs = cls(components.utilities, components._utility_registrations)
cls._regs_for_components[key] = regs
if key not in cls._weakrefs_for_components:
def _cleanup(r):
cls._weakrefs_for_components.pop(key)
cls._regs_for_components.pop(key)
cls._weakrefs_for_components[key] = weakref.ref(components, _cleanup)
return regs
@classmethod
def clear_cache(cls):
cls._regs_for_components.clear()
def __init__(self, utilities, utility_registrations):
# {provided -> {component: count}}
self._cache = defaultdict(lambda: defaultdict(int))
self._utilities = utilities
self._utility_registrations = utility_registrations
self.__populate_cache()
def __populate_cache(self):
for ((p, _), data) in iter(self._utility_registrations.items()):
component = data[0]
self.__cache_utility(p, component)
def __cache_utility(self, provided, component):
try:
self._cache[provided][component] += 1
except TypeError:
# The component is not hashable, and we have a dict. Switch to a strategy
# that doesn't use hashing.
prov = self._cache[provided] = _UnhashableComponentCounter(self._cache[provided])
prov[component] += 1
def __uncache_utility(self, provided, component):
provided = self._cache[provided]
# It seems like this line could raise a TypeError if component isn't
# hashable and we haven't yet switched to _UnhashableComponentCounter. However,
# we can't actually get in that situation. In order to get here, we would
# have had to cache the utility already which would have switched
# the datastructure if needed.
count = provided[component]
count -= 1
if count == 0:
del provided[component]
else:
provided[component] = count
return count > 0
def _is_utility_subscribed(self, provided, component):
try:
return self._cache[provided][component] > 0
except TypeError:
# Not hashable and we're still using a dict
return False
def registerUtility(self, provided, name, component, info, factory):
subscribed = self._is_utility_subscribed(provided, component)
self._utility_registrations[(provided, name)] = component, info, factory
self._utilities.register((), provided, name, component)
if not subscribed:
self._utilities.subscribe((), provided, component)
self.__cache_utility(provided, component)
def unregisterUtility(self, provided, name, component):
del self._utility_registrations[(provided, name)]
self._utilities.unregister((), provided, name)
subscribed = self.__uncache_utility(provided, component)
if not subscribed:
self._utilities.unsubscribe((), provided, component)
@implementer(IComponents)
class Components(object):
def __init__(self, name='', bases=()):
assert isinstance(name, STRING_TYPES)
self.__name__ = name
self._init_registries()
self._init_registrations()
self.__bases__ = tuple(bases)
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, self.__name__)
def _init_registries(self):
self.adapters = AdapterRegistry()
self.utilities = AdapterRegistry()
def _init_registrations(self):
self._utility_registrations = {}
self._adapter_registrations = {}
self._subscription_registrations = []
self._handler_registrations = []
def _getBases(self):
# Subclasses might override
return self.__dict__.get('__bases__', ())
def _setBases(self, bases):
# Subclasses might override
self.adapters.__bases__ = tuple([
base.adapters for base in bases])
self.utilities.__bases__ = tuple([
base.utilities for base in bases])
self.__dict__['__bases__'] = tuple(bases)
__bases__ = property(
lambda self: self._getBases(),
lambda self, bases: self._setBases(bases),
)
def registerUtility(self, component=None, provided=None, name=u'',
info=u'', event=True, factory=None):
if factory:
if component:
raise TypeError("Can't specify factory and component.")
component = factory()
if provided is None:
provided = _getUtilityProvided(component)
if name == u'':
name = _getName(component)
reg = self._utility_registrations.get((provided, name))
if reg is not None:
if reg[:2] == (component, info):
# already registered
return
self.unregisterUtility(reg[0], provided, name)
_UtilityRegistrations.for_components(self).registerUtility(provided, name, component, info, factory)
if event:
notify(Registered(
UtilityRegistration(self, provided, name, component, info,
factory)
))
def unregisterUtility(self, component=None, provided=None, name=u'',
factory=None):
if factory:
if component:
raise TypeError("Can't specify factory and component.")
component = factory()
if provided is None:
if component is None:
raise TypeError("Must specify one of component, factory and "
"provided")
provided = _getUtilityProvided(component)
old = self._utility_registrations.get((provided, name))
if (old is None) or ((component is not None) and
(component != old[0])):
return False
if component is None:
component = old[0]
# Note that component is now the old thing registered
_UtilityRegistrations.for_components(self).unregisterUtility(provided, name, component)
notify(Unregistered(
UtilityRegistration(self, provided, name, component, *old[1:])
))
return True
def registeredUtilities(self):
for ((provided, name), data
) in iter(self._utility_registrations.items()):
yield UtilityRegistration(self, provided, name, *data)
def queryUtility(self, provided, name=u'', default=None):
return self.utilities.lookup((), provided, name, default)
def getUtility(self, provided, name=u''):
utility = self.utilities.lookup((), provided, name)
if utility is None:
raise ComponentLookupError(provided, name)
return utility
def getUtilitiesFor(self, interface):
for name, utility in self.utilities.lookupAll((), interface):
yield name, utility
def getAllUtilitiesRegisteredFor(self, interface):
return self.utilities.subscriptions((), interface)
def registerAdapter(self, factory, required=None, provided=None,
name=u'', info=u'', event=True):
if provided is None:
provided = _getAdapterProvided(factory)
required = _getAdapterRequired(factory, required)
if name == u'':
name = _getName(factory)
self._adapter_registrations[(required, provided, name)
] = factory, info
self.adapters.register(required, provided, name, factory)
if event:
notify(Registered(
AdapterRegistration(self, required, provided, name,
factory, info)
))
def unregisterAdapter(self, factory=None,
required=None, provided=None, name=u'',
):
if provided is None:
if factory is None:
raise TypeError("Must specify one of factory and provided")
provided = _getAdapterProvided(factory)
if (required is None) and (factory is None):
raise TypeError("Must specify one of factory and required")
required = _getAdapterRequired(factory, required)
old = self._adapter_registrations.get((required, provided, name))
if (old is None) or ((factory is not None) and
(factory != old[0])):
return False
del self._adapter_registrations[(required, provided, name)]
self.adapters.unregister(required, provided, name)
notify(Unregistered(
AdapterRegistration(self, required, provided, name,
*old)
))
return True
def registeredAdapters(self):
for ((required, provided, name), (component, info)
) in iter(self._adapter_registrations.items()):
yield AdapterRegistration(self, required, provided, name,
component, info)
def queryAdapter(self, object, interface, name=u'', default=None):
return self.adapters.queryAdapter(object, interface, name, default)
def getAdapter(self, object, interface, name=u''):
adapter = self.adapters.queryAdapter(object, interface, name)
if adapter is None:
raise ComponentLookupError(object, interface, name)
return adapter
def queryMultiAdapter(self, objects, interface, name=u'',
default=None):
return self.adapters.queryMultiAdapter(
objects, interface, name, default)
def getMultiAdapter(self, objects, interface, name=u''):
adapter = self.adapters.queryMultiAdapter(objects, interface, name)
if adapter is None:
raise ComponentLookupError(objects, interface, name)
return adapter
def getAdapters(self, objects, provided):
for name, factory in self.adapters.lookupAll(
list(map(providedBy, objects)),
provided):
adapter = factory(*objects)
if adapter is not None:
yield name, adapter
def registerSubscriptionAdapter(self,
factory, required=None, provided=None,
name=u'', info=u'',
event=True):
if name:
raise TypeError("Named subscribers are not yet supported")
if provided is None:
provided = _getAdapterProvided(factory)
required = _getAdapterRequired(factory, required)
self._subscription_registrations.append(
(required, provided, name, factory, info)
)
self.adapters.subscribe(required, provided, factory)
if event:
notify(Registered(
SubscriptionRegistration(self, required, provided, name,
factory, info)
))
def registeredSubscriptionAdapters(self):
for data in self._subscription_registrations:
yield SubscriptionRegistration(self, *data)
def unregisterSubscriptionAdapter(self, factory=None,
required=None, provided=None, name=u'',
):
if name:
raise TypeError("Named subscribers are not yet supported")
if provided is None:
if factory is None:
raise TypeError("Must specify one of factory and provided")
provided = _getAdapterProvided(factory)
if (required is None) and (factory is None):
raise TypeError("Must specify one of factory and required")
required = _getAdapterRequired(factory, required)
if factory is None:
new = [(r, p, n, f, i)
for (r, p, n, f, i)
in self._subscription_registrations
if not (r == required and p == provided)
]
else:
new = [(r, p, n, f, i)
for (r, p, n, f, i)
in self._subscription_registrations
if not (r == required and p == provided and f == factory)
]
if len(new) == len(self._subscription_registrations):
return False
self._subscription_registrations[:] = new
self.adapters.unsubscribe(required, provided, factory)
notify(Unregistered(
SubscriptionRegistration(self, required, provided, name,
factory, '')
))
return True
def subscribers(self, objects, provided):
return self.adapters.subscribers(objects, provided)
def registerHandler(self,
factory, required=None,
name=u'', info=u'',
event=True):
if name:
raise TypeError("Named handlers are not yet supported")
required = _getAdapterRequired(factory, required)
self._handler_registrations.append(
(required, name, factory, info)
)
self.adapters.subscribe(required, None, factory)
if event:
notify(Registered(
HandlerRegistration(self, required, name, factory, info)
))
def registeredHandlers(self):
for data in self._handler_registrations:
yield HandlerRegistration(self, *data)
def unregisterHandler(self, factory=None, required=None, name=u''):
if name:
raise TypeError("Named subscribers are not yet supported")
if (required is None) and (factory is None):
raise TypeError("Must specify one of factory and required")
required = _getAdapterRequired(factory, required)
if factory is None:
new = [(r, n, f, i)
for (r, n, f, i)
in self._handler_registrations
if r != required
]
else:
new = [(r, n, f, i)
for (r, n, f, i)
in self._handler_registrations
if not (r == required and f == factory)
]
if len(new) == len(self._handler_registrations):
return False
self._handler_registrations[:] = new
self.adapters.unsubscribe(required, None, factory)
notify(Unregistered(
HandlerRegistration(self, required, name, factory, '')
))
return True
def handle(self, *objects):
self.adapters.subscribers(objects, None)
def _getName(component):
try:
return component.__component_name__
except AttributeError:
return u''
def _getUtilityProvided(component):
provided = list(providedBy(component))
if len(provided) == 1:
return provided[0]
raise TypeError(
"The utility doesn't provide a single interface "
"and no provided interface was specified.")
def _getAdapterProvided(factory):
provided = list(implementedBy(factory))
if len(provided) == 1:
return provided[0]
raise TypeError(
"The adapter factory doesn't implement a single interface "
"and no provided interface was specified.")
def _getAdapterRequired(factory, required):
if required is None:
try:
required = factory.__component_adapts__
except AttributeError:
raise TypeError(
"The adapter factory doesn't have a __component_adapts__ "
"attribute and no required specifications were specified"
)
elif ISpecification.providedBy(required):
raise TypeError("the required argument should be a list of "
"interfaces, not a single interface")
result = []
for r in required:
if r is None:
r = Interface
elif not ISpecification.providedBy(r):
if isinstance(r, CLASS_TYPES):
r = implementedBy(r)
else:
raise TypeError("Required specification must be a "
"specification or class."
)
result.append(r)
return tuple(result)
@implementer(IUtilityRegistration)
class UtilityRegistration(object):
def __init__(self, registry, provided, name, component, doc, factory=None):
(self.registry, self.provided, self.name, self.component, self.info,
self.factory
) = registry, provided, name, component, doc, factory
def __repr__(self):
return '%s(%r, %s, %r, %s, %r, %r)' % (
self.__class__.__name__,
self.registry,
getattr(self.provided, '__name__', None), self.name,
getattr(self.component, '__name__', repr(self.component)),
self.factory, self.info,
)
def __hash__(self):
return id(self)
def __eq__(self, other):
return repr(self) == repr(other)
def __ne__(self, other):
return repr(self) != repr(other)
def __lt__(self, other):
return repr(self) < repr(other)
def __le__(self, other):
return repr(self) <= repr(other)
def __gt__(self, other):
return repr(self) > repr(other)
def __ge__(self, other):
return repr(self) >= repr(other)
@implementer(IAdapterRegistration)
class AdapterRegistration(object):
def __init__(self, registry, required, provided, name, component, doc):
(self.registry, self.required, self.provided, self.name,
self.factory, self.info
) = registry, required, provided, name, component, doc
def __repr__(self):
return '%s(%r, %s, %s, %r, %s, %r)' % (
self.__class__.__name__,
self.registry,
'[' + ", ".join([r.__name__ for r in self.required]) + ']',
getattr(self.provided, '__name__', None), self.name,
getattr(self.factory, '__name__', repr(self.factory)), self.info,
)
def __hash__(self):
return id(self)
def __eq__(self, other):
return repr(self) == repr(other)
def __ne__(self, other):
return repr(self) != repr(other)
def __lt__(self, other):
return repr(self) < repr(other)
def __le__(self, other):
return repr(self) <= repr(other)
def __gt__(self, other):
return repr(self) > repr(other)
def __ge__(self, other):
return repr(self) >= repr(other)
@implementer_only(ISubscriptionAdapterRegistration)
class SubscriptionRegistration(AdapterRegistration):
pass
@implementer_only(IHandlerRegistration)
class HandlerRegistration(AdapterRegistration):
def __init__(self, registry, required, name, handler, doc):
(self.registry, self.required, self.name, self.handler, self.info
) = registry, required, name, handler, doc
@property
def factory(self):
return self.handler
provided = None
def __repr__(self):
return '%s(%r, %s, %r, %s, %r)' % (
self.__class__.__name__,
self.registry,
'[' + ", ".join([r.__name__ for r in self.required]) + ']',
self.name,
getattr(self.factory, '__name__', repr(self.factory)), self.info,
)
zope.interface-4.3.2/src/zope/interface/interfaces.py 0000664 0001750 0001750 00000124100 12763206174 021675 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 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 Package Interfaces
"""
__docformat__ = 'restructuredtext'
from zope.interface.interface import Attribute
from zope.interface.interface import Interface
from zope.interface.declarations import implementer
_BLANK = u''
class IElement(Interface):
"""Objects that have basic documentation and tagged values.
"""
__name__ = Attribute('__name__', 'The object name')
__doc__ = Attribute('__doc__', 'The object doc string')
def getTaggedValue(tag):
"""Returns the value associated with `tag`.
Raise a `KeyError` of the tag isn't set.
"""
def queryTaggedValue(tag, default=None):
"""Returns the value associated with `tag`.
Return the default value of the tag isn't set.
"""
def getTaggedValueTags():
"""Returns a list of all tags."""
def setTaggedValue(tag, value):
"""Associates `value` with `key`."""
class IAttribute(IElement):
"""Attribute descriptors"""
interface = Attribute('interface',
'Stores the interface instance in which the '
'attribute is located.')
class IMethod(IAttribute):
"""Method attributes"""
def getSignatureInfo():
"""Returns the signature information.
This method returns a dictionary with the following keys:
o `positional` - All positional arguments.
o `required` - A list of all required arguments.
o `optional` - A list of all optional arguments.
o `varargs` - The name of the varargs argument.
o `kwargs` - The name of the kwargs argument.
"""
def getSignatureString():
"""Return a signature string suitable for inclusion in documentation.
This method returns the function signature string. For example, if you
have `func(a, b, c=1, d='f')`, then the signature string is `(a, b,
c=1, d='f')`.
"""
class ISpecification(Interface):
"""Object Behavioral specifications"""
def providedBy(object):
"""Test whether the interface is implemented by the object
Return true of the object asserts that it implements the
interface, including asserting that it implements an extended
interface.
"""
def implementedBy(class_):
"""Test whether the interface is implemented by instances of the class
Return true of the class asserts that its instances implement the
interface, including asserting that they implement an extended
interface.
"""
def isOrExtends(other):
"""Test whether the specification is or extends another
"""
def extends(other, strict=True):
"""Test whether a specification extends another
The specification extends other if it has other as a base
interface or if one of it's bases extends other.
If strict is false, then the specification extends itself.
"""
def weakref(callback=None):
"""Return a weakref to the specification
This method is, regrettably, needed to allow weakrefs to be
computed to security-proxied specifications. While the
zope.interface package does not require zope.security or
zope.proxy, it has to be able to coexist with it.
"""
__bases__ = Attribute("""Base specifications
A tuple if specifications from which this specification is
directly derived.
""")
__sro__ = Attribute("""Specification-resolution order
A tuple of the specification and all of it's ancestor
specifications from most specific to least specific.
(This is similar to the method-resolution order for new-style classes.)
""")
__iro__ = Attribute("""Interface-resolution order
A tuple of the of the specification's ancestor interfaces from
most specific to least specific. The specification itself is
included if it is an interface.
(This is similar to the method-resolution order for new-style classes.)
""")
def get(name, default=None):
"""Look up the description for a name
If the named attribute is not defined, the default is
returned.
"""
class IInterface(ISpecification, IElement):
"""Interface objects
Interface objects describe the behavior of an object by containing
useful information about the object. This information includes:
o Prose documentation about the object. In Python terms, this
is called the "doc string" of the interface. In this element,
you describe how the object works in prose language and any
other useful information about the object.
o Descriptions of attributes. Attribute descriptions include
the name of the attribute and prose documentation describing
the attributes usage.
o Descriptions of methods. Method descriptions can include:
- Prose "doc string" documentation about the method and its
usage.
- A description of the methods arguments; how many arguments
are expected, optional arguments and their default values,
the position or arguments in the signature, whether the
method accepts arbitrary arguments and whether the method
accepts arbitrary keyword arguments.
o Optional tagged data. Interface objects (and their attributes and
methods) can have optional, application specific tagged data
associated with them. Examples uses for this are examples,
security assertions, pre/post conditions, and other possible
information you may want to associate with an Interface or its
attributes.
Not all of this information is mandatory. For example, you may
only want the methods of your interface to have prose
documentation and not describe the arguments of the method in
exact detail. Interface objects are flexible and let you give or
take any of these components.
Interfaces are created with the Python class statement using
either Interface.Interface or another interface, as in::
from zope.interface import Interface
class IMyInterface(Interface):
'''Interface documentation'''
def meth(arg1, arg2):
'''Documentation for meth'''
# Note that there is no self argument
class IMySubInterface(IMyInterface):
'''Interface documentation'''
def meth2():
'''Documentation for meth2'''
You use interfaces in two ways:
o You assert that your object implement the interfaces.
There are several ways that you can assert that an object
implements an interface:
1. Call zope.interface.implements in your class definition.
2. Call zope.interfaces.directlyProvides on your object.
3. Call 'zope.interface.classImplements' to assert that instances
of a class implement an interface.
For example::
from zope.interface import classImplements
classImplements(some_class, some_interface)
This approach is useful when it is not an option to modify
the class source. Note that this doesn't affect what the
class itself implements, but only what its instances
implement.
o You query interface meta-data. See the IInterface methods and
attributes for details.
"""
def names(all=False):
"""Get the interface attribute names
Return a sequence of the names of the attributes, including
methods, included in the interface definition.
Normally, only directly defined attributes are included. If
a true positional or keyword argument is given, then
attributes defined by base classes will be included.
"""
def namesAndDescriptions(all=False):
"""Get the interface attribute names and descriptions
Return a sequence of the names and descriptions of the
attributes, including methods, as name-value pairs, included
in the interface definition.
Normally, only directly defined attributes are included. If
a true positional or keyword argument is given, then
attributes defined by base classes will be included.
"""
def __getitem__(name):
"""Get the description for a name
If the named attribute is not defined, a KeyError is raised.
"""
def direct(name):
"""Get the description for the name if it was defined by the interface
If the interface doesn't define the name, returns None.
"""
def validateInvariants(obj, errors=None):
"""Validate invariants
Validate object to defined invariants. If errors is None,
raises first Invalid error; if errors is a list, appends all errors
to list, then raises Invalid with the errors as the first element
of the "args" tuple."""
def __contains__(name):
"""Test whether the name is defined by the interface"""
def __iter__():
"""Return an iterator over the names defined by the interface
The names iterated include all of the names defined by the
interface directly and indirectly by base interfaces.
"""
__module__ = Attribute("""The name of the module defining the interface""")
class IDeclaration(ISpecification):
"""Interface declaration
Declarations are used to express the interfaces implemented by
classes or provided by objects.
"""
def __contains__(interface):
"""Test whether an interface is in the specification
Return true if the given interface is one of the interfaces in
the specification and false otherwise.
"""
def __iter__():
"""Return an iterator for the interfaces in the specification
"""
def flattened():
"""Return an iterator of all included and extended interfaces
An iterator is returned for all interfaces either included in
or extended by interfaces included in the specifications
without duplicates. The interfaces are in "interface
resolution order". The interface resolution order is such that
base interfaces are listed after interfaces that extend them
and, otherwise, interfaces are included in the order that they
were defined in the specification.
"""
def __sub__(interfaces):
"""Create an interface specification with some interfaces excluded
The argument can be an interface or an interface
specifications. The interface or interfaces given in a
specification are subtracted from the interface specification.
Removing an interface that is not in the specification does
not raise an error. Doing so has no effect.
Removing an interface also removes sub-interfaces of the interface.
"""
def __add__(interfaces):
"""Create an interface specification with some interfaces added
The argument can be an interface or an interface
specifications. The interface or interfaces given in a
specification are added to the interface specification.
Adding an interface that is already in the specification does
not raise an error. Doing so has no effect.
"""
def __nonzero__():
"""Return a true value of the interface specification is non-empty
"""
class IInterfaceDeclaration(Interface):
"""Declare and check the interfaces of objects
The functions defined in this interface are used to declare the
interfaces that objects provide and to query the interfaces that have
been declared.
Interfaces can be declared for objects in two ways:
- Interfaces are declared for instances of the object's class
- Interfaces are declared for the object directly.
The interfaces declared for an object are, therefore, the union of
interfaces declared for the object directly and the interfaces
declared for instances of the object's class.
Note that we say that a class implements the interfaces provided
by it's instances. An instance can also provide interfaces
directly. The interfaces provided by an object are the union of
the interfaces provided directly and the interfaces implemented by
the class.
"""
def providedBy(ob):
"""Return the interfaces provided by an object
This is the union of the interfaces directly provided by an
object and interfaces implemented by it's class.
The value returned is an IDeclaration.
"""
def implementedBy(class_):
"""Return the interfaces implemented for a class' instances
The value returned is an IDeclaration.
"""
def classImplements(class_, *interfaces):
"""Declare additional interfaces implemented for instances of a class
The arguments after the class are one or more interfaces or
interface specifications (IDeclaration objects).
The interfaces given (including the interfaces in the
specifications) are added to any interfaces previously
declared.
Consider the following example::
class C(A, B):
...
classImplements(C, I1, I2)
Instances of ``C`` provide ``I1``, ``I2``, and whatever interfaces
instances of ``A`` and ``B`` provide.
"""
def implementer(*interfaces):
"""Create a decorator for declaring interfaces implemented by a facory
A callable is returned that makes an implements declaration on
objects passed to it.
"""
def classImplementsOnly(class_, *interfaces):
"""Declare the only interfaces implemented by instances of a class
The arguments after the class are one or more interfaces or
interface specifications (IDeclaration objects).
The interfaces given (including the interfaces in the
specifications) replace any previous declarations.
Consider the following example::
class C(A, B):
...
classImplements(C, IA, IB. IC)
classImplementsOnly(C. I1, I2)
Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
whatever interfaces instances of ``A`` and ``B`` implement.
"""
def implementer_only(*interfaces):
"""Create a decorator for declaring the only interfaces implemented
A callable is returned that makes an implements declaration on
objects passed to it.
"""
def directlyProvidedBy(object):
"""Return the interfaces directly provided by the given object
The value returned is an IDeclaration.
"""
def directlyProvides(object, *interfaces):
"""Declare interfaces declared directly for an object
The arguments after the object are one or more interfaces or
interface specifications (IDeclaration objects).
The interfaces given (including the interfaces in the
specifications) replace interfaces previously
declared for the object.
Consider the following example::
class C(A, B):
...
ob = C()
directlyProvides(ob, I1, I2)
The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
instances have been declared for instances of ``C``.
To remove directly provided interfaces, use ``directlyProvidedBy`` and
subtract the unwanted interfaces. For example::
directlyProvides(ob, directlyProvidedBy(ob)-I2)
removes I2 from the interfaces directly provided by
``ob``. The object, ``ob`` no longer directly provides ``I2``,
although it might still provide ``I2`` if it's class
implements ``I2``.
To add directly provided interfaces, use ``directlyProvidedBy`` and
include additional interfaces. For example::
directlyProvides(ob, directlyProvidedBy(ob), I2)
adds I2 to the interfaces directly provided by ob.
"""
def alsoProvides(object, *interfaces):
"""Declare additional interfaces directly for an object::
alsoProvides(ob, I1)
is equivalent to::
directlyProvides(ob, directlyProvidedBy(ob), I1)
"""
def noLongerProvides(object, interface):
"""Remove an interface from the list of an object's directly
provided interfaces::
noLongerProvides(ob, I1)
is equivalent to::
directlyProvides(ob, directlyProvidedBy(ob)-I1)
with the exception that if ``I1`` is an interface that is
provided by ``ob`` through the class's implementation,
ValueError is raised.
"""
def implements(*interfaces):
"""Declare interfaces implemented by instances of a class
This function is called in a class definition (Python 2.x only).
The arguments are one or more interfaces or interface
specifications (IDeclaration objects).
The interfaces given (including the interfaces in the
specifications) are added to any interfaces previously
declared.
Previous declarations include declarations for base classes
unless implementsOnly was used.
This function is provided for convenience. It provides a more
convenient way to call classImplements. For example::
implements(I1)
is equivalent to calling::
classImplements(C, I1)
after the class has been created.
Consider the following example (Python 2.x only)::
class C(A, B):
implements(I1, I2)
Instances of ``C`` implement ``I1``, ``I2``, and whatever interfaces
instances of ``A`` and ``B`` implement.
"""
def implementsOnly(*interfaces):
"""Declare the only interfaces implemented by instances of a class
This function is called in a class definition (Python 2.x only).
The arguments are one or more interfaces or interface
specifications (IDeclaration objects).
Previous declarations including declarations for base classes
are overridden.
This function is provided for convenience. It provides a more
convenient way to call classImplementsOnly. For example::
implementsOnly(I1)
is equivalent to calling::
classImplementsOnly(I1)
after the class has been created.
Consider the following example (Python 2.x only)::
class C(A, B):
implementsOnly(I1, I2)
Instances of ``C`` implement ``I1``, ``I2``, regardless of what
instances of ``A`` and ``B`` implement.
"""
def classProvides(*interfaces):
"""Declare interfaces provided directly by a class
This function is called in a class definition.
The arguments are one or more interfaces or interface
specifications (IDeclaration objects).
The given interfaces (including the interfaces in the
specifications) are used to create the class's direct-object
interface specification. An error will be raised if the module
class has an direct interface specification. In other words, it is
an error to call this function more than once in a class
definition.
Note that the given interfaces have nothing to do with the
interfaces implemented by instances of the class.
This function is provided for convenience. It provides a more
convenient way to call directlyProvides for a class. For example::
classProvides(I1)
is equivalent to calling::
directlyProvides(theclass, I1)
after the class has been created.
"""
def provider(*interfaces):
"""A class decorator version of classProvides"""
def moduleProvides(*interfaces):
"""Declare interfaces provided by a module
This function is used in a module definition.
The arguments are one or more interfaces or interface
specifications (IDeclaration objects).
The given interfaces (including the interfaces in the
specifications) are used to create the module's direct-object
interface specification. An error will be raised if the module
already has an interface specification. In other words, it is
an error to call this function more than once in a module
definition.
This function is provided for convenience. It provides a more
convenient way to call directlyProvides for a module. For example::
moduleImplements(I1)
is equivalent to::
directlyProvides(sys.modules[__name__], I1)
"""
def Declaration(*interfaces):
"""Create an interface specification
The arguments are one or more interfaces or interface
specifications (IDeclaration objects).
A new interface specification (IDeclaration) with
the given interfaces is returned.
"""
class IAdapterRegistry(Interface):
"""Provide an interface-based registry for adapters
This registry registers objects that are in some sense "from" a
sequence of specification to an interface and a name.
No specific semantics are assumed for the registered objects,
however, the most common application will be to register factories
that adapt objects providing required specifications to a provided
interface.
"""
def register(required, provided, name, value):
"""Register a value
A value is registered for a *sequence* of required specifications, a
provided interface, and a name.
"""
def registered(required, provided, name=_BLANK):
"""Return the component registered for the given interfaces and name
Unlike the lookup method, this methods won't retrieve
components registered for more specific required interfaces or
less specific provided interfaces.
If no component was registered exactly for the given
interfaces and name, then None is returned.
"""
def lookup(required, provided, name='', default=None):
"""Lookup a value
A value is looked up based on a *sequence* of required
specifications, a provided interface, and a name.
"""
def queryMultiAdapter(objects, provided, name=_BLANK, default=None):
"""Adapt a sequence of objects to a named, provided, interface
"""
def lookup1(required, provided, name=_BLANK, default=None):
"""Lookup a value using a single required interface
A value is looked up based on a single required
specifications, a provided interface, and a name.
"""
def queryAdapter(object, provided, name=_BLANK, default=None):
"""Adapt an object using a registered adapter factory.
"""
def adapter_hook(provided, object, name=_BLANK, default=None):
"""Adapt an object using a registered adapter factory.
"""
def lookupAll(required, provided):
"""Find all adapters from the required to the provided interfaces
An iterable object is returned that provides name-value two-tuples.
"""
def names(required, provided):
"""Return the names for which there are registered objects
"""
def subscribe(required, provided, subscriber, name=_BLANK):
"""Register a subscriber
A subscriber is registered for a *sequence* of required
specifications, a provided interface, and a name.
Multiple subscribers may be registered for the same (or
equivalent) interfaces.
"""
def subscriptions(required, provided, name=_BLANK):
"""Get a sequence of subscribers
Subscribers for a *sequence* of required interfaces, and a provided
interface are returned.
"""
def subscribers(objects, provided, name=_BLANK):
"""Get a sequence of subscription adapters
"""
# begin formerly in zope.component
class ComponentLookupError(LookupError):
"""A component could not be found."""
class Invalid(Exception):
"""A component doesn't satisfy a promise."""
class IObjectEvent(Interface):
"""An event related to an object.
The object that generated this event is not necessarily the object
refered to by location.
"""
object = Attribute("The subject of the event.")
@implementer(IObjectEvent)
class ObjectEvent(object):
def __init__(self, object):
self.object = object
class IComponentLookup(Interface):
"""Component Manager for a Site
This object manages the components registered at a particular site. The
definition of a site is intentionally vague.
"""
adapters = Attribute(
"Adapter Registry to manage all registered adapters.")
utilities = Attribute(
"Adapter Registry to manage all registered utilities.")
def queryAdapter(object, interface, name=_BLANK, default=None):
"""Look for a named adapter to an interface for an object
If a matching adapter cannot be found, returns the default.
"""
def getAdapter(object, interface, name=_BLANK):
"""Look for a named adapter to an interface for an object
If a matching adapter cannot be found, a ComponentLookupError
is raised.
"""
def queryMultiAdapter(objects, interface, name=_BLANK, default=None):
"""Look for a multi-adapter to an interface for multiple objects
If a matching adapter cannot be found, returns the default.
"""
def getMultiAdapter(objects, interface, name=_BLANK):
"""Look for a multi-adapter to an interface for multiple objects
If a matching adapter cannot be found, a ComponentLookupError
is raised.
"""
def getAdapters(objects, provided):
"""Look for all matching adapters to a provided interface for objects
Return an iterable of name-adapter pairs for adapters that
provide the given interface.
"""
def subscribers(objects, provided):
"""Get subscribers
Subscribers are returned that provide the provided interface
and that depend on and are comuted from the sequence of
required objects.
"""
def handle(*objects):
"""Call handlers for the given objects
Handlers registered for the given objects are called.
"""
def queryUtility(interface, name='', default=None):
"""Look up a utility that provides an interface.
If one is not found, returns default.
"""
def getUtilitiesFor(interface):
"""Look up the registered utilities that provide an interface.
Returns an iterable of name-utility pairs.
"""
def getAllUtilitiesRegisteredFor(interface):
"""Return all registered utilities for an interface
This includes overridden utilities.
An iterable of utility instances is returned. No names are
returned.
"""
class IRegistration(Interface):
"""A registration-information object
"""
registry = Attribute("The registry having the registration")
name = Attribute("The registration name")
info = Attribute("""Information about the registration
This is information deemed useful to people browsing the
configuration of a system. It could, for example, include
commentary or information about the source of the configuration.
""")
class IUtilityRegistration(IRegistration):
"""Information about the registration of a utility
"""
factory = Attribute("The factory used to create the utility. Optional.")
component = Attribute("The object registered")
provided = Attribute("The interface provided by the component")
class _IBaseAdapterRegistration(IRegistration):
"""Information about the registration of an adapter
"""
factory = Attribute("The factory used to create adapters")
required = Attribute("""The adapted interfaces
This is a sequence of interfaces adapters by the registered
factory. The factory will be caled with a sequence of objects, as
positional arguments, that provide these interfaces.
""")
provided = Attribute("""The interface provided by the adapters.
This interface is implemented by the factory
""")
class IAdapterRegistration(_IBaseAdapterRegistration):
"""Information about the registration of an adapter
"""
class ISubscriptionAdapterRegistration(_IBaseAdapterRegistration):
"""Information about the registration of a subscription adapter
"""
class IHandlerRegistration(IRegistration):
handler = Attribute("An object called used to handle an event")
required = Attribute("""The handled interfaces
This is a sequence of interfaces handled by the registered
handler. The handler will be caled with a sequence of objects, as
positional arguments, that provide these interfaces.
""")
class IRegistrationEvent(IObjectEvent):
"""An event that involves a registration"""
@implementer(IRegistrationEvent)
class RegistrationEvent(ObjectEvent):
"""There has been a change in a registration
"""
def __repr__(self):
return "%s event:\n%r" % (self.__class__.__name__, self.object)
class IRegistered(IRegistrationEvent):
"""A component or factory was registered
"""
@implementer(IRegistered)
class Registered(RegistrationEvent):
pass
class IUnregistered(IRegistrationEvent):
"""A component or factory was unregistered
"""
@implementer(IUnregistered)
class Unregistered(RegistrationEvent):
"""A component or factory was unregistered
"""
pass
class IComponentRegistry(Interface):
"""Register components
"""
def registerUtility(component=None, provided=None, name=_BLANK,
info=_BLANK, factory=None):
"""Register a utility
factory
Factory for the component to be registerd.
component
The registered component
provided
This is the interface provided by the utility. If the
component provides a single interface, then this
argument is optional and the component-implemented
interface will be used.
name
The utility name.
info
An object that can be converted to a string to provide
information about the registration.
Only one of component and factory can be used.
A Registered event is generated with an IUtilityRegistration.
"""
def unregisterUtility(component=None, provided=None, name=_BLANK,
factory=None):
"""Unregister a utility
A boolean is returned indicating whether the registry was
changed. If the given component is None and there is no
component registered, or if the given component is not
None and is not registered, then the function returns
False, otherwise it returns True.
factory
Factory for the component to be unregisterd.
component
The registered component The given component can be
None, in which case any component registered to provide
the given provided interface with the given name is
unregistered.
provided
This is the interface provided by the utility. If the
component is not None and provides a single interface,
then this argument is optional and the
component-implemented interface will be used.
name
The utility name.
Only one of component and factory can be used.
An UnRegistered event is generated with an IUtilityRegistration.
"""
def registeredUtilities():
"""Return an iterable of IUtilityRegistration instances.
These registrations describe the current utility registrations
in the object.
"""
def registerAdapter(factory, required=None, provided=None, name=_BLANK,
info=_BLANK):
"""Register an adapter factory
Parameters:
factory
The object used to compute the adapter
required
This is a sequence of specifications for objects to be
adapted. If omitted, then the value of the factory's
__component_adapts__ attribute will be used. The
__component_adapts__ attribute is usually attribute is
normally set in class definitions using adapts
function, or for callables using the adapter
decorator. If the factory doesn't have a
__component_adapts__ adapts attribute, then this
argument is required.
provided
This is the interface provided by the adapter and
implemented by the factory. If the factory
implements a single interface, then this argument is
optional and the factory-implemented interface will be
used.
name
The adapter name.
info
An object that can be converted to a string to provide
information about the registration.
A Registered event is generated with an IAdapterRegistration.
"""
def unregisterAdapter(factory=None, required=None,
provided=None, name=_BLANK):
"""Register an adapter factory
A boolean is returned indicating whether the registry was
changed. If the given component is None and there is no
component registered, or if the given component is not
None and is not registered, then the function returns
False, otherwise it returns True.
Parameters:
factory
This is the object used to compute the adapter. The
factory can be None, in which case any factory
registered to implement the given provided interface
for the given required specifications with the given
name is unregistered.
required
This is a sequence of specifications for objects to be
adapted. If the factory is not None and the required
arguments is omitted, then the value of the factory's
__component_adapts__ attribute will be used. The
__component_adapts__ attribute attribute is normally
set in class definitions using adapts function, or for
callables using the adapter decorator. If the factory
is None or doesn't have a __component_adapts__ adapts
attribute, then this argument is required.
provided
This is the interface provided by the adapter and
implemented by the factory. If the factory is not
None and implements a single interface, then this
argument is optional and the factory-implemented
interface will be used.
name
The adapter name.
An Unregistered event is generated with an IAdapterRegistration.
"""
def registeredAdapters():
"""Return an iterable of IAdapterRegistration instances.
These registrations describe the current adapter registrations
in the object.
"""
def registerSubscriptionAdapter(factory, required=None, provides=None,
name=_BLANK, info=''):
"""Register a subscriber factory
Parameters:
factory
The object used to compute the adapter
required
This is a sequence of specifications for objects to be
adapted. If omitted, then the value of the factory's
__component_adapts__ attribute will be used. The
__component_adapts__ attribute is usually attribute is
normally set in class definitions using adapts
function, or for callables using the adapter
decorator. If the factory doesn't have a
__component_adapts__ adapts attribute, then this
argument is required.
provided
This is the interface provided by the adapter and
implemented by the factory. If the factory implements
a single interface, then this argument is optional and
the factory-implemented interface will be used.
name
The adapter name.
Currently, only the empty string is accepted. Other
strings will be accepted in the future when support for
named subscribers is added.
info
An object that can be converted to a string to provide
information about the registration.
A Registered event is generated with an
ISubscriptionAdapterRegistration.
"""
def unregisterSubscriptionAdapter(factory=None, required=None,
provides=None, name=_BLANK):
"""Unregister a subscriber factory.
A boolean is returned indicating whether the registry was
changed. If the given component is None and there is no
component registered, or if the given component is not
None and is not registered, then the function returns
False, otherwise it returns True.
Parameters:
factory
This is the object used to compute the adapter. The
factory can be None, in which case any factories
registered to implement the given provided interface
for the given required specifications with the given
name are unregistered.
required
This is a sequence of specifications for objects to be
adapted. If the factory is not None and the required
arguments is omitted, then the value of the factory's
__component_adapts__ attribute will be used. The
__component_adapts__ attribute attribute is normally
set in class definitions using adapts function, or for
callables using the adapter decorator. If the factory
is None or doesn't have a __component_adapts__ adapts
attribute, then this argument is required.
provided
This is the interface provided by the adapter and
implemented by the factory. If the factory is not
None implements a single interface, then this argument
is optional and the factory-implemented interface will
be used.
name
The adapter name.
Currently, only the empty string is accepted. Other
strings will be accepted in the future when support for
named subscribers is added.
An Unregistered event is generated with an
ISubscriptionAdapterRegistration.
"""
def registeredSubscriptionAdapters():
"""Return an iterable of ISubscriptionAdapterRegistration instances.
These registrations describe the current subscription adapter
registrations in the object.
"""
def registerHandler(handler, required=None, name=_BLANK, info=''):
"""Register a handler.
A handler is a subscriber that doesn't compute an adapter
but performs some function when called.
Parameters:
handler
The object used to handle some event represented by
the objects passed to it.
required
This is a sequence of specifications for objects to be
adapted. If omitted, then the value of the factory's
__component_adapts__ attribute will be used. The
__component_adapts__ attribute is usually attribute is
normally set in class definitions using adapts
function, or for callables using the adapter
decorator. If the factory doesn't have a
__component_adapts__ adapts attribute, then this
argument is required.
name
The handler name.
Currently, only the empty string is accepted. Other
strings will be accepted in the future when support for
named handlers is added.
info
An object that can be converted to a string to provide
information about the registration.
A Registered event is generated with an IHandlerRegistration.
"""
def unregisterHandler(handler=None, required=None, name=_BLANK):
"""Unregister a handler.
A handler is a subscriber that doesn't compute an adapter
but performs some function when called.
A boolean is returned indicating whether the registry was
changed.
Parameters:
handler
This is the object used to handle some event
represented by the objects passed to it. The handler
can be None, in which case any handlers registered for
the given required specifications with the given are
unregistered.
required
This is a sequence of specifications for objects to be
adapted. If omitted, then the value of the factory's
__component_adapts__ attribute will be used. The
__component_adapts__ attribute is usually attribute is
normally set in class definitions using adapts
function, or for callables using the adapter
decorator. If the factory doesn't have a
__component_adapts__ adapts attribute, then this
argument is required.
name
The handler name.
Currently, only the empty string is accepted. Other
strings will be accepted in the future when support for
named handlers is added.
An Unregistered event is generated with an IHandlerRegistration.
"""
def registeredHandlers():
"""Return an iterable of IHandlerRegistration instances.
These registrations describe the current handler registrations
in the object.
"""
class IComponents(IComponentLookup, IComponentRegistry):
"""Component registration and access
"""
# end formerly in zope.component
zope.interface-4.3.2/src/zope/interface/interface.py 0000664 0001750 0001750 00000047660 12763206174 021531 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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 object implementation
"""
from __future__ import generators
import sys
from types import MethodType
from types import FunctionType
import warnings
import weakref
from zope.interface.exceptions import Invalid
from zope.interface.ro import ro
CO_VARARGS = 4
CO_VARKEYWORDS = 8
TAGGED_DATA = '__interface_tagged_values__'
_decorator_non_return = object()
def invariant(call):
f_locals = sys._getframe(1).f_locals
tags = f_locals.setdefault(TAGGED_DATA, {})
invariants = tags.setdefault('invariants', [])
invariants.append(call)
return _decorator_non_return
def taggedValue(key, value):
"""Attaches a tagged value to an interface at definition time."""
f_locals = sys._getframe(1).f_locals
tagged_values = f_locals.setdefault(TAGGED_DATA, {})
tagged_values[key] = value
return _decorator_non_return
class Element(object):
# We can't say this yet because we don't have enough
# infrastructure in place.
#
#implements(IElement)
def __init__(self, __name__, __doc__=''):
"""Create an 'attribute' description
"""
if not __doc__ and __name__.find(' ') >= 0:
__doc__ = __name__
__name__ = None
self.__name__=__name__
self.__doc__=__doc__
self.__tagged_values = {}
def getName(self):
""" Returns the name of the object. """
return self.__name__
def getDoc(self):
""" Returns the documentation for the object. """
return self.__doc__
def getTaggedValue(self, tag):
""" Returns the value associated with 'tag'. """
return self.__tagged_values[tag]
def queryTaggedValue(self, tag, default=None):
""" Returns the value associated with 'tag'. """
return self.__tagged_values.get(tag, default)
def getTaggedValueTags(self):
""" Returns a list of all tags. """
return self.__tagged_values.keys()
def setTaggedValue(self, tag, value):
""" Associates 'value' with 'key'. """
self.__tagged_values[tag] = value
class SpecificationBasePy(object):
def providedBy(self, ob):
"""Is the interface implemented by an object
"""
spec = providedBy(ob)
return self in spec._implied
def implementedBy(self, cls):
"""Test whether the specification is implemented by a class or factory.
Raise TypeError if argument is neither a class nor a callable.
"""
spec = implementedBy(cls)
return self in spec._implied
def isOrExtends(self, interface):
"""Is the interface the same as or extend the given interface
"""
return interface in self._implied
__call__ = isOrExtends
SpecificationBase = SpecificationBasePy
try:
from _zope_interface_coptimizations import SpecificationBase
except ImportError: #pragma NO COVER
pass
_marker = object()
class InterfaceBasePy(object):
"""Base class that wants to be replaced with a C base :)
"""
def __call__(self, obj, alternate=_marker):
"""Adapt an object to the interface
"""
conform = getattr(obj, '__conform__', None)
if conform is not None:
adapter = self._call_conform(conform)
if adapter is not None:
return adapter
adapter = self.__adapt__(obj)
if adapter is not None:
return adapter
elif alternate is not _marker:
return alternate
else:
raise TypeError("Could not adapt", obj, self)
def __adapt__(self, obj):
"""Adapt an object to the reciever
"""
if self.providedBy(obj):
return obj
for hook in adapter_hooks:
adapter = hook(self, obj)
if adapter is not None:
return adapter
InterfaceBase = InterfaceBasePy
try:
from _zope_interface_coptimizations import InterfaceBase
except ImportError: #pragma NO COVER
pass
adapter_hooks = []
try:
from _zope_interface_coptimizations import adapter_hooks
except ImportError: #pragma NO COVER
pass
class Specification(SpecificationBase):
"""Specifications
An interface specification is used to track interface declarations
and component registrations.
This class is a base class for both interfaces themselves and for
interface specifications (declarations).
Specifications are mutable. If you reassign their bases, their
relations with other specifications are adjusted accordingly.
"""
# Copy some base class methods for speed
isOrExtends = SpecificationBase.isOrExtends
providedBy = SpecificationBase.providedBy
def __init__(self, bases=()):
self._implied = {}
self.dependents = weakref.WeakKeyDictionary()
self.__bases__ = tuple(bases)
def subscribe(self, dependent):
self.dependents[dependent] = self.dependents.get(dependent, 0) + 1
def unsubscribe(self, dependent):
n = self.dependents.get(dependent, 0) - 1
if not n:
del self.dependents[dependent]
elif n > 0:
self.dependents[dependent] = n
else:
raise KeyError(dependent)
def __setBases(self, bases):
# Register ourselves as a dependent of our old bases
for b in self.__bases__:
b.unsubscribe(self)
# Register ourselves as a dependent of our bases
self.__dict__['__bases__'] = bases
for b in bases:
b.subscribe(self)
self.changed(self)
__bases__ = property(
lambda self: self.__dict__.get('__bases__', ()),
__setBases,
)
def changed(self, originally_changed):
"""We, or something we depend on, have changed
"""
try:
del self._v_attrs
except AttributeError:
pass
implied = self._implied
implied.clear()
ancestors = ro(self)
try:
if Interface not in ancestors:
ancestors.append(Interface)
except NameError:
pass # defining Interface itself
self.__sro__ = tuple(ancestors)
self.__iro__ = tuple([ancestor for ancestor in ancestors
if isinstance(ancestor, InterfaceClass)
])
for ancestor in ancestors:
# We directly imply our ancestors:
implied[ancestor] = ()
# Now, advise our dependents of change:
for dependent in tuple(self.dependents.keys()):
dependent.changed(originally_changed)
def interfaces(self):
"""Return an iterator for the interfaces in the specification.
"""
seen = {}
for base in self.__bases__:
for interface in base.interfaces():
if interface not in seen:
seen[interface] = 1
yield interface
def extends(self, interface, strict=True):
"""Does the specification extend the given interface?
Test whether an interface in the specification extends the
given interface
"""
return ((interface in self._implied)
and
((not strict) or (self != interface))
)
def weakref(self, callback=None):
return weakref.ref(self, callback)
def get(self, name, default=None):
"""Query for an attribute description
"""
try:
attrs = self._v_attrs
except AttributeError:
attrs = self._v_attrs = {}
attr = attrs.get(name)
if attr is None:
for iface in self.__iro__:
attr = iface.direct(name)
if attr is not None:
attrs[name] = attr
break
if attr is None:
return default
else:
return attr
class InterfaceClass(Element, InterfaceBase, Specification):
"""Prototype (scarecrow) Interfaces Implementation."""
# We can't say this yet because we don't have enough
# infrastructure in place.
#
#implements(IInterface)
def __init__(self, name, bases=(), attrs=None, __doc__=None,
__module__=None):
if attrs is None:
attrs = {}
if __module__ is None:
__module__ = attrs.get('__module__')
if isinstance(__module__, str):
del attrs['__module__']
else:
try:
# Figure out what module defined the interface.
# 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): #pragma NO COVERAGE
pass
self.__module__ = __module__
d = attrs.get('__doc__')
if d is not None:
if not isinstance(d, Attribute):
if __doc__ is None:
__doc__ = d
del attrs['__doc__']
if __doc__ is None:
__doc__ = ''
Element.__init__(self, name, __doc__)
tagged_data = attrs.pop(TAGGED_DATA, None)
if tagged_data is not None:
for key, val in tagged_data.items():
self.setTaggedValue(key, val)
for base in bases:
if not isinstance(base, InterfaceClass):
raise TypeError('Expected base interfaces')
Specification.__init__(self, bases)
# Make sure that all recorded attributes (and methods) are of type
# `Attribute` and `Method`
for name, attr in list(attrs.items()):
if name in ('__locals__', '__qualname__'):
# __locals__: Python 3 sometimes adds this.
# __qualname__: PEP 3155 (Python 3.3+)
del attrs[name]
continue
if isinstance(attr, Attribute):
attr.interface = self
if not attr.__name__:
attr.__name__ = name
elif isinstance(attr, FunctionType):
attrs[name] = fromFunction(attr, self, name=name)
elif attr is _decorator_non_return:
del attrs[name]
else:
raise InvalidInterface("Concrete attribute, " + name)
self.__attrs = attrs
self.__identifier__ = "%s.%s" % (self.__module__, self.__name__)
def interfaces(self):
"""Return an iterator for the interfaces in the specification.
"""
yield self
def getBases(self):
return self.__bases__
def isEqualOrExtendedBy(self, other):
"""Same interface or extends?"""
return self == other or other.extends(self)
def names(self, all=False):
"""Return the attribute names defined by the interface."""
if not all:
return self.__attrs.keys()
r = self.__attrs.copy()
for base in self.__bases__:
r.update(dict.fromkeys(base.names(all)))
return r.keys()
def __iter__(self):
return iter(self.names(all=True))
def namesAndDescriptions(self, all=False):
"""Return attribute names and descriptions defined by interface."""
if not all:
return self.__attrs.items()
r = {}
for base in self.__bases__[::-1]:
r.update(dict(base.namesAndDescriptions(all)))
r.update(self.__attrs)
return r.items()
def getDescriptionFor(self, name):
"""Return the attribute description for the given name."""
r = self.get(name)
if r is not None:
return r
raise KeyError(name)
__getitem__ = getDescriptionFor
def __contains__(self, name):
return self.get(name) is not None
def direct(self, name):
return self.__attrs.get(name)
def queryDescriptionFor(self, name, default=None):
return self.get(name, default)
def validateInvariants(self, obj, errors=None):
"""validate object to defined invariants."""
for call in self.queryTaggedValue('invariants', []):
try:
call(obj)
except Invalid as e:
if errors is None:
raise
else:
errors.append(e)
for base in self.__bases__:
try:
base.validateInvariants(obj, errors)
except Invalid:
if errors is None:
raise
if errors:
raise Invalid(errors)
def __repr__(self): # pragma: no cover
try:
return self._v_repr
except AttributeError:
name = self.__name__
m = self.__module__
if m:
name = '%s.%s' % (m, name)
r = "<%s %s>" % (self.__class__.__name__, name)
self._v_repr = r
return r
def _call_conform(self, conform):
try:
return conform(self)
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
# (object is a class). In the later case, we behave
# as though there is no __conform__ method. We can
# detect this case by checking whether there is more
# than one traceback object in the traceback chain:
if sys.exc_info()[2].tb_next is not None:
# There is more than one entry in the chain, so
# reraise the error:
raise
# This clever trick is from Phillip Eby
return None #pragma NO COVER
def __reduce__(self):
return self.__name__
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
# __eq__, which is really fast.
"""Make interfaces sortable
TODO: It would ne nice if:
More specific interfaces should sort before less specific ones.
Otherwise, sort on name and module.
But this is too complicated, and we're going to punt on it
for now.
For now, sort on interface and module name.
None is treated as a pseudo interface that implies the loosest
contact possible, no contract. For that reason, all interfaces
sort before None.
"""
if other is None:
return -1
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: #pragma NO COVER
warnings.warn('Hashing uninitialized InterfaceClass instance')
return 1
return hash((self.__name__, self.__module__))
def __eq__(self, other):
c = self.__cmp(other)
return c == 0
def __ne__(self, other):
c = self.__cmp(other)
return c != 0
def __lt__(self, other):
c = self.__cmp(other)
return c < 0
def __le__(self, other):
c = self.__cmp(other)
return c <= 0
def __gt__(self, other):
c = self.__cmp(other)
return c > 0
def __ge__(self, other):
c = self.__cmp(other)
return c >= 0
Interface = InterfaceClass("Interface", __module__ = 'zope.interface')
class Attribute(Element):
"""Attribute descriptions
"""
# We can't say this yet because we don't have enough
# infrastructure in place.
#
# implements(IAttribute)
interface = None
class Method(Attribute):
"""Method interfaces
The idea here is that you have objects that describe methods.
This provides an opportunity for rich meta-data.
"""
# We can't say this yet because we don't have enough
# infrastructure in place.
#
# 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__)
def getSignatureInfo(self):
return {'positional': self.positional,
'required': self.required,
'optional': self.optional,
'varargs': self.varargs,
'kwargs': self.kwargs,
}
def getSignatureString(self):
sig = []
for v in self.positional:
sig.append(v)
if v in self.optional.keys():
sig[-1] += "=" + repr(self.optional[v])
if self.varargs:
sig.append("*" + self.varargs)
if self.kwargs:
sig.append("**" + self.kwargs)
return "(%s)" % ", ".join(sig)
def fromFunction(func, interface=None, imlevel=0, name=None):
name = name or func.__name__
method = Method(name, func.__doc__)
defaults = getattr(func, '__defaults__', None) or ()
code = func.__code__
# Number of positional arguments
na = code.co_argcount-imlevel
names = code.co_varnames[imlevel:]
opt = {}
# Number of required arguments
nr = na-len(defaults)
if nr < 0:
defaults=defaults[-nr:]
nr = 0
# Determine the optional arguments.
opt.update(dict(zip(names[nr:], defaults)))
method.positional = names[:na]
method.required = names[:nr]
method.optional = opt
argno = na
# Determine the function's variable argument's name (i.e. *args)
if code.co_flags & CO_VARARGS:
method.varargs = names[argno]
argno = argno + 1
else:
method.varargs = None
# Determine the function's keyword argument's name (i.e. **kw)
if code.co_flags & CO_VARKEYWORDS:
method.kwargs = names[argno]
else:
method.kwargs = None
method.interface = interface
for key, value in func.__dict__.items():
method.setTaggedValue(key, value)
return method
def fromMethod(meth, interface=None, name=None):
if isinstance(meth, MethodType):
func = meth.__func__
else:
func = meth
return fromFunction(func, interface, imlevel=1, name=name)
# Now we can create the interesting interfaces and wire them up:
def _wire():
from zope.interface.declarations import classImplements
from zope.interface.interfaces import IAttribute
classImplements(Attribute, IAttribute)
from zope.interface.interfaces import IMethod
classImplements(Method, IMethod)
from zope.interface.interfaces import IInterface
classImplements(InterfaceClass, IInterface)
from zope.interface.interfaces import ISpecification
classImplements(Specification, ISpecification)
# We import this here to deal with module dependencies.
from zope.interface.declarations import implementedBy
from zope.interface.declarations import providedBy
from zope.interface.exceptions import InvalidInterface
from zope.interface.exceptions import BrokenImplementation
zope.interface-4.3.2/src/zope/interface/exceptions.py 0000664 0001750 0001750 00000003717 12763206174 021745 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 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-specific exceptions
"""
class Invalid(Exception):
"""A specification is violated
"""
class DoesNotImplement(Invalid):
""" This object does not implement """
def __init__(self, interface):
self.interface = interface
def __str__(self):
return """An object does not implement interface %(interface)s
""" % self.__dict__
class BrokenImplementation(Invalid):
"""An attribute is not completely implemented.
"""
def __init__(self, interface, name):
self.interface=interface
self.name=name
def __str__(self):
return """An object has failed to implement interface %(interface)s
The %(name)s attribute was not provided.
""" % self.__dict__
class BrokenMethodImplementation(Invalid):
"""An method is not completely implemented.
"""
def __init__(self, method, mess):
self.method=method
self.mess=mess
def __str__(self):
return """The implementation of %(method)s violates its contract
because %(mess)s.
""" % self.__dict__
class InvalidInterface(Exception):
"""The interface has invalid contents
"""
class BadImplements(TypeError):
"""An implementation assertion is invalid
because it doesn't contain an interface or a sequence of valid
implementation assertions.
"""
zope.interface-4.3.2/src/zope/interface/document.py 0000664 0001750 0001750 00000007624 12763206174 021403 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
""" Pretty-Print an Interface object as structured text (Yum)
This module provides a function, asStructuredText, for rendering an
interface as structured text.
"""
import zope.interface
def asStructuredText(I, munge=0, rst=False):
""" Output structured text format. Note, this will whack any existing
'structured' format of the text.
If `rst=True`, then the output will quote all code as inline literals in
accordance with 'reStructuredText' markup principles.
"""
if rst:
inline_literal = lambda s: "``%s``" % (s,)
else:
inline_literal = lambda s: s
r = [inline_literal(I.getName())]
outp = r.append
level = 1
if I.getDoc():
outp(_justify_and_indent(_trim_doc_string(I.getDoc()), level))
bases = [base
for base in I.__bases__
if base is not zope.interface.Interface
]
if bases:
outp(_justify_and_indent("This interface extends:", level, munge))
level += 1
for b in bases:
item = "o %s" % inline_literal(b.getName())
outp(_justify_and_indent(_trim_doc_string(item), level, munge))
level -= 1
namesAndDescriptions = sorted(I.namesAndDescriptions())
outp(_justify_and_indent("Attributes:", level, munge))
level += 1
for name, desc in namesAndDescriptions:
if not hasattr(desc, 'getSignatureString'): # ugh...
item = "%s -- %s" % (inline_literal(desc.getName()),
desc.getDoc() or 'no documentation')
outp(_justify_and_indent(_trim_doc_string(item), level, munge))
level -= 1
outp(_justify_and_indent("Methods:", level, munge))
level += 1
for name, desc in namesAndDescriptions:
if hasattr(desc, 'getSignatureString'): # ugh...
_call = "%s%s" % (desc.getName(), desc.getSignatureString())
item = "%s -- %s" % (inline_literal(_call),
desc.getDoc() or 'no documentation')
outp(_justify_and_indent(_trim_doc_string(item), level, munge))
return "\n\n".join(r) + "\n\n"
def asReStructuredText(I, munge=0):
""" Output reStructuredText format. Note, this will whack any existing
'structured' format of the text."""
return asStructuredText(I, munge=munge, rst=True)
def _trim_doc_string(text):
""" Trims a doc string to make it format
correctly with structured text. """
lines = text.replace('\r\n', '\n').split('\n')
nlines = [lines.pop(0)]
if lines:
min_indent = min([len(line) - len(line.lstrip())
for line in lines])
for line in lines:
nlines.append(line[min_indent:])
return '\n'.join(nlines)
def _justify_and_indent(text, level, munge=0, width=72):
""" indent and justify text, rejustify (munge) if specified """
indent = " " * level
if munge:
lines = []
line = indent
text = text.split()
for word in text:
line = ' '.join([line, word])
if len(line) > width:
lines.append(line)
line = indent
else:
lines.append(line)
return '\n'.join(lines)
else:
return indent + \
text.strip().replace("\r\n", "\n") .replace("\n", "\n" + indent)
zope.interface-4.3.2/src/zope/interface/declarations.py 0000664 0001750 0001750 00000075161 12763206174 022236 0 ustar mg mg 0000000 0000000 ##############################################################################
# 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.
##############################################################################
"""Implementation of interface declarations
There are three flavors of declarations:
- Declarations are used to simply name declared interfaces.
- ImplementsDeclarations are used to express the interfaces that a
class implements (that instances of the class provides).
Implements specifications support inheriting interfaces.
- ProvidesDeclarations are used to express interfaces directly
provided by objects.
"""
__docformat__ = 'restructuredtext'
import sys
from types import FunctionType
from types import MethodType
from types import ModuleType
import weakref
from zope.interface.advice import addClassAdvisor
from zope.interface.interface import InterfaceClass
from zope.interface.interface import SpecificationBase
from zope.interface.interface import Specification
from zope.interface._compat import CLASS_TYPES as DescriptorAwareMetaClasses
from zope.interface._compat import PYTHON3
# Registry of class-implementation specifications
BuiltinImplementationSpecifications = {}
_ADVICE_ERROR = ('Class advice impossible in Python3. '
'Use the @%s class decorator instead.')
_ADVICE_WARNING = ('The %s API is deprecated, and will not work in Python3 '
'Use the @%s class decorator instead.')
class named(object):
def __init__(self, name):
self.name = name
def __call__(self, ob):
ob.__component_name__ = self.name
return ob
class Declaration(Specification):
"""Interface declarations"""
def __init__(self, *interfaces):
Specification.__init__(self, _normalizeargs(interfaces))
def changed(self, originally_changed):
Specification.changed(self, originally_changed)
try:
del self._v_attrs
except AttributeError:
pass
def __contains__(self, interface):
"""Test whether an interface is in the specification
"""
return self.extends(interface) and interface in self.interfaces()
def __iter__(self):
"""Return an iterator for the interfaces in the specification
"""
return self.interfaces()
def flattened(self):
"""Return an iterator of all included and extended interfaces
"""
return iter(self.__iro__)
def __sub__(self, other):
"""Remove interfaces from a specification
"""
return Declaration(
*[i for i in self.interfaces()
if not [j for j in other.interfaces()
if i.extends(j, 0)]
]
)
def __add__(self, other):
"""Add two specifications or a specification and an interface
"""
seen = {}
result = []
for i in self.interfaces():
seen[i] = 1
result.append(i)
for i in other.interfaces():
if i not in seen:
seen[i] = 1
result.append(i)
return Declaration(*result)
__radd__ = __add__
##############################################################################
#
# Implementation specifications
#
# These specify interfaces implemented by instances of classes
class Implements(Declaration):
# class whose specification should be used as additional base
inherit = None
# interfaces actually declared for a class
declared = ()
__name__ = '?'
@classmethod
def named(cls, name, *interfaces):
# Implementation method: Produce an Implements interface with
# a fully fleshed out __name__ before calling the constructor, which
# sets bases to the given interfaces and which may pass this object to
# other objects (e.g., to adjust dependents). If they're sorting or comparing
# by name, this needs to be set.
inst = cls.__new__(cls)
inst.__name__ = name
inst.__init__(*interfaces)
return inst
def __repr__(self):
return '' % (self.__name__)
def __reduce__(self):
return implementedBy, (self.inherit, )
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__.
# This is based on, and compatible with, InterfaceClass.
# (The two must be mutually comparable to be able to work in e.g., BTrees.)
# Instances of this class generally don't have a __module__ other than
# `zope.interface.declarations`, whereas they *do* have a __name__ that is the
# fully qualified name of the object they are representing.
# Note, though, that equality and hashing are still identity based. This
# accounts for things like nested objects that have the same name (typically
# only in tests) and is consistent with pickling. As far as comparisons to InterfaceClass
# goes, we'll never have equal name and module to those, so we're still consistent there.
# Instances of this class are essentially intended to be unique and are
# heavily cached (note how our __reduce__ handles this) so having identity
# based hash and eq should also work.
if other is None:
return -1
n1 = (self.__name__, 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):
return Declaration.__hash__(self)
# We want equality to be based on identity. However, we can't actually
# implement __eq__/__ne__ to do this because sometimes we get wrapped in a proxy.
# We need to let the proxy types implement these methods so they can handle unwrapping
# and then rely on: (1) the interpreter automatically changing `implements == proxy` into
# `proxy == implements` (which will call proxy.__eq__ to do the unwrapping) and then
# (2) the default equality semantics being identity based.
def __lt__(self, other):
c = self.__cmp(other)
return c < 0
def __le__(self, other):
c = self.__cmp(other)
return c <= 0
def __gt__(self, other):
c = self.__cmp(other)
return c > 0
def __ge__(self, other):
c = self.__cmp(other)
return c >= 0
def _implements_name(ob):
# Return the __name__ attribute to be used by its __implemented__
# property.
# This must be stable for the "same" object across processes
# because it is used for sorting. It needn't be unique, though, in cases
# like nested classes named Foo created by different functions, because
# equality and hashing is still based on identity.
# It might be nice to use __qualname__ on Python 3, but that would produce
# different values between Py2 and Py3.
return (getattr(ob, '__module__', '?') or '?') + \
'.' + (getattr(ob, '__name__', '?') or '?')
def implementedByFallback(cls):
"""Return the interfaces implemented for a class' instances
The value returned is an IDeclaration.
"""
try:
spec = cls.__dict__.get('__implemented__')
except AttributeError:
# we can't get the class dict. This is probably due to a
# security proxy. If this is the case, then probably no
# descriptor was installed for the class.
# We don't want to depend directly on zope.security in
# zope.interface, but we'll try to make reasonable
# accommodations in an indirect way.
# We'll check to see if there's an implements:
spec = getattr(cls, '__implemented__', None)
if spec is None:
# There's no spec stred in the class. Maybe its a builtin:
spec = BuiltinImplementationSpecifications.get(cls)
if spec is not None:
return spec
return _empty
if spec.__class__ == Implements:
# we defaulted to _empty or there was a spec. Good enough.
# Return it.
return spec
# TODO: need old style __implements__ compatibility?
# Hm, there's an __implemented__, but it's not a spec. Must be
# an old-style declaration. Just compute a spec for it
return Declaration(*_normalizeargs((spec, )))
if isinstance(spec, Implements):
return spec
if spec is None:
spec = BuiltinImplementationSpecifications.get(cls)
if spec is not None:
return spec
# TODO: need old style __implements__ compatibility?
spec_name = _implements_name(cls)
if spec is not None:
# old-style __implemented__ = foo declaration
spec = (spec, ) # tuplefy, as it might be just an int
spec = Implements.named(spec_name, *_normalizeargs(spec))
spec.inherit = None # old-style implies no inherit
del cls.__implemented__ # get rid of the old-style declaration
else:
try:
bases = cls.__bases__
except AttributeError:
if not callable(cls):
raise TypeError("ImplementedBy called for non-factory", cls)
bases = ()
spec = Implements.named(spec_name, *[implementedBy(c) for c in bases])
spec.inherit = cls
try:
cls.__implemented__ = spec
if not hasattr(cls, '__providedBy__'):
cls.__providedBy__ = objectSpecificationDescriptor
if (isinstance(cls, DescriptorAwareMetaClasses)
and
'__provides__' not in cls.__dict__):
# Make sure we get a __provides__ descriptor
cls.__provides__ = ClassProvides(
cls,
getattr(cls, '__class__', type(cls)),
)
except TypeError:
if not isinstance(cls, type):
raise TypeError("ImplementedBy called for non-type", cls)
BuiltinImplementationSpecifications[cls] = spec
return spec
implementedBy = implementedByFallback
def classImplementsOnly(cls, *interfaces):
"""Declare the only interfaces implemented by instances of a class
The arguments after the class are one or more interfaces or interface
specifications (``IDeclaration`` objects).
The interfaces given (including the interfaces in the specifications)
replace any previous declarations.
"""
spec = implementedBy(cls)
spec.declared = ()
spec.inherit = None
classImplements(cls, *interfaces)
def classImplements(cls, *interfaces):
"""Declare additional interfaces implemented for instances of a class
The arguments after the class are one or more interfaces or
interface specifications (``IDeclaration`` objects).
The interfaces given (including the interfaces in the specifications)
are added to any interfaces previously declared.
"""
spec = implementedBy(cls)
spec.declared += tuple(_normalizeargs(interfaces))
# compute the bases
bases = []
seen = {}
for b in spec.declared:
if b not in seen:
seen[b] = 1
bases.append(b)
if spec.inherit is not None:
for c in spec.inherit.__bases__:
b = implementedBy(c)
if b not in seen:
seen[b] = 1
bases.append(b)
spec.__bases__ = tuple(bases)
def _implements_advice(cls):
interfaces, classImplements = cls.__dict__['__implements_advice_data__']
del cls.__implements_advice_data__
classImplements(cls, *interfaces)
return cls
class implementer:
"""Declare the interfaces implemented by instances of a class.
This function is called as a class decorator.
The arguments are one or more interfaces or interface
specifications (IDeclaration objects).
The interfaces given (including the interfaces in the
specifications) are added to any interfaces previously
declared.
Previous declarations include declarations for base classes
unless implementsOnly was used.
This function is provided for convenience. It provides a more
convenient way to call classImplements. For example::
@implementer(I1)
class C(object):
pass
is equivalent to calling::
classImplements(C, I1)
after the class has been created.
"""
def __init__(self, *interfaces):
self.interfaces = interfaces
def __call__(self, ob):
if isinstance(ob, DescriptorAwareMetaClasses):
classImplements(ob, *self.interfaces)
return ob
spec_name = _implements_name(ob)
spec = Implements.named(spec_name, *self.interfaces)
try:
ob.__implemented__ = spec
except AttributeError:
raise TypeError("Can't declare implements", ob)
return ob
class implementer_only:
"""Declare the only interfaces implemented by instances of a class
This function is called as a class decorator.
The arguments are one or more interfaces or interface
specifications (IDeclaration objects).
Previous declarations including declarations for base classes
are overridden.
This function is provided for convenience. It provides a more
convenient way to call classImplementsOnly. For example::
@implementer_only(I1)
class C(object): pass
is equivalent to calling::
classImplementsOnly(I1)
after the class has been created.
"""
def __init__(self, *interfaces):
self.interfaces = interfaces
def __call__(self, ob):
if isinstance(ob, (FunctionType, MethodType)):
# XXX Does this decorator make sense for anything but classes?
# I don't think so. There can be no inheritance of interfaces
# on a method pr function....
raise ValueError('The implementer_only decorator is not '
'supported for methods or functions.')
else:
# Assume it's a class:
classImplementsOnly(ob, *self.interfaces)
return ob
def _implements(name, interfaces, classImplements):
# This entire approach is invalid under Py3K. Don't even try to fix
# the coverage for this block there. :(
if PYTHON3: #pragma NO COVER
raise TypeError('Class advice impossible in Python3')
frame = sys._getframe(2)
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:
raise TypeError(name+" can be used only from a class definition.")
if '__implements_advice_data__' in locals:
raise TypeError(name+" can be used only once in a class definition.")
locals['__implements_advice_data__'] = interfaces, classImplements
addClassAdvisor(_implements_advice, depth=3)
def implements(*interfaces):
"""Declare interfaces implemented by instances of a class
This function is called in a class definition.
The arguments are one or more interfaces or interface
specifications (IDeclaration objects).
The interfaces given (including the interfaces in the
specifications) are added to any interfaces previously
declared.
Previous declarations include declarations for base classes
unless implementsOnly was used.
This function is provided for convenience. It provides a more
convenient way to call classImplements. For example::
implements(I1)
is equivalent to calling::
classImplements(C, I1)
after the class has been created.
"""
# This entire approach is invalid under Py3K. Don't even try to fix
# the coverage for this block there. :(
if PYTHON3: #pragma NO COVER
raise TypeError(_ADVICE_ERROR % 'implementer')
_implements("implements", interfaces, classImplements)
def implementsOnly(*interfaces):
"""Declare the only interfaces implemented by instances of a class
This function is called in a class definition.
The arguments are one or more interfaces or interface
specifications (IDeclaration objects).
Previous declarations including declarations for base classes
are overridden.
This function is provided for convenience. It provides a more
convenient way to call classImplementsOnly. For example::
implementsOnly(I1)
is equivalent to calling::
classImplementsOnly(I1)
after the class has been created.
"""
# This entire approach is invalid under Py3K. Don't even try to fix
# the coverage for this block there. :(
if PYTHON3: #pragma NO COVER
raise TypeError(_ADVICE_ERROR % 'implementer_only')
_implements("implementsOnly", interfaces, classImplementsOnly)
##############################################################################
#
# Instance declarations
class Provides(Declaration): # Really named ProvidesClass
"""Implement __provides__, the instance-specific specification
When an object is pickled, we pickle the interfaces that it implements.
"""
def __init__(self, cls, *interfaces):
self.__args = (cls, ) + interfaces
self._cls = cls
Declaration.__init__(self, *(interfaces + (implementedBy(cls), )))
def __reduce__(self):
return Provides, self.__args
__module__ = 'zope.interface'
def __get__(self, inst, cls):
"""Make sure that a class __provides__ doesn't leak to an instance
"""
if inst is None and cls is self._cls:
# We were accessed through a class, so we are the class'
# provides spec. Just return this object, but only if we are
# being called on the same class that we were defined for:
return self
raise AttributeError('__provides__')
ProvidesClass = Provides
# Registry of instance declarations
# This is a memory optimization to allow objects to share specifications.
InstanceDeclarations = weakref.WeakValueDictionary()
def Provides(*interfaces):
"""Cache instance declarations
Instance declarations are shared among instances that have the same
declaration. The declarations are cached in a weak value dictionary.
"""
spec = InstanceDeclarations.get(interfaces)
if spec is None:
spec = ProvidesClass(*interfaces)
InstanceDeclarations[interfaces] = spec
return spec
Provides.__safe_for_unpickling__ = True
def directlyProvides(object, *interfaces):
"""Declare interfaces declared directly for an object
The arguments after the object are one or more interfaces or interface
specifications (``IDeclaration`` objects).
The interfaces given (including the interfaces in the specifications)
replace interfaces previously declared for the object.
"""
cls = getattr(object, '__class__', None)
if cls is not None and getattr(cls, '__class__', None) is cls:
# It's a meta class (well, at least it it could be an extension class)
# Note that we can't get here from Py3k tests: there is no normal
# class which isn't descriptor aware.
if not isinstance(object,
DescriptorAwareMetaClasses): #pragma NO COVER Py3k
raise TypeError("Attempt to make an interface declaration on a "
"non-descriptor-aware class")
interfaces = _normalizeargs(interfaces)
if cls is None:
cls = type(object)
issub = False
for damc in DescriptorAwareMetaClasses:
if issubclass(cls, damc):
issub = True
break
if issub:
# we have a class or type. We'll use a special descriptor
# that provides some extra caching
object.__provides__ = ClassProvides(object, cls, *interfaces)
else:
object.__provides__ = Provides(cls, *interfaces)
def alsoProvides(object, *interfaces):
"""Declare interfaces declared directly for an object
The arguments after the object are one or more interfaces or interface
specifications (``IDeclaration`` objects).
The interfaces given (including the interfaces in the specifications) are
added to the interfaces previously declared for the object.
"""
directlyProvides(object, directlyProvidedBy(object), *interfaces)
def noLongerProvides(object, interface):
""" Removes a directly provided interface from an object.
"""
directlyProvides(object, directlyProvidedBy(object) - interface)
if interface.providedBy(object):
raise ValueError("Can only remove directly provided interfaces.")
class ClassProvidesBaseFallback(object):
def __get__(self, inst, cls):
if cls is self._cls:
# We only work if called on the class we were defined for
if inst is None:
# We were accessed through a class, so we are the class'
# provides spec. Just return this object as is:
return self
return self._implements
raise AttributeError('__provides__')
ClassProvidesBasePy = ClassProvidesBaseFallback # BBB
ClassProvidesBase = ClassProvidesBaseFallback
# Try to get C base:
try:
import _zope_interface_coptimizations
except ImportError: #pragma NO COVERAGE
pass
else: #pragma NO COVERAGE
from _zope_interface_coptimizations import ClassProvidesBase
class ClassProvides(Declaration, ClassProvidesBase):
"""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.
"""
def __init__(self, cls, metacls, *interfaces):
self._cls = cls
self._implements = implementedBy(cls)
self.__args = (cls, metacls, ) + interfaces
Declaration.__init__(self, *(interfaces + (implementedBy(metacls), )))
def __reduce__(self):
return self.__class__, self.__args
# Copy base-class method for speed
__get__ = ClassProvidesBase.__get__
def directlyProvidedBy(object):
"""Return the interfaces directly provided by the given object
The value returned is an ``IDeclaration``.
"""
provides = getattr(object, "__provides__", None)
if (provides is None # no spec
or
# We might have gotten the implements spec, as an
# optimization. If so, it's like having only one base, that we
# lop off to exclude class-supplied declarations:
isinstance(provides, Implements)
):
return _empty
# Strip off the class part of the spec:
return Declaration(provides.__bases__[:-1])
def classProvides(*interfaces):
"""Declare interfaces provided directly by a class
This function is called in a class definition.
The arguments are one or more interfaces or interface specifications
(``IDeclaration`` objects).
The given interfaces (including the interfaces in the specifications)
are used to create the class's direct-object interface specification.
An error will be raised if the module class has an direct interface
specification. In other words, it is an error to call this function more
than once in a class definition.
Note that the given interfaces have nothing to do with the interfaces
implemented by instances of the class.
This function is provided for convenience. It provides a more convenient
way to call directlyProvides for a class. For example::
classProvides(I1)
is equivalent to calling::
directlyProvides(theclass, I1)
after the class has been created.
"""
# This entire approach is invalid under Py3K. Don't even try to fix
# the coverage for this block there. :(
if PYTHON3: #pragma NO COVER
raise TypeError(_ADVICE_ERROR % 'provider')
frame = sys._getframe(1)
locals = frame.f_locals
# Try to make sure we were called from a class def
if (locals is frame.f_globals) or ('__module__' not in locals):
raise TypeError("classProvides can be used only from a "
"class definition.")
if '__provides__' in locals:
raise TypeError(
"classProvides can only be used once in a class definition.")
locals["__provides__"] = _normalizeargs(interfaces)
addClassAdvisor(_classProvides_advice, depth=2)
def _classProvides_advice(cls):
# This entire approach is invalid under Py3K. Don't even try to fix
# the coverage for this block there. :(
interfaces = cls.__dict__['__provides__']
del cls.__provides__
directlyProvides(cls, *interfaces)
return cls
class provider:
"""Class decorator version of classProvides"""
def __init__(self, *interfaces):
self.interfaces = interfaces
def __call__(self, ob):
directlyProvides(ob, *self.interfaces)
return ob
def moduleProvides(*interfaces):
"""Declare interfaces provided by a module
This function is used in a module definition.
The arguments are one or more interfaces or interface specifications
(``IDeclaration`` objects).
The given interfaces (including the interfaces in the specifications) are
used to create the module's direct-object interface specification. An
error will be raised if the module already has an interface specification.
In other words, it is an error to call this function more than once in a
module definition.
This function is provided for convenience. It provides a more convenient
way to call directlyProvides. For example::
moduleImplements(I1)
is equivalent to::
directlyProvides(sys.modules[__name__], I1)
"""
frame = sys._getframe(1)
locals = frame.f_locals
# Try to make sure we were called from a class def
if (locals is not frame.f_globals) or ('__name__' not in locals):
raise TypeError(
"moduleProvides can only be used from a module definition.")
if '__provides__' in locals:
raise TypeError(
"moduleProvides can only be used once in a module definition.")
locals["__provides__"] = Provides(ModuleType,
*_normalizeargs(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
These combine information for the object and for it's classes.
"""
return Provides(cls, direct) #pragma NO COVER fossil
def getObjectSpecificationFallback(ob):
provides = getattr(ob, '__provides__', None)
if provides is not None:
if isinstance(provides, SpecificationBase):
return provides
try:
cls = ob.__class__
except AttributeError:
# We can't get the class, so just consider provides
return _empty
return implementedBy(cls)
getObjectSpecification = getObjectSpecificationFallback
def providedByFallback(ob):
# Here we have either a special object, an old-style declaration
# or a descriptor
# Try to get __providedBy__
try:
r = ob.__providedBy__
except AttributeError:
# Not set yet. Fall back to lower-level thing that computes it
return getObjectSpecification(ob)
try:
# We might have gotten a descriptor from an instance of a
# class (like an ExtensionClass) that doesn't support
# descriptors. We'll make sure we got one by trying to get
# the only attribute, which all specs have.
r.extends
except AttributeError:
# The object's class doesn't understand descriptors.
# Sigh. We need to get an object descriptor, but we have to be
# careful. We want to use the instance's __provides__, if
# there is one, but only if it didn't come from the class.
try:
r = ob.__provides__
except AttributeError:
# No __provides__, so just fall back to implementedBy
return implementedBy(ob.__class__)
# We need to make sure we got the __provides__ from the
# instance. We'll do this by making sure we don't get the same
# thing from the class:
try:
cp = ob.__class__.__provides__
except AttributeError:
# The ob doesn't have a class or the class has no
# provides, assume we're done:
return r
if r is cp:
# Oops, we got the provides from the class. This means
# the object doesn't have it's own. We should use implementedBy
return implementedBy(ob.__class__)
return r
providedBy = providedByFallback
class ObjectSpecificationDescriptorFallback(object):
"""Implement the `__providedBy__` attribute
The `__providedBy__` attribute computes the interfaces peovided by
an object.
"""
def __get__(self, inst, cls):
"""Get an object specification for an object
"""
if inst is None:
return getObjectSpecification(cls)
provides = getattr(inst, '__provides__', None)
if provides is not None:
return provides
return implementedBy(cls)
ObjectSpecificationDescriptor = ObjectSpecificationDescriptorFallback
##############################################################################
def _normalizeargs(sequence, output = None):
"""Normalize declaration arguments
Normalization arguments might contain Declarions, tuples, or single
interfaces.
Anything but individial interfaces or implements specs will be expanded.
"""
if output is None:
output = []
cls = sequence.__class__
if InterfaceClass in cls.__mro__ or Implements in cls.__mro__:
output.append(sequence)
else:
for v in sequence:
_normalizeargs(v, output)
return output
_empty = Declaration()
try:
import _zope_interface_coptimizations
except ImportError: #pragma NO COVER
pass
else: #pragma NO COVER PyPy
from _zope_interface_coptimizations import implementedBy
from _zope_interface_coptimizations import providedBy
from _zope_interface_coptimizations import getObjectSpecification
from _zope_interface_coptimizations import ObjectSpecificationDescriptor
objectSpecificationDescriptor = ObjectSpecificationDescriptor()
zope.interface-4.3.2/src/zope/interface/advice.py 0000664 0001750 0001750 00000016572 12763206174 021022 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Class advice.
This module was adapted from 'protocols.advice', part of the Python
Enterprise Application Kit (PEAK). Please notify the PEAK authors
(pje@telecommunity.com and tsarna@sarna.org) if bugs are found or
Zope-specific changes are required, so that the PEAK version of this module
can be kept in sync.
PEAK is a Python application framework that interoperates with (but does
not require) Zope 3 and Twisted. It provides tools for manipulating UML
models, object-relational persistence, aspect-oriented programming, and more.
Visit the PEAK home page at http://peak.telecommunity.com for more information.
"""
from types import FunctionType
try:
from types import ClassType
except ImportError: #pragma NO COVER Python > 3.x
__python3 = True
else: #pragma NO COVER Python < 3.x
__python3 = False
import sys
def getFrameInfo(frame):
"""Return (kind,module,locals,globals) for a frame
'kind' is one of "exec", "module", "class", "function call", or "unknown".
"""
f_locals = frame.f_locals
f_globals = frame.f_globals
sameNamespace = f_locals is f_globals
hasModule = '__module__' in f_locals
hasName = '__name__' in f_globals
sameName = hasModule and hasName
sameName = sameName and f_globals['__name__']==f_locals['__module__']
module = hasName and sys.modules.get(f_globals['__name__']) or None
namespaceIsModule = module and module.__dict__ is f_globals
if not namespaceIsModule:
# some kind of funky exec
kind = "exec"
elif sameNamespace and not hasModule:
kind = "module"
elif sameName and not sameNamespace:
kind = "class"
elif not sameNamespace:
kind = "function call"
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"
return kind, module, f_locals, f_globals
def addClassAdvisor(callback, depth=2):
"""Set up 'callback' to be passed the containing class upon creation
This function is designed to be called by an "advising" function executed
in a class suite. The "advising" function supplies a callback that it
wishes to have executed when the containing class is created. The
callback will be given one argument: the newly created containing class.
The return value of the callback will be used in place of the class, so
the callback should return the input if it does not wish to replace the
class.
The optional 'depth' argument to this function determines the number of
frames between this function and the targeted class suite. 'depth'
defaults to 2, since this skips this function's frame and one calling
function frame. If you use this function from a function called directly
in the class suite, the default will be correct, otherwise you will need
to determine the correct depth yourself.
This function works by installing a special class factory function in
place of the '__metaclass__' of the containing class. Therefore, only
callbacks *after* the last '__metaclass__' assignment in the containing
class will be executed. Be sure that classes using "advising" functions
declare any '__metaclass__' *first*, to ensure all callbacks are run."""
# This entire approach is invalid under Py3K. Don't even try to fix
# the coverage for this block there. :(
if __python3: #pragma NO COVER
raise TypeError('Class advice impossible in Python3')
frame = sys._getframe(depth)
kind, module, caller_locals, caller_globals = getFrameInfo(frame)
# This causes a problem when zope interfaces are used from doctest.
# In these cases, kind == "exec".
#
#if kind != "class":
# raise SyntaxError(
# "Advice must be in the body of a class statement"
# )
previousMetaclass = caller_locals.get('__metaclass__')
if __python3: # pragma: no cover
defaultMetaclass = caller_globals.get('__metaclass__', type)
else:
defaultMetaclass = caller_globals.get('__metaclass__', ClassType)
def advise(name, bases, cdict):
if '__metaclass__' in cdict:
del cdict['__metaclass__']
if previousMetaclass is None:
if bases:
# find best metaclass or use global __metaclass__ if no bases
meta = determineMetaclass(bases)
else:
meta = defaultMetaclass
elif isClassAdvisor(previousMetaclass):
# special case: we can't compute the "true" metaclass here,
# so we need to invoke the previous metaclass and let it
# figure it out for us (and apply its own advice in the process)
meta = previousMetaclass
else:
meta = determineMetaclass(bases, previousMetaclass)
newClass = meta(name,bases,cdict)
# this lets the callback replace the class completely, if it wants to
return callback(newClass)
# introspection data only, not used by inner function
advise.previousMetaclass = previousMetaclass
advise.callback = callback
# install the advisor
caller_locals['__metaclass__'] = advise
def isClassAdvisor(ob):
"""True if 'ob' is a class advisor function"""
return isinstance(ob,FunctionType) and hasattr(ob,'previousMetaclass')
def determineMetaclass(bases, explicit_mc=None):
"""Determine metaclass from 1+ bases and optional explicit __metaclass__"""
meta = [getattr(b,'__class__',type(b)) for b in bases]
if explicit_mc is not None:
# The explicit metaclass needs to be verified for compatibility
# as well, and allowed to resolve the incompatible bases, if any
meta.append(explicit_mc)
if len(meta)==1:
# easy case
return meta[0]
candidates = minimalBases(meta) # minimal set of metaclasses
if not candidates: #pragma NO COVER
# they're all "classic" classes
assert(not __python3) # This should not happen under Python 3
return ClassType
elif len(candidates)>1:
# We could auto-combine, but for now we won't...
raise TypeError("Incompatible metatypes",bases)
# Just one, return it
return candidates[0]
def minimalBases(classes):
"""Reduce a list of base classes to its ordered minimum equivalent"""
if not __python3: #pragma NO COVER
classes = [c for c in classes if c is not ClassType]
candidates = []
for m in classes:
for n in classes:
if issubclass(n,m) and m is not n:
break
else:
# m has no subclasses in 'classes'
if m in candidates:
candidates.remove(m) # ensure that we're later in the list
candidates.append(m)
return candidates
zope.interface-4.3.2/src/zope/interface/adapter.py 0000664 0001750 0001750 00000054451 12763206174 021205 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2004 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.
#
##############################################################################
"""Adapter management
"""
import weakref
from zope.interface import providedBy
from zope.interface import Interface
from zope.interface import ro
from zope.interface._compat import _normalize_name
_BLANK = u''
class BaseAdapterRegistry(object):
# List of methods copied from lookup sub-objects:
_delegated = ('lookup', 'queryMultiAdapter', 'lookup1', 'queryAdapter',
'adapter_hook', 'lookupAll', 'names',
'subscriptions', 'subscribers')
# All registries maintain a generation that can be used by verifying
# registries
_generation = 0
def __init__(self, bases=()):
# The comments here could be improved. Possibly this bit needs
# explaining in a separate document, as the comments here can
# be quite confusing. /regebro
# {order -> {required -> {provided -> {name -> value}}}}
# Here "order" is actually an index in a list, "required" and
# "provided" are interfaces, and "required" is really a nested
# key. So, for example:
# for order == 0 (that is, self._adapters[0]), we have:
# {provided -> {name -> value}}
# but for order == 2 (that is, self._adapters[2]), we have:
# {r1 -> {r2 -> {provided -> {name -> value}}}}
#
self._adapters = []
# {order -> {required -> {provided -> {name -> [value]}}}}
# where the remarks about adapters above apply
self._subscribers = []
# Set, with a reference count, keeping track of the interfaces
# for which we have provided components:
self._provided = {}
# Create ``_v_lookup`` object to perform lookup. We make this a
# separate object to to make it easier to implement just the
# lookup functionality in C. This object keeps track of cache
# invalidation data in two kinds of registries.
# 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 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
# if their cache data are current. See VerifyingBasePy below
# for the pertinent object.
self._createLookup()
# Setting the bases causes the registries described above
# to be initialized (self._setBases -> self.changed ->
# self._v_lookup.changed).
self.__bases__ = bases
def _setBases(self, bases):
self.__dict__['__bases__'] = bases
self.ro = ro.ro(self)
self.changed(self)
__bases__ = property(lambda self: self.__dict__['__bases__'],
lambda self, bases: self._setBases(bases),
)
def _createLookup(self):
self._v_lookup = self.LookupClass(self)
for name in self._delegated:
self.__dict__[name] = getattr(self._v_lookup, name)
def changed(self, originally_changed):
self._generation += 1
self._v_lookup.changed(originally_changed)
def register(self, required, provided, name, value):
if value is None:
self.unregister(required, provided, name, value)
return
required = tuple(map(_convert_None_to_Interface, required))
name = _normalize_name(name)
order = len(required)
byorder = self._adapters
while len(byorder) <= order:
byorder.append({})
components = byorder[order]
key = required + (provided,)
for k in key:
d = components.get(k)
if d is None:
d = {}
components[k] = d
components = d
if components.get(name) is value:
return
components[name] = value
n = self._provided.get(provided, 0) + 1
self._provided[provided] = n
if n == 1:
self._v_lookup.add_extendor(provided)
self.changed(self)
def registered(self, required, provided, name=_BLANK):
required = tuple(map(_convert_None_to_Interface, required))
name = _normalize_name(name)
order = len(required)
byorder = self._adapters
if len(byorder) <= order:
return None
components = byorder[order]
key = required + (provided,)
for k in key:
d = components.get(k)
if d is None:
return None
components = d
return components.get(name)
def unregister(self, required, provided, name, value=None):
required = tuple(map(_convert_None_to_Interface, required))
order = len(required)
byorder = self._adapters
if order >= len(byorder):
return False
components = byorder[order]
key = required + (provided,)
# Keep track of how we got to `components`:
lookups = []
for k in key:
d = components.get(k)
if d is None:
return
lookups.append((components, k))
components = d
old = components.get(name)
if old is None:
return
if (value is not None) and (old is not value):
return
del components[name]
if not components:
# Clean out empty containers, since we don't want our keys
# to reference global objects (interfaces) unnecessarily.
# This is often a problem when an interface is slated for
# removal; a hold-over entry in the registry can make it
# difficult to remove such interfaces.
for comp, k in reversed(lookups):
d = comp[k]
if d:
break
else:
del comp[k]
while byorder and not byorder[-1]:
del byorder[-1]
n = self._provided[provided] - 1
if n == 0:
del self._provided[provided]
self._v_lookup.remove_extendor(provided)
else:
self._provided[provided] = n
self.changed(self)
def subscribe(self, required, provided, value):
required = tuple(map(_convert_None_to_Interface, required))
name = _BLANK
order = len(required)
byorder = self._subscribers
while len(byorder) <= order:
byorder.append({})
components = byorder[order]
key = required + (provided,)
for k in key:
d = components.get(k)
if d is None:
d = {}
components[k] = d
components = d
components[name] = components.get(name, ()) + (value, )
if provided is not None:
n = self._provided.get(provided, 0) + 1
self._provided[provided] = n
if n == 1:
self._v_lookup.add_extendor(provided)
self.changed(self)
def unsubscribe(self, required, provided, value=None):
required = tuple(map(_convert_None_to_Interface, required))
order = len(required)
byorder = self._subscribers
if order >= len(byorder):
return
components = byorder[order]
key = required + (provided,)
# Keep track of how we got to `components`:
lookups = []
for k in key:
d = components.get(k)
if d is None:
return
lookups.append((components, k))
components = d
old = components.get(_BLANK)
if not old:
# this is belt-and-suspenders against the failure of cleanup below
return #pragma NO COVERAGE
if value is None:
new = ()
else:
new = tuple([v for v in old if v is not value])
if new == old:
return
if new:
components[_BLANK] = new
else:
# Instead of setting components[_BLANK] = new, we clean out
# empty containers, since we don't want our keys to
# reference global objects (interfaces) unnecessarily. This
# is often a problem when an interface is slated for
# removal; a hold-over entry in the registry can make it
# difficult to remove such interfaces.
del components[_BLANK]
for comp, k in reversed(lookups):
d = comp[k]
if d:
break
else:
del comp[k]
while byorder and not byorder[-1]:
del byorder[-1]
if provided is not None:
n = self._provided[provided] + len(new) - len(old)
if n == 0:
del self._provided[provided]
self._v_lookup.remove_extendor(provided)
self.changed(self)
# 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, _): #pragma NO COVER
class XXXTwistedFakeOut:
selfImplied = {}
return XXXTwistedFakeOut
_not_in_mapping = object()
class LookupBaseFallback(object):
def __init__(self):
self._cache = {}
self._mcache = {}
self._scache = {}
def changed(self, ignored=None):
self._cache.clear()
self._mcache.clear()
self._scache.clear()
def _getcache(self, provided, name):
cache = self._cache.get(provided)
if cache is None:
cache = {}
self._cache[provided] = cache
if name:
c = cache.get(name)
if c is None:
c = {}
cache[name] = c
cache = c
return cache
def lookup(self, required, provided, name=_BLANK, default=None):
cache = self._getcache(provided, name)
required = tuple(required)
if len(required) == 1:
result = cache.get(required[0], _not_in_mapping)
else:
result = cache.get(tuple(required), _not_in_mapping)
if result is _not_in_mapping:
result = self._uncached_lookup(required, provided, name)
if len(required) == 1:
cache[required[0]] = result
else:
cache[tuple(required)] = result
if result is None:
return default
return result
def lookup1(self, required, provided, name=_BLANK, default=None):
cache = self._getcache(provided, name)
result = cache.get(required, _not_in_mapping)
if result is _not_in_mapping:
return self.lookup((required, ), provided, name, default)
if result is None:
return default
return result
def queryAdapter(self, object, provided, name=_BLANK, default=None):
return self.adapter_hook(provided, object, name, default)
def adapter_hook(self, provided, object, name=_BLANK, default=None):
required = providedBy(object)
cache = self._getcache(provided, name)
factory = cache.get(required, _not_in_mapping)
if factory is _not_in_mapping:
factory = self.lookup((required, ), provided, name)
if factory is not None:
result = factory(object)
if result is not None:
return result
return default
def lookupAll(self, required, provided):
cache = self._mcache.get(provided)
if cache is None:
cache = {}
self._mcache[provided] = cache
required = tuple(required)
result = cache.get(required, _not_in_mapping)
if result is _not_in_mapping:
result = self._uncached_lookupAll(required, provided)
cache[required] = result
return result
def subscriptions(self, required, provided):
cache = self._scache.get(provided)
if cache is None:
cache = {}
self._scache[provided] = cache
required = tuple(required)
result = cache.get(required, _not_in_mapping)
if result is _not_in_mapping:
result = self._uncached_subscriptions(required, provided)
cache[required] = result
return result
LookupBasePy = LookupBaseFallback # BBB
try:
from _zope_interface_coptimizations import LookupBase
except ImportError: #pragma NO COVER
LookupBase = LookupBaseFallback
class VerifyingBaseFallback(LookupBaseFallback):
# Mixin for lookups against registries which "chain" upwards, and
# whose lookups invalidate their own caches whenever a parent registry
# bumps its own '_generation' counter. E.g., used by
# zope.component.persistentregistry
def changed(self, originally_changed):
LookupBaseFallback.changed(self, originally_changed)
self._verify_ro = self._registry.ro[1:]
self._verify_generations = [r._generation for r in self._verify_ro]
def _verify(self):
if ([r._generation for r in self._verify_ro]
!= self._verify_generations):
self.changed(None)
def _getcache(self, provided, name):
self._verify()
return LookupBaseFallback._getcache(self, provided, name)
def lookupAll(self, required, provided):
self._verify()
return LookupBaseFallback.lookupAll(self, required, provided)
def subscriptions(self, required, provided):
self._verify()
return LookupBaseFallback.subscriptions(self, required, provided)
VerifyingBasePy = VerifyingBaseFallback #BBB
try:
from _zope_interface_coptimizations import VerifyingBase
except ImportError: #pragma NO COVER
VerifyingBase = VerifyingBaseFallback
class AdapterLookupBase(object):
def __init__(self, registry):
self._registry = registry
self._required = {}
self.init_extendors()
super(AdapterLookupBase, self).__init__()
def changed(self, ignored=None):
super(AdapterLookupBase, self).changed(None)
for r in self._required.keys():
r = r()
if r is not None:
r.unsubscribe(self)
self._required.clear()
# Extendors
# ---------
# When given an target interface for an adapter lookup, we need to consider
# adapters for interfaces that extend the target interface. This is
# what the extendors dictionary is about. It tells us all of the
# interfaces that extend an interface for which there are adapters
# registered.
# We could separate this by order and name, thus reducing the
# number of provided interfaces to search at run time. The tradeoff,
# however, is that we have to store more information. For example,
# is the same interface is provided for multiple names and if the
# interface extends many interfaces, we'll have to keep track of
# a fair bit of information for each name. It's better to
# be space efficient here and be time efficient in the cache
# implementation.
# TODO: add invalidation when a provided interface changes, in case
# the interface's __iro__ has changed. This is unlikely enough that
# we'll take our chances for now.
def init_extendors(self):
self._extendors = {}
for p in self._registry._provided:
self.add_extendor(p)
def add_extendor(self, provided):
_extendors = self._extendors
for i in provided.__iro__:
extendors = _extendors.get(i, ())
_extendors[i] = (
[e for e in extendors if provided.isOrExtends(e)]
+
[provided]
+
[e for e in extendors if not provided.isOrExtends(e)]
)
def remove_extendor(self, provided):
_extendors = self._extendors
for i in provided.__iro__:
_extendors[i] = [e for e in _extendors.get(i, ())
if e != provided]
def _subscribe(self, *required):
_refs = self._required
for r in required:
ref = r.weakref()
if ref not in _refs:
r.subscribe(self)
_refs[ref] = 1
def _uncached_lookup(self, required, provided, name=_BLANK):
required = tuple(required)
result = None
order = len(required)
for registry in self._registry.ro:
byorder = registry._adapters
if order >= len(byorder):
continue
extendors = registry._v_lookup._extendors.get(provided)
if not extendors:
continue
components = byorder[order]
result = _lookup(components, required, extendors, name, 0,
order)
if result is not None:
break
self._subscribe(*required)
return result
def queryMultiAdapter(self, objects, provided, name=_BLANK, default=None):
factory = self.lookup(map(providedBy, objects), provided, name)
if factory is None:
return default
result = factory(*objects)
if result is None:
return default
return result
def _uncached_lookupAll(self, required, provided):
required = tuple(required)
order = len(required)
result = {}
for registry in reversed(self._registry.ro):
byorder = registry._adapters
if order >= len(byorder):
continue
extendors = registry._v_lookup._extendors.get(provided)
if not extendors:
continue
components = byorder[order]
_lookupAll(components, required, extendors, result, 0, order)
self._subscribe(*required)
return tuple(result.items())
def names(self, required, provided):
return [c[0] for c in self.lookupAll(required, provided)]
def _uncached_subscriptions(self, required, provided):
required = tuple(required)
order = len(required)
result = []
for registry in reversed(self._registry.ro):
byorder = registry._subscribers
if order >= len(byorder):
continue
if provided is None:
extendors = (provided, )
else:
extendors = registry._v_lookup._extendors.get(provided)
if extendors is None:
continue
_subscriptions(byorder[order], required, extendors, _BLANK,
result, 0, order)
self._subscribe(*required)
return result
def subscribers(self, objects, provided):
subscriptions = self.subscriptions(map(providedBy, objects), provided)
if provided is None:
result = ()
for subscription in subscriptions:
subscription(*objects)
else:
result = []
for subscription in subscriptions:
subscriber = subscription(*objects)
if subscriber is not None:
result.append(subscriber)
return result
class AdapterLookup(AdapterLookupBase, LookupBase):
pass
class AdapterRegistry(BaseAdapterRegistry):
LookupClass = AdapterLookup
def __init__(self, bases=()):
# AdapterRegisties are invalidating registries, so
# we need to keep track of out invalidating subregistries.
self._v_subregistries = weakref.WeakKeyDictionary()
super(AdapterRegistry, self).__init__(bases)
def _addSubregistry(self, r):
self._v_subregistries[r] = 1
def _removeSubregistry(self, r):
if r in self._v_subregistries:
del self._v_subregistries[r]
def _setBases(self, bases):
old = self.__dict__.get('__bases__', ())
for r in old:
if r not in bases:
r._removeSubregistry(self)
for r in bases:
if r not in old:
r._addSubregistry(self)
super(AdapterRegistry, self)._setBases(bases)
def changed(self, originally_changed):
super(AdapterRegistry, self).changed(originally_changed)
for sub in self._v_subregistries.keys():
sub.changed(originally_changed)
class VerifyingAdapterLookup(AdapterLookupBase, VerifyingBase):
pass
class VerifyingAdapterRegistry(BaseAdapterRegistry):
LookupClass = VerifyingAdapterLookup
def _convert_None_to_Interface(x):
if x is None:
return Interface
else:
return x
def _lookup(components, specs, provided, name, i, l):
if i < l:
for spec in specs[i].__sro__:
comps = components.get(spec)
if comps:
r = _lookup(comps, specs, provided, name, i+1, l)
if r is not None:
return r
else:
for iface in provided:
comps = components.get(iface)
if comps:
r = comps.get(name)
if r is not None:
return r
return None
def _lookupAll(components, specs, provided, result, i, l):
if i < l:
for spec in reversed(specs[i].__sro__):
comps = components.get(spec)
if comps:
_lookupAll(comps, specs, provided, result, i+1, l)
else:
for iface in reversed(provided):
comps = components.get(iface)
if comps:
result.update(comps)
def _subscriptions(components, specs, provided, name, result, i, l):
if i < l:
for spec in reversed(specs[i].__sro__):
comps = components.get(spec)
if comps:
_subscriptions(comps, specs, provided, name, result, i+1, l)
else:
for iface in reversed(provided):
comps = components.get(iface)
if comps:
comps = comps.get(name)
if comps:
result.extend(comps)
zope.interface-4.3.2/src/zope/interface/_zope_interface_coptimizations.c 0000664 0001750 0001750 00000127736 12763206174 025656 0 ustar mg mg 0000000 0000000 /*###########################################################################
#
# 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.
#
############################################################################*/
#include "Python.h"
#include "structmember.h"
#define TYPE(O) ((PyTypeObject*)(O))
#define OBJECT(O) ((PyObject*)(O))
#define CLASSIC(O) ((PyClassObject*)(O))
#ifndef PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(a, b) PyObject_HEAD_INIT(a) b,
#endif
#ifndef Py_TYPE
#define Py_TYPE(o) ((o)->ob_type)
#endif
static PyObject *str__dict__, *str__implemented__, *strextends;
static PyObject *BuiltinImplementationSpecifications, *str__provides__;
static PyObject *str__class__, *str__providedBy__;
static PyObject *empty, *fallback, *str_implied, *str_cls, *str_implements;
static PyObject *str__conform__, *str_call_conform, *adapter_hooks;
static PyObject *str_uncached_lookup, *str_uncached_lookupAll;
static PyObject *str_uncached_subscriptions;
static PyObject *str_registry, *strro, *str_generation, *strchanged;
static PyTypeObject *Implements;
static int imported_declarations = 0;
static int
import_declarations(void)
{
PyObject *declarations, *i;
declarations = PyImport_ImportModule("zope.interface.declarations");
if (declarations == NULL)
return -1;
BuiltinImplementationSpecifications = PyObject_GetAttrString(
declarations, "BuiltinImplementationSpecifications");
if (BuiltinImplementationSpecifications == NULL)
return -1;
empty = PyObject_GetAttrString(declarations, "_empty");
if (empty == NULL)
return -1;
fallback = PyObject_GetAttrString(declarations, "implementedByFallback");
if (fallback == NULL)
return -1;
i = PyObject_GetAttrString(declarations, "Implements");
if (i == NULL)
return -1;
if (! PyType_Check(i))
{
PyErr_SetString(PyExc_TypeError,
"zope.interface.declarations.Implements is not a type");
return -1;
}
Implements = (PyTypeObject *)i;
Py_DECREF(declarations);
imported_declarations = 1;
return 0;
}
static PyTypeObject SpecType; /* Forward */
static PyObject *
implementedByFallback(PyObject *cls)
{
if (imported_declarations == 0 && import_declarations() < 0)
return NULL;
return PyObject_CallFunctionObjArgs(fallback, cls, NULL);
}
static PyObject *
implementedBy(PyObject *ignored, PyObject *cls)
{
/* Fast retrieval of implements spec, if possible, to optimize
common case. Use fallback code if we get stuck.
*/
PyObject *dict = NULL, *spec;
if (PyType_Check(cls))
{
dict = TYPE(cls)->tp_dict;
Py_XINCREF(dict);
}
if (dict == NULL)
dict = PyObject_GetAttr(cls, str__dict__);
if (dict == NULL)
{
/* Probably a security proxied class, use more expensive fallback code */
PyErr_Clear();
return implementedByFallback(cls);
}
spec = PyObject_GetItem(dict, str__implemented__);
Py_DECREF(dict);
if (spec)
{
if (imported_declarations == 0 && import_declarations() < 0)
return NULL;
if (PyObject_TypeCheck(spec, Implements))
return spec;
/* Old-style declaration, use more expensive fallback code */
Py_DECREF(spec);
return implementedByFallback(cls);
}
PyErr_Clear();
/* Maybe we have a builtin */
if (imported_declarations == 0 && import_declarations() < 0)
return NULL;
spec = PyDict_GetItem(BuiltinImplementationSpecifications, cls);
if (spec != NULL)
{
Py_INCREF(spec);
return spec;
}
/* We're stuck, use fallback */
return implementedByFallback(cls);
}
static PyObject *
getObjectSpecification(PyObject *ignored, PyObject *ob)
{
PyObject *cls, *result;
result = PyObject_GetAttr(ob, str__provides__);
if (result != NULL && PyObject_TypeCheck(result, &SpecType))
return result;
PyErr_Clear();
/* We do a getattr here so as not to be defeated by proxies */
cls = PyObject_GetAttr(ob, str__class__);
if (cls == NULL)
{
PyErr_Clear();
if (imported_declarations == 0 && import_declarations() < 0)
return NULL;
Py_INCREF(empty);
return empty;
}
result = implementedBy(NULL, cls);
Py_DECREF(cls);
return result;
}
static PyObject *
providedBy(PyObject *ignored, PyObject *ob)
{
PyObject *result, *cls, *cp;
result = PyObject_GetAttr(ob, str__providedBy__);
if (result == NULL)
{
PyErr_Clear();
return getObjectSpecification(NULL, ob);
}
/* We want to make sure we have a spec. We can't do a type check
because we may have a proxy, so we'll just try to get the
only attribute.
*/
if (PyObject_TypeCheck(result, &SpecType)
||
PyObject_HasAttr(result, strextends)
)
return result;
/*
The object's class doesn't understand descriptors.
Sigh. We need to get an object descriptor, but we have to be
careful. We want to use the instance's __provides__,l if
there is one, but only if it didn't come from the class.
*/
Py_DECREF(result);
cls = PyObject_GetAttr(ob, str__class__);
if (cls == NULL)
return NULL;
result = PyObject_GetAttr(ob, str__provides__);
if (result == NULL)
{
/* No __provides__, so just fall back to implementedBy */
PyErr_Clear();
result = implementedBy(NULL, cls);
Py_DECREF(cls);
return result;
}
cp = PyObject_GetAttr(cls, str__provides__);
if (cp == NULL)
{
/* The the class has no provides, assume we're done: */
PyErr_Clear();
Py_DECREF(cls);
return result;
}
if (cp == result)
{
/*
Oops, we got the provides from the class. This means
the object doesn't have it's own. We should use implementedBy
*/
Py_DECREF(result);
result = implementedBy(NULL, cls);
}
Py_DECREF(cls);
Py_DECREF(cp);
return result;
}
/*
Get an attribute from an inst dict. Return a borrowed reference.
This has a number of advantages:
- It avoids layers of Python api
- It doesn't waste time looking for descriptors
- It fails wo raising an exception, although that shouldn't really
matter.
*/
static PyObject *
inst_attr(PyObject *self, PyObject *name)
{
PyObject **dictp, *v;
dictp = _PyObject_GetDictPtr(self);
if (dictp && *dictp && (v = PyDict_GetItem(*dictp, name)))
return v;
PyErr_SetObject(PyExc_AttributeError, name);
return NULL;
}
static PyObject *
Spec_extends(PyObject *self, PyObject *other)
{
PyObject *implied;
implied = inst_attr(self, str_implied);
if (implied == NULL)
return NULL;
#ifdef Py_True
if (PyDict_GetItem(implied, other) != NULL)
{
Py_INCREF(Py_True);
return Py_True;
}
Py_INCREF(Py_False);
return Py_False;
#else
return PyInt_FromLong(PyDict_GetItem(implied, other) != NULL);
#endif
}
static char Spec_extends__doc__[] =
"Test whether a specification is or extends another"
;
static char Spec_providedBy__doc__[] =
"Test whether an interface is implemented by the specification"
;
static PyObject *
Spec_call(PyObject *self, PyObject *args, PyObject *kw)
{
PyObject *spec;
if (! PyArg_ParseTuple(args, "O", &spec))
return NULL;
return Spec_extends(self, spec);
}
static PyObject *
Spec_providedBy(PyObject *self, PyObject *ob)
{
PyObject *decl, *item;
decl = providedBy(NULL, ob);
if (decl == NULL)
return NULL;
if (PyObject_TypeCheck(decl, &SpecType))
item = Spec_extends(decl, self);
else
/* decl is probably a security proxy. We have to go the long way
around.
*/
item = PyObject_CallFunctionObjArgs(decl, self, NULL);
Py_DECREF(decl);
return item;
}
static char Spec_implementedBy__doc__[] =
"Test whether the specification is implemented by a class or factory.\n"
"Raise TypeError if argument is neither a class nor a callable."
;
static PyObject *
Spec_implementedBy(PyObject *self, PyObject *cls)
{
PyObject *decl, *item;
decl = implementedBy(NULL, cls);
if (decl == NULL)
return NULL;
if (PyObject_TypeCheck(decl, &SpecType))
item = Spec_extends(decl, self);
else
item = PyObject_CallFunctionObjArgs(decl, self, NULL);
Py_DECREF(decl);
return item;
}
static struct PyMethodDef Spec_methods[] = {
{"providedBy",
(PyCFunction)Spec_providedBy, METH_O,
Spec_providedBy__doc__},
{"implementedBy",
(PyCFunction)Spec_implementedBy, METH_O,
Spec_implementedBy__doc__},
{"isOrExtends", (PyCFunction)Spec_extends, METH_O,
Spec_extends__doc__},
{NULL, NULL} /* sentinel */
};
static PyTypeObject SpecType = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_interface_coptimizations."
"SpecificationBase",
/* tp_basicsize */ 0,
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)0,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)Spec_call,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
"Base type for Specification objects",
/* tp_traverse */ (traverseproc)0,
/* tp_clear */ (inquiry)0,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ Spec_methods,
};
static PyObject *
OSD_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
{
PyObject *provides;
if (inst == NULL)
return getObjectSpecification(NULL, cls);
provides = PyObject_GetAttr(inst, str__provides__);
if (provides != NULL)
return provides;
PyErr_Clear();
return implementedBy(NULL, cls);
}
static PyTypeObject OSDType = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_interface_coptimizations."
"ObjectSpecificationDescriptor",
/* tp_basicsize */ 0,
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)0,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)0,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE ,
"Object Specification Descriptor",
/* tp_traverse */ (traverseproc)0,
/* tp_clear */ (inquiry)0,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ 0,
/* tp_members */ 0,
/* tp_getset */ 0,
/* tp_base */ 0,
/* tp_dict */ 0, /* internal use */
/* tp_descr_get */ (descrgetfunc)OSD_descr_get,
};
static PyObject *
CPB_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
{
PyObject *mycls, *implements;
mycls = inst_attr(self, str_cls);
if (mycls == NULL)
return NULL;
if (cls == mycls)
{
if (inst == NULL)
{
Py_INCREF(self);
return OBJECT(self);
}
implements = inst_attr(self, str_implements);
Py_XINCREF(implements);
return implements;
}
PyErr_SetObject(PyExc_AttributeError, str__provides__);
return NULL;
}
static PyTypeObject CPBType = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_interface_coptimizations."
"ClassProvidesBase",
/* tp_basicsize */ 0,
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)0,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)0,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
"C Base class for ClassProvides",
/* tp_traverse */ (traverseproc)0,
/* tp_clear */ (inquiry)0,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ 0,
/* tp_members */ 0,
/* tp_getset */ 0,
/* tp_base */ &SpecType,
/* tp_dict */ 0, /* internal use */
/* tp_descr_get */ (descrgetfunc)CPB_descr_get,
};
/* ==================================================================== */
/* ========== Begin: __call__ and __adapt__ =========================== */
/*
def __adapt__(self, obj):
"""Adapt an object to the reciever
"""
if self.providedBy(obj):
return obj
for hook in adapter_hooks:
adapter = hook(self, obj)
if adapter is not None:
return adapter
*/
static PyObject *
__adapt__(PyObject *self, PyObject *obj)
{
PyObject *decl, *args, *adapter;
int implements, i, l;
decl = providedBy(NULL, obj);
if (decl == NULL)
return NULL;
if (PyObject_TypeCheck(decl, &SpecType))
{
PyObject *implied;
implied = inst_attr(decl, str_implied);
if (implied == NULL)
{
Py_DECREF(decl);
return NULL;
}
implements = PyDict_GetItem(implied, self) != NULL;
Py_DECREF(decl);
}
else
{
/* decl is probably a security proxy. We have to go the long way
around.
*/
PyObject *r;
r = PyObject_CallFunctionObjArgs(decl, self, NULL);
Py_DECREF(decl);
if (r == NULL)
return NULL;
implements = PyObject_IsTrue(r);
Py_DECREF(r);
}
if (implements)
{
Py_INCREF(obj);
return obj;
}
l = PyList_GET_SIZE(adapter_hooks);
args = PyTuple_New(2);
if (args == NULL)
return NULL;
Py_INCREF(self);
PyTuple_SET_ITEM(args, 0, self);
Py_INCREF(obj);
PyTuple_SET_ITEM(args, 1, obj);
for (i = 0; i < l; i++)
{
adapter = PyObject_CallObject(PyList_GET_ITEM(adapter_hooks, i), args);
if (adapter == NULL || adapter != Py_None)
{
Py_DECREF(args);
return adapter;
}
Py_DECREF(adapter);
}
Py_DECREF(args);
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef ib_methods[] = {
{"__adapt__", (PyCFunction)__adapt__, METH_O,
"Adapt an object to the reciever"},
{NULL, NULL} /* sentinel */
};
/*
def __call__(self, obj, alternate=_marker):
conform = getattr(obj, '__conform__', None)
if conform is not None:
adapter = self._call_conform(conform)
if adapter is not None:
return adapter
adapter = self.__adapt__(obj)
if adapter is not None:
return adapter
elif alternate is not _marker:
return alternate
else:
raise TypeError("Could not adapt", obj, self)
*/
static PyObject *
ib_call(PyObject *self, PyObject *args, PyObject *kwargs)
{
PyObject *conform, *obj, *alternate=NULL, *adapter;
static char *kwlist[] = {"obj", "alternate", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist,
&obj, &alternate))
return NULL;
conform = PyObject_GetAttr(obj, str__conform__);
if (conform != NULL)
{
adapter = PyObject_CallMethodObjArgs(self, str_call_conform,
conform, NULL);
Py_DECREF(conform);
if (adapter == NULL || adapter != Py_None)
return adapter;
Py_DECREF(adapter);
}
else
PyErr_Clear();
adapter = __adapt__(self, obj);
if (adapter == NULL || adapter != Py_None)
return adapter;
Py_DECREF(adapter);
if (alternate != NULL)
{
Py_INCREF(alternate);
return alternate;
}
adapter = Py_BuildValue("sOO", "Could not adapt", obj, self);
if (adapter != NULL)
{
PyErr_SetObject(PyExc_TypeError, adapter);
Py_DECREF(adapter);
}
return NULL;
}
static PyTypeObject InterfaceBase = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_zope_interface_coptimizations."
"InterfaceBase",
/* tp_basicsize */ 0,
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)0,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)ib_call,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE ,
/* tp_doc */ "Interface base type providing __call__ and __adapt__",
/* tp_traverse */ (traverseproc)0,
/* tp_clear */ (inquiry)0,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ ib_methods,
};
/* =================== End: __call__ and __adapt__ ==================== */
/* ==================================================================== */
/* ==================================================================== */
/* ========================== Begin: Lookup Bases ===================== */
typedef struct {
PyObject_HEAD
PyObject *_cache;
PyObject *_mcache;
PyObject *_scache;
} lookup;
typedef struct {
PyObject_HEAD
PyObject *_cache;
PyObject *_mcache;
PyObject *_scache;
PyObject *_verify_ro;
PyObject *_verify_generations;
} verify;
static int
lookup_traverse(lookup *self, visitproc visit, void *arg)
{
int vret;
if (self->_cache) {
vret = visit(self->_cache, arg);
if (vret != 0)
return vret;
}
if (self->_mcache) {
vret = visit(self->_mcache, arg);
if (vret != 0)
return vret;
}
if (self->_scache) {
vret = visit(self->_scache, arg);
if (vret != 0)
return vret;
}
return 0;
}
static int
lookup_clear(lookup *self)
{
Py_CLEAR(self->_cache);
Py_CLEAR(self->_mcache);
Py_CLEAR(self->_scache);
return 0;
}
static void
lookup_dealloc(lookup *self)
{
lookup_clear(self);
Py_TYPE(self)->tp_free((PyObject*)self);
}
/*
def changed(self, ignored=None):
self._cache.clear()
self._mcache.clear()
self._scache.clear()
*/
static PyObject *
lookup_changed(lookup *self, PyObject *ignored)
{
lookup_clear(self);
Py_INCREF(Py_None);
return Py_None;
}
#define ASSURE_DICT(N) if (N == NULL) { N = PyDict_New(); \
if (N == NULL) return NULL; \
}
/*
def _getcache(self, provided, name):
cache = self._cache.get(provided)
if cache is None:
cache = {}
self._cache[provided] = cache
if name:
c = cache.get(name)
if c is None:
c = {}
cache[name] = c
cache = c
return cache
*/
static PyObject *
_subcache(PyObject *cache, PyObject *key)
{
PyObject *subcache;
subcache = PyDict_GetItem(cache, key);
if (subcache == NULL)
{
int status;
subcache = PyDict_New();
if (subcache == NULL)
return NULL;
status = PyDict_SetItem(cache, key, subcache);
Py_DECREF(subcache);
if (status < 0)
return NULL;
}
return subcache;
}
static PyObject *
_getcache(lookup *self, PyObject *provided, PyObject *name)
{
PyObject *cache;
ASSURE_DICT(self->_cache);
cache = _subcache(self->_cache, provided);
if (cache == NULL)
return NULL;
if (name != NULL && PyObject_IsTrue(name))
cache = _subcache(cache, name);
return cache;
}
/*
def lookup(self, required, provided, name=u'', default=None):
cache = self._getcache(provided, name)
if len(required) == 1:
result = cache.get(required[0], _not_in_mapping)
else:
result = cache.get(tuple(required), _not_in_mapping)
if result is _not_in_mapping:
result = self._uncached_lookup(required, provided, name)
if len(required) == 1:
cache[required[0]] = result
else:
cache[tuple(required)] = result
if result is None:
return default
return result
*/
static PyObject *
tuplefy(PyObject *v)
{
if (! PyTuple_Check(v))
{
v = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), v, NULL);
if (v == NULL)
return NULL;
}
else
Py_INCREF(v);
return v;
}
static PyObject *
_lookup(lookup *self,
PyObject *required, PyObject *provided, PyObject *name,
PyObject *default_)
{
PyObject *result, *key, *cache;
cache = _getcache(self, provided, name);
if (cache == NULL)
return NULL;
required = tuplefy(required);
if (required == NULL)
return NULL;
if (PyTuple_GET_SIZE(required) == 1)
key = PyTuple_GET_ITEM(required, 0);
else
key = required;
result = PyDict_GetItem(cache, key);
if (result == NULL)
{
int status;
result = PyObject_CallMethodObjArgs(OBJECT(self), str_uncached_lookup,
required, provided, name, NULL);
if (result == NULL)
{
Py_DECREF(required);
return NULL;
}
status = PyDict_SetItem(cache, key, result);
Py_DECREF(required);
if (status < 0)
{
Py_DECREF(result);
return NULL;
}
}
else
{
Py_INCREF(result);
Py_DECREF(required);
}
if (result == Py_None && default_ != NULL)
{
Py_DECREF(Py_None);
Py_INCREF(default_);
return default_;
}
return result;
}
static PyObject *
lookup_lookup(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", "name", "default", NULL};
PyObject *required, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&required, &provided, &name, &default_))
return NULL;
return _lookup(self, required, provided, name, default_);
}
/*
def lookup1(self, required, provided, name=u'', default=None):
cache = self._getcache(provided, name)
result = cache.get(required, _not_in_mapping)
if result is _not_in_mapping:
return self.lookup((required, ), provided, name, default)
if result is None:
return default
return result
*/
static PyObject *
_lookup1(lookup *self,
PyObject *required, PyObject *provided, PyObject *name,
PyObject *default_)
{
PyObject *result, *cache;
cache = _getcache(self, provided, name);
if (cache == NULL)
return NULL;
result = PyDict_GetItem(cache, required);
if (result == NULL)
{
PyObject *tup;
tup = PyTuple_New(1);
if (tup == NULL)
return NULL;
Py_INCREF(required);
PyTuple_SET_ITEM(tup, 0, required);
result = _lookup(self, tup, provided, name, default_);
Py_DECREF(tup);
}
else
{
if (result == Py_None && default_ != NULL)
{
result = default_;
}
Py_INCREF(result);
}
return result;
}
static PyObject *
lookup_lookup1(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", "name", "default", NULL};
PyObject *required, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&required, &provided, &name, &default_))
return NULL;
return _lookup1(self, required, provided, name, default_);
}
/*
def adapter_hook(self, provided, object, name=u'', default=None):
required = providedBy(object)
cache = self._getcache(provided, name)
factory = cache.get(required, _not_in_mapping)
if factory is _not_in_mapping:
factory = self.lookup((required, ), provided, name)
if factory is not None:
result = factory(object)
if result is not None:
return result
return default
*/
static PyObject *
_adapter_hook(lookup *self,
PyObject *provided, PyObject *object, PyObject *name,
PyObject *default_)
{
PyObject *required, *factory, *result;
required = providedBy(NULL, object);
if (required == NULL)
return NULL;
factory = _lookup1(self, required, provided, name, Py_None);
Py_DECREF(required);
if (factory == NULL)
return NULL;
if (factory != Py_None)
{
result = PyObject_CallFunctionObjArgs(factory, object, NULL);
Py_DECREF(factory);
if (result == NULL || result != Py_None)
return result;
}
else
result = factory; /* None */
if (default_ == NULL || default_ == result) /* No default specified, */
return result; /* Return None. result is owned None */
Py_DECREF(result);
Py_INCREF(default_);
return default_;
}
static PyObject *
lookup_adapter_hook(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"provided", "object", "name", "default", NULL};
PyObject *object, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&provided, &object, &name, &default_))
return NULL;
return _adapter_hook(self, provided, object, name, default_);
}
static PyObject *
lookup_queryAdapter(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"object", "provided", "name", "default", NULL};
PyObject *object, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&object, &provided, &name, &default_))
return NULL;
return _adapter_hook(self, provided, object, name, default_);
}
/*
def lookupAll(self, required, provided):
cache = self._mcache.get(provided)
if cache is None:
cache = {}
self._mcache[provided] = cache
required = tuple(required)
result = cache.get(required, _not_in_mapping)
if result is _not_in_mapping:
result = self._uncached_lookupAll(required, provided)
cache[required] = result
return result
*/
static PyObject *
_lookupAll(lookup *self, PyObject *required, PyObject *provided)
{
PyObject *cache, *result;
ASSURE_DICT(self->_mcache);
cache = _subcache(self->_mcache, provided);
if (cache == NULL)
return NULL;
required = tuplefy(required);
if (required == NULL)
return NULL;
result = PyDict_GetItem(cache, required);
if (result == NULL)
{
int status;
result = PyObject_CallMethodObjArgs(OBJECT(self), str_uncached_lookupAll,
required, provided, NULL);
if (result == NULL)
{
Py_DECREF(required);
return NULL;
}
status = PyDict_SetItem(cache, required, result);
Py_DECREF(required);
if (status < 0)
{
Py_DECREF(result);
return NULL;
}
}
else
{
Py_INCREF(result);
Py_DECREF(required);
}
return result;
}
static PyObject *
lookup_lookupAll(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", NULL};
PyObject *required, *provided;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
&required, &provided))
return NULL;
return _lookupAll(self, required, provided);
}
/*
def subscriptions(self, required, provided):
cache = self._scache.get(provided)
if cache is None:
cache = {}
self._scache[provided] = cache
required = tuple(required)
result = cache.get(required, _not_in_mapping)
if result is _not_in_mapping:
result = self._uncached_subscriptions(required, provided)
cache[required] = result
return result
*/
static PyObject *
_subscriptions(lookup *self, PyObject *required, PyObject *provided)
{
PyObject *cache, *result;
ASSURE_DICT(self->_scache);
cache = _subcache(self->_scache, provided);
if (cache == NULL)
return NULL;
required = tuplefy(required);
if (required == NULL)
return NULL;
result = PyDict_GetItem(cache, required);
if (result == NULL)
{
int status;
result = PyObject_CallMethodObjArgs(
OBJECT(self), str_uncached_subscriptions,
required, provided, NULL);
if (result == NULL)
{
Py_DECREF(required);
return NULL;
}
status = PyDict_SetItem(cache, required, result);
Py_DECREF(required);
if (status < 0)
{
Py_DECREF(result);
return NULL;
}
}
else
{
Py_INCREF(result);
Py_DECREF(required);
}
return result;
}
static PyObject *
lookup_subscriptions(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", NULL};
PyObject *required, *provided;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
&required, &provided))
return NULL;
return _subscriptions(self, required, provided);
}
static struct PyMethodDef lookup_methods[] = {
{"changed", (PyCFunction)lookup_changed, METH_O, ""},
{"lookup", (PyCFunction)lookup_lookup, METH_KEYWORDS, ""},
{"lookup1", (PyCFunction)lookup_lookup1, METH_KEYWORDS, ""},
{"queryAdapter", (PyCFunction)lookup_queryAdapter, METH_KEYWORDS, ""},
{"adapter_hook", (PyCFunction)lookup_adapter_hook, METH_KEYWORDS, ""},
{"lookupAll", (PyCFunction)lookup_lookupAll, METH_KEYWORDS, ""},
{"subscriptions", (PyCFunction)lookup_subscriptions, METH_KEYWORDS, ""},
{NULL, NULL} /* sentinel */
};
static PyTypeObject LookupBase = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_zope_interface_coptimizations."
"LookupBase",
/* tp_basicsize */ sizeof(lookup),
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)&lookup_dealloc,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)0,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC,
/* tp_doc */ "",
/* tp_traverse */ (traverseproc)lookup_traverse,
/* tp_clear */ (inquiry)lookup_clear,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ lookup_methods,
};
static int
verifying_traverse(verify *self, visitproc visit, void *arg)
{
int vret;
vret = lookup_traverse((lookup *)self, visit, arg);
if (vret != 0)
return vret;
if (self->_verify_ro) {
vret = visit(self->_verify_ro, arg);
if (vret != 0)
return vret;
}
if (self->_verify_generations) {
vret = visit(self->_verify_generations, arg);
if (vret != 0)
return vret;
}
return 0;
}
static int
verifying_clear(verify *self)
{
lookup_clear((lookup *)self);
Py_CLEAR(self->_verify_generations);
Py_CLEAR(self->_verify_ro);
return 0;
}
static void
verifying_dealloc(verify *self)
{
verifying_clear(self);
Py_TYPE(self)->tp_free((PyObject*)self);
}
/*
def changed(self, originally_changed):
super(VerifyingBasePy, self).changed(originally_changed)
self._verify_ro = self._registry.ro[1:]
self._verify_generations = [r._generation for r in self._verify_ro]
*/
static PyObject *
_generations_tuple(PyObject *ro)
{
int i, l;
PyObject *generations;
l = PyTuple_GET_SIZE(ro);
generations = PyTuple_New(l);
for (i=0; i < l; i++)
{
PyObject *generation;
generation = PyObject_GetAttr(PyTuple_GET_ITEM(ro, i), str_generation);
if (generation == NULL)
{
Py_DECREF(generations);
return NULL;
}
PyTuple_SET_ITEM(generations, i, generation);
}
return generations;
}
static PyObject *
verifying_changed(verify *self, PyObject *ignored)
{
PyObject *t, *ro;
verifying_clear(self);
t = PyObject_GetAttr(OBJECT(self), str_registry);
if (t == NULL)
return NULL;
ro = PyObject_GetAttr(t, strro);
Py_DECREF(t);
if (ro == NULL)
return NULL;
t = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), ro, NULL);
Py_DECREF(ro);
if (t == NULL)
return NULL;
ro = PyTuple_GetSlice(t, 1, PyTuple_GET_SIZE(t));
Py_DECREF(t);
if (ro == NULL)
return NULL;
self->_verify_generations = _generations_tuple(ro);
if (self->_verify_generations == NULL)
{
Py_DECREF(ro);
return NULL;
}
self->_verify_ro = ro;
Py_INCREF(Py_None);
return Py_None;
}
/*
def _verify(self):
if ([r._generation for r in self._verify_ro]
!= self._verify_generations):
self.changed(None)
*/
static int
_verify(verify *self)
{
PyObject *changed_result;
if (self->_verify_ro != NULL && self->_verify_generations != NULL)
{
PyObject *generations;
int changed;
generations = _generations_tuple(self->_verify_ro);
if (generations == NULL)
return -1;
changed = PyObject_RichCompareBool(self->_verify_generations,
generations, Py_NE);
Py_DECREF(generations);
if (changed == -1)
return -1;
if (changed == 0)
return 0;
}
changed_result = PyObject_CallMethodObjArgs(OBJECT(self), strchanged,
Py_None, NULL);
if (changed_result == NULL)
return -1;
Py_DECREF(changed_result);
return 0;
}
static PyObject *
verifying_lookup(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", "name", "default", NULL};
PyObject *required, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&required, &provided, &name, &default_))
return NULL;
if (_verify(self) < 0)
return NULL;
return _lookup((lookup *)self, required, provided, name, default_);
}
static PyObject *
verifying_lookup1(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", "name", "default", NULL};
PyObject *required, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&required, &provided, &name, &default_))
return NULL;
if (_verify(self) < 0)
return NULL;
return _lookup1((lookup *)self, required, provided, name, default_);
}
static PyObject *
verifying_adapter_hook(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"provided", "object", "name", "default", NULL};
PyObject *object, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&provided, &object, &name, &default_))
return NULL;
if (_verify(self) < 0)
return NULL;
return _adapter_hook((lookup *)self, provided, object, name, default_);
}
static PyObject *
verifying_queryAdapter(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"object", "provided", "name", "default", NULL};
PyObject *object, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&object, &provided, &name, &default_))
return NULL;
if (_verify(self) < 0)
return NULL;
return _adapter_hook((lookup *)self, provided, object, name, default_);
}
static PyObject *
verifying_lookupAll(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", NULL};
PyObject *required, *provided;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
&required, &provided))
return NULL;
if (_verify(self) < 0)
return NULL;
return _lookupAll((lookup *)self, required, provided);
}
static PyObject *
verifying_subscriptions(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", NULL};
PyObject *required, *provided;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
&required, &provided))
return NULL;
if (_verify(self) < 0)
return NULL;
return _subscriptions((lookup *)self, required, provided);
}
static struct PyMethodDef verifying_methods[] = {
{"changed", (PyCFunction)verifying_changed, METH_O, ""},
{"lookup", (PyCFunction)verifying_lookup, METH_KEYWORDS, ""},
{"lookup1", (PyCFunction)verifying_lookup1, METH_KEYWORDS, ""},
{"queryAdapter", (PyCFunction)verifying_queryAdapter, METH_KEYWORDS, ""},
{"adapter_hook", (PyCFunction)verifying_adapter_hook, METH_KEYWORDS, ""},
{"lookupAll", (PyCFunction)verifying_lookupAll, METH_KEYWORDS, ""},
{"subscriptions", (PyCFunction)verifying_subscriptions, METH_KEYWORDS, ""},
{NULL, NULL} /* sentinel */
};
static PyTypeObject VerifyingBase = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_zope_interface_coptimizations."
"VerifyingBase",
/* tp_basicsize */ sizeof(verify),
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)&verifying_dealloc,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)0,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC,
/* tp_doc */ "",
/* tp_traverse */ (traverseproc)verifying_traverse,
/* tp_clear */ (inquiry)verifying_clear,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ verifying_methods,
/* tp_members */ 0,
/* tp_getset */ 0,
/* tp_base */ &LookupBase,
};
/* ========================== End: Lookup Bases ======================= */
/* ==================================================================== */
static struct PyMethodDef m_methods[] = {
{"implementedBy", (PyCFunction)implementedBy, METH_O,
"Interfaces implemented by a class or factory.\n"
"Raises TypeError if argument is neither a class nor a callable."},
{"getObjectSpecification", (PyCFunction)getObjectSpecification, METH_O,
"Get an object's interfaces (internal api)"},
{"providedBy", (PyCFunction)providedBy, METH_O,
"Get an object's interfaces"},
{NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
};
#if PY_MAJOR_VERSION >= 3
static char module_doc[] = "C optimizations for zope.interface\n\n";
static struct PyModuleDef _zic_module = {
PyModuleDef_HEAD_INIT,
"_zope_interface_coptimizations",
module_doc,
-1,
m_methods,
NULL,
NULL,
NULL,
NULL
};
#endif
static PyObject *
init(void)
{
PyObject *m;
#if PY_MAJOR_VERSION < 3
#define DEFINE_STRING(S) \
if(! (str ## S = PyString_FromString(# S))) return NULL
#else
#define DEFINE_STRING(S) \
if(! (str ## S = PyUnicode_FromString(# S))) return NULL
#endif
DEFINE_STRING(__dict__);
DEFINE_STRING(__implemented__);
DEFINE_STRING(__provides__);
DEFINE_STRING(__class__);
DEFINE_STRING(__providedBy__);
DEFINE_STRING(extends);
DEFINE_STRING(_implied);
DEFINE_STRING(_implements);
DEFINE_STRING(_cls);
DEFINE_STRING(__conform__);
DEFINE_STRING(_call_conform);
DEFINE_STRING(_uncached_lookup);
DEFINE_STRING(_uncached_lookupAll);
DEFINE_STRING(_uncached_subscriptions);
DEFINE_STRING(_registry);
DEFINE_STRING(_generation);
DEFINE_STRING(ro);
DEFINE_STRING(changed);
#undef DEFINE_STRING
adapter_hooks = PyList_New(0);
if (adapter_hooks == NULL)
return NULL;
/* Initialize types: */
SpecType.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&SpecType) < 0)
return NULL;
OSDType.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&OSDType) < 0)
return NULL;
CPBType.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&CPBType) < 0)
return NULL;
InterfaceBase.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&InterfaceBase) < 0)
return NULL;
LookupBase.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&LookupBase) < 0)
return NULL;
VerifyingBase.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&VerifyingBase) < 0)
return NULL;
#if PY_MAJOR_VERSION < 3
/* Create the module and add the functions */
m = Py_InitModule3("_zope_interface_coptimizations", m_methods,
"C optimizations for zope.interface\n\n");
#else
m = PyModule_Create(&_zic_module);
#endif
if (m == NULL)
return NULL;
/* Add types: */
if (PyModule_AddObject(m, "SpecificationBase", OBJECT(&SpecType)) < 0)
return NULL;
if (PyModule_AddObject(m, "ObjectSpecificationDescriptor",
(PyObject *)&OSDType) < 0)
return NULL;
if (PyModule_AddObject(m, "ClassProvidesBase", OBJECT(&CPBType)) < 0)
return NULL;
if (PyModule_AddObject(m, "InterfaceBase", OBJECT(&InterfaceBase)) < 0)
return NULL;
if (PyModule_AddObject(m, "LookupBase", OBJECT(&LookupBase)) < 0)
return NULL;
if (PyModule_AddObject(m, "VerifyingBase", OBJECT(&VerifyingBase)) < 0)
return NULL;
if (PyModule_AddObject(m, "adapter_hooks", adapter_hooks) < 0)
return NULL;
return m;
}
PyMODINIT_FUNC
#if PY_MAJOR_VERSION < 3
init_zope_interface_coptimizations(void)
{
init();
}
#else
PyInit__zope_interface_coptimizations(void)
{
return init();
}
#endif
zope.interface-4.3.2/src/zope/interface/_flatten.py 0000664 0001750 0001750 00000002040 12763206174 021344 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 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.
#
##############################################################################
"""Adapter-style interface registry
See Adapter class.
"""
from zope.interface import Declaration
def _flatten(implements, include_None=0):
try:
r = implements.flattened()
except AttributeError:
if implements is None:
r=()
else:
r = Declaration(implements).flattened()
if not include_None:
return r
r = list(r)
r.append(None)
return r
zope.interface-4.3.2/src/zope/interface/_compat.py 0000664 0001750 0001750 00000003350 12763206174 021177 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""Basic components support
"""
import sys
import types
if sys.version_info[0] < 3: #pragma NO COVER
def _normalize_name(name):
if isinstance(name, basestring):
return unicode(name)
raise TypeError("name must be a regular or unicode string")
CLASS_TYPES = (type, types.ClassType)
STRING_TYPES = (basestring,)
_BUILTINS = '__builtin__'
PYTHON3 = False
PYTHON2 = True
else: #pragma NO COVER
def _normalize_name(name):
if isinstance(name, bytes):
name = str(name, 'ascii')
if isinstance(name, str):
return name
raise TypeError("name must be a string or ASCII-only bytes")
CLASS_TYPES = (type,)
STRING_TYPES = (str,)
_BUILTINS = 'builtins'
PYTHON3 = True
PYTHON2 = False
def _skip_under_py3k(test_method): #pragma NO COVER
if sys.version_info[0] < 3:
return test_method
def _dummy(*args):
pass
return _dummy
def _skip_under_py2(test_method): #pragma NO COVER
if sys.version_info[0] > 2:
return test_method
def _dummy(*args):
pass
return _dummy
zope.interface-4.3.2/src/zope/interface/__init__.py 0000664 0001750 0001750 00000006522 12763206174 021320 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Interfaces
This package implements the Python "scarecrow" proposal.
The package exports two objects, `Interface` and `Attribute` directly. It also
exports several helper methods. Interface is used to create an interface with
a class statement, as in:
class IMyInterface(Interface):
'''Interface documentation
'''
def meth(arg1, arg2):
'''Documentation for meth
'''
# Note that there is no self argument
To find out what you can do with interfaces, see the interface
interface, `IInterface` in the `interfaces` module.
The package has several public modules:
o `declarations` provides utilities to declare interfaces on objects. It
also provides a wide range of helpful utilities that aid in managing
declared interfaces. Most of its public names are however imported here.
o `document` has a utility for documenting an interface as structured text.
o `exceptions` has the interface-defined exceptions
o `interfaces` contains a list of all public interfaces for this package.
o `verify` has utilities for verifying implementations of interfaces.
See the module doc strings for more information.
"""
__docformat__ = 'restructuredtext'
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.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 named
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
from zope.interface.interfaces import IInterfaceDeclaration
moduleProvides(IInterfaceDeclaration)
__all__ = ('Interface', 'Attribute') + tuple(IInterfaceDeclaration)
zope.interface-4.3.2/src/zope/interface/tests/ 0000775 0001750 0001750 00000000000 12763206175 020345 5 ustar mg mg 0000000 0000000 zope.interface-4.3.2/src/zope/interface/tests/test_verify.py 0000664 0001750 0001750 00000036503 12763206174 023270 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
""" zope.interface.verify unit tests
"""
import unittest
class Test_verifyClass(unittest.TestCase):
def _callFUT(self, iface, klass):
from zope.interface.verify import verifyClass
return verifyClass(iface, klass)
def test_class_doesnt_implement(self):
from zope.interface import Interface
from zope.interface.exceptions import DoesNotImplement
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
classImplements(Current, ICurrent)
self._callFUT(ICurrent, Current)
def test_class_doesnt_have_required_method_simple(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.interface.exceptions import BrokenImplementation
class ICurrent(Interface):
def method(): pass
@implementer(ICurrent)
class Current(object):
pass
self.assertRaises(BrokenImplementation,
self._callFUT, ICurrent, Current)
def test_class_has_required_method_simple(self):
from zope.interface import Interface
from zope.interface import implementer
class ICurrent(Interface):
def method(): pass
@implementer(ICurrent)
class Current(object):
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 implementer
from zope.interface.exceptions import BrokenImplementation
class IBase(Interface):
def method():
pass
class IDerived(IBase):
pass
@implementer(IDerived)
class Current(object):
pass
self.assertRaises(BrokenImplementation,
self._callFUT, IDerived, Current)
def test_class_has_required_method_derived(self):
from zope.interface import Interface
from zope.interface import implementer
class IBase(Interface):
def method():
pass
class IDerived(IBase):
pass
@implementer(IDerived)
class Current(object):
def method(self):
pass
self._callFUT(IDerived, Current)
def test_method_takes_wrong_arg_names_but_OK(self):
# We no longer require names to match.
from zope.interface import Interface
from zope.interface import implementer
class ICurrent(Interface):
def method(a):
pass
@implementer(ICurrent)
class Current(object):
def method(self, b):
pass
self._callFUT(ICurrent, Current)
def test_method_takes_not_enough_args(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.interface.exceptions import BrokenMethodImplementation
class ICurrent(Interface):
def method(a):
pass
@implementer(ICurrent)
class Current(object):
def method(self):
pass
self.assertRaises(BrokenMethodImplementation,
self._callFUT, ICurrent, Current)
def test_method_doesnt_take_required_starargs(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.interface.exceptions import BrokenMethodImplementation
class ICurrent(Interface):
def method(*args):
pass
@implementer(ICurrent)
class Current(object):
def method(self):
pass
self.assertRaises(BrokenMethodImplementation,
self._callFUT, ICurrent, Current)
def test_method_doesnt_take_required_only_kwargs(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.interface.exceptions import BrokenMethodImplementation
class ICurrent(Interface):
def method(**kw):
pass
@implementer(ICurrent)
class Current(object):
def method(self):
pass
self.assertRaises(BrokenMethodImplementation,
self._callFUT, ICurrent, Current)
def test_method_takes_extra_arg(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.interface.exceptions import BrokenMethodImplementation
class ICurrent(Interface):
def method(a):
pass
@implementer(ICurrent)
class Current(object):
def method(self, a, b):
pass
self.assertRaises(BrokenMethodImplementation,
self._callFUT, ICurrent, Current)
def test_method_takes_extra_arg_with_default(self):
from zope.interface import Interface
from zope.interface import implementer
class ICurrent(Interface):
def method(a):
pass
@implementer(ICurrent)
class Current(object):
def method(self, a, b=None):
pass
self._callFUT(ICurrent, Current)
def test_method_takes_only_positional_args(self):
from zope.interface import Interface
from zope.interface import implementer
class ICurrent(Interface):
def method(a):
pass
@implementer(ICurrent)
class Current(object):
def method(self, *args):
pass
self._callFUT(ICurrent, Current)
def test_method_takes_only_kwargs(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.interface.exceptions import BrokenMethodImplementation
class ICurrent(Interface):
def method(a):
pass
@implementer(ICurrent)
class Current(object):
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 implementer
class ICurrent(Interface):
def method(a):
pass
@implementer(ICurrent)
class Current(object):
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 implementer
class ICurrent(Interface):
def method(a):
pass
@implementer(ICurrent)
class Current(object):
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 implementer
from zope.interface.exceptions import BrokenMethodImplementation
class ICurrent(Interface):
def method(a, *args):
pass
@implementer(ICurrent)
class Current(object):
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 implementer
class ICurrent(Interface):
def method(a, *args):
pass
@implementer(ICurrent)
class Current(object):
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 implementer
class ICurrent(Interface):
def method(a, *args):
pass
@implementer(ICurrent)
class Current(object):
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 implementer
class ICurrent(Interface):
def method(**kwargs):
pass
@implementer(ICurrent)
class Current(object):
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 implementer
from zope.interface.exceptions import BrokenMethodImplementation
class ICurrent(Interface):
def method(*args):
pass
@implementer(ICurrent)
class Current(object):
def method(self, a, *args):
pass
self.assertRaises(BrokenMethodImplementation,
self._callFUT, ICurrent, Current)
def test_method_doesnt_take_required_kwargs(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.interface.exceptions import BrokenMethodImplementation
class ICurrent(Interface):
def method(**kwargs):
pass
@implementer(ICurrent)
class Current(object):
def method(self, a):
pass
self.assertRaises(BrokenMethodImplementation,
self._callFUT, ICurrent, Current)
def test_class_has_method_for_iface_attr(self):
from zope.interface import Attribute
from zope.interface import Interface
from zope.interface import implementer
class ICurrent(Interface):
attr = Attribute("The foo Attribute")
@implementer(ICurrent)
class Current:
def attr(self):
pass
self._callFUT(ICurrent, Current)
def test_class_has_nonmethod_for_method(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.interface.exceptions import BrokenMethodImplementation
class ICurrent(Interface):
def method():
pass
@implementer(ICurrent)
class Current:
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 implementer
class ICurrent(Interface):
attr = Attribute("The foo Attribute")
@implementer(ICurrent)
class Current:
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 implementer
class ICurrent(Interface):
attr = Attribute("The foo Attribute")
@implementer(ICurrent)
class Current:
pass
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 implementer
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')
@implementer(ICurrent)
class Current:
attr = QuasiCallable()
self._callFUT(ICurrent, Current)
def test_w_decorated_method(self):
from zope.interface import Interface
from zope.interface import implementer
def decorator(func):
# this is, in fact, zope.proxy.non_overridable
return property(lambda self: func.__get__(self))
class ICurrent(Interface):
def method(a):
pass
@implementer(ICurrent)
class Current(object):
@decorator
def method(self, a):
pass
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 implementer
from zope.interface.exceptions import BrokenImplementation
class ICurrent(Interface):
attr = Attribute("The foo Attribute")
@implementer(ICurrent)
class Current:
pass
self.assertRaises(BrokenImplementation,
self._callFUT, ICurrent, Current)
def test_module_hit(self):
from zope.interface.tests.idummy import IDummyModule
from zope.interface.tests import dummy
self._callFUT(IDummyModule, dummy)
def test_module_miss(self):
from zope.interface import Interface
from zope.interface.tests import dummy
from zope.interface.exceptions import DoesNotImplement
# same name, different object
class IDummyModule(Interface):
pass
self.assertRaises(DoesNotImplement,
self._callFUT, IDummyModule, dummy)
class OldSkool:
pass
def test_suite():
#import doctest
return unittest.TestSuite((
unittest.makeSuite(Test_verifyClass),
unittest.makeSuite(Test_verifyObject),
# This one needs to turn into just docs.
#doctest.DocFileSuite('../verify.txt',
# optionflags=doctest.NORMALIZE_WHITESPACE),
))
zope.interface-4.3.2/src/zope/interface/tests/test_sorting.py 0000664 0001750 0001750 00000003114 12763206174 023441 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Test interface sorting
"""
from unittest import TestCase, TestSuite, main, makeSuite
from zope.interface import Interface
class I1(Interface): pass
class I2(I1): pass
class I3(I1): pass
class I4(Interface): pass
class I5(I4): pass
class I6(I2): pass
class Test(TestCase):
def test(self):
l = [I1, I3, I5, I6, I4, I2]
l.sort()
self.assertEqual(l, [I1, I2, I3, I4, I5, I6])
def test_w_None(self):
l = [I1, None, I3, I5, I6, I4, I2]
l.sort()
self.assertEqual(l, [I1, I2, I3, I4, I5, I6, None])
def test_w_equal_names(self):
# interfaces with equal names but different modules should sort by
# module name
from zope.interface.tests.m1 import I1 as m1_I1
l = [I1, m1_I1]
l.sort()
self.assertEqual(l, [m1_I1, I1])
def test_suite():
return TestSuite((
makeSuite(Test),
))
if __name__=='__main__':
main(defaultTest='test_suite')
zope.interface-4.3.2/src/zope/interface/tests/test_ro.py 0000664 0001750 0001750 00000006351 12763206174 022402 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2014 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.
#
##############################################################################
"""Resolution ordering utility tests"""
import unittest
class Test__mergeOrderings(unittest.TestCase):
def _callFUT(self, orderings):
from zope.interface.ro import _mergeOrderings
return _mergeOrderings(orderings)
def test_empty(self):
self.assertEqual(self._callFUT([]), [])
def test_single(self):
self.assertEqual(self._callFUT(['a', 'b', 'c']), ['a', 'b', 'c'])
def test_w_duplicates(self):
self.assertEqual(self._callFUT([['a'], ['b', 'a']]), ['b', 'a'])
def test_suffix_across_multiple_duplicats(self):
O1 = ['x', 'y', 'z']
O2 = ['q', 'z']
O3 = [1, 3, 5]
O4 = ['z']
self.assertEqual(self._callFUT([O1, O2, O3, O4]),
['x', 'y', 'q', 1, 3, 5, 'z'])
class Test__flatten(unittest.TestCase):
def _callFUT(self, ob):
from zope.interface.ro import _flatten
return _flatten(ob)
def test_w_empty_bases(self):
class Foo(object):
pass
foo = Foo()
foo.__bases__ = ()
self.assertEqual(self._callFUT(foo), [foo])
def test_w_single_base(self):
class Foo(object):
pass
self.assertEqual(self._callFUT(Foo), [Foo, object])
def test_w_bases(self):
class Foo(object):
pass
class Bar(Foo):
pass
self.assertEqual(self._callFUT(Bar), [Bar, Foo, object])
def test_w_diamond(self):
class Foo(object):
pass
class Bar(Foo):
pass
class Baz(Foo):
pass
class Qux(Bar, Baz):
pass
self.assertEqual(self._callFUT(Qux),
[Qux, Bar, Foo, object, Baz, Foo, object])
class Test_ro(unittest.TestCase):
def _callFUT(self, ob):
from zope.interface.ro import ro
return ro(ob)
def test_w_empty_bases(self):
class Foo(object):
pass
foo = Foo()
foo.__bases__ = ()
self.assertEqual(self._callFUT(foo), [foo])
def test_w_single_base(self):
class Foo(object):
pass
self.assertEqual(self._callFUT(Foo), [Foo, object])
def test_w_bases(self):
class Foo(object):
pass
class Bar(Foo):
pass
self.assertEqual(self._callFUT(Bar), [Bar, Foo, object])
def test_w_diamond(self):
class Foo(object):
pass
class Bar(Foo):
pass
class Baz(Foo):
pass
class Qux(Bar, Baz):
pass
self.assertEqual(self._callFUT(Qux),
[Qux, Bar, Baz, Foo, object])
zope.interface-4.3.2/src/zope/interface/tests/test_registry.py 0000664 0001750 0001750 00000307452 12763206174 023640 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2001, 2002, 2009 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.
#
##############################################################################
"""Component Registry Tests"""
import unittest
class ComponentsTests(unittest.TestCase):
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.assertTrue(isinstance(comp.adapters, AdapterRegistry))
self.assertTrue(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), '')
# 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_with_component_name(self):
from zope.interface.declarations import named, InterfaceClass
class IFoo(InterfaceClass):
pass
ifoo = IFoo('IFoo')
@named(u'foo')
class Foo(object):
pass
foo = Foo()
_info = u'info'
comp = self._makeOne()
comp.registerUtility(foo, ifoo, info=_info)
self.assertEqual(
comp._utility_registrations[ifoo, u'foo'],
(foo, _info, None))
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
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.assertTrue(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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, UtilityRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.component is _to_reg)
self.assertTrue(event.object.info is _info)
self.assertTrue(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
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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, UtilityRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.component is _to_reg)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is _factory)
def test_registerUtility_no_provided_available(self):
from zope.interface.declarations import InterfaceClass
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
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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, UtilityRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.component is _to_reg)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is None)
def test_registerUtility_duplicates_existing_reg(self):
from zope.interface.declarations import InterfaceClass
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_w_different_info(self):
from zope.interface.declarations import InterfaceClass
class IFoo(InterfaceClass):
pass
ifoo = IFoo('IFoo')
_info1 = u'info1'
_info2 = u'info2'
_name = u'name'
_to_reg = object()
comp = self._makeOne()
comp.registerUtility(_to_reg, ifoo, _name, _info1)
_monkey, _events = self._wrapEvents()
with _monkey:
comp.registerUtility(_to_reg, ifoo, _name, _info2)
self.assertEqual(len(_events), 2) # unreg, reg
self.assertEqual(comp._utility_registrations[(ifoo, _name)],
(_to_reg, _info2, None)) # replaced
self.assertEqual(comp.utilities._subscribers[0][ifoo][u''],
(_to_reg,))
def test_registerUtility_w_different_names_same_component(self):
from zope.interface.declarations import InterfaceClass
class IFoo(InterfaceClass):
pass
ifoo = IFoo('IFoo')
_info = u'info'
_name1 = u'name1'
_name2 = u'name2'
_other_reg = object()
_to_reg = object()
comp = self._makeOne()
comp.registerUtility(_other_reg, ifoo, _name1, _info)
_monkey, _events = self._wrapEvents()
with _monkey:
comp.registerUtility(_to_reg, ifoo, _name2, _info)
self.assertEqual(len(_events), 1) # reg
self.assertEqual(comp._utility_registrations[(ifoo, _name1)],
(_other_reg, _info, None))
self.assertEqual(comp._utility_registrations[(ifoo, _name2)],
(_to_reg, _info, None))
self.assertEqual(comp.utilities._subscribers[0][ifoo][u''],
(_other_reg, _to_reg,))
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
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.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, UtilityRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.component is _before)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is None)
args, kw = _events[1]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, UtilityRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.component is _after)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is None)
def test_registerUtility_w_existing_subscr(self):
from zope.interface.declarations import InterfaceClass
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
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
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.assertFalse(unreg)
self.assertFalse(_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
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.assertTrue(unreg)
self.assertFalse(comp.utilities._adapters) # all erased
self.assertFalse((ifoo, _name) in comp._utility_registrations)
self.assertFalse(comp.utilities._subscribers)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, UtilityRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.component is _to_reg)
self.assertTrue(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
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.assertTrue(unreg)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, UtilityRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.component is _to_reg)
self.assertTrue(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
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.assertTrue(unreg)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, UtilityRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.component is _to_reg)
self.assertTrue(event.object.info is _info)
self.assertTrue(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
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.assertTrue(unreg)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, UtilityRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.component is _to_reg)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is None)
def test_unregisterUtility_w_existing_subscr(self):
from zope.interface.declarations import InterfaceClass
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_unregisterUtility_w_existing_subscr_non_hashable(self):
from zope.interface.declarations import InterfaceClass
class IFoo(InterfaceClass):
pass
ifoo = IFoo('IFoo')
_info = u'info'
_name1 = u'name1'
_name2 = u'name2'
_to_reg = dict()
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_unregisterUtility_w_existing_subscr_non_hashable_fresh_cache(self):
# We correctly populate the cache of registrations if it has gone away
# (for example, the Components was unpickled)
from zope.interface.declarations import InterfaceClass
from zope.interface.registry import _UtilityRegistrations
class IFoo(InterfaceClass):
pass
ifoo = IFoo('IFoo')
_info = u'info'
_name1 = u'name1'
_name2 = u'name2'
_to_reg = dict()
comp = self._makeOne()
comp.registerUtility(_to_reg, ifoo, _name1, _info)
comp.registerUtility(_to_reg, ifoo, _name2, _info)
_UtilityRegistrations.clear_cache()
_monkey, _events = self._wrapEvents()
with _monkey:
comp.unregisterUtility(_to_reg, ifoo, _name2)
self.assertEqual(comp.utilities._subscribers[0][ifoo][''], (_to_reg,))
def test_unregisterUtility_w_existing_subscr_non_hashable_reinitted(self):
# We correctly populate the cache of registrations if the base objects change
# out from under us
from zope.interface.declarations import InterfaceClass
class IFoo(InterfaceClass):
pass
ifoo = IFoo('IFoo')
_info = u'info'
_name1 = u'name1'
_name2 = u'name2'
_to_reg = dict()
comp = self._makeOne()
comp.registerUtility(_to_reg, ifoo, _name1, _info)
comp.registerUtility(_to_reg, ifoo, _name2, _info)
# zope.component.testing does this
comp.__init__('base')
comp.registerUtility(_to_reg, ifoo, _name2, _info)
_monkey, _events = self._wrapEvents()
with _monkey:
# Nothing to do, but we don't break either
comp.unregisterUtility(_to_reg, ifoo, _name2)
self.assertEqual(0, len(comp.utilities._subscribers))
def test_unregisterUtility_w_existing_subscr_other_component(self):
from zope.interface.declarations import InterfaceClass
class IFoo(InterfaceClass):
pass
ifoo = IFoo('IFoo')
_info = u'info'
_name1 = u'name1'
_name2 = u'name2'
_other_reg = object()
_to_reg = object()
comp = self._makeOne()
comp.registerUtility(_other_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][''],
(_other_reg,))
def test_unregisterUtility_w_existing_subscr_other_component_mixed_hash(self):
from zope.interface.declarations import InterfaceClass
class IFoo(InterfaceClass):
pass
ifoo = IFoo('IFoo')
_info = u'info'
_name1 = u'name1'
_name2 = u'name2'
# First register something hashable
_other_reg = object()
# Then it transfers to something unhashable
_to_reg = dict()
comp = self._makeOne()
comp.registerUtility(_other_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][''],
(_other_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 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 = sorted(comp.registeredUtilities(), key=lambda r: r.name)
self.assertEqual(len(reg), 2)
self.assertTrue(isinstance(reg[0], UtilityRegistration))
self.assertTrue(reg[0].registry is comp)
self.assertTrue(reg[0].provided is ifoo)
self.assertTrue(reg[0].name is _name1)
self.assertTrue(reg[0].component is _to_reg)
self.assertTrue(reg[0].info is _info)
self.assertTrue(reg[0].factory is None)
self.assertTrue(isinstance(reg[1], UtilityRegistration))
self.assertTrue(reg[1].registry is comp)
self.assertTrue(reg[1].provided is ifoo)
self.assertTrue(reg[1].name is _name2)
self.assertTrue(reg[1].component is _to_reg)
self.assertTrue(reg[1].info is _info)
self.assertTrue(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.assertTrue(comp.queryUtility(ifoo) is None)
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.assertTrue(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.assertTrue(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)
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.assertTrue(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
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
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_with_component_name(self):
from zope.interface.declarations import named, InterfaceClass
class IFoo(InterfaceClass):
pass
ifoo = IFoo('IFoo')
ibar = IFoo('IBar')
@named(u'foo')
class Foo(object):
pass
_info = u'info'
comp = self._makeOne()
comp.registerAdapter(Foo, (ibar,), ifoo, info=_info)
self.assertEqual(
comp._adapter_registrations[(ibar,), ifoo, u'foo'],
(Foo, _info))
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
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.assertTrue(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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, AdapterRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is _factory)
def test_registerAdapter_no_provided_available(self):
from zope.interface.declarations import InterfaceClass
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
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.assertTrue(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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, AdapterRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is _Factory)
def test_registerAdapter_no_required_available(self):
from zope.interface.declarations import InterfaceClass
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
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
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.assertTrue(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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, AdapterRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (Interface,))
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is _Factory)
def test_registerAdapter_w_required_containing_class(self):
from zope.interface.declarations import InterfaceClass
from zope.interface.declarations import implementer
from zope.interface.declarations import implementedBy
from zope.interface.interfaces import Registered
from zope.interface.registry import AdapterRegistration
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
@implementer(ibar)
class _Context(object):
pass
_ctx_impl = implementedBy(_Context)
comp = self._makeOne()
_monkey, _events = self._wrapEvents()
with _monkey:
comp.registerAdapter(_Factory, [_Context], provided=ifoo,
name=_name, info=_info)
self.assertTrue(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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, AdapterRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (_ctx_impl,))
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is _Factory)
def test_registerAdapter_w_required_containing_junk(self):
from zope.interface.declarations import InterfaceClass
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
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.assertTrue(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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, AdapterRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertTrue(event.object.name is _name)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is _Factory)
def test_registerAdapter_wo_event(self):
from zope.interface.declarations import InterfaceClass
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.assertFalse(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.assertTrue(unreg)
self.assertFalse(comp.adapters._adapters)
self.assertFalse(comp._adapter_registrations)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, AdapterRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertEqual(event.object.name, '')
self.assertEqual(event.object.info, '')
self.assertTrue(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.assertTrue(unreg)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, AdapterRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertEqual(event.object.name, '')
self.assertEqual(event.object.info, '')
self.assertTrue(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.assertTrue(unreg)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, AdapterRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertEqual(event.object.name, '')
self.assertEqual(event.object.info, '')
self.assertTrue(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 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 = sorted(comp.registeredAdapters(), key=lambda r: r.name)
self.assertEqual(len(reg), 2)
self.assertTrue(isinstance(reg[0], AdapterRegistration))
self.assertTrue(reg[0].registry is comp)
self.assertTrue(reg[0].provided is ifoo)
self.assertEqual(reg[0].required, (ibar,))
self.assertTrue(reg[0].name is _name1)
self.assertTrue(reg[0].info is _info)
self.assertTrue(reg[0].factory is _Factory)
self.assertTrue(isinstance(reg[1], AdapterRegistration))
self.assertTrue(reg[1].registry is comp)
self.assertTrue(reg[1].provided is ifoo)
self.assertEqual(reg[1].required, (ibar,))
self.assertTrue(reg[1].name is _name2)
self.assertTrue(reg[1].info is _info)
self.assertTrue(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.assertTrue(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.assertTrue(
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.assertTrue(isinstance(adapter, _Factory))
self.assertTrue(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,
comp.getAdapter, _context, ifoo)
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.assertTrue(isinstance(adapter, _Factory))
self.assertTrue(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.assertTrue(
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.assertTrue(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,
comp.getMultiAdapter, (_context1, _context2), ifoo)
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.assertTrue(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(
list(comp.getAdapters((_context1, _context2), ifoo)), [])
def test_getAdapters_factory_returns_None(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()
_called_with = []
def _side_effect_only(context1, context2):
_called_with.append((context1, context2))
return None
comp.registerAdapter(_side_effect_only, (ibar, ibaz), ifoo)
self.assertEqual(
list(comp.getAdapters((_context1, _context2), ifoo)), [])
self.assertEqual(_called_with, [(_context1, _context2)])
def test_getAdapters_non_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()
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.assertTrue(isinstance(found[0][1], _Factory1))
self.assertEqual(found[1][0], _name2)
self.assertTrue(isinstance(found[1][1], _Factory2))
def test_registerSubscriptionAdapter_w_nonblank_name(self):
from zope.interface.declarations import InterfaceClass
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
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.assertTrue(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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, SubscriptionRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertEqual(event.object.name, _blank)
self.assertTrue(event.object.info is _info)
self.assertTrue(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
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.assertTrue(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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, SubscriptionRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertEqual(event.object.name, _blank)
self.assertTrue(event.object.info is _info)
self.assertTrue(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
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.assertTrue(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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, SubscriptionRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertEqual(event.object.name, _blank)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is _Factory)
def test_registerSubscriptionAdapter_wo_event(self):
from zope.interface.declarations import InterfaceClass
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 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.assertTrue(isinstance(reg[0], SubscriptionRegistration))
self.assertTrue(reg[0].registry is comp)
self.assertTrue(reg[0].provided is ifoo)
self.assertEqual(reg[0].required, (ibar,))
self.assertEqual(reg[0].name, _blank)
self.assertTrue(reg[0].info is _info)
self.assertTrue(reg[0].factory is _Factory)
self.assertTrue(isinstance(reg[1], SubscriptionRegistration))
self.assertTrue(reg[1].registry is comp)
self.assertTrue(reg[1].provided is ifoo)
self.assertEqual(reg[1].required, (ibar,))
self.assertEqual(reg[1].name, _blank)
self.assertTrue(reg[1].info is _info)
self.assertTrue(reg[1].factory is _Factory)
def test_unregisterSubscriptionAdapter_w_nonblank_name(self):
from zope.interface.declarations import InterfaceClass
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.assertFalse(unreg)
self.assertFalse(_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.assertTrue(unreg)
self.assertFalse(comp.adapters._subscribers)
self.assertFalse(comp._subscription_registrations)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, SubscriptionRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertEqual(event.object.name, '')
self.assertEqual(event.object.info, '')
self.assertTrue(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.assertTrue(unreg)
self.assertFalse(comp.adapters._subscribers)
self.assertFalse(comp._subscription_registrations)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, SubscriptionRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertEqual(event.object.name, '')
self.assertEqual(event.object.info, '')
self.assertTrue(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.assertTrue(unreg)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, SubscriptionRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertEqual(event.object.name, '')
self.assertEqual(event.object.info, '')
self.assertTrue(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.assertTrue(unreg)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, SubscriptionRegistration))
self.assertTrue(event.object.registry is comp)
self.assertTrue(event.object.provided is ifoo)
self.assertEqual(event.object.required, (ibar,))
self.assertEqual(event.object.name, '')
self.assertEqual(event.object.info, '')
self.assertTrue(event.object.factory is _Factory)
def test_subscribers_empty(self):
from zope.interface.declarations import InterfaceClass
from zope.interface.declarations import implementer
class IFoo(InterfaceClass):
pass
ifoo = IFoo('IFoo')
ibar = IFoo('IBar')
comp = self._makeOne()
@implementer(ibar)
class Bar(object):
pass
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 implementer
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)
@implementer(ibar)
class Bar(object):
pass
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.assertTrue(isinstance(subscribers[0], _Derived))
self.assertTrue(isinstance(subscribers[1], _Factory))
def test_registerHandler_w_nonblank_name(self):
from zope.interface.declarations import InterfaceClass
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
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.assertTrue(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.assertTrue(isinstance(event, Registered))
self.assertTrue(isinstance(event.object, HandlerRegistration))
self.assertTrue(event.object.registry is comp)
self.assertEqual(event.object.required, (ifoo,))
self.assertEqual(event.object.name, _blank)
self.assertTrue(event.object.info is _info)
self.assertTrue(event.object.factory is _factory)
def test_registerHandler_wo_explicit_required_no_event(self):
from zope.interface.declarations import InterfaceClass
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, event=False)
reg = comp.adapters._subscribers[1][ifoo][None][_blank]
self.assertEqual(len(reg), 1)
self.assertTrue(reg[0] is _Factory)
self.assertEqual(comp._handler_registrations,
[((ifoo,), _blank, _Factory, _info)])
self.assertEqual(len(_events), 0)
def test_registeredHandlers_empty(self):
from zope.interface.declarations import InterfaceClass
class IFoo(InterfaceClass):
pass
comp = self._makeOne()
self.assertFalse(list(comp.registeredHandlers()))
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.__code__.co_name
subscribers = sorted(comp.registeredHandlers(), key=_factory_name)
self.assertEqual(len(subscribers), 2)
self.assertTrue(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.assertTrue(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
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 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.assertFalse(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.assertTrue(unreg)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, HandlerRegistration))
self.assertTrue(event.object.registry is comp)
self.assertEqual(event.object.required, (ifoo,))
self.assertEqual(event.object.name, '')
self.assertTrue(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.assertTrue(unreg)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, HandlerRegistration))
self.assertTrue(event.object.registry is comp)
self.assertEqual(event.object.required, (ifoo,))
self.assertEqual(event.object.name, '')
self.assertTrue(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.assertTrue(unreg)
self.assertEqual(len(_events), 1)
args, kw = _events[0]
event, = args
self.assertEqual(kw, {})
self.assertTrue(isinstance(event, Unregistered))
self.assertTrue(isinstance(event.object, HandlerRegistration))
self.assertTrue(event.object.registry is comp)
self.assertEqual(event.object.required, (ifoo,))
self.assertEqual(event.object.name, '')
self.assertEqual(event.object.info, '')
self.assertTrue(event.object.factory is _Factory)
def test_handle_empty(self):
from zope.interface.declarations import InterfaceClass
from zope.interface.declarations import implementer
class IFoo(InterfaceClass):
pass
ifoo = IFoo('IFoo')
comp = self._makeOne()
@implementer(ifoo)
class Bar(object):
pass
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 implementer
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,))
@implementer(ifoo)
class Bar(object):
pass
bar = Bar()
comp.handle(bar)
self.assertEqual(_called_1, [bar])
self.assertEqual(_called_2, [bar])
class UnhashableComponentsTests(ComponentsTests):
def _getTargetClass(self):
# Mimic what pyramid does to create an unhashable
# registry
class Components(super(UnhashableComponentsTests, self)._getTargetClass(), dict):
pass
return Components
# 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
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(ur.__hash__(), id(ur))
def test___eq___identity(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
self.assertTrue(ur == ur)
def test___eq___hit(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
ur2, _, _ = self._makeOne(_component)
self.assertTrue(ur == ur2)
def test___eq___miss(self):
_component = object()
_component2 = object()
ur, _registry, _name = self._makeOne(_component)
ur2, _, _ = self._makeOne(_component2)
self.assertFalse(ur == ur2)
def test___ne___identity(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
self.assertFalse(ur != ur)
def test___ne___hit(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
ur2, _, _ = self._makeOne(_component)
self.assertFalse(ur != ur2)
def test___ne___miss(self):
_component = object()
_component2 = object()
ur, _registry, _name = self._makeOne(_component)
ur2, _, _ = self._makeOne(_component2)
self.assertTrue(ur != ur2)
def test___lt___identity(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
self.assertFalse(ur < ur)
def test___lt___hit(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
ur2, _, _ = self._makeOne(_component)
self.assertFalse(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.assertTrue(ur < ur2)
def test___le___identity(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
self.assertTrue(ur <= ur)
def test___le___hit(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
ur2, _, _ = self._makeOne(_component)
self.assertTrue(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.assertTrue(ur <= ur2)
def test___gt___identity(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
self.assertFalse(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.assertTrue(ur2 > ur)
def test___gt___miss(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
ur2, _, _ = self._makeOne(_component)
self.assertFalse(ur2 > ur)
def test___ge___identity(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
self.assertTrue(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.assertFalse(ur >= ur2)
def test___ge___hit(self):
_component = object()
ur, _registry, _name = self._makeOne(_component)
ur2, _, _ = self._makeOne(_component)
ur2.name = _name + '2'
self.assertTrue(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
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(ar.__hash__(), id(ar))
def test___eq___identity(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
self.assertTrue(ar == ar)
def test___eq___hit(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
ar2, _, _ = self._makeOne(_component)
self.assertTrue(ar == ar2)
def test___eq___miss(self):
_component = object()
_component2 = object()
ar, _registry, _name = self._makeOne(_component)
ar2, _, _ = self._makeOne(_component2)
self.assertFalse(ar == ar2)
def test___ne___identity(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
self.assertFalse(ar != ar)
def test___ne___miss(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
ar2, _, _ = self._makeOne(_component)
self.assertFalse(ar != ar2)
def test___ne___hit_component(self):
_component = object()
_component2 = object()
ar, _registry, _name = self._makeOne(_component)
ar2, _, _ = self._makeOne(_component2)
self.assertTrue(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.assertTrue(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.assertTrue(ar != ar2)
def test___lt___identity(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
self.assertFalse(ar < ar)
def test___lt___hit(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
ar2, _, _ = self._makeOne(_component)
self.assertFalse(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.assertTrue(ar < ar2)
def test___le___identity(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
self.assertTrue(ar <= ar)
def test___le___hit(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
ar2, _, _ = self._makeOne(_component)
self.assertTrue(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.assertTrue(ar <= ar2)
def test___gt___identity(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
self.assertFalse(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.assertTrue(ar2 > ar)
def test___gt___miss(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
ar2, _, _ = self._makeOne(_component)
self.assertFalse(ar2 > ar)
def test___ge___identity(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
self.assertTrue(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.assertFalse(ar >= ar2)
def test___ge___hit(self):
_component = object()
ar, _registry, _name = self._makeOne(_component)
ar2, _, _ = self._makeOne(_component)
ar2.name = _name + '2'
self.assertTrue(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
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
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.assertTrue(hr.handler is _factory)
self.assertTrue(hr.factory is hr.handler)
self.assertTrue(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))
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(ComponentsTests),
unittest.makeSuite(UnhashableComponentsTests),
unittest.makeSuite(UtilityRegistrationTests),
unittest.makeSuite(AdapterRegistrationTests),
unittest.makeSuite(SubscriptionRegistrationTests),
unittest.makeSuite(AdapterRegistrationTests),
))
zope.interface-4.3.2/src/zope/interface/tests/test_odd_declarations.py 0000664 0001750 0001750 00000015377 12763206174 025270 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Test interface declarations against ExtensionClass-like classes.
These tests are to make sure we do something sane in the presence of
classic ExtensionClass classes and instances.
"""
import unittest
from zope.interface.tests import odd
from zope.interface import Interface
from zope.interface import implementer
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
from zope.interface._compat import _skip_under_py3k
class I1(Interface): pass
class I2(Interface): pass
class I3(Interface): pass
class I31(I3): pass
class I4(Interface): pass
class I5(Interface): pass
class Odd(object): __metaclass__ = odd.MetaClass
class B(Odd): __implemented__ = I2
# TODO: We are going to need more magic to make classProvides work with odd
# classes. This will work in the next iteration. For now, we'll use
# a different mechanism.
# from zope.interface import classProvides
class A(Odd):
pass
classImplements(A, I1)
class C(A, B):
pass
classImplements(C, I31)
class Test(unittest.TestCase):
def test_ObjectSpecification(self):
c = C()
directlyProvides(c, I4)
self.assertEqual([i.getName() for i in providedBy(c)],
['I4', 'I31', 'I1', 'I2']
)
self.assertEqual([i.getName() for i in providedBy(c).flattened()],
['I4', 'I31', 'I3', 'I1', 'I2', 'Interface']
)
self.assertTrue(I1 in providedBy(c))
self.assertFalse(I3 in providedBy(c))
self.assertTrue(providedBy(c).extends(I3))
self.assertTrue(providedBy(c).extends(I31))
self.assertFalse(providedBy(c).extends(I5))
class COnly(A, B):
pass
classImplementsOnly(COnly, I31)
class D(COnly):
pass
classImplements(D, I5)
classImplements(D, I5)
c = D()
directlyProvides(c, I4)
self.assertEqual([i.getName() for i in providedBy(c)],
['I4', 'I5', 'I31'])
self.assertEqual([i.getName() for i in providedBy(c).flattened()],
['I4', 'I5', 'I31', 'I3', 'Interface'])
self.assertFalse(I1 in providedBy(c))
self.assertFalse(I3 in providedBy(c))
self.assertTrue(providedBy(c).extends(I3))
self.assertFalse(providedBy(c).extends(I1))
self.assertTrue(providedBy(c).extends(I31))
self.assertTrue(providedBy(c).extends(I5))
class COnly(A, B): __implemented__ = I31
class D(COnly):
pass
classImplements(D, I5)
classImplements(D, I5)
c = D()
directlyProvides(c, I4)
self.assertEqual([i.getName() for i in providedBy(c)],
['I4', 'I5', 'I31'])
self.assertEqual([i.getName() for i in providedBy(c).flattened()],
['I4', 'I5', 'I31', 'I3', 'Interface'])
self.assertFalse(I1 in providedBy(c))
self.assertFalse(I3 in providedBy(c))
self.assertTrue(providedBy(c).extends(I3))
self.assertFalse(providedBy(c).extends(I1))
self.assertTrue(providedBy(c).extends(I31))
self.assertTrue(providedBy(c).extends(I5))
def test_classImplements(self):
@implementer(I3)
class A(Odd):
pass
@implementer(I4)
class B(Odd):
pass
class C(A, B):
pass
classImplements(C, I1, I2)
self.assertEqual([i.getName() for i in implementedBy(C)],
['I1', 'I2', 'I3', 'I4'])
classImplements(C, I5)
self.assertEqual([i.getName() for i in implementedBy(C)],
['I1', 'I2', 'I5', 'I3', 'I4'])
def test_classImplementsOnly(self):
@implementer(I3)
class A(Odd):
pass
@implementer(I4)
class B(Odd):
pass
class C(A, B):
pass
classImplementsOnly(C, I1, I2)
self.assertEqual([i.__name__ for i in implementedBy(C)],
['I1', 'I2'])
def test_directlyProvides(self):
class IA1(Interface): pass
class IA2(Interface): pass
class IB(Interface): pass
class IC(Interface): pass
class A(Odd):
pass
classImplements(A, IA1, IA2)
class B(Odd):
pass
classImplements(B, IB)
class C(A, B):
pass
classImplements(C, IC)
ob = C()
directlyProvides(ob, I1, I2)
self.assertTrue(I1 in providedBy(ob))
self.assertTrue(I2 in providedBy(ob))
self.assertTrue(IA1 in providedBy(ob))
self.assertTrue(IA2 in providedBy(ob))
self.assertTrue(IB in providedBy(ob))
self.assertTrue(IC in providedBy(ob))
directlyProvides(ob, directlyProvidedBy(ob)-I2)
self.assertTrue(I1 in providedBy(ob))
self.assertFalse(I2 in providedBy(ob))
self.assertFalse(I2 in providedBy(ob))
directlyProvides(ob, directlyProvidedBy(ob), I2)
self.assertTrue(I2 in providedBy(ob))
@_skip_under_py3k
def test_directlyProvides_fails_for_odd_class(self):
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.assert_(False,
# "Shouldn't be able to use directlyProvides on odd class."
# )
def test_implementedBy(self):
class I2(I1): pass
class C1(Odd):
pass
classImplements(C1, I2)
class C2(C1):
pass
classImplements(C2, I3)
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
zope.interface-4.3.2/src/zope/interface/tests/test_interfaces.py 0000664 0001750 0001750 00000006760 12763206174 024111 0 ustar mg mg 0000000 0000000 import unittest
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(unittest.TestCase, _ConformsToIObjectEvent):
def _getTargetClass(self):
from zope.interface.interfaces import ObjectEvent
return ObjectEvent
def test_ctor(self):
target = object()
event = self._makeOne(target)
self.assertTrue(event.object is target)
class RegistrationEventTests(unittest.TestCase,
_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(unittest.TestCase,
_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(unittest.TestCase,
_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),
))
zope.interface-4.3.2/src/zope/interface/tests/test_interface.py 0000664 0001750 0001750 00000216261 12763206174 023725 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Test Interface implementation
"""
import unittest
_marker = object()
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(list(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(list(element.getTaggedValueTags()), ['foo'])
self.assertEqual(element.getTaggedValue('foo'), 'bar')
self.assertEqual(element.queryTaggedValue('foo'), 'bar')
class SpecificationBasePyTests(unittest.TestCase):
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.assertFalse(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.assertTrue(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.assertFalse(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.assertTrue(sb.implementedBy(object()))
def test_isOrExtends_miss(self):
sb = self._makeOne()
sb._implied = {} # not defined by SpecificationBasePy
self.assertFalse(sb.isOrExtends(object()))
def test_isOrExtends_hit(self):
sb = self._makeOne()
testing = object()
sb._implied = {testing: {}} # not defined by SpecificationBasePy
self.assertTrue(sb(testing))
def test___call___miss(self):
sb = self._makeOne()
sb._implied = {} # not defined by SpecificationBasePy
self.assertFalse(sb.isOrExtends(object()))
def test___call___hit(self):
sb = self._makeOne()
testing = object()
sb._implied = {testing: {}} # not defined by SpecificationBasePy
self.assertTrue(sb(testing))
class InterfaceBasePyTests(unittest.TestCase):
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.assertTrue(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.assertTrue(ib(adapted) is adapted)
def test___call___wo___conform___ob_no_provides_w_alternate(self):
ib = self._makeOne(False)
adapted = object()
alternate = object()
self.assertTrue(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.assertTrue(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.assertTrue(ib.__adapt__(adapted) is adapted)
self.assertEqual(_missed, [(ib, adapted)])
class SpecificationTests(unittest.TestCase):
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.assertTrue(spec in spec._implied)
self.assertTrue(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.assertFalse(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.assertTrue(getattr(spec, '_v_attrs', self) is self)
self.assertFalse(I in spec._implied)
def test_interfaces_skips_already_seen(self):
from zope.interface.interface import Interface
class IFoo(Interface):
pass
spec = self._makeOne([IFoo, IFoo])
self.assertEqual(list(spec.interfaces()), [IFoo])
def test_extends_strict_wo_self(self):
from zope.interface.interface import Interface
class IFoo(Interface):
pass
spec = self._makeOne(IFoo)
self.assertFalse(spec.extends(IFoo, strict=True))
def test_extends_strict_w_self(self):
spec = self._makeOne()
self.assertFalse(spec.extends(spec, strict=True))
def test_extends_non_strict_w_self(self):
spec = self._makeOne()
self.assertTrue(spec.extends(spec, strict=False))
def test_get_hit_w__v_attrs(self):
spec = self._makeOne()
foo = object()
spec._v_attrs = {'foo': foo}
self.assertTrue(spec.get('foo') is foo)
def test_get_hit_from_base_wo__v_attrs(self):
from zope.interface.interface import Attribute
from zope.interface.interface import Interface
class IFoo(Interface):
foo = Attribute('foo')
class IBar(Interface):
bar = Attribute('bar')
spec = self._makeOne([IFoo, IBar])
self.assertTrue(spec.get('foo') is IFoo.get('foo'))
self.assertTrue(spec.get('bar') is IBar.get('bar'))
class InterfaceClassTests(unittest.TestCase):
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(list(inst.names()), [])
def test_ctor_attrs_w_invalid_attr_type(self):
from zope.interface.exceptions import InvalidInterface
ATTRS = {'invalid': object()}
klass = self._getTargetClass()
self.assertRaises(InvalidInterface, klass, 'ITesting', attrs=ATTRS)
def test_ctor_w_explicit___doc__(self):
ATTRS = {'__doc__': 'ATTR'}
klass = self._getTargetClass()
inst = klass('ITesting', attrs=ATTRS, __doc__='EXPLICIT')
self.assertEqual(inst.__doc__, 'EXPLICIT')
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.assertTrue(iface.isEqualOrExtendedBy(iface))
def test_isEqualOrExtendedBy_subiface(self):
iface = self._makeOne()
sub = self._makeOne('ISub', bases=(iface,))
self.assertTrue(iface.isEqualOrExtendedBy(sub))
self.assertFalse(sub.isEqualOrExtendedBy(iface))
def test_isEqualOrExtendedBy_unrelated(self):
one = self._makeOne('One')
another = self._makeOne('Another')
self.assertFalse(one.isEqualOrExtendedBy(another))
self.assertFalse(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.assertFalse('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.assertTrue('foo' in one)
self.assertTrue('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'])
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.assertTrue(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,), {})])
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.assertTrue(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.assertTrue(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.assertTrue(iface < None)
self.assertTrue(iface <= None)
self.assertFalse(iface == None)
self.assertTrue(iface != None)
self.assertFalse(iface >= None)
self.assertFalse(iface > None)
self.assertFalse(None < iface)
self.assertFalse(None <= iface)
self.assertFalse(None == iface)
self.assertTrue(None != iface)
self.assertTrue(None >= iface)
self.assertTrue(None > iface)
def test_comparison_with_same_instance(self):
iface = self._makeOne()
self.assertFalse(iface < iface)
self.assertTrue(iface <= iface)
self.assertTrue(iface == iface)
self.assertFalse(iface != iface)
self.assertTrue(iface >= iface)
self.assertFalse(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.assertTrue(one < other)
self.assertFalse(other < one)
self.assertTrue(one <= other)
self.assertFalse(other <= one)
self.assertFalse(one == other)
self.assertFalse(other == one)
self.assertTrue(one != other)
self.assertTrue(other != one)
self.assertFalse(one >= other)
self.assertTrue(other >= one)
self.assertFalse(one > other)
self.assertTrue(other > one)
class InterfaceTests(unittest.TestCase):
def test_attributes_link_to_interface(self):
from zope.interface import Interface
from zope.interface import Attribute
class I1(Interface):
attr = Attribute("My attr")
self.assertTrue(I1['attr'].interface is I1)
def test_methods_link_to_interface(self):
from zope.interface import Interface
class I1(Interface):
def method(foo, bar, bingo):
pass
self.assertTrue(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
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.assertTrue(ICurrent.implementedBy(Current))
self.assertFalse(IOther.implementedBy(Current))
self.assertTrue(ICurrent in implementedBy(Current))
self.assertFalse(IOther in implementedBy(Current))
self.assertTrue(ICurrent in providedBy(current))
self.assertFalse(IOther in providedBy(current))
def test_classImplements_base_not_derived(self):
from zope.interface import Interface
from zope.interface import implementedBy
from zope.interface import providedBy
class IBase(Interface):
def method():
pass
class IDerived(IBase):
pass
class Current():
__implemented__ = IBase
def method(self):
pass
current = Current()
self.assertTrue(IBase.implementedBy(Current))
self.assertFalse(IDerived.implementedBy(Current))
self.assertTrue(IBase in implementedBy(Current))
self.assertFalse(IDerived in implementedBy(Current))
self.assertTrue(IBase in providedBy(current))
self.assertFalse(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 IDerived(IBase):
pass
class Current(object):
__implemented__ = IDerived
def method(self):
pass
current = Current()
self.assertTrue(IBase.implementedBy(Current))
self.assertTrue(IDerived.implementedBy(Current))
self.assertFalse(IBase in implementedBy(Current))
self.assertTrue(IBase in implementedBy(Current).flattened())
self.assertTrue(IDerived in implementedBy(Current))
self.assertFalse(IBase in providedBy(current))
self.assertTrue(IBase in providedBy(current).flattened())
self.assertTrue(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
class Right(object):
__implemented__ = IRight
class Ambi(Left, Right):
pass
ambi = Ambi()
self.assertTrue(ILeft.implementedBy(Ambi))
self.assertTrue(IRight.implementedBy(Ambi))
self.assertTrue(ILeft in implementedBy(Ambi))
self.assertTrue(IRight in implementedBy(Ambi))
self.assertTrue(ILeft in providedBy(ambi))
self.assertTrue(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
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.assertTrue(ILeft.implementedBy(Mixed))
self.assertFalse(IRight.implementedBy(Mixed))
self.assertTrue(IOther.implementedBy(Mixed))
self.assertTrue(ILeft in implementedBy(Mixed))
self.assertFalse(IRight in implementedBy(Mixed))
self.assertTrue(IOther in implementedBy(Mixed))
self.assertTrue(ILeft in providedBy(mixed))
self.assertFalse(IRight in providedBy(mixed))
self.assertTrue(IOther in providedBy(mixed))
def testInterfaceExtendsInterface(self):
from zope.interface import Interface
new = Interface.__class__
FunInterface = new('FunInterface')
BarInterface = new('BarInterface', [FunInterface])
BobInterface = new('BobInterface')
BazInterface = new('BazInterface', [BobInterface, BarInterface])
self.assertTrue(BazInterface.extends(BobInterface))
self.assertTrue(BazInterface.extends(BarInterface))
self.assertTrue(BazInterface.extends(FunInterface))
self.assertFalse(BobInterface.extends(FunInterface))
self.assertFalse(BobInterface.extends(BarInterface))
self.assertTrue(BarInterface.extends(FunInterface))
self.assertFalse(BarInterface.extends(BazInterface))
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.assertTrue(verifyClass(ICheckMe, CheckMe))
def test_verifyObject(self):
from zope.interface import Attribute
from zope.interface import Interface
from zope.interface.verify import verifyObject
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.assertTrue(verifyObject(ICheckMe, check_me))
def test_interface_object_provides_Interface(self):
from zope.interface import Interface
class AnInterface(Interface):
pass
self.assertTrue(Interface.providedBy(AnInterface))
def test_names_simple(self):
from zope.interface import Attribute
from zope.interface import 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 attr2')
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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(isinstance(a_desc, Attribute))
self.assertEqual(a_desc.__name__, 'attr')
self.assertEqual(a_desc.__doc__, 'My attr')
m_desc = ISimple.getDescriptionFor('method')
self.assertTrue(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.assertTrue(isinstance(a_desc, Attribute))
self.assertEqual(a_desc.__name__, 'attr')
self.assertEqual(a_desc.__doc__, 'My attr')
m_desc = IDerived.getDescriptionFor('method')
self.assertTrue(isinstance(m_desc, Method))
self.assertEqual(m_desc.__name__, 'method')
self.assertEqual(m_desc.__doc__, 'My method, overridden')
a2_desc = IDerived.getDescriptionFor('attr2')
self.assertTrue(isinstance(a2_desc, Attribute))
self.assertEqual(a2_desc.__name__, 'attr2')
self.assertEqual(a2_desc.__doc__, 'My attr2')
m2_desc = IDerived.getDescriptionFor('method2')
self.assertTrue(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.assertTrue(isinstance(a_desc, Attribute))
self.assertEqual(a_desc.__name__, 'attr')
self.assertEqual(a_desc.__doc__, 'My attr')
m_desc = ISimple['method']
self.assertTrue(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.assertTrue(isinstance(a_desc, Attribute))
self.assertEqual(a_desc.__name__, 'attr')
self.assertEqual(a_desc.__doc__, 'My attr')
m_desc = IDerived['method']
self.assertTrue(isinstance(m_desc, Method))
self.assertEqual(m_desc.__name__, 'method')
self.assertEqual(m_desc.__doc__, 'My method, overridden')
a2_desc = IDerived['attr2']
self.assertTrue(isinstance(a2_desc, Attribute))
self.assertEqual(a2_desc.__name__, 'attr2')
self.assertEqual(a2_desc.__doc__, 'My attr2')
m2_desc = IDerived['method2']
self.assertTrue(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.assertFalse('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.assertTrue('attr' in ISimple)
self.assertTrue('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.assertTrue('attr' in IDerived)
self.assertTrue('method' in IDerived)
self.assertTrue('attr2' in IDerived)
self.assertTrue('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 = ITagMe['method']
self.assertEqual(method.getTaggedValue('optional'), 1)
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 as 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))
def test_invariant_simple(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
# set up
has_invariant = HasInvariant()
directlyProvides(has_invariant, IInvariant)
# the tests
self.assertEqual(IInvariant.getTaggedValue('invariants'),
[_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])
has_invariant = HasInvariant()
directlyProvides(has_invariant, ISubInvariant)
has_invariant.foo = 42
# even though the interface has changed, we should still only have one
# error.
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
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!
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
has_invariant.foo = 1
has_invariant.bar = 2
self.assertEqual(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.
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)
IInvariant.setTaggedValue('invariants', invariants)
# even though the interface has changed, we should still only have one
# error.
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
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!
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
has_invariant.foo = 1
has_invariant.bar = 2
self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
# clean up
IInvariant.setTaggedValue('invariants', old_invariants)
def test___doc___element(self):
from zope.interface import Interface
from zope.interface import Attribute
class I(Interface):
"xxx"
self.assertEqual(I.__doc__, "xxx")
self.assertEqual(list(I), [])
class I(Interface):
"xxx"
__doc__ = Attribute('the doc')
self.assertEqual(I.__doc__, "")
self.assertEqual(list(I), ['__doc__'])
def testIssue228(self):
# Test for http://collector.zope.org/Zope3-dev/228
# 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.
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 implementer
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')
@implementer(IRange)
class Range(object):
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 as 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.assertEqual(ITagged.getTaggedValue('qux'), 'Spam')
self.assertTrue('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.assertTrue(I3.get('a') is I1.get('a'))
I2.__bases__ = (Interface,)
self.assertTrue(I3.get('a') is None)
def test___call___defers_to___conform___(self):
from zope.interface import Interface
from zope.interface import implementer
class I(Interface):
pass
@implementer(I)
class C(object):
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 implementer
class I(Interface):
pass
@implementer(I)
class C(object):
pass
c = C()
self.assertTrue(I(c) is c)
def test___call___miss_wo_alternate(self):
from zope.interface import Interface
class I(Interface):
pass
class C(object):
pass
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.assertTrue(I(c, self) is self)
def test___call___w_adapter_hook(self):
from zope.interface import Interface
from zope.interface.interface import adapter_hooks
old_hooks = adapter_hooks[:]
def _miss(iface, obj):
pass
def _hit(iface, obj):
return self
class I(Interface):
pass
class C(object):
pass
c = C()
old_adapter_hooks = adapter_hooks[:]
adapter_hooks[:] = [_miss, _hit]
try:
self.assertTrue(I(c) is self)
finally:
adapter_hooks[:] = old_adapter_hooks
class AttributeTests(ElementTests):
DEFAULT_NAME = 'TestAttribute'
def _getTargetClass(self):
from zope.interface.interface import Attribute
return Attribute
class MethodTests(AttributeTests):
DEFAULT_NAME = 'TestMethod'
def _getTargetClass(self):
from zope.interface.interface import Method
return Method
def test_optional_as_property(self):
method = self._makeOne()
self.assertEqual(method.optional, {})
method.optional = {'foo': 'bar'}
self.assertEqual(method.optional, {'foo': 'bar'})
del method.optional
self.assertEqual(method.optional, {})
def test___call___raises_BrokenImplementation(self):
from zope.interface.exceptions import BrokenImplementation
method = self._makeOne()
try:
method()
except BrokenImplementation as 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(list(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(list(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')
def test_w_non_method(self):
def foo():
"DOCSTRING"
method = self._callFUT(foo)
self.assertEqual(method.getName(), 'foo')
self.assertEqual(method.getDoc(), 'DOCSTRING')
self.assertEqual(method.interface, None)
self.assertEqual(list(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)
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():
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"),
))
zope.interface-4.3.2/src/zope/interface/tests/test_exceptions.py 0000664 0001750 0001750 00000005242 12763206174 024141 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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 \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 \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 ')
zope.interface-4.3.2/src/zope/interface/tests/test_element.py 0000664 0001750 0001750 00000002450 12763206174 023407 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Test Element meta-class.
"""
import unittest
from zope.interface.interface import Element
class TestElement(unittest.TestCase):
def test_taggedValues(self):
"""Test that we can update tagged values of more than one element
"""
e1 = Element("foo")
e2 = Element("bar")
e1.setTaggedValue("x", 1)
e2.setTaggedValue("x", 2)
self.assertEqual(e1.getTaggedValue("x"), 1)
self.assertEqual(e2.getTaggedValue("x"), 2)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestElement))
return suite
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
zope.interface-4.3.2/src/zope/interface/tests/test_document.py 0000664 0001750 0001750 00000040725 12763206174 023603 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Documentation tests.
"""
import unittest
class Test_asStructuredText(unittest.TestCase):
def _callFUT(self, iface):
from zope.interface.document import asStructuredText
return asStructuredText(iface)
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)
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)
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.
It can be used to annotate any class or object, because it promises
nothing.
"""
self.assertEqual(self._callFUT(IEmpty), EXPECTED)
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')
self.assertEqual(self._callFUT(IHasAttribute), EXPECTED)
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.')
self.assertEqual(self._callFUT(IHasAttribute), EXPECTED)
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
self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
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
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 IDerived(IBase):
"IDerived doc"
attr1 = Attribute('attr1')
attr2 = Attribute('attr2', 'attr2 doc')
def method3():
"method3 doc"
def method4():
pass
def method5():
"method5 doc"
self.assertEqual(self._callFUT(IDerived), EXPECTED)
class Test_asReStructuredText(unittest.TestCase):
def _callFUT(self, iface):
from zope.interface.document import asReStructuredText
return asReStructuredText(iface)
def test_asReStructuredText_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)
def test_asReStructuredText_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)
def test_asReStructuredText_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.
It can be used to annotate any class or object, because it promises
nothing.
"""
self.assertEqual(self._callFUT(IEmpty), EXPECTED)
def test_asReStructuredText_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')
self.assertEqual(self._callFUT(IHasAttribute), EXPECTED)
def test_asReStructuredText_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.')
self.assertEqual(self._callFUT(IHasAttribute), EXPECTED)
def test_asReStructuredText_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
self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
def test_asReStructuredText_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_asReStructuredText_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
self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
def test_asReStructuredText_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_asReStructuredText_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_asReStructuredText_derived_ignores_base(self):
from zope.interface import Attribute
from zope.interface import Interface
EXPECTED = '\n\n'.join([
"``IDerived``",
" IDerived doc",
" This interface extends:",
" o ``IBase``",
" Attributes:",
" ``attr1`` -- no documentation",
" ``attr2`` -- attr2 doc",
" Methods:",
" ``method3()`` -- method3 doc",
" ``method4()`` -- no documentation",
" ``method5()`` -- method5 doc",
"",
])
class IBase(Interface):
def method1():
pass
def method2():
pass
class IDerived(IBase):
"IDerived doc"
attr1 = Attribute('attr1')
attr2 = Attribute('attr2', 'attr2 doc')
def method3():
"method3 doc"
def method4():
pass
def method5():
"method5 doc"
self.assertEqual(self._callFUT(IDerived), EXPECTED)
class Test__justify_and_indent(unittest.TestCase):
def _callFUT(self, text, level, **kw):
from zope.interface.document import _justify_and_indent
return _justify_and_indent(text, level, **kw)
def test_simple_level_0(self):
LINES = ['Three blind mice', 'See how they run']
text = '\n'.join(LINES)
self.assertEqual(self._callFUT(text, 0), text)
def test_simple_level_1(self):
LINES = ['Three blind mice', 'See how they run']
text = '\n'.join(LINES)
self.assertEqual(self._callFUT(text, 1),
'\n'.join([' ' + line for line in LINES]))
def test_simple_level_2(self):
LINES = ['Three blind mice', 'See how they run']
text = '\n'.join(LINES)
self.assertEqual(self._callFUT(text, 1),
'\n'.join([' ' + line for line in LINES]))
def test_simple_w_CRLF(self):
LINES = ['Three blind mice', 'See how they run']
text = '\r\n'.join(LINES)
self.assertEqual(self._callFUT(text, 1),
'\n'.join([' ' + line for line in LINES]))
def test_with_munge(self):
TEXT = ("This is a piece of text longer than 15 characters, \n"
"and split across multiple lines.")
EXPECTED = (" This is a piece\n"
" of text longer\n"
" than 15 characters,\n"
" and split across\n"
" multiple lines.\n"
" ")
self.assertEqual(self._callFUT(TEXT, 1, munge=1, width=15), EXPECTED)
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(Test_asStructuredText),
unittest.makeSuite(Test_asReStructuredText),
unittest.makeSuite(Test__justify_and_indent),
))
zope.interface-4.3.2/src/zope/interface/tests/test_declarations.py 0000664 0001750 0001750 00000165233 12763206174 024437 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Test the new API for making and checking interface declarations
"""
import unittest
from zope.interface._compat import _skip_under_py3k
class _Py3ClassAdvice(object):
def _run_generated_code(self, code, globs, locs,
fails_under_py3k=True,
):
import warnings
from zope.interface._compat import PYTHON3
with warnings.catch_warnings(record=True) as log:
warnings.resetwarnings()
if not PYTHON3:
exec(code, globs, locs)
self.assertEqual(len(log), 0) # no longer warn
return True
else:
try:
exec(code, globs, locs)
except TypeError:
return False
else:
if fails_under_py3k:
self.fail("Didn't raise TypeError")
class NamedTests(unittest.TestCase):
def test_class(self):
from zope.interface.declarations import named
@named(u'foo')
class Foo(object):
pass
self.assertEqual(Foo.__component_name__, u'foo')
def test_function(self):
from zope.interface.declarations import named
@named(u'foo')
def doFoo(object):
pass
self.assertEqual(doFoo.__component_name__, u'foo')
def test_instance(self):
from zope.interface.declarations import named
class Foo(object):
pass
foo = Foo()
named(u'foo')(foo)
self.assertEqual(foo.__component_name__, u'foo')
class DeclarationTests(unittest.TestCase):
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.assertFalse('_v_attrs' in decl.__dict__)
def test_changed_w_existing__v_attrs(self):
decl = self._makeOne()
decl._v_attrs = object()
decl.changed(decl)
self.assertFalse('_v_attrs' in decl.__dict__)
def test___contains__w_self(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
decl = self._makeOne()
self.assertFalse(decl in decl)
def test___contains__w_unrelated_iface(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
decl = self._makeOne()
self.assertFalse(IFoo in decl)
def test___contains__w_base_interface(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
decl = self._makeOne(IFoo)
self.assertTrue(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.assertTrue(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.assertTrue(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 TestImplements(unittest.TestCase):
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), '')
def test___reduce__(self):
from zope.interface.declarations import implementedBy
impl = self._makeOne()
self.assertEqual(impl.__reduce__(), (implementedBy, (None,)))
def test_sort(self):
from zope.interface.declarations import implementedBy
class A(object):
pass
class B(object):
pass
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
self.assertEqual(implementedBy(A), implementedBy(A))
self.assertEqual(hash(implementedBy(A)), hash(implementedBy(A)))
self.assertTrue(implementedBy(A) < None)
self.assertTrue(None > implementedBy(A))
self.assertTrue(implementedBy(A) < implementedBy(B))
self.assertTrue(implementedBy(A) > IFoo)
self.assertTrue(implementedBy(A) <= implementedBy(B))
self.assertTrue(implementedBy(A) >= IFoo)
self.assertTrue(implementedBy(A) != IFoo)
def test_proxy_equality(self):
# https://github.com/zopefoundation/zope.interface/issues/55
class Proxy(object):
def __init__(self, wrapped):
self._wrapped = wrapped
def __getattr__(self, name):
return getattr(self._wrapped, name)
def __eq__(self, other):
return self._wrapped == other
def __ne__(self, other):
return self._wrapped != other
from zope.interface.declarations import implementedBy
class A(object):
pass
class B(object):
pass
implementedByA = implementedBy(A)
implementedByB = implementedBy(B)
proxy = Proxy(implementedByA)
# The order of arguments to the operators matters,
# test both
self.assertTrue(implementedByA == implementedByA)
self.assertTrue(implementedByA != implementedByB)
self.assertTrue(implementedByB != implementedByA)
self.assertTrue(proxy == implementedByA)
self.assertTrue(implementedByA == proxy)
self.assertFalse(proxy != implementedByA)
self.assertFalse(implementedByA != proxy)
self.assertTrue(proxy != implementedByB)
self.assertTrue(implementedByB != proxy)
class Test_implementedByFallback(unittest.TestCase):
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()
with _MonkeyDict(declarations,
'BuiltinImplementationSpecifications') as specs:
specs[foo] = reg
self.assertTrue(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.assertTrue(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.assertTrue(self._callFUT(Foo) is impl)
def test_builtins_added_to_cache(self):
from zope.interface import declarations
from zope.interface.declarations import Implements
from zope.interface._compat import _BUILTINS
with _MonkeyDict(declarations,
'BuiltinImplementationSpecifications') as 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.assertTrue(isinstance(spec, Implements))
self.assertEqual(repr(spec),
''
% (_BUILTINS, typ.__name__))
def test_builtins_w_existing_cache(self):
from zope.interface import declarations
t_spec, l_spec, d_spec = object(), object(), object()
with _MonkeyDict(declarations,
'BuiltinImplementationSpecifications') as specs:
specs[tuple] = t_spec
specs[list] = l_spec
specs[dict] = d_spec
self.assertTrue(self._callFUT(tuple) is t_spec)
self.assertTrue(self._callFUT(list) is l_spec)
self.assertTrue(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.assertTrue(spec.inherit is foo)
self.assertTrue(foo.__implemented__ is spec)
self.assertTrue(foo.__providedBy__ is objectSpecificationDescriptor)
self.assertFalse('__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.assertTrue(spec.inherit is Foo)
self.assertTrue(Foo.__implemented__ is spec)
self.assertTrue(isinstance(Foo.__providedBy__, ClassProvides))
self.assertTrue(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.assertTrue(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(unittest.TestCase):
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.assertTrue(spec.inherit is None)
self.assertTrue(Foo.__implemented__ is spec)
self.assertTrue(isinstance(Foo.__providedBy__, ClassProvides))
self.assertTrue(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.assertTrue(Foo.__implemented__ is impl)
self.assertEqual(impl.inherit, None)
self.assertEqual(impl.declared, (IBar,))
class Test_classImplements(unittest.TestCase):
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.assertTrue(spec.inherit is Foo)
self.assertTrue(Foo.__implemented__ is spec)
self.assertTrue(isinstance(Foo.__providedBy__, ClassProvides))
self.assertTrue(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.assertTrue(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('IBaz', IFoo)
b_impl = Implements(IBaz)
impl = Implements(IFoo)
impl.declared = (IFoo,)
class Base1(object):
__implemented__ = b_impl
class Base2(object):
__implemented__ = b_impl
class Foo(Base1, Base2):
__implemented__ = impl
impl.inherit = Foo
self._callFUT(Foo, IBar)
# Same spec, now different values
self.assertTrue(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(unittest.TestCase):
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.assertFalse('__implements_advice_data__' in Foo.__dict__)
self.assertTrue(isinstance(Foo.__implemented__, Implements))
self.assertEqual(list(Foo.__implemented__), [IFoo])
class Test_implementer(unittest.TestCase):
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.assertTrue(returned is Foo)
spec = Foo.__implemented__
self.assertEqual(spec.__name__,
'zope.interface.tests.test_declarations.Foo')
self.assertTrue(spec.inherit is Foo)
self.assertTrue(Foo.__implemented__ is spec)
self.assertTrue(isinstance(Foo.__providedBy__, ClassProvides))
self.assertTrue(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.assertTrue(returned is Foo)
spec = Foo.__implemented__
self.assertEqual(spec.__name__,
'zope.interface.tests.test_declarations.Foo')
self.assertTrue(spec.inherit is Foo)
self.assertTrue(Foo.__implemented__ is spec)
self.assertTrue(isinstance(Foo.__providedBy__, ClassProvides))
self.assertTrue(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.assertTrue(returned is foo)
spec = foo.__implemented__
self.assertEqual(spec.__name__, 'zope.interface.tests.test_declarations.?')
self.assertTrue(spec.inherit is None)
self.assertTrue(foo.__implemented__ is spec)
class Test_implementer_only(unittest.TestCase):
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.assertTrue(returned is Foo)
spec = Foo.__implemented__
self.assertEqual(spec.__name__, '?')
self.assertTrue(spec.inherit is None)
self.assertTrue(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.assertTrue(returned is Foo)
spec = Foo.__implemented__
self.assertEqual(spec.__name__, '?')
self.assertTrue(spec.inherit is None)
self.assertTrue(Foo.__implemented__ is spec)
# Test '_implements' by way of 'implements{,Only}', its only callers.
class Test_implementsOnly(unittest.TestCase, _Py3ClassAdvice):
def _getFUT(self):
from zope.interface.declarations import implementsOnly
return implementsOnly
def test_simple(self):
import warnings
from zope.interface.declarations import implementsOnly
from zope.interface._compat import PYTHON3
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
globs = {'implementsOnly': implementsOnly,
'IFoo': IFoo,
}
locs = {}
CODE = "\n".join([
'class Foo(object):'
' implementsOnly(IFoo)',
])
with warnings.catch_warnings(record=True) as log:
warnings.resetwarnings()
try:
exec(CODE, globs, locs)
except TypeError:
if not PYTHON3:
raise
else:
if PYTHON3:
self.fail("Didn't raise TypeError")
Foo = locs['Foo']
spec = Foo.__implemented__
self.assertEqual(list(spec), [IFoo])
self.assertEqual(len(log), 0) # no longer warn
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)',
])
if self._run_generated_code(CODE, globs, locs):
Bar = locs['Bar']
spec = Bar.__implemented__
self.assertEqual(list(spec), [IBar])
class Test_implements(unittest.TestCase, _Py3ClassAdvice):
def _getFUT(self):
from zope.interface.declarations import implements
return implements
def test_called_from_function(self):
import warnings
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)'
])
if self._run_generated_code(CODE, globs, locs, False):
foo = locs['foo']
with warnings.catch_warnings(record=True) as log:
warnings.resetwarnings()
self.assertRaises(TypeError, foo)
self.assertEqual(len(log), 0) # no longer warn
def test_called_twice_from_class(self):
import warnings
from zope.interface.declarations import implements
from zope.interface.interface import InterfaceClass
from zope.interface._compat import PYTHON3
IFoo = InterfaceClass("IFoo")
IBar = InterfaceClass("IBar")
globs = {'implements': implements, 'IFoo': IFoo, 'IBar': IBar}
locs = {}
CODE = "\n".join([
'class Foo(object):',
' implements(IFoo)',
' implements(IBar)',
])
with warnings.catch_warnings(record=True) as log:
warnings.resetwarnings()
try:
exec(CODE, globs, locs)
except TypeError:
if not PYTHON3:
self.assertEqual(len(log), 0) # no longer warn
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)',
])
if self._run_generated_code(CODE, globs, locs):
Foo = locs['Foo']
spec = Foo.__implemented__
self.assertEqual(list(spec), [IFoo])
class ProvidesClassTests(unittest.TestCase):
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.assertTrue(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.assertTrue(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(unittest.TestCase):
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.assertTrue(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.assertTrue(spec is prior)
class Test_directlyProvides(unittest.TestCase):
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.assertTrue(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.assertTrue(isinstance(Foo.__provides__, ClassProvides))
self.assertEqual(list(Foo.__provides__), [IFoo])
@_skip_under_py3k
def test_w_non_descriptor_aware_metaclass(self):
# There are no non-descriptor-aware types in Py3k
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.assertTrue(isinstance(the_dict['__provides__'], ProvidesClass))
self.assertEqual(list(the_dict['__provides__']), [IFoo])
class Test_alsoProvides(unittest.TestCase):
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.assertTrue(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.assertTrue(isinstance(obj.__provides__, ProvidesClass))
self.assertEqual(list(obj.__provides__), [IFoo, IBar])
class Test_noLongerProvides(unittest.TestCase):
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 implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
@implementer(IFoo)
class Foo(object):
pass
obj = Foo()
self.assertRaises(ValueError, self._callFUT, obj, IFoo)
class ClassProvidesBaseFallbackTests(unittest.TestCase):
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.assertTrue(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.assertTrue(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(unittest.TestCase):
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 implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
IBar = InterfaceClass("IBar")
@implementer(IFoo)
class Foo(object):
pass
cp = Foo.__provides__ = self._makeOne(Foo, type(Foo), IBar)
self.assertTrue(Foo.__provides__ is cp)
self.assertEqual(list(Foo().__provides__), [IFoo])
def test___reduce__(self):
from zope.interface.declarations import implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
IBar = InterfaceClass("IBar")
@implementer(IFoo)
class Foo(object):
pass
cp = Foo.__provides__ = self._makeOne(Foo, type(Foo), IBar)
self.assertEqual(cp.__reduce__(),
(self._getTargetClass(), (Foo, type(Foo), IBar)))
class Test_directlyProvidedBy(unittest.TestCase):
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 implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
@implementer(IFoo)
class Foo(object):
pass
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 implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
IBar = InterfaceClass("IBar")
@implementer(IFoo)
class Foo(object):
pass
foo = Foo()
directlyProvides(foo, IBar)
self.assertEqual(list(self._callFUT(foo)), [IBar])
class Test_classProvides(unittest.TestCase, _Py3ClassAdvice):
def _getFUT(self):
from zope.interface.declarations import classProvides
return classProvides
def test_called_from_function(self):
import warnings
from zope.interface.declarations import classProvides
from zope.interface.interface import InterfaceClass
from zope.interface._compat import PYTHON3
IFoo = InterfaceClass("IFoo")
globs = {'classProvides': classProvides, 'IFoo': IFoo}
locs = {}
CODE = "\n".join([
'def foo():',
' classProvides(IFoo)'
])
exec(CODE, globs, locs)
foo = locs['foo']
with warnings.catch_warnings(record=True) as log:
warnings.resetwarnings()
self.assertRaises(TypeError, foo)
if not PYTHON3:
self.assertEqual(len(log), 0) # no longer warn
def test_called_twice_from_class(self):
import warnings
from zope.interface.declarations import classProvides
from zope.interface.interface import InterfaceClass
from zope.interface._compat import PYTHON3
IFoo = InterfaceClass("IFoo")
IBar = InterfaceClass("IBar")
globs = {'classProvides': classProvides, 'IFoo': IFoo, 'IBar': IBar}
locs = {}
CODE = "\n".join([
'class Foo(object):',
' classProvides(IFoo)',
' classProvides(IBar)',
])
with warnings.catch_warnings(record=True) as log:
warnings.resetwarnings()
try:
exec(CODE, globs, locs)
except TypeError:
if not PYTHON3:
self.assertEqual(len(log), 0) # no longer warn
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)',
])
if self._run_generated_code(CODE, globs, locs):
Foo = locs['Foo']
spec = Foo.__providedBy__
self.assertEqual(list(spec), [IFoo])
# Test _classProvides_advice through classProvides, its only caller.
class Test_provider(unittest.TestCase):
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.assertTrue(isinstance(Foo.__provides__, ClassProvides))
self.assertEqual(list(Foo.__provides__), [IFoo])
class Test_moduleProvides(unittest.TestCase):
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)'
])
exec(CODE, 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}
locs = {}
CODE = "\n".join([
'class Foo(object):',
' moduleProvides(IFoo)',
])
try:
exec(CODE, globs, locs)
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)',
])
exec(CODE, 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}
locs = {}
CODE = "\n".join([
'moduleProvides(IFoo)',
'moduleProvides(IFoo)',
])
try:
exec(CODE, globs)
except TypeError:
pass
else:
assert False, 'TypeError not raised'
class Test_getObjectSpecificationFallback(unittest.TestCase):
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.assertTrue(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 implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
@implementer(IFoo)
class Foo(object):
pass
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(unittest.TestCase):
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 implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
@implementer(IFoo)
class Foo(object):
pass
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.assertTrue(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.assertTrue(spec is expected)
def test_w_providedBy_invalid_spec_w_provides_same_provides_on_class(self):
from zope.interface.declarations import implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
@implementer(IFoo)
class Foo(object):
pass
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(unittest.TestCase):
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 implementer
from zope.interface.declarations import Provides
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
IBar = InterfaceClass("IBar")
@implementer(IFoo)
class Foo(object):
pass
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 implementer
from zope.interface.declarations import Provides
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
IBar = InterfaceClass("IBar")
IBaz = InterfaceClass("IBaz")
@implementer(IFoo)
class Foo(object):
pass
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)
class _MonkeyDict(object):
# context-manager for restoring a dict w/in a module in the scope of a test.
def __init__(self, module, attrname, **kw):
self.module = module
self.target = getattr(module, attrname)
self.to_restore = self.target.copy()
self.target.clear()
self.target.update(kw)
def __enter__(self):
return self.target
def __exit__(self, exc_type, exc_val, exc_tb):
self.target.clear()
self.target.update(self.to_restore)
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(DeclarationTests),
unittest.makeSuite(TestImplements),
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),
))
zope.interface-4.3.2/src/zope/interface/tests/test_advice.py 0000664 0001750 0001750 00000026342 12763206174 023217 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Tests for advice
This module was adapted from 'protocols.tests.advice', part of the Python
Enterprise Application Kit (PEAK). Please notify the PEAK authors
(pje@telecommunity.com and tsarna@sarna.org) if bugs are found or
Zope-specific changes are required, so that the PEAK version of this module
can be kept in sync.
PEAK is a Python application framework that interoperates with (but does
not require) Zope 3 and Twisted. It provides tools for manipulating UML
models, object-relational persistence, aspect-oriented programming, and more.
Visit the PEAK home page at http://peak.telecommunity.com for more information.
"""
import unittest
import sys
from zope.interface._compat import _skip_under_py2
from zope.interface._compat import _skip_under_py3k
class FrameInfoTest(unittest.TestCase):
def test_w_module(self):
from zope.interface.tests import advisory_testing
(kind, module,
f_locals, f_globals) = advisory_testing.moduleLevelFrameInfo
self.assertEqual(kind, "module")
for d in module.__dict__, f_locals, f_globals:
self.assertTrue(d is advisory_testing.my_globals)
@_skip_under_py3k
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.assertEqual(kind, "class")
self.assertTrue(
f_locals is advisory_testing.ClassicClass.__dict__) # ???
for d in module.__dict__, f_globals:
self.assertTrue(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.assertEqual(kind, "class")
for d in module.__dict__, f_globals:
self.assertTrue(d is advisory_testing.my_globals)
def test_inside_function_call(self):
from zope.interface.advice import getFrameInfo
kind, module, f_locals, f_globals = getFrameInfo(sys._getframe())
self.assertEqual(kind, "function call")
self.assertTrue(f_locals is locals()) # ???
for d in module.__dict__, f_globals:
self.assertTrue(d is globals())
def test_inside_exec(self):
from zope.interface.advice import getFrameInfo
_globals = {'getFrameInfo': getFrameInfo}
_locals = {}
exec(_FUNKY_EXEC, _globals, _locals)
self.assertEqual(_locals['kind'], "exec")
self.assertTrue(_locals['f_locals'] is _locals)
self.assertTrue(_locals['module'] is None)
self.assertTrue(_locals['f_globals'] is _globals)
_FUNKY_EXEC = """\
import sys
kind, module, f_locals, f_globals = getFrameInfo(sys._getframe())
"""
class AdviceTests(unittest.TestCase):
@_skip_under_py3k
def test_order(self):
from zope.interface.tests.advisory_testing import ping
log = []
class Foo(object):
ping(log, 1)
ping(log, 2)
ping(log, 3)
# Strip the list nesting
for i in 1, 2, 3:
self.assertTrue(isinstance(Foo, list))
Foo, = Foo
self.assertEqual(log, [(1, Foo), (2, [Foo]), (3, [[Foo]])])
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)
except SyntaxError:
pass
else:
raise AssertionError(
"Should have detected advice outside class body"
)
@_skip_under_py3k
def test_single_explicit_meta(self):
from zope.interface.tests.advisory_testing import ping
class Metaclass(type):
pass
class Concrete(Metaclass):
__metaclass__ = Metaclass
ping([],1)
Concrete, = Concrete
self.assertTrue(Concrete.__class__ is Metaclass)
@_skip_under_py3k
def test_mixed_metas(self):
from zope.interface.tests.advisory_testing import ping
class Metaclass1(type):
pass
class Metaclass2(type):
pass
class Base1:
__metaclass__ = Metaclass1
class Base2:
__metaclass__ = Metaclass2
try:
class Derived(Base1, Base2):
ping([], 1)
except TypeError:
pass
else:
raise AssertionError("Should have gotten incompatibility error")
class Metaclass3(Metaclass1, Metaclass2):
pass
class Derived(Base1, Base2):
__metaclass__ = Metaclass3
ping([], 1)
self.assertTrue(isinstance(Derived, list))
Derived, = Derived
self.assertTrue(isinstance(Derived, Metaclass3))
@_skip_under_py3k
def test_meta_no_bases(self):
from zope.interface.tests.advisory_testing import ping
try:
from types import ClassType
except ImportError:
return
class Thing:
ping([], 1)
klass, = Thing # unpack list created by pong
self.assertEqual(type(klass), ClassType)
class Test_isClassAdvisor(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.interface.advice import isClassAdvisor
return isClassAdvisor(*args, **kw)
def test_w_non_function(self):
self.assertEqual(self._callFUT(self), False)
def test_w_normal_function(self):
def foo():
pass
self.assertEqual(self._callFUT(foo), False)
def test_w_advisor_function(self):
def bar():
pass
bar.previousMetaclass = object()
self.assertEqual(self._callFUT(bar), True)
class Test_determineMetaclass(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.interface.advice import determineMetaclass
return determineMetaclass(*args, **kw)
@_skip_under_py3k
def test_empty(self):
from types import ClassType
self.assertEqual(self._callFUT(()), ClassType)
def test_empty_w_explicit_metatype(self):
class Meta(type):
pass
self.assertEqual(self._callFUT((), Meta), Meta)
def test_single(self):
class Meta(type):
pass
self.assertEqual(self._callFUT((Meta,)), type)
@_skip_under_py3k
def test_meta_of_class(self):
class Metameta(type):
pass
class Meta(type):
__metaclass__ = Metameta
self.assertEqual(self._callFUT((Meta, type)), Metameta)
@_skip_under_py2
def test_meta_of_class_py3k(self):
# Work around SyntaxError under Python2.
EXEC = '\n'.join([
'class Metameta(type):',
' pass',
'class Meta(type, metaclass=Metameta):',
' pass',
])
globs = {}
exec(EXEC, globs)
Meta = globs['Meta']
Metameta = globs['Metameta']
self.assertEqual(self._callFUT((Meta, type)), Metameta)
@_skip_under_py3k
def test_multiple_in_hierarchy(self):
class Meta_A(type):
pass
class Meta_B(Meta_A):
pass
class A(type):
__metaclass__ = Meta_A
class B(type):
__metaclass__ = Meta_B
self.assertEqual(self._callFUT((A, B,)), Meta_B)
@_skip_under_py2
def test_multiple_in_hierarchy_py3k(self):
# Work around SyntaxError under Python2.
EXEC = '\n'.join([
'class Meta_A(type):',
' pass',
'class Meta_B(Meta_A):',
' pass',
'class A(type, metaclass=Meta_A):',
' pass',
'class B(type, metaclass=Meta_B):',
' pass',
])
globs = {}
exec(EXEC, globs)
Meta_A = globs['Meta_A']
Meta_B = globs['Meta_B']
A = globs['A']
B = globs['B']
self.assertEqual(self._callFUT((A, B)), Meta_B)
@_skip_under_py3k
def test_multiple_not_in_hierarchy(self):
class Meta_A(type):
pass
class Meta_B(type):
pass
class A(type):
__metaclass__ = Meta_A
class B(type):
__metaclass__ = Meta_B
self.assertRaises(TypeError, self._callFUT, (A, B,))
@_skip_under_py2
def test_multiple_not_in_hierarchy_py3k(self):
# Work around SyntaxError under Python2.
EXEC = '\n'.join([
'class Meta_A(type):',
' pass',
'class Meta_B(type):',
' pass',
'class A(type, metaclass=Meta_A):',
' pass',
'class B(type, metaclass=Meta_B):',
' pass',
])
globs = {}
exec(EXEC, globs)
Meta_A = globs['Meta_A']
Meta_B = globs['Meta_B']
A = globs['A']
B = globs['B']
self.assertRaises(TypeError, self._callFUT, (A, B))
class Test_minimalBases(unittest.TestCase):
def _callFUT(self, klasses):
from zope.interface.advice import minimalBases
return minimalBases(klasses)
def test_empty(self):
self.assertEqual(self._callFUT([]), [])
@_skip_under_py3k
def test_w_oldstyle_meta(self):
class C:
pass
self.assertEqual(self._callFUT([type(C)]), [])
@_skip_under_py3k
def test_w_oldstyle_class(self):
class C:
pass
self.assertEqual(self._callFUT([C]), [C])
def test_w_newstyle_meta(self):
self.assertEqual(self._callFUT([type]), [type])
def test_w_newstyle_class(self):
class C(object):
pass
self.assertEqual(self._callFUT([C]), [C])
def test_simple_hierarchy_skips_implied(self):
class A(object):
pass
class B(A):
pass
class C(B):
pass
class D(object):
pass
self.assertEqual(self._callFUT([A, B, C]), [C])
self.assertEqual(self._callFUT([A, C]), [C])
self.assertEqual(self._callFUT([B, C]), [C])
self.assertEqual(self._callFUT([A, B]), [B])
self.assertEqual(self._callFUT([D, B, D]), [B, D])
def test_repeats_kicked_to_end_of_queue(self):
class A(object):
pass
class B(object):
pass
self.assertEqual(self._callFUT([A, B, A]), [B, A])
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(FrameInfoTest),
unittest.makeSuite(AdviceTests),
unittest.makeSuite(Test_isClassAdvisor),
unittest.makeSuite(Test_determineMetaclass),
unittest.makeSuite(Test_minimalBases),
))
zope.interface-4.3.2/src/zope/interface/tests/test_adapter.py 0000664 0001750 0001750 00000150765 12763206174 023413 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Adapter registry tests
"""
import unittest
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(unittest.TestCase):
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.assertTrue(
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.assertTrue(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.assertTrue(IB2 in registry._adapters[2][IB1])
self.assertTrue(IB3 in registry._adapters[2][IB1])
registry.unregister([IB1, IB3], None, '', another)
self.assertTrue(IB2 in registry._adapters[2][IB1])
self.assertFalse(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()
fourth = object()
registry.subscribe([IB1], None, first)
registry.subscribe([IB1], None, second)
registry.subscribe([IB1], IR0, third)
registry.subscribe([IB1], IR0, fourth)
registry.unsubscribe([IB1], IR0, fourth)
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(unittest.TestCase):
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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(found is _default)
found = lb.lookup1('A', 'B', 'C', _default)
self.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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(unittest.TestCase):
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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(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.assertTrue(adapted is a)
adapted = lb.adapter_hook(prv, req, 'C', _default)
self.assertTrue(adapted is a)
reg.ro[1]._generation += 1
adapted = lb.adapter_hook(prv, req, 'C', _default)
self.assertTrue(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.assertTrue(adapted is a)
adapted = lb.queryAdapter(req, prv, 'C', _default)
self.assertTrue(adapted is a)
reg.ro[1]._generation += 1
adapted = lb.adapter_hook(prv, req, 'C', _default)
self.assertTrue(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(unittest.TestCase):
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.assertTrue(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_wrong_iface(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
IBar = InterfaceClass('IBar', IFoo)
IQux = InterfaceClass('IQux')
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
irrelevant = object()
subr._adapters = [ #utilities, single adapters
{},
{IFoo: {IQux: {'': irrelevant},
}},
]
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_wrong_name(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
IBar = InterfaceClass('IBar', IFoo)
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
irrelevant = object()
wrongname = object()
subr._adapters = [ #utilities, single adapters
{},
{IFoo: {IBar: {'wrongname': wrongname},
}},
]
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.assertTrue(result is _expected)
def test__uncached_lookup_repeated_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)
result2 = alb._uncached_lookup((IFoo,), IBar)
self.assertTrue(result is _expected)
self.assertTrue(result2 is _expected)
def test_queryMultiAdaptor_lookup_miss(self):
from zope.interface.declarations import implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
IBar = InterfaceClass('IBar', IFoo)
@implementer(IFoo)
class Foo(object):
pass
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.assertTrue(result is _default)
def test_queryMultiAdaptor_factory_miss(self):
from zope.interface.declarations import implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
IBar = InterfaceClass('IBar', IFoo)
@implementer(IFoo)
class Foo(object):
pass
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.assertTrue(result is _default)
self.assertEqual(_called_with, [foo])
def test_queryMultiAdaptor_factory_hit(self):
from zope.interface.declarations import implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
IBar = InterfaceClass('IBar', IFoo)
@implementer(IFoo)
class Foo(object):
pass
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.assertTrue(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.assertTrue(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)
IQux = InterfaceClass('IQux')
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
irrelevant = object()
subr._adapters = [ #utilities, single adapters
{},
{IFoo: {IQux: {'': irrelevant}}},
]
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.assertTrue(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_wrong_iface(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
IBar = InterfaceClass('IBar', IFoo)
IQux = InterfaceClass('IQux')
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
irrelevant = object()
subr._subscribers = [ #utilities, single adapters
{},
{IFoo: {IQux: {'': irrelevant}}},
]
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_wrong_name(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
IBar = InterfaceClass('IBar', IFoo)
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
wrongname = object()
subr._subscribers = [ #utilities, single adapters
{},
{IFoo: {IBar: {'wrongname': wrongname}}},
]
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()
class Foo(object):
def __lt__(self, other):
return True
_exp1, _exp2 = Foo(), Foo()
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 implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
IBar = InterfaceClass('IBar', IFoo)
@implementer(IFoo)
class Foo(object):
pass
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 implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
IBar = InterfaceClass('IBar', IFoo)
@implementer(IFoo)
class Foo(object):
pass
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
def _side_effect_only(context):
_called.setdefault('_side_effect_only', []).append(context)
return None
subr._subscribers = [ #utilities, single adapters
{},
{IFoo: {IBar: {'': (_factory1, _factory2, _side_effect_only)}}},
]
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],
'_side_effect_only': [foo],
})
class AdapterRegistryTests(unittest.TestCase):
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.assertTrue(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.assertTrue(sub in after._v_subregistries)
def test__setBases_wo_stray_entry(self):
before = self._makeOne()
stray = self._makeOne()
after = self._makeOne()
sub = self._makeOne([before])
sub.__dict__['__bases__'].append(stray)
sub.__bases__ = [after]
self.assertEqual(len(before._v_subregistries), 0)
self.assertEqual(len(after._v_subregistries), 1)
self.assertTrue(sub in after._v_subregistries)
def test__setBases_w_existing_entry_continuing(self):
before = self._makeOne()
after = self._makeOne()
sub = self._makeOne([before])
sub.__bases__ = [before, after]
self.assertEqual(len(before._v_subregistries), 1)
self.assertEqual(len(after._v_subregistries), 1)
self.assertTrue(sub in before._v_subregistries)
self.assertTrue(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.assertTrue(derived1._changed is orig)
self.assertTrue(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.assertTrue(_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.assertTrue(_convert_None_to_Interface(other) is other)
def test__normalize_name_str(self):
import sys
from zope.interface.adapter import _normalize_name
STR = b'str'
if sys.version_info[0] < 3:
self.assertEqual(_normalize_name(STR), unicode(STR))
else:
self.assertEqual(_normalize_name(STR), str(STR, 'ascii'))
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((
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),
))
zope.interface-4.3.2/src/zope/interface/tests/odd.py 0000664 0001750 0001750 00000006007 12763206174 021467 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Odd meta class that doesn't subclass type.
This is used for testing support for ExtensionClass in new interfaces.
>>> class A(object):
... __metaclass__ = MetaClass
... a = 1
...
>>> A.__name__
'A'
>>> A.__bases__ == (object,)
True
>>> class B(object):
... __metaclass__ = MetaClass
... b = 1
...
>>> class C(A, B): pass
...
>>> C.__name__
'C'
>>> int(C.__bases__ == (A, B))
1
>>> a = A()
>>> aa = A()
>>> a.a
1
>>> aa.a
1
>>> aa.a = 2
>>> a.a
1
>>> aa.a
2
>>> c = C()
>>> c.a
1
>>> c.b
1
>>> c.b = 2
>>> c.b
2
>>> C.c = 1
>>> c.c
1
>>> import sys
>>> if sys.version[0] == '2': # This test only makes sense under Python 2.x
... from types import ClassType
... assert not isinstance(C, (type, ClassType))
>>> int(C.__class__.__class__ is C.__class__)
1
"""
# class OddClass is an odd meta class
class MetaMetaClass(type):
def __getattribute__(self, name):
if name == '__class__':
return self
return type.__getattribute__(self, name)
class MetaClass(object):
"""Odd classes
"""
__metaclass__ = MetaMetaClass
def __init__(self, name, bases, dict):
self.__name__ = name
self.__bases__ = bases
self.__dict__.update(dict)
def __call__(self):
return OddInstance(self)
def __getattr__(self, name):
for b in self.__bases__:
v = getattr(b, name, self)
if v is not self:
return v
raise AttributeError(name)
def __repr__(self):
return "" % (self.__name__, hex(id(self)))
class OddInstance(object):
def __init__(self, cls):
self.__dict__['__class__'] = cls
def __getattribute__(self, name):
dict = object.__getattribute__(self, '__dict__')
if name == '__dict__':
return dict
v = dict.get(name, self)
if v is not self:
return v
return getattr(dict['__class__'], name)
def __setattr__(self, name, v):
self.__dict__[name] = v
def __delattr__(self, name):
del self.__dict__[name]
def __repr__(self):
return "" % (
self.__class__.__name__, hex(id(self)))
# DocTest:
if __name__ == "__main__":
import doctest, __main__
doctest.testmod(__main__, isprivate=lambda *a: False)
zope.interface-4.3.2/src/zope/interface/tests/m2.py 0000664 0001750 0001750 00000001261 12763206174 021234 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2004 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.
#
##############################################################################
"""Test module that doesn't declare an interface
"""
zope.interface-4.3.2/src/zope/interface/tests/m1.py 0000664 0001750 0001750 00000001454 12763206174 021237 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2004 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.
#
##############################################################################
"""Test module that declares an interface
"""
from zope.interface import Interface, moduleProvides
class I1(Interface): pass
class I2(Interface): pass
moduleProvides(I1, I2)
zope.interface-4.3.2/src/zope/interface/tests/ifoo_other.py 0000664 0001750 0001750 00000001523 12763206174 023054 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""IFoo test module
"""
from zope.interface import Interface
class IFoo(Interface):
"""
Dummy interface for unit tests.
"""
def bar(baz):
"""
Just a note.
"""
zope.interface-4.3.2/src/zope/interface/tests/ifoo.py 0000664 0001750 0001750 00000001523 12763206174 021653 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""IFoo test module
"""
from zope.interface import Interface
class IFoo(Interface):
"""
Dummy interface for unit tests.
"""
def bar(baz):
"""
Just a note.
"""
zope.interface-4.3.2/src/zope/interface/tests/idummy.py 0000664 0001750 0001750 00000001571 12763206174 022226 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
"""
zope.interface-4.3.2/src/zope/interface/tests/dummy.py 0000664 0001750 0001750 00000001570 12763206174 022054 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
""" Dummy Module
"""
from zope.interface import moduleProvides
from zope.interface.tests.idummy import IDummyModule
moduleProvides(IDummyModule)
def bar(baz):
# Note: no 'self', because the module provides the interface directly.
pass
zope.interface-4.3.2/src/zope/interface/tests/advisory_testing.py 0000664 0001750 0001750 00000002354 12763206174 024317 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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())
zope.interface-4.3.2/src/zope/interface/tests/__init__.py 0000664 0001750 0001750 00000000741 12763206174 022457 0 ustar mg mg 0000000 0000000 import os
import unittest
def additional_tests():
suites = unittest.TestSuite()
for file in os.listdir(os.path.dirname(__file__)):
if file.endswith('.py') and file!='__init__.py':
name = os.path.splitext(file)[0]
module = __import__('.'.join((__name__, name)), globals(),
locals(), [name])
if hasattr(module, 'test_suite'):
suites.addTests(module.test_suite())
return suites
zope.interface-4.3.2/src/zope/interface/common/ 0000775 0001750 0001750 00000000000 12763206175 020473 5 ustar mg mg 0000000 0000000 zope.interface-4.3.2/src/zope/interface/common/sequence.py 0000664 0001750 0001750 00000011075 12763206174 022660 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Sequence Interfaces
"""
__docformat__ = 'restructuredtext'
from zope.interface import Interface
class IMinimalSequence(Interface):
"""Most basic sequence interface.
All sequences are iterable. This requires at least one of the
following:
- a `__getitem__()` method that takes a single argument; interger
values starting at 0 must be supported, and `IndexError` should
be raised for the first index for which there is no value, or
- an `__iter__()` method that returns an iterator as defined in
the Python documentation (http://docs.python.org/lib/typeiter.html).
"""
def __getitem__(index):
"""`x.__getitem__(index)` <==> `x[index]`
Declaring this interface does not specify whether `__getitem__`
supports slice objects."""
class IFiniteSequence(IMinimalSequence):
def __len__():
"""`x.__len__()` <==> `len(x)`"""
class IReadSequence(IFiniteSequence):
"""read interface shared by tuple and list"""
def __contains__(item):
"""`x.__contains__(item)` <==> `item in x`"""
def __lt__(other):
"""`x.__lt__(other)` <==> `x < other`"""
def __le__(other):
"""`x.__le__(other)` <==> `x <= other`"""
def __eq__(other):
"""`x.__eq__(other)` <==> `x == other`"""
def __ne__(other):
"""`x.__ne__(other)` <==> `x != other`"""
def __gt__(other):
"""`x.__gt__(other)` <==> `x > other`"""
def __ge__(other):
"""`x.__ge__(other)` <==> `x >= other`"""
def __add__(other):
"""`x.__add__(other)` <==> `x + other`"""
def __mul__(n):
"""`x.__mul__(n)` <==> `x * n`"""
def __rmul__(n):
"""`x.__rmul__(n)` <==> `n * x`"""
def __getslice__(i, j):
"""`x.__getslice__(i, j)` <==> `x[i:j]`
Use of negative indices is not supported.
Deprecated since Python 2.0 but still a part of `UserList`.
"""
class IExtendedReadSequence(IReadSequence):
"""Full read interface for lists"""
def count(item):
"""Return number of occurrences of value"""
def index(item, *args):
"""Return first index of value
`L.index(value, [start, [stop]])` -> integer"""
class IUniqueMemberWriteSequence(Interface):
"""The write contract for a sequence that may enforce unique members"""
def __setitem__(index, item):
"""`x.__setitem__(index, item)` <==> `x[index] = item`
Declaring this interface does not specify whether `__setitem__`
supports slice objects.
"""
def __delitem__(index):
"""`x.__delitem__(index)` <==> `del x[index]`
Declaring this interface does not specify whether `__delitem__`
supports slice objects.
"""
def __setslice__(i, j, other):
"""`x.__setslice__(i, j, other)` <==> `x[i:j]=other`
Use of negative indices is not supported.
Deprecated since Python 2.0 but still a part of `UserList`.
"""
def __delslice__(i, j):
"""`x.__delslice__(i, j)` <==> `del x[i:j]`
Use of negative indices is not supported.
Deprecated since Python 2.0 but still a part of `UserList`.
"""
def __iadd__(y):
"""`x.__iadd__(y)` <==> `x += y`"""
def append(item):
"""Append item to end"""
def insert(index, item):
"""Insert item before index"""
def pop(index=-1):
"""Remove and return item at index (default last)"""
def remove(item):
"""Remove first occurrence of value"""
def reverse():
"""Reverse *IN PLACE*"""
def sort(cmpfunc=None):
"""Stable sort *IN PLACE*; `cmpfunc(x, y)` -> -1, 0, 1"""
def extend(iterable):
"""Extend list by appending elements from the iterable"""
class IWriteSequence(IUniqueMemberWriteSequence):
"""Full write contract for sequences"""
def __imul__(n):
"""`x.__imul__(n)` <==> `x *= n`"""
class ISequence(IReadSequence, IWriteSequence):
"""Full sequence contract"""
zope.interface-4.3.2/src/zope/interface/common/mapping.py 0000664 0001750 0001750 00000006601 12763206174 022502 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Mapping Interfaces
"""
from zope.interface import Interface
class IItemMapping(Interface):
"""Simplest readable mapping object
"""
def __getitem__(key):
"""Get a value for a key
A KeyError is raised if there is no value for the key.
"""
class IReadMapping(IItemMapping):
"""Basic mapping interface
"""
def get(key, default=None):
"""Get a value for a key
The default is returned if there is no value for the key.
"""
def __contains__(key):
"""Tell if a key exists in the mapping."""
class IWriteMapping(Interface):
"""Mapping methods for changing data"""
def __delitem__(key):
"""Delete a value from the mapping using the key."""
def __setitem__(key, value):
"""Set a new item in the mapping."""
class IEnumerableMapping(IReadMapping):
"""Mapping objects whose items can be enumerated.
"""
def keys():
"""Return the keys of the mapping object.
"""
def __iter__():
"""Return an iterator for the keys of the mapping object.
"""
def values():
"""Return the values of the mapping object.
"""
def items():
"""Return the items of the mapping object.
"""
def __len__():
"""Return the number of items.
"""
class IMapping(IWriteMapping, IEnumerableMapping):
''' Simple mapping interface '''
class IIterableMapping(IEnumerableMapping):
def iterkeys():
"iterate over keys; equivalent to __iter__"
def itervalues():
"iterate over values"
def iteritems():
"iterate over items"
class IClonableMapping(Interface):
def copy():
"return copy of dict"
class IExtendedReadMapping(IIterableMapping):
def has_key(key):
"""Tell if a key exists in the mapping; equivalent to __contains__"""
class IExtendedWriteMapping(IWriteMapping):
def clear():
"delete all items"
def update(d):
" Update D from E: for k in E.keys(): D[k] = E[k]"
def setdefault(key, default=None):
"D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"
def pop(k, *args):
"""remove specified key and return the corresponding value
*args may contain a single default value, or may not be supplied.
If key is not found, default is returned if given, otherwise
KeyError is raised"""
def popitem():
"""remove and return some (key, value) pair as a
2-tuple; but raise KeyError if mapping is empty"""
class IFullMapping(
IExtendedReadMapping, IExtendedWriteMapping, IClonableMapping, IMapping):
''' Full mapping interface ''' # IMapping included so tests for IMapping
# succeed with IFullMapping
zope.interface-4.3.2/src/zope/interface/common/interfaces.py 0000664 0001750 0001750 00000010237 12763206174 023172 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Interfaces for standard python exceptions
"""
from zope.interface import Interface
from zope.interface import classImplements
class IException(Interface): pass
class IStandardError(IException): pass
class IWarning(IException): pass
class ISyntaxError(IStandardError): pass
class ILookupError(IStandardError): pass
class IValueError(IStandardError): pass
class IRuntimeError(IStandardError): pass
class IArithmeticError(IStandardError): pass
class IAssertionError(IStandardError): pass
class IAttributeError(IStandardError): pass
class IDeprecationWarning(IWarning): pass
class IEOFError(IStandardError): pass
class IEnvironmentError(IStandardError): pass
class IFloatingPointError(IArithmeticError): pass
class IIOError(IEnvironmentError): pass
class IImportError(IStandardError): pass
class IIndentationError(ISyntaxError): pass
class IIndexError(ILookupError): pass
class IKeyError(ILookupError): pass
class IKeyboardInterrupt(IStandardError): pass
class IMemoryError(IStandardError): pass
class INameError(IStandardError): pass
class INotImplementedError(IRuntimeError): pass
class IOSError(IEnvironmentError): pass
class IOverflowError(IArithmeticError): pass
class IOverflowWarning(IWarning): pass
class IReferenceError(IStandardError): pass
class IRuntimeWarning(IWarning): pass
class IStopIteration(IException): pass
class ISyntaxWarning(IWarning): pass
class ISystemError(IStandardError): pass
class ISystemExit(IException): pass
class ITabError(IIndentationError): pass
class ITypeError(IStandardError): pass
class IUnboundLocalError(INameError): pass
class IUnicodeError(IValueError): pass
class IUserWarning(IWarning): pass
class IZeroDivisionError(IArithmeticError): pass
classImplements(ArithmeticError, IArithmeticError)
classImplements(AssertionError, IAssertionError)
classImplements(AttributeError, IAttributeError)
classImplements(DeprecationWarning, IDeprecationWarning)
classImplements(EnvironmentError, IEnvironmentError)
classImplements(EOFError, IEOFError)
classImplements(Exception, IException)
classImplements(FloatingPointError, IFloatingPointError)
classImplements(ImportError, IImportError)
classImplements(IndentationError, IIndentationError)
classImplements(IndexError, IIndexError)
classImplements(IOError, IIOError)
classImplements(KeyboardInterrupt, IKeyboardInterrupt)
classImplements(KeyError, IKeyError)
classImplements(LookupError, ILookupError)
classImplements(MemoryError, IMemoryError)
classImplements(NameError, INameError)
classImplements(NotImplementedError, INotImplementedError)
classImplements(OSError, IOSError)
classImplements(OverflowError, IOverflowError)
try:
classImplements(OverflowWarning, IOverflowWarning)
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: #pragma NO COVER
pass # StandardError does not exist in Python 3
classImplements(StopIteration, IStopIteration)
classImplements(SyntaxError, ISyntaxError)
classImplements(SyntaxWarning, ISyntaxWarning)
classImplements(SystemError, ISystemError)
classImplements(SystemExit, ISystemExit)
classImplements(TabError, ITabError)
classImplements(TypeError, ITypeError)
classImplements(UnboundLocalError, IUnboundLocalError)
classImplements(UnicodeError, IUnicodeError)
classImplements(UserWarning, IUserWarning)
classImplements(ValueError, IValueError)
classImplements(Warning, IWarning)
classImplements(ZeroDivisionError, IZeroDivisionError)
zope.interface-4.3.2/src/zope/interface/common/idatetime.py 0000664 0001750 0001750 00000047127 12763206174 023024 0 ustar mg mg 0000000 0000000 ##############################################################################
# Copyright (c) 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.
##############################################################################
"""Datetime interfaces.
This module is called idatetime because if it were called datetime the import
of the real datetime would fail.
"""
from zope.interface import Interface, Attribute
from zope.interface import classImplements
from datetime import timedelta, date, datetime, time, tzinfo
class ITimeDeltaClass(Interface):
"""This is the timedelta class interface."""
min = Attribute("The most negative timedelta object")
max = Attribute("The most positive timedelta object")
resolution = Attribute(
"The smallest difference between non-equal timedelta objects")
class ITimeDelta(ITimeDeltaClass):
"""Represent the difference between two datetime objects.
Supported operators:
- add, subtract timedelta
- unary plus, minus, abs
- compare to timedelta
- multiply, divide by int/long
In addition, datetime supports subtraction of two datetime objects
returning a timedelta, and addition or subtraction of a datetime
and a timedelta giving a datetime.
Representation: (days, seconds, microseconds).
"""
days = Attribute("Days between -999999999 and 999999999 inclusive")
seconds = Attribute("Seconds between 0 and 86399 inclusive")
microseconds = Attribute("Microseconds between 0 and 999999 inclusive")
class IDateClass(Interface):
"""This is the date class interface."""
min = Attribute("The earliest representable date")
max = Attribute("The latest representable date")
resolution = Attribute(
"The smallest difference between non-equal date objects")
def today():
"""Return the current local time.
This is equivalent to date.fromtimestamp(time.time())"""
def fromtimestamp(timestamp):
"""Return the local date from a POSIX timestamp (like time.time())
This may raise ValueError, if the timestamp is out of the range of
values supported by the platform C localtime() function. It's common
for this to be restricted to years from 1970 through 2038. Note that
on non-POSIX systems that include leap seconds in their notion of a
timestamp, leap seconds are ignored by fromtimestamp().
"""
def fromordinal(ordinal):
"""Return the date corresponding to the proleptic Gregorian ordinal.
January 1 of year 1 has ordinal 1. ValueError is raised unless
1 <= ordinal <= date.max.toordinal().
For any date d, date.fromordinal(d.toordinal()) == d.
"""
class IDate(IDateClass):
"""Represents a date (year, month and day) in an idealized calendar.
Operators:
__repr__, __str__
__cmp__, __hash__
__add__, __radd__, __sub__ (add/radd only with timedelta arg)
"""
year = Attribute("Between MINYEAR and MAXYEAR inclusive.")
month = Attribute("Between 1 and 12 inclusive")
day = Attribute(
"Between 1 and the number of days in the given month of the given year.")
def replace(year, month, day):
"""Return a date with the same value.
Except for those members given new values by whichever keyword
arguments are specified. For example, if d == date(2002, 12, 31), then
d.replace(day=26) == date(2000, 12, 26).
"""
def timetuple():
"""Return a 9-element tuple of the form returned by time.localtime().
The hours, minutes and seconds are 0, and the DST flag is -1.
d.timetuple() is equivalent to
(d.year, d.month, d.day, 0, 0, 0, d.weekday(), d.toordinal() -
date(d.year, 1, 1).toordinal() + 1, -1)
"""
def toordinal():
"""Return the proleptic Gregorian ordinal of the date
January 1 of year 1 has ordinal 1. For any date object d,
date.fromordinal(d.toordinal()) == d.
"""
def weekday():
"""Return the day of the week as an integer.
Monday is 0 and Sunday is 6. For example,
date(2002, 12, 4).weekday() == 2, a Wednesday.
See also isoweekday().
"""
def isoweekday():
"""Return the day of the week as an integer.
Monday is 1 and Sunday is 7. For example,
date(2002, 12, 4).isoweekday() == 3, a Wednesday.
See also weekday(), isocalendar().
"""
def isocalendar():
"""Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
The ISO calendar is a widely used variant of the Gregorian calendar.
See http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm for a good
explanation.
The ISO year consists of 52 or 53 full weeks, and where a week starts
on a Monday and ends on a Sunday. The first week of an ISO year is the
first (Gregorian) calendar week of a year containing a Thursday. This
is called week number 1, and the ISO year of that Thursday is the same
as its Gregorian year.
For example, 2004 begins on a Thursday, so the first week of ISO year
2004 begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004, so
that date(2003, 12, 29).isocalendar() == (2004, 1, 1) and
date(2004, 1, 4).isocalendar() == (2004, 1, 7).
"""
def isoformat():
"""Return a string representing the date in ISO 8601 format.
This is 'YYYY-MM-DD'.
For example, date(2002, 12, 4).isoformat() == '2002-12-04'.
"""
def __str__():
"""For a date d, str(d) is equivalent to d.isoformat()."""
def ctime():
"""Return a string representing the date.
For example date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'.
d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple()))
on platforms where the native C ctime() function
(which time.ctime() invokes, but which date.ctime() does not invoke)
conforms to the C standard.
"""
def strftime(format):
"""Return a string representing the date.
Controlled by an explicit format string. Format codes referring to
hours, minutes or seconds will see 0 values.
"""
class IDateTimeClass(Interface):
"""This is the datetime class interface."""
min = Attribute("The earliest representable datetime")
max = Attribute("The latest representable datetime")
resolution = Attribute(
"The smallest possible difference between non-equal datetime objects")
def today():
"""Return the current local datetime, with tzinfo None.
This is equivalent to datetime.fromtimestamp(time.time()).
See also now(), fromtimestamp().
"""
def now(tz=None):
"""Return the current local date and time.
If optional argument tz is None or not specified, this is like today(),
but, if possible, supplies more precision than can be gotten from going
through a time.time() timestamp (for example, this may be possible on
platforms supplying the C gettimeofday() function).
Else tz must be an instance of a class tzinfo subclass, and the current
date and time are converted to tz's time zone. In this case the result
is equivalent to tz.fromutc(datetime.utcnow().replace(tzinfo=tz)).
See also today(), utcnow().
"""
def utcnow():
"""Return the current UTC date and time, with tzinfo None.
This is like now(), but returns the current UTC date and time, as a
naive datetime object.
See also now().
"""
def fromtimestamp(timestamp, tz=None):
"""Return the local date and time corresponding to the POSIX timestamp.
Same as is returned by time.time(). If optional argument tz is None or
not specified, the timestamp is converted to the platform's local date
and time, and the returned datetime object is naive.
Else tz must be an instance of a class tzinfo subclass, and the
timestamp is converted to tz's time zone. In this case the result is
equivalent to
tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)).
fromtimestamp() may raise ValueError, if the timestamp is out of the
range of values supported by the platform C localtime() or gmtime()
functions. It's common for this to be restricted to years in 1970
through 2038. Note that on non-POSIX systems that include leap seconds
in their notion of a timestamp, leap seconds are ignored by
fromtimestamp(), and then it's possible to have two timestamps
differing by a second that yield identical datetime objects.
See also utcfromtimestamp().
"""
def utcfromtimestamp(timestamp):
"""Return the UTC datetime from the POSIX timestamp with tzinfo None.
This may raise ValueError, if the timestamp is out of the range of
values supported by the platform C gmtime() function. It's common for
this to be restricted to years in 1970 through 2038.
See also fromtimestamp().
"""
def fromordinal(ordinal):
"""Return the datetime from the proleptic Gregorian ordinal.
January 1 of year 1 has ordinal 1. ValueError is raised unless
1 <= ordinal <= datetime.max.toordinal().
The hour, minute, second and microsecond of the result are all 0, and
tzinfo is None.
"""
def combine(date, time):
"""Return a new datetime object.
Its date members are equal to the given date object's, and whose time
and tzinfo members are equal to the given time object's. For any
datetime object d, d == datetime.combine(d.date(), d.timetz()).
If date is a datetime object, its time and tzinfo members are ignored.
"""
class IDateTime(IDate, IDateTimeClass):
"""Object contains all the information from a date object and a time object.
"""
year = Attribute("Year between MINYEAR and MAXYEAR inclusive")
month = Attribute("Month between 1 and 12 inclusive")
day = Attribute(
"Day between 1 and the number of days in the given month of the year")
hour = Attribute("Hour in range(24)")
minute = Attribute("Minute in range(60)")
second = Attribute("Second in range(60)")
microsecond = Attribute("Microsecond in range(1000000)")
tzinfo = Attribute(
"""The object passed as the tzinfo argument to the datetime constructor
or None if none was passed""")
def date():
"""Return date object with same year, month and day."""
def time():
"""Return time object with same hour, minute, second, microsecond.
tzinfo is None. See also method timetz().
"""
def timetz():
"""Return time object with same hour, minute, second, microsecond,
and tzinfo.
See also method time().
"""
def replace(year, month, day, hour, minute, second, microsecond, tzinfo):
"""Return a datetime with the same members, except for those members
given new values by whichever keyword arguments are specified.
Note that tzinfo=None can be specified to create a naive datetime from
an aware datetime with no conversion of date and time members.
"""
def astimezone(tz):
"""Return a datetime object with new tzinfo member tz, adjusting the
date and time members so the result is the same UTC time as self, but
in tz's local time.
tz must be an instance of a tzinfo subclass, and its utcoffset() and
dst() methods must not return None. self must be aware (self.tzinfo
must not be None, and self.utcoffset() must not return None).
If self.tzinfo is tz, self.astimezone(tz) is equal to self: no
adjustment of date or time members is performed. Else the result is
local time in time zone tz, representing the same UTC time as self:
after astz = dt.astimezone(tz), astz - astz.utcoffset()
will usually have the same date and time members as dt - dt.utcoffset().
The discussion of class tzinfo explains the cases at Daylight Saving
Time transition boundaries where this cannot be achieved (an issue only
if tz models both standard and daylight time).
If you merely want to attach a time zone object tz to a datetime dt
without adjustment of date and time members, use dt.replace(tzinfo=tz).
If you merely want to remove the time zone object from an aware
datetime dt without conversion of date and time members, use
dt.replace(tzinfo=None).
Note that the default tzinfo.fromutc() method can be overridden in a
tzinfo subclass to effect the result returned by astimezone().
"""
def utcoffset():
"""Return the timezone offset in minutes east of UTC (negative west of
UTC)."""
def dst():
"""Return 0 if DST is not in effect, or the DST offset (in minutes
eastward) if DST is in effect.
"""
def tzname():
"""Return the timezone name."""
def timetuple():
"""Return a 9-element tuple of the form returned by time.localtime()."""
def utctimetuple():
"""Return UTC time tuple compatilble with time.gmtimr()."""
def toordinal():
"""Return the proleptic Gregorian ordinal of the date.
The same as self.date().toordinal().
"""
def weekday():
"""Return the day of the week as an integer.
Monday is 0 and Sunday is 6. The same as self.date().weekday().
See also isoweekday().
"""
def isoweekday():
"""Return the day of the week as an integer.
Monday is 1 and Sunday is 7. The same as self.date().isoweekday.
See also weekday(), isocalendar().
"""
def isocalendar():
"""Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
The same as self.date().isocalendar().
"""
def isoformat(sep='T'):
"""Return a string representing the date and time in ISO 8601 format.
YYYY-MM-DDTHH:MM:SS.mmmmmm or YYYY-MM-DDTHH:MM:SS if microsecond is 0
If utcoffset() does not return None, a 6-character string is appended,
giving the UTC offset in (signed) hours and minutes:
YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or YYYY-MM-DDTHH:MM:SS+HH:MM
if microsecond is 0.
The optional argument sep (default 'T') is a one-character separator,
placed between the date and time portions of the result.
"""
def __str__():
"""For a datetime instance d, str(d) is equivalent to d.isoformat(' ').
"""
def ctime():
"""Return a string representing the date and time.
datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'.
d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple())) on
platforms where the native C ctime() function (which time.ctime()
invokes, but which datetime.ctime() does not invoke) conforms to the
C standard.
"""
def strftime(format):
"""Return a string representing the date and time.
This is controlled by an explicit format string.
"""
class ITimeClass(Interface):
"""This is the time class interface."""
min = Attribute("The earliest representable time")
max = Attribute("The latest representable time")
resolution = Attribute(
"The smallest possible difference between non-equal time objects")
class ITime(ITimeClass):
"""Represent time with time zone.
Operators:
__repr__, __str__
__cmp__, __hash__
"""
hour = Attribute("Hour in range(24)")
minute = Attribute("Minute in range(60)")
second = Attribute("Second in range(60)")
microsecond = Attribute("Microsecond in range(1000000)")
tzinfo = Attribute(
"""The object passed as the tzinfo argument to the time constructor
or None if none was passed.""")
def replace(hour, minute, second, microsecond, tzinfo):
"""Return a time with the same value.
Except for those members given new values by whichever keyword
arguments are specified. Note that tzinfo=None can be specified
to create a naive time from an aware time, without conversion of the
time members.
"""
def isoformat():
"""Return a string representing the time in ISO 8601 format.
That is HH:MM:SS.mmmmmm or, if self.microsecond is 0, HH:MM:SS
If utcoffset() does not return None, a 6-character string is appended,
giving the UTC offset in (signed) hours and minutes:
HH:MM:SS.mmmmmm+HH:MM or, if self.microsecond is 0, HH:MM:SS+HH:MM
"""
def __str__():
"""For a time t, str(t) is equivalent to t.isoformat()."""
def strftime(format):
"""Return a string representing the time.
This is controlled by an explicit format string.
"""
def utcoffset():
"""Return the timezone offset in minutes east of UTC (negative west of
UTC).
If tzinfo is None, returns None, else returns
self.tzinfo.utcoffset(None), and raises an exception if the latter
doesn't return None or a timedelta object representing a whole number
of minutes with magnitude less than one day.
"""
def dst():
"""Return 0 if DST is not in effect, or the DST offset (in minutes
eastward) if DST is in effect.
If tzinfo is None, returns None, else returns self.tzinfo.dst(None),
and raises an exception if the latter doesn't return None, or a
timedelta object representing a whole number of minutes with
magnitude less than one day.
"""
def tzname():
"""Return the timezone name.
If tzinfo is None, returns None, else returns self.tzinfo.tzname(None),
or raises an exception if the latter doesn't return None or a string
object.
"""
class ITZInfo(Interface):
"""Time zone info class.
"""
def utcoffset(dt):
"""Return offset of local time from UTC, in minutes east of UTC.
If local time is west of UTC, this should be negative.
Note that this is intended to be the total offset from UTC;
for example, if a tzinfo object represents both time zone and DST
adjustments, utcoffset() should return their sum. If the UTC offset
isn't known, return None. Else the value returned must be a timedelta
object specifying a whole number of minutes in the range -1439 to 1439
inclusive (1440 = 24*60; the magnitude of the offset must be less
than one day).
"""
def dst(dt):
"""Return the daylight saving time (DST) adjustment, in minutes east
of UTC, or None if DST information isn't known.
"""
def tzname(dt):
"""Return the time zone name corresponding to the datetime object as
a string.
"""
def fromutc(dt):
"""Return an equivalent datetime in self's local time."""
classImplements(timedelta, ITimeDelta)
classImplements(date, IDate)
classImplements(datetime, IDateTime)
classImplements(time, ITime)
classImplements(tzinfo, ITZInfo)
## directlyProvides(timedelta, ITimeDeltaClass)
## directlyProvides(date, IDateClass)
## directlyProvides(datetime, IDateTimeClass)
## directlyProvides(time, ITimeClass)
zope.interface-4.3.2/src/zope/interface/common/__init__.py 0000664 0001750 0001750 00000000075 12763206174 022605 0 ustar mg mg 0000000 0000000 #
# This file is necessary to make this directory a package.
zope.interface-4.3.2/src/zope/interface/common/tests/ 0000775 0001750 0001750 00000000000 12763206175 021635 5 ustar mg mg 0000000 0000000 zope.interface-4.3.2/src/zope/interface/common/tests/test_import_interfaces.py 0000664 0001750 0001750 00000001640 12763206174 026763 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2006 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 doctest
import unittest
def test_interface_import():
"""
>>> import zope.interface.common.interfaces
"""
def test_suite():
return unittest.TestSuite((
doctest.DocTestSuite(),
))
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
zope.interface-4.3.2/src/zope/interface/common/tests/test_idatetime.py 0000664 0001750 0001750 00000003357 12763206174 025222 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Test for datetime interfaces
"""
import unittest
from zope.interface.verify import verifyObject, verifyClass
from zope.interface.common.idatetime import ITimeDelta, ITimeDeltaClass
from zope.interface.common.idatetime import IDate, IDateClass
from zope.interface.common.idatetime import IDateTime, IDateTimeClass
from zope.interface.common.idatetime import ITime, ITimeClass, ITZInfo
from datetime import timedelta, date, datetime, time, tzinfo
class TestDateTimeInterfaces(unittest.TestCase):
def test_interfaces(self):
verifyObject(ITimeDelta, timedelta(minutes=20))
verifyObject(IDate, date(2000, 1, 2))
verifyObject(IDateTime, datetime(2000, 1, 2, 10, 20))
verifyObject(ITime, time(20, 30, 15, 1234))
verifyObject(ITZInfo, tzinfo())
verifyClass(ITimeDeltaClass, timedelta)
verifyClass(IDateClass, date)
verifyClass(IDateTimeClass, datetime)
verifyClass(ITimeClass, time)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestDateTimeInterfaces))
return suite
if __name__ == '__main__':
unittest.main()
zope.interface-4.3.2/src/zope/interface/common/tests/basemapping.py 0000664 0001750 0001750 00000007512 12763206174 024501 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# 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.
#
##############################################################################
"""Base Mapping tests
"""
from operator import __getitem__
def testIReadMapping(self, inst, state, absent):
for key in state:
self.assertEqual(inst[key], state[key])
self.assertEqual(inst.get(key, None), state[key])
self.assertTrue(key in inst)
for key in absent:
self.assertEqual(inst.get(key, None), None)
self.assertEqual(inst.get(key), None)
self.assertEqual(inst.get(key, self), self)
self.assertRaises(KeyError, __getitem__, inst, key)
def test_keys(self, inst, state):
# Return the keys of the mapping object
inst_keys = list(inst.keys()); inst_keys.sort()
state_keys = list(state.keys()) ; state_keys.sort()
self.assertEqual(inst_keys, state_keys)
def test_iter(self, inst, state):
# Return the keys of the mapping object
inst_keys = list(inst); inst_keys.sort()
state_keys = list(state.keys()) ; state_keys.sort()
self.assertEqual(inst_keys, state_keys)
def test_values(self, inst, state):
# Return the values of the mapping object
inst_values = list(inst.values()); inst_values.sort()
state_values = list(state.values()) ; state_values.sort()
self.assertEqual(inst_values, state_values)
def test_items(self, inst, state):
# Return the items of the mapping object
inst_items = list(inst.items()); inst_items.sort()
state_items = list(state.items()) ; state_items.sort()
self.assertEqual(inst_items, state_items)
def test___len__(self, inst, state):
# Return the number of items
self.assertEqual(len(inst), len(state))
def testIEnumerableMapping(self, inst, state):
test_keys(self, inst, state)
test_items(self, inst, state)
test_values(self, inst, state)
test___len__(self, inst, state)
class BaseTestIReadMapping(object):
def testIReadMapping(self):
inst = self._IReadMapping__sample()
state = self._IReadMapping__stateDict()
absent = self._IReadMapping__absentKeys()
testIReadMapping(self, inst, state, absent)
class BaseTestIEnumerableMapping(BaseTestIReadMapping):
# Mapping objects whose items can be enumerated
def test_keys(self):
# Return the keys of the mapping object
inst = self._IEnumerableMapping__sample()
state = self._IEnumerableMapping__stateDict()
test_keys(self, inst, state)
def test_values(self):
# Return the values of the mapping object
inst = self._IEnumerableMapping__sample()
state = self._IEnumerableMapping__stateDict()
test_values(self, inst, state)
def test_items(self):
# Return the items of the mapping object
inst = self._IEnumerableMapping__sample()
state = self._IEnumerableMapping__stateDict()
test_items(self, inst, state)
def test___len__(self):
# Return the number of items
inst = self._IEnumerableMapping__sample()
state = self._IEnumerableMapping__stateDict()
test___len__(self, inst, state)
def _IReadMapping__stateDict(self):
return self._IEnumerableMapping__stateDict()
def _IReadMapping__sample(self):
return self._IEnumerableMapping__sample()
def _IReadMapping__absentKeys(self):
return self._IEnumerableMapping__absentKeys()
zope.interface-4.3.2/src/zope/interface/common/tests/__init__.py 0000664 0001750 0001750 00000000075 12763206174 023747 0 ustar mg mg 0000000 0000000 #
# This file is necessary to make this directory a package.
zope.interface-4.3.2/docs/ 0000775 0001750 0001750 00000000000 12763206175 014427 5 ustar mg mg 0000000 0000000 zope.interface-4.3.2/docs/verify.rst 0000664 0001750 0001750 00000007024 12763206174 016467 0 ustar mg mg 0000000 0000000 ===================================
Verifying interface implementations
===================================
The ``zope.interface.verify`` module provides functions that test whether a
given interface is implemented by a class or provided by an object, resp.
Verifying classes
=================
This is covered by unit tests defined in ``zope.interface.tests.test_verify``.
Verifying objects
=================
An object provides an interface if
- either its class declares that it implements the interfaces, or the object
declares that it directly provides the interface
- the object defines all the methods required by the interface
- all the methods have the correct signature
- the object defines all non-method attributes required by the interface
This doctest currently covers only the latter item.
Testing for attributes
----------------------
Attributes of the object, be they defined by its class or added by its
``__init__`` method, will be recognized:
.. doctest::
>>> from zope.interface import Interface, Attribute, implements
>>> from zope.interface.exceptions import BrokenImplementation
>>> class IFoo(Interface):
... x = Attribute("The X attribute")
... y = Attribute("The Y attribute")
>>> class Foo(object):
... implements(IFoo)
... x = 1
... def __init__(self):
... self.y = 2
>>> from zope.interface.verify import verifyObject
>>> verifyObject(IFoo, Foo())
True
If either attribute is missing, verification will fail:
.. doctest::
>>> class Foo(object):
... implements(IFoo)
... x = 1
>>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
... verifyObject(IFoo, Foo())
... except BrokenImplementation, e:
... print str(e)
An object has failed to implement interface
The y attribute was not provided.
>>> class Foo(object):
... implements(IFoo)
... def __init__(self):
... self.y = 2
>>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
... verifyObject(IFoo, Foo())
... except BrokenImplementation, e:
... print str(e)
An object has failed to implement interface
The x attribute was not provided.
If an attribute is implemented as a property that raises an AttributeError
when trying to get its value, the attribute is considered missing:
.. doctest::
>>> class IFoo(Interface):
... x = Attribute('The X attribute')
>>> class Foo(object):
... implements(IFoo)
... @property
... def x(self):
... raise AttributeError
>>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
... verifyObject(IFoo, Foo())
... except BrokenImplementation, e:
... print str(e)
An object has failed to implement interface
The x attribute was not provided.
Any other exception raised by a property will propagate to the caller of
``verifyObject``:
.. doctest::
>>> class Foo(object):
... implements(IFoo)
... @property
... def x(self):
... raise Exception
>>> verifyObject(IFoo, Foo())
Traceback (most recent call last):
Exception
Of course, broken properties that are not required by the interface don't do
any harm:
.. doctest::
>>> class Foo(object):
... implements(IFoo)
... x = 1
... @property
... def y(self):
... raise Exception
>>> verifyObject(IFoo, Foo())
True
zope.interface-4.3.2/docs/make.bat 0000664 0001750 0001750 00000011766 12763206174 016046 0 ustar mg mg 0000000 0000000 @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 ^` where ^ 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
zope.interface-4.3.2/docs/index.rst 0000664 0001750 0001750 00000001157 12763206174 016273 0 ustar mg mg 0000000 0000000 .. zope.interface documentation master file, created by
sphinx-quickstart on Mon Mar 26 16:31:31 2012.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to zope.interface's documentation!
==========================================
Contents:
.. toctree::
:maxdepth: 2
README
adapter
human
verify
foodforthought
api
hacking
По-русски
=========
.. toctree::
:maxdepth: 2
README.ru
adapter.ru
human.ru
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
zope.interface-4.3.2/docs/human.ru.rst 0000664 0001750 0001750 00000024671 12763206174 016727 0 ustar mg mg 0000000 0000000 ===============================
Использование реестра адаптеров
===============================
Данный документ содержит небольшую демонстрацию пакета ``zope.interface`` и его
реестра адаптеров. Документ рассчитывался как конкретный, но более узкий пример
того как использовать интерфейсы и адаптеры вне Zope 3.
Сначала нам необходимо импортировать пакет для работы с интерфейсами::
>>> import zope.interface
Теперь мы разработаем интерфейс для нашего объекта - простого файла. Наш файл
будет содержать всего один атрибут - body, в котором фактически будет сохранено
содержимое файла::
>>> class IFile(zope.interface.Interface):
...
... body = zope.interface.Attribute(u'Содержимое файла.')
...
Для статистики нам часто необходимо знать размер файла. Но было бы несколько
топорно реализовывать определение размера прямо для объекта файла, т.к. размер
больше относится к мета-данным. Таким образом мы создаем еще один интерфейс для
представления размера какого-либо объекта::
>>> class ISize(zope.interface.Interface):
...
... def getSize():
... 'Return the size of an object.'
...
Теперь мы должны создать класс реализующий наш файл. Необходимо что бы наш
объект хранил информацию о том, что он реализует интерфейс `IFile`. Мы также
создаем атрибут с содержимым файла по умолчанию (для упрощения нашего
примера)::
>>> class File(object):
...
... zope.interface.implements(IFile)
... body = 'foo bar'
...
Дальше мы создаем адаптер, который будет предоставлять интерфейс `ISize`
получая любой объект предоставляющий интерфейс `IFile`. По соглашению мы
используем атрибут `__used_for__` для указания интерфейса который как мы
ожидаем предоставляет адаптируемый объект, `IFile` в нашем случае. На самом
деле этот атрибут используется только для документирования. В случае если
адаптер используется для нескольких интерфейсов можно указать их все в виде
кортежа.
Опять же по соглашению конструктор адаптера получает один аргумент - context
(контекст). В нашем случае контекст - это экземпляр `IFile` (объект,
предоставляющий `IFile`) который используется для получения из него размера.
Так же по соглашению контекст сохраняется а адаптере в атрибуте с именем
`context`. Twisted комьюнити ссылается на контекст как на объект `original`.
Таким образом можно также дать аргументу любое подходящее имя, например
`file`::
>>> class FileSize(object):
...
... zope.interface.implements(ISize)
... __used_for__ = IFile
...
... def __init__(self, context):
... self.context = context
...
... def getSize(self):
... return len(self.context.body)
...
Теперь когда мы написали наш адаптер мы должны зарегистрировать его в реестре
адаптеров, что бы его можно было запросить когда он понадобится. Здесь нет
какого-либо глобального реестра адаптеров, таким образом мы должны
самостоятельно создать для нашего примера реестр::
>>> from zope.interface.adapter import AdapterRegistry
>>> registry = AdapterRegistry()
Реестр содержит отображение того, что адаптер реализует на основе другого
интерфейса который предоставляет объект. Поэтому дальше мы регистрируем адаптер
который адаптирует интерфейс `IFile` к интерфейсу `ISize`. Первый аргумент к
методу `register()` реестра - это список адаптируемых интерфейсов. В нашем
случае мы имеем только один адаптируемый интерфейс - `IFile`. Список
интерфейсов имеет смысл для использования концепции мульти-адаптеров, которые
требуют нескольких оригинальных объектов для адаптации к новому интерфейсу. В
этой ситуации конструктор адаптера будет требовать новый аргумент для каждого
оригинального интерфейса.
Второй аргумент метода `register()` - это интерфейс который предоставляет
адаптер, в нашем случае `ISize`. Третий аргумент - имя адаптера. Сейчас нам не
важно имя адаптера и мы передаем его как пустую строку. Обычно имена полезны
если используются адаптеры для одинакового набора интерфейсов, но в различных
ситуациях. Последний аргумент - это класс адаптера::
>>> registry.register([IFile], ISize, '', FileSize)
Теперь мы можем использовать реестр для запроса адаптера::
>>> registry.lookup1(IFile, ISize, '')
Попробуем более практичный пример. Создадим экземпляр `File` и создадим адаптер
использующий запрос реестра. Затем мы увидим возвращает ли адаптер корректный
размер при вызове `getSize()`::
>>> file = File()
>>> size = registry.lookup1(IFile, ISize, '')(file)
>>> size.getSize()
7
На самом деле это не очень практично, т.к. нам нужно самим передавать все
аргументы методу запроса. Существует некоторый синтаксический леденец который
позволяет нам получить экземпляр адаптера просто вызвав `ISize(file)`. Что бы
использовать эту функциональность нам понадобится добавить наш реестр к списку
adapter_hooks, который находится в модуле с адаптерами. Этот список хранит
коллекцию вызываемых объектов которые вызываются автоматически когда вызывается
IFoo(obj); их предназначение - найти адаптеры которые реализуют интерфейс для
определенного экземпляра контекста.
Необходимо реализовать свою собственную функцию для поиска адаптера; данный
пример описывает одну из простейших функций для использования с реестром, но
также можно реализовать поисковые функции которые, например, используют
кэширование, или адаптеры сохраняемые в базе. Функция поиска должна принимать
желаемый на выходе интерфейс (в нашем случае `ISize`) как первый аргумент и
контекст для адаптации (`file`) как второй. Функция должна вернуть адаптер,
т.е. экземпляр `FileSize`::
>>> def hook(provided, object):
... adapter = registry.lookup1(zope.interface.providedBy(object),
... provided, '')
... return adapter(object)
...
Теперь мы просто добавляем нашу функцию к списку `adapter_hooks`::
>>> from zope.interface.interface import adapter_hooks
>>> adapter_hooks.append(hook)
Как только функция зарегистрирована мы можем использовать желаемый синтаксис::
>>> size = ISize(file)
>>> size.getSize()
7
После нам нужно прибраться за собой, что бы другие получили чистый список
`adaper_hooks` после нас::
>>> adapter_hooks.remove(hook)
Это все. Здесь намеренно отложена дискуссия об именованных и мульти-адаптерах,
т.к. данный текст рассчитан как практическое и простое введение в интерфейсы и
адаптеры Zope 3. Для более подробной информации имеет смысл прочитать
`adapter.txt` из пакета `zope.interface`, что бы получить более формальное,
справочное и полное трактование пакета. Внимание: многие жаловались, что
`adapter.txt` приводит их мозг к расплавленному состоянию!
zope.interface-4.3.2/docs/human.rst 0000664 0001750 0001750 00000014432 12763206174 016274 0 ustar mg mg 0000000 0000000 ==========================
Using the Adapter Registry
==========================
This is a small demonstration of the ``zope.interface`` package including its
adapter registry. It is intended to provide a concrete but narrow example on
how to use interfaces and adapters outside of Zope 3.
First we have to import the interface package:
.. doctest::
>>> import zope.interface
We now develop an interface for our object, which is a simple file in this
case. For now we simply support one attribute, the body, which contains the
actual file contents:
.. doctest::
>>> class IFile(zope.interface.Interface):
...
... body = zope.interface.Attribute('Contents of the file.')
...
For statistical reasons we often want to know the size of a file. However, it
would be clumsy to implement the size directly in the file object, since the
size really represents meta-data. Thus we create another interface that
provides the size of something:
.. doctest::
>>> class ISize(zope.interface.Interface):
...
... def getSize():
... 'Return the size of an object.'
...
Now we need to implement the file. It is essential that the object states
that it implements the `IFile` interface. We also provide a default body
value (just to make things simpler for this example):
.. doctest::
>>> class File(object):
...
... zope.interface.implements(IFile)
... body = 'foo bar'
...
Next we implement an adapter that can provide the `ISize` interface given any
object providing `IFile`. By convention we use `__used_for__` to specify the
interface that we expect the adapted object to provide, in our case
`IFile`. However, this attribute is not used for anything. If you have
multiple interfaces for which an adapter is used, just specify the interfaces
via a tuple.
Again by convention, the constructor of an adapter takes one argument, the
context. The context in this case is an instance of `File` (providing `IFile`)
that is used to extract the size from. Also by convention the context is
stored in an attribute named `context` on the adapter. The twisted community
refers to the context as the `original` object. However, you may feel free to
use a specific argument name, such as `file`:
.. doctest::
>>> class FileSize(object):
...
... zope.interface.implements(ISize)
... __used_for__ = IFile
...
... def __init__(self, context):
... self.context = context
...
... def getSize(self):
... return len(self.context.body)
...
Now that we have written our adapter, we have to register it with an adapter
registry, so that it can be looked up when needed. There is no such thing as a
global registry; thus we have to instantiate one for our example manually:
.. doctest::
>>> from zope.interface.adapter import AdapterRegistry
>>> registry = AdapterRegistry()
The registry keeps a map of what adapters implement based on another
interface, the object already provides. Therefore, we next have to register an
adapter that adapts from `IFile` to `ISize`. The first argument to
the registry's `register()` method is a list of original interfaces.In our
cause we have only one original interface, `IFile`. A list makes sense, since
the interface package has the concept of multi-adapters, which are adapters
that require multiple objects to adapt to a new interface. In these
situations, your adapter constructor will require an argument for each
specified interface.
The second argument is the interface the adapter provides, in our case
`ISize`. The third argument is the name of the adapter. Since we do not care
about names, we simply leave it as an empty string. Names are commonly useful,
if you have adapters for the same set of interfaces, but they are useful in
different situations. The last argument is simply the adapter class:
.. doctest::
>>> registry.register([IFile], ISize, '', FileSize)
You can now use the the registry to lookup the adapter:
.. doctest::
>>> registry.lookup1(IFile, ISize, '')
Let's get a little bit more practical. Let's create a `File` instance and
create the adapter using a registry lookup. Then we see whether the adapter
returns the correct size by calling `getSize()`:
.. doctest::
>>> file = File()
>>> size = registry.lookup1(IFile, ISize, '')(file)
>>> size.getSize()
7
However, this is not very practical, since I have to manually pass in the
arguments to the lookup method. There is some syntactic candy that will allow
us to get an adapter instance by simply calling `ISize(file)`. To make use of
this functionality, we need to add our registry to the adapter_hooks list,
which is a member of the adapters module. This list stores a collection of
callables that are automatically invoked when IFoo(obj) is called; their
purpose is to locate adapters that implement an interface for a certain
context instance.
You are required to implement your own adapter hook; this example covers one
of the simplest hooks that use the registry, but you could implement one that
used an adapter cache or persistent adapters, for instance. The helper hook is
required to expect as first argument the desired output interface (for us
`ISize`) and as the second argument the context of the adapter (here
`file`). The function returns an adapter, i.e. a `FileSize` instance:
.. doctest::
>>> def hook(provided, object):
... adapter = registry.lookup1(zope.interface.providedBy(object),
... provided, '')
... return adapter(object)
...
We now just add the hook to an `adapter_hooks` list:
.. doctest::
>>> from zope.interface.interface import adapter_hooks
>>> adapter_hooks.append(hook)
Once the hook is registered, you can use the desired syntax:
.. doctest::
>>> size = ISize(file)
>>> size.getSize()
7
Now we have to cleanup after ourselves, so that others after us have a clean
`adapter_hooks` list:
.. doctest::
>>> adapter_hooks.remove(hook)
That's it. I have intentionally left out a discussion of named adapters and
multi-adapters, since this text is intended as a practical and simple
introduction to Zope 3 interfaces and adapters. You might want to read the
`adapter.txt` in the `zope.interface` package for a more formal, referencial
and complete treatment of the package. Warning: People have reported that
`adapter.txt` makes their brain feel soft!
zope.interface-4.3.2/docs/hacking.rst 0000664 0001750 0001750 00000022442 12763206174 016570 0 ustar mg mg 0000000 0000000 Hacking on :mod:`zope.interface`
================================
Getting the Code
################
The main repository for :mod:`zope.interface` is in the Zope Foundation
Github repository:
https://github.com/zopefoundation/zope.interface
You can get a read-only checkout from there:
.. code-block:: sh
$ git clone https://github.com/zopefoundation/zope.interface.git
or fork it and get a writeable checkout of your fork:
.. code-block:: sh
$ git clone git@github.com/jrandom/zope.interface.git
The project also mirrors the trunk from the Github repository as a
Bazaar branch on Launchpad:
https://code.launchpad.net/zope.interface
You can branch the trunk from there using Bazaar:
.. code-block:: sh
$ bzr branch lp:zope.interface
Working in a ``virtualenv``
###########################
Running the tests
-----------------
If you use the ``virtualenv`` package to create lightweight Python
development environments, you can run the tests using nothing more
than the ``python`` binary in a virtualenv. First, create a scratch
environment:
.. code-block:: sh
$ /path/to/virtualenv --no-site-packages /tmp/hack-zope.interface
Next, get this package registered as a "development egg" in the
environment:
.. code-block:: sh
$ /tmp/hack-zope.interface/bin/python setup.py develop
Finally, run the tests using the build-in ``setuptools`` testrunner:
.. code-block:: sh
$ /tmp/hack-zope.interface/bin/python setup.py test -q
running test
...
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
The ``dev`` command alias downloads and installs extra tools, like the
:mod:`nose` testrunner and the :mod:`coverage` coverage analyzer:
.. code-block:: sh
$ /tmp/hack-zope.interface/bin/python setup.py dev
$ /tmp/hack-zope.interface/bin/nosetests
running nosetests
.................................... (lots more dots)
----------------------------------------------------------------------
Ran 707 tests in 2.166s
OK
If you have the :mod:`coverage` pacakge installed in the virtualenv,
you can see how well the tests cover the code:
.. code-block:: sh
$ /tmp/hack-zope.interface/bin/nosetests --with coverage
running nosetests
.................................... (lots more dots)
Name Stmts Miss Cover Missing
----------------------------------------------------------------
zope.interface 30 0 100%
zope.interface.adapter 440 0 100%
zope.interface.advice 69 0 100%
zope.interface.common 0 0 100%
zope.interface.common.idatetime 98 0 100%
zope.interface.common.interfaces 81 0 100%
zope.interface.common.mapping 32 0 100%
zope.interface.common.sequence 38 0 100%
zope.interface.declarations 312 0 100%
zope.interface.document 54 0 100%
zope.interface.exceptions 21 0 100%
zope.interface.interface 378 0 100%
zope.interface.interfaces 137 0 100%
zope.interface.registry 300 0 100%
zope.interface.ro 25 0 100%
zope.interface.verify 48 0 100%
----------------------------------------------------------------
TOTAL 2063 0 100%
----------------------------------------------------------------------
Ran 707 tests in 2.166s
OK
Building the documentation
--------------------------
:mod:`zope.interface` uses the nifty :mod:`Sphinx` documentation system
for building its docs. Using the same virtualenv you set up to run the
tests, you can build the docs:
The ``docs`` command alias downloads and installs Sphinx and its dependencies:
.. code-block:: sh
$ /tmp/hack-zope.interface/bin/python setup.py docs
...
$ bin/sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html
...
build succeeded.
Build finished. The HTML pages are in docs/_build/html.
You can also test the code snippets in the documentation:
.. code-block:: sh
$ bin/sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest
...
running tests...
Document: index
---------------
1 items passed all tests:
17 tests in default
17 tests in 1 items.
17 passed and 0 failed.
Test passed.
Doctest summary
===============
17 tests
0 failures in tests
0 failures in setup code
build succeeded.
Testing of doctests in the sources finished, look at the \
results in docs/_build/doctest/output.txt.
Using :mod:`zc.buildout`
########################
Setting up the buildout
-----------------------
:mod:`zope.interface` ships with its own :file:`buildout.cfg` file and
:file:`bootstrap.py` for setting up a development buildout:
.. code-block:: sh
$ /path/to/python2.7 bootstrap.py
...
Generated script '.../bin/buildout'
$ bin/buildout
Develop: '/home/jrandom/projects/Zope/BTK/interface/.'
...
Generated script '.../bin/sphinx-quickstart'.
Generated script '.../bin/sphinx-build'.
Running the tests
-----------------
You can now run the tests:
.. code-block:: sh
$ bin/test --all
Running zope.testing.testrunner.layer.UnitTests tests:
Set up zope.testing.testrunner.layer.UnitTests in 0.000 seconds.
Ran 702 tests with 0 failures and 0 errors in 0.000 seconds.
Tearing down left over layers:
Tear down zope.testing.testrunner.layer.UnitTests in 0.000 seconds.
Using :mod:`tox`
################
Running Tests on Multiple Python Versions
-----------------------------------------
`tox `_ is a Python-based test automation
tool designed to run tests against multiple Python versions. It creates
a ``virtualenv`` for each configured version, installs the current package
and configured dependencies into each ``virtualenv``, and then runs the
configured commands.
:mod:`zope.interface` configures the following :mod:`tox` environments via
its ``tox.ini`` file:
- The ``py26``, ``py27``, ``py33``, ``py34``, and ``pypy`` environments
builds a ``virtualenv`` with ``pypy``,
installs :mod:`zope.interface` and dependencies, and runs the tests
via ``python setup.py test -q``.
- The ``coverage`` environment builds a ``virtualenv`` with ``python2.7``,
installs :mod:`zope.interface` and dependencies, installs
:mod:`nose` and :mod:`coverage`, and runs ``nosetests`` with statement
coverage.
- The ``docs`` environment builds a virtualenv with ``python2.7``, installs
:mod:`zope.interface` and dependencies, installs ``Sphinx`` and
dependencies, and then builds the docs and exercises the doctest snippets.
This example requires that you have a working ``python2.7`` on your path,
as well as installing ``tox``:
.. code-block:: sh
$ tox -e py26
GLOB sdist-make: .../zope.interface/setup.py
py26 sdist-reinst: .../zope.interface/.tox/dist/zope.interface-4.0.2dev.zip
py26 runtests: commands[0]
...
----------------------------------------------------------------------
Ran 1341 tests in 0.477s
OK
___________________________________ summary ____________________________________
py26: commands succeeded
congratulations :)
Running ``tox`` with no arguments runs all the configured environments,
including building the docs and testing their snippets:
.. code-block:: sh
$ tox
GLOB sdist-make: .../zope.interface/setup.py
py26 sdist-reinst: .../zope.interface/.tox/dist/zope.interface-4.0.2dev.zip
py26 runtests: commands[0]
...
Doctest summary
===============
678 tests
0 failures in tests
0 failures in setup code
0 failures in cleanup code
build succeeded.
___________________________________ summary ____________________________________
py26: commands succeeded
py27: commands succeeded
py32: commands succeeded
pypy: commands succeeded
coverage: commands succeeded
docs: commands succeeded
congratulations :)
Contributing to :mod:`zope.interface`
#####################################
Submitting a Bug Report
-----------------------
:mod:`zope.interface` tracks its bugs on Github:
https://github.com/zopefoundation/zope.interface/issues
Please submit bug reports and feature requests there.
Sharing Your Changes
--------------------
.. note::
Please ensure that all tests are passing before you submit your code.
If possible, your submission should include new tests for new features
or bug fixes, although it is possible that you may have tested your
new code by updating existing tests.
If have made a change you would like to share, the best route is to fork
the Githb repository, check out your fork, make your changes on a branch
in your fork, and push it. You can then submit a pull request from your
branch:
https://github.com/zopefoundation/zope.interface/pulls
If you branched the code from Launchpad using Bazaar, you have another
option: you can "push" your branch to Launchpad:
.. code-block:: sh
$ bzr push lp:~jrandom/zope.interface/cool_feature
After pushing your branch, you can link it to a bug report on Launchpad,
or request that the maintainers merge your branch using the Launchpad
"merge request" feature.
zope.interface-4.3.2/docs/foodforthought.rst 0000664 0001750 0001750 00000003316 12763206174 020224 0 ustar mg mg 0000000 0000000 ================================
Food-based subscription examples
================================
This file gives more subscription examples using a cooking-based example:
.. doctest::
>>> from zope.interface.adapter import AdapterRegistry
>>> registry = AdapterRegistry()
>>> import zope.interface
>>> class IAnimal(zope.interface.Interface):
... pass
>>> class IPoultry(IAnimal):
... pass
>>> class IChicken(IPoultry):
... pass
>>> class ISeafood(IAnimal):
... pass
Adapting to some other interface for which there is no
subscription adapter returns an empty sequence:
.. doctest::
>>> class IRecipe(zope.interface.Interface):
... pass
>>> class ISausages(IRecipe):
... pass
>>> class INoodles(IRecipe):
... pass
>>> class IKFC(IRecipe):
... pass
>>> list(registry.subscriptions([IPoultry], IRecipe))
[]
unless we define a subscription:
.. doctest::
>>> registry.subscribe([IAnimal], ISausages, 'sausages')
>>> list(registry.subscriptions([IPoultry], ISausages))
['sausages']
And define another subscription adapter:
.. doctest::
>>> registry.subscribe([IPoultry], INoodles, 'noodles')
>>> meals = list(registry.subscriptions([IPoultry], IRecipe))
>>> meals.sort()
>>> meals
['noodles', 'sausages']
>>> registry.subscribe([IChicken], IKFC, 'kfc')
>>> meals = list(registry.subscriptions([IChicken], IRecipe))
>>> meals.sort()
>>> meals
['kfc', 'noodles', 'sausages']
And the answer for poultry hasn't changed:
.. doctest::
>>> meals = list(registry.subscriptions([IPoultry], IRecipe))
>>> meals.sort()
>>> meals
['noodles', 'sausages']
zope.interface-4.3.2/docs/conf.py 0000664 0001750 0001750 00000017761 12763206174 015741 0 ustar mg mg 0000000 0000000 # -*- 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.autodoc',
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.ifconfig',
'sphinx.ext.viewcode',
'repoze.sphinx.autointerface',
]
# 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 = 'zope.interface'
copyright = '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 = '4.0'
# The full version, including alpha/beta/rc tags.
release = '4.0.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
# " v 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 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', 'zope.interface Documentation',
'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', 'zope.interface Documentation',
['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', 'zope.interface Documentation',
'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}
zope.interface-4.3.2/docs/api.rst 0000664 0001750 0001750 00000053070 12763206174 015736 0 ustar mg mg 0000000 0000000 :mod:`zope.interface` API Documentation
=======================================
:class:`zope.interface.interface.Specification`
-----------------------------------------------
API
+++
Specification objects implement the API defined by
:class:`zope.interface.interfaces.ISpecification`:
.. autointerface:: zope.interface.interfaces.ISpecification
:members:
:member-order: bysource
Usage
+++++
For example:
.. doctest::
>>> from zope.interface.interface import Specification
>>> from zope.interface import Interface
>>> class I1(Interface):
... pass
>>> class I2(I1):
... pass
>>> class I3(I2):
... pass
>>> [i.__name__ for i in I1.__bases__]
['Interface']
>>> [i.__name__ for i in I2.__bases__]
['I1']
>>> I3.extends(I1)
True
>>> I2.__bases__ = (Interface, )
>>> [i.__name__ for i in I2.__bases__]
['Interface']
>>> I3.extends(I1)
False
Exmples for :meth:`Specification.providedBy`:
.. doctest::
>>> from zope.interface import *
>>> class I1(Interface):
... pass
>>> class C(object):
... implements(I1)
>>> c = C()
>>> class X(object):
... pass
>>> x = X()
>>> I1.providedBy(x)
False
>>> I1.providedBy(C)
False
>>> I1.providedBy(c)
True
>>> directlyProvides(x, I1)
>>> I1.providedBy(x)
True
>>> directlyProvides(C, I1)
>>> I1.providedBy(C)
True
Examples for :meth:`Specification.isOrExtends`:
.. doctest::
>>> from zope.interface import Interface
>>> from zope.interface.declarations import Declaration
>>> class I1(Interface): pass
...
>>> class I2(I1): pass
...
>>> class I3(Interface): pass
...
>>> class I4(I3): pass
...
>>> spec = Declaration()
>>> int(spec.extends(Interface))
1
>>> spec = Declaration(I2)
>>> int(spec.extends(Interface))
1
>>> int(spec.extends(I1))
1
>>> int(spec.extends(I2))
1
>>> int(spec.extends(I3))
0
>>> int(spec.extends(I4))
0
Examples for :meth:`Specification.interfaces`:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(I1): pass
...
>>> class I3(Interface): pass
...
>>> class I4(I3): pass
...
>>> spec = Specification((I2, I3))
>>> spec = Specification((I4, spec))
>>> i = spec.interfaces()
>>> [x.getName() for x in i]
['I4', 'I2', 'I3']
>>> list(i)
[]
Exmples for :meth:`Specification.extends`:
.. doctest::
>>> from zope.interface import Interface
>>> from zope.interface.declarations import Declaration
>>> class I1(Interface): pass
...
>>> class I2(I1): pass
...
>>> class I3(Interface): pass
...
>>> class I4(I3): pass
...
>>> spec = Declaration()
>>> int(spec.extends(Interface))
1
>>> spec = Declaration(I2)
>>> int(spec.extends(Interface))
1
>>> int(spec.extends(I1))
1
>>> int(spec.extends(I2))
1
>>> int(spec.extends(I3))
0
>>> int(spec.extends(I4))
0
>>> I2.extends(I2)
False
>>> I2.extends(I2, False)
True
>>> I2.extends(I2, strict=False)
True
:class:`zope.interface.interface.InterfaceClass`
------------------------------------------------
API
+++
Specification objects implement the API defined by
:class:`zope.interface.interfaces.IInterface`:
.. autointerface:: zope.interface.interfaces.IInterface
:members:
:member-order: bysource
Usage
+++++
Exmples for :meth:`InterfaceClass.extends`:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>>
>>> i = I1.interfaces()
>>> [x.getName() for x in i]
['I1']
>>> list(i)
[]
:class:`zope.interface.declarations.Declaration`
------------------------------------------------
API
+++
Specification objects implement the API defined by
:class:`zope.interface.interfaces.IDeclaration`:
.. autointerface:: zope.interface.interfaces.IDeclaration
:members:
:member-order: bysource
Usage
+++++
Exmples for :meth:`Declaration.__contains__`:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(I1): pass
...
>>> class I3(Interface): pass
...
>>> class I4(I3): pass
...
>>> spec = Declaration(I2, I3)
>>> spec = Declaration(I4, spec)
>>> int(I1 in spec)
0
>>> int(I2 in spec)
1
>>> int(I3 in spec)
1
>>> int(I4 in spec)
1
Exmples for :meth:`Declaration.__iter__`:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(I1): pass
...
>>> class I3(Interface): pass
...
>>> class I4(I3): pass
...
>>> spec = Declaration(I2, I3)
>>> spec = Declaration(I4, spec)
>>> i = iter(spec)
>>> [x.getName() for x in i]
['I4', 'I2', 'I3']
>>> list(i)
[]
Exmples for :meth:`Declaration.flattened`:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(I1): pass
...
>>> class I3(Interface): pass
...
>>> class I4(I3): pass
...
>>> spec = Declaration(I2, I3)
>>> spec = Declaration(I4, spec)
>>> i = spec.flattened()
>>> [x.getName() for x in i]
['I4', 'I2', 'I1', 'I3', 'Interface']
>>> list(i)
[]
Exmples for :meth:`Declaration.__sub__`:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(I1): pass
...
>>> class I3(Interface): pass
...
>>> class I4(I3): pass
...
>>> spec = Declaration()
>>> [iface.getName() for iface in spec]
[]
>>> spec -= I1
>>> [iface.getName() for iface in spec]
[]
>>> spec -= Declaration(I1, I2)
>>> [iface.getName() for iface in spec]
[]
>>> spec = Declaration(I2, I4)
>>> [iface.getName() for iface in spec]
['I2', 'I4']
>>> [iface.getName() for iface in spec - I4]
['I2']
>>> [iface.getName() for iface in spec - I1]
['I4']
>>> [iface.getName() for iface
... in spec - Declaration(I3, I4)]
['I2']
Exmples for :meth:`Declaration.__add__`:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(I1): pass
...
>>> class I3(Interface): pass
...
>>> class I4(I3): pass
...
>>> spec = Declaration()
>>> [iface.getName() for iface in spec]
[]
>>> [iface.getName() for iface in spec+I1]
['I1']
>>> [iface.getName() for iface in I1+spec]
['I1']
>>> spec2 = spec
>>> spec += I1
>>> [iface.getName() for iface in spec]
['I1']
>>> [iface.getName() for iface in spec2]
[]
>>> spec2 += Declaration(I3, I4)
>>> [iface.getName() for iface in spec2]
['I3', 'I4']
>>> [iface.getName() for iface in spec+spec2]
['I1', 'I3', 'I4']
>>> [iface.getName() for iface in spec2+spec]
['I3', 'I4', 'I1']
:func:`zope.interface.declarations.implementedBy`
-------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.implementedByFallback
Usage
+++++
Consider the following example:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(Interface): pass
...
>>> class I3(Interface): pass
...
>>> class I4(Interface): pass
...
>>> class A(object):
... implements(I3)
>>> class B(object):
... implements(I4)
>>> class C(A, B):
... pass
>>> classImplementsOnly(C, I1, I2)
>>> [i.getName() for i in implementedBy(C)]
['I1', 'I2']
Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
whatever interfaces instances of ``A`` and ``B`` implement.
Another example:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(I1): pass
...
>>> class I3(Interface): pass
...
>>> class I4(I3): pass
...
>>> class C1(object):
... implements(I2)
>>> class C2(C1):
... implements(I3)
>>> [i.getName() for i in implementedBy(C2)]
['I3', 'I2']
Really, any object should be able to receive a successful answer, even
an instance:
.. doctest::
>>> class Callable(object):
... def __call__(self):
... return self
>>> implementedBy(Callable())
Note that the name of the spec ends with a '?', because the `Callable`
instance does not have a `__name__` attribute.
This also manages storage of implementation specifications
:func:`zope.interface.declarations.classImplementsOnly`
-------------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.classImplementsOnly
Usage
+++++
Consider the following example:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(Interface): pass
...
>>> class I3(Interface): pass
...
>>> class I4(Interface): pass
...
>>> class A(object):
... implements(I3)
>>> class B(object):
... implements(I4)
>>> class C(A, B):
... pass
>>> classImplementsOnly(C, I1, I2)
>>> [i.getName() for i in implementedBy(C)]
['I1', 'I2']
Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
whatever interfaces instances of ``A`` and ``B`` implement.
:func:`zope.interface.declarations.classImplements`
---------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.classImplements
Usage
+++++
Consider the following example:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(Interface): pass
...
>>> class I3(Interface): pass
...
>>> class I4(Interface): pass
...
>>> class I5(Interface): pass
...
>>> class A(object):
... implements(I3)
>>> class B(object):
... implements(I4)
>>> class C(A, B):
... pass
>>> classImplements(C, I1, I2)
>>> [i.getName() for i in implementedBy(C)]
['I1', 'I2', 'I3', 'I4']
>>> classImplements(C, I5)
>>> [i.getName() for i in implementedBy(C)]
['I1', 'I2', 'I5', 'I3', 'I4']
Instances of ``C`` provide ``I1``, ``I2``, ``I5``, and whatever
interfaces instances of ``A`` and ``B`` provide.
:class:`zope.interface.declarations.implementer`
------------------------------------------------
API
+++
.. autoclass:: zope.interface.declarations.implementer
:members:
:member-order: bysource
:class:`zope.interface.declarations.implementer_only`
-----------------------------------------------------
API
+++
.. autoclass:: zope.interface.declarations.implementer_only
:members:
:member-order: bysource
:func:`zope.interface.declarations.implements`
----------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.implements
:func:`zope.interface.declarations.implementsOnly`
--------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.implementsOnly
:class:`zope.interface.declarations.ProvidesClass`
--------------------------------------------------
API
+++
.. autoclass:: zope.interface.declarations.ProvidesClass
:members:
:member-order: bysource
Usage
+++++
Descriptor semantics (via ``Provides.__get__``):
.. doctest::
>>> from zope.interface import Interface
>>> class IFooFactory(Interface): pass
...
>>> class C(object):
... pass
>>> from zope.interface.declarations import ProvidesClass
>>> C.__provides__ = ProvidesClass(C, IFooFactory)
>>> [i.getName() for i in C.__provides__]
['IFooFactory']
>>> getattr(C(), '__provides__', 0)
0
:func:`zope.interface.declarations.Provides`
--------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.Provides
Usage
+++++
In the examples below, we are going to make assertions about
the size of the weakvalue dictionary. For the assertions to be
meaningful, we need to force garbage collection to make sure garbage
objects are, indeed, removed from the system. Depending on how Python
is run, we may need to make multiple calls to be sure. We provide a
collect function to help with this:
.. doctest::
>>> import gc
>>> def collect():
... for i in range(4):
... gc.collect()
>>> collect()
>>> from zope.interface.declarations import InstanceDeclarations
>>> before = len(InstanceDeclarations)
>>> class C(object):
... pass
>>> from zope.interface import Interface
>>> class I(Interface):
... pass
>>> c1 = C()
>>> c2 = C()
>>> len(InstanceDeclarations) == before
True
>>> directlyProvides(c1, I)
>>> len(InstanceDeclarations) == before + 1
True
>>> directlyProvides(c2, I)
>>> len(InstanceDeclarations) == before + 1
True
>>> del c1
>>> collect()
>>> len(InstanceDeclarations) == before + 1
True
>>> del c2
>>> collect()
>>> len(InstanceDeclarations) == before
True
:func:`zope.interface.declarations.directlyProvides`
----------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.directlyProvides
Usage
+++++
Consider the following example:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(Interface): pass
...
>>> class IA1(Interface): pass
...
>>> class IA2(Interface): pass
...
>>> class IB(Interface): pass
...
>>> class IC(Interface): pass
...
>>> class A(object):
... implements(IA1, IA2)
>>> class B(object):
... implements(IB)
>>> class C(A, B):
... implements(IC)
>>> ob = C()
>>> directlyProvides(ob, I1, I2)
>>> int(I1 in providedBy(ob))
1
>>> int(I2 in providedBy(ob))
1
>>> int(IA1 in providedBy(ob))
1
>>> int(IA2 in providedBy(ob))
1
>>> int(IB in providedBy(ob))
1
>>> int(IC in providedBy(ob))
1
The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
instances have been declared for instances of ``C``.
To remove directly provided interfaces, use ``directlyProvidedBy`` and
subtract the unwanted interfaces. For example:
.. doctest::
>>> directlyProvides(ob, directlyProvidedBy(ob)-I2)
>>> int(I1 in providedBy(ob))
1
>>> int(I2 in providedBy(ob))
0
removes I2 from the interfaces directly provided by ``ob``. The object,
``ob`` no longer directly provides ``I2``, although it might still
provide ``I2`` if it's class implements ``I2``.
To add directly provided interfaces, use ``directlyProvidedBy`` and
include additional interfaces. For example:
.. doctest::
>>> int(I2 in providedBy(ob))
0
>>> directlyProvides(ob, directlyProvidedBy(ob), I2)
adds ``I2`` to the interfaces directly provided by ob:
.. doctest::
>>> int(I2 in providedBy(ob))
1
We need to avoid setting this attribute on meta classes that
don't support descriptors.
We can do away with this check when we get rid of the old EC
:func:`zope.interface.declarations.alsoProvides`
------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.alsoProvides
Usage
+++++
Consider the following example:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(Interface): pass
...
>>> class IA1(Interface): pass
...
>>> class IA2(Interface): pass
...
>>> class IB(Interface): pass
...
>>> class IC(Interface): pass
...
>>> class A(object):
... implements(IA1, IA2)
>>> class B(object):
... implements(IB)
>>> class C(A, B):
... implements(IC)
>>> ob = C()
>>> directlyProvides(ob, I1)
>>> int(I1 in providedBy(ob))
1
>>> int(I2 in providedBy(ob))
0
>>> int(IA1 in providedBy(ob))
1
>>> int(IA2 in providedBy(ob))
1
>>> int(IB in providedBy(ob))
1
>>> int(IC in providedBy(ob))
1
>>> alsoProvides(ob, I2)
>>> int(I1 in providedBy(ob))
1
>>> int(I2 in providedBy(ob))
1
>>> int(IA1 in providedBy(ob))
1
>>> int(IA2 in providedBy(ob))
1
>>> int(IB in providedBy(ob))
1
>>> int(IC in providedBy(ob))
1
The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
instances have been declared for instances of ``C``. Notice that the
alsoProvides just extends the provided interfaces.
:func:`zope.interface.declarations.noLongerProvides`
----------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.noLongerProvides
Usage
+++++
Consider the following two interfaces:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(Interface): pass
...
``I1`` is provided through the class, ``I2`` is directly provided
by the object:
.. doctest::
>>> class C(object):
... implements(I1)
>>> c = C()
>>> alsoProvides(c, I2)
>>> I2.providedBy(c)
True
Remove I2 from c again:
.. doctest::
>>> noLongerProvides(c, I2)
>>> I2.providedBy(c)
False
Removing an interface that is provided through the class is not possible:
.. doctest::
>>> noLongerProvides(c, I1)
Traceback (most recent call last):
...
ValueError: Can only remove directly provided interfaces.
:func:`zope.interface.declarations.directlyProvidedBy`
------------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.directlyProvidedBy
:func:`zope.interface.declarations.classProvides`
-------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.classProvides
Usage
+++++
For example:
.. doctest::
>>> from zope.interface import Interface
>>> from zope.interface.declarations import implementer
>>> class IFooFactory(Interface):
... pass
>>> class IFoo(Interface):
... pass
>>> @implementer(IFoo)
... class C(object):
... classProvides(IFooFactory)
>>> [i.getName() for i in C.__provides__]
['IFooFactory']
>>> [i.getName() for i in C().__provides__]
['IFoo']
Which is equivalent to:
.. doctest::
>>> from zope.interface import Interface
>>> class IFoo(Interface): pass
...
>>> class IFooFactory(Interface): pass
...
>>> @implementer(IFoo)
... class C(object):
... pass
>>> directlyProvides(C, IFooFactory)
>>> [i.getName() for i in C.__providedBy__]
['IFooFactory']
>>> [i.getName() for i in C().__providedBy__]
['IFoo']
:class:`zope.interface.declarations.provider`
---------------------------------------------
API
+++
.. autoclass:: zope.interface.declarations.provider
:members:
:member-order: bysource
:func:`zope.interface.declarations.moduleProvides`
--------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.moduleProvides
:func:`zope.interface.declarations.ObjectSpecification`
-------------------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.ObjectSpecification
Usage
+++++
For example:
.. doctest::
>>> from zope.interface import Interface
>>> class I1(Interface): pass
...
>>> class I2(Interface): pass
...
>>> class I3(Interface): pass
...
>>> class I31(I3): pass
...
>>> class I4(Interface): pass
...
>>> class I5(Interface): pass
...
>>> class A(object):
... implements(I1)
>>> class B(object): __implemented__ = I2
...
>>> class C(A, B):
... implements(I31)
>>> c = C()
>>> directlyProvides(c, I4)
>>> [i.getName() for i in providedBy(c)]
['I4', 'I31', 'I1', 'I2']
>>> [i.getName() for i in providedBy(c).flattened()]
['I4', 'I31', 'I3', 'I1', 'I2', 'Interface']
>>> int(I1 in providedBy(c))
1
>>> int(I3 in providedBy(c))
0
>>> int(providedBy(c).extends(I3))
1
>>> int(providedBy(c).extends(I31))
1
>>> int(providedBy(c).extends(I5))
0
>>> class COnly(A, B):
... implementsOnly(I31)
>>> class D(COnly):
... implements(I5)
>>> c = D()
>>> directlyProvides(c, I4)
>>> [i.getName() for i in providedBy(c)]
['I4', 'I5', 'I31']
>>> [i.getName() for i in providedBy(c).flattened()]
['I4', 'I5', 'I31', 'I3', 'Interface']
>>> int(I1 in providedBy(c))
0
>>> int(I3 in providedBy(c))
0
>>> int(providedBy(c).extends(I3))
1
>>> int(providedBy(c).extends(I1))
0
>>> int(providedBy(c).extends(I31))
1
>>> int(providedBy(c).extends(I5))
1
:func:`zope.interface.declarations.providedBy`
----------------------------------------------
API
+++
.. autofunction:: zope.interface.declarations.providedBy
:class:`zope.interface.declarations.ObjectSpecificationDescriptor`
------------------------------------------------------------------
API
+++
.. autoclass:: zope.interface.declarations.ObjectSpecificationDescriptor
:members:
:member-order: bysource
Usage
+++++
For example:
.. doctest::
>>> from zope.interface import Interface
>>> class IFoo(Interface): pass
...
>>> class IFooFactory(Interface): pass
...
>>> @implementer(IFoo)
... class C(object):
... classProvides(IFooFactory)
>>> [i.getName() for i in C.__providedBy__]
['IFooFactory']
>>> [i.getName() for i in C().__providedBy__]
['IFoo']
Get an ObjectSpecification bound to either an instance or a class,
depending on how we were accessed.
:class:`zope.interface.declarations.named`
---------------------------------------------
API
+++
.. autoclass:: zope.interface.declarations.named
:members:
:member-order: bysource
Usage
+++++
For example:
.. doctest::
>>> from zope.interface.declarations import named
>>> @named('foo')
... class Foo(object):
... pass
>>> Foo.__component_name__
'foo'
When registering an adapter or utility component, the registry looks for the
`__component_name__` attribute and uses it, if no name was explicitly
provided.
zope.interface-4.3.2/docs/adapter.ru.rst 0000664 0001750 0001750 00000051261 12763206174 017232 0 ustar mg mg 0000000 0000000 ================
Реестр адаптеров
================
.. contents::
Реестры адаптеров предоставляют возможность для регистрации объектов которые
зависят от одной, или нескольких спецификаций интерфейсов и предоставляют
(возможно не напрямую) какой-либо интерфейс. В дополнение, регистрации имеют
имена. (Можно думать об именах как о спецификаторах предоставляемого
интерфейса.)
Термин "спецификация интерфейса" ссылается и на интерфейсы и на определения
интерфейсов, такие как определения интерфейсов реализованных некоторым классом.
Одиночные адаптеры
==================
Давайте рассмотрим простой пример использующий единственную требуемую
спецификацию::
>>> from zope.interface.adapter import AdapterRegistry
>>> import zope.interface
>>> class IR1(zope.interface.Interface):
... pass
>>> class IP1(zope.interface.Interface):
... pass
>>> class IP2(IP1):
... pass
>>> registry = AdapterRegistry()
Мы зарегистрируем объект который зависит от IR1 и "предоставляет" IP2::
>>> registry.register([IR1], IP2, '', 12)
После регистрации мы можем запросить объект снова::
>>> registry.lookup([IR1], IP2, '')
12
Заметьте, что мы используем целое в этом примере. В реальных приложениях вы
можете использовать объекты которые на самом деле зависят или предоставляют
интерфейсы. Реестр не заботиться о том, что регистрируется и таким образом мы
можем использовать целые, или строки что бы упростить наши примеры. Здесь есть
одно исключение. Регистрация значения None удаляет регистрацию для любого
зарегистрированного прежде значения.
Если объект зависит от спецификации он может быть запрошен с помощью
спецификации которая расширяет спецификацию от которой он зависит::
>>> class IR2(IR1):
... pass
>>> registry.lookup([IR2], IP2, '')
12
Мы можем использовать класс реализующий спецификацию для запроса объекта::
>>> class C2:
... zope.interface.implements(IR2)
>>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
12
и объект может быть запрошен для интерфейсов которые предоставляемый объектом
интерфейс расширяет::
>>> registry.lookup([IR1], IP1, '')
12
>>> registry.lookup([IR2], IP1, '')
12
Но если вы требуете спецификацию которая не расширяет спецификацию от которой
зависит объект, вы не получите ничего::
>>> registry.lookup([zope.interface.Interface], IP1, '')
Между прочим, вы можете передать значение по умолчанию при запросе::
>>> registry.lookup([zope.interface.Interface], IP1, '', 42)
42
Если вы пробуете получить интерфейс который объект не предоставляет вы также
не получите ничего::
>>> class IP3(IP2):
... pass
>>> registry.lookup([IR1], IP3, '')
Вы также не получите ничего если вы используете неверное имя::
>>> registry.lookup([IR1], IP1, 'bob')
>>> registry.register([IR1], IP2, 'bob', "Bob's 12")
>>> registry.lookup([IR1], IP1, 'bob')
"Bob's 12"
Вы можете не использовать имя при запросе::
>>> registry.lookup([IR1], IP1)
12
Если мы регистрируем объект который предоставляет IP1::
>>> registry.register([IR1], IP1, '', 11)
тогда этот объект будет иметь преимущество перед O(12)::
>>> registry.lookup([IR1], IP1, '')
11
Также, если мы регистрируем объект для IR2 тогда он будет иметь преимущество
когда используется IR2::
>>> registry.register([IR2], IP1, '', 21)
>>> registry.lookup([IR2], IP1, '')
21
Поиск того, что (если вообще что-то) зарегистрировано
-----------------------------------------------------
Мы можем спросить есть-ли адаптер зарегистрированный для набора интерфейсов.
Это отличается от обычного запроса так как здесь мы ищем точное совпадение::
>>> print registry.registered([IR1], IP1)
11
>>> print registry.registered([IR1], IP2)
12
>>> print registry.registered([IR1], IP2, 'bob')
Bob's 12
>>> print registry.registered([IR2], IP1)
21
>>> print registry.registered([IR2], IP2)
None
В последнем примере, None был возвращен потому, что для данного интерфейса
ничего не было зарегистрировано.
lookup1
-------
Запрос одиночного адаптера - это наиболее частая операция и для нее есть
специализированная версия запроса которая получает на вход единственный
требуемый интерфейс::
>>> registry.lookup1(IR2, IP1, '')
21
>>> registry.lookup1(IR2, IP1)
21
Адаптация на практике
---------------------
Реестр адаптеров предназначен для поддержки адаптации когда один объект
реализующий интерфейс адаптируется к другому объекту который поддерживает
другой интерфейс. Реестр адаптеров также поддерживает вычисление адаптеров. В
этом случае мы должны регистрировать фабрики для адаптеров::
>>> class IR(zope.interface.Interface):
... pass
>>> class X:
... zope.interface.implements(IR)
>>> class Y:
... zope.interface.implements(IP1)
... def __init__(self, context):
... self.context = context
>>> registry.register([IR], IP1, '', Y)
В этом случае мы регистрируем класс как фабрику. Теперь мы можем вызвать
`queryAdapter` для получения адаптированного объекта::
>>> x = X()
>>> y = registry.queryAdapter(x, IP1)
>>> y.__class__.__name__
'Y'
>>> y.context is x
True
Мы также можем регистрировать и запрашивать по имени::
>>> class Y2(Y):
... pass
>>> registry.register([IR], IP1, 'bob', Y2)
>>> y = registry.queryAdapter(x, IP1, 'bob')
>>> y.__class__.__name__
'Y2'
>>> y.context is x
True
Когда фабрика для адаптера возвращает `None` - это рассматривается как если бы
адаптер не был найден. Это позволяет нам избежать адаптации (по желанию) и дает
возможность фабрике адаптера определить возможна ли адаптация основываясь на
состоянии объекта который адаптируется::
>>> def factory(context):
... if context.name == 'object':
... return 'adapter'
... return None
>>> class Object(object):
... zope.interface.implements(IR)
... name = 'object'
>>> registry.register([IR], IP1, 'conditional', factory)
>>> obj = Object()
>>> registry.queryAdapter(obj, IP1, 'conditional')
'adapter'
>>> obj.name = 'no object'
>>> registry.queryAdapter(obj, IP1, 'conditional') is None
True
>>> registry.queryAdapter(obj, IP1, 'conditional', 'default')
'default'
Альтернативный метод для предоставления такой же функциональности как и
`queryAdapter()` - это `adapter_hook()`::
>>> y = registry.adapter_hook(IP1, x)
>>> y.__class__.__name__
'Y'
>>> y.context is x
True
>>> y = registry.adapter_hook(IP1, x, 'bob')
>>> y.__class__.__name__
'Y2'
>>> y.context is x
True
`adapter_hook()` просто меняет порядок аргументов для объекта и интерфейса. Это
используется для встраивания в механизм вызовов интерфейсов.
Адаптеры по умолчанию
---------------------
Иногда вы можете захотеть предоставить адаптер который не будет ничего
адаптировать. Для этого нужно передать None как требуемый интерфейс::
>>> registry.register([None], IP1, '', 1)
после этого вы можете использовать этот адаптер для интерфейсов для которых у
вас нет конкретного адаптера::
>>> class IQ(zope.interface.Interface):
... pass
>>> registry.lookup([IQ], IP1, '')
1
Конечно, конкретные адаптеры все еще используются когда необходимо::
>>> registry.lookup([IR2], IP1, '')
21
Адаптеры классов
----------------
Вы можете регистрировать адаптеры для определений классов, что будет похоже на
регистрацию их для классов::
>>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
>>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
'C21'
Адаптеры для словарей
---------------------
В какой-то момент было невозможно регистрировать адаптеры основанные на
словарях из-за ошибки. Давайте удостоверимся что это теперь работает::
>>> adapter = {}
>>> registry.register((), IQ, '', adapter)
>>> registry.lookup((), IQ, '') is adapter
True
Удаление регистрации
--------------------
Вы можете удалить регистрацию регистрируя None вместо объекта::
>>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
>>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
21
Конечно это значит, что None не может быть зарегистрирован. Это исключение к
утверждению выше о том, что реестр не заботиться о том, что регистрируется.
Мульти-адаптеры
===============
Вы можете адаптировать несколько спецификаций::
>>> registry.register([IR1, IQ], IP2, '', '1q2')
>>> registry.lookup([IR1, IQ], IP2, '')
'1q2'
>>> registry.lookup([IR2, IQ], IP1, '')
'1q2'
>>> class IS(zope.interface.Interface):
... pass
>>> registry.lookup([IR2, IS], IP1, '')
>>> class IQ2(IQ):
... pass
>>> registry.lookup([IR2, IQ2], IP1, '')
'1q2'
>>> registry.register([IR1, IQ2], IP2, '', '1q22')
>>> registry.lookup([IR2, IQ2], IP1, '')
'1q22'
Мульти-адаптация
----------------
Вы можете адаптировать несколько объектов::
>>> class Q:
... zope.interface.implements(IQ)
Как и с одиночными адаптерами, мы регистрируем фабрику которая возвращает
класс::
>>> class IM(zope.interface.Interface):
... pass
>>> class M:
... zope.interface.implements(IM)
... def __init__(self, x, q):
... self.x, self.q = x, q
>>> registry.register([IR, IQ], IM, '', M)
И затем мы можем вызвать `queryMultiAdapter` для вычисления адаптера::
>>> q = Q()
>>> m = registry.queryMultiAdapter((x, q), IM)
>>> m.__class__.__name__
'M'
>>> m.x is x and m.q is q
True
и, конечно, мы можем использовать имена::
>>> class M2(M):
... pass
>>> registry.register([IR, IQ], IM, 'bob', M2)
>>> m = registry.queryMultiAdapter((x, q), IM, 'bob')
>>> m.__class__.__name__
'M2'
>>> m.x is x and m.q is q
True
Адаптеры по умолчанию
---------------------
Как и для одиночных адаптеров вы можете определить адаптер по умолчанию передав
None вместо *первой* спецификации::
>>> registry.register([None, IQ], IP2, '', 'q2')
>>> registry.lookup([IS, IQ], IP2, '')
'q2'
Нулевые адаптеры
================
Вы можете также адаптировать без спецификации::
>>> registry.register([], IP2, '', 2)
>>> registry.lookup([], IP2, '')
2
>>> registry.lookup([], IP1, '')
2
Перечисление именованных адаптеров
----------------------------------
Адаптеры имеют имена. Иногда это полезно для получения всех именованных
адаптеров для заданного интерфейса::
>>> adapters = list(registry.lookupAll([IR1], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', 11), (u'bob', "Bob's 12")]
Это работает также и для мульти-адаптеров::
>>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
>>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]
И даже для нулевых адаптеров::
>>> registry.register([], IP2, 'bob', 3)
>>> adapters = list(registry.lookupAll([], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', 2), (u'bob', 3)]
Подписки
========
Обычно мы хотим запросить объект который наиболее близко соответствует
спецификации. Иногда мы хотим получить все объекты которые соответствуют
какой-либо спецификации. Мы используем подписки для этого. Мы подписываем
объекты для спецификаций и затем позже находим все подписанные объекты::
>>> registry.subscribe([IR1], IP2, 'sub12 1')
>>> registry.subscriptions([IR1], IP2)
['sub12 1']
Заметьте, что в отличие от обычных адаптеров подписки не имеют имен.
Вы можете иметь несколько подписчиков для одной спецификации::
>>> registry.subscribe([IR1], IP2, 'sub12 2')
>>> registry.subscriptions([IR1], IP2)
['sub12 1', 'sub12 2']
Если подписчики зарегистрированы для одних и тех же требуемых интерфейсов, они
возвращаются в порядке определения.
Вы можете зарегистрировать подписчики для всех спецификаций используя None::
>>> registry.subscribe([None], IP1, 'sub_1')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2']
Заметьте, что новый подписчик возвращается первым. Подписчики определенные
для менее общих требуемых интерфейсов возвращаются перед подписчиками
для более общих интерфейсов.
Подписки могут смешиваться между несколькими совместимыми спецификациями::
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2']
>>> registry.subscribe([IR1], IP1, 'sub11')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2', 'sub11']
>>> registry.subscribe([IR2], IP2, 'sub22')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2', 'sub11', 'sub22']
>>> registry.subscriptions([IR2], IP2)
['sub12 1', 'sub12 2', 'sub22']
Подписки могут существовать для нескольких спецификаций::
>>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
>>> registry.subscriptions([IR1, IQ], IP2)
['sub1q2']
Как и с одиночными подписчиками и адаптерами без подписок, вы можете определить
None для первого требуемого интерфейса, что бы задать значение по умолчанию::
>>> registry.subscribe([None, IQ], IP2, 'sub_q2')
>>> registry.subscriptions([IS, IQ], IP2)
['sub_q2']
>>> registry.subscriptions([IR1, IQ], IP2)
['sub_q2', 'sub1q2']
Вы можете создать подписки которые независимы от любых спецификаций::
>>> list(registry.subscriptions([], IP1))
[]
>>> registry.subscribe([], IP2, 'sub2')
>>> registry.subscriptions([], IP1)
['sub2']
>>> registry.subscribe([], IP1, 'sub1')
>>> registry.subscriptions([], IP1)
['sub2', 'sub1']
>>> registry.subscriptions([], IP2)
['sub2']
Удаление регистрации подписчиков
--------------------------------
Мы можем удалять регистрацию подписчиков. При удалении регистрации подписчика
мы можем удалить регистрацию заданного адаптера::
>>> registry.unsubscribe([IR1], IP1, 'sub11')
>>> registry.subscriptions([IR1], IP1)
['sub_1', 'sub12 1', 'sub12 2']
Если мы не задаем никакого значения тогда подписки будут удалены для всех
подписчиков совпадающих с заданным интерфейсом::
>>> registry.unsubscribe([IR1], IP2)
>>> registry.subscriptions([IR1], IP1)
['sub_1']
Адаптеры подписки
-----------------
Обычно мы регистрируем фабрики для адаптеров которые затем позволяют нам
вычислять адаптеры, но с подписками мы получаем несколько адаптеров. Это пример
подписчика для нескольких объектов::
>>> registry.subscribe([IR, IQ], IM, M)
>>> registry.subscribe([IR, IQ], IM, M2)
>>> subscribers = registry.subscribers((x, q), IM)
>>> len(subscribers)
2
>>> class_names = [s.__class__.__name__ for s in subscribers]
>>> class_names.sort()
>>> class_names
['M', 'M2']
>>> [(s.x is x and s.q is q) for s in subscribers]
[True, True]
подписчики фабрик адаптеров не могут возвращать None::
>>> def M3(x, y):
... return None
>>> registry.subscribe([IR, IQ], IM, M3)
>>> subscribers = registry.subscribers((x, q), IM)
>>> len(subscribers)
2
Обработчики
-----------
Обработчик - это подписанная фабрика которая не возвращает нормального
значения. Она возвращает None. Обработчик отличается от адаптеров тем, что он
делает всю работу когда вызывается фабрика.
Для регистрации обработчика надо просто передать None как предоставляемый
интерфейс::
>>> def handler(event):
... print 'handler', event
>>> registry.subscribe([IR1], None, handler)
>>> registry.subscriptions([IR1], None) == [handler]
True
zope.interface-4.3.2/docs/adapter.rst 0000664 0001750 0001750 00000035430 12763206174 016605 0 ustar mg mg 0000000 0000000 ================
Adapter Registry
================
Adapter registries provide a way to register objects that depend on
one or more interface specifications and provide (perhaps indirectly)
some interface. In addition, the registrations have names. (You can
think of the names as qualifiers of the provided interfaces.)
The term "interface specification" refers both to interfaces and to
interface declarations, such as declarations of interfaces implemented
by a class.
Single Adapters
===============
Let's look at a simple example, using a single required specification:
.. doctest::
>>> from zope.interface.adapter import AdapterRegistry
>>> import zope.interface
>>> class IR1(zope.interface.Interface):
... pass
>>> class IP1(zope.interface.Interface):
... pass
>>> class IP2(IP1):
... pass
>>> registry = AdapterRegistry()
We'll register an object that depends on IR1 and "provides" IP2:
.. doctest::
>>> registry.register([IR1], IP2, '', 12)
Given the registration, we can look it up again:
.. doctest::
>>> registry.lookup([IR1], IP2, '')
12
Note that we used an integer in the example. In real applications,
one would use some objects that actually depend on or provide
interfaces. The registry doesn't care about what gets registered, so
we'll use integers and strings to keep the examples simple. There is
one exception. Registering a value of None unregisters any
previously-registered value.
If an object depends on a specification, it can be looked up with a
specification that extends the specification that it depends on:
.. doctest::
>>> class IR2(IR1):
... pass
>>> registry.lookup([IR2], IP2, '')
12
We can use a class implementation specification to look up the object:
.. doctest::
>>> class C2:
... zope.interface.implements(IR2)
>>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
12
and it can be looked up for interfaces that its provided interface
extends:
.. doctest::
>>> registry.lookup([IR1], IP1, '')
12
>>> registry.lookup([IR2], IP1, '')
12
But if you require a specification that doesn't extend the specification the
object depends on, you won't get anything:
.. doctest::
>>> registry.lookup([zope.interface.Interface], IP1, '')
By the way, you can pass a default value to lookup:
.. doctest::
>>> registry.lookup([zope.interface.Interface], IP1, '', 42)
42
If you try to get an interface the object doesn't provide, you also
won't get anything:
.. doctest::
>>> class IP3(IP2):
... pass
>>> registry.lookup([IR1], IP3, '')
You also won't get anything if you use the wrong name:
.. doctest::
>>> registry.lookup([IR1], IP1, 'bob')
>>> registry.register([IR1], IP2, 'bob', "Bob's 12")
>>> registry.lookup([IR1], IP1, 'bob')
"Bob's 12"
You can leave the name off when doing a lookup:
.. doctest::
>>> registry.lookup([IR1], IP1)
12
If we register an object that provides IP1:
.. doctest::
>>> registry.register([IR1], IP1, '', 11)
then that object will be prefered over O(12):
.. doctest::
>>> registry.lookup([IR1], IP1, '')
11
Also, if we register an object for IR2, then that will be prefered
when using IR2:
.. doctest::
>>> registry.register([IR2], IP1, '', 21)
>>> registry.lookup([IR2], IP1, '')
21
Finding out what, if anything, is registered
--------------------------------------------
We can ask if there is an adapter registered for a collection of
interfaces. This is different than lookup, because it looks for an
exact match:
.. doctest::
>>> print registry.registered([IR1], IP1)
11
>>> print registry.registered([IR1], IP2)
12
>>> print registry.registered([IR1], IP2, 'bob')
Bob's 12
>>> print registry.registered([IR2], IP1)
21
>>> print registry.registered([IR2], IP2)
None
In the last example, None was returned because nothing was registered
exactly for the given interfaces.
lookup1
-------
Lookup of single adapters is common enough that there is a specialized
version of lookup that takes a single required interface:
.. doctest::
>>> registry.lookup1(IR2, IP1, '')
21
>>> registry.lookup1(IR2, IP1)
21
Actual Adaptation
-----------------
The adapter registry is intended to support adaptation, where one
object that implements an interface is adapted to another object that
supports a different interface. The adapter registry supports the
computation of adapters. In this case, we have to register adapter
factories:
.. doctest::
>>> class IR(zope.interface.Interface):
... pass
>>> class X:
... zope.interface.implements(IR)
>>> class Y:
... zope.interface.implements(IP1)
... def __init__(self, context):
... self.context = context
>>> registry.register([IR], IP1, '', Y)
In this case, we registered a class as the factory. Now we can call
`queryAdapter` to get the adapted object:
.. doctest::
>>> x = X()
>>> y = registry.queryAdapter(x, IP1)
>>> y.__class__.__name__
'Y'
>>> y.context is x
True
We can register and lookup by name too:
.. doctest::
>>> class Y2(Y):
... pass
>>> registry.register([IR], IP1, 'bob', Y2)
>>> y = registry.queryAdapter(x, IP1, 'bob')
>>> y.__class__.__name__
'Y2'
>>> y.context is x
True
When the adapter factory produces `None`, then this is treated as if no
adapter has been found. This allows us to prevent adaptation (when desired)
and let the adapter factory determine whether adaptation is possible based on
the state of the object being adapted:
.. doctest::
>>> def factory(context):
... if context.name == 'object':
... return 'adapter'
... return None
>>> class Object(object):
... zope.interface.implements(IR)
... name = 'object'
>>> registry.register([IR], IP1, 'conditional', factory)
>>> obj = Object()
>>> registry.queryAdapter(obj, IP1, 'conditional')
'adapter'
>>> obj.name = 'no object'
>>> registry.queryAdapter(obj, IP1, 'conditional') is None
True
>>> registry.queryAdapter(obj, IP1, 'conditional', 'default')
'default'
An alternate method that provides the same function as `queryAdapter()` is
`adapter_hook()`:
.. doctest::
>>> y = registry.adapter_hook(IP1, x)
>>> y.__class__.__name__
'Y'
>>> y.context is x
True
>>> y = registry.adapter_hook(IP1, x, 'bob')
>>> y.__class__.__name__
'Y2'
>>> y.context is x
True
The `adapter_hook()` simply switches the order of the object and
interface arguments. It is used to hook into the interface call
mechanism.
Default Adapters
----------------
Sometimes, you want to provide an adapter that will adapt anything.
For that, provide None as the required interface:
.. doctest::
>>> registry.register([None], IP1, '', 1)
then we can use that adapter for interfaces we don't have specific
adapters for:
.. doctest::
>>> class IQ(zope.interface.Interface):
... pass
>>> registry.lookup([IQ], IP1, '')
1
Of course, specific adapters are still used when applicable:
.. doctest::
>>> registry.lookup([IR2], IP1, '')
21
Class adapters
--------------
You can register adapters for class declarations, which is almost the
same as registering them for a class:
.. doctest::
>>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
>>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
'C21'
Dict adapters
-------------
At some point it was impossible to register dictionary-based adapters due a
bug. Let's make sure this works now:
.. doctest::
>>> adapter = {}
>>> registry.register((), IQ, '', adapter)
>>> registry.lookup((), IQ, '') is adapter
True
Unregistering
-------------
You can unregister by registering None, rather than an object:
.. doctest::
>>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
>>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
21
Of course, this means that None can't be registered. This is an
exception to the statement, made earlier, that the registry doesn't
care what gets registered.
Multi-adapters
==============
You can adapt multiple specifications:
.. doctest::
>>> registry.register([IR1, IQ], IP2, '', '1q2')
>>> registry.lookup([IR1, IQ], IP2, '')
'1q2'
>>> registry.lookup([IR2, IQ], IP1, '')
'1q2'
>>> class IS(zope.interface.Interface):
... pass
>>> registry.lookup([IR2, IS], IP1, '')
>>> class IQ2(IQ):
... pass
>>> registry.lookup([IR2, IQ2], IP1, '')
'1q2'
>>> registry.register([IR1, IQ2], IP2, '', '1q22')
>>> registry.lookup([IR2, IQ2], IP1, '')
'1q22'
Multi-adaptation
----------------
You can adapt multiple objects:
.. doctest::
>>> class Q:
... zope.interface.implements(IQ)
As with single adapters, we register a factory, which is often a class:
.. doctest::
>>> class IM(zope.interface.Interface):
... pass
>>> class M:
... zope.interface.implements(IM)
... def __init__(self, x, q):
... self.x, self.q = x, q
>>> registry.register([IR, IQ], IM, '', M)
And then we can call `queryMultiAdapter` to compute an adapter:
.. doctest::
>>> q = Q()
>>> m = registry.queryMultiAdapter((x, q), IM)
>>> m.__class__.__name__
'M'
>>> m.x is x and m.q is q
True
and, of course, we can use names:
.. doctest::
>>> class M2(M):
... pass
>>> registry.register([IR, IQ], IM, 'bob', M2)
>>> m = registry.queryMultiAdapter((x, q), IM, 'bob')
>>> m.__class__.__name__
'M2'
>>> m.x is x and m.q is q
True
Default Adapters
----------------
As with single adapters, you can define default adapters by specifying
None for the *first* specification:
.. doctest::
>>> registry.register([None, IQ], IP2, '', 'q2')
>>> registry.lookup([IS, IQ], IP2, '')
'q2'
Null Adapters
=============
You can also adapt no specification:
.. doctest::
>>> registry.register([], IP2, '', 2)
>>> registry.lookup([], IP2, '')
2
>>> registry.lookup([], IP1, '')
2
Listing named adapters
----------------------
Adapters are named. Sometimes, it's useful to get all of the named
adapters for given interfaces:
.. doctest::
>>> adapters = list(registry.lookupAll([IR1], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', 11), (u'bob', "Bob's 12")]
This works for multi-adapters too:
.. doctest::
>>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
>>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]
And even null adapters:
.. doctest::
>>> registry.register([], IP2, 'bob', 3)
>>> adapters = list(registry.lookupAll([], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', 2), (u'bob', 3)]
Subscriptions
=============
Normally, we want to look up an object that most-closely matches a
specification. Sometimes, we want to get all of the objects that
match some specification. We use subscriptions for this. We
subscribe objects against specifications and then later find all of
the subscribed objects:
.. doctest::
>>> registry.subscribe([IR1], IP2, 'sub12 1')
>>> registry.subscriptions([IR1], IP2)
['sub12 1']
Note that, unlike regular adapters, subscriptions are unnamed.
You can have multiple subscribers for the same specification:
.. doctest::
>>> registry.subscribe([IR1], IP2, 'sub12 2')
>>> registry.subscriptions([IR1], IP2)
['sub12 1', 'sub12 2']
If subscribers are registered for the same required interfaces, they
are returned in the order of definition.
You can register subscribers for all specifications using None:
.. doctest::
>>> registry.subscribe([None], IP1, 'sub_1')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2']
Note that the new subscriber is returned first. Subscribers defined
for less general required interfaces are returned before subscribers
for more general interfaces.
Subscriptions may be combined over multiple compatible specifications:
.. doctest::
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2']
>>> registry.subscribe([IR1], IP1, 'sub11')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2', 'sub11']
>>> registry.subscribe([IR2], IP2, 'sub22')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2', 'sub11', 'sub22']
>>> registry.subscriptions([IR2], IP2)
['sub12 1', 'sub12 2', 'sub22']
Subscriptions can be on multiple specifications:
.. doctest::
>>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
>>> registry.subscriptions([IR1, IQ], IP2)
['sub1q2']
As with single subscriptions and non-subscription adapters, you can
specify None for the first required interface, to specify a default:
.. doctest::
>>> registry.subscribe([None, IQ], IP2, 'sub_q2')
>>> registry.subscriptions([IS, IQ], IP2)
['sub_q2']
>>> registry.subscriptions([IR1, IQ], IP2)
['sub_q2', 'sub1q2']
You can have subscriptions that are indepenent of any specifications:
.. doctest::
>>> list(registry.subscriptions([], IP1))
[]
>>> registry.subscribe([], IP2, 'sub2')
>>> registry.subscriptions([], IP1)
['sub2']
>>> registry.subscribe([], IP1, 'sub1')
>>> registry.subscriptions([], IP1)
['sub2', 'sub1']
>>> registry.subscriptions([], IP2)
['sub2']
Unregistering subscribers
-------------------------
We can unregister subscribers. When unregistering a subscriber, we
can unregister a specific subscriber:
.. doctest::
>>> registry.unsubscribe([IR1], IP1, 'sub11')
>>> registry.subscriptions([IR1], IP1)
['sub_1', 'sub12 1', 'sub12 2']
If we don't specify a value, then all subscribers matching the given
interfaces will be unsubscribed:
.. doctest::
>>> registry.unsubscribe([IR1], IP2)
>>> registry.subscriptions([IR1], IP1)
['sub_1']
Subscription adapters
---------------------
We normally register adapter factories, which then allow us to compute
adapters, but with subscriptions, we get multiple adapters. Here's an
example of multiple-object subscribers:
.. doctest::
>>> registry.subscribe([IR, IQ], IM, M)
>>> registry.subscribe([IR, IQ], IM, M2)
>>> subscribers = registry.subscribers((x, q), IM)
>>> len(subscribers)
2
>>> class_names = [s.__class__.__name__ for s in subscribers]
>>> class_names.sort()
>>> class_names
['M', 'M2']
>>> [(s.x is x and s.q is q) for s in subscribers]
[True, True]
adapter factory subcribers can't return None values:
.. doctest::
>>> def M3(x, y):
... return None
>>> registry.subscribe([IR, IQ], IM, M3)
>>> subscribers = registry.subscribers((x, q), IM)
>>> len(subscribers)
2
Handlers
--------
A handler is a subscriber factory that doesn't produce any normal
output. It returns None. A handler is unlike adapters in that it does
all of its work when the factory is called.
To register a handler, simply provide None as the provided interface:
.. doctest::
>>> def handler(event):
... print 'handler', event
>>> registry.subscribe([IR1], None, handler)
>>> registry.subscriptions([IR1], None) == [handler]
True
zope.interface-4.3.2/docs/README.ru.rst 0000664 0001750 0001750 00000102275 12763206174 016551 0 ustar mg mg 0000000 0000000 ==========
Интерфейсы
==========
.. contents::
Интерфейсы - это объекты специфицирующие (документирующие) внешнее поведение
объектов которые их "предоставляют". Интерфейсы определяют поведение через
следующие составляющие:
- Неформальную документацию в строках документации
- Определения атрибутов
- Инварианты - условия, которые должны соблюдаться для объектов предоставляющих
интерфейс
Определения атрибутов описывают конкретные атрибуты. Они определяют
имя атрибута и предоставляют документацию и ограничения для значений
атрибута. Определения атрибутов могут быть заданы несколькими путями
как мы увидим ниже.
Определение интерфейсов
=======================
Интерфейсы определяются с использованием ключевого слова class::
>>> import zope.interface
>>> class IFoo(zope.interface.Interface):
... """Foo blah blah"""
...
... x = zope.interface.Attribute("""X blah blah""")
...
... def bar(q, r=None):
... """bar blah blah"""
В примере выше мы создали интерфейс `IFoo`. Мы наследуем его от
класса `zope.interface.Interface`, который является родительским интерфейсом
для всех интерфейсов, как `object` - это родительский класс для всех новых
классов [#create]_. Данный интерфейс не является классом, а является
Интерфейсом, экземпляром `InterfaceClass`::
>>> type(IFoo)
Мы можем запросить у интерфейса его документацию::
>>> IFoo.__doc__
'Foo blah blah'
и его имя::
>>> IFoo.__name__
'IFoo'
и даже модуль в котором он определен::
>>> IFoo.__module__
'__main__'
Наш интерфейс определяет два атрибута:
`x`
Это простейшая форма определения атрибутов. Определяются имя
и строка документации. Формально здесь не определяется ничего более.
`bar`
Это метод. Методы определяются как обычные функции. Метод - это просто
атрибут который должен быть вызываемым с указанием сигнатуры,
предоставляемой определением функции.
Надо отметить, что аргумент `self` не указывается для `bar`. Интерфейс
документирует как объект *используется*. Когда методы экземпляров классов
вызываются мы не передаем аргумент `self`, таким образом аргумент `self`
не включается и в сигнатуру интерфейса. Аргумент `self` в методах
экземпляров классов на самом деле деталь реализации экземпляров классов
в Python. Другие объекты кроме экземпляров классов могут предоставлять
интерфейсы и их методы могут не быть методами экземпляров классов. Для
примера модули могут предоставлять интерфейсы и их методы обычно просто
функции. Даже экземпляры могут иметь методы не являющиеся методами
экземпляров класса.
Мы можем получить доступ к атрибутам определенным интерфейсом используя
синтаксис доступа к элементам массива::
>>> x = IFoo['x']
>>> type(x)
>>> x.__name__
'x'
>>> x.__doc__
'X blah blah'
>>> IFoo.get('x').__name__
'x'
>>> IFoo.get('y')
Можно использовать `in` для определения содержит ли интерфейс
определенное имя::
>>> 'x' in IFoo
True
Мы можем использовать итератор для интерфейсов что бы получить все имена
которые интерфейсы определяют::
>>> names = list(IFoo)
>>> names.sort()
>>> names
['bar', 'x']
Надо помнить, что интерфейсы не являются классами. Мы не можем получить
доступ к определениям атрибутов через доступ к атрибутам интерфейсов::
>>> IFoo.x
Traceback (most recent call last):
File "", line 1, in ?
AttributeError: 'InterfaceClass' object has no attribute 'x'
Методы также предоставляют доступ к сигнатуре метода::
>>> bar = IFoo['bar']
>>> bar.getSignatureString()
'(q, r=None)'
Объявление интерфейсов
======================
Определив интерфейс мы можем теперь *объявить*, что объекты предоставляют их.
Перед описанием деталей определим некоторые термины:
*предоставлять*
Мы говорим, что объекты *предоставляют* интерфейсы. Если объект
предоставляет интерфейс, тогда интерфейс специфицирует поведение объекта.
Другими словами, интерфейсы специфицируют поведение объектов которые
предоставляют их.
*реализовать*
Мы обычно говорим что классы *реализуют* интерфейсы. Если класс
реализует интерфейс, тогда экземпляры этого класса предоставляют
данный интерфейс. Объекты предоставляют интерфейсы которые их классы
реализуют [#factory]_. (Объекты также могут предоставлять интерфейсы напрямую
плюс к тем которые реализуют их классы.)
Важно помнить, что классы обычно не предоставляют интерфейсы которые
они реализуют.
Мы можем обобщить это до фабрик. Для любого вызываемого объекта мы можем
объявить что он производит объекты которые предоставляют какие-либо
интерфейсы сказав, что фабрика реализует данные интерфейсы.
Теперь после того как мы определили эти термины мы можем поговорить об
API для объявления интерфейсов.
Объявление реализуемых интерфейсов
----------------------------------
Наиболее часто используемый путь для объявления интерфейсов - это использование
функции implements в определении класса::
>>> class Foo:
... zope.interface.implements(IFoo)
...
... def __init__(self, x=None):
... self.x = x
...
... def bar(self, q, r=None):
... return q, r, self.x
...
... def __repr__(self):
... return "Foo(%s)" % self.x
В этом примере мы объявили, что `Foo` реализует `IFoo`. Это значит, что
экземпляры `Foo` предоставляют `IFoo`. После данного объявления есть
несколько путей для анализа объявлений. Во-первых мы можем спросить
что интерфейс реализован классом::
>>> IFoo.implementedBy(Foo)
True
Также мы можем спросить если интерфейс предоставляется объектами класса::
>>> foo = Foo()
>>> IFoo.providedBy(foo)
True
Конечно `Foo` не предоставляет `IFoo`, он реализует его::
>>> IFoo.providedBy(Foo)
False
Мы можем также узнать какие интерфейсы реализуются объектами::
>>> list(zope.interface.implementedBy(Foo))
[]
Это ошибка спрашивать про интерфейсы реализуемые не вызываемым объектом::
>>> IFoo.implementedBy(foo)
Traceback (most recent call last):
...
TypeError: ('ImplementedBy called for non-factory', Foo(None))
>>> list(zope.interface.implementedBy(foo))
Traceback (most recent call last):
...
TypeError: ('ImplementedBy called for non-factory', Foo(None))
Также можно узнать какие интерфейсы предоставляются объектами::
>>> list(zope.interface.providedBy(foo))
[]
>>> list(zope.interface.providedBy(Foo))
[]
Мы можем объявить интерфейсы реализуемые другими фабриками (кроме классов).
Это можно сделать используя декоратор `implementer` (в стиле Python 2.4).
Для версий Python ниже 2.4 это будет выглядеть следующим образом::
>>> def yfoo(y):
... foo = Foo()
... foo.y = y
... return foo
>>> yfoo = zope.interface.implementer(IFoo)(yfoo)
>>> list(zope.interface.implementedBy(yfoo))
[]
Надо заметить, что декоратор implementer может модифицировать свои аргументы.
Вызывающая сторона не должна предполагать, что всегда будет создаваться
новый объект.
XXX: Double check and update these version numbers, and translate to russian:
In zope.interface 3.5.1 and lower, the implementer decorator can not
be used for classes, but in 3.5.2 and higher it can::
>>> Foo = zope.interface.implementer(IFoo)(Foo)
>>> list(zope.interface.providedBy(Foo()))
[]
Note that class decorators using the @implementer(IFoo) syntax are only
supported in Python 2.6 and later.
Объявление предоставляемых интерфейсов
--------------------------------------
Мы можем объявлять интерфейсы напрямую предоставляемые объектами. Предположим
что мы хотим документировать что делает метод `__init__` класса `Foo`. Это
*точно* не часть `IFoo`. Обычно мы не должны напрямую вызывать метод `__init__`
для экземпляров Foo. Скорее метод `__init__` является частью метода `__call__`
класса `Foo`::
>>> class IFooFactory(zope.interface.Interface):
... """Create foos"""
...
... def __call__(x=None):
... """Create a foo
...
... The argument provides the initial value for x ...
... """
У нас есть класс предоставляющий данный интерфейс, таким образом мы можем
объявить интерфейс класса::
>>> zope.interface.directlyProvides(Foo, IFooFactory)
Теперь мы видим, что Foo уже предоставляет интерфейсы::
>>> list(zope.interface.providedBy(Foo))
[]
>>> IFooFactory.providedBy(Foo)
True
Объявление интерфейсов класса достаточно частая операция и для нее есть
специальная функция объявления `classProvides`, которая позволяет объявлять
интерфейсы при определении класса::
>>> class Foo2:
... zope.interface.implements(IFoo)
... zope.interface.classProvides(IFooFactory)
...
... def __init__(self, x=None):
... self.x = x
...
... def bar(self, q, r=None):
... return q, r, self.x
...
... def __repr__(self):
... return "Foo(%s)" % self.x
>>> list(zope.interface.providedBy(Foo2))
[]
>>> IFooFactory.providedBy(Foo2)
True
Похожая функция `moduleProvides` поддерживает объявление интерфейсов при
определении модуля. Для примера смотрите использование вызова
`moduleProvides` в `zope.interface.__init__`, который объявляет, что
пакет `zope.interface` предоставляет `IInterfaceDeclaration`.
Иногда мы хотим объявить интерфейсы экземпляров, даже если эти экземпляры
уже берут интерфейсы от своих классов. Предположим, что мы создаем новый
интерфейс `ISpecial`::
>>> class ISpecial(zope.interface.Interface):
... reason = zope.interface.Attribute("Reason why we're special")
... def brag():
... "Brag about being special"
Мы можем сделать созданный экземпляр foo специальным предоставив атрибуты
`reason` и `brag`::
>>> foo.reason = 'I just am'
>>> def brag():
... return "I'm special!"
>>> foo.brag = brag
>>> foo.reason
'I just am'
>>> foo.brag()
"I'm special!"
и объявив интерфейс::
>>> zope.interface.directlyProvides(foo, ISpecial)
таким образом новый интерфейс включается в список предоставляемых интерфейсов::
>>> ISpecial.providedBy(foo)
True
>>> list(zope.interface.providedBy(foo))
[, ]
Мы также можем определить, что интерфейсы напрямую предоставляются
объектами::
>>> list(zope.interface.directlyProvidedBy(foo))
[]
>>> newfoo = Foo()
>>> list(zope.interface.directlyProvidedBy(newfoo))
[]
Наследуемые объявления
----------------------
Обычно объявления наследуются::
>>> class SpecialFoo(Foo):
... zope.interface.implements(ISpecial)
... reason = 'I just am'
... def brag(self):
... return "I'm special because %s" % self.reason
>>> list(zope.interface.implementedBy(SpecialFoo))
[, ]
>>> list(zope.interface.providedBy(SpecialFoo()))
[, ]
Иногда мы не хотим наследовать объявления. В этом случае мы можем
использовать `implementsOnly` вместо `implements`::
>>> class Special(Foo):
... zope.interface.implementsOnly(ISpecial)
... reason = 'I just am'
... def brag(self):
... return "I'm special because %s" % self.reason
>>> list(zope.interface.implementedBy(Special))
[]
>>> list(zope.interface.providedBy(Special()))
[]
Внешние объявления
------------------
Обычно мы создаем объявления реализации как часть объявления класса. Иногда
мы можем захотеть создать объявления вне объявления класса. Для примера,
мы можем хотеть объявить интерфейсы для классов которые писали не мы.
Для этого может использоваться функция `classImplements`::
>>> class C:
... pass
>>> zope.interface.classImplements(C, IFoo)
>>> list(zope.interface.implementedBy(C))
[]
Мы можем использовать `classImplementsOnly` для исключения наследуемых
интерфейсов::
>>> class C(Foo):
... pass
>>> zope.interface.classImplementsOnly(C, ISpecial)
>>> list(zope.interface.implementedBy(C))
[]
Объекты объявлений
------------------
Когда мы объявляем интерфейсы мы создаем объект *объявления*. Когда мы
запрашиваем объявления возвращается объект объявления::
>>> type(zope.interface.implementedBy(Special))
Объекты объявления и объекты интерфейсов во многом похожи друг на друга.
На самом деле они даже имеют общий базовый класс. Важно понять, что они могут
использоваться там где в объявлениях ожидаются интерфейсы. Вот простой
пример::
>>> class Special2(Foo):
... zope.interface.implementsOnly(
... zope.interface.implementedBy(Foo),
... ISpecial,
... )
... reason = 'I just am'
... def brag(self):
... return "I'm special because %s" % self.reason
Объявление здесь практически такое же как
``zope.interface.implements(ISpecial)``, отличие только в порядке
интерфейсов в итоговом объявления::
>>> list(zope.interface.implementedBy(Special2))
[, ]
Наследование интерфейсов
========================
Интерфейсы могут расширять другие интерфейсы. Они делают это просто
показывая эти интерфейсы как базовые::
>>> class IBlat(zope.interface.Interface):
... """Blat blah blah"""
...
... y = zope.interface.Attribute("y blah blah")
... def eek():
... """eek blah blah"""
>>> IBlat.__bases__
(,)
>>> class IBaz(IFoo, IBlat):
... """Baz blah"""
... def eek(a=1):
... """eek in baz blah"""
...
>>> IBaz.__bases__
(, )
>>> names = list(IBaz)
>>> names.sort()
>>> names
['bar', 'eek', 'x', 'y']
Заметим, что `IBaz` переопределяет eek::
>>> IBlat['eek'].__doc__
'eek blah blah'
>>> IBaz['eek'].__doc__
'eek in baz blah'
Мы были осторожны переопределяя eek совместимым путем. Когда интерфейс
расширяется, расширенный интерфейс должен быть совместимым [#compat]_ с
расширяемыми интерфейсами.
Мы можем запросить расширяет ли один из интерфейсов другой::
>>> IBaz.extends(IFoo)
True
>>> IBlat.extends(IFoo)
False
Заметим, что интерфейсы не расширяют сами себя::
>>> IBaz.extends(IBaz)
False
Иногда мы можем хотеть что бы они расширяли сами себя, но вместо этого
мы можем использовать `isOrExtends`::
>>> IBaz.isOrExtends(IBaz)
True
>>> IBaz.isOrExtends(IFoo)
True
>>> IFoo.isOrExtends(IBaz)
False
Когда мы применяем итерацию к интерфейсу мы получаем все имена которые он
определяет включая имена определенные для базовых интерфейсов. Иногда
мы хотим получить *только* имена определенные интерфейсом напрямую.
Для этого мы используем метод `names`::
>>> list(IBaz.names())
['eek']
Наследование в случае определения атрибутов
--------------------------------------------
Интерфейс может переопределять определения атрибутов из базовых интерфейсов.
Если два базовых интерфейса определяют один и тот же атрибут атрибут
наследуется от более специфичного интерфейса. Для примера::
>>> class IBase(zope.interface.Interface):
...
... def foo():
... "base foo doc"
>>> class IBase1(IBase):
... pass
>>> class IBase2(IBase):
...
... def foo():
... "base2 foo doc"
>>> class ISub(IBase1, IBase2):
... pass
Определение ISub для foo будет из IBase2 т.к. IBase2 более специфичен для
IBase::
>>> ISub['foo'].__doc__
'base2 foo doc'
Заметим, что это отличается от поиска в глубину.
Иногда полезно узнать, что интерфейс определяет атрибут напрямую. Мы можем
использовать метод direct для получения напрямую определенных атрибутов::
>>> IBase.direct('foo').__doc__
'base foo doc'
>>> ISub.direct('foo')
Спецификации
------------
Интерфейсы и объявления - это специальные случаи спецификаций. Описание
выше для наследования интерфейсов можно применить и к объявлениям и
к спецификациям. Объявления фактически расширяют интерфейсы которые они
объявляют::
>>> class Baz(object):
... zope.interface.implements(IBaz)
>>> baz_implements = zope.interface.implementedBy(Baz)
>>> baz_implements.__bases__
(, )
>>> baz_implements.extends(IFoo)
True
>>> baz_implements.isOrExtends(IFoo)
True
>>> baz_implements.isOrExtends(baz_implements)
True
Спецификации (интерфейсы и объявления) предоставляют атрибут `__sro__`
который описывает спецификацию и всех ее предков::
>>> baz_implements.__sro__
(,
,
,
,
,
)
Помеченные значения
===================
Интерфейсы и описания атрибутов поддерживают механизм расширения
заимствованный из UML и называемый "помеченные значения" который позволяет
сохранять дополнительные данные::
>>> IFoo.setTaggedValue('date-modified', '2004-04-01')
>>> IFoo.setTaggedValue('author', 'Jim Fulton')
>>> IFoo.getTaggedValue('date-modified')
'2004-04-01'
>>> IFoo.queryTaggedValue('date-modified')
'2004-04-01'
>>> IFoo.queryTaggedValue('datemodified')
>>> tags = list(IFoo.getTaggedValueTags())
>>> tags.sort()
>>> tags
['author', 'date-modified']
Атрибуты функций конвертируются в помеченные значения когда создаются
определения атрибутов метода::
>>> class IBazFactory(zope.interface.Interface):
... def __call__():
... "create one"
... __call__.return_type = IBaz
>>> IBazFactory['__call__'].getTaggedValue('return_type')
Помеченные значения также могут быть определены внутри определения
интерфейса::
>>> class IWithTaggedValues(zope.interface.Interface):
... zope.interface.taggedValue('squish', 'squash')
>>> IWithTaggedValues.getTaggedValue('squish')
'squash'
Инварианты
==========
Интерфейсы могут описывать условия которые должны быть соблюдены для объектов
которые их предоставляют. Эти условия описываются используя один или более
инвариантов. Инварианты - это вызываемые объекты которые будут вызваны
с объектом предоставляющим интерфейс в качестве параметра. Инвариант
должен выкинуть исключение `Invalid` если условие не соблюдено. Например::
>>> class RangeError(zope.interface.Invalid):
... """A range has invalid limits"""
... def __repr__(self):
... return "RangeError(%r)" % self.args
>>> def range_invariant(ob):
... if ob.max < ob.min:
... raise RangeError(ob)
Определив этот инвариант мы можем использовать его в определении интерфейсов::
>>> class IRange(zope.interface.Interface):
... min = zope.interface.Attribute("Lower bound")
... max = zope.interface.Attribute("Upper bound")
...
... zope.interface.invariant(range_invariant)
Интерфейсы имеют метод для проверки своих инвариантов::
>>> class Range(object):
... zope.interface.implements(IRange)
...
... def __init__(self, min, max):
... self.min, self.max = min, max
...
... def __repr__(self):
... return "Range(%s, %s)" % (self.min, self.max)
>>> IRange.validateInvariants(Range(1,2))
>>> IRange.validateInvariants(Range(1,1))
>>> IRange.validateInvariants(Range(2,1))
Traceback (most recent call last):
...
RangeError: Range(2, 1)
В случае нескольких инвариантов мы можем захотеть остановить проверку после
первой ошибки. Если мы передадим в `validateInvariants` пустой список тогда
будет выкинуто единственное исключение `Invalid` со списком исключений
как аргументом::
>>> from zope.interface.exceptions import Invalid
>>> errors = []
>>> try:
... IRange.validateInvariants(Range(2,1), errors)
... except Invalid, e:
... str(e)
'[RangeError(Range(2, 1))]'
И список будет заполнен индивидуальными исключениями::
>>> errors
[RangeError(Range(2, 1))]
>>> del errors[:]
Адаптация
=========
Интерфейсы могут быть вызваны для осуществления адаптации. Эта семантика
основана на функции adapt из PEP 246. Если объект не может быть адаптирован
будет выкинут TypeError::
>>> class I(zope.interface.Interface):
... pass
>>> I(0)
Traceback (most recent call last):
...
TypeError: ('Could not adapt', 0, )
только если альтернативное значение не передано как второй аргумент::
>>> I(0, 'bob')
'bob'
Если объект уже реализует нужный интерфейс он будет возвращен::
>>> class C(object):
... zope.interface.implements(I)
>>> obj = C()
>>> I(obj) is obj
True
Если объект реализует __conform__, тогда она будет использована::
>>> class C(object):
... zope.interface.implements(I)
... def __conform__(self, proto):
... return 0
>>> I(C())
0
Также если присутствуют функции для вызова адаптации (см. __adapt__) они будут
использованы::
>>> from zope.interface.interface import adapter_hooks
>>> def adapt_0_to_42(iface, obj):
... if obj == 0:
... return 42
>>> adapter_hooks.append(adapt_0_to_42)
>>> I(0)
42
>>> adapter_hooks.remove(adapt_0_to_42)
>>> I(0)
Traceback (most recent call last):
...
TypeError: ('Could not adapt', 0, )
__adapt__
---------
::
>>> class I(zope.interface.Interface):
... pass
Интерфейсы реализуют метод __adapt__ из PEP 246. Этот метод обычно не
вызывается напрямую. Он вызывается архитектурой адаптации из PEP 246 и методом
__call__ интерфейсов. Метод адаптации отвечает за адаптацию объекта к
получателю. Версия по умолчанию возвращает None::
>>> I.__adapt__(0)
если только переданный объект не предоставляет нужный интерфейс::
>>> class C(object):
... zope.interface.implements(I)
>>> obj = C()
>>> I.__adapt__(obj) is obj
True
Функции для вызова адаптации могут быть добавлены (или удалены) для
предоставления адаптации "на заказ". Мы установим глупую функцию которая
адаптирует 0 к 42. Мы устанавливаем функцию просто добавляя ее к списку
adapter_hooks::
>>> from zope.interface.interface import adapter_hooks
>>> def adapt_0_to_42(iface, obj):
... if obj == 0:
... return 42
>>> adapter_hooks.append(adapt_0_to_42)
>>> I.__adapt__(0)
42
Функции должны возвращать либо адаптер, либо None если адаптер не найден.
Функции могут быть удалены удалением их из списка::
>>> adapter_hooks.remove(adapt_0_to_42)
>>> I.__adapt__(0)
.. [#create] Основная причина по которой мы наследуемся от `Interface` - это
что бы быть уверенными в том, что ключевое слово class будет
создавать интерфейс, а не класс.
Есть возможность создать интерфейсы вызвав специальный
класс интерфейса напрямую. Делая это, возможно (и в редких
случаях полезно) создать интерфейсы которые не наследуются
от `Interface`. Однако использование этой техники выходит
за рамки данного документа.
.. [#factory] Классы - это фабрики. Они могут быть вызваны для создания
своих экземпляров. Мы ожидаем что в итоге мы расширим
концепцию реализации на другие типы фабрик, таким образом
мы сможем объявлять интерфейсы предоставляемые созданными
фабриками объектами.
.. [#compat] Цель - заменяемость. Объект который предоставляет расширенный
интерфейс должен быть заменяем в качестве объектов которые
предоставляют расширяемый интерфейс. В нашем примере объект
который предоставляет IBaz должен быть используемым и
в случае если ожидается объект который предоставляет IBlat.
Реализация интерфейса не требует этого. Но возможно в дальнейшем
она должна будет делать какие-либо проверки.
zope.interface-4.3.2/docs/README.rst 0000664 0001750 0001750 00000060572 12763206174 016127 0 ustar mg mg 0000000 0000000 ==========
Interfaces
==========
Interfaces are objects that specify (document) the external behavior
of objects that "provide" them. An interface specifies behavior
through:
- Informal documentation in a doc string
- Attribute definitions
- Invariants, which are conditions that must hold for objects that
provide the interface
Attribute definitions specify specific attributes. They define the
attribute name and provide documentation and constraints of attribute
values. Attribute definitions can take a number of forms, as we'll
see below.
Defining interfaces
===================
Interfaces are defined using Python ``class`` statements:
.. doctest::
>>> import zope.interface
>>> class IFoo(zope.interface.Interface):
... """Foo blah blah"""
...
... x = zope.interface.Attribute("""X blah blah""")
...
... def bar(q, r=None):
... """bar blah blah"""
In the example above, we've created an interface, :class:`IFoo`. We
subclassed :class:`zope.interface.Interface`, which is an ancestor interface for
all interfaces, much as `object` is an ancestor of all new-style
classes [#create]_. The interface is not a class, it's an Interface,
an instance of :class:`zope.interface.interface.InterfaceClass`:
.. doctest::
>>> type(IFoo)
We can ask for the interface's documentation:
.. doctest::
>>> IFoo.__doc__
'Foo blah blah'
and its name:
.. doctest::
>>> IFoo.__name__
'IFoo'
and even its module:
.. doctest::
>>> IFoo.__module__
'__builtin__'
The interface defined two attributes:
`x`
This is the simplest form of attribute definition. It has a name
and a doc string. It doesn't formally specify anything else.
`bar`
This is a method. A method is defined via a function definition. A
method is simply an attribute constrained to be a callable with a
particular signature, as provided by the function definition.
Note that `bar` doesn't take a `self` argument. Interfaces document
how an object is *used*. When calling instance methods, you don't
pass a `self` argument, so a `self` argument isn't included in the
interface signature. The `self` argument in instance methods is
really an implementation detail of Python instances. Other objects,
besides instances can provide interfaces and their methods might not
be instance methods. For example, modules can provide interfaces and
their methods are usually just functions. Even instances can have
methods that are not instance methods.
You can access the attributes defined by an interface using mapping
syntax:
.. doctest::
>>> x = IFoo['x']
>>> type(x)
>>> x.__name__
'x'
>>> x.__doc__
'X blah blah'
>>> IFoo.get('x').__name__
'x'
>>> IFoo.get('y')
You can use `in` to determine if an interface defines a name:
.. doctest::
>>> 'x' in IFoo
True
You can iterate over interfaces to get the names they define:
.. doctest::
>>> names = list(IFoo)
>>> names.sort()
>>> names
['bar', 'x']
Remember that interfaces aren't classes. You can't access attribute
definitions as attributes of interfaces:
.. doctest::
>>> IFoo.x
Traceback (most recent call last):
File "", line 1, in ?
AttributeError: 'InterfaceClass' object has no attribute 'x'
Methods provide access to the method signature:
.. doctest::
>>> bar = IFoo['bar']
>>> bar.getSignatureString()
'(q, r=None)'
TODO
Methods really should have a better API. This is something that
needs to be improved.
Declaring interfaces
====================
Having defined interfaces, we can *declare* that objects provide
them. Before we describe the details, lets define some terms:
*provide*
We say that objects *provide* interfaces. If an object provides an
interface, then the interface specifies the behavior of the
object. In other words, interfaces specify the behavior of the
objects that provide them.
*implement*
We normally say that classes *implement* interfaces. If a class
implements an interface, then the instances of the class provide
the interface. Objects provide interfaces that their classes
implement [#factory]_. (Objects can provide interfaces directly,
in addition to what their classes implement.)
It is important to note that classes don't usually provide the
interfaces that they implement.
We can generalize this to factories. For any callable object we
can declare that it produces objects that provide some interfaces
by saying that the factory implements the interfaces.
Now that we've defined these terms, we can talk about the API for
declaring interfaces.
Declaring implemented interfaces
--------------------------------
The most common way to declare interfaces is using the implements
function in a class statement:
.. doctest::
>>> class Foo:
... zope.interface.implements(IFoo)
...
... def __init__(self, x=None):
... self.x = x
...
... def bar(self, q, r=None):
... return q, r, self.x
...
... def __repr__(self):
... return "Foo(%s)" % self.x
In this example, we declared that `Foo` implements `IFoo`. This means
that instances of `Foo` provide `IFoo`. Having made this declaration,
there are several ways we can introspect the declarations. First, we
can ask an interface whether it is implemented by a class:
.. doctest::
>>> IFoo.implementedBy(Foo)
True
And we can ask whether an interface is provided by an object:
.. doctest::
>>> foo = Foo()
>>> IFoo.providedBy(foo)
True
Of course, `Foo` doesn't provide `IFoo`, it implements it:
.. doctest::
>>> IFoo.providedBy(Foo)
False
We can also ask what interfaces are implemented by an object:
.. doctest::
>>> list(zope.interface.implementedBy(Foo))
[]
It's an error to ask for interfaces implemented by a non-callable
object:
.. doctest::
>>> IFoo.implementedBy(foo)
Traceback (most recent call last):
...
TypeError: ('ImplementedBy called for non-factory', Foo(None))
>>> list(zope.interface.implementedBy(foo))
Traceback (most recent call last):
...
TypeError: ('ImplementedBy called for non-factory', Foo(None))
Similarly, we can ask what interfaces are provided by an object:
.. doctest::
>>> list(zope.interface.providedBy(foo))
[]
>>> list(zope.interface.providedBy(Foo))
[]
We can declare interfaces implemented by other factories (besides
classes). We do this using a Python-2.4-style decorator named
`implementer`. In versions of Python before 2.4, this looks like:
.. doctest::
>>> def yfoo(y):
... foo = Foo()
... foo.y = y
... return foo
>>> yfoo = zope.interface.implementer(IFoo)(yfoo)
>>> list(zope.interface.implementedBy(yfoo))
[]
Note that the implementer decorator may modify it's argument. Callers
should not assume that a new object is created.
Using implementer also works on callable objects. This is used by
zope.formlib, as an example:
.. doctest::
>>> class yfactory:
... def __call__(self, y):
... foo = Foo()
... foo.y = y
... return foo
>>> yfoo = yfactory()
>>> yfoo = zope.interface.implementer(IFoo)(yfoo)
>>> list(zope.interface.implementedBy(yfoo))
[]
XXX: Double check and update these version numbers:
In zope.interface 3.5.2 and lower, the implementer decorator can not
be used for classes, but in 3.6.0 and higher it can:
.. doctest::
>>> Foo = zope.interface.implementer(IFoo)(Foo)
>>> list(zope.interface.providedBy(Foo()))
[]
Note that class decorators using the @implementer(IFoo) syntax are only
supported in Python 2.6 and later.
Declaring provided interfaces
-----------------------------
We can declare interfaces directly provided by objects. Suppose that
we want to document what the `__init__` method of the `Foo` class
does. It's not *really* part of `IFoo`. You wouldn't normally call
the `__init__` method on Foo instances. Rather, the `__init__` method
is part of the `Foo`'s `__call__` method:
.. doctest::
>>> class IFooFactory(zope.interface.Interface):
... """Create foos"""
...
... def __call__(x=None):
... """Create a foo
...
... The argument provides the initial value for x ...
... """
It's the class that provides this interface, so we declare the
interface on the class:
.. doctest::
>>> zope.interface.directlyProvides(Foo, IFooFactory)
And then, we'll see that Foo provides some interfaces:
.. doctest::
>>> list(zope.interface.providedBy(Foo))
[]
>>> IFooFactory.providedBy(Foo)
True
Declaring class interfaces is common enough that there's a special
declaration function for it, `classProvides`, that allows the
declaration from within a class statement:
.. doctest::
>>> class Foo2:
... zope.interface.implements(IFoo)
... zope.interface.classProvides(IFooFactory)
...
... def __init__(self, x=None):
... self.x = x
...
... def bar(self, q, r=None):
... return q, r, self.x
...
... def __repr__(self):
... return "Foo(%s)" % self.x
>>> list(zope.interface.providedBy(Foo2))
[]
>>> IFooFactory.providedBy(Foo2)
True
There's a similar function, `moduleProvides`, that supports interface
declarations from within module definitions. For example, see the use
of `moduleProvides` call in `zope.interface.__init__`, which declares that
the package `zope.interface` provides `IInterfaceDeclaration`.
Sometimes, we want to declare interfaces on instances, even though
those instances get interfaces from their classes. Suppose we create
a new interface, `ISpecial`:
.. doctest::
>>> class ISpecial(zope.interface.Interface):
... reason = zope.interface.Attribute("Reason why we're special")
... def brag():
... "Brag about being special"
We can make an existing foo instance special by providing `reason`
and `brag` attributes:
.. doctest::
>>> foo.reason = 'I just am'
>>> def brag():
... return "I'm special!"
>>> foo.brag = brag
>>> foo.reason
'I just am'
>>> foo.brag()
"I'm special!"
and by declaring the interface:
.. doctest::
>>> zope.interface.directlyProvides(foo, ISpecial)
then the new interface is included in the provided interfaces:
.. doctest::
>>> ISpecial.providedBy(foo)
True
>>> list(zope.interface.providedBy(foo))
[, ]
We can find out what interfaces are directly provided by an object:
.. doctest::
>>> list(zope.interface.directlyProvidedBy(foo))
[]
>>> newfoo = Foo()
>>> list(zope.interface.directlyProvidedBy(newfoo))
[]
Inherited declarations
----------------------
Normally, declarations are inherited:
.. doctest::
>>> class SpecialFoo(Foo):
... zope.interface.implements(ISpecial)
... reason = 'I just am'
... def brag(self):
... return "I'm special because %s" % self.reason
>>> list(zope.interface.implementedBy(SpecialFoo))
[, ]
>>> list(zope.interface.providedBy(SpecialFoo()))
[, ]
Sometimes, you don't want to inherit declarations. In that case, you
can use `implementsOnly`, instead of `implements`:
.. doctest::
>>> class Special(Foo):
... zope.interface.implementsOnly(ISpecial)
... reason = 'I just am'
... def brag(self):
... return "I'm special because %s" % self.reason
>>> list(zope.interface.implementedBy(Special))
[]
>>> list(zope.interface.providedBy(Special()))
[]
External declarations
---------------------
Normally, we make implementation declarations as part of a class
definition. Sometimes, we may want to make declarations from outside
the class definition. For example, we might want to declare interfaces
for classes that we didn't write. The function `classImplements` can
be used for this purpose:
.. doctest::
>>> class C:
... pass
>>> zope.interface.classImplements(C, IFoo)
>>> list(zope.interface.implementedBy(C))
[]
We can use `classImplementsOnly` to exclude inherited interfaces:
.. doctest::
>>> class C(Foo):
... pass
>>> zope.interface.classImplementsOnly(C, ISpecial)
>>> list(zope.interface.implementedBy(C))
[]
Declaration Objects
-------------------
When we declare interfaces, we create *declaration* objects. When we
query declarations, declaration objects are returned:
.. doctest::
>>> type(zope.interface.implementedBy(Special))
Declaration objects and interface objects are similar in many ways. In
fact, they share a common base class. The important thing to realize
about them is that they can be used where interfaces are expected in
declarations. Here's a silly example:
.. doctest::
>>> class Special2(Foo):
... zope.interface.implementsOnly(
... zope.interface.implementedBy(Foo),
... ISpecial,
... )
... reason = 'I just am'
... def brag(self):
... return "I'm special because %s" % self.reason
The declaration here is almost the same as
``zope.interface.implements(ISpecial)``, except that the order of
interfaces in the resulting declaration is different:
.. doctest::
>>> list(zope.interface.implementedBy(Special2))
[, ]
Interface Inheritance
=====================
Interfaces can extend other interfaces. They do this simply by listing
the other interfaces as base interfaces:
.. doctest::
>>> class IBlat(zope.interface.Interface):
... """Blat blah blah"""
...
... y = zope.interface.Attribute("y blah blah")
... def eek():
... """eek blah blah"""
>>> IBlat.__bases__
(,)
>>> class IBaz(IFoo, IBlat):
... """Baz blah"""
... def eek(a=1):
... """eek in baz blah"""
...
>>> IBaz.__bases__
(, )
>>> names = list(IBaz)
>>> names.sort()
>>> names
['bar', 'eek', 'x', 'y']
Note that `IBaz` overrides eek:
.. doctest::
>>> IBlat['eek'].__doc__
'eek blah blah'
>>> IBaz['eek'].__doc__
'eek in baz blah'
We were careful to override eek in a compatible way. When extending
an interface, the extending interface should be compatible [#compat]_
with the extended interfaces.
We can ask whether one interface extends another:
.. doctest::
>>> IBaz.extends(IFoo)
True
>>> IBlat.extends(IFoo)
False
Note that interfaces don't extend themselves:
.. doctest::
>>> IBaz.extends(IBaz)
False
Sometimes we wish they did, but we can, instead use `isOrExtends`:
.. doctest::
>>> IBaz.isOrExtends(IBaz)
True
>>> IBaz.isOrExtends(IFoo)
True
>>> IFoo.isOrExtends(IBaz)
False
When we iterate over an interface, we get all of the names it defines,
including names defined by base interfaces. Sometimes, we want *just*
the names defined by the interface directly. We bane use the `names`
method for that:
.. doctest::
>>> list(IBaz.names())
['eek']
Inheritance of attribute specifications
---------------------------------------
An interface may override attribute definitions from base interfaces.
If two base interfaces define the same attribute, the attribute is
inherited from the most specific interface. For example, with:
.. doctest::
>>> class IBase(zope.interface.Interface):
...
... def foo():
... "base foo doc"
>>> class IBase1(IBase):
... pass
>>> class IBase2(IBase):
...
... def foo():
... "base2 foo doc"
>>> class ISub(IBase1, IBase2):
... pass
ISub's definition of foo is the one from IBase2, since IBase2 is more
specific that IBase:
.. doctest::
>>> ISub['foo'].__doc__
'base2 foo doc'
Note that this differs from a depth-first search.
Sometimes, it's useful to ask whether an interface defines an
attribute directly. You can use the direct method to get a directly
defined definitions:
.. doctest::
>>> IBase.direct('foo').__doc__
'base foo doc'
>>> ISub.direct('foo')
Specifications
--------------
Interfaces and declarations are both special cases of specifications.
What we described above for interface inheritance applies to both
declarations and specifications. Declarations actually extend the
interfaces that they declare:
.. doctest::
>>> class Baz(object):
... zope.interface.implements(IBaz)
>>> baz_implements = zope.interface.implementedBy(Baz)
>>> baz_implements.__bases__
(, )
>>> baz_implements.extends(IFoo)
True
>>> baz_implements.isOrExtends(IFoo)
True
>>> baz_implements.isOrExtends(baz_implements)
True
Specifications (interfaces and declarations) provide an `__sro__`
that lists the specification and all of it's ancestors:
.. doctest::
>>> from pprint import pprint
>>> pprint(baz_implements.__sro__)
(,
,
,
,
,
)
Tagged Values
=============
Interfaces and attribute descriptions support an extension mechanism,
borrowed from UML, called "tagged values" that lets us store extra
data:
.. doctest::
>>> IFoo.setTaggedValue('date-modified', '2004-04-01')
>>> IFoo.setTaggedValue('author', 'Jim Fulton')
>>> IFoo.getTaggedValue('date-modified')
'2004-04-01'
>>> IFoo.queryTaggedValue('date-modified')
'2004-04-01'
>>> IFoo.queryTaggedValue('datemodified')
>>> tags = list(IFoo.getTaggedValueTags())
>>> tags.sort()
>>> tags
['author', 'date-modified']
Function attributes are converted to tagged values when method
attribute definitions are created:
.. doctest::
>>> class IBazFactory(zope.interface.Interface):
... def __call__():
... "create one"
... __call__.return_type = IBaz
>>> IBazFactory['__call__'].getTaggedValue('return_type')
Tagged values can also be defined from within an interface definition:
.. doctest::
>>> class IWithTaggedValues(zope.interface.Interface):
... zope.interface.taggedValue('squish', 'squash')
>>> IWithTaggedValues.getTaggedValue('squish')
'squash'
Invariants
==========
Interfaces can express conditions that must hold for objects that
provide them. These conditions are expressed using one or more
invariants. Invariants are callable objects that will be called with
an object that provides an interface. An invariant raises an `Invalid`
exception if the condition doesn't hold. Here's an example:
.. doctest::
>>> class RangeError(zope.interface.Invalid):
... """A range has invalid limits"""
... def __repr__(self):
... return "RangeError(%r)" % self.args
>>> def range_invariant(ob):
... if ob.max < ob.min:
... raise RangeError(ob)
Given this invariant, we can use it in an interface definition:
.. doctest::
>>> class IRange(zope.interface.Interface):
... min = zope.interface.Attribute("Lower bound")
... max = zope.interface.Attribute("Upper bound")
...
... zope.interface.invariant(range_invariant)
Interfaces have a method for checking their invariants:
.. doctest::
>>> class Range(object):
... zope.interface.implements(IRange)
...
... def __init__(self, min, max):
... self.min, self.max = min, max
...
... def __repr__(self):
... return "Range(%s, %s)" % (self.min, self.max)
>>> IRange.validateInvariants(Range(1,2))
>>> IRange.validateInvariants(Range(1,1))
>>> IRange.validateInvariants(Range(2,1))
Traceback (most recent call last):
...
RangeError: Range(2, 1)
If you have multiple invariants, you may not want to stop checking
after the first error. If you pass a list to `validateInvariants`,
then a single `Invalid` exception will be raised with the list of
exceptions as it's argument:
.. doctest::
>>> from zope.interface.exceptions import Invalid
>>> errors = []
>>> try:
... IRange.validateInvariants(Range(2,1), errors)
... except Invalid, e:
... str(e)
'[RangeError(Range(2, 1))]'
And the list will be filled with the individual exceptions:
.. doctest::
>>> errors
[RangeError(Range(2, 1))]
>>> del errors[:]
Adaptation
==========
Interfaces can be called to perform adaptation.
The semantics are based on those of the PEP 246 adapt function.
If an object cannot be adapted, then a TypeError is raised:
.. doctest::
>>> class I(zope.interface.Interface):
... pass
>>> I(0)
Traceback (most recent call last):
...
TypeError: ('Could not adapt', 0, )
unless an alternate value is provided as a second positional argument:
.. doctest::
>>> I(0, 'bob')
'bob'
If an object already implements the interface, then it will be returned:
.. doctest::
>>> class C(object):
... zope.interface.implements(I)
>>> obj = C()
>>> I(obj) is obj
True
If an object implements __conform__, then it will be used:
.. doctest::
>>> class C(object):
... zope.interface.implements(I)
... def __conform__(self, proto):
... return 0
>>> I(C())
0
Adapter hooks (see __adapt__) will also be used, if present:
.. doctest::
>>> from zope.interface.interface import adapter_hooks
>>> def adapt_0_to_42(iface, obj):
... if obj == 0:
... return 42
>>> adapter_hooks.append(adapt_0_to_42)
>>> I(0)
42
>>> adapter_hooks.remove(adapt_0_to_42)
>>> I(0)
Traceback (most recent call last):
...
TypeError: ('Could not adapt', 0, )
__adapt__
---------
.. doctest::
>>> class I(zope.interface.Interface):
... pass
Interfaces implement the PEP 246 __adapt__ method.
This method is normally not called directly. It is called by the PEP
246 adapt framework and by the interface __call__ operator.
The adapt method is responsible for adapting an object to the
reciever.
The default version returns None:
.. doctest::
>>> I.__adapt__(0)
unless the object given provides the interface:
.. doctest::
>>> class C(object):
... zope.interface.implements(I)
>>> obj = C()
>>> I.__adapt__(obj) is obj
True
Adapter hooks can be provided (or removed) to provide custom
adaptation. We'll install a silly hook that adapts 0 to 42.
We install a hook by simply adding it to the adapter_hooks
list:
.. doctest::
>>> from zope.interface.interface import adapter_hooks
>>> def adapt_0_to_42(iface, obj):
... if obj == 0:
... return 42
>>> adapter_hooks.append(adapt_0_to_42)
>>> I.__adapt__(0)
42
Hooks must either return an adapter, or None if no adapter can
be found.
Hooks can be uninstalled by removing them from the list:
.. doctest::
>>> adapter_hooks.remove(adapt_0_to_42)
>>> I.__adapt__(0)
.. [#create] The main reason we subclass `Interface` is to cause the
Python class statement to create an interface, rather
than a class.
It's possible to create interfaces by calling a special
interface class directly. Doing this, it's possible
(and, on rare occasions, useful) to create interfaces
that don't descend from `Interface`. Using this
technique is beyond the scope of this document.
.. [#factory] Classes are factories. They can be called to create
their instances. We expect that we will eventually
extend the concept of implementation to other kinds of
factories, so that we can declare the interfaces
provided by the objects created.
.. [#compat] The goal is substitutability. An object that provides an
extending interface should be substitutable for an object
that provides the extended interface. In our example, an
object that provides IBaz should be usable whereever an
object that provides IBlat is expected.
The interface implementation doesn't enforce this.
but maybe it should do some checks.
zope.interface-4.3.2/docs/Makefile 0000664 0001750 0001750 00000012730 12763206174 016071 0 ustar mg mg 0000000 0000000 # 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 ' where 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."
zope.interface-4.3.2/docs/_static/ 0000775 0001750 0001750 00000000000 12763206175 016055 5 ustar mg mg 0000000 0000000 zope.interface-4.3.2/docs/_static/.gitignore 0000664 0001750 0001750 00000000000 12763206174 020032 0 ustar mg mg 0000000 0000000