zope.configuration-4.0.3/ 0000775 0001750 0001750 00000000000 12312363233 015245 5 ustar tseaver tseaver zope.configuration-4.0.3/setup.cfg 0000664 0001750 0001750 00000000473 12312363233 017072 0 ustar tseaver tseaver [egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
[nosetests]
cover-package = zope.configuration
nocapture = 1
cover-erase = 1
ignore-files = (bad|victim|notyet).py
with-doctest = 0
where = src
[aliases]
dev = develop easy_install zope.configuration[testing]
docs = easy_install zope.configuration[docs]
zope.configuration-4.0.3/buildout.cfg 0000664 0001750 0001750 00000000302 12073042162 017547 0 ustar tseaver tseaver [buildout]
develop = .
parts = test python
[test]
recipe = zc.recipe.testrunner
eggs = zope.configuration [test]
[python]
recipe = zc.recipe.egg
eggs = zope.configuration
interpreter = python
zope.configuration-4.0.3/PKG-INFO 0000664 0001750 0001750 00000016075 12312363233 016353 0 ustar tseaver tseaver Metadata-Version: 1.0
Name: zope.configuration
Version: 4.0.3
Summary: Zope Configuration Markup Language (ZCML)
Home-page: http://pypi.python.org/pypi/zope.configuration
Author: Zope Foundation and Contributors
Author-email: zope-dev@zope.org
License: ZPL 2.1
Description: zope.configuration README
=========================
The zope configuration system provides an extensible system for
supporting various kinds of configurations.
It is based on the idea of configuration directives. Users of the
configuration system provide configuration directives in some
language that express configuration choices. The intent is that the
language be pluggable. An XML language is provided by default.
Please see http://docs.zope.org/zope.configuration/ for the documentation.
zope.configuration Changelog
============================
4.0.3 (2014-03-19)
------------------
- Added explicit support for Python 3.4.
4.0.2 (2012-12-31)
------------------
- Fleshed out PyPI Trove classifiers.
- Removed spurious declaration of 'test' dependency on ``zope.testing``.
4.0.1 (2012-11-21)
------------------
- Added support for Python 3.3.
- Removed the deprecated 'zope.configuration.stxdocs' script.
and made the 'zope.configuration.tests.conditions' helper module
(used in running Sphinx doctest snippets) Py3k compatible.
https://bugs.launchpad.net/zope.configuration/+bug/1025390
4.0.0 (2012-05-16)
------------------
- 100% unit test coverage.
- Automated build of Sphinx HTML docs and running doctest snippets via tox.
- Dropped hard testing dependency on ``zope.testing``.
- Added explicit support for PyPy.
- Added explicit support for Python 3.2.
- Dropped explicit support for Python 2.4 / 2.5.
- Added support for continuous integration using ``tox`` and ``jenkins``.
- Added ``Sphinx`` documentation.
- Added ``setup.py docs`` alias (installs ``Sphinx`` and dependencies).
- Added ``setup.py dev`` alias (runs ``setup.py develop`` plus installs
``nose`` and ``coverage``).
3.8.1 (2012-05-05)
------------------
- Fixed Python 2.4 backwards incompat (itemgetter used with multiple args);
Python 2.4 now works (at least if you use zope.schema == 3.8.1).
This is the last release which will support Python 2.4 or 2.5.
3.8.0 (2011-12-06)
------------------
- Action structures changed from tuples to dictionaries to allow for action
structure extensibility (merged chrism-dictactions branch).
3.7.4 (2011-04-03)
------------------
- Test fixes for Windows.
3.7.3 (2011-03-11)
------------------
- Correctly locate packages with a __path__ attribute but no
__file__ attribute (such as namespace packages installed with setup.py
install --single-version-externally-managed).
- Allow "info" and "includepath" to be passed optionally to context.action.
3.7.2 (2010-04-30)
------------------
- Prefer the standard libraries doctest module over zope.testing.doctest.
3.7.1 (2010-01-05)
------------------
- Jython support: use ``__builtin__`` module import rather than assuming
``__builtins__`` is available.
- Jython support: deal with the fact that the Jython SAX parser
returns attribute sets that have an empty string indicating no
namespace instead of ``None``.
- Allow ``setup.py test`` to run at least a subset of the tests that
would be run when using the zope testrunner: ``setup.py test`` runs
53 tests, while ``bin/test`` runs 156.
3.7.0 (2009-12-22)
------------------
- Adjust testing output to newer zope.schema.
- Prefer zope.testing.doctest over doctestunit.
3.6.0 (2009-04-01)
------------------
- Removed dependency of `zope.deprecation` package.
- Don't suppress deprecation warnings any more in 'zope.configuration'
package level. This makes it more likely other packages will generate
deprecation warnings now, which will allow us to remove more
outdated ones.
- Don't fail when zope.testing is not installed.
- Added missing ``processFile`` method to ``IConfigurationContext``.
It is already implemented in the mix-in class,
``zope.configuration.config.ConfigurationContext``, and used by
implementations of ``include`` and ``exclude`` directives.
3.5.0 (2009-02-26)
------------------
- Added the ``exclude`` directive to standard directives. It was
previously available via ``zc.configuration`` package and now it's
merged into ``zope.configuration``.
- Changed package's mailing list address to zope-dev at zope.org,
change "cheeseshop" to "pypi" in the package's url.
3.4.1 (2008-12-11)
------------------
- Use built-in 'set' type, rather than importin the 'sets' module,
which is deprecated in Python 2.6.
- Added support to bootstrap on Jython.
3.4.0 (2007-10-02)
------------------
- Initial release as a standalone package.
Before 3.4.0
------------
This package was part of the Zope 3 distribution and did not have its own
CHANGES.txt. For earlier changes please refer to either our subversion log or
the CHANGES.txt of earlier Zope 3 releases.
Keywords: zope configuration zcml
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Zope Public License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Framework :: Zope3
zope.configuration-4.0.3/tox.ini 0000664 0001750 0001750 00000002150 12312122003 016542 0 ustar tseaver tseaver [tox]
envlist =
# Jython support pending 2.7 support, due 2012-07-15 or so. See:
# http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html
# py26,py27,py32,jython,pypy,coverage
py26,py27,py32,py33,py34,pypy,coverage,docs
[testenv]
deps =
zope.configuration[test]
commands =
python setup.py test -q
[testenv:jython]
commands =
jython setup.py test -q
[testenv:coverage]
basepython =
python2.6
commands =
# The installed version messes up nose's test discovery / coverage reporting
# So, we uninstall that from the environment, and then install the editable
# version, before running nosetests.
pip uninstall -y zope.configuration
pip install -e .
nosetests --with-xunit --with-xcoverage
deps =
zope.interface>=3.6.0
zope.event
nose
coverage
nosexcover
[testenv:docs]
basepython =
python2.6
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 =
zope.interface>=3.6.0
zope.event
Sphinx
repoze.sphinx.autointerface
zope.configuration-4.0.3/.gitignore 0000664 0001750 0001750 00000000261 12167130113 017231 0 ustar tseaver tseaver *.pyc
__pycache__
./.installed.cfg
./bin
./develop-eggs
./eggs
./parts
*.egg-info
docs/_build
.tox
.coverage
nosetests.xml
src/coverage.xml
.installed.cfg
bin
develop-eggs
eggs
zope.configuration-4.0.3/setup.py 0000664 0001750 0001750 00000010107 12312363174 016762 0 ustar tseaver tseaver ##############################################################################
#
# 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.
#
##############################################################################
# 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.
##############################################################################
import os
from setuptools import setup, find_packages
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
def _modname(path, base, name=''):
if path == base:
return name
dirname, basename = os.path.split(path)
return _modname(dirname, base, basename + '.' + name)
def alltests():
import logging
import pkg_resources
import unittest
class NullHandler(logging.Handler):
level = 50
def emit(self, record):
pass
logging.getLogger().addHandler(NullHandler())
suite = unittest.TestSuite()
base = pkg_resources.working_set.find(
pkg_resources.Requirement.parse('zope.configuration')).location
for dirpath, dirnames, filenames in os.walk(base):
if os.path.basename(dirpath) == 'tests':
for filename in filenames:
if ( filename.endswith('.py') and
filename.startswith('test') ):
mod = __import__(
_modname(dirpath, base, os.path.splitext(filename)[0]),
{}, {}, ['*'])
suite.addTest(mod.test_suite())
return suite
TESTS_REQUIRE = []
setup(name='zope.configuration',
version = '4.0.3',
author='Zope Foundation and Contributors',
author_email='zope-dev@zope.org',
description='Zope Configuration Markup Language (ZCML)',
long_description=(
read('README.rst')
+ '\n\n' +
read('CHANGES.rst')
),
keywords = "zope configuration zcml",
classifiers = [
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: Zope Public License',
'Programming Language :: Python',
"Programming Language :: Python :: 2",
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
"Programming Language :: Python :: 3",
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Natural Language :: English',
'Operating System :: OS Independent',
'Topic :: Internet :: WWW/HTTP',
'Framework :: Zope3'],
url='http://pypi.python.org/pypi/zope.configuration',
license='ZPL 2.1',
packages=find_packages('src'),
package_dir={'': 'src'},
namespace_packages=['zope'],
extras_require={
'docs': ['Sphinx', 'repoze.sphinx.autointerface'],
'test': [],
'testing': TESTS_REQUIRE + ['nose', 'coverage'],
},
install_requires=['zope.i18nmessageid',
'zope.interface',
'zope.schema',
'setuptools',
],
include_package_data=True,
zip_safe=False,
tests_require = TESTS_REQUIRE,
test_suite='__main__.alltests',
)
zope.configuration-4.0.3/bootstrap.py 0000664 0001750 0001750 00000013066 12167130034 017641 0 ustar tseaver tseaver ##############################################################################
#
# 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
tmpeggs = tempfile.mkdtemp()
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("-v", "--version", help="use a specific zc.buildout 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"))
options, args = parser.parse_args()
######################################################################
# load/install setuptools
to_reload = False
try:
import pkg_resources
import setuptools
except ImportError:
ez = {}
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
# XXX use a more permanent ez_setup.py URL when available.
exec(urlopen('https://bitbucket.org/pypa/setuptools/raw/0.7.2/ez_setup.py'
).read(), ez)
setup_args = dict(to_dir=tmpeggs, download_delay=0)
ez['use_setuptools'](**setup_args)
if to_reload:
reload(pkg_resources)
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
cmd = [sys.executable, '-c',
'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])
setuptools_path = ws.find(
pkg_resources.Requirement.parse('setuptools')).location
requirement = 'zc.buildout'
version = options.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):
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, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 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.configuration-4.0.3/.travis.yml 0000664 0001750 0001750 00000000275 12167130027 017363 0 ustar tseaver tseaver language: python
python:
- 2.6
- 2.7
- 3.2
- 3.3
- pypy
install:
- pip install . --use-mirrors
script:
- python setup.py test -q
notifications:
email: false
zope.configuration-4.0.3/src/ 0000775 0001750 0001750 00000000000 12312363233 016034 5 ustar tseaver tseaver zope.configuration-4.0.3/src/zope.configuration.egg-info/ 0000775 0001750 0001750 00000000000 12312363233 023351 5 ustar tseaver tseaver zope.configuration-4.0.3/src/zope.configuration.egg-info/top_level.txt 0000664 0001750 0001750 00000000005 12312363233 026076 0 ustar tseaver tseaver zope
zope.configuration-4.0.3/src/zope.configuration.egg-info/SOURCES.txt 0000664 0001750 0001750 00000013425 12312363233 025242 0 ustar tseaver tseaver .gitignore
.travis.yml
CHANGES.rst
COPYRIGHT.txt
LICENSE.txt
MANIFEST.in
README.rst
bootstrap.py
buildout.cfg
setup.cfg
setup.py
tox.ini
docs/Makefile
docs/api.rst
docs/conf.py
docs/hacking.rst
docs/index.rst
docs/make.bat
docs/narr.rst
docs/_build/doctest/output.txt
docs/_build/doctrees/api.doctree
docs/_build/doctrees/environment.pickle
docs/_build/doctrees/hacking.doctree
docs/_build/doctrees/index.doctree
docs/_build/doctrees/narr.doctree
docs/_build/doctrees/api/config.doctree
docs/_build/doctrees/api/docutils.doctree
docs/_build/doctrees/api/exceptions.doctree
docs/_build/doctrees/api/fields.doctree
docs/_build/doctrees/api/interfaces.doctree
docs/_build/doctrees/api/name.doctree
docs/_build/doctrees/api/xmlconfig.doctree
docs/_build/doctrees/api/zopeconfigure.doctree
docs/_build/html/.buildinfo
docs/_build/html/api.html
docs/_build/html/genindex.html
docs/_build/html/hacking.html
docs/_build/html/index.html
docs/_build/html/narr.html
docs/_build/html/objects.inv
docs/_build/html/py-modindex.html
docs/_build/html/search.html
docs/_build/html/searchindex.js
docs/_build/html/_modules/index.html
docs/_build/html/_modules/zope/configuration/config.html
docs/_build/html/_modules/zope/configuration/docutils.html
docs/_build/html/_modules/zope/configuration/exceptions.html
docs/_build/html/_modules/zope/configuration/fields.html
docs/_build/html/_modules/zope/configuration/interfaces.html
docs/_build/html/_modules/zope/configuration/name.html
docs/_build/html/_modules/zope/configuration/xmlconfig.html
docs/_build/html/_modules/zope/configuration/zopeconfigure.html
docs/_build/html/_sources/api.txt
docs/_build/html/_sources/hacking.txt
docs/_build/html/_sources/index.txt
docs/_build/html/_sources/narr.txt
docs/_build/html/_sources/api/config.txt
docs/_build/html/_sources/api/docutils.txt
docs/_build/html/_sources/api/exceptions.txt
docs/_build/html/_sources/api/fields.txt
docs/_build/html/_sources/api/interfaces.txt
docs/_build/html/_sources/api/name.txt
docs/_build/html/_sources/api/xmlconfig.txt
docs/_build/html/_sources/api/zopeconfigure.txt
docs/_build/html/_static/ajax-loader.gif
docs/_build/html/_static/basic.css
docs/_build/html/_static/comment-bright.png
docs/_build/html/_static/comment-close.png
docs/_build/html/_static/comment.png
docs/_build/html/_static/default.css
docs/_build/html/_static/doctools.js
docs/_build/html/_static/down-pressed.png
docs/_build/html/_static/down.png
docs/_build/html/_static/file.png
docs/_build/html/_static/jquery.js
docs/_build/html/_static/minus.png
docs/_build/html/_static/plus.png
docs/_build/html/_static/pygments.css
docs/_build/html/_static/searchtools.js
docs/_build/html/_static/sidebar.js
docs/_build/html/_static/underscore.js
docs/_build/html/_static/up-pressed.png
docs/_build/html/_static/up.png
docs/_build/html/_static/websupport.js
docs/_build/html/api/config.html
docs/_build/html/api/docutils.html
docs/_build/html/api/exceptions.html
docs/_build/html/api/fields.html
docs/_build/html/api/interfaces.html
docs/_build/html/api/name.html
docs/_build/html/api/xmlconfig.html
docs/_build/html/api/zopeconfigure.html
docs/api/config.rst
docs/api/docutils.rst
docs/api/exceptions.rst
docs/api/fields.rst
docs/api/interfaces.rst
docs/api/name.rst
docs/api/xmlconfig.rst
docs/api/zopeconfigure.rst
src/coverage.xml
src/zope/__init__.py
src/zope.configuration.egg-info/PKG-INFO
src/zope.configuration.egg-info/SOURCES.txt
src/zope.configuration.egg-info/dependency_links.txt
src/zope.configuration.egg-info/namespace_packages.txt
src/zope.configuration.egg-info/not-zip-safe
src/zope.configuration.egg-info/requires.txt
src/zope.configuration.egg-info/top_level.txt
src/zope/configuration/__init__.py
src/zope/configuration/_compat.py
src/zope/configuration/config.py
src/zope/configuration/docutils.py
src/zope/configuration/exceptions.py
src/zope/configuration/fields.py
src/zope/configuration/interfaces.py
src/zope/configuration/name.py
src/zope/configuration/xmlconfig.py
src/zope/configuration/zopeconfigure.py
src/zope/configuration/tests/__init__.py
src/zope/configuration/tests/bad.py
src/zope/configuration/tests/conditions.py
src/zope/configuration/tests/conditions.zcml
src/zope/configuration/tests/directives.py
src/zope/configuration/tests/nested.py
src/zope/configuration/tests/notyet.py
src/zope/configuration/tests/sample.zcml
src/zope/configuration/tests/schema.zcml
src/zope/configuration/tests/simple.py
src/zope/configuration/tests/simple.zcml
src/zope/configuration/tests/test___init__.py
src/zope/configuration/tests/test_config.py
src/zope/configuration/tests/test_docutils.py
src/zope/configuration/tests/test_fields.py
src/zope/configuration/tests/test_name.py
src/zope/configuration/tests/test_xmlconfig.py
src/zope/configuration/tests/test_zopeconfigure.py
src/zope/configuration/tests/victim.py
src/zope/configuration/tests/excludedemo/__init__.py
src/zope/configuration/tests/excludedemo/configure.zcml
src/zope/configuration/tests/excludedemo/spam.zcml
src/zope/configuration/tests/excludedemo/sub/__init__.py
src/zope/configuration/tests/excludedemo/sub/configure.zcml
src/zope/configuration/tests/samplepackage/NamedForClass.py
src/zope/configuration/tests/samplepackage/__init__.py
src/zope/configuration/tests/samplepackage/bar.zcml
src/zope/configuration/tests/samplepackage/bar1.zcml
src/zope/configuration/tests/samplepackage/bar2.zcml
src/zope/configuration/tests/samplepackage/bar21.zcml
src/zope/configuration/tests/samplepackage/baro.zcml
src/zope/configuration/tests/samplepackage/baro2.zcml
src/zope/configuration/tests/samplepackage/baz1.zcml
src/zope/configuration/tests/samplepackage/baz2.zcml
src/zope/configuration/tests/samplepackage/baz3.zcml
src/zope/configuration/tests/samplepackage/configure.zcml
src/zope/configuration/tests/samplepackage/configure.zcml.in
src/zope/configuration/tests/samplepackage/foo.py
src/zope/configuration/tests/samplepackage/foo.zcml.in zope.configuration-4.0.3/src/zope.configuration.egg-info/PKG-INFO 0000664 0001750 0001750 00000016075 12312363233 024457 0 ustar tseaver tseaver Metadata-Version: 1.0
Name: zope.configuration
Version: 4.0.3
Summary: Zope Configuration Markup Language (ZCML)
Home-page: http://pypi.python.org/pypi/zope.configuration
Author: Zope Foundation and Contributors
Author-email: zope-dev@zope.org
License: ZPL 2.1
Description: zope.configuration README
=========================
The zope configuration system provides an extensible system for
supporting various kinds of configurations.
It is based on the idea of configuration directives. Users of the
configuration system provide configuration directives in some
language that express configuration choices. The intent is that the
language be pluggable. An XML language is provided by default.
Please see http://docs.zope.org/zope.configuration/ for the documentation.
zope.configuration Changelog
============================
4.0.3 (2014-03-19)
------------------
- Added explicit support for Python 3.4.
4.0.2 (2012-12-31)
------------------
- Fleshed out PyPI Trove classifiers.
- Removed spurious declaration of 'test' dependency on ``zope.testing``.
4.0.1 (2012-11-21)
------------------
- Added support for Python 3.3.
- Removed the deprecated 'zope.configuration.stxdocs' script.
and made the 'zope.configuration.tests.conditions' helper module
(used in running Sphinx doctest snippets) Py3k compatible.
https://bugs.launchpad.net/zope.configuration/+bug/1025390
4.0.0 (2012-05-16)
------------------
- 100% unit test coverage.
- Automated build of Sphinx HTML docs and running doctest snippets via tox.
- Dropped hard testing dependency on ``zope.testing``.
- Added explicit support for PyPy.
- Added explicit support for Python 3.2.
- Dropped explicit support for Python 2.4 / 2.5.
- Added support for continuous integration using ``tox`` and ``jenkins``.
- Added ``Sphinx`` documentation.
- Added ``setup.py docs`` alias (installs ``Sphinx`` and dependencies).
- Added ``setup.py dev`` alias (runs ``setup.py develop`` plus installs
``nose`` and ``coverage``).
3.8.1 (2012-05-05)
------------------
- Fixed Python 2.4 backwards incompat (itemgetter used with multiple args);
Python 2.4 now works (at least if you use zope.schema == 3.8.1).
This is the last release which will support Python 2.4 or 2.5.
3.8.0 (2011-12-06)
------------------
- Action structures changed from tuples to dictionaries to allow for action
structure extensibility (merged chrism-dictactions branch).
3.7.4 (2011-04-03)
------------------
- Test fixes for Windows.
3.7.3 (2011-03-11)
------------------
- Correctly locate packages with a __path__ attribute but no
__file__ attribute (such as namespace packages installed with setup.py
install --single-version-externally-managed).
- Allow "info" and "includepath" to be passed optionally to context.action.
3.7.2 (2010-04-30)
------------------
- Prefer the standard libraries doctest module over zope.testing.doctest.
3.7.1 (2010-01-05)
------------------
- Jython support: use ``__builtin__`` module import rather than assuming
``__builtins__`` is available.
- Jython support: deal with the fact that the Jython SAX parser
returns attribute sets that have an empty string indicating no
namespace instead of ``None``.
- Allow ``setup.py test`` to run at least a subset of the tests that
would be run when using the zope testrunner: ``setup.py test`` runs
53 tests, while ``bin/test`` runs 156.
3.7.0 (2009-12-22)
------------------
- Adjust testing output to newer zope.schema.
- Prefer zope.testing.doctest over doctestunit.
3.6.0 (2009-04-01)
------------------
- Removed dependency of `zope.deprecation` package.
- Don't suppress deprecation warnings any more in 'zope.configuration'
package level. This makes it more likely other packages will generate
deprecation warnings now, which will allow us to remove more
outdated ones.
- Don't fail when zope.testing is not installed.
- Added missing ``processFile`` method to ``IConfigurationContext``.
It is already implemented in the mix-in class,
``zope.configuration.config.ConfigurationContext``, and used by
implementations of ``include`` and ``exclude`` directives.
3.5.0 (2009-02-26)
------------------
- Added the ``exclude`` directive to standard directives. It was
previously available via ``zc.configuration`` package and now it's
merged into ``zope.configuration``.
- Changed package's mailing list address to zope-dev at zope.org,
change "cheeseshop" to "pypi" in the package's url.
3.4.1 (2008-12-11)
------------------
- Use built-in 'set' type, rather than importin the 'sets' module,
which is deprecated in Python 2.6.
- Added support to bootstrap on Jython.
3.4.0 (2007-10-02)
------------------
- Initial release as a standalone package.
Before 3.4.0
------------
This package was part of the Zope 3 distribution and did not have its own
CHANGES.txt. For earlier changes please refer to either our subversion log or
the CHANGES.txt of earlier Zope 3 releases.
Keywords: zope configuration zcml
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Zope Public License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Framework :: Zope3
zope.configuration-4.0.3/src/zope.configuration.egg-info/dependency_links.txt 0000664 0001750 0001750 00000000001 12312363233 027417 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope.configuration.egg-info/not-zip-safe 0000664 0001750 0001750 00000000001 12073042570 025601 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope.configuration.egg-info/namespace_packages.txt 0000664 0001750 0001750 00000000005 12312363233 027677 0 ustar tseaver tseaver zope
zope.configuration-4.0.3/src/zope.configuration.egg-info/requires.txt 0000664 0001750 0001750 00000000205 12312363233 025746 0 ustar tseaver tseaver zope.i18nmessageid
zope.interface
zope.schema
setuptools
[test]
[docs]
Sphinx
repoze.sphinx.autointerface
[testing]
nose
coverage zope.configuration-4.0.3/src/coverage.xml 0000664 0001750 0001750 00000106720 12073042765 020367 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/ 0000775 0001750 0001750 00000000000 12312363233 017011 5 ustar tseaver tseaver zope.configuration-4.0.3/src/zope/__init__.py 0000664 0001750 0001750 00000000070 12073042162 021116 0 ustar tseaver tseaver __import__('pkg_resources').declare_namespace(__name__)
zope.configuration-4.0.3/src/zope/configuration/ 0000775 0001750 0001750 00000000000 12312363233 021660 5 ustar tseaver tseaver zope.configuration-4.0.3/src/zope/configuration/name.py 0000664 0001750 0001750 00000004726 12073042162 023162 0 ustar tseaver tseaver ##############################################################################
#
# 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.
#
##############################################################################
"""Provide configuration object name resolution
"""
import os
from types import ModuleType
def resolve(name, package='zopeproducts', _silly=('__doc__',), _globals={}):
name = name.strip()
if name.startswith('.'):
name = package + name
if name.endswith('.') or name.endswith('+'):
name = name[:-1]
repeat = True
else:
repeat = False
names = name.split('.')
last = names[-1]
mod = '.'.join(names[:-1])
if not mod:
return __import__(name, _globals, _globals, _silly)
while 1:
m = __import__(mod, _globals, _globals, _silly)
try:
a = getattr(m, last)
except AttributeError:
if not repeat:
return __import__(name, _globals, _globals, _silly)
else:
if not repeat or (not isinstance(a, ModuleType)):
return a
mod += '.' + last
def getNormalizedName(name, package):
name = name.strip()
if name.startswith('.'):
name = package + name
if name.endswith('.') or name.endswith('+'):
name = name[:-1]
repeat = True
else:
repeat = False
name = name.split(".")
while len(name) > 1 and name[-1] == name[-2]:
name.pop()
repeat = 1
name = ".".join(name)
if repeat:
name += "+"
return name
def path(file='', package='zopeproducts', _silly=('__doc__',), _globals={}):
# XXX WTF? why not look for abspath before importing?
try:
package = __import__(package, _globals, _globals, _silly)
except ImportError:
norm = os.path.normpath(file)
if file and os.path.abspath(norm) == norm:
# The package didn't matter
return norm
raise
path = os.path.dirname(package.__file__)
if file:
path = os.path.join(path, file)
return path
zope.configuration-4.0.3/src/zope/configuration/fields.py 0000664 0001750 0001750 00000013024 12073042162 023477 0 ustar tseaver tseaver ##############################################################################
#
# 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.
#
##############################################################################
"""Configuration-specific schema fields
"""
import os
import re
import warnings
from zope.interface import implementer
from zope.schema import Bool as schema_Bool
from zope.schema import Field
from zope.schema import InterfaceField
from zope.schema import List
from zope.schema import Text
from zope.schema import TextLine
from zope.schema import ValidationError
from zope.schema.interfaces import IFromUnicode
from zope.configuration.exceptions import ConfigurationError
from zope.configuration.interfaces import InvalidToken
from zope.configuration._compat import u
PYIDENTIFIER_REGEX = u('\\A[a-zA-Z_]+[a-zA-Z0-9_]*\\Z')
pyidentifierPattern = re.compile(PYIDENTIFIER_REGEX)
@implementer(IFromUnicode)
class PythonIdentifier(TextLine):
"""This field describes a python identifier, i.e. a variable name.
"""
def fromUnicode(self, u):
return u.strip()
def _validate(self, value):
super(PythonIdentifier, self)._validate(value)
if pyidentifierPattern.match(value) is None:
raise ValidationError(value)
@implementer(IFromUnicode)
class GlobalObject(Field):
"""An object that can be accessed as a module global.
"""
def __init__(self, value_type=None, **kw):
self.value_type = value_type
super(GlobalObject, self).__init__(**kw)
def _validate(self, value):
super(GlobalObject, self)._validate(value)
if self.value_type is not None:
self.value_type.validate(value)
def fromUnicode(self, u):
name = str(u.strip())
# special case, mostly for interfaces
if name == '*':
return None
try:
value = self.context.resolve(name)
except ConfigurationError as v:
raise ValidationError(v)
self.validate(value)
return value
@implementer(IFromUnicode)
class GlobalInterface(GlobalObject):
"""An interface that can be accessed from a module.
"""
def __init__(self, **kw):
super(GlobalInterface, self).__init__(InterfaceField(), **kw)
@implementer(IFromUnicode)
class Tokens(List):
"""A list that can be read from a space-separated string.
"""
def fromUnicode(self, u):
u = u.strip()
if u:
vt = self.value_type.bind(self.context)
values = []
for s in u.split():
try:
v = vt.fromUnicode(s)
except ValidationError as v:
raise InvalidToken("%s in %s" % (v, u))
else:
values.append(v)
else:
values = []
self.validate(values)
return values
@implementer(IFromUnicode)
class Path(Text):
"""A file path name, which may be input as a relative path
Input paths are converted to absolute paths and normalized.
"""
def fromUnicode(self, u):
u = u.strip()
if os.path.isabs(u):
return os.path.normpath(u)
return self.context.path(u)
@implementer(IFromUnicode)
class Bool(schema_Bool):
"""A boolean value
Values may be input (in upper or lower case) as any of:
yes, no, y, n, true, false, t, or f.
"""
def fromUnicode(self, u):
u = u.lower()
if u in ('1', 'true', 'yes', 't', 'y'):
return True
if u in ('0', 'false', 'no', 'f', 'n'):
return False
raise ValidationError
@implementer(IFromUnicode)
class MessageID(Text):
"""Text string that should be translated.
When a string is converted to a message ID, it is also
recorded in the context.
"""
__factories = {}
def fromUnicode(self, u):
context = self.context
domain = getattr(context, 'i18n_domain', '')
if not domain:
domain = 'untranslated'
warnings.warn(
"You did not specify an i18n translation domain for the "\
"'%s' field in %s" % (self.getName(), context.info.file )
)
v = super(MessageID, self).fromUnicode(u)
# Check whether there is an explicit message is specified
default = None
if v.startswith('[]'):
v = v[2:].lstrip()
elif v.startswith('['):
end = v.find(']')
default = v[end+2:]
v = v[1:end]
# Convert to a message id, importing the factory, if necessary
factory = self.__factories.get(domain)
if factory is None:
import zope.i18nmessageid
factory = zope.i18nmessageid.MessageFactory(domain)
self.__factories[domain] = factory
msgid = factory(v, default)
# Record the string we got for the domain
i18n_strings = context.i18n_strings
strings = i18n_strings.get(domain)
if strings is None:
strings = i18n_strings[domain] = {}
locations = strings.setdefault(msgid, [])
locations.append((context.info.file, context.info.line))
return msgid
zope.configuration-4.0.3/src/zope/configuration/xmlconfig.py 0000664 0001750 0001750 00000044105 12073042162 024223 0 ustar tseaver tseaver ##############################################################################
#
# Copyright (c) 2001, 2002, 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.
#
##############################################################################
"""Support for the XML configuration file format
Note, for a detailed description of the way that conflicting
configuration actions are resolved, see the detailed example in
test_includeOverrides in tests/test_xmlconfig.py
"""
__docformat__ = 'restructuredtext'
import errno
from glob import glob
import logging
import os
import sys
from xml.sax import make_parser
from xml.sax.xmlreader import InputSource
from xml.sax.handler import ContentHandler, feature_namespaces
from xml.sax import SAXParseException
from zope.interface import Interface
from zope.schema import NativeStringLine
from zope.configuration.config import ConfigurationMachine
from zope.configuration.config import defineGroupingDirective
from zope.configuration.config import defineSimpleDirective
from zope.configuration.config import GroupingContextDecorator
from zope.configuration.config import GroupingStackItem
from zope.configuration.config import resolveConflicts
from zope.configuration.exceptions import ConfigurationError
from zope.configuration.fields import GlobalObject
from zope.configuration.zopeconfigure import IZopeConfigure
from zope.configuration.zopeconfigure import ZopeConfigure
from zope.configuration._compat import StringIO
from zope.configuration._compat import reraise
from zope.configuration._compat import u
logger = logging.getLogger("config")
ZCML_NAMESPACE = "http://namespaces.zope.org/zcml"
ZCML_CONDITION = (ZCML_NAMESPACE, u("condition"))
class ZopeXMLConfigurationError(ConfigurationError):
"""Zope XML Configuration error
These errors are wrappers for other errors. They include configuration
info and the wrapped error type and value.
"""
def __init__(self, info, etype, evalue):
self.info, self.etype, self.evalue = info, etype, evalue
def __str__(self):
# Only use the repr of the info. This is because we expect to
# get a parse info and we only want the location information.
return "%s\n %s: %s" % (
repr(self.info), self.etype.__name__, self.evalue)
class ZopeSAXParseException(ConfigurationError):
"""Sax Parser errors, reformatted in an emacs friendly way
"""
def __init__(self, v):
self._v = v
def __str__(self):
v = self._v
s = tuple(str(v).split(':'))
if len(s) == 4:
return 'File "%s", line %s.%s, %s' % s
else:
return str(v)
class ParserInfo(object):
"""Information about a directive based on parser data
This includes the directive location, as well as text data
contained in the directive.
"""
text = u('')
def __init__(self, file, line, column):
self.file, self.line, self.column = file, line, column
self.eline, self.ecolumn = line, column
def end(self, line, column):
self.eline, self.ecolumn = line, column
def __repr__(self):
if (self.line, self.column) == (self.eline, self.ecolumn):
return 'File "%s", line %s.%s' % (
self.file, self.line, self.column)
return 'File "%s", line %s.%s-%s.%s' % (
self.file, self.line, self.column, self.eline, self.ecolumn)
def __str__(self):
if (self.line, self.column) == (self.eline, self.ecolumn):
return 'File "%s", line %s.%s' % (
self.file, self.line, self.column)
file = self.file
if file == 'tests//sample.zcml':
# special case for testing
file = os.path.join(os.path.dirname(__file__),
'tests', 'sample.zcml')
try:
with open(file) as f:
lines = f.readlines()[self.line-1:self.eline]
except IOError:
src = " Could not read source."
else:
ecolumn = self.ecolumn
if lines[-1][ecolumn:ecolumn+2] == '': #pragma NO COVER
# We're pointing to the start of an end tag. Try to find
# the end
l = lines[-1].find('>', ecolumn)
if l >= 0:
lines[-1] = lines[-1][:l+1]
else: #pragma NO COVER
lines[-1] = lines[-1][:ecolumn+1]
column = self.column
if lines[0][:column].strip(): #pragma NO COVER
# Remove text before start if it's noy whitespace
lines[0] = lines[0][self.column:]
pad = u(' ')
blank = u('')
try:
src = blank.join([pad + l for l in lines])
except UnicodeDecodeError: #pragma NO COVER
# XXX:
# I hope so most internation zcml will use UTF-8 as encoding
# otherwise this code must be made more clever
src = blank.join([pad + l.decode('utf-8') for l in lines])
# unicode won't be printable, at least on my console
src = src.encode('ascii','replace')
return "%s\n%s" % (repr(self), src)
def characters(self, characters):
self.text += characters
class ConfigurationHandler(ContentHandler):
"""Interface to the xml parser
Translate parser events into calls into the configuration system.
"""
locator = None
def __init__(self, context, testing=False):
self.context = context
self.testing = testing
self.ignore_depth = 0
def setDocumentLocator(self, locator):
self.locator = locator
def characters(self, text):
self.context.getInfo().characters(text)
def startElementNS(self, name, qname, attrs):
if self.ignore_depth:
self.ignore_depth += 1
return
data = {}
for (ns, aname), value in attrs.items():
# NB: even though on CPython, 'ns' will be ``None`` always,
# do not change the below to "if ns is None" because Jython's
# sax parser generates attrs that have empty strings for
# the namepace instead of ``None``.
if not ns:
aname = str(aname)
data[aname] = value
if (ns, aname) == ZCML_CONDITION:
# need to process the expression to determine if we
# use this element and it's descendents
use = self.evaluateCondition(value)
if not use:
self.ignore_depth = 1
return
info = ParserInfo(
self.locator.getSystemId(),
self.locator.getLineNumber(),
self.locator.getColumnNumber(),
)
try:
self.context.begin(name, data, info)
except (KeyboardInterrupt, SystemExit): #pragma NO COVER
raise
except:
if self.testing:
raise
reraise(ZopeXMLConfigurationError(info,
sys.exc_info()[0],
sys.exc_info()[1]),
None, sys.exc_info()[2])
self.context.setInfo(info)
def evaluateCondition(self, expression):
"""Evaluate a ZCML condition.
``expression`` is a string of the form "verb arguments".
Currently the supported verbs are ``have``, ``not-have``,
``installed`` and ``not-installed``.
"""
arguments = expression.split(None)
verb = arguments.pop(0)
if verb in ('have', 'not-have'):
if not arguments:
raise ValueError("Feature name missing: %r" % expression)
if len(arguments) > 1:
raise ValueError("Only one feature allowed: %r" % expression)
if verb == 'have':
return self.context.hasFeature(arguments[0])
elif verb == 'not-have':
return not self.context.hasFeature(arguments[0])
elif verb in ('installed', 'not-installed'):
if not arguments:
raise ValueError("Package name missing: %r" % expression)
if len(arguments) > 1:
raise ValueError("Only one package allowed: %r" % expression)
try:
__import__(arguments[0])
installed = True
except ImportError:
installed = False
if verb == 'installed':
return installed
elif verb == 'not-installed':
return not installed
else:
raise ValueError("Invalid ZCML condition: %r" % expression)
def endElementNS(self, name, qname):
# If ignore_depth is set, this element will be ignored, even
# if this this decrements ignore_depth to 0.
if self.ignore_depth:
self.ignore_depth -= 1
return
info = self.context.getInfo()
info.end(
self.locator.getLineNumber(),
self.locator.getColumnNumber(),
)
try:
self.context.end()
except (KeyboardInterrupt, SystemExit): #pragma NO COVER
raise
except:
if self.testing:
raise
reraise(ZopeXMLConfigurationError(info,
sys.exc_info()[0],
sys.exc_info()[1]),
None, sys.exc_info()[2])
def processxmlfile(file, context, testing=False):
"""Process a configuration file
See examples in tests/text_xmlconfig.py
"""
src = InputSource(getattr(file, 'name', ''))
src.setByteStream(file)
parser = make_parser()
parser.setContentHandler(ConfigurationHandler(context, testing=testing))
parser.setFeature(feature_namespaces, True)
try:
parser.parse(src)
except SAXParseException:
reraise(ZopeSAXParseException(sys.exc_info()[1]),
None, sys.exc_info()[2])
def openInOrPlain(filename):
"""Open a file, falling back to filename.in.
If the requested file does not exist and filename.in does, fall
back to filename.in. If opening the original filename fails for
any other reason, allow the failure to propogate.
"""
try:
return open(filename)
except IOError as e:
code, msg = e.args
if code == errno.ENOENT:
fn = filename + ".in"
if os.path.exists(fn):
return open(fn)
raise
class IInclude(Interface):
"""The ``include``, ``includeOverrides`` and ``exclude`` directives
These directives allows you to include or preserve including of another
ZCML file in the configuration. This enables you to write configuration
files in each package and then link them together.
"""
file = NativeStringLine(
title=u("Configuration file name"),
description=u("The name of a configuration file to be included/"
"excluded, relative to the directive containing the "
"including configuration file."),
required=False,
)
files = NativeStringLine(
title=u("Configuration file name pattern"),
description=u("""
The names of multiple configuration files to be included/excluded,
expressed as a file-name pattern, relative to the directive
containing the including or excluding configuration file.
The pattern can include:
- ``*`` matches 0 or more characters
- ``?`` matches a single character
- ``[]`` matches any character in seq
- ``[!]`` matches any character not in seq
The file names are included in sorted order, where sorting is
without regard to case.
"""),
required=False,
)
package = GlobalObject(
title=u("Include or exclude package"),
description=u("""
Include or exclude the named file (or configure.zcml) from the
directory of this package.
"""),
required=False,
)
def include(_context, file=None, package=None, files=None):
"""Include a zcml file
See examples in tests/text_xmlconfig.py
"""
if files:
if file:
raise ValueError("Must specify only one of file or files")
elif not file:
file = 'configure.zcml'
# This is a tad tricky. We want to behave as a grouping directive.
context = GroupingContextDecorator(_context)
if package is not None:
context.package = package
context.basepath = None
if files:
paths = glob(context.path(files))
paths = sorted(zip([path.lower() for path in paths], paths))
paths = [path for (l, path) in paths]
else:
paths = [context.path(file)]
for path in paths:
if context.processFile(path):
with openInOrPlain(path) as f:
logger.debug("include %s" % f.name)
context.basepath = os.path.dirname(path)
context.includepath = _context.includepath + (f.name, )
_context.stack.append(GroupingStackItem(context))
processxmlfile(f, context)
assert _context.stack[-1].context is context
_context.stack.pop()
def exclude(_context, file=None, package=None, files=None):
"""Exclude a zcml file
This directive should be used before any ZML that includes
configuration you want to exclude.
"""
if files:
if file:
raise ValueError("Must specify only one of file or files")
elif not file:
file = 'configure.zcml'
context = GroupingContextDecorator(_context)
if package is not None:
context.package = package
context.basepath = None
if files:
paths = glob(context.path(files))
paths = sorted(zip([path.lower() for path in paths], paths))
paths = [path for (l, path) in paths]
else:
paths = [context.path(file)]
for path in paths:
# processFile returns a boolean indicating if the file has been
# processed or not, it *also* marks the file as having been processed,
# here the side effect is used to keep the given file from being
# processed in the future
context.processFile(path)
def includeOverrides(_context, file=None, package=None, files=None):
"""Include zcml file containing overrides
The actions in the included file are added to the context as if they
were in the including file directly.
See the detailed example in test_includeOverrides in
tests/text_xmlconfig.py
"""
# We need to remember how many actions we had before
nactions = len(_context.actions)
# We'll give the new actions this include path
includepath = _context.includepath
# Now we'll include the file. We'll munge the actions after
include(_context, file, package, files)
# Now we'll grab the new actions, resolve conflicts,
# and munge the includepath:
newactions = []
for action in resolveConflicts(_context.actions[nactions:]):
action['includepath'] = includepath
newactions.append(action)
_context.actions[nactions:] = newactions
def registerCommonDirectives(context):
# We have to use the direct definition functions to define
# a directive for all namespaces.
defineSimpleDirective(
context, "include", IInclude, include, namespace="*")
defineSimpleDirective(
context, "exclude", IInclude, exclude, namespace="*")
defineSimpleDirective(
context, "includeOverrides", IInclude, includeOverrides, namespace="*")
defineGroupingDirective(
context,
name="configure",
namespace="*",
schema=IZopeConfigure,
handler=ZopeConfigure,
)
def file(name, package=None, context=None, execute=True):
"""Execute a zcml file
"""
if context is None:
context = ConfigurationMachine()
registerCommonDirectives(context)
context.package = package
include(context, name, package)
if execute:
context.execute_actions()
return context
def string(s, context=None, name="", execute=True):
"""Execute a zcml string
"""
if context is None:
context = ConfigurationMachine()
registerCommonDirectives(context)
f = StringIO(s)
f.name = name
processxmlfile(f, context)
if execute:
context.execute_actions()
return context
##############################################################################
# Backward compatability, mainly for tests
_context = None
def _clearContext():
global _context
_context = ConfigurationMachine()
registerCommonDirectives(_context)
def _getContext():
global _context
if _context is None:
_clearContext()
try:
from zope.testing.cleanup import addCleanUp
except ImportError: #pragma NO COVER
pass
else: #pragma NO COVER
addCleanUp(_clearContext)
del addCleanUp
return _context
class XMLConfig(object):
"""Provide high-level handling of configuration files.
See examples in tests/text_xmlconfig.py
"""
def __init__(self, file_name, module=None):
context = _getContext()
include(context, file_name, module)
self.context = context
def __call__(self):
self.context.execute_actions()
def xmlconfig(file, testing=False):
context = _getContext()
processxmlfile(file, context, testing=testing)
context.execute_actions(testing=testing)
def testxmlconfig(file):
"""xmlconfig that doesn't raise configuration errors
This is useful for testing, as it doesn't mask exception types.
"""
context = _getContext()
processxmlfile(file, context, testing=True)
context.execute_actions(testing=True)
zope.configuration-4.0.3/src/zope/configuration/_compat.py 0000664 0001750 0001750 00000005667 12073042162 023671 0 ustar tseaver tseaver ##############################################################################
#
# Copyright (c) 2012 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
PY3 = sys.version_info[0] >= 3
if PY3: #pragma NO COVER
import builtins
from io import StringIO
string_types = str,
text_type = str
def b(s):
return s.encode("latin-1")
def u(s):
return s
# borrowed from 'six'
print_ = getattr(builtins, "print")
# borrowed from 'six'
def reraise(tp, value, tb=None):
if value is None:
value = tp
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value
else: #pragma NO COVER
import __builtin__ as builtins
from StringIO import StringIO
text_type = unicode
string_types = basestring,
def b(s):
return s
def u(s):
return unicode(s, "unicode_escape")
# borrowed from 'six'
def print_(*args, **kwargs):
"""The new-style print function."""
fp = kwargs.pop("file", sys.stdout)
if fp is None:
return
def write(data):
if not isinstance(data, basestring):
data = str(data)
fp.write(data)
want_unicode = False
sep = kwargs.pop("sep", None)
if sep is not None:
if isinstance(sep, unicode):
want_unicode = True
elif not isinstance(sep, str):
raise TypeError("sep must be None or a string")
end = kwargs.pop("end", None)
if end is not None:
if isinstance(end, unicode):
want_unicode = True
elif not isinstance(end, str):
raise TypeError("end must be None or a string")
if kwargs:
raise TypeError("invalid keyword arguments to print()")
if not want_unicode:
for arg in args:
if isinstance(arg, unicode):
want_unicode = True
break
if want_unicode:
newline = unicode("\n")
space = unicode(" ")
else:
newline = "\n"
space = " "
if sep is None:
sep = space
if end is None:
end = newline
for i, arg in enumerate(args):
if i:
write(sep)
write(arg)
write(end)
# borrowed from 'six'
exec("""\
def reraise(tp, value, tb=None):
raise tp, value, tb
""")
zope.configuration-4.0.3/src/zope/configuration/__init__.py 0000664 0001750 0001750 00000001513 12073042162 023770 0 ustar tseaver tseaver ##############################################################################
#
# 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 configuration support
Software that wants to provide new config directives calls
zope.configuration.meta.register.
"""
def namespace(suffix):
return 'http://namespaces.zope.org/'+suffix
zope.configuration-4.0.3/src/zope/configuration/config.py 0000664 0001750 0001750 00000104043 12073042162 023500 0 ustar tseaver tseaver ##############################################################################
#
# 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.
#
##############################################################################
"""Configuration processor
"""
from keyword import iskeyword
import operator
import os.path
import sys
from zope.interface.adapter import AdapterRegistry
from zope.interface import Interface
from zope.interface import implementer
from zope.interface import providedBy
from zope.schema import TextLine
from zope.schema import URI
from zope.schema import ValidationError
from zope.configuration.exceptions import ConfigurationError
from zope.configuration.interfaces import IConfigurationContext
from zope.configuration.interfaces import IGroupingContext
from zope.configuration.fields import GlobalInterface
from zope.configuration.fields import GlobalObject
from zope.configuration._compat import builtins
from zope.configuration._compat import reraise
from zope.configuration._compat import string_types
from zope.configuration._compat import text_type
from zope.configuration._compat import u
zopens = 'http://namespaces.zope.org/zope'
metans = 'http://namespaces.zope.org/meta'
testns = 'http://namespaces.zope.org/test'
_import_chickens = {}, {}, ("*",) # dead chickens needed by __import__
class ConfigurationContext(object):
"""Mix-in that implements IConfigurationContext
Subclasses provide a ``package`` attribute and a ``basepath``
attribute. If the base path is not None, relative paths are
converted to absolute paths using the the base path. If the
package is not none, relative imports are performed relative to
the package.
In general, the basepath and package attributes should be
consistent. When a package is provided, the base path should be
set to the path of the package directory.
Subclasses also provide an ``actions`` attribute, which is a list
of actions, an ``includepath`` attribute, and an ``info``
attribute.
The include path is appended to each action and is used when
resolving conflicts among actions. Normally, only the a
ConfigurationMachine provides the actions attribute. Decorators
simply use the actions of the context they decorate. The
``includepath`` attribute is a tuple of names. Each name is
typically the name of an included configuration file.
The ``info`` attribute contains descriptive information helpful
when reporting errors. If not set, it defaults to an empty string.
The actions attribute is a sequence of dictionaries where each dictionary
has the following keys:
- ``discriminator``, a value that identifies the action. Two actions
that have the same (non None) discriminator conflict.
- ``callable``, an object that is called to execute the action,
- ``args``, positional arguments for the action
- ``kw``, keyword arguments for the action
- ``includepath``, a tuple of include file names (defaults to ())
- ``info``, an object that has descriptive information about
the action (defaults to '')
"""
def __init__(self):
super(ConfigurationContext, self).__init__()
self._seen_files = set()
self._features = set()
def resolve(self, dottedname):
"""Resolve a dotted name to an object.
"""
name = dottedname.strip()
if not name:
raise ValueError("The given name is blank")
if name == '.':
return self.package
names = name.split('.')
if not names[-1]:
raise ValueError(
"Trailing dots are no longer supported in dotted names")
if len(names) == 1:
# Check for built-in objects
marker = object()
obj = getattr(builtins, names[0], marker)
if obj is not marker:
return obj
if not names[0]:
# Got a relative name. Convert it to abs using package info
if self.package is None:
raise ConfigurationError(
"Can't use leading dots in dotted names, "
"no package has been set.")
pnames = self.package.__name__.split(".")
pnames.append('')
while names and not names[0]:
names.pop(0)
try:
pnames.pop()
except IndexError:
raise ConfigurationError("Invalid global name", name)
names[0:0] = pnames
# Now we should have an absolute dotted name
# Split off object name:
oname, mname = names[-1], '.'.join(names[:-1])
# Import the module
if not mname:
# Just got a single name. Must me a module
mname = oname
oname = ''
try:
mod = __import__(mname, *_import_chickens)
except ImportError as v:
if sys.exc_info()[2].tb_next is not None:
# ImportError was caused deeper
raise
raise ConfigurationError(
"ImportError: Couldn't import %s, %s" % (mname, v))
if not oname:
# see not mname case above
return mod
try:
obj = getattr(mod, oname)
return obj
except AttributeError:
# No such name, maybe it's a module that we still need to import
try:
return __import__(mname+'.'+oname, *_import_chickens)
except ImportError:
if sys.exc_info()[2].tb_next is not None:
# ImportError was caused deeper
raise
raise ConfigurationError(
"ImportError: Module %s has no global %s" % (mname, oname))
def path(self, filename):
""" Compute package-relative paths.
"""
filename = os.path.normpath(filename)
if os.path.isabs(filename):
return filename
# Got a relative path, combine with base path.
# If we have no basepath, compute the base path from the package
# path.
basepath = getattr(self, 'basepath', '')
if not basepath:
if self.package is None:
basepath = os.getcwd()
else:
if hasattr(self.package, '__path__'):
basepath = self.package.__path__[0]
else:
basepath = os.path.dirname(self.package.__file__)
basepath = os.path.abspath(os.path.normpath(basepath))
self.basepath = basepath
return os.path.normpath(os.path.join(basepath, filename))
def checkDuplicate(self, filename):
"""Check for duplicate imports of the same file.
Raises an exception if this file had been processed before. This
is better than an unlimited number of conflict errors.
"""
path = self.path(filename)
if path in self._seen_files:
raise ConfigurationError('%r included more than once' % path)
self._seen_files.add(path)
def processFile(self, filename):
"""Check whether a file needs to be processed.
Return True if processing is needed and False otherwise. If
the file needs to be processed, it will be marked as
processed, assuming that the caller will procces the file if
it needs to be procssed.
""" #' <-- bow to font-lock
path = self.path(filename)
if path in self._seen_files:
return False
self._seen_files.add(path)
return True
def action(self, discriminator, callable=None, args=(), kw=None, order=0,
includepath=None, info=None, **extra):
"""Add an action with the given discriminator, callable and arguments.
For testing purposes, the callable and arguments may be omitted.
In that case, a default noop callable is used.
The discriminator must be given, but it can be None, to indicate that
the action never conflicts.
"""
if kw is None:
kw = {}
action = extra
if info is None:
info = getattr(self, 'info', '')
if includepath is None:
includepath = getattr(self, 'includepath', ())
action.update(
dict(
discriminator=discriminator,
callable=callable,
args=args,
kw=kw,
includepath=includepath,
info=info,
order=order,
)
)
self.actions.append(action)
def hasFeature(self, feature):
"""Check whether a named feature has been provided.
Initially no features are provided
"""
return feature in self._features
def provideFeature(self, feature):
"""Declare thata named feature has been provided.
See :meth:`hasFeature` for examples.
"""
self._features.add(feature)
class ConfigurationAdapterRegistry(object):
"""Simple adapter registry that manages directives as adapters
"""
def __init__(self):
super(ConfigurationAdapterRegistry, self).__init__()
self._registry = {}
# Stores tuples of form:
# (namespace, name), schema, usedIn, info, parent
self._docRegistry = []
def register(self, interface, name, factory):
r = self._registry.get(name)
if r is None:
r = AdapterRegistry()
self._registry[name] = r
r.register([interface], Interface, '', factory)
def document(self, name, schema, usedIn, handler, info, parent=None):
if isinstance(name, string_types):
name = ('', name)
self._docRegistry.append((name, schema, usedIn, handler, info, parent))
def factory(self, context, name):
r = self._registry.get(name)
if r is None:
# Try namespace-independent name
ns, n = name
r = self._registry.get(n)
if r is None:
raise ConfigurationError("Unknown directive", ns, n)
f = r.lookup1(providedBy(context), Interface)
if f is None:
raise ConfigurationError(
"The directive %s cannot be used in this context" % (name, ))
return f
@implementer(IConfigurationContext)
class ConfigurationMachine(ConfigurationAdapterRegistry, ConfigurationContext):
"""Configuration machine
"""
package = None
basepath = None
includepath = ()
info = ''
def __init__(self):
super(ConfigurationMachine, self).__init__()
self.actions = []
self.stack = [RootStackItem(self)]
self.i18n_strings = {}
_bootstrap(self)
def begin(self, __name, __data=None, __info=None, **kw):
if __data:
if kw:
raise TypeError("Can't provide a mapping object and keyword "
"arguments")
else:
__data = kw
self.stack.append(self.stack[-1].contained(__name, __data, __info))
def end(self):
self.stack.pop().finish()
def __call__(self, __name, __info=None, **__kw):
self.begin(__name, __kw, __info)
self.end()
def getInfo(self):
return self.stack[-1].context.info
def setInfo(self, info):
self.stack[-1].context.info = info
def execute_actions(self, clear=True, testing=False):
"""Execute the configuration actions.
This calls the action callables after resolving conflicts.
"""
try:
for action in resolveConflicts(self.actions):
callable = action['callable']
if callable is None:
continue
args = action['args']
kw = action['kw']
info = action['info']
try:
callable(*args, **kw)
except (KeyboardInterrupt, SystemExit): #pragma NO COVER
raise
except:
if testing:
raise
t, v, tb = sys.exc_info()
try:
reraise(ConfigurationExecutionError(t, v, info),
None, tb)
finally:
del t, v, tb
finally:
if clear:
del self.actions[:]
class ConfigurationExecutionError(ConfigurationError):
"""An error occurred during execution of a configuration action
"""
def __init__(self, etype, evalue, info):
self.etype, self.evalue, self.info = etype, evalue, info
def __str__(self): #pragma NO COVER
return "%s: %s\n in:\n %s" % (self.etype, self.evalue, self.info)
##############################################################################
# Stack items
class IStackItem(Interface):
"""Configuration machine stack items
Stack items are created when a directive is being processed.
A stack item is created for each directive use.
"""
def contained(name, data, info):
"""Begin processing a contained directive
The data are a dictionary of attribute names mapped to unicode
strings.
The info argument is an object that can be converted to a
string and that contains information about the directive.
The begin method returns the next item to be placed on the stack.
"""
def finish():
"""Finish processing a directive
"""
@implementer(IStackItem)
class SimpleStackItem(object):
"""Simple stack item
A simple stack item can't have anything added after it. It can
only be removed. It is used for simple directives and
subdirectives, which can't contain other directives.
It also defers any computation until the end of the directive
has been reached.
"""
#XXX why this *argdata hack instead of schema, data?
def __init__(self, context, handler, info, *argdata):
newcontext = GroupingContextDecorator(context)
newcontext.info = info
self.context = newcontext
self.handler = handler
self.argdata = argdata
def contained(self, name, data, info):
raise ConfigurationError("Invalid directive %s" % str(name))
def finish(self):
# We're going to use the context that was passed to us, which wasn't
# created for the directive. We want to set it's info to the one
# passed to us while we make the call, so we'll save the old one
# and restore it.
context = self.context
args = toargs(context, *self.argdata)
actions = self.handler(context, **args)
if actions:
# we allow the handler to return nothing
for action in actions:
if not isinstance(action, dict):
action = expand_action(*action) # b/c
context.action(**action)
@implementer(IStackItem)
class RootStackItem(object):
def __init__(self, context):
self.context = context
def contained(self, name, data, info):
"""Handle a contained directive
We have to compute a new stack item by getting a named adapter
for the current context object.
"""
factory = self.context.factory(self.context, name)
if factory is None:
raise ConfigurationError("Invalid directive", name)
adapter = factory(self.context, data, info)
return adapter
def finish(self):
pass
@implementer(IStackItem)
class GroupingStackItem(RootStackItem):
"""Stack item for a grouping directive
A grouping stack item is in the stack when a grouping directive is
being processed. Grouping directives group other directives.
Often, they just manage common data, but they may also take
actions, either before or after contained directives are executed.
A grouping stack item is created with a grouping directive
definition, a configuration context, and directive data.
"""
def __init__(self, context):
super(GroupingStackItem, self).__init__(context)
def __callBefore(self):
actions = self.context.before()
if actions:
for action in actions:
if not isinstance(action, dict):
action = expand_action(*action)
self.context.action(**action)
self.__callBefore = noop
def contained(self, name, data, info):
self.__callBefore()
return RootStackItem.contained(self, name, data, info)
def finish(self):
self.__callBefore()
actions = self.context.after()
if actions:
for action in actions:
if not isinstance(action, dict):
action = expand_action(*action)
self.context.action(**action)
def noop():
pass
@implementer(IStackItem)
class ComplexStackItem(object):
"""Complex stack item
A complex stack item is in the stack when a complex directive is
being processed. It only allows subdirectives to be used.
A complex stack item is created with a complex directive
definition (IComplexDirectiveContext), a configuration context,
and directive data.
"""
def __init__(self, meta, context, data, info):
newcontext = GroupingContextDecorator(context)
newcontext.info = info
self.context = newcontext
self.meta = meta
# Call the handler contructor
args = toargs(newcontext, meta.schema, data)
self.handler = self.meta.handler(newcontext, **args)
def contained(self, name, data, info):
"""Handle a subdirective
"""
# Look up the subdirective meta data on our meta object
ns, name = name
schema = self.meta.get(name)
if schema is None:
raise ConfigurationError("Invalid directive", name)
schema = schema[0] # strip off info
handler = getattr(self.handler, name)
return SimpleStackItem(self.context, handler, info, schema, data)
def finish(self):
# when we're done, we call the handler, which might return more actions
# Need to save and restore old info
# XXX why not just use callable()?
try:
actions = self.handler()
except AttributeError as v:
if v.args[0] == '__call__':
return # noncallable
raise
except TypeError:
return # non callable
if actions:
# we allow the handler to return nothing
for action in actions:
if not isinstance(action, dict):
action = expand_action(*action)
self.context.action(**action)
##############################################################################
# Helper classes
@implementer(IConfigurationContext, IGroupingContext)
class GroupingContextDecorator(ConfigurationContext):
"""Helper mix-in class for building grouping directives
See the discussion (and test) in GroupingStackItem.
"""
def __init__(self, context, **kw):
self.context = context
for name, v in kw.items():
setattr(self, name, v)
def __getattr__(self, name,
getattr=getattr, setattr=setattr):
v = getattr(self.context, name)
# cache result in self
setattr(self, name, v)
return v
def before(self):
pass
def after(self):
pass
##############################################################################
# Directive-definition
class DirectiveSchema(GlobalInterface):
"""A field that contains a global variable value that must be a schema
"""
class IDirectivesInfo(Interface):
"""Schema for the ``directives`` directive
"""
namespace = URI(
title=u("Namespace"),
description=u("The namespace in which directives' names "
"will be defined"),
)
class IDirectivesContext(IDirectivesInfo, IConfigurationContext):
pass
@implementer(IDirectivesContext)
class DirectivesHandler(GroupingContextDecorator):
"""Handler for the directives directive
This is just a grouping directive that adds a namespace attribute
to the normal directive context.
"""
class IDirectiveInfo(Interface):
"""Information common to all directive definitions have
"""
name = TextLine(
title = u("Directive name"),
description = u("The name of the directive being defined"),
)
schema = DirectiveSchema(
title = u("Directive handler"),
description = u("The dotted name of the directive handler"),
)
class IFullInfo(IDirectiveInfo):
"""Information that all top-level directives (not subdirectives) have
"""
handler = GlobalObject(
title = u("Directive handler"),
description = u("The dotted name of the directive handler"),
)
usedIn = GlobalInterface(
title = u("The directive types the directive can be used in"),
description = u("The interface of the directives that can contain "
"the directive"
),
default = IConfigurationContext,
)
class IStandaloneDirectiveInfo(IDirectivesInfo, IFullInfo):
"""Info for full directives defined outside a directives directives
"""
def defineSimpleDirective(context, name, schema, handler,
namespace='', usedIn=IConfigurationContext):
"""Define a simple directive
Define and register a factory that invokes the simple directive
and returns a new stack item, which is always the same simple stack item.
If the namespace is '*', the directive is registered for all namespaces.
"""
namespace = namespace or context.namespace
if namespace != '*':
name = namespace, name
def factory(context, data, info):
return SimpleStackItem(context, handler, info, schema, data)
factory.schema = schema
context.register(usedIn, name, factory)
context.document(name, schema, usedIn, handler, context.info)
def defineGroupingDirective(context, name, schema, handler,
namespace='', usedIn=IConfigurationContext):
"""Define a grouping directive
Define and register a factory that sets up a grouping directive.
If the namespace is '*', the directive is registered for all namespaces.
"""
namespace = namespace or context.namespace
if namespace != '*':
name = namespace, name
def factory(context, data, info):
args = toargs(context, schema, data)
newcontext = handler(context, **args)
newcontext.info = info
return GroupingStackItem(newcontext)
factory.schema = schema
context.register(usedIn, name, factory)
context.document(name, schema, usedIn, handler, context.info)
class IComplexDirectiveContext(IFullInfo, IConfigurationContext):
pass
@implementer(IComplexDirectiveContext)
class ComplexDirectiveDefinition(GroupingContextDecorator, dict):
"""Handler for defining complex directives
See the description and tests for ComplexStackItem.
"""
def before(self):
def factory(context, data, info):
return ComplexStackItem(self, context, data, info)
factory.schema = self.schema
self.register(self.usedIn, (self.namespace, self.name), factory)
self.document((self.namespace, self.name), self.schema, self.usedIn,
self.handler, self.info)
def subdirective(context, name, schema):
context.document((context.namespace, name), schema, context.usedIn,
getattr(context.handler, name, context.handler),
context.info, context.context)
context.context[name] = schema, context.info
##############################################################################
# Features
class IProvidesDirectiveInfo(Interface):
"""Information for a directive"""
feature = TextLine(
title = u("Feature name"),
description = u("""The name of the feature being provided
You can test available features with zcml:condition="have featurename".
"""),
)
def provides(context, feature):
"""Declare that a feature is provided in context.
"""
if len(feature.split()) > 1:
raise ValueError("Only one feature name allowed")
context.provideFeature(feature)
##############################################################################
# Argument conversion
def toargs(context, schema, data):
"""Marshal data to an argument dictionary using a schema
Names that are python keywords have an underscore added as a
suffix in the schema and in the argument list, but are used
without the underscore in the data.
The fields in the schema must all implement IFromUnicode.
All of the items in the data must have corresponding fields in the
schema unless the schema has a true tagged value named
'keyword_arguments'.
"""
data = dict(data)
args = {}
for name, field in schema.namesAndDescriptions(True):
field = field.bind(context)
n = name
if n.endswith('_') and iskeyword(n[:-1]):
n = n[:-1]
s = data.get(n, data)
if s is not data:
s = text_type(s)
del data[n]
try:
args[str(name)] = field.fromUnicode(s)
except ValidationError as v:
reraise(ConfigurationError("Invalid value for", n, str(v)),
None, sys.exc_info()[2])
elif field.required:
# if the default is valid, we can use that:
default = field.default
try:
field.validate(default)
except ValidationError:
raise ConfigurationError("Missing parameter:", n)
args[str(name)] = default
if data:
# we had data left over
try:
keyword_arguments = schema.getTaggedValue('keyword_arguments')
except KeyError:
keyword_arguments = False
if not keyword_arguments:
raise ConfigurationError("Unrecognized parameters:", *data)
for name in data:
args[str(name)] = data[name]
return args
##############################################################################
# Conflict resolution
def expand_action(discriminator, callable=None, args=(), kw=None,
includepath=(), info=None, order=0, **extra):
if kw is None:
kw = {}
action = extra
action.update(
dict(
discriminator=discriminator,
callable=callable,
args=args,
kw=kw,
includepath=includepath,
info=info,
order=order,
)
)
return action
def resolveConflicts(actions):
"""Resolve conflicting actions
Given an actions list, identify and try to resolve conflicting actions.
Actions conflict if they have the same non-None discriminator.
Conflicting actions can be resolved if the include path of one of
the actions is a prefix of the includepaths of the other
conflicting actions and is unequal to the include paths in the
other conflicting actions.
"""
# organize actions by discriminators
unique = {}
output = []
for i, action in enumerate(actions):
if not isinstance(action, dict):
# old-style tuple action
action = expand_action(*action)
# "order" is an integer grouping. Actions in a lower order will be
# executed before actions in a higher order. Within an order,
# actions are executed sequentially based on original action ordering
# ("i").
order = action['order'] or 0
discriminator = action['discriminator']
# "ainfo" is a tuple of (order, i, action) where "order" is a
# user-supplied grouping, "i" is an integer expressing the relative
# position of this action in the action list being resolved, and
# "action" is an action dictionary. The purpose of an ainfo is to
# associate an "order" and an "i" with a particular action; "order"
# and "i" exist for sorting purposes after conflict resolution.
ainfo = (order, i, action)
if discriminator is None:
# The discriminator is None, so this action can never conflict.
# We can add it directly to the result.
output.append(ainfo)
continue
L = unique.setdefault(discriminator, [])
L.append(ainfo)
# Check for conflicts
conflicts = {}
for discriminator, ainfos in unique.items():
# We use (includepath, order, i) as a sort key because we need to
# sort the actions by the paths so that the shortest path with a
# given prefix comes first. The "first" action is the one with the
# shortest include path. We break sorting ties using "order", then
# "i".
def bypath(ainfo):
path, order, i = ainfo[2]['includepath'], ainfo[0], ainfo[1]
return path, order, i
ainfos.sort(key=bypath)
ainfo, rest = ainfos[0], ainfos[1:]
output.append(ainfo)
_, _, action = ainfo
basepath, baseinfo, discriminator = (action['includepath'],
action['info'],
action['discriminator'])
for _, _, action in rest:
includepath = action['includepath']
# Test whether path is a prefix of opath
if (includepath[:len(basepath)] != basepath # not a prefix
or includepath == basepath):
L = conflicts.setdefault(discriminator, [baseinfo])
L.append(action['info'])
if conflicts:
raise ConfigurationConflictError(conflicts)
# Sort conflict-resolved actions by (order, i) and return them.
return [x[2] for x in sorted(output, key=operator.itemgetter(0, 1))]
class ConfigurationConflictError(ConfigurationError):
def __init__(self, conflicts):
self._conflicts = conflicts
def __str__(self): #pragma NO COVER
r = ["Conflicting configuration actions"]
items = self._conflicts.items()
items.sort()
for discriminator, infos in items:
r.append(" For: %s" % (discriminator, ))
for info in infos:
for line in text_type(info).rstrip().split(u('\n')):
r.append(u(" ") + line)
return "\n".join(r)
##############################################################################
# Bootstap code
def _bootstrap(context):
# Set enough machinery to register other directives
# Define the directive (simple directive) directive by calling it's
# handler directly
info = 'Manually registered in zope/configuration/config.py'
context.info = info
defineSimpleDirective(
context,
namespace=metans, name='directive',
schema=IStandaloneDirectiveInfo,
handler=defineSimpleDirective)
context.info = ''
# OK, now that we have that, we can use the machine to define the
# other directives. This isn't the easiest way to proceed, but it lets
# us eat our own dogfood. :)
# Standalone groupingDirective
context((metans, 'directive'),
info,
name='groupingDirective',
namespace=metans,
handler="zope.configuration.config.defineGroupingDirective",
schema="zope.configuration.config.IStandaloneDirectiveInfo"
)
# Now we can use the grouping directive to define the directives directive
context((metans, 'groupingDirective'),
info,
name='directives',
namespace=metans,
handler="zope.configuration.config.DirectivesHandler",
schema="zope.configuration.config.IDirectivesInfo"
)
# directive and groupingDirective inside directives
context((metans, 'directive'),
info,
name='directive',
namespace=metans,
usedIn="zope.configuration.config.IDirectivesContext",
handler="zope.configuration.config.defineSimpleDirective",
schema="zope.configuration.config.IFullInfo"
)
context((metans, 'directive'),
info,
name='groupingDirective',
namespace=metans,
usedIn="zope.configuration.config.IDirectivesContext",
handler="zope.configuration.config.defineGroupingDirective",
schema="zope.configuration.config.IFullInfo"
)
# Setup complex directive directive, both standalone, and in
# directives directive
context((metans, 'groupingDirective'),
info,
name='complexDirective',
namespace=metans,
handler="zope.configuration.config.ComplexDirectiveDefinition",
schema="zope.configuration.config.IStandaloneDirectiveInfo"
)
context((metans, 'groupingDirective'),
info,
name='complexDirective',
namespace=metans,
usedIn="zope.configuration.config.IDirectivesContext",
handler="zope.configuration.config.ComplexDirectiveDefinition",
schema="zope.configuration.config.IFullInfo"
)
# Finally, setup subdirective directive
context((metans, 'directive'),
info,
name='subdirective',
namespace=metans,
usedIn="zope.configuration.config.IComplexDirectiveContext",
handler="zope.configuration.config.subdirective",
schema="zope.configuration.config.IDirectiveInfo"
)
# meta:provides
context((metans, 'directive'),
info,
name='provides',
namespace=metans,
handler="zope.configuration.config.provides",
schema="zope.configuration.config.IProvidesDirectiveInfo"
)
zope.configuration-4.0.3/src/zope/configuration/docutils.py 0000664 0001750 0001750 00000004664 12073042162 024071 0 ustar tseaver tseaver ##############################################################################
#
# 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.
#
##############################################################################
"""Helper Utility to wrap a text to a set width of characters
"""
__docformat__ = 'restructuredtext'
import re
para_sep = re.compile('\n{2,}')
whitespace = re.compile('[ \t\n\r]+')
def wrap(text, width=78, indent=0):
"""Makes sure that we keep a line length of a certain width.
"""
paras = para_sep.split(text.strip())
new_paras = []
for par in paras:
words= filter(None, whitespace.split(par))
lines = []
line = []
length = indent
for word in words:
if length + len(word) <= width:
line.append(word)
length += len(word) + 1
else:
lines.append(' '*indent + ' '.join(line))
line = [word]
length = len(word) + 1 + indent
lines.append(' '*indent + ' '.join(line))
new_paras.append('\n'.join(lines))
return '\n\n'.join(new_paras) + '\n\n'
def makeDocStructures(context):
"""Creates two structures that provide a friendly format for
documentation.
'namespaces' is a dictionary that maps namespaces to a directives
dictionary with the key being the name of the directive and the value is a
tuple: (schema, handler, info).
'subdirs' maps a (namespace, name) pair to a list of subdirectives that
have the form (namespace, name, schema, info).
"""
namespaces = {}
subdirs = {}
registry = context._docRegistry
for (namespace, name), schema, usedIn, handler, info, parent in registry:
if not parent:
ns_entry = namespaces.setdefault(namespace, {})
ns_entry[name] = (schema, handler, info)
else:
sd_entry = subdirs.setdefault((parent.namespace, parent.name), [])
sd_entry.append((namespace, name, schema, handler, info))
return namespaces, subdirs
zope.configuration-4.0.3/src/zope/configuration/interfaces.py 0000664 0001750 0001750 00000010726 12073042162 024362 0 ustar tseaver tseaver ##############################################################################
#
# 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 Configuration (ZCML) interfaces
"""
from zope.interface import Interface
from zope.schema import BytesLine
from zope.schema.interfaces import ValidationError
from zope.configuration._compat import u
class InvalidToken(ValidationError):
"""Invaid token in list."""
class IConfigurationContext(Interface):
"""Configuration Context
The configuration context manages information about the state of
the configuration system, such as the package containing the
configuration file. More importantly, it provides methods for
importing objects and opening files relative to the package.
"""
package = BytesLine(
title=u("The current package name"),
description=u("""\
This is the name of the package containing the configuration
file being executed. If the configuration file was not
included by package, then this is None.
"""),
required=False,
)
def resolve(dottedname):
"""Resolve a dotted name to an object
A dotted name is constructed by concatenating a dotted module
name with a global name within the module using a dot. For
example, the object named "spam" in the foo.bar module has a
dotted name of foo.bar.spam. If the current package is a
prefix of a dotted name, then the package name can be relaced
with a leading dot, So, for example, if the configuration file
is in the foo package, then the dotted name foo.bar.spam can
be shortened to .bar.spam.
If the current package is multiple levels deep, multiple
leading dots can be used to refer to higher-level modules.
For example, if the current package is x.y.z, the dotted
object name ..foo refers to x.y.foo.
"""
def path(filename):
"""Compute a full file name for the given file
If the filename is relative to the package, then the returned
name will include the package path, otherwise, the original
file name is returned.
"""
def checkDuplicate(filename):
"""Check for duplicate imports of the same file.
Raises an exception if this file had been processed before. This
is better than an unlimited number of conflict errors.
"""
def processFile(filename):
"""Check whether a file needs to be processed.
Return True if processing is needed and False otherwise. If
the file needs to be processed, it will be marked as
processed, assuming that the caller will procces the file if
it needs to be procssed.
"""
def action(discriminator, callable, args=(), kw={}, order=0,
includepath=None, info=None):
"""Record a configuration action
The job of most directives is to compute actions for later
processing. The action method is used to record those
actions. The discriminator is used to to find actions that
conflict. Actions conflict if they have the same
discriminator. The exception to this is the special case of
the discriminator with the value None. An actions with a
discriminator of None never conflicts with other actions. This
is possible to add an order argument to crudely control the
order of execution. 'info' is optional source line information,
'includepath' is None (the default) or a tuple of include paths for
this action.
"""
def provideFeature(name):
"""Record that a named feature is available in this context."""
def hasFeature(name):
"""Check whether a named feature is available in this context."""
class IGroupingContext(Interface):
def before():
"""Do something before processing nested directives
"""
def after():
"""Do something after processing nested directives
"""
zope.configuration-4.0.3/src/zope/configuration/tests/ 0000775 0001750 0001750 00000000000 12312363233 023022 5 ustar tseaver tseaver zope.configuration-4.0.3/src/zope/configuration/tests/simple.zcml 0000664 0001750 0001750 00000001563 12073042162 025206 0 ustar tseaver tseaver
Register a file with the file registry
Blah blah blah :)
Describes how to implement a simple directive
Shows the ZCML directives needed to register a simple directive.
Also show some usage examples,
zope.configuration-4.0.3/src/zope/configuration/tests/sample.zcml 0000664 0001750 0001750 00000000443 12073042162 025172 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/ 0000775 0001750 0001750 00000000000 12312363233 025617 5 ustar tseaver tseaver zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/bar21.zcml 0000664 0001750 0001750 00000000170 12073042162 027412 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/bar.zcml 0000664 0001750 0001750 00000000134 12073042162 027247 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/NamedForClass.py 0000664 0001750 0001750 00000000146 12073042162 030652 0 ustar tseaver tseaver # Test the "repeat" feature of zope.configuration.name.resolve.
class NamedForClass(object):
pass
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/__init__.py 0000664 0001750 0001750 00000000075 12073042162 027731 0 ustar tseaver tseaver #
# This file is necessary to make this directory a package.
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/foo.py 0000664 0001750 0001750 00000002450 12073042162 026754 0 ustar tseaver tseaver ##############################################################################
#
# 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.
#
##############################################################################
"""Sample module used for testing
"""
from zope.interface import Interface
from zope import schema
data = []
class S1(Interface):
x = schema.BytesLine()
y = schema.Int()
class stuff(object):
def __init__(self, args, info, basepath, package, includepath):
(self.args, self.info, self.basepath, self.package, self.includepath
) = args, info, basepath, package, includepath
def handler(_context, **kw):
args = sorted(kw.items())
args = tuple(args)
discriminator = args
args = (stuff(args, _context.info, _context.basepath, _context.package,
_context.includepath), )
_context.action(discriminator, data.append, args)
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/baz3.zcml 0000664 0001750 0001750 00000000237 12073042162 027346 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/bar2.zcml 0000664 0001750 0001750 00000000231 12073042162 027327 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/bar1.zcml 0000664 0001750 0001750 00000000204 12073042162 027326 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/baro.zcml 0000664 0001750 0001750 00000000145 12073042162 027430 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/configure.zcml.in 0000664 0001750 0001750 00000000101 12073042162 031063 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/configure.zcml 0000664 0001750 0001750 00000000673 12073042162 030474 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/baz2.zcml 0000664 0001750 0001750 00000000237 12073042162 027345 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/baz1.zcml 0000664 0001750 0001750 00000000634 12073042162 027345 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/baro2.zcml 0000664 0001750 0001750 00000000144 12073042162 027511 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/samplepackage/foo.zcml.in 0000664 0001750 0001750 00000000672 12073042162 027702 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/__init__.py 0000664 0001750 0001750 00000000075 12073042162 025134 0 ustar tseaver tseaver #
# This file is necessary to make this directory a package.
zope.configuration-4.0.3/src/zope/configuration/tests/test_docutils.py 0000664 0001750 0001750 00000011203 12073042162 026255 0 ustar tseaver tseaver ##############################################################################
#
# 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 for zope.configuration.docutils
"""
import unittest
class Test_wrap(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.docutils import wrap
return wrap(*args, **kw)
def test_empty(self):
self.assertEqual(self._callFUT(''), '\n\n')
def test_only_whitespace(self):
self.assertEqual(self._callFUT(' \t\n\r'), '\n\n')
def test_single_paragraphs(self):
self.assertEqual(
self._callFUT('abcde fghij klmno pqrst uvwxy', 10, 3),
' abcde\n fghij\n klmno\n pqrst\n uvwxy\n\n')
def test_multiple_paragraphs(self):
self.assertEqual(
self._callFUT('abcde fghij klmno\n\npqrst uvwxy', 10, 3),
' abcde\n fghij\n klmno\n\n pqrst\n uvwxy\n\n')
class Test_makeDocStructures(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.docutils import makeDocStructures
return makeDocStructures(*args, **kw)
def _makeContext(self):
class _Context(object):
def __init__(self):
self._docRegistry = []
return _Context()
def test_empty(self):
context = self._makeContext()
namespaces, subdirs = self._callFUT(context)
self.assertEqual(len(namespaces), 0)
self.assertEqual(len(subdirs), 0)
def test_wo_parents(self):
from zope.interface import Interface
class ISchema(Interface):
pass
class IUsedIn(Interface):
pass
NS = 'http://namespace.example.com/main'
NS2 = 'http://namespace.example.com/other'
def _one():
pass
def _two():
pass
def _three():
pass
context = self._makeContext()
context._docRegistry.append(
((NS, 'one'), ISchema, IUsedIn, _one, 'ONE', None))
context._docRegistry.append(
((NS2, 'two'), ISchema, IUsedIn, _two, 'TWO', None))
context._docRegistry.append(
((NS, 'three'), ISchema, IUsedIn, _three, 'THREE', None))
namespaces, subdirs = self._callFUT(context)
self.assertEqual(len(namespaces), 2)
self.assertEqual(namespaces[NS], {'one': (ISchema, _one, 'ONE'),
'three': (ISchema, _three, 'THREE')})
self.assertEqual(namespaces[NS2], {'two': (ISchema, _two, 'TWO')})
self.assertEqual(len(subdirs), 0)
def test_w_parents(self):
from zope.interface import Interface
class ISchema(Interface):
pass
class IUsedIn(Interface):
pass
PNS = 'http://namespace.example.com/parent'
NS = 'http://namespace.example.com/main'
NS2 = 'http://namespace.example.com/other'
def _one():
pass
def _two():
pass
def _three():
pass
class Parent(object):
namespace = PNS
name = 'parent'
parent1 = Parent()
parent2 = Parent()
parent2.name = 'parent2'
context = self._makeContext()
context._docRegistry.append(
((NS, 'one'), ISchema, IUsedIn, _one, 'ONE', parent1))
context._docRegistry.append(
((NS2, 'two'), ISchema, IUsedIn, _two, 'TWO', parent2))
context._docRegistry.append(
((NS, 'three'), ISchema, IUsedIn, _three, 'THREE', parent1))
namespaces, subdirs = self._callFUT(context)
self.assertEqual(len(namespaces), 0)
self.assertEqual(len(subdirs), 2)
self.assertEqual(subdirs[(PNS, 'parent')],
[(NS, 'one', ISchema, _one, 'ONE'),
(NS, 'three', ISchema, _three, 'THREE')])
self.assertEqual(subdirs[(PNS, 'parent2')],
[(NS2, 'two', ISchema, _two, 'TWO')])
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(Test_wrap),
unittest.makeSuite(Test_makeDocStructures),
))
zope.configuration-4.0.3/src/zope/configuration/tests/test_zopeconfigure.py 0000664 0001750 0001750 00000002645 12073042162 027320 0 ustar tseaver tseaver ##############################################################################
#
# 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 zope.configuration.xmlconfig.
"""
import unittest
class ZopeConfigureTests(unittest.TestCase):
def _getTargetClass(self):
from zope.configuration.xmlconfig import ZopeConfigure
return ZopeConfigure
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_ctor_wo_package(self):
zc = self._makeOne(Context())
self.assertEqual(zc.basepath, None)
def test_ctor_w_package(self):
import os
import zope.configuration.tests as zct
zc = self._makeOne(Context(), package=zct)
self.assertEqual(zc.basepath, os.path.dirname(zct.__file__))
class Context(object):
basepath = None
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(ZopeConfigureTests),
))
zope.configuration-4.0.3/src/zope/configuration/tests/directives.py 0000664 0001750 0001750 00000004732 12073042162 025542 0 ustar tseaver tseaver ##############################################################################
#
# 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 directives
"""
from zope.interface import Interface
from zope.interface import implementer
from zope.schema import BytesLine
from zope.schema import Text
from zope.configuration.config import GroupingContextDecorator
from zope.configuration.interfaces import IConfigurationContext
from zope.configuration.fields import GlobalObject
from zope.configuration._compat import u
class F(object):
def __repr__(self):
return 'f'
def __call__(self, *a, **k):
pass
f = F()
class ISimple(Interface):
a = Text()
b = Text(required=False)
c = BytesLine()
def simple(context, a=None, c=None, b=u("xxx")):
return [(('simple', a, b, c), f, (a, b, c))]
def newsimple(context, a, c, b=u("xxx")):
context.action(('newsimple', a, b, c), f, (a, b, c))
class IPackaged(Interface):
package = GlobalObject()
class IPackagedContext(IPackaged, IConfigurationContext):
pass
@implementer(IPackagedContext)
class Packaged(GroupingContextDecorator):
pass
class IFactory(Interface):
factory = GlobalObject()
def factory(context, factory):
context.action(('factory', 1,2), factory)
class Complex(object):
def __init__(self, context, a, c, b=u("xxx")):
self.a, self.b, self.c = a, b, c
context.action("Complex.__init__")
def factory(self, context, factory):
return [(('Complex.factory', 1,2), factory, (self.a, ))]
def factory2(self, context, factory):
return [(('Complex.factory', 1,2), factory, (self.a, ))]
def __call__(self):
return [(('Complex', 1,2), f, (self.b, self.c))]
class Ik(Interface):
for_ = BytesLine()
class_ = BytesLine()
x = BytesLine()
def k(context, for_, class_, x):
context.action(('k', for_), f, (for_, class_, x))
def kkw(context, for_, class_, x, **kw):
context.action(('k', for_), f, (for_, class_, x, kw))
zope.configuration-4.0.3/src/zope/configuration/tests/conditions.py 0000664 0001750 0001750 00000002303 12073042162 025542 0 ustar tseaver tseaver ##############################################################################
#
# 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.
#
##############################################################################
""" Enable "Making specific directives condition" section of narrative docs.
"""
from zope.interface import Interface
from zope.schema import Id
from zope.configuration._compat import u
class IRegister(Interface):
"""Trivial sample registry."""
id = Id(
title=u("Identifier"),
description=u("Some identifier that can be checked."),
required=True,
)
registry = []
def register(context, id):
context.action(discriminator=('Register', id),
callable=registry.append,
args=(id,)
)
zope.configuration-4.0.3/src/zope/configuration/tests/notyet.py 0000664 0001750 0001750 00000000046 12073042162 024715 0 ustar tseaver tseaver # We don't get imported automagically
zope.configuration-4.0.3/src/zope/configuration/tests/test_fields.py 0000664 0001750 0001750 00000026115 12073042162 025705 0 ustar tseaver tseaver ##############################################################################
#
# Copyright (c) 20!2 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 zope.configuration.fields.
"""
import unittest
class _ConformsToIFromUnicode(object):
def test_class_conforms_to_IFromUnicode(self):
from zope.interface.verify import verifyClass
from zope.schema.interfaces import IFromUnicode
verifyClass(IFromUnicode, self._getTargetClass())
def test_instance_conforms_to_IFromUnicode(self):
from zope.interface.verify import verifyObject
from zope.schema.interfaces import IFromUnicode
verifyObject(IFromUnicode, self._makeOne())
class PythonIdentifierTests(unittest.TestCase, _ConformsToIFromUnicode):
def _getTargetClass(self):
from zope.configuration.fields import PythonIdentifier
return PythonIdentifier
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_fromUnicode_empty(self):
pi = self._makeOne()
self.assertEqual(pi.fromUnicode(''), '')
def test_fromUnicode_normal(self):
pi = self._makeOne()
self.assertEqual(pi.fromUnicode('normal'), 'normal')
def test_fromUnicode_strips_ws(self):
pi = self._makeOne()
self.assertEqual(pi.fromUnicode(' '), '')
self.assertEqual(pi.fromUnicode(' normal '), 'normal')
def test__validate_miss(self):
from zope.schema import ValidationError
from zope.configuration._compat import u
pi = self._makeOne()
self.assertRaises(ValidationError,
pi._validate, u('not-an-identifier'))
def test__validate_hit(self):
from zope.configuration._compat import u
pi = self._makeOne()
pi._validate(u('is_an_identifier'))
class GlobalObjectTests(unittest.TestCase, _ConformsToIFromUnicode):
def _getTargetClass(self):
from zope.configuration.fields import GlobalObject
return GlobalObject
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test__validate_wo_value_type(self):
from zope.configuration._compat import u
from zope.configuration._compat import b
go = self._makeOne(value_type=None)
for value in [0, 0.0, (), [], set(), frozenset(), u(''), b('')]:
go._validate(value) #noraise
def test__validate_w_value_type(self):
from zope.schema import Text
from zope.schema.interfaces import WrongType
from zope.configuration._compat import u
from zope.configuration._compat import b
go = self._makeOne(value_type=Text())
go.validate(u(''))
for value in [0, 0.0, (), [], set(), frozenset(), b('')]:
self.assertRaises(WrongType, go._validate, value)
def test_fromUnicode_w_star_and_extra_ws(self):
go = self._makeOne()
self.assertEqual(go.fromUnicode(' * '), None)
def test_fromUnicode_w_resolve_fails(self):
from zope.schema import ValidationError
from zope.configuration.config import ConfigurationError
class Context(object):
def resolve(self, name):
self._resolved = name
raise ConfigurationError()
go = self._makeOne()
context = Context()
bound = go.bind(context)
self.assertRaises(ValidationError, bound.fromUnicode, 'tried')
self.assertEqual(context._resolved, 'tried')
def test_fromUnicode_w_resolve_success(self):
_target = object()
class Context(object):
def resolve(self, name):
self._resolved = name
return _target
go = self._makeOne()
context = Context()
bound = go.bind(context)
found = bound.fromUnicode('tried')
self.assertTrue(found is _target)
self.assertEqual(context._resolved, 'tried')
def test_fromUnicode_w_resolve_but_validation_fails(self):
from zope.schema import Text
from zope.schema import ValidationError
_target = object()
class Context(object):
def resolve(self, name):
self._resolved = name
return _target
go = self._makeOne(value_type=Text())
context = Context()
bound = go.bind(context)
self.assertRaises(ValidationError, bound.fromUnicode, 'tried')
self.assertEqual(context._resolved, 'tried')
class GlobalInterfaceTests(unittest.TestCase, _ConformsToIFromUnicode):
def _getTargetClass(self):
from zope.configuration.fields import GlobalInterface
return GlobalInterface
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_ctor(self):
from zope.schema import InterfaceField
gi = self._makeOne()
self.assertTrue(isinstance(gi.value_type, InterfaceField))
class TokensTests(unittest.TestCase, _ConformsToIFromUnicode):
def _getTargetClass(self):
from zope.configuration.fields import Tokens
return Tokens
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_fromUnicode_empty(self):
tok = self._makeOne()
self.assertEqual(tok.fromUnicode(''), [])
def test_fromUnicode_strips_ws(self):
from zope.schema import Text
from zope.configuration._compat import u
tok = self._makeOne(value_type=Text())
context = object()
self.assertEqual(tok.fromUnicode(u(' one two three ')),
[u('one'), u('two'), u('three')])
def test_fromUnicode_invalid(self):
from zope.schema import Int
from zope.configuration.interfaces import InvalidToken
from zope.configuration._compat import u
tok = self._makeOne(value_type=Int(min=0))
context = object()
self.assertRaises(InvalidToken,
tok.fromUnicode, u(' 1 -1 3 '))
class PathTests(unittest.TestCase, _ConformsToIFromUnicode):
def _getTargetClass(self):
from zope.configuration.fields import Path
return Path
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_fromUnicode_absolute(self):
import os
path = self._makeOne()
self.assertEqual(path.fromUnicode('/'), os.path.normpath('/'))
def test_fromUnicode_relative(self):
class Context(object):
def path(self, value):
self._pathed = value
return '/hard/coded'
context = Context()
path = self._makeOne()
bound = path.bind(context)
self.assertEqual(bound.fromUnicode('relative/path'), '/hard/coded')
self.assertEqual(context._pathed, 'relative/path')
class BoolTests(unittest.TestCase, _ConformsToIFromUnicode):
def _getTargetClass(self):
from zope.configuration.fields import Bool
return Bool
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_fromUnicode_w_true_values(self):
values = ['1', 'true', 'yes', 't', 'y']
values += [x.upper() for x in values]
bo = self._makeOne()
for value in values:
self.assertEqual(bo.fromUnicode(value), True)
def test_fromUnicode_w_false_values(self):
values = ['0', 'false', 'no', 'f', 'n']
values += [x.upper() for x in values]
bo = self._makeOne()
for value in values:
self.assertEqual(bo.fromUnicode(value), False)
def test_fromUnicode_w_invalid(self):
from zope.schema import ValidationError
bo = self._makeOne()
self.assertRaises(ValidationError, bo.fromUnicode, 'notvalid')
class MessageIDTests(unittest.TestCase, _ConformsToIFromUnicode):
def _getTargetClass(self):
from zope.configuration.fields import MessageID
return MessageID
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def _makeContext(self, domain='testing_domain'):
class Info(object):
file = 'test_file'
line = 42
class Context(object):
i18n_domain = domain
def __init__(self):
self.i18n_strings = {}
self.info = Info()
return Context()
def test_wo_domain(self):
import warnings
from zope.configuration._compat import u
mid = self._makeOne()
context = self._makeContext(None)
bound = mid.bind(context)
with warnings.catch_warnings(record=True) as log:
msgid = bound.fromUnicode(u('testing'))
self.assertEqual(len(log), 1)
self.assertTrue(str(log[0].message).startswith(
'You did not specify an i18n translation domain'))
self.assertEqual(msgid, 'testing')
self.assertEqual(msgid.default, None)
self.assertEqual(msgid.domain, 'untranslated')
self.assertEqual(context.i18n_strings,
{'untranslated': {'testing': [('test_file', 42)]}})
def test_w_empty_id(self):
import warnings
from zope.configuration._compat import u
mid = self._makeOne()
context = self._makeContext()
bound = mid.bind(context)
with warnings.catch_warnings(record=True) as log:
msgid = bound.fromUnicode(u('[] testing'))
self.assertEqual(len(log), 0)
self.assertEqual(msgid, 'testing')
self.assertEqual(msgid.default, None)
self.assertEqual(msgid.domain, 'testing_domain')
self.assertEqual(context.i18n_strings,
{'testing_domain': {'testing': [('test_file', 42)]}})
def test_w_id_and_default(self):
import warnings
from zope.configuration._compat import u
mid = self._makeOne()
context = self._makeContext()
bound = mid.bind(context)
with warnings.catch_warnings(record=True) as log:
msgid = bound.fromUnicode(u('[testing] default'))
self.assertEqual(len(log), 0)
self.assertEqual(msgid, 'testing')
self.assertEqual(msgid.default, 'default')
self.assertEqual(msgid.domain, 'testing_domain')
self.assertEqual(context.i18n_strings,
{'testing_domain': {'testing': [('test_file', 42)]}})
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(PythonIdentifierTests),
unittest.makeSuite(GlobalObjectTests),
unittest.makeSuite(GlobalInterfaceTests),
unittest.makeSuite(TokensTests),
unittest.makeSuite(PathTests),
unittest.makeSuite(BoolTests),
unittest.makeSuite(MessageIDTests),
))
zope.configuration-4.0.3/src/zope/configuration/tests/victim.py 0000664 0001750 0001750 00000000013 12073042162 024660 0 ustar tseaver tseaver import bad
zope.configuration-4.0.3/src/zope/configuration/tests/test_config.py 0000664 0001750 0001750 00000211154 12073042162 025703 0 ustar tseaver tseaver ##############################################################################
#
# 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 configuration machinery.
"""
import unittest
class _Catchable(object):
# Mixin for classes which need to make assertions about the exception
# instance.
def assertRaises(self, excClass, callableObj, *args, **kwargs):
# Morph stdlib version to return the raised exception
try:
callableObj(*args, **kwargs)
except excClass as exc:
return exc
if hasattr(excClass,'__name__'):
excName = excClass.__name__
else:
excName = str(excClass)
raise self.failureException("%s not raised" % excName)
class ConfigurationContextTests(_Catchable,
unittest.TestCase,
):
def _getTargetClass(self):
from zope.configuration.config import ConfigurationContext
return ConfigurationContext
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_resolve_blank(self):
c = self._makeOne()
self.assertRaises(ValueError, c.resolve, '')
self.assertRaises(ValueError, c.resolve, ' ')
def test_resolve_dot(self):
c = self._makeOne()
package = c.package = object()
self.assertTrue(c.resolve('.') is package)
def test_resolve_trailing_dot_in_resolve(self):
#Dotted names are no longer allowed to end in dots
c = self._makeOne()
self.assertRaises(ValueError, c.resolve, 'zope.')
def test_resolve_builtin(self):
c = self._makeOne()
self.assertTrue(c.resolve('str') is str)
def test_resolve_single_non_builtin(self):
import os
c = self._makeOne()
self.assertTrue(c.resolve('os') is os)
def test_resolve_relative_miss_no_package(self):
from zope.configuration.exceptions import ConfigurationError
c = self._makeOne()
c.package = None
self.assertRaises(ConfigurationError, c.resolve, '.nonesuch')
def test_resolve_relative_miss_w_package_too_many_dots(self):
class FauxPackage(object):
pass
from zope.configuration.exceptions import ConfigurationError
c = self._makeOne()
package = c.package = FauxPackage()
package.__name__ = 'one.dot'
self.assertRaises(ConfigurationError, c.resolve, '....nonesuch')
def test_resolve_bad_dotted_last_import(self):
# Import error caused by a bad last component in the dotted name.
from zope.configuration.exceptions import ConfigurationError
c = self._makeOne()
exc = self.assertRaises(ConfigurationError,
c.resolve, 'zope.configuration.tests.nosuch')
self.assertTrue('ImportError' in str(exc))
def test_resolve_bad_dotted_import(self):
# Import error caused by a totally wrong dotted name.
from zope.configuration.exceptions import ConfigurationError
c = self._makeOne()
exc = self.assertRaises(ConfigurationError,
c.resolve, 'zope.configuration.nosuch.noreally')
self.assertTrue('ImportError' in str(exc))
def test_resolve_bad_sub_last_import(self):
#Import error caused by a bad sub import inside the referenced
#dotted name. Here we keep the standard traceback.
import sys
c = self._makeOne()
self.assertRaises(ImportError,
c.resolve, 'zope.configuration.tests.victim')
#Cleanup:
for name in ('zope.configuration.tests.victim',
'zope.configuration.tests.bad'):
if name in sys.modules:
del sys.modules[name]
def test_resolve_bad_sub_import(self):
#Import error caused by a bad sub import inside part of the referenced
#dotted name. Here we keep the standard traceback.
import sys
c = self._makeOne()
self.assertRaises(ImportError,
c.resolve, 'zope.configuration.tests.victim.nosuch')
#Cleanup:
for name in ('zope.configuration.tests.victim',
'zope.configuration.tests.bad'):
if name in sys.modules:
del sys.modules[name]
def test_path_w_absolute_filename(self):
import os
c = self._makeOne()
self.assertEqual(c.path('/path/to/somewhere'),
os.path.normpath('/path/to/somewhere'))
def test_path_w_relative_filename_w_basepath(self):
import os
c = self._makeOne()
c.basepath = '/path/to'
self.assertEqual(c.path('somewhere'),
os.path.normpath('/path/to/somewhere'))
def test_path_w_relative_filename_wo_basepath_wo_package(self):
import os
c = self._makeOne()
c.package = None
self.assertEqual(c.path('somewhere'),
os.path.join(os.getcwd(), 'somewhere'))
def test_path_wo_basepath_w_package_having_file(self):
#Path must always return an absolute path.
import os
class stub:
__file__ = os.path.join('relative', 'path')
c = self._makeOne()
c.package = stub()
self.assertTrue(os.path.isabs(c.path('y/z')))
def test_path_wo_basepath_w_package_having_no_file_but_path(self):
#Determine package path using __path__ if __file__ isn't available.
# (i.e. namespace package installed with
#--single-version-externally-managed)
import os
class stub:
__path__ = [os.path.join('relative', 'path')]
c = self._makeOne()
c.package = stub()
self.assertTrue(os.path.isabs(c.path('y/z')))
def test_checkDuplicate_miss(self):
import os
c = self._makeOne()
c.checkDuplicate('/path') # doesn't raise
self.assertEqual(list(c._seen_files), [os.path.normpath('/path')])
def test_checkDuplicate_hit(self):
import os
from zope.configuration.exceptions import ConfigurationError
c = self._makeOne()
c.checkDuplicate('/path')
self.assertRaises(ConfigurationError, c.checkDuplicate, '/path')
self.assertEqual(list(c._seen_files), [os.path.normpath('/path')])
def test_processFile_miss(self):
import os
c = self._makeOne()
self.assertEqual(c.processFile('/path'), True)
self.assertEqual(list(c._seen_files), [os.path.normpath('/path')])
def test_processFile_hit(self):
import os
c = self._makeOne()
c.processFile('/path')
self.assertEqual(c.processFile('/path'), False)
self.assertEqual(list(c._seen_files), [os.path.normpath('/path')])
def test_action_defaults_no_info_no_includepath(self):
DISCRIMINATOR = ('a', ('b',), 0)
c = self._makeOne()
c.actions = [] # normally provided by subclass
c.action(DISCRIMINATOR)
self.assertEqual(len(c.actions), 1)
info = c.actions[0]
self.assertEqual(info['discriminator'], DISCRIMINATOR)
self.assertEqual(info['callable'], None)
self.assertEqual(info['args'], ())
self.assertEqual(info['kw'], {})
self.assertEqual(info['includepath'], ())
self.assertEqual(info['info'], '')
self.assertEqual(info['order'], 0)
def test_action_defaults_w_info_w_includepath(self):
DISCRIMINATOR = ('a', ('b',), 0)
c = self._makeOne()
c.actions = [] # normally provided by subclass
c.info = 'INFO' # normally provided by subclass
c.includepath = ('a', 'b') # normally provided by subclass
c.action(DISCRIMINATOR)
self.assertEqual(len(c.actions), 1)
info = c.actions[0]
self.assertEqual(info['discriminator'], DISCRIMINATOR)
self.assertEqual(info['callable'], None)
self.assertEqual(info['args'], ())
self.assertEqual(info['kw'], {})
self.assertEqual(info['order'], 0)
self.assertEqual(info['includepath'], ('a', 'b'))
self.assertEqual(info['info'], 'INFO')
def test_action_explicit_no_extra(self):
DISCRIMINATOR = ('a', ('b',), 0)
ARGS = (12, 'z')
KW = {'one': 1}
INCLUDE_PATH = ('p', 'q/r')
INFO = 'INFO'
def _callable():
pass
c = self._makeOne()
c.actions = [] # normally provided by subclass
c.action(DISCRIMINATOR,
_callable,
ARGS,
KW,
42,
INCLUDE_PATH,
INFO,
)
self.assertEqual(len(c.actions), 1)
info = c.actions[0]
self.assertEqual(info['discriminator'], DISCRIMINATOR)
self.assertEqual(info['callable'], _callable)
self.assertEqual(info['args'], ARGS)
self.assertEqual(info['kw'], KW)
self.assertEqual(info['order'], 42)
self.assertEqual(info['includepath'], INCLUDE_PATH)
self.assertEqual(info['info'], INFO)
def test_action_explicit_w_extra(self):
DISCRIMINATOR = ('a', ('b',), 0)
ARGS = (12, 'z')
KW = {'one': 1}
INCLUDE_PATH = ('p', 'q/r')
INFO = 'INFO'
def _callable():
pass
c = self._makeOne()
c.actions = [] # normally provided by subclass
c.action(DISCRIMINATOR,
_callable,
ARGS,
KW,
42,
INCLUDE_PATH,
INFO,
foo='bar',
baz=17,
)
self.assertEqual(len(c.actions), 1)
info = c.actions[0]
self.assertEqual(info['discriminator'], DISCRIMINATOR)
self.assertEqual(info['callable'], _callable)
self.assertEqual(info['args'], ARGS)
self.assertEqual(info['kw'], KW)
self.assertEqual(info['order'], 42)
self.assertEqual(info['includepath'], INCLUDE_PATH)
self.assertEqual(info['info'], INFO)
self.assertEqual(info['foo'], 'bar')
self.assertEqual(info['baz'], 17)
def test_hasFeature_miss(self):
c = self._makeOne()
self.assertFalse(c.hasFeature('nonesuch'))
def test_hasFeature_hit(self):
c = self._makeOne()
c._features.add('a.feature')
self.assertTrue(c.hasFeature('a.feature'))
def test_provideFeature(self):
c = self._makeOne()
c.provideFeature('a.feature')
self.assertTrue(c.hasFeature('a.feature'))
class ConfigurationAdapterRegistryTests(unittest.TestCase):
def _getTargetClass(self):
from zope.configuration.config import ConfigurationAdapterRegistry
return ConfigurationAdapterRegistry
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_ctor(self):
reg = self._makeOne()
self.assertEqual(len(reg._registry), 0)
self.assertEqual(len(reg._docRegistry), 0)
def test_register(self):
from zope.interface import Interface
class IFoo(Interface):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
def _factory():
pass
reg = self._makeOne()
reg.register(IFoo, (NS, NAME), _factory)
self.assertEqual(len(reg._registry), 1)
areg = reg._registry[(NS, NAME)]
self.assertTrue(areg.lookup1(IFoo, Interface) is _factory)
self.assertEqual(len(reg._docRegistry), 0)
def test_register_replacement(self):
from zope.interface import Interface
class IFoo(Interface):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
def _factory():
pass
def _rival():
pass
reg = self._makeOne()
reg.register(IFoo, (NS, NAME), _factory)
reg.register(IFoo, (NS, NAME), _rival)
self.assertEqual(len(reg._registry), 1)
areg = reg._registry[(NS, NAME)]
self.assertTrue(areg.lookup1(IFoo, Interface) is _rival)
self.assertEqual(len(reg._docRegistry), 0)
def test_register_new_name(self):
from zope.interface import Interface
class IFoo(Interface):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
NAME2 = 'other'
def _factory():
pass
def _rival():
pass
reg = self._makeOne()
reg.register(IFoo, (NS, NAME), _factory)
reg.register(IFoo, (NS, NAME2), _rival)
self.assertEqual(len(reg._registry), 2)
areg = reg._registry[(NS, NAME)]
self.assertTrue(areg.lookup1(IFoo, Interface) is _factory)
areg = reg._registry[(NS, NAME2)]
self.assertTrue(areg.lookup1(IFoo, Interface) is _rival)
self.assertEqual(len(reg._docRegistry), 0)
def test_document_non_string_name(self):
from zope.interface import Interface
class ISchema(Interface):
pass
class IUsedIn(Interface):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
HANDLER = object()
INFO = 'INFO'
PARENT = object()
reg = self._makeOne()
reg.document((NS, NAME), ISchema, IUsedIn, HANDLER, INFO, PARENT)
self.assertEqual(len(reg._registry), 0)
self.assertEqual(len(reg._docRegistry), 1)
name, schema, used_in, handler, info, parent = reg._docRegistry[0]
self.assertEqual(name, (NS, NAME))
self.assertEqual(schema, ISchema)
self.assertEqual(used_in, IUsedIn)
self.assertEqual(info, INFO)
self.assertEqual(parent, PARENT)
def test_document_w_string_name(self):
from zope.interface import Interface
class ISchema(Interface):
pass
class IUsedIn(Interface):
pass
NAME = 'testing'
HANDLER = object()
INFO = 'INFO'
PARENT = object()
reg = self._makeOne()
reg.document(NAME, ISchema, IUsedIn, HANDLER, INFO, PARENT)
self.assertEqual(len(reg._registry), 0)
self.assertEqual(len(reg._docRegistry), 1)
name, schema, used_in, handler, info, parent = reg._docRegistry[0]
self.assertEqual(name, ('', NAME))
self.assertEqual(schema, ISchema)
self.assertEqual(used_in, IUsedIn)
self.assertEqual(info, INFO)
self.assertEqual(parent, PARENT)
def test_factory_miss(self):
from zope.configuration.exceptions import ConfigurationError
NS = 'http://namespace.example.com/'
NAME = 'testing'
context = object()
reg = self._makeOne()
self.assertRaises(ConfigurationError, reg.factory, context, (NS, NAME))
def test_factory_hit_on_fqn(self):
from zope.interface import Interface
from zope.interface import implementer
class IFoo(Interface):
pass
@implementer(IFoo)
class Context(object):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
context = Context()
def _factory():
pass
reg = self._makeOne()
reg.register(IFoo, (NS, NAME), _factory)
self.assertEqual(reg.factory(context, (NS, NAME)), _factory)
def test_factory_miss_on_fqn_hit_on_bare_name(self):
from zope.interface import Interface
from zope.interface import implementer
class IFoo(Interface):
pass
@implementer(IFoo)
class Context(object):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
context = Context()
def _factory():
pass
reg = self._makeOne()
reg.register(IFoo, NAME, _factory)
self.assertEqual(reg.factory(context, (NS, NAME)), _factory)
def test_factory_hit_on_fqn_lookup_fails(self):
from zope.interface import Interface
from zope.configuration.exceptions import ConfigurationError
class IFoo(Interface):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
context = object() # doesn't provide IFoo
def _factory():
pass
reg = self._makeOne()
reg.register(IFoo, (NS, NAME), _factory)
self.assertRaises(ConfigurationError, reg.factory, context, (NS, NAME))
class _ConformsToIConfigurationContext(object):
def test_class_conforms_to_IConfigurationContext(self):
from zope.interface.verify import verifyClass
from zope.configuration.interfaces import IConfigurationContext
verifyClass(IConfigurationContext, self._getTargetClass())
def test_instance_conforms_to_IConfigurationContext(self):
from zope.interface.verify import verifyObject
from zope.configuration.interfaces import IConfigurationContext
verifyObject(IConfigurationContext, self._makeOne())
class ConfigurationMachineTests(_Catchable,
_ConformsToIConfigurationContext,
unittest.TestCase,
):
def _getTargetClass(self):
from zope.configuration.config import ConfigurationMachine
return ConfigurationMachine
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_ctor(self):
from zope.configuration.config import RootStackItem
from zope.configuration.config import metans
cm = self._makeOne()
self.assertEqual(cm.package, None)
self.assertEqual(cm.basepath, None)
self.assertEqual(cm.includepath, ())
self.assertEqual(cm.info, '')
self.assertEqual(len(cm.actions), 0)
self.assertEqual(len(cm.stack), 1)
root = cm.stack[0]
self.assertTrue(isinstance(root, RootStackItem))
self.assertTrue(root.context is cm)
self.assertEqual(len(cm.i18n_strings), 0)
# Check bootstrapped meta:*.
self.assertTrue((metans, 'directive') in cm._registry)
self.assertTrue((metans, 'directives') in cm._registry)
self.assertTrue((metans, 'complexDirective') in cm._registry)
self.assertTrue((metans, 'groupingDirective') in cm._registry)
self.assertTrue((metans, 'provides') in cm._registry)
self.assertTrue((metans, 'subdirective') in cm._registry)
def test_begin_w___data_and_kw(self):
from zope.configuration.config import IConfigurationContext
NS = 'http://namespace.example.com/'
NAME = 'testing'
def _factory(context, data, info):
pass
cm = self._makeOne()
cm.register(IConfigurationContext, (NS, NAME), _factory)
self.assertRaises(TypeError,
cm.begin, (NS, NAME), {'foo': 'bar'}, baz='bam')
def test_begin_w___data_no_kw(self):
from zope.interface import Interface
from zope.configuration.config import IConfigurationContext
from zope.configuration.config import RootStackItem
class ISchema(Interface):
pass
class IUsedIn(Interface):
pass
def _handler(*args, **kw):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
_called_with = []
item = object()
def _factory(context, data, info):
_called_with.append((context, data, info))
return item
cm = self._makeOne()
cm.register(IConfigurationContext, (NS, NAME), _factory)
cm.begin((NS, NAME), {'name': 'testing',
'schema': ISchema,
'usedIn': IUsedIn,
'handler': _handler,
}, 'INFO')
self.assertEqual(len(cm.stack), 2)
root = cm.stack[0]
self.assertTrue(isinstance(root, RootStackItem))
nested = cm.stack[1]
self.assertTrue(nested is item)
self.assertEqual(_called_with,
[(cm, {'name': 'testing',
'schema': ISchema,
'usedIn': IUsedIn,
'handler': _handler,
}, 'INFO')])
def test_begin_wo___data_w_kw(self):
from zope.interface import Interface
from zope.configuration.config import IConfigurationContext
from zope.configuration.config import RootStackItem
class ISchema(Interface):
pass
class IUsedIn(Interface):
pass
def _handler(*args, **kw):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
_called_with = []
item = object()
def _factory(context, data, info):
_called_with.append((context, data, info))
return item
cm = self._makeOne()
cm.register(IConfigurationContext, (NS, NAME), _factory)
cm.begin((NS, NAME), None, 'INFO',
name='testing',
schema=ISchema,
usedIn=IUsedIn,
handler=_handler,
)
self.assertEqual(len(cm.stack), 2)
root = cm.stack[0]
self.assertTrue(isinstance(root, RootStackItem))
nested = cm.stack[1]
self.assertTrue(nested is item)
self.assertEqual(_called_with,
[(cm, {'name': 'testing',
'schema': ISchema,
'usedIn': IUsedIn,
'handler': _handler,
}, 'INFO')])
def test_end(self):
from zope.configuration.config import RootStackItem
class FauxItem(object):
_finished = False
def finish(self):
self._finished = True
cm = self._makeOne()
item = FauxItem()
cm.stack.append(item)
cm.end()
self.assertEqual(len(cm.stack), 1)
root = cm.stack[0]
self.assertTrue(isinstance(root, RootStackItem))
self.assertTrue(item._finished)
def test___call__(self):
from zope.interface import Interface
from zope.configuration.config import IConfigurationContext
from zope.configuration.config import RootStackItem
class ISchema(Interface):
pass
class IUsedIn(Interface):
pass
class FauxItem(object):
_finished = False
def finish(self):
self._finished = True
def _handler(*args, **kw):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
_called_with = []
item = FauxItem()
def _factory(context, data, info):
_called_with.append((context, data, info))
return item
cm = self._makeOne()
cm.register(IConfigurationContext, (NS, NAME), _factory)
cm((NS, NAME), 'INFO',
name='testing',
schema=ISchema,
usedIn=IUsedIn,
handler=_handler,
)
self.assertEqual(len(cm.stack), 1)
root = cm.stack[0]
self.assertTrue(isinstance(root, RootStackItem))
self.assertEqual(_called_with,
[(cm, {'name': 'testing',
'schema': ISchema,
'usedIn': IUsedIn,
'handler': _handler,
}, 'INFO')])
self.assertTrue(item._finished)
def test_getInfo_only_root_default(self):
cm = self._makeOne()
self.assertEqual(cm.getInfo(), '')
def test_getInfo_only_root(self):
cm = self._makeOne()
cm.info = 'INFO'
self.assertEqual(cm.getInfo(), 'INFO')
def test_getInfo_w_item(self):
class FauxItem(object):
info = 'FAUX'
def __init__(self):
self.context = self
cm = self._makeOne()
cm.stack.append(FauxItem())
self.assertEqual(cm.getInfo(), 'FAUX')
def test_setInfo_only_root(self):
cm = self._makeOne()
cm.setInfo('INFO')
self.assertEqual(cm.info, 'INFO')
def test_setInfo_w_item(self):
class FauxItem(object):
info = 'FAUX'
def __init__(self):
self.context = self
cm = self._makeOne()
item = FauxItem()
cm.stack.append(item)
cm.setInfo('UPDATED')
self.assertEqual(item.info, 'UPDATED')
def test_execute_actions_empty(self):
cm = self._makeOne()
cm.execute_actions() # noop
def test_execute_actions_wo_errors(self):
_called_with = {}
def _a1(*args, **kw):
_called_with.setdefault('_a1', []).append((args, kw))
def _a2(*args, **kw):
_called_with.setdefault('_a2', []).append((args, kw))
cm = self._makeOne()
cm.action(None, None) # will be skipped
cm.action(None, _a1, ('a', 0), {'foo': 'bar'}, 4)
cm.action(None, _a2, ('a', 1), {'foo': 'baz'}, 3)
cm.action(None, _a1, ('b', 2), {'foo': 'qux'}, 2)
cm.execute_actions()
self.assertEqual(_called_with['_a1'],
[(('b', 2), {'foo': 'qux'}),
(('a', 0), {'foo': 'bar'}),
])
self.assertEqual(_called_with['_a2'],
[(('a', 1), {'foo': 'baz'}),
])
def test_execute_actions_w_errors_w_testing(self):
def _err(*args, **kw):
raise ValueError('XXX')
cm = self._makeOne()
cm.action(None, _err)
exc = self.assertRaises(ValueError, cm.execute_actions, testing=True)
self.assertEqual(str(exc), 'XXX')
def test_execute_actions_w_errors_wo_testing(self):
from zope.configuration.config import ConfigurationExecutionError
def _err(*args, **kw):
raise ValueError('XXX')
cm = self._makeOne()
cm.info = 'INFO'
cm.action(None, _err)
exc = self.assertRaises(ConfigurationExecutionError,
cm.execute_actions)
self.assertTrue(exc.etype is ValueError)
self.assertEqual(str(exc.evalue), "XXX")
self.assertEqual(exc.info, "INFO")
def test_keyword_handling(self):
# This is really an integraiton test.
from zope.configuration.config import metans
from zope.configuration.tests.directives import f
from zope.configuration._compat import b
from zope.configuration._compat import u
machine = self._makeOne()
ns = "http://www.zope.org/testing"
#Register some test directives, starting with a grouping directive
# that sets a package:
machine((metans, "groupingDirective"),
name="package", namespace=ns,
schema="zope.configuration.tests.directives.IPackaged",
handler="zope.configuration.tests.directives.Packaged",
)
# set the package:
machine.begin((ns, "package"),
package="zope.configuration.tests.directives",
)
#Which makes it easier to define the other directives:
machine((metans, "directive"),
namespace=ns, name="k",
schema=".Ik", handler=".k")
machine((ns, "k"), "yee ha",
**{"for": u("f"), "class": u("c"), "x": u("x")})
self.assertEqual(len(machine.actions), 1)
self.assertEqual(machine.actions[0],
{'args': (b('f'), b('c'), b('x')),
'callable': f,
'discriminator': ('k', b('f')),
'includepath': (),
'info': 'yee ha',
'kw': {},
'order': 0,
})
class _ConformsToIStackItem(object):
def test_class_conforms_to_IStackItem(self):
from zope.interface.verify import verifyClass
from zope.configuration.config import IStackItem
verifyClass(IStackItem, self._getTargetClass())
def test_instance_conforms_to_IStackItem(self):
from zope.interface.verify import verifyObject
from zope.configuration.config import IStackItem
verifyObject(IStackItem, self._makeOne())
class SimpleStackItemTests(_ConformsToIStackItem,
unittest.TestCase,
):
def _getTargetClass(self):
from zope.configuration.config import SimpleStackItem
return SimpleStackItem
def _makeOne(self,
context=None, handler=None, info=None,
schema=None, data=None):
from zope.interface import Interface
if context is None:
context = FauxContext()
if handler is None:
def handler():
pass
if info is None:
info = 'INFO'
if schema is None:
schema = Interface
if data is None:
data = {}
return self._getTargetClass()(context, handler, info, schema, data)
def test_ctor(self):
from zope.interface import Interface
from zope.configuration.config import GroupingContextDecorator
class ISchema(Interface):
pass
context = FauxContext()
def _handler():
pass
_data = {}
ssi = self._makeOne(context, _handler, 'INFO', ISchema, _data)
self.assertTrue(isinstance(ssi.context, GroupingContextDecorator))
self.assertTrue(ssi.context.context is context)
self.assertEqual(ssi.context.info, 'INFO')
self.assertEqual(ssi.handler, _handler)
self.assertEqual(ssi.argdata, (ISchema, _data))
def test_contained_raises(self):
from zope.configuration.exceptions import ConfigurationError
ssi = self._makeOne()
self.assertRaises(ConfigurationError,
ssi.contained, ('ns', 'name'), {}, '')
def test_finish_handler_returns_no_actions(self):
from zope.interface import Interface
from zope.schema import Text
class ISchema(Interface):
name = Text(required=True)
context = FauxContext()
def _handler(context, **kw):
return ()
_data = {'name': 'NAME'}
ssi = self._makeOne(context, _handler, 'INFO', ISchema, _data)
ssi.finish() # noraise
self.assertEqual(context.actions, [])
def test_finish_handler_returns_oldstyle_actions(self):
from zope.interface import Interface
from zope.schema import Text
class ISchema(Interface):
name = Text(required=True)
context = FauxContext()
def _action(context, **kw):
pass
def _handler(context, **kw):
return [(None, _action)]
_data = {'name': 'NAME'}
ssi = self._makeOne(context, _handler, 'INFO', ISchema, _data)
ssi.finish()
self.assertEqual(context.actions,
[{'discriminator': None,
'callable': _action,
'args': (),
'kw': {},
'includepath': (),
'info': 'INFO',
'order': 0,
}])
def test_finish_handler_returns_newstyle_actions(self):
from zope.interface import Interface
from zope.schema import Text
class ISchema(Interface):
name = Text(required=True)
context = FauxContext()
def _action(context, **kw):
pass
def _handler(context, **kw):
return [{'discriminator': None, 'callable': _action}]
_data = {'name': 'NAME'}
ssi = self._makeOne(context, _handler, 'INFO', ISchema, _data)
ssi.finish()
self.assertEqual(context.actions,
[{'discriminator': None,
'callable': _action,
'args': (),
'kw': {},
'includepath': (),
'info': 'INFO',
'order': 0,
}])
class RootStackItemTests(_ConformsToIStackItem,
unittest.TestCase,
):
def _getTargetClass(self):
from zope.configuration.config import RootStackItem
return RootStackItem
def _makeOne(self, context=None):
if context is None:
context = object()
return self._getTargetClass()(context)
def test_contained_context_factory_fails(self):
from zope.configuration.exceptions import ConfigurationError
class _Context(object):
def factory(self, context, name):
pass
rsi = self._makeOne(_Context())
self.assertRaises(ConfigurationError,
rsi.contained, ('ns', 'name'), {}, '')
def test_contained_context_factory_normal(self):
_called_with = []
_adapter = object()
def _factory(context, data, info):
_called_with.append((context, data, info))
return _adapter
class _Context(object):
def factory(self, context, name):
return _factory
context = _Context()
rsi = self._makeOne(context)
adapter = rsi.contained(('ns', 'name'), {'a': 'b'}, 'INFO')
self.assertTrue(adapter is _adapter)
self.assertEqual(_called_with, [(context, {'a': 'b'}, 'INFO')])
def test_finish(self):
rsi = self._makeOne()
rsi.finish() #noraise
class GroupingStackItemTests(_ConformsToIStackItem,
unittest.TestCase,
):
def _getTargetClass(self):
from zope.configuration.config import GroupingStackItem
return GroupingStackItem
def _makeOne(self, context=None):
if context is None:
context = object()
return self._getTargetClass()(context)
def test_contained_context_before_returns_oldstyle_actions(self):
_called_with = []
_adapter = object()
def _factory(context, data, info):
_called_with.append((context, data, info))
return _adapter
def _action(*args, **kw):
pass
class _Context(FauxContext):
def factory(self, context, name):
return _factory
def before(self):
return [(None, _action)]
def after(self):
return ()
context = _Context()
rsi = self._makeOne(context)
adapter = rsi.contained(('ns', 'name'), {'a': 'b'}, 'INFO')
self.assertTrue(adapter is _adapter)
self.assertEqual(_called_with, [(context, {'a': 'b'}, 'INFO')])
self.assertEqual(len(context.actions), 1)
self.assertEqual(context.actions[0],
{'discriminator': None,
'callable': _action,
'args': (),
'kw': {},
'includepath': (),
'info': None,
'order': 0,
})
rsi.finish() # doesn't re-do the 'before' dance
self.assertEqual(len(context.actions), 1)
def test_contained_context_before_returns_newstyle_actions(self):
_called_with = []
_adapter = object()
def _factory(context, data, info):
_called_with.append((context, data, info))
return _adapter
def _before(*args, **kw):
pass
def _after(*args, **kw):
pass
class _Context(FauxContext):
def factory(self, context, name):
return _factory
def before(self):
return [{'discriminator': None, 'callable': _before}]
def after(self):
return [{'discriminator': None, 'callable': _after}]
context = _Context()
rsi = self._makeOne(context)
adapter = rsi.contained(('ns', 'name'), {'a': 'b'}, 'INFO')
self.assertTrue(adapter is _adapter)
self.assertEqual(_called_with, [(context, {'a': 'b'}, 'INFO')])
self.assertEqual(len(context.actions), 1)
self.assertEqual(context.actions[0], # no GSI to add extras
{'discriminator': None,
'callable': _before,
})
rsi.finish() # doesn't re-do the 'before' dance
self.assertEqual(len(context.actions), 2)
self.assertEqual(context.actions[1],
{'discriminator': None,
'callable': _after,
})
def test_finish_calls_before_if_not_already_called(self):
def _before(*args, **kw):
pass
def _after(*args, **kw):
pass
class _Context(FauxContext):
def before(self):
return [(None, _before)]
def after(self):
return [(None, _after)]
context = _Context()
rsi = self._makeOne(context)
adapter = rsi.finish()
self.assertEqual(len(context.actions), 2)
self.assertEqual(context.actions[0], # no GSI to add extras
{'discriminator': None,
'callable': _before,
'args': (),
'kw': {},
'includepath': (),
'info': None,
'order': 0,
})
self.assertEqual(context.actions[1],
{'discriminator': None,
'callable': _after,
'args': (),
'kw': {},
'includepath': (),
'info': None,
'order': 0,
})
class ComplexStackItemTests(_ConformsToIStackItem,
unittest.TestCase,
):
def _getTargetClass(self):
from zope.configuration.config import ComplexStackItem
return ComplexStackItem
def _makeOne(self, meta=None, context=None, data=None, info=None):
if meta is None:
meta = self._makeMeta()
if context is None:
context = object()
if data is None:
data = {'name': 'NAME'}
if info is None:
info = 'INFO'
return self._getTargetClass()(meta, context, data, info)
def _makeMeta(self):
from zope.interface import Interface
from zope.schema import Text
class ISchema(Interface):
name = Text()
class FauxMeta(dict):
schema = ISchema
_handler_args = None
_handler = object()
def handler(self, newcontext, **kw):
self._handler_kwargs = kw
return self._handler
return FauxMeta()
def test_ctor(self):
from zope.configuration.config import GroupingContextDecorator
meta = self._makeMeta()
context = FauxContext()
_data = {'name': 'NAME'}
csi = self._makeOne(meta, context, _data, 'INFO')
self.assertTrue(isinstance(csi.context, GroupingContextDecorator))
self.assertTrue(csi.context.context is context)
self.assertEqual(csi.context.info, 'INFO')
self.assertEqual(csi.handler, meta._handler)
self.assertEqual(meta._handler_kwargs, _data)
def test_contained_miss(self):
from zope.configuration.exceptions import ConfigurationError
NS = 'http://namespace.example.com/'
NAME = 'testing'
csi = self._makeOne()
self.assertRaises(ConfigurationError,
csi.contained, (NS, NAME), {}, 'INFO')
def test_contained_hit(self):
from zope.interface import Interface
from zope.configuration.config import GroupingContextDecorator
from zope.configuration.config import SimpleStackItem
NS = 'http://namespace.example.com/'
NAME = 'testing'
class ISubSchema(Interface):
pass
class WithName(object):
def testing(self, *args):
pass
meta = self._makeMeta()
wn = meta._handler = WithName()
meta[NAME] = (ISubSchema, 'SUBINFO')
context = FauxContext()
_data = {'name': 'NAME'}
csi = self._makeOne(meta, context, _data, 'INFO')
ssi = csi.contained((NS, NAME), {}, 'SUBINFO')
self.assertTrue(isinstance(ssi, SimpleStackItem))
self.assertTrue(isinstance(ssi.context, GroupingContextDecorator))
self.assertTrue(ssi.context.context is csi.context)
self.assertEqual(ssi.context.info, 'SUBINFO')
self.assertEqual(ssi.handler, wn.testing)
self.assertEqual(ssi.argdata, (ISubSchema, {}))
def test_finish_handler_is_noncallable(self):
meta = self._makeMeta()
context = FauxContext()
_data = {'name': 'NAME'}
csi = self._makeOne(meta, context, _data, 'INFO')
csi.finish() #noraise
self.assertEqual(len(context.actions), 0)
def test_finish_handler_raises_AE_for___call__(self):
def _handler():
raise AttributeError('__call__')
meta = self._makeMeta()
meta._handler = _handler
context = FauxContext()
_data = {'name': 'NAME'}
csi = self._makeOne(meta, context, _data, 'INFO')
csi.finish() #noraise
self.assertEqual(len(context.actions), 0)
def test_finish_handler_raises_AE_for_other(self):
def _handler():
raise AttributeError('other')
meta = self._makeMeta()
meta._handler = _handler
context = FauxContext()
_data = {'name': 'NAME'}
csi = self._makeOne(meta, context, _data, 'INFO')
self.assertRaises(AttributeError, csi.finish)
def test_finish_handler_returns_oldstyle_actions(self):
def _action():
pass
def _handler():
return [(None, _action)]
meta = self._makeMeta()
meta._handler = _handler
context = FauxContext()
_data = {'name': 'NAME'}
csi = self._makeOne(meta, context, _data, 'INFO')
csi.finish()
self.assertEqual(len(context.actions), 1)
self.assertEqual(context.actions[0],
{'discriminator': None,
'callable': _action,
'args': (),
'kw': {},
'includepath': (),
'info': 'INFO',
'order': 0,
})
def test_finish_handler_returns_newstyle_actions(self):
def _action():
pass
def _handler():
return [{'discriminator': None, 'callable': _action}]
meta = self._makeMeta()
meta._handler = _handler
context = FauxContext()
_data = {'name': 'NAME'}
csi = self._makeOne(meta, context, _data, 'INFO')
csi.finish()
self.assertEqual(len(context.actions), 1)
self.assertEqual(context.actions[0],
{'discriminator': None,
'callable': _action,
'args': (),
'kw': {},
'includepath': (),
'info': 'INFO',
'order': 0,
})
class _ConformsToIGroupingContext(object):
def test_class_conforms_to_IGroupingContext(self):
from zope.interface.verify import verifyClass
from zope.configuration.interfaces import IGroupingContext
verifyClass(IGroupingContext, self._getTargetClass())
def test_instance_conforms_to_IGroupingContext(self):
from zope.interface.verify import verifyObject
from zope.configuration.interfaces import IGroupingContext
verifyObject(IGroupingContext, self._makeOne())
class GroupingContextDecoratorTests(_ConformsToIConfigurationContext,
_ConformsToIGroupingContext,
unittest.TestCase,
):
def _getTargetClass(self):
from zope.configuration.config import GroupingContextDecorator
return GroupingContextDecorator
def _makeOne(self, context=None, **kw):
if context is None:
context = FauxContext()
context.package = None #appease IConfigurationContext
instance = self._getTargetClass()(context, **kw)
return instance
def test_ctor_no_kwargs(self):
context = FauxContext()
gcd = self._makeOne(context)
self.assertTrue(gcd.context is context)
def test_ctor_w_kwargs(self):
context = FauxContext()
gcd = self._makeOne(context, foo='bar', baz=42)
self.assertTrue(gcd.context is context)
self.assertEqual(gcd.foo, 'bar')
self.assertEqual(gcd.baz, 42)
def test_getattr_fetches_from_context_and_caches(self):
context = FauxContext()
gcd = self._makeOne(context)
context.foo = 'bar'
self.assertEqual(gcd.foo, 'bar')
self.assertTrue('foo' in gcd.__dict__)
def test_before(self):
gcd = self._makeOne()
gcd.before() #noraise
def test_after(self):
gcd = self._makeOne()
gcd.after() #noraise
class _ConformsToIDirectivesContext(object):
def test_class_conforms_to_IDirectivesContext(self):
from zope.interface.verify import verifyClass
from zope.configuration.config import IDirectivesContext
verifyClass(IDirectivesContext, self._getTargetClass())
def test_instance_conforms_to_IDirectivesContext(self):
from zope.interface.verify import verifyObject
from zope.configuration.config import IDirectivesContext
verifyObject(IDirectivesContext, self._makeOne())
class DirectivesHandlerTests(_ConformsToIDirectivesContext,
unittest.TestCase,
):
def _getTargetClass(self):
from zope.configuration.config import DirectivesHandler
return DirectivesHandler
def _makeOne(self, context=None):
if context is None:
context = FauxContext()
context.package = None #appease IConfigurationContext
context.namespace = None #appease IDirectivesInfo
instance = self._getTargetClass()(context)
return instance
class Test_defineSimpleDirective(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.config import defineSimpleDirective
return defineSimpleDirective(*args, **kw)
def _makeContext(self):
class _Context(FauxContext):
def __init__(self):
self._registered = []
self._documented = []
def register(self, usedIn, name, factory):
self._registered.append((usedIn, name, factory))
def document(self, name, schema, usedIn, handler, info):
self._documented.append((name, schema, usedIn, handler, info))
return _Context()
def test_defaults(self):
from zope.interface import Interface
from zope.configuration.interfaces import IConfigurationContext as ICC
class ISchema(Interface):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
context = self._makeContext()
context.namespace = NS
context.info = 'INFO'
def _handler():
pass
self._callFUT(context, NAME, ISchema, _handler)
self.assertEqual(len(context._registered), 1)
usedIn, name, factory = context._registered[0]
self.assertEqual(usedIn, ICC)
self.assertEqual(name, (NS, NAME))
sub = object()
ssi = factory(sub, {'a': 1}, 'SUBINFO')
self.assertTrue(ssi.context.context is sub)
self.assertEqual(ssi.context.info, 'SUBINFO')
self.assertEqual(ssi.handler, _handler)
self.assertEqual(len(context._documented), 1)
self.assertEqual(context._documented[0],
((NS, NAME), ISchema, ICC, _handler, 'INFO'))
def test_explicit_w_star_namespace(self):
from zope.interface import Interface
class ISchema(Interface):
pass
class IUsedIn(Interface):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
context = self._makeContext()
context.namespace = NS
context.info = 'INFO'
def _handler():
pass
self._callFUT(context, NAME, ISchema, _handler,
namespace='*', usedIn=IUsedIn)
self.assertEqual(len(context._registered), 1)
usedIn, name, factory = context._registered[0]
self.assertEqual(usedIn, IUsedIn)
self.assertEqual(name, NAME)
sub = object()
ssi = factory(sub, {'a': 1}, 'SUBINFO')
self.assertTrue(ssi.context.context is sub)
self.assertEqual(ssi.context.info, 'SUBINFO')
self.assertEqual(ssi.handler, _handler)
self.assertEqual(len(context._documented), 1)
self.assertEqual(context._documented[0],
(NAME, ISchema, IUsedIn, _handler, 'INFO'))
class Test_defineGroupingDirective(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.config import defineGroupingDirective
return defineGroupingDirective(*args, **kw)
def _makeContext(self):
class _Context(FauxContext):
def __init__(self):
self._registered = []
self._documented = []
def register(self, usedIn, name, factory):
self._registered.append((usedIn, name, factory))
def document(self, name, schema, usedIn, handler, info):
self._documented.append((name, schema, usedIn, handler, info))
return _Context()
def test_defaults(self):
from zope.interface import Interface
from zope.schema import Text
from zope.configuration.interfaces import IConfigurationContext as ICC
class ISchema(Interface):
arg = Text()
NS = 'http://namespace.example.com/'
NAME = 'testing'
context = self._makeContext()
context.namespace = NS
context.info = 'INFO'
newcontext = FauxContext()
_called_with = []
def _handler(context, **kw):
_called_with.append((context, kw))
return newcontext
self._callFUT(context, NAME, ISchema, _handler)
self.assertEqual(len(context._registered), 1)
usedIn, name, factory = context._registered[0]
self.assertEqual(usedIn, ICC)
self.assertEqual(name, (NS, NAME))
sub = object()
gsi = factory(sub, {'arg': 'val'}, 'SUBINFO')
self.assertTrue(gsi.context is newcontext)
self.assertEqual(newcontext.info, 'SUBINFO')
self.assertEqual(_called_with, [(sub, {'arg': 'val'})])
self.assertEqual(len(context._documented), 1)
self.assertEqual(context._documented[0],
((NS, NAME), ISchema, ICC, _handler, 'INFO'))
def test_explicit_w_star_namespace(self):
from zope.interface import Interface
from zope.schema import Text
class ISchema(Interface):
arg = Text()
class IUsedIn(Interface):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
context = self._makeContext()
context.namespace = NS
context.info = 'INFO'
newcontext = FauxContext()
_called_with = []
def _handler(context, **kw):
_called_with.append((context, kw))
return newcontext
self._callFUT(context, NAME, ISchema, _handler,
namespace='*', usedIn=IUsedIn)
self.assertEqual(len(context._registered), 1)
usedIn, name, factory = context._registered[0]
self.assertEqual(usedIn, IUsedIn)
self.assertEqual(name, NAME)
sub = object()
gsi = factory(sub, {'arg': 'val'}, 'SUBINFO')
self.assertTrue(gsi.context is newcontext)
self.assertEqual(newcontext.info, 'SUBINFO')
self.assertEqual(_called_with, [(sub, {'arg': 'val'})])
self.assertEqual(len(context._documented), 1)
self.assertEqual(context._documented[0],
(NAME, ISchema, IUsedIn, _handler, 'INFO'))
class _ConformsToIComplexDirectiveContext(object):
def test_class_conforms_to_IComplexDirectiveContext(self):
from zope.interface.verify import verifyClass
from zope.configuration.config import IComplexDirectiveContext
verifyClass(IComplexDirectiveContext, self._getTargetClass())
def test_instance_conforms_to_IComplexDirectiveContext(self):
from zope.interface.verify import verifyObject
from zope.configuration.config import IComplexDirectiveContext
verifyObject(IComplexDirectiveContext, self._makeOne())
class ComplexDirectiveDefinitionTests(_ConformsToIComplexDirectiveContext,
unittest.TestCase,
):
def _getTargetClass(self):
from zope.configuration.config import ComplexDirectiveDefinition
return ComplexDirectiveDefinition
def _makeOne(self, context=None):
if context is None:
context = self._makeContext()
instance = self._getTargetClass()(context)
return instance
def _makeContext(self, package=None, namespace=None, name=None,
schema=None, handler=None, usedIn=None):
context = FauxContext()
context.package = package
context.namespace = namespace
context.name = name
context.schema = schema
context.handler = handler
context.usedIn = usedIn
return context
def test_before(self):
from zope.interface import Interface
from zope.schema import Text
class ISchema(Interface):
arg = Text()
class IUsedIn(Interface):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
_handled = []
_csi_handler = object()
def _handler(context, **kw):
_handled.append((context, kw))
return _csi_handler
context = self._makeContext(namespace=NS, name=NAME, schema=ISchema,
handler=_handler, usedIn=IUsedIn)
context.info = 'INFO'
_registered = []
def _register(*args):
_registered.append(args)
context.register = _register
_documented = []
def _document(*args):
_documented.append(args)
context.document = _document
cdd = self._makeOne(context)
cdd.before()
self.assertEqual(len(_registered), 1)
usedIn, fqn, factory = _registered[0]
self.assertEqual(usedIn, IUsedIn)
self.assertEqual(fqn, (NS, NAME))
sub = FauxContext()
csi = factory(sub, {'arg': 'val'}, 'SUBINFO')
self.assertEqual(csi.meta, cdd)
self.assertEqual(csi.context.context, sub)
self.assertEqual(csi.context.info, 'SUBINFO')
self.assertEqual(csi.handler, _csi_handler)
self.assertEqual(_handled, [(csi.context, {'arg': 'val'})])
self.assertEqual(_documented,
[((NS, NAME), ISchema, IUsedIn, _handler, 'INFO')])
class Test_subdirective(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.config import subdirective
return subdirective(*args, **kw)
def _makeContext(self, package=None, namespace=None, name=None,
schema=None, handler=None, usedIn=None):
class _Context(object):
def __init__(self):
self.context = {}
self._documented = []
def document(self, *args):
self._documented.append(args)
context = _Context()
context.package = package
context.namespace = namespace
context.name = name
context.schema = schema
context.handler = handler
context.usedIn = usedIn
return context
def test_wo_handler_attribute(self):
from zope.interface import Interface
from zope.schema import Text
class ISubSchema(Interface):
arg = Text()
class ISchema(Interface):
pass
class IUsedIn(Interface):
pass
NS = 'http://namespace.example.com/'
NAME = 'testing'
SUBNAME = 'sub'
_handler = object()
context = self._makeContext(None, NS, NAME, ISchema, _handler, IUsedIn)
context.info = 'INFO'
self._callFUT(context, SUBNAME, ISubSchema)
self.assertEqual(len(context._documented), 1)
fqn, schema, usedIn, handler, info, ctx = context._documented[0]
self.assertEqual(fqn, (NS, SUBNAME))
self.assertEqual(schema, ISubSchema)
self.assertEqual(usedIn, IUsedIn)
self.assertEqual(handler, _handler)
self.assertEqual(info, 'INFO')
self.assertEqual(ctx, context.context)
self.assertEqual(context.context[SUBNAME], (ISubSchema, 'INFO'))
def test_w_handler_attribute(self):
from zope.interface import Interface
from zope.schema import Text
class ISubSchema(Interface):
arg = Text()
class ISchema(Interface):
pass
class IUsedIn(Interface):
pass
class Handler(object):
sub = object()
NS = 'http://namespace.example.com/'
NAME = 'testing'
SUBNAME = 'sub'
handler = Handler()
context = self._makeContext(None, NS, NAME, ISchema, handler, IUsedIn)
context.info = 'INFO'
self._callFUT(context, SUBNAME, ISubSchema)
self.assertEqual(len(context._documented), 1)
fqn, schema, usedIn, handler, info, ctx = context._documented[0]
self.assertEqual(fqn, (NS, SUBNAME))
self.assertEqual(schema, ISubSchema)
self.assertEqual(usedIn, IUsedIn)
self.assertEqual(handler, Handler.sub)
self.assertEqual(info, 'INFO')
self.assertEqual(ctx, context.context)
self.assertEqual(context.context[SUBNAME], (ISubSchema, 'INFO'))
class Test_provides(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.config import provides
return provides(*args, **kw)
def test_w_multiple(self):
context = FauxContext()
self.assertRaises(ValueError, self._callFUT, context, 'one two')
def test_w_single(self):
_provided = []
def _provideFeature(feature):
_provided.append(feature)
context = FauxContext()
context.provideFeature = _provideFeature
self._callFUT(context, 'one')
self.assertEqual(_provided, ['one'])
class Test_toargs(_Catchable, unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.config import toargs
return toargs(*args, **kw)
def test_w_empty_schema_no_data(self):
from zope.interface import Interface
class ISchema(Interface):
pass
context = FauxContext()
self.assertEqual(self._callFUT(context, ISchema, {}), {})
def test_w_empty_schema_w_data_no_kwargs_allowed(self):
from zope.configuration.exceptions import ConfigurationError
from zope.interface import Interface
class ISchema(Interface):
pass
context = FauxContext()
exc = self.assertRaises(ConfigurationError,
self._callFUT, context, ISchema, {'a': 'b'})
self.assertEqual(exc.args, ('Unrecognized parameters:', 'a'))
def test_w_empty_schema_w_data_w_kwargs_allowed(self):
from zope.interface import Interface
class ISchema(Interface):
pass
ISchema.setTaggedValue('keyword_arguments', True)
context = FauxContext()
self.assertEqual(self._callFUT(context, ISchema, {'a': 'b'}),
{'a': 'b'})
def test_w_keyword_sub(self):
from zope.interface import Interface
from zope.schema import Text
class ISchema(Interface):
for_ = Text()
context = FauxContext()
self.assertEqual(self._callFUT(context, ISchema, {'for': 'foo'}),
{'for_': 'foo'})
def test_w_field_missing_no_default(self):
from zope.interface import Interface
from zope.schema import Text
from zope.configuration.exceptions import ConfigurationError
class ISchema(Interface):
no_default = Text()
context = FauxContext()
exc = self.assertRaises(ConfigurationError,
self._callFUT, context, ISchema, {})
self.assertEqual(exc.args, ('Missing parameter:', 'no_default'))
def test_w_field_missing_but_default(self):
from zope.interface import Interface
from zope.schema import Text
from zope.configuration._compat import u
class ISchema(Interface):
w_default = Text(default=u('default'))
context = FauxContext()
self.assertEqual(self._callFUT(context, ISchema, {}),
{'w_default': 'default'})
def test_w_invalid_value(self):
from zope.interface import Interface
from zope.schema import Int
from zope.configuration.exceptions import ConfigurationError
class ISchema(Interface):
count = Int(min=0)
context = FauxContext()
exc = self.assertRaises(ConfigurationError,
self._callFUT, context, ISchema, {'count': '-1'})
self.assertEqual(exc.args, ('Invalid value for', 'count', '(-1, 0)'))
class Test_expand_action(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.config import expand_action
return expand_action(*args, **kw)
def test_defaults(self):
self.assertEqual(self._callFUT(('a', 1, None)),
{'discriminator': ('a', 1, None),
'callable': None,
'args': (),
'kw': {},
'includepath': (),
'info': None,
'order': 0,
})
def test_explicit_no_extra(self):
def _callable():
pass
self.assertEqual(self._callFUT(('a', 1, None),
_callable, ('b', 2), {'c': None},
('p', 'q/r'), 'INFO', 42,
),
{'discriminator': ('a', 1, None),
'callable': _callable,
'args': ('b', 2),
'kw': {'c': None},
'includepath': ('p', 'q/r'),
'info': 'INFO',
'order': 42,
})
def test_explicit_w_extra(self):
def _callable():
pass
self.assertEqual(self._callFUT(('a', 1, None),
_callable, ('b', 2), {'c': None},
('p', 'q/r'), 'INFO', 42,
foo='bar', baz=None,
),
{'discriminator': ('a', 1, None),
'callable': _callable,
'args': ('b', 2),
'kw': {'c': None},
'includepath': ('p', 'q/r'),
'info': 'INFO',
'order': 42,
'foo': 'bar',
'baz': None,
})
class Test_resolveConflicts(_Catchable, unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.config import resolveConflicts
return resolveConflicts(*args, **kw)
def test_empty(self):
self.assertEqual(self._callFUT(()), [])
def test_expands_oldstyle_actions(self):
def _callable():
pass
self.assertEqual(self._callFUT([(None, _callable)]),
[{'discriminator': None,
'callable': _callable,
'args': (),
'kw': {},
'includepath': (),
'info': None,
'order': 0,
}])
def test_wo_discriminator_clash(self):
from zope.configuration.config import expand_action
def _a():
pass
def _b():
pass
def _c():
pass
def _d():
pass
actions = [expand_action(('a', 1), _a, order=3),
expand_action(('b', 2), _b, order=1),
expand_action(('c', 3), _c, order=2),
expand_action(('d', 4), _d, order=1),
]
self.assertEqual([x['callable'] for x in self._callFUT(actions)],
[_b, _d, _c, _a])
def test_w_resolvable_discriminator_clash(self):
from zope.configuration.config import expand_action
def _a():
pass
def _b():
pass
actions = [expand_action(('a', 1), _a, includepath=('a',)),
expand_action(('a', 1), _b, includepath=('a', 'b')),
]
self.assertEqual([x['callable'] for x in self._callFUT(actions)],
[_a])
def test_w_non_resolvable_discriminator_clash_different_paths(self):
from zope.configuration.config import ConfigurationConflictError
from zope.configuration.config import expand_action
def _a():
pass
def _b():
pass
actions = [expand_action(('a', 1), _a, includepath=('b','c'), info='X'),
expand_action(('a', 1), _b, includepath=('a',), info='Y'),
]
exc = self.assertRaises(ConfigurationConflictError,
self._callFUT, actions)
self.assertEqual(exc._conflicts, {('a', 1): ['Y', 'X']})
def test_w_non_resolvable_discriminator_clash_same_path(self):
from zope.configuration.config import ConfigurationConflictError
from zope.configuration.config import expand_action
def _a():
pass
def _b():
pass
actions = [expand_action(('a', 1), _a, includepath=('a',), info='X'),
expand_action(('a', 1), _b, includepath=('a',), info='Y'),
]
exc = self.assertRaises(ConfigurationConflictError,
self._callFUT, actions)
self.assertEqual(exc._conflicts, {('a', 1): ['X', 'Y']})
def test_wo_discriminators_final_sorting_order(self):
from zope.configuration.config import expand_action
def _a():
pass
def _b():
pass
def _c():
pass
def _d():
pass
actions = [expand_action(None, _a, order=3),
expand_action(None, _b, order=1),
expand_action(None, _c, order=2),
expand_action(None, _d, order=1),
]
self.assertEqual([x['callable'] for x in self._callFUT(actions)],
[_b, _d, _c, _a])
class FauxContext(object):
def __init__(self):
self.actions = []
def action(self, **kw):
self.actions.append(kw)
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(ConfigurationContextTests),
unittest.makeSuite(ConfigurationAdapterRegistryTests),
unittest.makeSuite(ConfigurationMachineTests),
unittest.makeSuite(SimpleStackItemTests),
unittest.makeSuite(RootStackItemTests),
unittest.makeSuite(GroupingStackItemTests),
unittest.makeSuite(ComplexStackItemTests),
unittest.makeSuite(GroupingContextDecoratorTests),
unittest.makeSuite(DirectivesHandlerTests),
unittest.makeSuite(Test_defineSimpleDirective),
unittest.makeSuite(Test_defineGroupingDirective),
unittest.makeSuite(ComplexDirectiveDefinitionTests),
unittest.makeSuite(Test_subdirective),
unittest.makeSuite(Test_provides),
unittest.makeSuite(Test_toargs),
unittest.makeSuite(Test_expand_action),
unittest.makeSuite(Test_resolveConflicts),
))
zope.configuration-4.0.3/src/zope/configuration/tests/test_name.py 0000664 0001750 0001750 00000011202 12073042162 025346 0 ustar tseaver tseaver ##############################################################################
#
# Copyright (c) 20!2 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 zope.configuration.name
"""
import unittest
class Test_resolve(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.name import resolve
return resolve(*args, **kw)
def test_top_level_module(self):
import os
self.assertTrue(self._callFUT('os') is os)
def test_nested_module(self):
import os.path
self.assertTrue(self._callFUT('os.path') is os.path)
def test_function_in_module(self):
import os.path
self.assertTrue(self._callFUT('os.path.join') is os.path.join)
def test_importable_but_not_attr_of_parent(self):
import sys
import zope.configuration.tests as zct
self.assertFalse('notyet' in zct.__dict__)
mod = self._callFUT('zope.configuration.tests.notyet')
self.assertTrue(mod is zct.notyet)
del zct.notyet
del sys.modules['zope.configuration.tests.notyet']
def test_function_in_module_relative(self):
import os.path
self.assertTrue(self._callFUT('.join', 'os.path') is os.path.join)
def test_class_in_module(self):
from zope.configuration.tests.directives import Complex
self.assertTrue(
self._callFUT('zope.configuration.tests.directives.Complex')
is Complex)
def test_class_w_same_name_as_module(self):
from zope.configuration.tests.samplepackage.NamedForClass \
import NamedForClass
self.assertTrue(
self._callFUT(
'zope.configuration.tests.samplepackage.NamedForClass+')
is NamedForClass)
self.assertTrue(
self._callFUT(
'zope.configuration.tests.samplepackage.NamedForClass.')
is NamedForClass)
class Test_getNormalizedName(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.name import getNormalizedName
return getNormalizedName(*args, **kw)
def test_no_dots(self):
self.assertEqual(self._callFUT('os', None), 'os')
def test_one_dot(self):
self.assertEqual(self._callFUT('os.path', None), 'os.path')
def test_two_dots(self):
self.assertEqual(self._callFUT('os.path.join', None), 'os.path.join')
def test_relative(self):
self.assertEqual(self._callFUT('.join', 'os.path'), 'os.path.join')
def test_repeat_plus(self):
self.assertEqual(
self._callFUT('zope.configuration.tests.NamedForClass+', None),
'zope.configuration.tests.NamedForClass+')
def test_repeat_dot(self):
self.assertEqual(
self._callFUT('zope.configuration.tests.NamedForClass.', None),
'zope.configuration.tests.NamedForClass+')
def test_repeat_inferred(self):
self.assertEqual(
self._callFUT(
'zope.configuration.tests.NamedForClass.NamedForClass', None),
'zope.configuration.tests.NamedForClass+')
class Test_path(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.name import path
return path(*args, **kw)
def test_absolute(self):
import os
absolute_path = os.path.abspath('/absolute')
self.assertEqual(self._callFUT(absolute_path),
os.path.normpath(absolute_path))
def test_relative_bogus_package(self):
self.assertRaises(ImportError,
self._callFUT, '', 'no.such.package.exists')
def test_relative_empty(self):
import os
self.assertEqual(self._callFUT('', 'zope.configuration.tests'),
os.path.dirname(__file__))
def test_relative_w_file(self):
import os
self.assertEqual(
self._callFUT('configure.zcml', 'zope.configuration.tests'),
os.path.join(os.path.dirname(__file__), 'configure.zcml'))
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(Test_resolve),
unittest.makeSuite(Test_resolve),
unittest.makeSuite(Test_path),
))
zope.configuration-4.0.3/src/zope/configuration/tests/simple.py 0000664 0001750 0001750 00000003247 12073042162 024672 0 ustar tseaver tseaver ##############################################################################
#
# 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.
#
##############################################################################
""" Utilities for the 'simple directive' section in the narrative docs.
"""
from zope.interface import Interface
from zope.schema import Text
from zope.configuration.fields import Path
from zope.configuration._compat import u
class IRegisterFile(Interface):
path = Path(
title=u("File path"),
description=u("This is the path name of the file to be registered."),
)
title = Text(
title=u("Short summary of the file"),
description=u("This will be used in file listings"),
required = False
)
class FileInfo(object):
def __init__(self, path, title, description, info):
(self.path, self.title, self.description, self.info
) = path, title, description, info
file_registry = []
def registerFile(context, path, title=u("")):
info = context.info
description = info.text.strip()
context.action(discriminator=('RegisterFile', path),
callable=file_registry.append,
args=(FileInfo(path, title, description, info),)
)
zope.configuration-4.0.3/src/zope/configuration/tests/test_xmlconfig.py 0000664 0001750 0001750 00000140636 12073042162 026432 0 ustar tseaver tseaver ##############################################################################
#
# 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 zope.configuration.xmlconfig.
"""
import unittest
from zope.configuration._compat import u
NS = u('ns')
FOO = u('foo')
XXX = u('xxx')
SPLAT = u('splat')
SPLATV = u('splatv')
A = u('a')
AVALUE = u('avalue')
B = u('b')
BVALUE = u('bvalue')
class _Catchable(object):
# Mixin for classes which need to make assertions about the exception
# instance.
def assertRaises(self, excClass, callableObj, *args, **kwargs):
# Morph stdlib version to return the raised exception
try:
callableObj(*args, **kwargs)
except excClass as exc:
return exc
if hasattr(excClass,'__name__'):
excName = excClass.__name__
else:
excName = str(excClass)
raise self.failureException("%s not raised" % excName)
class ZopeXMLConfigurationErrorTests(unittest.TestCase):
def _getTargetClass(self):
from zope.configuration.xmlconfig import ZopeXMLConfigurationError
return ZopeXMLConfigurationError
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test___str___uses_repr_of_info(self):
zxce = self._makeOne('info', Exception, 'value')
self.assertEqual(str(zxce), "'info'\n Exception: value")
class ZopeSAXParseExceptionTests(unittest.TestCase):
def _getTargetClass(self):
from zope.configuration.xmlconfig import ZopeSAXParseException
return ZopeSAXParseException
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test___str___not_a_sax_error(self):
zxce = self._makeOne(Exception('Not a SAX error'))
self.assertEqual(str(zxce), "Not a SAX error")
def test___str___w_a_sax_error(self):
zxce = self._makeOne(Exception('filename.xml:24:32:WAAA'))
self.assertEqual(str(zxce), 'File "filename.xml", line 24.32, WAAA')
class ParserInfoTests(unittest.TestCase):
_tempdir = None
def tearDown(self):
if self._tempdir is not None:
import shutil
shutil.rmtree(self._tempdir)
def _getTargetClass(self):
from zope.configuration.xmlconfig import ParserInfo
return ParserInfo
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test___repr___w_eline_ecolumn_match_line_column(self):
pi = self._makeOne('filename.xml', 24, 32)
pi.end(24, 32)
self.assertEqual(repr(pi), 'File "filename.xml", line 24.32')
def test___repr___w_eline_ecolumn_dont_match_line_column(self):
pi = self._makeOne('filename.xml', 24, 32)
pi.end(33, 21)
self.assertEqual(repr(pi), 'File "filename.xml", line 24.32-33.21')
def test___str___w_eline_ecolumn_match_line_column(self):
pi = self._makeOne('filename.xml', 24, 32)
pi.end(24, 32)
self.assertEqual(str(pi), 'File "filename.xml", line 24.32')
def test___str___w_eline_ecolumn_dont_match_line_column_bad_file(self):
pi = self._makeOne('/path/to/nonesuch.xml', 24, 32)
pi.end(33, 21)
self.assertEqual(str(pi),
'File "/path/to/nonesuch.xml", line 24.32-33.21\n'
' Could not read source.')
def test___str___w_good_file(self):
pi = self._makeOne('tests//sample.zcml', 3, 2)
pi.end(3, 57)
self.assertEqual(
str(pi),
'File "tests//sample.zcml", line 3.2-3.57\n'
' ')
class ConfigurationHandlerTests(_Catchable, unittest.TestCase):
def _getTargetClass(self):
from zope.configuration.xmlconfig import ConfigurationHandler
return ConfigurationHandler
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_ctor_defaults(self):
context = FauxContext()
handler = self._makeOne(context)
self.assertTrue(handler.context is context)
self.assertFalse(handler.testing)
self.assertEqual(handler.ignore_depth, 0)
def test_ctor_explicit(self):
context = FauxContext()
handler = self._makeOne(context, True)
self.assertTrue(handler.context is context)
self.assertTrue(handler.testing)
self.assertEqual(handler.ignore_depth, 0)
self.assertTrue(handler.locator is None)
def test_setDocumentLocator(self):
context = FauxContext()
locator = FauxLocator('tests//sample.zcml', 1, 1)
handler = self._makeOne(context, True)
handler.setDocumentLocator(locator)
self.assertTrue(handler.locator is locator)
def test_startElementNS_w_zcml_condition_failing(self):
from zope.configuration.xmlconfig import ZCML_CONDITION
context = FauxContext()
handler = self._makeOne(context, True)
# No locator set: we won't need it, due to a failed condition.
handler.startElementNS((NS, FOO), FOO,
{ZCML_CONDITION: 'have nonesuch',
(None, A): AVALUE,
(None, B): BVALUE,
})
self.assertEqual(handler.ignore_depth, 1)
def test_startElementNS_w_ignore_depth_already_set(self):
context = FauxContext()
handler = self._makeOne(context, True)
handler.ignore_depth = 1
# No locator set: we won't need it, as an ancestor had a
# failed condition.
handler.startElementNS((NS, FOO), FOO,
{(XXX, SPLAT): SPLATV,
(None, A): AVALUE,
(None, B): BVALUE,
})
self.assertEqual(handler.ignore_depth, 2)
def test_startElementNS_context_begin_raises_wo_testing(self):
from zope.configuration.xmlconfig import ZopeXMLConfigurationError
class ErrorContext(FauxContext):
def begin(self, *args):
raise AttributeError("xxx")
context = ErrorContext()
locator = FauxLocator('tests//sample.zcml', 1, 1)
handler = self._makeOne(context)
handler.setDocumentLocator(locator)
exc = self.assertRaises(ZopeXMLConfigurationError,
handler.startElementNS, (NS, FOO), FOO,
{(XXX, SPLAT): SPLATV,
(None, A): AVALUE,
(None, B): BVALUE,
})
self.assertEqual(exc.info.file, 'tests//sample.zcml')
self.assertEqual(exc.info.line, 1)
self.assertEqual(exc.info.column, 1)
def test_startElementNS_context_begin_raises_w_testing(self):
class ErrorContext(FauxContext):
def begin(self, *args):
raise AttributeError("xxx")
context = ErrorContext()
locator = FauxLocator('tests//sample.zcml', 1, 1)
handler = self._makeOne(context, True)
handler.setDocumentLocator(locator)
self.assertRaises(AttributeError,
handler.startElementNS, (NS, FOO), FOO,
{(XXX, SPLAT): SPLATV,
(None, A): AVALUE,
(None, B): BVALUE,
})
def test_startElementNS_normal(self):
# Integration test of startElementNS / endElementNS pair.
context = FauxContext()
locator = FauxLocator('tests//sample.zcml', 1, 1)
handler = self._makeOne(context)
handler.setDocumentLocator(locator)
handler.startElementNS((NS, FOO), FOO,
{(XXX, SPLAT): SPLATV,
(None, A): AVALUE,
(None, B): BVALUE,
})
self.assertEqual(context.info.file, 'tests//sample.zcml')
self.assertEqual(context.info.line, 1)
self.assertEqual(context.info.column, 1)
self.assertEqual(context.begin_args,
((NS, FOO),
{'a': AVALUE, 'b': BVALUE}))
self.assertFalse(context._end_called)
def test_endElementNS_w_ignore_depth_already_set(self):
context = FauxContext()
handler = self._makeOne(context, True)
handler.ignore_depth = 1
# No locator set: we won't need it, as we had a
# failed condition.
handler.endElementNS((NS, FOO), FOO)
self.assertEqual(handler.ignore_depth, 0)
def test_endElementNS_context_end_raises_wo_testing(self):
from zope.configuration.xmlconfig import ZopeXMLConfigurationError
class ErrorContext(FauxContext):
def end(self):
raise AttributeError("xxx")
class Info(object):
_line = _col = None
def end(self, line, col):
self._line, self._col = line, col
context = ErrorContext()
info = Info()
context.setInfo(info)
locator = FauxLocator('tests//sample.zcml', 1, 1)
handler = self._makeOne(context)
handler.setDocumentLocator(locator)
locator.line, locator.column = 7, 16
exc = self.assertRaises(ZopeXMLConfigurationError,
handler.endElementNS, (NS, FOO), FOO)
self.assertTrue(exc.info is context.info)
self.assertEqual(exc.info._line, 7)
self.assertEqual(exc.info._col, 16)
def test_endElementNS_context_end_raises_w_testing(self):
class ErrorContext(FauxContext):
def end(self):
raise AttributeError("xxx")
class Info(object):
_line = _col = None
def end(self, line, col):
self._line, self._col = line, col
context = ErrorContext()
info = Info()
context.setInfo(info)
locator = FauxLocator('tests//sample.zcml', 1, 1)
handler = self._makeOne(context, True)
handler.setDocumentLocator(locator)
locator.line, locator.column = 7, 16
self.assertRaises(AttributeError,
handler.endElementNS, (NS, FOO), FOO)
self.assertEqual(context.info._line, 7)
self.assertEqual(context.info._col, 16)
def test_evaluateCondition_w_have_no_args(self):
context = FauxContext()
handler = self._makeOne(context)
exc = self.assertRaises(ValueError,
handler.evaluateCondition, 'have')
self.assertEqual(str(exc.args[0]), "Feature name missing: 'have'")
def test_evaluateCondition_w_not_have_too_many_args(self):
context = FauxContext()
handler = self._makeOne(context)
exc = self.assertRaises(ValueError,
handler.evaluateCondition, 'not-have a b')
self.assertEqual(str(exc.args[0]),
"Only one feature allowed: 'not-have a b'")
def test_evaluateCondition_w_have_miss(self):
context = FauxContext()
handler = self._makeOne(context)
self.assertFalse(handler.evaluateCondition('have feature'))
def test_evaluateCondition_w_have_hit(self):
context = FauxContext()
context._features = ('feature',)
handler = self._makeOne(context)
self.assertTrue(handler.evaluateCondition('have feature'))
def test_evaluateCondition_w_not_have_miss(self):
context = FauxContext()
context._features = ('feature',)
handler = self._makeOne(context)
self.assertFalse(handler.evaluateCondition('not-have feature'))
def test_evaluateCondition_w_not_have_hit(self):
context = FauxContext()
handler = self._makeOne(context)
self.assertTrue(handler.evaluateCondition('not-have feature'))
def test_evaluateCondition_w_installed_no_args(self):
context = FauxContext()
handler = self._makeOne(context)
exc = self.assertRaises(ValueError,
handler.evaluateCondition, 'installed')
self.assertEqual(str(exc.args[0]), "Package name missing: 'installed'")
def test_evaluateCondition_w_not_installed_too_many_args(self):
context = FauxContext()
handler = self._makeOne(context)
exc = self.assertRaises(ValueError,
handler.evaluateCondition, 'not-installed a b')
self.assertEqual(str(exc.args[0]),
"Only one package allowed: 'not-installed a b'")
def test_evaluateCondition_w_installed_miss(self):
context = FauxContext()
handler = self._makeOne(context)
self.assertFalse(handler.evaluateCondition('installed nonsuch.package'))
def test_evaluateCondition_w_installed_hit(self):
context = FauxContext()
handler = self._makeOne(context)
self.assertTrue(handler.evaluateCondition('installed os'))
def test_evaluateCondition_w_not_installed_miss(self):
context = FauxContext()
handler = self._makeOne(context)
self.assertFalse(handler.evaluateCondition('not-installed os'))
def test_evaluateCondition_w_not_installed_hit(self):
context = FauxContext()
handler = self._makeOne(context)
self.assertTrue(
handler.evaluateCondition('not-installed nonsuch.package'))
def test_evaluateCondition_w_unknown_verb(self):
context = FauxContext()
handler = self._makeOne(context)
exc = self.assertRaises(ValueError,
handler.evaluateCondition, 'nonesuch')
self.assertEqual(str(exc.args[0]),
"Invalid ZCML condition: 'nonesuch'")
def test_endElementNS_normal(self):
class Info(object):
_line = _col = None
def end(self, line, col):
self._line, self._col = line, col
context = FauxContext()
info = Info()
context.setInfo(info)
locator = FauxLocator('tests//sample.zcml', 7, 16)
handler = self._makeOne(context, True)
handler.setDocumentLocator(locator)
handler.endElementNS((NS, FOO), FOO)
self.assertEqual(context.info._line, 7)
self.assertEqual(context.info._col, 16)
self.assertTrue(context._end_called)
class Test_processxmlfile(_Catchable, unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.xmlconfig import processxmlfile
return processxmlfile(*args, **kw)
def test_w_empty_xml(self):
from zope.configuration.config import ConfigurationMachine
from zope.configuration.xmlconfig import registerCommonDirectives
from zope.configuration.xmlconfig import ZopeSAXParseException
from zope.configuration._compat import StringIO
context = ConfigurationMachine()
registerCommonDirectives(context)
exc = self.assertRaises(ZopeSAXParseException,
self._callFUT, StringIO(), context)
self.assertEqual(str(exc._v), ':1:0: no element found')
def test_w_valid_xml_fp(self):
# Integration test, really
from zope.configuration.config import ConfigurationMachine
from zope.configuration.xmlconfig import registerCommonDirectives
from zope.configuration._compat import b
from zope.configuration.tests.samplepackage import foo
file = open(path("samplepackage", "configure.zcml"))
context = ConfigurationMachine()
registerCommonDirectives(context)
self._callFUT(file, context)
self.assertEqual(foo.data, [])
context.execute_actions()
data = foo.data.pop()
self.assertEqual(data.args, (('x', b('blah')), ('y', 0)))
self.assertEqual(clean_info_path(repr(data.info)),
'File "tests/samplepackage/configure.zcml", line 12.2-12.29')
self.assertEqual(clean_info_path(str(data.info)),
'File "tests/samplepackage/configure.zcml", line 12.2-12.29\n'
+ ' ')
self.assertEqual(data.package, None)
self.assertEqual(data.basepath, None)
class Test_openInOrPlain(_Catchable, unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.xmlconfig import openInOrPlain
return openInOrPlain(*args, **kw)
def _makeFilename(self, fn):
import os
from zope.configuration.tests.samplepackage import __file__
return os.path.join(os.path.dirname(__file__), fn)
def test_file_present(self):
import os
with self._callFUT(self._makeFilename('configure.zcml')) as fp:
self.assertEqual(os.path.basename(fp.name), 'configure.zcml')
def test_file_missing_but_dot_in_present(self):
import os
with self._callFUT(self._makeFilename('foo.zcml')) as fp:
self.assertEqual(os.path.basename(fp.name), 'foo.zcml.in')
def test_file_missing_and_dot_in_not_present(self):
import errno
exc = self.assertRaises(
IOError,
self._callFUT, self._makeFilename('nonesuch.zcml'))
self.assertEqual(exc.errno, errno.ENOENT)
class Test_include(_Catchable, unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.xmlconfig import include
return include(*args, **kw)
def test_both_file_and_files_passed(self):
context = FauxContext()
exc = self.assertRaises(ValueError,
self._callFUT, context, 'tests//sample.zcml',
files=['tests/*.zcml'])
self.assertEqual(str(exc), "Must specify only one of file or files")
def test_neither_file_nor_files_passed_already_seen(self):
from zope.configuration import xmlconfig
from zope.configuration.config import ConfigurationMachine
from zope.configuration.xmlconfig import registerCommonDirectives
from zope.configuration.tests import samplepackage
context = ConfigurationMachine()
registerCommonDirectives(context)
context.package = samplepackage
fqn = _packageFile(samplepackage, 'configure.zcml')
context._seen_files.add(fqn)
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
self._callFUT(context) #skips
self.assertEqual(len(logger.debugs), 0)
self.assertEqual(len(context.actions), 0)
def test_neither_file_nor_files_passed(self):
from zope.configuration import xmlconfig
from zope.configuration.config import ConfigurationMachine
from zope.configuration.xmlconfig import registerCommonDirectives
from zope.configuration.tests import samplepackage
from zope.configuration.tests.samplepackage import foo
context = ConfigurationMachine()
registerCommonDirectives(context)
before_stack = context.stack[:]
context.package = samplepackage
fqn = _packageFile(samplepackage, 'configure.zcml')
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
self._callFUT(context)
self.assertEqual(len(logger.debugs), 1)
self.assertEqual(logger.debugs[0], ('include %s' % fqn, (), {}))
self.assertEqual(len(context.actions), 1)
action = context.actions[0]
self.assertEqual(action['callable'], foo.data.append)
self.assertEqual(action['includepath'], (fqn,))
self.assertEqual(context.stack, before_stack)
self.assertEqual(len(context._seen_files), 1)
self.assertTrue(fqn in context._seen_files)
def test_w_file_passed(self):
from zope.configuration import xmlconfig
from zope.configuration.config import ConfigurationMachine
from zope.configuration.xmlconfig import registerCommonDirectives
from zope.configuration import tests
from zope.configuration.tests import simple
context = ConfigurationMachine()
registerCommonDirectives(context)
before_stack = context.stack[:]
context.package = tests
fqn = _packageFile(tests, 'simple.zcml')
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
self._callFUT(context, 'simple.zcml')
self.assertEqual(len(logger.debugs), 1)
self.assertEqual(logger.debugs[0], ('include %s' % fqn, (), {}))
self.assertEqual(len(context.actions), 3)
action = context.actions[0]
self.assertEqual(action['callable'], simple.file_registry.append)
self.assertEqual(action['includepath'], (fqn,))
self.assertEqual(action['args'][0].path,
_packageFile(tests, 'simple.py'))
action = context.actions[1]
self.assertEqual(action['callable'], simple.file_registry.append)
self.assertEqual(action['includepath'], (fqn,))
self.assertEqual(action['args'][0].path,
_packageFile(tests, 'simple.zcml'))
action = context.actions[2]
self.assertEqual(action['callable'], simple.file_registry.append)
self.assertEqual(action['includepath'], (fqn,))
self.assertEqual(action['args'][0].path,
_packageFile(tests, '__init__.py'))
self.assertEqual(context.stack, before_stack)
self.assertEqual(len(context._seen_files), 1)
self.assertTrue(fqn in context._seen_files)
def test_w_files_passed_and_package(self):
from zope.configuration import xmlconfig
from zope.configuration.config import ConfigurationMachine
from zope.configuration.xmlconfig import registerCommonDirectives
from zope.configuration._compat import b
from zope.configuration.tests import samplepackage
from zope.configuration.tests.samplepackage import foo
context = ConfigurationMachine()
registerCommonDirectives(context)
before_stack = context.stack[:]
fqn1 = _packageFile(samplepackage, 'baz1.zcml')
fqn2 = _packageFile(samplepackage, 'baz2.zcml')
fqn3 = _packageFile(samplepackage, 'baz3.zcml')
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
self._callFUT(context, package=samplepackage, files='baz*.zcml')
self.assertEqual(len(logger.debugs), 3)
self.assertEqual(logger.debugs[0], ('include %s' % fqn1, (), {}))
self.assertEqual(logger.debugs[1], ('include %s' % fqn2, (), {}))
self.assertEqual(logger.debugs[2], ('include %s' % fqn3, (), {}))
self.assertEqual(len(context.actions), 2)
action = context.actions[0]
self.assertEqual(action['callable'], foo.data.append)
self.assertEqual(action['includepath'], (fqn2,))
self.assertTrue(isinstance(action['args'][0], foo.stuff))
self.assertEqual(action['args'][0].args, (('x', b('foo')), ('y', 2)))
action = context.actions[1]
self.assertEqual(action['callable'], foo.data.append)
self.assertEqual(action['includepath'], (fqn3,))
self.assertTrue(isinstance(action['args'][0], foo.stuff))
self.assertEqual(action['args'][0].args, (('x', b('foo')), ('y', 3)))
self.assertEqual(context.stack, before_stack)
self.assertEqual(len(context._seen_files), 3)
self.assertTrue(fqn1 in context._seen_files)
self.assertTrue(fqn2 in context._seen_files)
self.assertTrue(fqn3 in context._seen_files)
class Test_exclude(_Catchable, unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.xmlconfig import exclude
return exclude(*args, **kw)
def test_both_file_and_files_passed(self):
context = FauxContext()
exc = self.assertRaises(ValueError,
self._callFUT, context, 'tests//sample.zcml',
files=['tests/*.zcml'])
self.assertEqual(str(exc), "Must specify only one of file or files")
def test_neither_file_nor_files_passed(self):
from zope.configuration.config import ConfigurationMachine
from zope.configuration.tests import samplepackage
context = ConfigurationMachine()
context.package = samplepackage
fqn = _packageFile(samplepackage, 'configure.zcml')
self._callFUT(context)
self.assertEqual(len(context.actions), 0)
self.assertEqual(len(context._seen_files), 1)
self.assertTrue(fqn in context._seen_files)
def test_w_file_passed(self):
from zope.configuration.config import ConfigurationMachine
from zope.configuration import tests
context = ConfigurationMachine()
context.package = tests
fqn = _packageFile(tests, 'simple.zcml')
self._callFUT(context, 'simple.zcml')
self.assertEqual(len(context.actions), 0)
self.assertEqual(len(context._seen_files), 1)
self.assertTrue(fqn in context._seen_files)
def test_w_files_passed_and_package(self):
from zope.configuration.config import ConfigurationMachine
from zope.configuration.tests import samplepackage
context = ConfigurationMachine()
fqn1 = _packageFile(samplepackage, 'baz1.zcml')
fqn2 = _packageFile(samplepackage, 'baz2.zcml')
fqn3 = _packageFile(samplepackage, 'baz3.zcml')
self._callFUT(context, package=samplepackage, files='baz*.zcml')
self.assertEqual(len(context.actions), 0)
self.assertEqual(len(context._seen_files), 3)
self.assertTrue(fqn1 in context._seen_files)
self.assertTrue(fqn2 in context._seen_files)
self.assertTrue(fqn3 in context._seen_files)
def test_w_subpackage(self):
from zope.configuration.config import ConfigurationMachine
from zope.configuration.tests import excludedemo
from zope.configuration.tests.excludedemo import sub
context = ConfigurationMachine()
fqne_spam = _packageFile(excludedemo, 'spam.zcml')
fqne_config = _packageFile(excludedemo, 'configure.zcml')
fqns_config = _packageFile(sub, 'configure.zcml')
self._callFUT(context, package=sub)
self.assertEqual(len(context.actions), 0)
self.assertEqual(len(context._seen_files), 1)
self.assertFalse(fqne_spam in context._seen_files)
self.assertFalse(fqne_config in context._seen_files)
self.assertTrue(fqns_config in context._seen_files)
class Test_includeOverrides(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.xmlconfig import includeOverrides
return includeOverrides(*args, **kw)
def test_actions_have_parents_includepath(self):
from zope.configuration import xmlconfig
from zope.configuration.config import ConfigurationMachine
from zope.configuration.xmlconfig import registerCommonDirectives
from zope.configuration import tests
from zope.configuration.tests import simple
context = ConfigurationMachine()
fqp = _packageFile(tests, 'configure.zcml')
registerCommonDirectives(context)
before_stack = context.stack[:]
context.package = tests
# dummy action, path from "previous" include
context.includepath = (fqp,)
def _callable():
pass
context.actions.append({'discriminator': None,
'callable': _callable,
})
fqn = _packageFile(tests, 'simple.zcml')
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
self._callFUT(context, 'simple.zcml')
self.assertEqual(len(logger.debugs), 1)
self.assertEqual(logger.debugs[0], ('include %s' % fqn, (), {}))
self.assertEqual(len(context.actions), 4)
action = context.actions[0]
self.assertEqual(action['discriminator'], None)
self.assertEqual(action['callable'], _callable)
action = context.actions[1]
self.assertEqual(action['callable'], simple.file_registry.append)
self.assertEqual(action['includepath'], (fqp,))
self.assertEqual(action['args'][0].path,
_packageFile(tests, 'simple.py'))
action = context.actions[2]
self.assertEqual(action['callable'], simple.file_registry.append)
self.assertEqual(action['includepath'], (fqp,))
self.assertEqual(action['args'][0].path,
_packageFile(tests, 'simple.zcml'))
action = context.actions[3]
self.assertEqual(action['callable'], simple.file_registry.append)
self.assertEqual(action['includepath'], (fqp,))
self.assertEqual(action['args'][0].path,
_packageFile(tests, '__init__.py'))
self.assertEqual(context.stack, before_stack)
self.assertEqual(len(context._seen_files), 1)
self.assertTrue(fqn in context._seen_files)
class Test_file(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.xmlconfig import file
return file(*args, **kw)
def test_wo_execute_wo_context_wo_package(self):
from zope.configuration import xmlconfig
from zope.configuration._compat import b
from zope.configuration.tests.samplepackage import foo
file_name = path("samplepackage", "configure.zcml")
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
context = self._callFUT(file_name, execute=False)
self.assertEqual(len(logger.debugs), 1)
self.assertEqual(logger.debugs[0], ('include %s' % file_name, (), {}))
self.assertEqual(len(foo.data), 0)
self.assertEqual(len(context.actions), 1)
action = context.actions[0]
self.assertEqual(action['discriminator'], (('x', b('blah')), ('y', 0)))
self.assertEqual(action['callable'], foo.data.append)
def test_wo_execute_wo_context_w_package(self):
from zope.configuration import xmlconfig
from zope.configuration._compat import b
from zope.configuration.tests import samplepackage
from zope.configuration.tests.samplepackage import foo
file_name = path("samplepackage", "configure.zcml")
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
context = self._callFUT('configure.zcml', package=samplepackage,
execute=False)
self.assertEqual(len(logger.debugs), 1)
self.assertEqual(logger.debugs[0], ('include %s' % file_name, (), {}))
self.assertEqual(len(foo.data), 0)
self.assertTrue(context.package is samplepackage)
self.assertEqual(len(context.actions), 1)
action = context.actions[0]
self.assertEqual(action['discriminator'], (('x', b('blah')), ('y', 0)))
self.assertEqual(action['callable'], foo.data.append)
def test_wo_execute_w_context(self):
from zope.configuration import xmlconfig
from zope.configuration.config import ConfigurationMachine
from zope.configuration.xmlconfig import registerCommonDirectives
from zope.configuration._compat import b
from zope.configuration.tests import samplepackage
from zope.configuration.tests.samplepackage import foo
context = ConfigurationMachine()
context.package = samplepackage
registerCommonDirectives(context)
file_name = path("samplepackage", "configure.zcml")
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
ret = self._callFUT('configure.zcml', context=context,
execute=False)
self.assertTrue(ret is context)
self.assertEqual(len(logger.debugs), 1)
self.assertEqual(logger.debugs[0], ('include %s' % file_name, (), {}))
self.assertEqual(len(foo.data), 0)
self.assertEqual(len(context.actions), 1)
action = context.actions[0]
self.assertEqual(action['discriminator'], (('x', b('blah')), ('y', 0)))
self.assertEqual(action['callable'], foo.data.append)
def test_w_execute(self):
import os
from zope.configuration import xmlconfig
from zope.configuration._compat import b
from zope.configuration.tests.samplepackage import foo
file_name = path("samplepackage", "configure.zcml")
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
context = self._callFUT(file_name)
self.assertEqual(len(logger.debugs), 1)
self.assertEqual(logger.debugs[0], ('include %s' % file_name, (), {}))
data = foo.data.pop()
self.assertEqual(data.args, (('x', b('blah')), ('y', 0)))
self.assertTrue(data.info.file.endswith(
os.path.normpath('tests/samplepackage/configure.zcml')))
self.assertEqual(data.info.line, 12)
self.assertEqual(data.info.column, 2)
self.assertEqual(data.info.eline, 12)
self.assertEqual(data.info.ecolumn, 29)
self.assertEqual(data.package, None)
self.assertTrue(data.basepath.endswith(
os.path.normpath('tests/samplepackage')))
class Test_string(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration.xmlconfig import string
return string(*args, **kw)
def test_wo_execute_wo_context(self):
from zope.configuration._compat import b
from zope.configuration.tests.samplepackage import foo
file_name = path("samplepackage", "configure.zcml")
with open(file_name) as f:
xml = f.read()
context = self._callFUT(xml, execute=False)
self.assertEqual(len(foo.data), 0)
self.assertEqual(len(context.actions), 1)
action = context.actions[0]
self.assertEqual(action['discriminator'], (('x', b('blah')), ('y', 0)))
self.assertEqual(action['callable'], foo.data.append)
def test_wo_execute_w_context(self):
from zope.configuration.config import ConfigurationMachine
from zope.configuration.xmlconfig import registerCommonDirectives
from zope.configuration._compat import b
from zope.configuration.tests.samplepackage import foo
context = ConfigurationMachine()
registerCommonDirectives(context)
file_name = path("samplepackage", "configure.zcml")
with open(file_name) as f:
xml = f.read()
ret = self._callFUT(xml, context=context, execute=False)
self.assertTrue(ret is context)
self.assertEqual(len(foo.data), 0)
self.assertEqual(len(context.actions), 1)
action = context.actions[0]
self.assertEqual(action['discriminator'], (('x', b('blah')), ('y', 0)))
self.assertEqual(action['callable'], foo.data.append)
def test_w_execute(self):
from zope.configuration._compat import b
from zope.configuration.tests.samplepackage import foo
file_name = path("samplepackage", "configure.zcml")
with open(file_name) as f:
xml = f.read()
context = self._callFUT(xml)
data = foo.data.pop()
self.assertEqual(data.args, (('x', b('blah')), ('y', 0)))
self.assertTrue(data.info.file, '')
self.assertEqual(data.info.line, 12)
self.assertEqual(data.info.column, 2)
self.assertEqual(data.info.eline, 12)
self.assertEqual(data.info.ecolumn, 29)
self.assertEqual(data.package, None)
self.assertEqual(data.basepath, None)
class XMLConfigTests(unittest.TestCase):
def setUp(self):
from zope.configuration.xmlconfig import _clearContext
from zope.configuration.tests.samplepackage.foo import data
_clearContext()
del data[:]
def tearDown(self):
from zope.configuration.xmlconfig import _clearContext
from zope.configuration.tests.samplepackage.foo import data
_clearContext()
del data[:]
def _getTargetClass(self):
from zope.configuration.xmlconfig import XMLConfig
return XMLConfig
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_ctor_w_global_context_missing(self):
import os
from zope.configuration import xmlconfig
from zope.configuration._compat import b
from zope.configuration.tests.samplepackage import foo
here = os.path.dirname(__file__)
path = os.path.join(here, "samplepackage", "configure.zcml")
logger = LoggerStub()
xmlconfig._context = None
with _Monkey(xmlconfig, logger=logger):
xc = self._makeOne(path)
self.assertEqual(len(logger.debugs), 1)
self.assertEqual(logger.debugs[0], ('include %s' % path, (), {}))
self.assertEqual(len(foo.data), 0) # no execut_actions
self.assertEqual(len(xc.context.actions), 1)
action = xc.context.actions[0]
self.assertEqual(action['discriminator'], (('x', b('blah')), ('y', 0)))
self.assertEqual(action['callable'], foo.data.append)
def test_ctor(self):
from zope.configuration import xmlconfig
from zope.configuration._compat import b
from zope.configuration.tests import samplepackage
from zope.configuration.tests.samplepackage import foo
fqn = _packageFile(samplepackage, 'configure.zcml')
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
xc = self._makeOne(fqn)
self.assertEqual(len(logger.debugs), 1)
self.assertEqual(logger.debugs[0], ('include %s' % fqn, (), {}))
self.assertEqual(len(foo.data), 0) # no execut_actions
self.assertEqual(len(xc.context.actions), 1)
action = xc.context.actions[0]
self.assertEqual(action['discriminator'], (('x', b('blah')), ('y', 0)))
self.assertEqual(action['callable'], foo.data.append)
def test_ctor_w_module(self):
from zope.configuration import xmlconfig
from zope.configuration._compat import b
from zope.configuration.tests.samplepackage import foo
from zope.configuration.tests import samplepackage
fqn = _packageFile(samplepackage, 'configure.zcml')
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
xc = self._makeOne("configure.zcml", samplepackage)
self.assertEqual(len(logger.debugs), 1)
self.assertEqual(logger.debugs[0], ('include %s' % fqn, (), {}))
self.assertEqual(len(foo.data), 0) # no execut_actions
self.assertEqual(len(xc.context.actions), 1)
action = xc.context.actions[0]
self.assertEqual(action['discriminator'], (('x', b('blah')), ('y', 0)))
self.assertEqual(action['callable'], foo.data.append)
def test___call__(self):
import os
from zope.configuration import xmlconfig
from zope.configuration._compat import b
from zope.configuration.tests import samplepackage
from zope.configuration.tests.samplepackage import foo
fqn = _packageFile(samplepackage, 'configure.zcml')
logger = LoggerStub()
with _Monkey(xmlconfig, logger=logger):
xc = self._makeOne(fqn)
self.assertEqual(len(logger.debugs), 1)
self.assertEqual(logger.debugs[0], ('include %s' % fqn, (), {}))
self.assertEqual(len(foo.data), 0)
xc() # call to process the actions
self.assertEqual(len(foo.data), 1)
data = foo.data.pop(0)
self.assertEqual(data.args, (('x', b('blah')), ('y', 0)))
self.assertTrue(data.info.file.endswith(
os.path.normpath('tests/samplepackage/configure.zcml')))
self.assertEqual(data.info.line, 12)
self.assertEqual(data.info.column, 2)
self.assertEqual(data.info.eline, 12)
self.assertEqual(data.info.ecolumn, 29)
class Test_xmlconfig(unittest.TestCase):
def setUp(self):
from zope.configuration.xmlconfig import _clearContext
from zope.configuration.tests.samplepackage.foo import data
_clearContext()
del data[:]
def tearDown(self):
from zope.configuration.xmlconfig import _clearContext
from zope.configuration.tests.samplepackage.foo import data
_clearContext()
del data[:]
def _callFUT(self, *args, **kw):
from zope.configuration.xmlconfig import xmlconfig
return xmlconfig(*args, **kw)
def test_wo_testing_passed(self):
import os
from zope.configuration import xmlconfig
from zope.configuration._compat import b
from zope.configuration.tests import samplepackage
from zope.configuration.tests.samplepackage import foo
def _assertTestingFalse(func):
def _wrapper(*args, **kw):
assert(not kw['testing'])
return func(*args, **kw)
return _wrapper
fqn = _packageFile(samplepackage, 'configure.zcml')
context = xmlconfig._getContext()
context.execute_actions = _assertTestingFalse(context.execute_actions)
with _Monkey(xmlconfig,
processxmlfile=_assertTestingFalse(
xmlconfig.processxmlfile)):
self._callFUT(open(fqn), False)
self.assertEqual(len(foo.data), 1)
data = foo.data.pop(0)
self.assertEqual(data.args, (('x', b('blah')), ('y', 0)))
self.assertTrue(data.info.file.endswith(
os.path.normpath('tests/samplepackage/configure.zcml')))
self.assertEqual(data.info.line, 12)
self.assertEqual(data.info.column, 2)
self.assertEqual(data.info.eline, 12)
self.assertEqual(data.info.ecolumn, 29)
def test_w_testing_passed(self):
import os
from zope.configuration import xmlconfig
from zope.configuration._compat import b
from zope.configuration.tests import samplepackage
from zope.configuration.tests.samplepackage import foo
def _assertTestingTrue(func):
def _wrapper(*args, **kw):
assert(kw['testing'])
return func(*args, **kw)
return _wrapper
fqn = _packageFile(samplepackage, 'configure.zcml')
context = xmlconfig._getContext()
context.execute_actions = _assertTestingTrue(context.execute_actions)
with _Monkey(xmlconfig,
processxmlfile=_assertTestingTrue(
xmlconfig.processxmlfile)):
self._callFUT(open(fqn), True)
self.assertEqual(len(foo.data), 1)
data = foo.data.pop(0)
self.assertEqual(data.args, (('x', b('blah')), ('y', 0)))
self.assertTrue(data.info.file.endswith(
os.path.normpath('tests/samplepackage/configure.zcml')))
self.assertEqual(data.info.line, 12)
self.assertEqual(data.info.column, 2)
self.assertEqual(data.info.eline, 12)
self.assertEqual(data.info.ecolumn, 29)
class Test_testxmlconfig(unittest.TestCase):
def setUp(self):
from zope.configuration.xmlconfig import _clearContext
from zope.configuration.tests.samplepackage.foo import data
_clearContext()
del data[:]
def tearDown(self):
from zope.configuration.xmlconfig import _clearContext
from zope.configuration.tests.samplepackage.foo import data
_clearContext()
del data[:]
def _callFUT(self, *args, **kw):
from zope.configuration.xmlconfig import testxmlconfig
return testxmlconfig(*args, **kw)
def test_w_testing_passed(self):
import os
from zope.configuration import xmlconfig
from zope.configuration._compat import b
from zope.configuration.tests import samplepackage
from zope.configuration.tests.samplepackage import foo
def _assertTestingTrue(func):
def _wrapper(*args, **kw):
assert(kw['testing'])
return func(*args, **kw)
return _wrapper
fqn = _packageFile(samplepackage, 'configure.zcml')
context = xmlconfig._getContext()
context.execute_actions = _assertTestingTrue(context.execute_actions)
with _Monkey(xmlconfig,
processxmlfile=_assertTestingTrue(
xmlconfig.processxmlfile)):
self._callFUT(open(fqn))
self.assertEqual(len(foo.data), 1)
data = foo.data.pop(0)
self.assertEqual(data.args, (('x', b('blah')), ('y', 0)))
self.assertTrue(data.info.file.endswith(
os.path.normpath('tests/samplepackage/configure.zcml')))
self.assertEqual(data.info.line, 12)
self.assertEqual(data.info.column, 2)
self.assertEqual(data.info.eline, 12)
self.assertEqual(data.info.ecolumn, 29)
class FauxLocator(object):
def __init__(self, file, line, column):
self.file, self.line, self.column = file, line, column
def getSystemId(self):
return self.file
def getLineNumber(self):
return self.line
def getColumnNumber(self):
return self.column
class FauxContext(object):
includepath = ()
_features = ()
_end_called = False
def setInfo(self, info):
self.info = info
def getInfo(self):
return self.info
def begin(self, name, data, info):
self.begin_args = name, data
self.info = info
def end(self):
self._end_called = 1
def hasFeature(self, feature):
return feature in self._features
def path(*p):
import os
return os.path.join(os.path.dirname(__file__), *p)
def clean_info_path(s):
import os
part1 = s[:6]
part2 = s[6:s.find('"', 6)]
part2 = part2[part2.rfind("tests"):]
part2 = part2.replace(os.sep, '/')
part3 = s[s.find('"', 6):].rstrip()
return part1+part2+part3
def clean_path(s):
import os
s = s[s.rfind("tests"):]
s = s.replace(os.sep, '/')
return s
def clean_actions(actions):
return [
{'discriminator': action['discriminator'],
'info': clean_info_path(repr(action['info'])),
'includepath': [clean_path(p) for p in action['includepath']],
}
for action in actions
]
def clean_text_w_paths(error):
r = []
for line in unicode(error).split("\n"):
line = line.rstrip()
if not line:
continue
l = line.find('File "')
if l >= 0:
line = line[:l] + clean_info_path(line[l:])
r.append(line)
return '\n'.join(r)
def _packageFile(package, filename):
import os
return os.path.join(os.path.dirname(package.__file__), filename)
class _Monkey(object):
def __init__(self, module, **replacements):
self.module = module
self.orig = {}
self.replacements = replacements
def __enter__(self):
for k, v in self.replacements.items():
orig = getattr(self.module, k, self)
if orig is not self:
self.orig[k] = orig
setattr(self.module, k, v)
def __exit__(self, *exc_info):
for k, v in self.replacements.items():
if k in self.orig:
setattr(self.module, k, self.orig[k])
else: #pragma NO COVERSGE
delattr(self.module, k)
class LoggerStub(object):
def __init__(self):
self.errors = []
self.warnings = []
self.infos = []
self.debugs = []
def error(self, msg, *args, **kwargs):
self.errors.append((msg, args, kwargs))
def warning(self, msg, *args, **kwargs):
self.warnings.append((msg, args, kwargs))
def info(self, msg, *args, **kwargs):
self.infos.append((msg, args, kwargs))
def debug(self, msg, *args, **kwargs):
self.debugs.append((msg, args, kwargs))
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(ZopeXMLConfigurationErrorTests),
unittest.makeSuite(ZopeSAXParseExceptionTests),
unittest.makeSuite(ParserInfoTests),
unittest.makeSuite(ConfigurationHandlerTests),
unittest.makeSuite(Test_processxmlfile),
unittest.makeSuite(Test_openInOrPlain),
unittest.makeSuite(Test_include),
unittest.makeSuite(Test_exclude),
unittest.makeSuite(Test_includeOverrides),
unittest.makeSuite(Test_file),
unittest.makeSuite(Test_string),
unittest.makeSuite(XMLConfigTests),
unittest.makeSuite(Test_xmlconfig),
unittest.makeSuite(Test_testxmlconfig),
))
zope.configuration-4.0.3/src/zope/configuration/tests/excludedemo/ 0000775 0001750 0001750 00000000000 12312363233 025320 5 ustar tseaver tseaver zope.configuration-4.0.3/src/zope/configuration/tests/excludedemo/__init__.py 0000664 0001750 0001750 00000000002 12073042162 027420 0 ustar tseaver tseaver #
zope.configuration-4.0.3/src/zope/configuration/tests/excludedemo/spam.zcml 0000664 0001750 0001750 00000000016 12073042162 027143 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/excludedemo/sub/ 0000775 0001750 0001750 00000000000 12312363233 026111 5 ustar tseaver tseaver zope.configuration-4.0.3/src/zope/configuration/tests/excludedemo/sub/__init__.py 0000664 0001750 0001750 00000000002 12073042162 030211 0 ustar tseaver tseaver #
zope.configuration-4.0.3/src/zope/configuration/tests/excludedemo/sub/configure.zcml 0000664 0001750 0001750 00000000016 12073042162 030755 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/excludedemo/configure.zcml 0000664 0001750 0001750 00000000123 12073042162 030163 0 ustar tseaver tseaver
zope.configuration-4.0.3/src/zope/configuration/tests/conditions.zcml 0000664 0001750 0001750 00000003764 12073042162 026073 0 ustar tseaver tseaver
This registers a directive which creates registrations we can test.
ZCML directives inside here should be included.
This registration should be included.
ZCML directives inside here should be ignored.
This registration should be ignored.
zope.configuration-4.0.3/src/zope/configuration/tests/bad.py 0000664 0001750 0001750 00000000115 12073042162 024116 0 ustar tseaver tseaver # I'm bad. I want to be bad. Don't try to change me.
import bad_to_the_bone
zope.configuration-4.0.3/src/zope/configuration/tests/test___init__.py 0000664 0001750 0001750 00000002314 12073042162 026171 0 ustar tseaver tseaver ##############################################################################
#
# Copyright (c) 20!2 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 zope.configuration.__init__
"""
import unittest
class Test_namespace(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.configuration import namespace
return namespace(*args, **kw)
def test_empty(self):
self.assertEqual(self._callFUT(''),
'http://namespaces.zope.org/')
def test_non_empty(self):
self.assertEqual(self._callFUT('test'),
'http://namespaces.zope.org/test')
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(Test_namespace),
))
zope.configuration-4.0.3/src/zope/configuration/tests/schema.zcml 0000664 0001750 0001750 00000003052 12073042162 025150 0 ustar tseaver tseaver
Define a schema
Use field directives (e.g. text and int directives) to define
the schema fields.
Define a text field
Define an integer field
Sample interface I1
A
Blah blah
B
Not feeling very creative
Sample interface I2
X
zope.configuration-4.0.3/src/zope/configuration/tests/nested.py 0000664 0001750 0001750 00000010305 12073042162 024654 0 ustar tseaver tseaver ##############################################################################
#
# 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.
#
##############################################################################
""" Utilities for the 'nested directive' section in the narrative docs.
"""
from zope.interface import Attribute
from zope.interface import Interface
from zope.interface import implementer
from zope.schema import BytesLine
from zope.schema import Id
from zope.schema import Int
from zope.schema import Text
from zope.schema import TextLine
from zope.configuration.config import GroupingContextDecorator
from zope.configuration.config import IConfigurationContext
from zope.configuration.fields import Bool
from zope.configuration._compat import u
schema_registry = {}
class ISchemaInfo(Interface):
"""Parameter schema for the schema directive
"""
name = TextLine(
title=u("The schema name"),
description=u("This is a descriptive name for the schema."),
)
id = Id(title=u("The unique id for the schema"))
class ISchema(Interface):
"""Interface that distinguishes the schema directive
"""
fields = Attribute("Dictionary of field definitions")
@implementer(IConfigurationContext, ISchema)
class Schema(GroupingContextDecorator):
"""Handle schema directives
"""
def __init__(self, context, name, id):
self.context, self.name, self.id = context, name, id
self.fields = {}
def after(self):
schema = Interface.__class__(
self.name,
(Interface, ),
self.fields
)
schema.__doc__ = self.info.text.strip()
self.action(
discriminator=('schema', self.id),
callable=schema_registry.__setitem__,
args=(self.id, schema),
)
class IFieldInfo(Interface):
name = BytesLine(
title=u("The field name"),
)
title = TextLine(
title=u("Title"),
description=u("A short summary or label"),
default=u(""),
required=False,
)
required = Bool(
title=u("Required"),
description=u("Determines whether a value is required."),
default=True)
readonly = Bool(
title=u("Read Only"),
description=u("Can the value be modified?"),
required=False,
default=False)
class ITextInfo(IFieldInfo):
min_length = Int(
title=u("Minimum length"),
description=u("Value after whitespace processing cannot have less than "
"min_length characters. If min_length is None, there is "
"no minimum."),
required=False,
min=0, # needs to be a positive number
default=0)
max_length = Int(
title=u("Maximum length"),
description=u("Value after whitespace processing cannot have greater "
"or equal than max_length characters. If max_length is "
"None, there is no maximum."),
required=False,
min=0, # needs to be a positive number
default=None)
def field(context, constructor, name, **kw):
# Compute the field
field = constructor(description=context.info.text.strip(), **kw)
# Save it in the schema's field dictionary
schema = context.context
if name in schema.fields:
raise ValueError("Duplicate field", name)
schema.fields[name] = field
def textField(context, **kw):
field(context, Text, **kw)
class IIntInfo(IFieldInfo):
min = Int(
title=u("Start of the range"),
required=False,
default=None
)
max = Int(
title=u("End of the range (excluding the value itself)"),
required=False,
default=None
)
def intField(context, **kw):
field(context, Int, **kw)
zope.configuration-4.0.3/src/zope/configuration/zopeconfigure.py 0000664 0001750 0001750 00000014022 12073042162 025107 0 ustar tseaver tseaver ##############################################################################
#
# Copyright (c) 2001, 2002, 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.
#
##############################################################################
"""Zope configure directive
This file contains the implementation of the Zope configure directive.
It is broken out in a separate file to provide an example of a grouping
directive.
The zope configuration directive is a pure grouping directive. It
doesn't compute any actions on it's own. Instead, it allows a package
to be specified, affecting the interpretation of relative dotted names
and file paths. It also allows an i18n domain to be specified. The
information collected is used by subdirectives.
To define a grouping directive, we need to do three things:
- Define a schema for the parameters passed to the directive
- Define a handler class.
- Register the class
The parameter schema is given by IZopeConfigure. It specifies a
package parameter and an i18n_domain parameter. The package parameter
is specified as a ``GlobalObject``. This means it must be given as a
dotted name that can be resolved through import. The i18n domain is
just a plain (not unicode) string.
The handler class has a constructor that takes a context to be adapted
and zero or more arguments (depending on the paramter schema). The
handler class must implement
``zope.configuration.interfaces.IGroupingContext``, which defines
hooks ``before`` and ``after``, that are called with no arguments
before and after nested directives are processed. If a grouping
directive handler creates any actions, or does any computation, this
is normally done in either the ``before`` or ``after`` hooks.
Grouping handlers are normally decorators.
The base class,
``zope.configuration.config.GroupingContextDecorator``, is normally
used to define grouping directive handlers. It provides:
- An implementation of IConfigurationContext, which grouping directive
handlers should normally implement,
- A default implementation of ``IGroupingContext`` that provides empty
hooks.
- Decorator support that uses a ``__getattr__`` method to delegate
attribute accesses to adapted contexts, and
- A constructor that sets the ``context`` attribute to the adapted
context and assigns keyword arguments to attributes.
The ``ZopeConfigure`` provides handling for the ``configure``
directive. It subclasses GroupingContextDecorator, and overrides the
constructor to set the ``basepath`` attribute if a ``package`` argument
is provided. Note that it delegates the job of assigning paramters to
attribute to the ``GroupingContextDecorator`` constructor.
The last step is to register the directive using the meta
configuration directive. If we wanted to register the Zope
``configure`` directive for the ``zope`` namespace, we'd use a
meta-configuration directive like::
Zope configure
The ``configure`` node is normally used as the root node for a
configuration file. It can also be used to specify a package or
internationalization domain for a group of directives within a
file by grouping those directives.
We use the groupingDirective meta-directive to register a grouping
directive. The parameters are self explanatory. The textual contents
of the directive provide documentation text, excluding parameter
documentation, which is provided by the schema.
(The Zope ``configuration`` directive is actually registered using a
lower-level Python API because it is registered for all namespaces,
which isn't supported using the meta-configuration directives.)
"""
__docformat__ = 'restructuredtext'
import os
from zope.interface import Interface
from zope.schema import BytesLine
from zope.configuration.config import GroupingContextDecorator
from zope.configuration.fields import GlobalObject
from zope.configuration._compat import u
class IZopeConfigure(Interface):
"""The ``zope:configure`` Directive
The zope configuration directive is a pure grouping directive. It
doesn't compute any actions on it's own. Instead, it allows a package to
be specified, affecting the interpretation of relative dotted names and
file paths. It also allows an i18n domain to be specified. The
information collected is used by subdirectives.
It may seem that this directive can only be used once per file, but it can
be applied whereever it is convenient.
"""
package = GlobalObject(
title=u("Package"),
description=u("The package to be used for evaluating relative imports "
"and file names."),
required=False)
i18n_domain = BytesLine(
title=u("Internationalization domain"),
description=u("This is a name for the software project. It must be a "
"legal file-system name as it will be used to contruct "
"names for directories containing translation data. "
"\n"
"The domain defines a namespace for the message ids "
"used by a project."),
required=False)
class ZopeConfigure(GroupingContextDecorator):
__doc__ = __doc__
def __init__(self, context, **kw):
super(ZopeConfigure, self).__init__(context, **kw)
if 'package' in kw:
# if we have a package, we want to also define basepath
# so we don't acquire one
self.basepath = os.path.dirname(self.package.__file__)
zope.configuration-4.0.3/src/zope/configuration/exceptions.py 0000664 0001750 0001750 00000001374 12073042162 024417 0 ustar tseaver tseaver ##############################################################################
#
# 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.
#
##############################################################################
"""Standard configuration errors
"""
class ConfigurationError(Exception):
"""There was an error in a configuration
"""
zope.configuration-4.0.3/COPYRIGHT.txt 0000664 0001750 0001750 00000000040 12073042162 017347 0 ustar tseaver tseaver Zope Foundation and Contributors zope.configuration-4.0.3/CHANGES.rst 0000664 0001750 0001750 00000010144 12312363166 017054 0 ustar tseaver tseaver zope.configuration Changelog
============================
4.0.3 (2014-03-19)
------------------
- Added explicit support for Python 3.4.
4.0.2 (2012-12-31)
------------------
- Fleshed out PyPI Trove classifiers.
- Removed spurious declaration of 'test' dependency on ``zope.testing``.
4.0.1 (2012-11-21)
------------------
- Added support for Python 3.3.
- Removed the deprecated 'zope.configuration.stxdocs' script.
and made the 'zope.configuration.tests.conditions' helper module
(used in running Sphinx doctest snippets) Py3k compatible.
https://bugs.launchpad.net/zope.configuration/+bug/1025390
4.0.0 (2012-05-16)
------------------
- 100% unit test coverage.
- Automated build of Sphinx HTML docs and running doctest snippets via tox.
- Dropped hard testing dependency on ``zope.testing``.
- Added explicit support for PyPy.
- Added explicit support for Python 3.2.
- Dropped explicit support for Python 2.4 / 2.5.
- Added support for continuous integration using ``tox`` and ``jenkins``.
- Added ``Sphinx`` documentation.
- Added ``setup.py docs`` alias (installs ``Sphinx`` and dependencies).
- Added ``setup.py dev`` alias (runs ``setup.py develop`` plus installs
``nose`` and ``coverage``).
3.8.1 (2012-05-05)
------------------
- Fixed Python 2.4 backwards incompat (itemgetter used with multiple args);
Python 2.4 now works (at least if you use zope.schema == 3.8.1).
This is the last release which will support Python 2.4 or 2.5.
3.8.0 (2011-12-06)
------------------
- Action structures changed from tuples to dictionaries to allow for action
structure extensibility (merged chrism-dictactions branch).
3.7.4 (2011-04-03)
------------------
- Test fixes for Windows.
3.7.3 (2011-03-11)
------------------
- Correctly locate packages with a __path__ attribute but no
__file__ attribute (such as namespace packages installed with setup.py
install --single-version-externally-managed).
- Allow "info" and "includepath" to be passed optionally to context.action.
3.7.2 (2010-04-30)
------------------
- Prefer the standard libraries doctest module over zope.testing.doctest.
3.7.1 (2010-01-05)
------------------
- Jython support: use ``__builtin__`` module import rather than assuming
``__builtins__`` is available.
- Jython support: deal with the fact that the Jython SAX parser
returns attribute sets that have an empty string indicating no
namespace instead of ``None``.
- Allow ``setup.py test`` to run at least a subset of the tests that
would be run when using the zope testrunner: ``setup.py test`` runs
53 tests, while ``bin/test`` runs 156.
3.7.0 (2009-12-22)
------------------
- Adjust testing output to newer zope.schema.
- Prefer zope.testing.doctest over doctestunit.
3.6.0 (2009-04-01)
------------------
- Removed dependency of `zope.deprecation` package.
- Don't suppress deprecation warnings any more in 'zope.configuration'
package level. This makes it more likely other packages will generate
deprecation warnings now, which will allow us to remove more
outdated ones.
- Don't fail when zope.testing is not installed.
- Added missing ``processFile`` method to ``IConfigurationContext``.
It is already implemented in the mix-in class,
``zope.configuration.config.ConfigurationContext``, and used by
implementations of ``include`` and ``exclude`` directives.
3.5.0 (2009-02-26)
------------------
- Added the ``exclude`` directive to standard directives. It was
previously available via ``zc.configuration`` package and now it's
merged into ``zope.configuration``.
- Changed package's mailing list address to zope-dev at zope.org,
change "cheeseshop" to "pypi" in the package's url.
3.4.1 (2008-12-11)
------------------
- Use built-in 'set' type, rather than importin the 'sets' module,
which is deprecated in Python 2.6.
- Added support to bootstrap on Jython.
3.4.0 (2007-10-02)
------------------
- Initial release as a standalone package.
Before 3.4.0
------------
This package was part of the Zope 3 distribution and did not have its own
CHANGES.txt. For earlier changes please refer to either our subversion log or
the CHANGES.txt of earlier Zope 3 releases.
zope.configuration-4.0.3/LICENSE.txt 0000664 0001750 0001750 00000004026 12073042162 017071 0 ustar tseaver tseaver 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.configuration-4.0.3/README.rst 0000664 0001750 0001750 00000000764 12073042162 016742 0 ustar tseaver tseaver zope.configuration README
=========================
The zope configuration system provides an extensible system for
supporting various kinds of configurations.
It is based on the idea of configuration directives. Users of the
configuration system provide configuration directives in some
language that express configuration choices. The intent is that the
language be pluggable. An XML language is provided by default.
Please see http://docs.zope.org/zope.configuration/ for the documentation.
zope.configuration-4.0.3/docs/ 0000775 0001750 0001750 00000000000 12312363233 016175 5 ustar tseaver tseaver zope.configuration-4.0.3/docs/api.rst 0000664 0001750 0001750 00000000362 12073042162 017500 0 ustar tseaver tseaver :mod:`zope.configuration` API Reference
=======================================
.. toctree::
:maxdepth: 2
api/config
api/docutils
api/exceptions
api/fields
api/interfaces
api/name
api/xmlconfig
api/zopeconfigure
zope.configuration-4.0.3/docs/make.bat 0000664 0001750 0001750 00000011776 12073042162 017615 0 ustar tseaver tseaver @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\zopeconfiguration.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\zopeconfiguration.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.configuration-4.0.3/docs/Makefile 0000664 0001750 0001750 00000012750 12073042162 017641 0 ustar tseaver tseaver # 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/zopeconfiguration.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/zopeconfiguration.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/zopeconfiguration"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/zopeconfiguration"
@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.configuration-4.0.3/docs/api/ 0000775 0001750 0001750 00000000000 12312363233 016746 5 ustar tseaver tseaver zope.configuration-4.0.3/docs/api/exceptions.rst 0000664 0001750 0001750 00000000230 12073042162 021653 0 ustar tseaver tseaver :mod:`zope.configuration.exceptions`
====================================
.. module:: zope.configuration.exceptions
.. autoclass:: ConfigurationError
zope.configuration-4.0.3/docs/api/xmlconfig.rst 0000664 0001750 0001750 00000012710 12073042162 021466 0 ustar tseaver tseaver :mod:`zope.configuration.xmlconfig`
===================================
.. module:: zope.configuration.xmlconfig
.. autoclass:: ZopeXMLConfigurationError
Example
.. doctest::
>>> from zope.configuration.xmlconfig import ZopeXMLConfigurationError
>>> v = ZopeXMLConfigurationError("blah", AttributeError, "xxx")
>>> print v
'blah'
AttributeError: xxx
.. autoclass:: ZopeSAXParseException
Example
.. doctest::
>>> from zope.configuration.xmlconfig import ZopeSAXParseException
>>> v = ZopeSAXParseException("foo.xml:12:3:Not well formed")
>>> print v
File "foo.xml", line 12.3, Not well formed
.. autoclass:: ParserInfo
:members:
:member-order: bysource
Example
.. doctest::
>>> from zope.configuration.xmlconfig import ParserInfo
>>> info = ParserInfo('tests//sample.zcml', 1, 0)
>>> info
File "tests//sample.zcml", line 1.0
>>> print info
File "tests//sample.zcml", line 1.0
>>> info.characters("blah\\n")
>>> info.characters("blah")
>>> info.text
u'blah\\nblah'
>>> info.end(7, 0)
>>> info
File "tests//sample.zcml", line 1.0-7.0
>>> print info
File "tests//sample.zcml", line 1.0-7.0
.. autoclass:: ConfigurationHandler
.. automethod:: evaluateCondition
The ``have`` and ``not-have`` verbs each take one argument: the name
of a feature:
.. doctest::
>>> from zope.configuration.config import ConfigurationContext
>>> from zope.configuration.xmlconfig import ConfigurationHandler
>>> context = ConfigurationContext()
>>> context.provideFeature('apidoc')
>>> c = ConfigurationHandler(context, testing=True)
>>> c.evaluateCondition("have apidoc")
True
>>> c.evaluateCondition("not-have apidoc")
False
>>> c.evaluateCondition("have onlinehelp")
False
>>> c.evaluateCondition("not-have onlinehelp")
True
Ill-formed expressions raise an error:
.. doctest::
>>> c.evaluateCondition("want apidoc")
Traceback (most recent call last):
...
ValueError: Invalid ZCML condition: 'want apidoc'
>>> c.evaluateCondition("have x y")
Traceback (most recent call last):
...
ValueError: Only one feature allowed: 'have x y'
>>> c.evaluateCondition("have")
Traceback (most recent call last):
...
ValueError: Feature name missing: 'have'
The ``installed`` and ``not-installed`` verbs each take one argument:
the dotted name of a pacakge.
If the pacakge is found, in other words, can be imported,
then the condition will return true / false:
.. doctest::
>>> context = ConfigurationContext()
>>> c = ConfigurationHandler(context, testing=True)
>>> c.evaluateCondition('installed zope.interface')
True
>>> c.evaluateCondition('not-installed zope.interface')
False
>>> c.evaluateCondition('installed zope.foo')
False
>>> c.evaluateCondition('not-installed zope.foo')
True
Ill-formed expressions raise an error:
.. doctest::
>>> c.evaluateCondition("installed foo bar")
Traceback (most recent call last):
...
ValueError: Only one package allowed: 'installed foo bar'
>>> c.evaluateCondition("installed")
Traceback (most recent call last):
...
ValueError: Package name missing: 'installed'
.. autofunction:: processxmlfile
.. autofunction:: openInOrPlain
For example, the tests/samplepackage dirextory has files:
- configure.zcml
- configure.zcml.in
- foo.zcml.in
If we open configure.zcml, we'll get that file:
.. doctest::
>>> import os
>>> from zope.configuration.xmlconfig import __file__
>>> from zope.configuration.xmlconfig import openInOrPlain
>>> here = os.path.dirname(__file__)
>>> path = os.path.join(here, 'tests', 'samplepackage', 'configure.zcml')
>>> f = openInOrPlain(path)
>>> f.name[-14:]
'configure.zcml'
But if we open foo.zcml, we'll get foo.zcml.in, since there isn't a
foo.zcml:
.. doctest::
>>> path = os.path.join(here, 'tests', 'samplepackage', 'foo.zcml')
>>> f = openInOrPlain(path)
>>> f.name[-11:]
'foo.zcml.in'
Make sure other IOErrors are re-raised. We need to do this in a
try-except block because different errors are raised on Windows and
on Linux.
.. doctest::
>>> try:
... f = openInOrPlain('.')
... except IOError:
... print "passed"
... else:
... print "failed"
passed
.. autointerface:: IInclude
:members:
:member-order: bysource
.. autofunction:: include
.. autofunction:: exclude
.. autofunction:: includeOverrides
.. autofunction:: registerCommonDirectives
.. autofunction:: file
.. autofunction:: string
.. autoclass:: XMLConfig
:members:
:member-order: bysource
.. autofunction:: xmlconfig
.. autofunction:: testxmlconfig
zope.configuration-4.0.3/docs/api/zopeconfigure.rst 0000664 0001750 0001750 00000000423 12073042162 022355 0 ustar tseaver tseaver :mod:`zope.configuration.zopeconfigure`
=======================================
.. automodule:: zope.configuration.zopeconfigure
.. autointerface:: IZopeConfigure
:members:
:member-order: bysource
.. autoclass:: ZopeConfigure
:members:
:member-order: bysource
zope.configuration-4.0.3/docs/api/name.rst 0000664 0001750 0001750 00000000273 12073042162 020421 0 ustar tseaver tseaver :mod:`zope.configuration.name`
==============================
.. module:: zope.configuration.name
.. autofunction:: resolve
.. autofunction:: getNormalizedName
.. autofunction:: path
zope.configuration-4.0.3/docs/api/docutils.rst 0000664 0001750 0001750 00000001074 12073042162 021327 0 ustar tseaver tseaver :mod:`zope.configuration.docutils`
==================================
.. module:: zope.configuration.docutils
.. autofunction:: wrap
Examples:
.. doctest::
>>> from zope.configuration.docutils import wrap
>>> print wrap('foo bar')[:-2]
foo bar
>>> print wrap('foo bar', indent=2)[:-2]
foo bar
>>> print wrap('foo bar, more foo bar', 10)[:-2]
foo bar,
more foo
bar
>>> print wrap('foo bar, more foo bar', 10, 2)[:-2]
foo bar,
more foo
bar
.. autofunction:: makeDocStructures
zope.configuration-4.0.3/docs/api/config.rst 0000664 0001750 0001750 00000070033 12073042162 020747 0 ustar tseaver tseaver :mod:`zope.configuration.config`
================================
.. module:: zope.configuration.config
.. autoclass:: ConfigurationContext
.. automethod:: resolve
Examples:
.. doctest::
>>> from zope.configuration.config import ConfigurationContext
>>> from zope.configuration.config import ConfigurationError
>>> c = ConfigurationContext()
>>> import zope, zope.interface
>>> c.resolve('zope') is zope
True
>>> c.resolve('zope.interface') is zope.interface
True
>>> c.resolve('zope.configuration.eek') #doctest: +NORMALIZE_WHITESPACE
Traceback (most recent call last):
...
ConfigurationError:
ImportError: Module zope.configuration has no global eek
>>> c.resolve('.config.ConfigurationContext')
Traceback (most recent call last):
...
AttributeError: 'ConfigurationContext' object has no attribute 'package'
>>> import zope.configuration
>>> c.package = zope.configuration
>>> c.resolve('.') is zope.configuration
True
>>> c.resolve('.config.ConfigurationContext') is ConfigurationContext
True
>>> c.resolve('..interface') is zope.interface
True
>>> c.resolve('str')
.. automethod:: path
Examples:
.. doctest::
>>> import os
>>> from zope.configuration.config import ConfigurationContext
>>> c = ConfigurationContext()
>>> c.path("/x/y/z") == os.path.normpath("/x/y/z")
True
>>> c.path("y/z")
Traceback (most recent call last):
...
AttributeError: 'ConfigurationContext' object has no attribute 'package'
>>> import zope.configuration
>>> c.package = zope.configuration
>>> import os
>>> d = os.path.dirname(zope.configuration.__file__)
>>> c.path("y/z") == d + os.path.normpath("/y/z")
True
>>> c.path("y/./z") == d + os.path.normpath("/y/z")
True
>>> c.path("y/../z") == d + os.path.normpath("/z")
True
.. automethod:: checkDuplicate
Examples:
.. doctest::
>>> from zope.configuration.config import ConfigurationContext
>>> from zope.configuration.config import ConfigurationError
>>> c = ConfigurationContext()
>>> c.checkDuplicate('/foo.zcml')
>>> try:
... c.checkDuplicate('/foo.zcml')
... except ConfigurationError as e:
... # On Linux the exact msg has /foo, on Windows \foo.
... str(e).endswith("foo.zcml' included more than once")
True
You may use different ways to refer to the same file:
.. doctest::
>>> import zope.configuration
>>> c.package = zope.configuration
>>> import os
>>> d = os.path.dirname(zope.configuration.__file__)
>>> c.checkDuplicate('bar.zcml')
>>> try:
... c.checkDuplicate(d + os.path.normpath('/bar.zcml'))
... except ConfigurationError as e:
... str(e).endswith("bar.zcml' included more than once")
...
True
.. automethod:: processFile
Examples:
.. doctest::
>>> from zope.configuration.config import ConfigurationContext
>>> c = ConfigurationContext()
>>> c.processFile('/foo.zcml')
True
>>> c.processFile('/foo.zcml')
False
You may use different ways to refer to the same file:
.. doctest::
>>> import zope.configuration
>>> c.package = zope.configuration
>>> import os
>>> d = os.path.dirname(zope.configuration.__file__)
>>> c.processFile('bar.zcml')
True
>>> c.processFile('bar.zcml')
False
.. automethod:: action
Examples:
.. doctest::
>>> from zope.configuration.config import ConfigurationContext
>>> c = ConfigurationContext()
Normally, the context gets actions from subclasses. We'll provide
an actions attribute ourselves:
.. doctest::
>>> c.actions = []
We'll use a test callable that has a convenient string representation
.. doctest::
>>> from zope.configuration.tests.directives import f
>>> c.action(1, f, (1, ), {'x': 1})
>>> from pprint import PrettyPrinter
>>> pprint=PrettyPrinter(width=60).pprint
>>> pprint(c.actions)
[{'args': (1,),
'callable': f,
'discriminator': 1,
'includepath': (),
'info': '',
'kw': {'x': 1},
'order': 0}]
>>> c.action(None)
>>> pprint(c.actions)
[{'args': (1,),
'callable': f,
'discriminator': 1,
'includepath': (),
'info': '',
'kw': {'x': 1},
'order': 0},
{'args': (),
'callable': None,
'discriminator': None,
'includepath': (),
'info': '',
'kw': {},
'order': 0}]
Now set the include path and info:
.. doctest::
>>> c.includepath = ('foo.zcml',)
>>> c.info = "?"
>>> c.action(None)
>>> pprint(c.actions[-1])
{'args': (),
'callable': None,
'discriminator': None,
'includepath': ('foo.zcml',),
'info': '?',
'kw': {},
'order': 0}
We can add an order argument to crudely control the order
of execution:
.. doctest::
>>> c.action(None, order=99999)
>>> pprint(c.actions[-1])
{'args': (),
'callable': None,
'discriminator': None,
'includepath': ('foo.zcml',),
'info': '?',
'kw': {},
'order': 99999}
We can also pass an includepath argument, which will be used as the the
includepath for the action. (if includepath is None, self.includepath
will be used):
.. doctest::
>>> c.action(None, includepath=('abc',))
>>> pprint(c.actions[-1])
{'args': (),
'callable': None,
'discriminator': None,
'includepath': ('abc',),
'info': '?',
'kw': {},
'order': 0}
We can also pass an info argument, which will be used as the the
source line info for the action. (if info is None, self.info will be
used):
.. doctest::
>>> c.action(None, info='abc')
>>> pprint(c.actions[-1])
{'args': (),
'callable': None,
'discriminator': None,
'includepath': ('foo.zcml',),
'info': 'abc',
'kw': {},
'order': 0}
.. automethod:: hasFeature
Examples:
.. doctest::
>>> from zope.configuration.config import ConfigurationContext
>>> c = ConfigurationContext()
>>> c.hasFeature('onlinehelp')
False
You can declare that a feature is provided
.. doctest::
>>> c.provideFeature('onlinehelp')
and it becomes available
.. doctest::
>>> c.hasFeature('onlinehelp')
True
.. automethod:: provideFeature
.. autoclass:: ConfigurationAdapterRegistry
:members:
:member-order: bysource
Examples:
.. doctest::
>>> from zope.configuration.interfaces import IConfigurationContext
>>> from zope.configuration.config import ConfigurationAdapterRegistry
>>> from zope.configuration.config import ConfigurationError
>>> from zope.configuration.config import ConfigurationMachine
>>> r = ConfigurationAdapterRegistry()
>>> c = ConfigurationMachine()
>>> r.factory(c, ('http://www.zope.com','xxx'))
Traceback (most recent call last):
...
ConfigurationError: ('Unknown directive', 'http://www.zope.com', 'xxx')
>>> def f():
... pass
>>> r.register(IConfigurationContext, ('http://www.zope.com', 'xxx'), f)
>>> r.factory(c, ('http://www.zope.com','xxx')) is f
True
>>> r.factory(c, ('http://www.zope.com','yyy')) is f
Traceback (most recent call last):
...
ConfigurationError: ('Unknown directive', 'http://www.zope.com', 'yyy')
>>> r.register(IConfigurationContext, 'yyy', f)
>>> r.factory(c, ('http://www.zope.com','yyy')) is f
True
Test the documentation feature:
.. doctest::
>>> from zope.configuration.config import IFullInfo
>>> r._docRegistry
[]
>>> r.document(('ns', 'dir'), IFullInfo, IConfigurationContext, None,
... 'inf', None)
>>> r._docRegistry[0][0] == ('ns', 'dir')
True
>>> r._docRegistry[0][1] is IFullInfo
True
>>> r._docRegistry[0][2] is IConfigurationContext
True
>>> r._docRegistry[0][3] is None
True
>>> r._docRegistry[0][4] == 'inf'
True
>>> r._docRegistry[0][5] is None
True
>>> r.document('all-dir', None, None, None, None)
>>> r._docRegistry[1][0]
('', 'all-dir')
.. autoclass:: ConfigurationMachine
Example:
.. doctest::
>>> from zope.configuration.config import ConfigurationMachine
>>> machine = ConfigurationMachine()
>>> ns = "http://www.zope.org/testing"
Register a directive:
.. doctest::
>>> from zope.configuration.config import metans
>>> machine((metans, "directive"),
... namespace=ns, name="simple",
... schema="zope.configuration.tests.directives.ISimple",
... handler="zope.configuration.tests.directives.simple")
and try it out:
.. doctest::
>>> machine((ns, "simple"), a=u"aa", c=u"cc")
>>> from pprint import PrettyPrinter
>>> pprint = PrettyPrinter(width=60).pprint
>>> pprint(machine.actions)
[{'args': (u'aa', u'xxx', 'cc'),
'callable': f,
'discriminator': ('simple', u'aa', u'xxx', 'cc'),
'includepath': (),
'info': None,
'kw': {},
'order': 0}]
.. automethod:: begin
.. automethod:: end
.. automethod:: __call__
.. automethod:: getInfo
.. automethod:: setInfo
.. automethod:: execute_actions
For example:
.. doctest::
>>> from zope.configuration.config import ConfigurationMachine
>>> output = []
>>> def f(*a, **k): #* syntax highlighting
... output.append(('f', a, k))
>>> context = ConfigurationMachine()
>>> context.actions = [
... (1, f, (1,)),
... (1, f, (11,), {}, ('x', )),
... (2, f, (2,)),
... ]
>>> context.execute_actions()
>>> output
[('f', (1,), {}), ('f', (2,), {})]
If the action raises an error, we convert it to a
ConfigurationExecutionError.
.. doctest::
>>> from zope.configuration.config import ConfigurationExecutionError
>>> output = []
>>> def bad():
... bad.xxx
>>> context.actions = [
... (1, f, (1,)),
... (1, f, (11,), {}, ('x', )),
... (2, f, (2,)),
... (3, bad, (), {}, (), 'oops')
... ]
>>> try:
... v = context.execute_actions()
... except ConfigurationExecutionError as v:
... pass
>>> lines = str(v).splitlines()
>>> 'exceptions.AttributeError' in lines[0]
True
>>> lines[0].endswith("'function' object has no attribute 'xxx'")
True
>>> lines[1:]
[' in:', ' oops']
Note that actions executed before the error still have an effect:
.. doctest::
>>> output
[('f', (1,), {}), ('f', (2,), {})]
.. autoclass:: ConfigurationExecutionError
.. autointerface:: IStackItem
:members:
:member-order: bysource
.. autoclass:: SimpleStackItem
:members:
:member-order: bysource
.. autoclass:: RootStackItem
:members:
:member-order: bysource
.. autoclass:: GroupingStackItem
:members:
:member-order: bysource
To see how this works, let's look at an example:
We need a context. We'll just use a configuration machine
.. doctest::
>>> from zope.configuration.config import GroupingStackItem
>>> from zope.configuration.config import ConfigurationMachine
>>> context = ConfigurationMachine()
We need a callable to use in configuration actions. We'll use a
convenient one from the tests:
.. doctest::
>>> from zope.configuration.tests.directives import f
We need a handler for the grouping directive. This is a class
that implements a context decorator. The decorator must also
provide ``before`` and ``after`` methods that are called before
and after any contained directives are processed. We'll typically
subclass ``GroupingContextDecorator``, which provides context
decoration, and default ``before`` and ``after`` methods.
.. doctest::
>>> from zope.configuration.config import GroupingContextDecorator
>>> class SampleGrouping(GroupingContextDecorator):
... def before(self):
... self.action(('before', self.x, self.y), f)
... def after(self):
... self.action(('after'), f)
We'll use our decorator to decorate our initial context, providing
keyword arguments x and y:
.. doctest::
>>> dec = SampleGrouping(context, x=1, y=2)
Note that the keyword arguments are made attributes of the
decorator.
Now we'll create the stack item.
.. doctest::
>>> item = GroupingStackItem(dec)
We still haven't called the before action yet, which we can verify
by looking at the context actions:
.. doctest::
>>> context.actions
[]
Subdirectives will get looked up as adapters of the context.
We'll create a simple handler:
.. doctest::
>>> def simple(context, data, info):
... context.action(("simple", context.x, context.y, data), f)
... return info
and register it with the context:
.. doctest::
>>> from zope.configuration.interfaces import IConfigurationContext
>>> from zope.configuration.config import testns
>>> context.register(IConfigurationContext, (testns, 'simple'), simple)
This handler isn't really a propert handler, because it doesn't
return a new context. It will do for this example.
Now we'll call the contained method on the stack item:
.. doctest::
>>> item.contained((testns, 'simple'), {'z': 'zope'}, "someinfo")
'someinfo'
We can verify thet the simple method was called by looking at the
context actions. Note that the before method was called before
handling the contained directive.
.. doctest::
>>> from pprint import PrettyPrinter
>>> pprint = PrettyPrinter(width=60).pprint
>>> pprint(context.actions)
[{'args': (),
'callable': f,
'discriminator': ('before', 1, 2),
'includepath': (),
'info': '',
'kw': {},
'order': 0},
{'args': (),
'callable': f,
'discriminator': ('simple', 1, 2, {'z': 'zope'}),
'includepath': (),
'info': '',
'kw': {},
'order': 0}]
Finally, we call finish, which calls the decorator after method:
.. doctest::
>>> item.finish()
>>> pprint(context.actions)
[{'args': (),
'callable': f,
'discriminator': ('before', 1, 2),
'includepath': (),
'info': '',
'kw': {},
'order': 0},
{'args': (),
'callable': f,
'discriminator': ('simple', 1, 2, {'z': 'zope'}),
'includepath': (),
'info': '',
'kw': {},
'order': 0},
{'args': (),
'callable': f,
'discriminator': 'after',
'includepath': (),
'info': '',
'kw': {},
'order': 0}]
If there were no nested directives:
.. doctest::
>>> context = ConfigurationMachine()
>>> dec = SampleGrouping(context, x=1, y=2)
>>> item = GroupingStackItem(dec)
>>> item.finish()
Then before will be when we call finish:
.. doctest::
>>> pprint(context.actions)
[{'args': (),
'callable': f,
'discriminator': ('before', 1, 2),
'includepath': (),
'info': '',
'kw': {},
'order': 0},
{'args': (),
'callable': f,
'discriminator': 'after',
'includepath': (),
'info': '',
'kw': {},
'order': 0}]
.. autoclass:: ComplexStackItem
:members:
:member-order: bysource
To see how this works, let's look at an example:
We need a context. We'll just use a configuration machine
.. doctest::
>>> from zope.configuration.config import ConfigurationMachine
>>> context = ConfigurationMachine()
We need a callable to use in configuration actions. We'll use a
convenient one from the tests:
.. doctest::
>>> from zope.configuration.tests.directives import f
We need a handler for the complex directive. This is a class
with a method for each subdirective:
.. doctest::
>>> class Handler(object):
... def __init__(self, context, x, y):
... self.context, self.x, self.y = context, x, y
... context.action('init', f)
... def sub(self, context, a, b):
... context.action(('sub', a, b), f)
... def __call__(self):
... self.context.action(('call', self.x, self.y), f)
We need a complex directive definition:
.. doctest::
>>> from zope.interface import Interface
>>> from zope.schema import TextLine
>>> from zope.configuration.config import ComplexDirectiveDefinition
>>> class Ixy(Interface):
... x = TextLine()
... y = TextLine()
>>> definition = ComplexDirectiveDefinition(
... context, name="test", schema=Ixy,
... handler=Handler)
>>> class Iab(Interface):
... a = TextLine()
... b = TextLine()
>>> definition['sub'] = Iab, ''
OK, now that we have the context, handler and definition, we're
ready to use a stack item.
.. doctest::
>>> from zope.configuration.config import ComplexStackItem
>>> item = ComplexStackItem(definition, context, {'x': u'xv', 'y': u'yv'},
... 'foo')
When we created the definition, the handler (factory) was called.
.. doctest::
>>> from pprint import PrettyPrinter
>>> pprint = PrettyPrinter(width=60).pprint
>>> pprint(context.actions)
[{'args': (),
'callable': f,
'discriminator': 'init',
'includepath': (),
'info': 'foo',
'kw': {},
'order': 0}]
If a subdirective is provided, the ``contained`` method of the stack item
is called. It will lookup the subdirective schema and call the
corresponding method on the handler instance:
.. doctest::
>>> simple = item.contained(('somenamespace', 'sub'),
... {'a': u'av', 'b': u'bv'}, 'baz')
>>> simple.finish()
Note that the name passed to ``contained`` is a 2-part name, consisting of
a namespace and a name within the namespace.
.. doctest::
>>> pprint(context.actions)
[{'args': (),
'callable': f,
'discriminator': 'init',
'includepath': (),
'info': 'foo',
'kw': {},
'order': 0},
{'args': (),
'callable': f,
'discriminator': ('sub', u'av', u'bv'),
'includepath': (),
'info': 'baz',
'kw': {},
'order': 0}]
The new stack item returned by contained is one that doesn't allow
any more subdirectives,
When all of the subdirectives have been provided, the ``finish``
method is called:
.. doctest::
>>> item.finish()
The stack item will call the handler if it is callable.
.. doctest::
>>> pprint(context.actions)
[{'args': (),
'callable': f,
'discriminator': 'init',
'includepath': (),
'info': 'foo',
'kw': {},
'order': 0},
{'args': (),
'callable': f,
'discriminator': ('sub', u'av', u'bv'),
'includepath': (),
'info': 'baz',
'kw': {},
'order': 0},
{'args': (),
'callable': f,
'discriminator': ('call', u'xv', u'yv'),
'includepath': (),
'info': 'foo',
'kw': {},
'order': 0}]
.. autoclass:: GroupingContextDecorator
:members:
:member-order: bysource
.. autoclass:: DirectiveSchema
:members:
:member-order: bysource
.. autointerface:: IDirectivesInfo
:members:
:member-order: bysource
.. autointerface:: IDirectivesContext
:members:
:member-order: bysource
.. autoclass:: DirectivesHandler
:members:
:member-order: bysource
.. autointerface:: IDirectiveInfo
:members:
:member-order: bysource
.. autointerface:: IFullInfo
:members:
:member-order: bysource
.. autointerface:: IStandaloneDirectiveInfo
:members:
:member-order: bysource
.. autofunction:: defineSimpleDirective
Example:
.. doctest::
>>> from zope.configuration.config import ConfigurationMachine
>>> context = ConfigurationMachine()
>>> from zope.interface import Interface
>>> from zope.schema import TextLine
>>> from zope.configuration.tests.directives import f
>>> class Ixy(Interface):
... x = TextLine()
... y = TextLine()
>>> def s(context, x, y):
... context.action(('s', x, y), f)
>>> from zope.configuration.config import defineSimpleDirective
>>> defineSimpleDirective(context, 's', Ixy, s, testns)
>>> context((testns, "s"), x=u"vx", y=u"vy")
>>> from pprint import PrettyPrinter
>>> pprint = PrettyPrinter(width=60).pprint
>>> pprint(context.actions)
[{'args': (),
'callable': f,
'discriminator': ('s', u'vx', u'vy'),
'includepath': (),
'info': None,
'kw': {},
'order': 0}]
>>> context(('http://www.zope.com/t1', "s"), x=u"vx", y=u"vy")
Traceback (most recent call last):
...
ConfigurationError: ('Unknown directive', 'http://www.zope.com/t1', 's')
>>> context = ConfigurationMachine()
>>> defineSimpleDirective(context, 's', Ixy, s, "*")
>>> context(('http://www.zope.com/t1', "s"), x=u"vx", y=u"vy")
>>> pprint(context.actions)
[{'args': (),
'callable': f,
'discriminator': ('s', u'vx', u'vy'),
'includepath': (),
'info': None,
'kw': {},
'order': 0}]
.. autofunction:: defineGroupingDirective
Example:
.. doctest::
>>> from zope.configuration.config import ConfigurationMachine
>>> context = ConfigurationMachine()
>>> from zope.interface import Interface
>>> from zope.schema import TextLine
>>> from zope.configuration.tests.directives import f
>>> class Ixy(Interface):
... x = TextLine()
... y = TextLine()
We won't bother creating a special grouping directive class. We'll
just use :class:`GroupingContextDecorator`, which simply sets up a
grouping context that has extra attributes defined by a schema:
.. doctest::
>>> from zope.configuration.config import defineGroupingDirective
>>> from zope.configuration.config import GroupingContextDecorator
>>> defineGroupingDirective(context, 'g', Ixy,
... GroupingContextDecorator, testns)
>>> context.begin((testns, "g"), x=u"vx", y=u"vy")
>>> context.stack[-1].context.x
u'vx'
>>> context.stack[-1].context.y
u'vy'
>>> context(('http://www.zope.com/t1', "g"), x=u"vx", y=u"vy")
Traceback (most recent call last):
...
ConfigurationError: ('Unknown directive', 'http://www.zope.com/t1', 'g')
>>> context = ConfigurationMachine()
>>> defineGroupingDirective(context, 'g', Ixy,
... GroupingContextDecorator, "*")
>>> context.begin(('http://www.zope.com/t1', "g"), x=u"vx", y=u"vy")
>>> context.stack[-1].context.x
u'vx'
>>> context.stack[-1].context.y
u'vy'
.. autointerface:: IComplexDirectiveContext
:members:
:member-order: bysource
.. autoclass:: ComplexDirectiveDefinition
:members:
:member-order: bysource
.. autofunction:: subdirective
.. autointerface:: IProvidesDirectiveInfo
:members:
:member-order: bysource
.. autofunction:: provides
Example:
.. doctest::
>>> from zope.configuration.config import ConfigurationContext
>>> from zope.configuration.config import provides
>>> c = ConfigurationContext()
>>> provides(c, 'apidoc')
>>> c.hasFeature('apidoc')
True
Spaces are not allowed in feature names (this is reserved for providing
many features with a single directive in the futute).
.. doctest::
>>> provides(c, 'apidoc onlinehelp')
Traceback (most recent call last):
...
ValueError: Only one feature name allowed
>>> c.hasFeature('apidoc onlinehelp')
False
.. autofunction:: toargs
Example:
.. doctest::
>>> from zope.configuration.config import toargs
>>> from zope.schema import BytesLine
>>> from zope.schema import Float
>>> from zope.schema import Int
>>> from zope.schema import TextLine
>>> from zope.schema import URI
>>> class schema(Interface):
... in_ = Int(constraint=lambda v: v > 0)
... f = Float()
... n = TextLine(min_length=1, default=u"rob")
... x = BytesLine(required=False)
... u = URI()
>>> context = ConfigurationMachine()
>>> from pprint import PrettyPrinter
>>> pprint=PrettyPrinter(width=50).pprint
>>> pprint(toargs(context, schema,
... {'in': u'1', 'f': u'1.2', 'n': u'bob', 'x': u'x.y.z',
... 'u': u'http://www.zope.org' }))
{'f': 1.2,
'in_': 1,
'n': u'bob',
'u': 'http://www.zope.org',
'x': 'x.y.z'}
If we have extra data, we'll get an error:
.. doctest::
>>> toargs(context, schema,
... {'in': u'1', 'f': u'1.2', 'n': u'bob', 'x': u'x.y.z',
... 'u': u'http://www.zope.org', 'a': u'1'})
Traceback (most recent call last):
...
ConfigurationError: ('Unrecognized parameters:', 'a')
Unless we set a tagged value to say that extra arguments are ok:
.. doctest::
>>> schema.setTaggedValue('keyword_arguments', True)
>>> pprint(toargs(context, schema,
... {'in': u'1', 'f': u'1.2', 'n': u'bob', 'x': u'x.y.z',
... 'u': u'http://www.zope.org', 'a': u'1'}))
{'a': u'1',
'f': 1.2,
'in_': 1,
'n': u'bob',
'u': 'http://www.zope.org',
'x': 'x.y.z'}
If we omit required data we get an error telling us what was omitted:
.. doctest::
>>> pprint(toargs(context, schema,
... {'in': u'1', 'f': u'1.2', 'n': u'bob', 'x': u'x.y.z'}))
Traceback (most recent call last):
...
ConfigurationError: ('Missing parameter:', 'u')
Although we can omit not-required data:
.. doctest::
>>> pprint(toargs(context, schema,
... {'in': u'1', 'f': u'1.2', 'n': u'bob',
... 'u': u'http://www.zope.org', 'a': u'1'}))
{'a': u'1',
'f': 1.2,
'in_': 1,
'n': u'bob',
'u': 'http://www.zope.org'}
And we can omit required fields if they have valid defaults
(defaults that are valid values):
.. doctest::
>>> pprint(toargs(context, schema,
... {'in': u'1', 'f': u'1.2',
... 'u': u'http://www.zope.org', 'a': u'1'}))
{'a': u'1',
'f': 1.2,
'in_': 1,
'n': u'rob',
'u': 'http://www.zope.org'}
We also get an error if any data was invalid:
.. doctest::
>>> pprint(toargs(context, schema,
... {'in': u'0', 'f': u'1.2', 'n': u'bob', 'x': u'x.y.z',
... 'u': u'http://www.zope.org', 'a': u'1'}))
Traceback (most recent call last):
...
ConfigurationError: ('Invalid value for', 'in', '0')
.. autofunction:: expand_action
.. autofunction:: resolveConflicts
.. autoclass:: ConfigurationConflictError
zope.configuration-4.0.3/docs/api/interfaces.rst 0000664 0001750 0001750 00000000531 12073042162 021621 0 ustar tseaver tseaver :mod:`zope.configuration.interfaces`
====================================
.. module:: zope.configuration.interfaces
.. autoclass:: InvalidToken
:members:
:member-order: bysource
.. autointerface:: IConfigurationContext
:members:
:member-order: bysource
.. autointerface:: IGroupingContext
:members:
:member-order: bysource
zope.configuration-4.0.3/docs/api/fields.rst 0000664 0001750 0001750 00000020006 12073042162 020743 0 ustar tseaver tseaver :mod:`zope.configuration.fields`
================================
.. module:: zope.configuration.fields
.. autoclass:: PythonIdentifier
:members:
:member-order: bysource
Let's look at an example:
.. doctest::
>>> from zope.configuration.fields import PythonIdentifier
>>> class FauxContext(object):
... pass
>>> context = FauxContext()
>>> field = PythonIdentifier().bind(context)
Let's test the fromUnicode method:
.. doctest::
>>> field.fromUnicode(u'foo')
u'foo'
>>> field.fromUnicode(u'foo3')
u'foo3'
>>> field.fromUnicode(u'_foo3')
u'_foo3'
Now let's see whether validation works alright
.. doctest::
>>> for value in (u'foo', u'foo3', u'foo_', u'_foo3', u'foo_3', u'foo3_'):
... field._validate(value)
>>> from zope.schema import ValidationError
>>> for value in (u'3foo', u'foo:', u'\\', u''):
... try:
... field._validate(value)
... except ValidationError:
... print 'Validation Error'
Validation Error
Validation Error
Validation Error
Validation Error
.. autoclass:: GlobalObject
:members:
:member-order: bysource
Let's look at an example:
.. doctest::
>>> d = {'x': 1, 'y': 42, 'z': 'zope'}
>>> class fakeresolver(dict):
... def resolve(self, n):
... return self[n]
>>> fake = fakeresolver(d)
>>> from zope.schema import Int
>>> from zope.configuration.fields import GlobalObject
>>> g = GlobalObject(value_type=Int())
>>> gg = g.bind(fake)
>>> gg.fromUnicode("x")
1
>>> gg.fromUnicode(" x \n ")
1
>>> gg.fromUnicode("y")
42
>>> gg.fromUnicode("z")
Traceback (most recent call last):
...
WrongType: ('zope', (, ), '')
>>> g = GlobalObject(constraint=lambda x: x%2 == 0)
>>> gg = g.bind(fake)
>>> gg.fromUnicode("x")
Traceback (most recent call last):
...
ConstraintNotSatisfied: 1
>>> gg.fromUnicode("y")
42
>>> g = GlobalObject()
>>> gg = g.bind(fake)
>>> print gg.fromUnicode('*')
None
.. autoclass:: GlobalInterface
:members:
:member-order: bysource
Example:
First, we need to set up a stub name resolver:
.. doctest::
>>> from zope.interface import Interface
>>> class IFoo(Interface):
... pass
>>> class Foo(object):
... pass
>>> d = {'Foo': Foo, 'IFoo': IFoo}
>>> class fakeresolver(dict):
... def resolve(self, n):
... return self[n]
>>> fake = fakeresolver(d)
Now verify constraints are checked correctly:
.. doctest::
>>> from zope.configuration.fields import GlobalInterface
>>> g = GlobalInterface()
>>> gg = g.bind(fake)
>>> gg.fromUnicode('IFoo') is IFoo
True
>>> gg.fromUnicode(' IFoo ') is IFoo
True
>>> gg.fromUnicode('Foo')
Traceback (most recent call last):
...
WrongType: ('An interface is required', ...
.. autoclass:: Tokens
:members:
:member-order: bysource
Consider GlobalObject tokens:
First, we need to set up a stub name resolver:
.. doctest::
>>> d = {'x': 1, 'y': 42, 'z': 'zope', 'x.y.x': 'foo'}
>>> class fakeresolver(dict):
... def resolve(self, n):
... return self[n]
>>> fake = fakeresolver(d)
>>> from zope.configuration.fields import Tokens
>>> from zope.configuration.fields import GlobalObject
>>> g = Tokens(value_type=GlobalObject())
>>> gg = g.bind(fake)
>>> gg.fromUnicode(" \n x y z \n")
[1, 42, 'zope']
>>> from zope.schema import Int
>>> g = Tokens(value_type=
... GlobalObject(value_type=
... Int(constraint=lambda x: x%2 == 0)))
>>> gg = g.bind(fake)
>>> gg.fromUnicode("x y")
Traceback (most recent call last):
...
InvalidToken: 1 in x y
>>> gg.fromUnicode("z y")
Traceback (most recent call last):
...
InvalidToken: ('zope', (, ), '') in z y
>>> gg.fromUnicode("y y")
[42, 42]
.. autoclass:: Path
:members:
:member-order: bysource
Let's look at an example:
First, we need a "context" for the field that has a path
function for converting relative path to an absolute path.
We'll be careful to do this in an os-independent fashion.
.. doctest::
>>> from zope.configuration.fields import Path
>>> class FauxContext(object):
... def path(self, p):
... return os.path.join(os.sep, 'faux', 'context', p)
>>> context = FauxContext()
>>> field = Path().bind(context)
Lets try an absolute path first:
.. doctest::
>>> import os
>>> p = unicode(os.path.join(os.sep, 'a', 'b'))
>>> n = field.fromUnicode(p)
>>> n.split(os.sep)
[u'', u'a', u'b']
This should also work with extra spaces around the path:
.. doctest::
>>> p = " \n %s \n\n " % p
>>> n = field.fromUnicode(p)
>>> n.split(os.sep)
[u'', u'a', u'b']
Now try a relative path:
.. doctest::
>>> p = unicode(os.path.join('a', 'b'))
>>> n = field.fromUnicode(p)
>>> n.split(os.sep)
[u'', u'faux', u'context', u'a', u'b']
.. autoclass:: Bool
:members:
:member-order: bysource
.. doctest::
>>> from zope.configuration.fields import Bool
>>> Bool().fromUnicode(u"yes")
True
>>> Bool().fromUnicode(u"y")
True
>>> Bool().fromUnicode(u"true")
True
>>> Bool().fromUnicode(u"no")
False
.. autoclass:: MessageID
:members:
:member-order: bysource
.. doctest::
>>> from zope.configuration.fields import MessageID
>>> class Info(object):
... file = 'file location'
... line = 8
>>> class FauxContext(object):
... i18n_strings = {}
... info = Info()
>>> context = FauxContext()
>>> field = MessageID().bind(context)
There is a fallback domain when no domain has been specified.
Exchange the warn function so we can make test whether the warning
has been issued
.. doctest::
>>> warned = None
>>> def fakewarn(*args, **kw): #* syntax highlighting
... global warned
... warned = args
>>> import warnings
>>> realwarn = warnings.warn
>>> warnings.warn = fakewarn
>>> i = field.fromUnicode(u"Hello world!")
>>> i
u'Hello world!'
>>> i.domain
'untranslated'
>>> warned
("You did not specify an i18n translation domain for the '' field in file location",)
>>> warnings.warn = realwarn
With the domain specified:
.. doctest::
>>> context.i18n_strings = {}
>>> context.i18n_domain = 'testing'
We can get a message id:
.. doctest::
>>> i = field.fromUnicode(u"Hello world!")
>>> i
u'Hello world!'
>>> i.domain
'testing'
In addition, the string has been registered with the context:
.. doctest::
>>> context.i18n_strings
{'testing': {u'Hello world!': [('file location', 8)]}}
>>> i = field.fromUnicode(u"Foo Bar")
>>> i = field.fromUnicode(u"Hello world!")
>>> from pprint import PrettyPrinter
>>> pprint=PrettyPrinter(width=70).pprint
>>> pprint(context.i18n_strings)
{'testing': {u'Foo Bar': [('file location', 8)],
u'Hello world!': [('file location', 8),
('file location', 8)]}}
>>> from zope.i18nmessageid import Message
>>> isinstance(context.i18n_strings['testing'].keys()[0], Message)
True
Explicit Message IDs
.. doctest::
>>> i = field.fromUnicode(u'[View-Permission] View')
>>> i
u'View-Permission'
>>> i.default
u'View'
>>> i = field.fromUnicode(u'[] [Some] text')
>>> i
u'[Some] text'
>>> i.default is None
True
zope.configuration-4.0.3/docs/conf.py 0000664 0001750 0001750 00000017535 12073042162 017506 0 ustar tseaver tseaver # -*- coding: utf-8 -*-
#
# zope.configuration documentation build configuration file, created by
# sphinx-quickstart on Sat May 5 13:59:34 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.todo',
'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 = u'zope.configuration'
copyright = u'2012, Zope Foundation Contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '4.0'
# The full version, including alpha/beta/rc tags.
release = '4.0'
# 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 = 'zopeconfigurationdoc'
# -- 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', 'zopeconfiguration.tex', u'zope.configuration Documentation',
u'Zope Foundation Contributors', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'zopeconfiguration', u'zope.configuration Documentation',
[u'Zope Foundation Contributors'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'zopeconfiguration', u'zope.configuration Documentation',
u'Zope Foundation Contributors', 'zopeconfiguration', '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'
zope.configuration-4.0.3/docs/index.rst 0000664 0001750 0001750 00000000362 12073042162 020036 0 ustar tseaver tseaver :mod:`zope.configuration` Documentation
=======================================
Contents:
.. toctree::
:maxdepth: 2
narr
api
hacking
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
zope.configuration-4.0.3/docs/narr.rst 0000664 0001750 0001750 00000110472 12073042162 017675 0 ustar tseaver tseaver ==========================
Zope configuration system
==========================
The zope configuration system provides an extensible system for
supporting variouse kinds of configurations.
It is based on the idea of configuration directives. Users of the
configuration system provide configuration directives in some
language that express configuration choices. The intent is that the
language be pluggable. An XML language is provided by default.
Configuration is performed in three stages. In the first stage,
directives are processed to compute configuration actions.
Configuration actions consist of:
- A discriminator
- A callable
- Positional arguments
- Keyword arguments
The actions are essentially delayed function calls. Two or more
actions conflict if they have the same discriminator. The
configuration system has rules for resolving conflicts. If conflicts
cannot be resolved, an error will result. Conflict resolution
typically discards all but one of the conflicting actions, so that
the remaining action of the originally-conflicting actions no longer
conflicts. Non-conflicting actions are executed in the order that
they were created by passing the positional and non-positional
arguments to the action callable.
The system is extensible. There is a meta-configuration language for
defining configuration directives. A directive is defined by
providing meta data about the directive and handler code to process
the directive. There are four kinds of directives:
- Simple directives compute configuration actions. Their handlers
are typically functions that take a context and zero or more
keyword arguments and return a sequence of configuration actions.
To learn how to create simple directives, see `tests/simple.py`.
- Grouping directives collect information to be used by nested
directives. They are called with a context object which they adapt
to some interface that extends IConfigurationContext.
To learn how to create grouping directives, look at the
documentation in zopeconfigure.py, which provides the implementation
of the zope `configure` directive.
Other directives can be nested in grouping directives.
To learn how to implement nested directives, look at the
documentation in the "Creating Nested Directives" section below.
- Complex directives are directives that have subdirectives.
Subdirectives have handlers that are simply methods of complex
directives. Complex diretives are handled by factories, typically
classes, that create objects that have methods for handling
subdirectives. These objects also have __call__ methods that are
called when processing of subdirectives is finished.
Complex directives only exist to support old directive
handlers. They will probably be deprecated in the future.
- Subdirectives are nested in complex directives. They are like
simple directives except that they hane handlers that are complex
directive methods.
Subdirectives, like complex directives only exist to support old
directive handlers. They will probably be deprecated in the future.
.. todo::
Flesh out narrative docs.
Using the configuration machinery programatically
==================================================
An extended example:
.. doctest::
>>> from zope.configuration.config import ConfigurationMachine
>>> from zope.configuration.config import metans
>>> machine = ConfigurationMachine()
>>> ns = "http://www.zope.org/testing"
Register some test directives:
Start with a grouping directive that sets a package:
.. doctest::
>>> machine((metans, "groupingDirective"),
... name="package", namespace=ns,
... schema="zope.configuration.tests.directives.IPackaged",
... handler="zope.configuration.tests.directives.Packaged",
... )
Now we can set the package:
.. doctest::
>>> machine.begin((ns, "package"),
... package="zope.configuration.tests.directives",
... )
Which makes it easier to define the other directives:
First, define some simple directives:
.. doctest::
>>> machine((metans, "directive"),
... namespace=ns, name="simple",
... schema=".ISimple", handler=".simple")
>>> machine((metans, "directive"),
... namespace=ns, name="newsimple",
... schema=".ISimple", handler=".newsimple")
and try them out:
.. doctest::
>>> machine((ns, "simple"), "first", a=u"aa", c=u"cc")
>>> machine((ns, "newsimple"), "second", a=u"naa", c=u"ncc", b=u"nbb")
>>> from pprint import PrettyPrinter
>>> pprint = PrettyPrinter(width=50).pprint
>>> pprint(machine.actions)
[{'args': (u'aa', u'xxx', 'cc'),
'callable': f,
'discriminator': ('simple',
u'aa',
u'xxx',
'cc'),
'includepath': (),
'info': 'first',
'kw': {},
'order': 0},
{'args': (u'naa', u'nbb', 'ncc'),
'callable': f,
'discriminator': ('newsimple',
u'naa',
u'nbb',
'ncc'),
'includepath': (),
'info': 'second',
'kw': {},
'order': 0}]
Define and try a simple directive that uses a component:
.. doctest::
>>> machine((metans, "directive"),
... namespace=ns, name="factory",
... schema=".IFactory", handler=".factory")
>>> machine((ns, "factory"), factory=u".f")
>>> pprint(machine.actions[-1:])
[{'args': (),
'callable': f,
'discriminator': ('factory', 1, 2),
'includepath': (),
'info': None,
'kw': {},
'order': 0}]
Define and try a complex directive:
.. doctest::
>>> machine.begin((metans, "complexDirective"),
... namespace=ns, name="testc",
... schema=".ISimple", handler=".Complex")
>>> machine((metans, "subdirective"),
... name="factory", schema=".IFactory")
>>> machine.end()
>>> machine.begin((ns, "testc"), None, "third", a=u'ca', c='cc')
>>> machine((ns, "factory"), "fourth", factory=".f")
Note that we can't call a complex method unless there is a directive for
it:
.. doctest::
>>> machine((ns, "factory2"), factory=".f")
Traceback (most recent call last):
...
ConfigurationError: ('Invalid directive', 'factory2')
>>> machine.end()
>>> pprint(machine.actions)
[{'args': (u'aa', u'xxx', 'cc'),
'callable': f,
'discriminator': ('simple',
u'aa',
u'xxx',
'cc'),
'includepath': (),
'info': 'first',
'kw': {},
'order': 0},
{'args': (u'naa', u'nbb', 'ncc'),
'callable': f,
'discriminator': ('newsimple',
u'naa',
u'nbb',
'ncc'),
'includepath': (),
'info': 'second',
'kw': {},
'order': 0},
{'args': (),
'callable': f,
'discriminator': ('factory', 1, 2),
'includepath': (),
'info': None,
'kw': {},
'order': 0},
{'args': (),
'callable': None,
'discriminator': 'Complex.__init__',
'includepath': (),
'info': 'third',
'kw': {},
'order': 0},
{'args': (u'ca',),
'callable': f,
'discriminator': ('Complex.factory', 1, 2),
'includepath': (),
'info': 'fourth',
'kw': {},
'order': 0},
{'args': (u'xxx', 'cc'),
'callable': f,
'discriminator': ('Complex', 1, 2),
'includepath': (),
'info': 'third',
'kw': {},
'order': 0}]
Done with the package
.. doctest::
>>> machine.end()
Verify that we can use a simple directive outside of the package:
.. doctest::
>>> machine((ns, "simple"), a=u"oaa", c=u"occ", b=u"obb")
But we can't use the factory directive, because it's only valid
inside a package directive:
.. doctest::
>>> machine((ns, "factory"), factory=u".F")
Traceback (most recent call last):
...
ConfigurationError: ('Invalid value for', 'factory',""" \
""" "Can't use leading dots in dotted names, no package has been set.")
>>> pprint(machine.actions)
[{'args': (u'aa', u'xxx', 'cc'),
'callable': f,
'discriminator': ('simple',
u'aa',
u'xxx',
'cc'),
'includepath': (),
'info': 'first',
'kw': {},
'order': 0},
{'args': (u'naa', u'nbb', 'ncc'),
'callable': f,
'discriminator': ('newsimple',
u'naa',
u'nbb',
'ncc'),
'includepath': (),
'info': 'second',
'kw': {},
'order': 0},
{'args': (),
'callable': f,
'discriminator': ('factory', 1, 2),
'includepath': (),
'info': None,
'kw': {},
'order': 0},
{'args': (),
'callable': None,
'discriminator': 'Complex.__init__',
'includepath': (),
'info': 'third',
'kw': {},
'order': 0},
{'args': (u'ca',),
'callable': f,
'discriminator': ('Complex.factory', 1, 2),
'includepath': (),
'info': 'fourth',
'kw': {},
'order': 0},
{'args': (u'xxx', 'cc'),
'callable': f,
'discriminator': ('Complex', 1, 2),
'includepath': (),
'info': 'third',
'kw': {},
'order': 0},
{'args': (u'oaa', u'obb', 'occ'),
'callable': f,
'discriminator': ('simple',
u'oaa',
u'obb',
'occ'),
'includepath': (),
'info': None,
'kw': {},
'order': 0}]
Overriding Included Configuration
==================================
When we have conflicting directives, we can resolve them if one of
the conflicting directives was from a file that included all of
the others. The problem with this is that this requires that all
of the overriding directives be in one file, typically the
top-most including file. This isn't very convenient. Fortunately,
we can overcome this with the includeOverrides directive. Let's
look at an example to see how this works.
Look at the file ``bar.zcml`` (in ``zope/configuration/tests/samplepackage``):
- It includes ``bar1.zcml`` and ``bar2.zcml``.
- ``bar1.zcml`` includes ``configure.zcml`` and has a ``foo``
directive.
- ``bar2.zcml`` includes ``bar21.zcml``, and has a ``foo``
directive that conflicts with one in ``bar1.zcml``.
- ``bar2.zcml`` also overrides a foo directive in ``bar21.zcml``.
- ``bar21.zcml`` has a ``foo`` directive that conflicts with one in in
``configure.zcml``. Whew!
Let's see what happens when we try to process ``bar.zcml``.
.. doctest::
>>> import os
>>> from zope.configuration.config import ConfigurationMachine
>>> from zope.configuration.xmlconfig import include
>>> from zope.configuration.xmlconfig import registerCommonDirectives
>>> context = ConfigurationMachine()
>>> registerCommonDirectives(context)
>>> from zope.configuration.tests import __file__
>>> here = os.path.dirname(__file__)
>>> path = os.path.join(here, "samplepackage", "bar.zcml")
>>> include(context, path)
So far so good, let's look at the configuration actions:
.. doctest::
>>> from zope.configuration.tests.test_xmlconfig import clean_actions
>>> pprint = PrettyPrinter(width=70).pprint
>>> pprint(clean_actions(context.actions))
[{'discriminator': (('x', 'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar1.zcml',
'tests/samplepackage/configure.zcml'],
'info': 'File "tests/samplepackage/configure.zcml", line 12.2-12.29'},
{'discriminator': (('x', 'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar1.zcml'],
'info': 'File "tests/samplepackage/bar1.zcml", line 5.2-5.24'},
{'discriminator': (('x', 'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar2.zcml',
'tests/samplepackage/bar21.zcml'],
'info': 'File "tests/samplepackage/bar21.zcml", line 3.2-3.24'},
{'discriminator': (('x', 'blah'), ('y', 2)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar2.zcml',
'tests/samplepackage/bar21.zcml'],
'info': 'File "tests/samplepackage/bar21.zcml", line 4.2-4.24'},
{'discriminator': (('x', 'blah'), ('y', 2)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar2.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 5.2-5.24'},
{'discriminator': (('x', 'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar2.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 6.2-6.24'}]
As you can see, there are a number of conflicts (actions with the same
discriminator). Some of these can be resolved, but many can't, as
we'll find if we try to execuse the actions:
.. doctest::
>>> from zope.configuration.config import ConfigurationConflictError
>>> from zope.configuration.tests.test_xmlconfig import clean_text_w_paths
>>> try:
... v = context.execute_actions()
... except ConfigurationConflictError, v:
... pass
>>> print clean_text_w_paths(str(v))
Conflicting configuration actions
For: (('x', 'blah'), ('y', 0))
File "tests/samplepackage/configure.zcml", line 12.2-12.29
File "tests/samplepackage/bar21.zcml", line 3.2-3.24
For: (('x', 'blah'), ('y', 1))
File "tests/samplepackage/bar1.zcml", line 5.2-5.24
File "tests/samplepackage/bar2.zcml", line 6.2-6.24
Note that the conflicts for (('x', 'blah'), ('y', 2)) aren't
included in the error because they could be resolved.
Let's try this again using includeOverrides. We'll include
baro.zcml which includes bar2.zcml as overrides.
.. doctest::
>>> context = ConfigurationMachine()
>>> registerCommonDirectives(context)
>>> path = os.path.join(here, "samplepackage", "baro.zcml")
>>> include(context, path)
Now, if we look at the actions:
.. doctest::
>>> pprint(clean_actions(context.actions))
[{'discriminator': (('x', 'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/baro.zcml',
'tests/samplepackage/bar1.zcml',
'tests/samplepackage/configure.zcml'],
'info': 'File "tests/samplepackage/configure.zcml", line 12.2-12.29'},
{'discriminator': (('x', 'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/baro.zcml',
'tests/samplepackage/bar1.zcml'],
'info': 'File "tests/samplepackage/bar1.zcml", line 5.2-5.24'},
{'discriminator': (('x', 'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/baro.zcml'],
'info': 'File "tests/samplepackage/bar21.zcml", line 3.2-3.24'},
{'discriminator': (('x', 'blah'), ('y', 2)),
'includepath': ['tests/samplepackage/baro.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 5.2-5.24'},
{'discriminator': (('x', 'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/baro.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 6.2-6.24'}]
We see that:
- The conflicting actions between bar2.zcml and bar21.zcml have
been resolved, and
- The remaining (after conflict resolution) actions from bar2.zcml
and bar21.zcml have the includepath that they would have if they
were defined in baro.zcml and this override the actions from
bar1.zcml and configure.zcml.
We can now execute the actions without problem, since the
remaining conflicts are resolvable:
.. doctest::
>>> context.execute_actions()
We should now have three entries in foo.data:
.. doctest::
>>> from zope.configuration.tests.samplepackage import foo
>>> from zope.configuration.tests.test_xmlconfig import clean_info_path
>>> len(foo.data)
3
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 0))
>>> print clean_info_path(`data.info`)
File "tests/samplepackage/bar21.zcml", line 3.2-3.24
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 2))
>>> print clean_info_path(`data.info`)
File "tests/samplepackage/bar2.zcml", line 5.2-5.24
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 1))
>>> print clean_info_path(`data.info`)
File "tests/samplepackage/bar2.zcml", line 6.2-6.24
We expect the exact same results when using includeOverrides with
the ``files`` argument instead of the ``file`` argument. The
baro2.zcml file uses the former:
.. doctest::
>>> context = ConfigurationMachine()
>>> registerCommonDirectives(context)
>>> path = os.path.join(here, "samplepackage", "baro2.zcml")
>>> include(context, path)
Actions look like above:
.. doctest::
>>> pprint(clean_actions(context.actions))
[{'discriminator': (('x', 'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/baro2.zcml',
'tests/samplepackage/bar1.zcml',
'tests/samplepackage/configure.zcml'],
'info': 'File "tests/samplepackage/configure.zcml", line 12.2-12.29'},
{'discriminator': (('x', 'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/baro2.zcml',
'tests/samplepackage/bar1.zcml'],
'info': 'File "tests/samplepackage/bar1.zcml", line 5.2-5.24'},
{'discriminator': (('x', 'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/baro2.zcml'],
'info': 'File "tests/samplepackage/bar21.zcml", line 3.2-3.24'},
{'discriminator': (('x', 'blah'), ('y', 2)),
'includepath': ['tests/samplepackage/baro2.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 5.2-5.24'},
{'discriminator': (('x', 'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/baro2.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 6.2-6.24'}]
>>> context.execute_actions()
>>> len(foo.data)
3
>>> del foo.data[:]
Making specific directives conditional
======================================
There is a ``condition`` attribute in the
"http://namespaces.zope.org/zcml" namespace which is honored on all
elements in ZCML. The value of the attribute is an expression
which is used to determine if that element and its descendents are
used. If the condition is true, processing continues normally,
otherwise that element and its descendents are ignored.
Currently the expression is always of the form "have featurename", and it
checks for the presence of a ````.
Our demonstration uses a trivial registry; each registration consists
of a simple id inserted in the global `registry` in this module. We
can checked that a registration was made by checking whether the id is
present in `registry`.
.. doctest::
>>> from zope.configuration.tests.conditions import registry
>>> registry
[]
We start by loading the example ZCML file, *conditions.zcml*:
.. doctest::
>>> import zope.configuration.tests
>>> from zope.configuration.xmlconfig import file
>>> context = file("conditions.zcml", zope.configuration.tests)
To show that our sample directive works, we see that the unqualified
registration was successful:
.. doctest::
>>> "unqualified.registration" in registry
True
When the expression specified with ``zcml:condition`` evaluates to
true, the element it is attached to and all contained elements (not
otherwise conditioned) should be processed normally:
.. doctest::
>>> "direct.true.condition" in registry
True
>>> "nested.true.condition" in registry
True
However, when the expression evaluates to false, the conditioned
element and all contained elements should be ignored:
.. doctest::
>>> "direct.false.condition" in registry
False
>>> "nested.false.condition" in registry
False
Conditions on container elements affect the conditions in nested
elements in a reasonable way. If an "outer" condition is true, nested
conditions are processed normally:
.. doctest::
>>> "true.condition.nested.in.true" in registry
True
>>> "false.condition.nested.in.true" in registry
False
If the outer condition is false, inner conditions are not even
evaluated, and the nested elements are ignored:
.. doctest::
>>> "true.condition.nested.in.false" in registry
False
>>> "false.condition.nested.in.false" in registry
False
.. testcleanup::
del registry[:]
Filtering and Inhibiting Configuration
======================================
The ``exclude`` standard directive is provided for inhibiting unwanted
configuration. It is used to exclude processing of configuration files.
It is useful when including a configuration that includes some other
configuration that you don't want.
It must be used BEFORE including the files to be excluded.
First, let's look at an example. The zope.configuration.tests.excludedemo
package has a ZCML configuration that includes some other configuration files.
We'll set a log handler so we can see what's going on:
.. doctest::
>>> import logging
>>> import logging.handlers
>>> import sys
>>> logger = logging.getLogger('config')
>>> oldlevel = logger.level
>>> logger.setLevel(logging.DEBUG)
>>> handler = logging.handlers.MemoryHandler(10)
>>> logger.addHandler(handler)
Now, we'll include the zope.configuration.tests.excludedemo config:
.. doctest::
>>> from zope.configuration.xmlconfig import string
>>> _ = string('')
>>> len(handler.buffer)
3
>>> logged = [x.msg for x in handler.buffer]
>>> logged[0].startswith('include ')
True
>>> logged[0].endswith('zope/configuration/tests/excludedemo/configure.zcml')
True
>>> logged[1].startswith('include ')
True
>>> logged[1].endswith('zope/configuration/tests/excludedemo/sub/configure.zcml')
True
>>> logged[2].startswith('include ')
True
>>> logged[2].endswith('zope/configuration/tests/excludedemo/spam.zcml')
True
>>> del handler.buffer[:]
Each run of the configuration machinery runs with fresh state, so
rerunning gives the same thing:
.. doctest::
>>> _ = string('')
>>> len(handler.buffer)
3
>>> logged = [x.msg for x in handler.buffer]
>>> logged[0].startswith('include ')
True
>>> logged[0].endswith('zope/configuration/tests/excludedemo/configure.zcml')
True
>>> logged[1].startswith('include ')
True
>>> logged[1].endswith('zope/configuration/tests/excludedemo/sub/configure.zcml')
True
>>> logged[2].startswith('include ')
True
>>> logged[2].endswith('zope/configuration/tests/excludedemo/spam.zcml')
True
>>> del handler.buffer[:]
Now, we'll use the exclude directive to exclude the two files included
by the configuration file in zope.configuration.tests.excludedemo:
.. doctest::
>>> _ = string(
... '''
...
...
...
...
...
... ''')
>>> len(handler.buffer)
1
>>> logged = [x.msg for x in handler.buffer]
>>> logged[0].startswith('include ')
True
>>> logged[0].endswith('zope/configuration/tests/excludedemo/configure.zcml')
True
.. testcleanup::
logger.setLevel(oldlevel)
logger.removeHandler(handler)
Creating simple directives
==========================
A simple directive is a directive that doesn't contain other
directives. It can be implemented via a fairly simple function.
To implement a simple directive, you need to do 3 things:
- You need to create a schema to describe the directive parameters,
- You need to write a directive handler, and
- You need to register the directive.
In this example, we'll implement a contrived example that records
information about files in a file registry. The file registry is just
the list, ``file_registry``.
.. doctest::
>>> from zope.configuration.tests.simple import file_registry
Our registry will contain tuples with:
- file path
- file title
- description
- Information about where the file was defined
Our schema is defined in ``zope.configuration.tests.simple.IRegisterFile``
(q.v).
.. doctest::
>>> from zope.configuration.tests.simple import IRegisterFile
Our schema lists the ``path`` and ``title`` attributes. We'll get the
description and other information for free, as we'll see later. The
title is not required, and may be omitted.
The job of a configuration handler is to compute one or more
configuration actions. Configuration actions are defered function
calls. The handler doesn't perform the actions. It just computes
actions, which may be performed later if they are not overridden by
other directives.
Our handler is given in the function,
``zope.configuration.tests.simple.registerFile``.
.. doctest::
>>> from zope.configuration.tests.simple import registerFile
It takes a context, a path and a title. All directive handlers take the
directive context as the first argument. A directive context, at a minimim,
implements, ``zope.configuration.IConfigurationContext``.
(Specialized contexts can implement more specific interfaces. We'll say more
about that when we talk about grouping directives.) The title argument
must have a default value, because we indicated that the title was not
required in the schema. (Alternatively, we could have made the title
required, but provided a default value in the schema.
In the first line of function ``registerFile``, we get the context information
object. This object contains information about the configuration
directive, such as the file and location within the file of the
directive.
The context information object also has a text attribute that contains
the textual data contained by the configuration directive. (This is
the concatenation of all of the xml text nodes directly contained by
the directive.) We use this for our description in the second line
of the handler.
The last thing the handler does is to compute an action by calling the
action method of the context. It passes the action method 3 keyword
arguments:
- discriminator
The discriminator is used to identify the action to be performed so
that duplicate actions can be detected. Two actions are duplicated,
and this conflict, if they have the same discriminator values and
the values are not ``None``. Conflicting actions can be resolved if
one of the conflicting actions is from a configuration file that
directly or indirectly includes the files containing the other
conflicting actions.
In function ``registerFile``, we a tuple with the string
``'RegisterFile'`` and the path to be registered.
- callable
The callable is the object to be called to perform the action.
- args
The args argument contains positinal arguments to be passed to the
callable. In function ``registerFile``, we pass a tuple containing a
``FileInfo`` object.
(Note that there's nothing special about the FileInfo class. It has
nothing to do with creating simple directives. It's just used in
this example to organize the application data.)
The final step in implementing the simple directive is to register
it. We do that with the zcml ``meta:directive`` directive. This is
given in the file simple.zcml. Here we specify the name, namespace,
schema, and handler for the directive. We also provide a
documentation for the directive as text between the start and end
tags.
The file simple.zcml also includes some directives that use the new
directive to register some files.
Now let's try it all out:
.. doctest::
>>> from zope.configuration import tests
>>> from zope.configuration.xmlconfig import file
>>> context = file("simple.zcml", tests)
Now we should see some file information in the registry:
.. doctest::
>>> from zope.configuration.tests.test_xmlconfig import clean_text_w_paths
>>> from zope.configuration.tests.test_xmlconfig import clean_path
>>> print clean_path(file_registry[0].path)
tests/simple.py
>>> print file_registry[0].title
How to create a simple directive
>>> print file_registry[0].description
Describes how to implement a simple directive
>>> print clean_text_w_paths(file_registry[0].info)
File "tests/simple.zcml", line 19.2-24.2
Describes how to implement a simple directive
>>> print clean_path(file_registry[1].path)
tests/simple.zcml
>>> print file_registry[1].title
>>> desc = file_registry[1].description
>>> print '\n'.join([l.rstrip()
... for l in desc.strip().splitlines()
... if l.rstrip()])
Shows the ZCML directives needed to register a simple directive.
Also show some usage examples,
>>> print clean_text_w_paths(file_registry[1].info)
File "tests/simple.zcml", line 26.2-30.2
Shows the ZCML directives needed to register a simple directive.
Also show some usage examples,
>>> print clean_path(file_registry[2].path)
tests/__init__.py
>>> print file_registry[2].title
Make this a package
>>> print file_registry[2].description
>>> print clean_text_w_paths(file_registry[2].info)
File "tests/simple.zcml", line 32.2-32.67
Clean up after ourselves:
.. doctest::
>>> del file_registry[:]
Creating nested directives
==========================
When using ZCML, you sometimes nest ZCML directives. This is typically
done either to:
- Avoid repetative input. Information shared among multiple
directives is provided in a surrounding directive.
- Put together information that is too complex or structured to express
with a single set of directive parameters.
Grouping directives are used to handle both of these cases. See the
documentation in :mod:`zope.configure.zopeconfigure`. This file describes the
implementation of the zope ``configure`` directive, which groups
directives that use a common package or internationalization domain.
You should also have read the section on "Creating simple directives."
This file shows you how to handle the second case above. In this case,
we have grouping directives that are meant to collaborate with
specific contained directives. To do this, you have the grouping
directives declare a more specific (or alternate) interface to
``IConfigurationContext``. Directives designed to work with those
grouping directives are registered for the new interface.
Let's look at example. Suppose we wanted to be able to define schema
using ZCML. We'd use a grouping directive to specify schemas and
contained directives to specify fields within the schema. We'll use a
schema registry to hold the defined schemas::
.. doctest::
>>> from zope.configuration.tests.nested import schema_registry
A schema has a name, an id, some documentation, and some fields.
We'll provide the name and the id as parameters. We'll define fields
as subdirectives and documentation as text contained in the schema
directive. The schema directive uses the schema, ``ISchemaInfo`` for
it's parameters.
.. doctest::
>>> from zope.configuration.tests.nested import ISchemaInfo
We also define the schema, ISchema, that specifies an attribute that
nested field directives will use to store the fields they define.
.. doctest::
>>> from zope.configuration.tests.nested import ISchema
The class, ``Schema``, provides the handler for the schema directive. (If
you haven't read the documentation in ``zopeconfigure.py``, you need
to do so now.) The constructor saves its arguments as attributes
and initializes its ``fields`` attribute:
.. doctest::
>>> from zope.configuration.tests.nested import Schema
The ``after`` method of the ``Schema`` class creates a schema and
computes an action to register the schema in the schema registry. The
discriminator prevents two schema directives from registering the same
schema.
It's important to note that when we call the ``action`` method on
``self``, rather than on ``self.context``. This is because, in a
grouping directive handler, the handler instance is itself a context.
When we call the ``action`` method, the method stores additional meta
data associated with the context it was called on. This meta data
includes an include path, used when resolving conflicting actions,
and an object that contains information about the XML source used
to invole the directive. If we called the action method on
``self.context``, the wrong meta data would be associated with the
configuration action.
The file ``schema.zcml`` contains the meta-configuration directive
that defines the schema directive.
To define fields, we'll create directives to define the fields.
Let's start with a ``text`` field. ``ITextField`` defines the schema for
text field parameters. It extends ``IFieldInfo``, which defines data
common to all fields. We also define a simple handler method,
textField, that takes a context and keyword arguments. (For
information on writing simple directives, see ``test_simple.py``.)
We've abstracted most of the logic into the function ``field``.
The ``field`` function computes a field instance using the
constructor, and the keyword arguments passed to it. It also uses the
context information object to get the text content of the directive,
which it uses for the field description.
After computing the field instance, it gets the ``Schema`` instance,
which is the context of the context passed to the function. The
function checks to see if there is already a field with that name. If
there is, it raises an error. Otherwise, it saves the field.
We also define an ``IIntInfo`` schema and ``intField`` handler
function to support defining integer fields.
We register the ``text`` and ``int`` directives in ``schema.zcml``.
These are like the simple directive definition we saw in
``test_simple.py`` with an important exception. We provide a
``usedIn`` parameter to say that these directives can *only* ne used
in a ``ISchema`` context. In other words, these can only be used
inside of ``schema`` directives.
The ``schema.zcml`` file also contains some sample ``schema``
directives. We can execute the file:
.. doctest::
>>> from zope.configuration import tests
>>> from zope.configuration.xmlconfig import file
>>> context = file("schema.zcml", tests)
And verify that the schema registery has the schemas we expect:
.. doctest::
>>> pprint(sorted(schema_registry))
['zope.configuration.tests.nested.I1',
'zope.configuration.tests.nested.I2']
>>> def sorted(x):
... r = list(x)
... r.sort()
... return r
>>> i1 = schema_registry['zope.configuration.tests.nested.I1']
>>> sorted(i1)
['a', 'b']
>>> i1['a'].__class__.__name__
'Text'
>>> i1['a'].description.strip()
u'A\n\n Blah blah'
>>> i1['a'].min_length
1
>>> i1['b'].__class__.__name__
'Int'
>>> i1['b'].description.strip()
u'B\n\n Not feeling very creative'
>>> i1['b'].min
1
>>> i1['b'].max
10
>>> i2 = schema_registry['zope.configuration.tests.nested.I2']
>>> sorted(i2)
['x', 'y']
Now let's look at some error situations. For example, let's see what
happens if we use a field directive outside of a schema dorective.
(Note that we used the context we created above, so we don't have to
redefine our directives:
.. doctest::
>>> from zope.configuration.xmlconfig import string
>>> from zope.configuration.xmlconfig import ZopeXMLConfigurationError
>>> try:
... v = string(
... '',
... context)
... except ZopeXMLConfigurationError, v:
... pass
>>> print v
File "", line 1.0
ConfigurationError: The directive (u'http://sample.namespaces.zope.org/schema', u'text') cannot be used in this context
Let's see what happens if we declare duplicate fields:
.. doctest::
>>> try:
... v = string(
... '''
...
...
...
...
... ''',
... context)
... except ZopeXMLConfigurationError, v:
... pass
>>> print v
File "", line 5.7-5.24
ValueError: ('Duplicate field', 'x')
zope.configuration-4.0.3/docs/hacking.rst 0000664 0001750 0001750 00000023777 12073042162 020352 0 ustar tseaver tseaver Hacking on :mod:`zope.configuration`
====================================
Getting the Code
-----------------
The main repository for :mod:`zope.configuration` is in the Zope Subversion
repository:
http://svn.zope.org/zope.configuration
You can get a read-only Subversion checkout from there:
.. code-block:: sh
$ svn checkout svn://svn.zope.org/repos/main/zope.configuration/trunk zope.configuration
The project also mirrors the trunk from the Subversion repository as a
Bazaar branch on Launchpad:
https://code.launchpad.net/zope.configuration
You can branch the trunk from there using Bazaar:
.. code-block:: sh
$ bzr branch lp:zope.configuration
Running the tests in a ``virtualenv``
-------------------------------------
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.configuration
Next, get this package registered as a "development egg" in the
environment:
.. code-block:: sh
$ /tmp/hack-zope.configuration/bin/python setup.py develop
Finally, run the tests using the build-in ``setuptools`` testrunner:
.. code-block:: sh
$ /tmp/hack-zope.configuration/bin/python setup.py test
running test
........
----------------------------------------------------------------------
Ran 249 tests in 0.366s
OK
If you have the :mod:`nose` package installed in the virtualenv, you can
use its testrunner too:
.. code-block:: sh
$ /tmp/hack-zope.configuration/bin/easy_install nose
...
$ /tmp/hack-zope.configuration/bin/python setup.py nosetests
running nosetests
.......
----------------------------------------------------------------------
Ran 249 tests in 0.366s
OK
or:
.. code-block:: sh
$ /tmp/hack-zope.configuration/bin/nosetests
.......
----------------------------------------------------------------------
Ran 249 tests in 0.366s
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.configuration/bin/easy_install nose coverage
...
$ /tmp/hack-zope.configuration/bin/python setup.py nosetests \
--with coverage --cover-package=zope.configuration
running nosetests
...
Name Stmts Miss Cover Missing
----------------------------------------------------------------
zope.configuration 3 0 100%
zope.configuration._compat 2 0 100%
zope.configuration.config 439 0 100%
zope.configuration.docutils 34 0 100%
zope.configuration.exceptions 2 0 100%
zope.configuration.fields 111 0 100%
zope.configuration.interfaces 18 0 100%
zope.configuration.name 54 0 100%
zope.configuration.xmlconfig 269 0 100%
zope.configuration.zopeconfigure 17 0 100%
----------------------------------------------------------------
TOTAL 955 0 100%
----------------------------------------------------------------------
Ran 256 tests in 1.063s
OK
Building the documentation in a ``virtualenv``
----------------------------------------------
:mod:`zope.configuration` 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:
.. code-block:: sh
$ /tmp/hack-zope.configuration/bin/easy_install Sphinx
...
$ cd docs
$ PATH=/tmp/hack-zope.configuration/bin:$PATH make html
sphinx-build -b html -d _build/doctrees . _build/html
...
build succeeded.
Build finished. The HTML pages are in _build/html.
You can also test the code snippets in the documentation:
.. code-block:: sh
$ PATH=/tmp/hack-zope.configuration/bin:$PATH make doctest
sphinx-build -b doctest -d _build/doctrees . _build/doctest
...
Doctest summary
===============
554 tests
0 failures in tests
0 failures in setup code
build succeeded.
Testing of doctests in the sources finished, look at the \
results in _build/doctest/output.txt.
Running the tests using :mod:`zc.buildout`
-------------------------------------------
:mod:`zope.configuration` ships with its own :file:`buildout.cfg` file and
:file:`bootstrap.py` for setting up a development buildout:
.. code-block:: sh
$ /path/to/python2.6 bootstrap.py
...
Generated script '.../bin/buildout'
$ bin/buildout
Develop: '/home/tseaver/projects/Zope/BTK/configuration/.'
...
Generated script '.../bin/sphinx-quickstart'.
Generated script '.../bin/sphinx-build'.
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 249 tests with 0 failures and 0 errors in 0.366 seconds.
Tearing down left over layers:
Tear down zope.testing.testrunner.layer.UnitTests in 0.000 seconds.
Building the documentation using :mod:`zc.buildout`
---------------------------------------------------
The :mod:`zope.configuration` buildout installs the Sphinx scripts required to build
the documentation, including testing its code snippets:
.. code-block:: sh
$ cd docs
$ bin/sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest
...
Doctest summary
===============
554 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.
.../bin/sphinx-build -b html -d .../docs/_build/doctrees .../docs .../docs/_build/html
...
build succeeded.
Running Tests on Multiple Python Versions via :mod:`tox`
--------------------------------------------------------
`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.configuration` configures the following :mod:`tox` environments via
its ``tox.ini`` file:
- The ``py26`` environment builds a ``virtualenv`` with ``python2.6``,
installs :mod:`zope.configuration`, and runs the tests
via ``python setup.py test -q``.
- The ``py27`` environment builds a ``virtualenv`` with ``python2.7``,
installs :mod:`zope.configuration`, and runs the tests
via ``python setup.py test -q``.
- The ``py32`` environment builds a ``virtualenv`` with ``python3.2``,
installs :mod:`zope.configuration` and dependencies, and runs the tests
via ``python setup.py test -q``.
- The ``pypy`` environment builds a ``virtualenv`` with ``pypy``,
installs :mod:`zope.configuration`, and runs the tests
via ``python setup.py test -q``.
- The ``coverage`` environment builds a ``virtualenv`` with ``python2.6``,
installs :mod:`zope.configuration`, installs
:mod:`nose` and :mod:`coverage`, and runs ``nosetests`` with statement
coverage.
- The ``docs`` environment builds a virtualenv with ``python2.6``, installs
:mod:`zope.configuration`, installs ``Sphinx`` and
dependencies, and then builds the docs and exercises the doctest snippets.
This example requires that you have a working ``python2.6`` 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 249 tests in 0.366s
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
===============
544 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 :)
Submitting a Bug Report
-----------------------
:mod:`zope.configuration` tracks its bugs on Launchpad:
https://bugs.launchpad.net/zope.configuration
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 you got a read-only checkout from the Subversion repository, and you
have made a change you would like to share, the best route is to let
Subversion help you make a patch file:
.. code-block:: sh
$ svn diff > zope.configuration-cool_feature.patch
You can then upload that patch file as an attachment to a Launchpad bug
report.
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:~tseaver/zope.configuration/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.configuration-4.0.3/MANIFEST.in 0000664 0001750 0001750 00000000242 12074062437 017010 0 ustar tseaver tseaver include *.rst
include *.txt
recursive-include docs *
recursive-include src *
global-exclude *.dll
global-exclude *.pyc
global-exclude *.pyo
global-exclude *.so