[Checkins] SVN: van.pydeb/ Initial import of van.pydeb. This package extends and replaces

Brian Sutherland jinty at web.de
Tue May 26 09:14:01 EDT 2009


Log message for revision 100399:
  Initial import of van.pydeb. This package extends and replaces
  vanguardistas.pydebdep.
  
  It also breaks backwards compatibility badly (which is why it's a new package).
  
  vanguardistas.pydebdep will shortly be removed.
  

Changed:
  A   van.pydeb/
  A   van.pydeb/trunk/
  A   van.pydeb/trunk/README.txt
  A   van.pydeb/trunk/buildout.cfg
  A   van.pydeb/trunk/setup.py
  A   van.pydeb/trunk/van/
  A   van.pydeb/trunk/van/__init__.py
  A   van.pydeb/trunk/van/pydeb/
  A   van.pydeb/trunk/van/pydeb/__init__.py
  A   van.pydeb/trunk/van/pydeb/py_to_bin.txt
  A   van.pydeb/trunk/van/pydeb/py_to_src.txt
  A   van.pydeb/trunk/van/pydeb/tests/
  A   van.pydeb/trunk/van/pydeb/tests/__init__.py
  A   van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/
  A   van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/PKG-INFO
  A   van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/SOURCES.txt
  A   van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/dependency_links.txt
  A   van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/namespace_packages.txt
  A   van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/requires.txt
  A   van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/top_level.txt
  A   van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/
  A   van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/PKG-INFO
  A   van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/SOURCES.txt
  A   van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/dependency_links.txt
  A   van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/namespace_packages.txt
  A   van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/requires.txt
  A   van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/top_level.txt
  A   van.pydeb/trunk/van/pydeb/tests/extras.txt
  A   van.pydeb/trunk/van/pydeb/tests/test_doctest.py
  A   van.pydeb/trunk/van/pydeb/tests/translations.txt
  A   van.pydeb/trunk/van/pydeb/tests/version.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/
  A   van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/PKG-INFO
  A   van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/SOURCES.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/dependency_links.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/namespace_packages.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/not-zip-safe
  A   van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/requires.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/top_level.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/
  A   van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/PKG-INFO
  A   van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/SOURCES.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/dependency_links.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/namespace_packages.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/not-zip-safe
  A   van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/requires.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/top_level.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/
  A   van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/PKG-INFO
  A   van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/SOURCES.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/dependency_links.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/namespace_packages.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/not-zip-safe
  A   van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/requires.txt
  A   van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/top_level.txt

-=-
Added: van.pydeb/trunk/README.txt
===================================================================
--- van.pydeb/trunk/README.txt	                        (rev 0)
+++ van.pydeb/trunk/README.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,45 @@
+PyDebDep
+========
+
+Tools for introspecting egg-info directories and translating the resulting
+information into debian format. This information is translated:
+
+    * Setuptools version numbers to debian format that sorts correctly
+    * Setuptools package names to debian binary and source package names
+    * Setuptools dependencies to debian dependencies
+
+This package provides a script ``pydebdep`` which introspects an installed
+.egg-info to extract egg dependency information. The package names are
+converted to their debian equivilant and the dependency information is printed
+in the format of a dpkg "Depends:" line.
+
+Usage
+-----
+
+To extract the dependency info of this package, one can::
+
+    $ python2.4 setup.py build
+    $ PYTHONPATH=./src python2.4 pydebdep --depends --egg_info src/vanguardistas.pydebdep.egg-info
+    python-setuptools, python-vanguardistas
+
+This information can then used in a debian/rules file as follows:
+
+    i="$$(pydebdep --depends --egg_info debian/$(PACKAGE)/usr/lib/python$*/site-packages/$(EGG_NAME).egg-info)" && echo "setuptools:Depends=$$i" >> debian/$(PACKAGE).substvars
+
+The different methods of using this are:
+
+Give the dependencies (including the extra dependencies) of the package:
+
+    pydebdep depends --egg_info debian/$(PACKAGE)/usr/lip/python$*/$(EGG_NAME).egg-info
+
+The dependencies of an extra:
+
+    pydebdep depends --egg_info debian/$(PACKAGE)/usr/lip/python$*/$(EGG_NAME).egg-info --extra $(EXTRA)
+
+The dependencies of 2 extras:
+    
+    pydebdep depends --egg_info debian/$(PACKAGE)/usr/lip/python$*/$(EGG_NAME).egg-info --extra $(EXTRA) --extra $(EXTRA2)
+
+The dependencies of a package excluding the dependencies of extras:
+
+    pydebdep depends --egg_info debian/$(PACKAGE)/usr/lip/python$*/$(EGG_NAME).egg-info --exclude-extra $(EXTRA1) --exclude-extra $(EXTRA2)


Property changes on: van.pydeb/trunk/README.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/buildout.cfg
===================================================================
--- van.pydeb/trunk/buildout.cfg	                        (rev 0)
+++ van.pydeb/trunk/buildout.cfg	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,13 @@
+[buildout]
+parts = test interp
+develop = .
+project = van.pydeb
+
+[interp]
+recipe = zc.recipe.egg
+eggs = ${buildout:project}
+interpreter = python
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = ${buildout:project}

Added: van.pydeb/trunk/setup.py
===================================================================
--- van.pydeb/trunk/setup.py	                        (rev 0)
+++ van.pydeb/trunk/setup.py	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,44 @@
+##############################################################################
+#
+# Copyright (c) 2008 Vanguardistas 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 os
+from setuptools import setup, find_packages
+
+long_description = open('README.txt', 'r').read()
+
+setup(name="van.pydeb",
+      description='Make egg metadata information available for Debian packaging',
+      long_description=long_description,
+      author="Vanguardistas",
+      url='http://pypi.python.org/pypi/van.pydeb',
+      version='1.0.0dev',
+      license = 'ZPL 2.1',
+      packages=find_packages(),
+      entry_points = {'console_scripts': ['van_pydeb = van.pydeb:main',]},
+      namespace_packages=["van"],
+      install_requires=[
+          'setuptools',
+          ],
+      classifiers=['Development Status :: 4 - Beta',
+                   'Intended Audience :: Developers',
+                   'Intended Audience :: System Administrators',
+                   'Topic :: System :: Archiving :: Packaging',
+                   'License :: DFSG approved',
+                   'License :: OSI Approved :: Zope Public License',
+                   'Framework :: Setuptools Plugin',
+                   'Operating System :: POSIX :: Linux',
+                   'Programming Language :: Python',
+                   ],
+      include_package_data = True,
+      zip_safe = False,
+      )


Property changes on: van.pydeb/trunk/setup.py
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/__init__.py
===================================================================
--- van.pydeb/trunk/van/__init__.py	                        (rev 0)
+++ van.pydeb/trunk/van/__init__.py	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,3 @@
+# this is a namespace package
+import pkg_resources
+pkg_resources.declare_namespace(__name__)


Property changes on: van.pydeb/trunk/van/__init__.py
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/__init__.py
===================================================================
--- van.pydeb/trunk/van/pydeb/__init__.py	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/__init__.py	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,206 @@
+##############################################################################
+#
+# Copyright (c) 2008 Vanguardistas 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
+import os.path
+import optparse
+
+from pkg_resources import PathMetadata, Distribution
+from pkg_resources import component_re # Is this a public interface?
+
+_HERE = os.path.dirname(__file__)
+#
+# Package name conversion
+#
+
+# An attempt at a cannonical list of translations
+def _read_map(file):
+    map = {}
+    reverse_map = {}
+    try:
+        f = open(file, 'r')
+        for line in f.readlines():
+            line = line.strip()
+            if not line or line.startswith('#'):
+                continue
+            k, v = line.split()
+            assert k not in map, "Duplicate key %s already in map. File %s" % (k, file)
+            map[k] = v
+            assert v not in reverse_map, "Duplicate key %s already in reverse map. File %s" % (v, file)
+            reverse_map[v] = k
+    finally:
+        f.close()
+    return map, reverse_map
+
+_PY_TO_BIN, _BIN_TO_PY = _read_map(os.path.join(_HERE, 'py_to_bin.txt'))
+_PY_TO_SRC, _SRC_TO_PY = _read_map(os.path.join(_HERE, 'py_to_src.txt'))
+
+def py_to_bin(setuptools_project):
+    """Convert a setuptools project name to a debian binary package name"""
+    return _PY_TO_BIN.get(setuptools_project, 'python-%s' % setuptools_project.lower())
+
+def py_to_src(setuptools_project):
+    """Convert a setuptools project name to a debian source package name"""
+    return _PY_TO_SRC.get(setuptools_project, setuptools_project.lower())
+
+def bin_to_py(binary_package):
+    """Convert a doebian binary package name to a setuptools project name"""
+    py_package_name = _BIN_TO_PY.get(binary_package)
+    if py_package_name is not None:
+        return py_package_name
+    assert binary_package.startswith('python-')
+    return binary_package[7:]
+
+def src_to_py(source_package):
+    """Convert a debian source package name to a setuptools project name"""
+    return _SRC_TO_PY.get(source_package, source_package)
+
+#
+# Version Conversion
+#
+
+
+def py_version_to_deb(version):
+    """Converts an egg version to debian format to preserve sorting rules.
+
+    We try to convert egg versions to debian versions here in a way that
+    preserves sorting rules and takes into account egg ideosynchracies. We also
+    try to maintain readability of the version numbers and so do not aim for
+    perfection (It's highly doubtful we could attain it anyway).
+
+    For a simple and nasty example:
+
+        >>> py_version_to_deb('2.8.0')
+        '2.8.0'
+        >>> py_version_to_deb('2.8.0pre1')
+        '2.8.0~c~pre1'
+
+    """
+    version = version.lower()
+    result = []
+    for part in component_re.split(version):
+        if not part or part.isdigit() or part == '.' or part == '-':
+            result.append(part)
+            continue
+        result.append('~')
+        if part in ['pre', 'preview', 'rc']:
+            # ok. so because of the way setuptools does this, we can't manage to preserve the original
+            # version number and maintain sort order
+            result.append('c~')
+        if part == 'dev':
+            result.append('~')
+        result.append(part)
+    return ''.join(result)
+
+#
+# Dependency Conversion
+#
+
+_setuptools_debian_operators = {'>=': '>=',
+                                '>': '>>',
+                                '<': '<<',
+                                '==': '=',
+                                '!=': None, # != not supported by debian, use conflicts in future for this
+                                '<=': '<='}
+
+def main(argv=sys.argv):
+    """Run the dependency calculation program.
+
+        >>> import os
+        >>> here = os.path.dirname(__file__)
+        >>> ex1 = os.path.join(here, 'tests', 'dummy.foo.egg-info')
+        >>> exitcode = main(['bin', 'depends', '--egg_info', ex1])
+        python-bar (<< 0.3~c~pre1), python-dummy, python-foo (>> 0.1), python-foobar
+        >>> exitcode
+        0
+    """
+    parser = optparse.OptionParser(usage="usage: %prog command [options]")
+    parser.add_option("--egg_info", dest="egg_info",
+                      help="The egg-info directory to use.")
+    parser.add_option("--exclude-extra", dest="exclude_extras", action="append",
+                      help="Exclude extras from dependencies")
+    parser.add_option("--extra", dest="extras", action="append",
+                      help="Generate dependency for extra[s]")
+    options, args = parser.parse_args(argv)
+    assert len(args) == 2, "One and only one command can be specified"
+    command = args[1]
+    assert os.path.exists(options.egg_info), "Does not exist: %s" % options.egg_info
+    if command == 'depends':
+        deps = _get_debian_dependencies(options.egg_info, extras=options.extras, exclude_extras=options.exclude_extras)
+        print ', '.join(sorted(deps))
+    elif command == 'provides':
+        deps = _get_debian_provides(options.egg_info, extras=options.extras, exclude_extras=options.exclude_extras)
+        print ', '.join(sorted(deps))
+    else:
+        raise Exception("Unknown command: %s" % command)
+    return 0
+
+def _get_debian_provides(file, extras=None, exclude_extras=None):
+    # get provides for extras
+    pydeps = set([])
+    base_dir = os.path.dirname(file)
+    metadata = PathMetadata(base_dir, file)
+    dist = Distribution.from_filename(file, metadata=metadata)
+    if exclude_extras is not None:
+        assert extras is None
+        extras = set(dist.extras) - set(exclude_extras)
+    if extras is None:
+        extras = set(dist.extras)
+    for i in extras:
+        pydeps.add('%s-%s' % (py_to_bin(dist.project_name), i))
+    return pydeps
+
+def _get_debian_dependencies(file, extras=None, exclude_extras=None):
+    """Returns a list of the format of the dpkg dependency info."""
+    pydeps = set([])
+    base_dir = os.path.dirname(file)
+    metadata = PathMetadata(base_dir, file)
+    dist = Distribution.from_filename(file, metadata=metadata)
+    included_extras = set(dist.extras)
+    if exclude_extras is not None:
+        included_extras = included_extras - set(exclude_extras)
+    if extras is not None:
+        assert exclude_extras is None
+        included_extras = extras
+    for req in dist.requires(extras=included_extras):
+        bin_pkg = py_to_bin(req.project_name)
+        pkgs = []
+        for extra in req.extras:
+            pkgs.append('%s-%s' % (bin_pkg, extra))
+        if not pkgs:
+            pkgs = [bin_pkg]
+        for pkg in pkgs:
+            if req.specs:
+                for spec in req.specs:
+                    op, version = spec
+                    op = _setuptools_debian_operators[op]
+                    if op is None:
+                        continue
+                    dpkg_version = py_version_to_deb(version)
+                    pydeps.add('%s (%s %s)' % (pkg, op, dpkg_version))
+            else:
+                pydeps.add(pkg)
+    # Let's depend on the namespace pacakges as well.
+    # this is a pretty ugly way to get __init__.py into the namespace packages
+    # which seems to be necessary.
+    # though testing it out on ubuntu gutsy said it wasnt, it was on Debian etch
+    #
+    # Perhaps we could remove this a bit later
+    namespace_pkgs = dist._get_metadata('namespace_packages.txt')
+    for pkg in namespace_pkgs:
+        bin_pkg = py_to_bin(pkg)
+        pydeps.add(bin_pkg)
+    if extras is not None:
+        # only give the dependencies of the metapackage
+        pydeps = pydeps - _get_debian_dependencies(file, exclude_extras=dist.extras)
+    return pydeps


Property changes on: van.pydeb/trunk/van/pydeb/__init__.py
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/py_to_bin.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/py_to_bin.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/py_to_bin.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,9 @@
+# Map eggs to debian binary packages
+
+pytz                                        python-tz
+PIL                                         python-imaging
+Reportlab                                   python-reportlab
+BeautifulSoup                               python-beautifulsoup
+M2Crypto                                    python-m2crypto
+SQLAlchemy                                  python-sqlalchemy
+ZODB3                                       python-zodb


Property changes on: van.pydeb/trunk/van/pydeb/py_to_bin.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/py_to_src.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/py_to_src.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/py_to_src.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,8 @@
+# Map eggs to debian source packages
+BeautifulSoup                                   beautifulsoup
+M2Crypto                                        m2crypto
+SQLAlchemy                                      sqlalchemy
+ZODB3                                           zodb
+PIL                                             python-imaging
+Reportlab                                       python-reportlab
+pytz                                            python-tz


Property changes on: van.pydeb/trunk/van/pydeb/py_to_src.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/__init__.py
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/__init__.py	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/__init__.py	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+# import


Property changes on: van.pydeb/trunk/van/pydeb/tests/__init__.py
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/PKG-INFO
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/PKG-INFO	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/PKG-INFO	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: dummy.FOO2
+Version: 1.0
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: UNKNOWN
+Author-email: UNKNOWN
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN

Added: van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/SOURCES.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/SOURCES.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/SOURCES.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,16 @@
+__init__.py
+apt.py
+egg_metadata.txt
+setup.ex1.py
+setup.ex2.py
+simple.dsc
+test_doctest.py
+dummy/__init__.py
+dummy.FOO2.egg-info/PKG-INFO
+dummy.FOO2.egg-info/SOURCES.txt
+dummy.FOO2.egg-info/dependency_links.txt
+dummy.FOO2.egg-info/namespace_packages.txt
+dummy.FOO2.egg-info/requires.txt
+dummy.FOO2.egg-info/top_level.txt
+dummy/FOO2/__init__.py
+test_eggs/z3c.breadcrumb-1.0.2.tar.gz


Property changes on: van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/SOURCES.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/dependency_links.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/dependency_links.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/dependency_links.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+


Property changes on: van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/dependency_links.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/namespace_packages.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/namespace_packages.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/namespace_packages.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+dummy


Property changes on: van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/namespace_packages.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/requires.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/requires.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/requires.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,4 @@
+foo > 0.1
+foobar
+bar != 0.2
+bar < 0.3
\ No newline at end of file


Property changes on: van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/requires.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/top_level.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/top_level.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/top_level.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+dummy


Property changes on: van.pydeb/trunk/van/pydeb/tests/dummy.FOO2.egg-info/top_level.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/PKG-INFO
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/PKG-INFO	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/PKG-INFO	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: dummy.foo
+Version: 1.0
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: UNKNOWN
+Author-email: UNKNOWN
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN

Added: van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/SOURCES.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/SOURCES.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/SOURCES.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,16 @@
+__init__.py
+apt.py
+egg_metadata.txt
+setup.ex1.py
+setup.ex2.py
+simple.dsc
+test_doctest.py
+dummy/__init__.py
+dummy.foo.egg-info/PKG-INFO
+dummy.foo.egg-info/SOURCES.txt
+dummy.foo.egg-info/dependency_links.txt
+dummy.foo.egg-info/namespace_packages.txt
+dummy.foo.egg-info/requires.txt
+dummy.foo.egg-info/top_level.txt
+dummy/foo/__init__.py
+test_eggs/z3c.breadcrumb-1.0.2.tar.gz


Property changes on: van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/SOURCES.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/dependency_links.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/dependency_links.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/dependency_links.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+


Property changes on: van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/dependency_links.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/namespace_packages.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/namespace_packages.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/namespace_packages.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+dummy


Property changes on: van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/namespace_packages.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/requires.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/requires.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/requires.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,4 @@
+foo > 0.1
+foobar
+bar != 0.2
+bar < 0.3pre1


Property changes on: van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/requires.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/top_level.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/top_level.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/top_level.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+dummy


Property changes on: van.pydeb/trunk/van/pydeb/tests/dummy.foo.egg-info/top_level.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/extras.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/extras.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/extras.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,76 @@
+Setuptools Extras Handling
+==========================
+
+Setup
+-----
+ 
+    >>> import os
+    >>> from van.pydeb import tests, main
+    >>> here = os.path.dirname(tests.__file__)
+    >>> zope_component = os.path.join(here, 'zope.component.egg-info')
+    >>> zope_security = os.path.join(here, 'zope.security.egg-info')
+    >>> zope_app_publication = os.path.join(here, 'zope.app.publication.egg-info')
+
+    >>> def runit(string):
+    ...     main(['bin'] + string.split())
+
+The basic case: package depends directly on all extra dependencies
+------------------------------------------------------------------
+
+zope.component has a 'zcml' extra, we should check that by the the dependencies
+of this extra are shown in the depends and provides line:
+  
+    >>> runit('depends --egg_info %s' % zope_component)
+    python-setuptools, python-z3c.recipe.sphinxdoc, python-zodb, python-zope, python-zope.configuration, python-zope.event, python-zope.hookable, python-zope.i18nmessageid, python-zope.interface, python-zope.location, python-zope.proxy, python-zope.security, python-zope.testing
+
+We can have create a provides line for all extras:
+
+    >>> runit('provides --egg_info %s' % zope_component)
+    python-zope.component-docs, python-zope.component-hook, python-zope.component-persistentregistry, python-zope.component-test, python-zope.component-zcml
+
+Moving an extra's dependencies into "Suggests:"
+-----------------------------------------------
+
+We notice that the "docs" dependency us not a hard one and decide to exclude it
+(it goes into Suggests:):
+
+    >>> runit('depends --egg_info %s --exclude-extra docs' % zope_component)
+    python-setuptools, python-zodb, python-zope, python-zope.configuration, python-zope.event, python-zope.hookable, python-zope.i18nmessageid, python-zope.interface, python-zope.location, python-zope.proxy, python-zope.security, python-zope.testing
+
+We could also exclude it from the "provides" list:
+
+    >>> runit('provides --egg_info %s --exclude-extra docs' % zope_component)
+    python-zope.component-hook, python-zope.component-persistentregistry, python-zope.component-test, python-zope.component-zcml
+
+Moving an extra into a metapackage
+----------------------------------
+
+Now we decide to move the 'zcml' extra to it's own metapackage, thus we need to separate out it's dependencies:
+
+    >>> runit('depends --egg_info %s --exclude-extra docs --exclude-extra zcml' % zope_component)
+    python-setuptools, python-zodb, python-zope, python-zope.event, python-zope.hookable, python-zope.interface, python-zope.location, python-zope.testing
+    >>> runit('depends --egg_info %s --extra zcml' % zope_component)
+    python-zope.configuration, python-zope.i18nmessageid, python-zope.proxy, python-zope.security
+
+We could also have the docs extra included in the metapackage if we wanted:
+
+    >>> runit('depends --egg_info %s --extra zcml --extra docs' % zope_component)
+    python-z3c.recipe.sphinxdoc, python-zope.configuration, python-zope.i18nmessageid, python-zope.proxy, python-zope.security
+
+And make a "Provides" list for that:
+
+    >>> runit('provides --egg_info %s --extra docs --extra zcml' % zope_component)
+    python-zope.component-docs, python-zope.component-zcml
+
+Packages that depend on extras
+------------------------------
+
+Depend on the provides list:
+
+    >>> runit('depends --egg_info %s' % zope_app_publication) # doctest: +ELLIPSIS
+    python-..., python-zope.component-zcml, ...
+
+But packages that don't, get the original dependency:
+
+    >>> runit('depends --egg_info %s' % zope_security) # doctest: +ELLIPSIS
+    python-..., python-zope.component, ...


Property changes on: van.pydeb/trunk/van/pydeb/tests/extras.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/test_doctest.py
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/test_doctest.py	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/test_doctest.py	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,23 @@
+##############################################################################
+#
+# Copyright (c) 2008 Vanguardistas 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 unittest
+import doctest
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(doctest.DocTestSuite('van.pydeb'))
+    suite.addTest(doctest.DocFileSuite('translations.txt'))
+    suite.addTest(doctest.DocFileSuite('extras.txt'))
+    suite.addTest(doctest.DocFileSuite('version.txt'))
+    return suite


Property changes on: van.pydeb/trunk/van/pydeb/tests/test_doctest.py
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/translations.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/translations.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/translations.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,39 @@
+Test various builtin translations
+=================================
+
+
+    >>> from van import pydeb
+
+Paste
+-----
+
+    >>> print pydeb.py_to_bin("Paste")
+    python-paste
+    >>> print pydeb.py_to_bin("PasteDeploy")
+    python-pastedeploy
+    >>> print pydeb.py_to_bin("PasteScript")
+    python-pastescript
+
+ZODB3
+-----
+
+    >>> print pydeb.py_to_bin("ZODB3")
+    python-zodb
+    >>> print pydeb.py_to_src("ZODB3")
+    zodb
+    >>> print pydeb.bin_to_py("python-zodb")
+    ZODB3
+    >>> print pydeb.src_to_py("zodb")
+    ZODB3
+
+zope.interface
+--------------
+    
+    >>> print pydeb.py_to_bin("zope.interface")
+    python-zope.interface
+    >>> print pydeb.py_to_src("zope.interface")
+    zope.interface
+    >>> print pydeb.bin_to_py("python-zope.interface")
+    zope.interface
+    >>> print pydeb.src_to_py("zope.interface")
+    zope.interface


Property changes on: van.pydeb/trunk/van/pydeb/tests/translations.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/version.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/version.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/version.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,82 @@
+Test conversion between setuptools and debian version numbers
+
+Setup a testing function:
+
+    >>> from van.pydeb import py_version_to_deb
+    >>> from pkg_resources import parse_version
+    >>> from subprocess import call
+
+    >>> def dpkg_is_gt(v1, v2):
+    ...     return call(['dpkg', '--compare-versions', v1, '>>', v2]) == 0
+    >>> def test_gt(v1, v2):
+    ...     st_gt = parse_version(v1) > parse_version(v2)
+    ...     v1_c, v2_c = py_version_to_deb(v1), py_version_to_deb(v2)
+    ...     dpkg_gt = dpkg_is_gt(v1_c, v2_c)
+    ...     print "Dpkgized versions:", v1_c, v2_c
+    ...     if st_gt == dpkg_gt:
+    ...         if st_gt:
+    ...             print "Greater Than"
+    ...         else:
+    ...             print "Not Greater Than"
+    ...     else:
+    ...         print "ERROR: setuptools and dpkg do not agree."
+
+These are the cases we want to fix:
+
+    >>> test_gt('2.8.0', '2.8.0dev1')
+    Dpkgized versions: 2.8.0 2.8.0~~dev1
+    Greater Than
+
+    >>> test_gt('2.8.0pre1', '2.8.0a1')
+    Dpkgized versions: 2.8.0~c~pre1 2.8.0~a1
+    Greater Than
+
+    >>> test_gt('2.8.0d1', '2.8.0pre1')
+    Dpkgized versions: 2.8.0~d1 2.8.0~c~pre1
+    Greater Than
+
+    >>> test_gt('2.8.0a1', '2.8.0dev1')
+    Dpkgized versions: 2.8.0~a1 2.8.0~~dev1
+    Greater Than
+
+    >>> test_gt('2.8.0-1', '2.8.0rc1')
+    Dpkgized versions: 2.8.0-1 2.8.0~c~rc1
+    Greater Than
+
+    >>> test_gt('2.8.1', '2.8.0-1')
+    Dpkgized versions: 2.8.1 2.8.0-1
+    Greater Than
+
+    >>> test_gt('2.8.0', '2.8.0a1')
+    Dpkgized versions: 2.8.0 2.8.0~a1
+    Greater Than
+
+    >>> test_gt('2.8.0', '2.8.0pre1')
+    Dpkgized versions: 2.8.0 2.8.0~c~pre1
+    Greater Than
+
+    >>> test_gt('2.8.0preview1', '2.8.0a1')
+    Dpkgized versions: 2.8.0~c~preview1 2.8.0~a1
+    Greater Than
+
+    >>> test_gt('2.8.0', '2.8.0rc1')
+    Dpkgized versions: 2.8.0 2.8.0~c~rc1
+    Greater Than
+
+    >>> test_gt('2.8.0', '2.8.0RC1')
+    Dpkgized versions: 2.8.0 2.8.0~c~rc1
+    Greater Than
+
+    >>> test_gt('2.8.0possible', '2.8.0rc1') # even duplicate the bugs...
+    Dpkgized versions: 2.8.0~possible 2.8.0~c~rc1
+    Greater Than
+
+    >>> test_gt('2.8.0rc1', '2.8.0RC1')
+    Dpkgized versions: 2.8.0~c~rc1 2.8.0~c~rc1
+    Not Greater Than
+
+    >>> test_gt('2.8.0cat', '2.8.0rc1')
+    Dpkgized versions: 2.8.0~cat 2.8.0~c~rc1
+    Greater Than
+
+


Property changes on: van.pydeb/trunk/van/pydeb/tests/version.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/PKG-INFO
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/PKG-INFO	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/PKG-INFO	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,122 @@
+Metadata-Version: 1.0
+Name: zope.app.publication
+Version: 3.7.1dev
+Summary: Zope publication
+Home-page: http://pypi.python.org/pypi/zope.app.publication
+Author: Zope Corporation and Contributors
+Author-email: zope-dev at zope.org
+License: ZPL 2.1
+Description: Publication and traversal components.
+        
+        =======
+        CHANGES
+        =======
+        
+        3.7.1 (unreleased)
+        ------------------
+        
+        - ...
+        
+        3.7.0 (2009-05-23)
+        ------------------
+        
+        - Moved the publicationtraverse module to zope.traversing, removing the
+        zope.app.publisher -> zope.app.publication dependency (which was a
+        cycle).
+        
+        - Moved IHTTPException to zope.publisher, removing the dependency
+        on zope.app.http.
+        
+        - Moved the DefaultViewName API from zope.app.publisher.browser to
+        zope.publisher.defaultview, making it accessible to other packages
+        that need it.
+        
+        - Look up the application controller through a utility registration
+        rather than a direct reference.
+        
+        3.6.0 (2009-05-18)
+        ------------------
+        
+        - Use ``zope:adapter`` ZCML directive instead of ``zope:view``.
+        This avoid dependency on ``zope.app.component``.
+        
+        - Update imports from ``zope.app.security`` to ``zope.authentication`` and
+        ``zope.principalregistry``.
+        
+        - Use ``zope.browser.interfaces.ISystemError`` to avoid dependency on
+        ``zope.app.exception``.
+        
+        - Refactored tests so they can run successfully with ZODB 3.8 and 3.9.
+        
+        3.5.3 (2009-03-13)
+        ------------------
+        
+        - Adapt to the removal of IXMLPresentation from zope.app.publisher which
+        was removed to adapt to removal of deprecated interfaces from zope.component.
+        
+        3.5.2 (2009-03-10)
+        ------------------
+        
+        - Use ISkinnable.providedBy(request) instead of IBrowserRequest as condition
+        for calling setDefaultSkin. This at the same time removes dependency to
+        the browser part of zope.publisher.
+        
+        - Remove deprecated code.
+        
+        - Use built-in set class instead of the deprecated sets.Set and thus
+        don't cause deprecation warning in Python 2.6.
+        
+        3.5.1 (2009-01-31)
+        ------------------
+        
+        - Import ISite from zope.location.interfaces instead of deprecated place
+        in zope.app.component.interfaces.
+        
+        3.5.0 (2008-10-09)
+        ------------------
+        
+        - Now ``zope.app.publication.zopepublication.ZopePublication`` annotates the
+        request with the connection to the main ZODB when ``getApplication`` is
+        called.
+        
+        - Removed support for non-existent Zope versions.
+        
+        
+        3.4.3 (2007-11-01)
+        ------------------
+        
+        - Removed unused imports.
+        
+        - Resolve ``ZopeSecurityPolicy`` deprecation warning.
+        
+        
+        3.4.2 (2007-09-26)
+        ------------------
+        
+        - Added missing files to egg distribution.
+        
+        
+        3.4.1 (2007-09-26)
+        ------------------
+        
+        - Added missing files to egg distribution.
+        
+        
+        3.4.0 (2007-09-25)
+        ------------------
+        
+        - Initial documented release.
+        
+        - Reflect changes form ``zope.app.error`` refactoring.
+        
+Keywords: zope3 publication
+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: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Topic :: Internet :: WWW/HTTP
+Classifier: Framework :: Zope3

Added: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/SOURCES.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/SOURCES.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/SOURCES.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,48 @@
+CHANGES.txt
+README.txt
+bootstrap.py
+buildout.cfg
+setup.py
+src/zope/__init__.py
+src/zope.app.publication.egg-info/PKG-INFO
+src/zope.app.publication.egg-info/SOURCES.txt
+src/zope.app.publication.egg-info/dependency_links.txt
+src/zope.app.publication.egg-info/namespace_packages.txt
+src/zope.app.publication.egg-info/not-zip-safe
+src/zope.app.publication.egg-info/requires.txt
+src/zope.app.publication.egg-info/top_level.txt
+src/zope/app/__init__.py
+src/zope/app/publication/__init__.py
+src/zope/app/publication/browser.py
+src/zope/app/publication/configure.zcml
+src/zope/app/publication/ftesting.zcml
+src/zope/app/publication/ftp.py
+src/zope/app/publication/http.py
+src/zope/app/publication/httpfactory.py
+src/zope/app/publication/httpfactory.txt
+src/zope/app/publication/interfaces.py
+src/zope/app/publication/meta.zcml
+src/zope/app/publication/metaconfigure.py
+src/zope/app/publication/metadirectives.py
+src/zope/app/publication/methodnotallowed.txt
+src/zope/app/publication/notfound.txt
+src/zope/app/publication/publicationtraverse.py
+src/zope/app/publication/requestpublicationfactories.py
+src/zope/app/publication/requestpublicationregistry.py
+src/zope/app/publication/soap.py
+src/zope/app/publication/testing.py
+src/zope/app/publication/traversers.py
+src/zope/app/publication/xmlrpc.py
+src/zope/app/publication/zopepublication.py
+src/zope/app/publication/tests/__init__.py
+src/zope/app/publication/tests/ftest_zcml_dependencies.zcml
+src/zope/app/publication/tests/test_browserpublication.py
+src/zope/app/publication/tests/test_dependencies.py
+src/zope/app/publication/tests/test_functional.py
+src/zope/app/publication/tests/test_http.py
+src/zope/app/publication/tests/test_httpfactory.py
+src/zope/app/publication/tests/test_requestpublicationfactories.py
+src/zope/app/publication/tests/test_requestpublicationregistry.py
+src/zope/app/publication/tests/test_simplecomponenttraverser.py
+src/zope/app/publication/tests/test_xmlrpcpublication.py
+src/zope/app/publication/tests/test_zopepublication.py
\ No newline at end of file


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/SOURCES.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/dependency_links.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/dependency_links.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/dependency_links.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/dependency_links.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/namespace_packages.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/namespace_packages.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/namespace_packages.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,2 @@
+zope
+zope.app


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/namespace_packages.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/not-zip-safe
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/not-zip-safe	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/not-zip-safe	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+

Added: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/requires.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/requires.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/requires.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,21 @@
+zope.interface
+ZODB3
+zope.authentication
+zope.component [zcml]
+zope.deprecation
+zope.error
+zope.i18n
+zope.browser>=1.2
+zope.publisher>=3.8.0
+zope.traversing>=3.7.0
+setuptools
+
+[test]
+zope.app.testing
+zope.app.securitypolicy
+zope.app.zcmlfiles>=3.5.4
+zope.app.dav
+zope.app.publisher
+zope.app.zptpage
+zope.principalregistry
+zope.app.applicationcontrol>=3.5.0
\ No newline at end of file


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/requires.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/top_level.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/top_level.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/top_level.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+zope


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.app.publication.egg-info/top_level.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/PKG-INFO
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/PKG-INFO	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/PKG-INFO	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,2537 @@
+Metadata-Version: 1.0
+Name: zope.component
+Version: 3.7.1dev
+Summary: Zope Component Architecture
+Home-page: http://pypi.python.org/pypi/zope.component
+Author: Zope Corporation and Contributors
+Author-email: zope-dev at zope.org
+License: ZPL 2.1
+Description: *****************************
+        zope.component Package Readme
+        *****************************
+        
+        *This package is intended to be independently reusable in any Python
+        project. It is maintained by the* `Zope Toolkit project <http://docs.zope.org/zopetoolkit/>`_.
+        
+        This package represents the core of the Zope Component Architecture.
+        Together with the 'zope.interface' package, it provides facilities for
+        defining, registering and looking up components.
+        
+        .. contents::
+        
+        Detailed Documentation
+        **********************
+        
+        Zope Component Architecture
+        ===========================
+        
+        This package, together with `zope.interface`, provides facilities for
+        defining, registering and looking up components.  There are two basic
+        kinds of components: adapters and utilities.
+        
+        Utilities
+        ---------
+        
+        Utilities are just components that provide an interface and that are
+        looked up by an interface and a name.  Let's look at a trivial utility
+        definition:
+        
+        >>> from zope import interface
+        
+        >>> class IGreeter(interface.Interface):
+        ...     def greet():
+        ...         "say hello"
+        
+        >>> class Greeter:
+        ...     interface.implements(IGreeter)
+        ...
+        ...     def __init__(self, other="world"):
+        ...         self.other = other
+        ...
+        ...     def greet(self):
+        ...         print "Hello", self.other
+        
+        We can register an instance this class using `provideUtility` [1]_:
+        
+        >>> from zope import component
+        >>> greet = Greeter('bob')
+        >>> component.provideUtility(greet, IGreeter, 'robert')
+        
+        In this example we registered the utility as providing the `IGreeter`
+        interface with a name of 'bob'. We can look the interface up with
+        either `queryUtility` or `getUtility`:
+        
+        >>> component.queryUtility(IGreeter, 'robert').greet()
+        Hello bob
+        
+        >>> component.getUtility(IGreeter, 'robert').greet()
+        Hello bob
+        
+        `queryUtility` and `getUtility` differ in how failed lookups are handled:
+        
+        >>> component.queryUtility(IGreeter, 'ted')
+        >>> component.queryUtility(IGreeter, 'ted', 42)
+        42
+        >>> component.getUtility(IGreeter, 'ted')
+        ... # doctest: +ELLIPSIS
+        Traceback (most recent call last):
+        ...
+        ComponentLookupError: (<InterfaceClass ...IGreeter>, 'ted')
+        
+        If a component provides only one interface, as in the example above,
+        then we can omit the provided interface from the call to `provideUtility`:
+        
+        >>> ted = Greeter('ted')
+        >>> component.provideUtility(ted, name='ted')
+        >>> component.queryUtility(IGreeter, 'ted').greet()
+        Hello ted
+        
+        The name defaults to an empty string:
+        
+        >>> world = Greeter()
+        >>> component.provideUtility(world)
+        >>> component.queryUtility(IGreeter).greet()
+        Hello world
+        
+        Adapters
+        --------
+        
+        Adapters are components that are computed from other components to
+        adapt them to some interface.  Because they are computed from other
+        objects, they are provided as factories, usually classes.  Here, we'll
+        create a greeter for persons, so we can provide personalized greetings
+        for different people:
+        
+        >>> class IPerson(interface.Interface):
+        ...     name = interface.Attribute("Name")
+        
+        >>> class PersonGreeter:
+        ...
+        ...     component.adapts(IPerson)
+        ...     interface.implements(IGreeter)
+        ...
+        ...     def __init__(self, person):
+        ...         self.person = person
+        ...
+        ...     def greet(self):
+        ...         print "Hello", self.person.name
+        
+        The class defines a constructor that takes an argument for every
+        object adapted.
+        
+        We used `component.adapts` to declare what we adapt.  We can find
+        out if an object declares that it adapts anything using adaptedBy:
+        
+        >>> list(component.adaptedBy(PersonGreeter)) == [IPerson]
+        True
+        
+        If an object makes no declaration, then None is returned:
+        
+        >>> component.adaptedBy(Greeter()) is None
+        True
+        
+        
+        If we declare the interfaces adapted and if we provide only one
+        interface, as in the example above, then we can provide the adapter
+        very simply [1]_:
+        
+        >>> component.provideAdapter(PersonGreeter)
+        
+        For adapters that adapt a single interface to a single interface
+        without a name, we can get the adapter by simply calling the
+        interface:
+        
+        >>> class Person:
+        ...     interface.implements(IPerson)
+        ...
+        ...     def __init__(self, name):
+        ...         self.name = name
+        
+        >>> IGreeter(Person("Sally")).greet()
+        Hello Sally
+        
+        We can also provide arguments to be very specific about what
+        how to register the adapter.
+        
+        >>> class BobPersonGreeter(PersonGreeter):
+        ...     name = 'Bob'
+        ...     def greet(self):
+        ...         print "Hello", self.person.name, "my name is", self.name
+        
+        >>> component.provideAdapter(
+        ...                        BobPersonGreeter, [IPerson], IGreeter, 'bob')
+        
+        The arguments can also be provided as keyword arguments:
+        
+        >>> class TedPersonGreeter(BobPersonGreeter):
+        ...     name = "Ted"
+        
+        >>> component.provideAdapter(
+        ...     factory=TedPersonGreeter, adapts=[IPerson],
+        ...     provides=IGreeter, name='ted')
+        
+        For named adapters, use `queryAdapter`, or `getAdapter`:
+        
+        >>> component.queryAdapter(Person("Sally"), IGreeter, 'bob').greet()
+        Hello Sally my name is Bob
+        
+        >>> component.getAdapter(Person("Sally"), IGreeter, 'ted').greet()
+        Hello Sally my name is Ted
+        
+        If an adapter can't be found, `queryAdapter` returns a default value
+        and `getAdapter` raises an error:
+        
+        >>> component.queryAdapter(Person("Sally"), IGreeter, 'frank')
+        >>> component.queryAdapter(Person("Sally"), IGreeter, 'frank', 42)
+        42
+        >>> component.getAdapter(Person("Sally"), IGreeter, 'frank')
+        ... # doctest: +ELLIPSIS
+        Traceback (most recent call last):
+        ...
+        ComponentLookupError: (...Person...>, <...IGreeter>, 'frank')
+        
+        Adapters can adapt multiple objects:
+        
+        >>> class TwoPersonGreeter:
+        ...
+        ...     component.adapts(IPerson, IPerson)
+        ...     interface.implements(IGreeter)
+        ...
+        ...     def __init__(self, person, greeter):
+        ...         self.person = person
+        ...         self.greeter = greeter
+        ...
+        ...     def greet(self):
+        ...         print "Hello", self.person.name
+        ...         print "my name is", self.greeter.name
+        
+        >>> component.provideAdapter(TwoPersonGreeter)
+        
+        To look up a multi-adapter, use either `queryMultiAdapter` or
+        `getMultiAdapter`:
+        
+        >>> component.queryMultiAdapter((Person("Sally"), Person("Bob")),
+        ...                                  IGreeter).greet()
+        Hello Sally
+        my name is Bob
+        
+        Adapters need not be classes.  Any callable will do.  We use the
+        adapter decorator (in the Python 2.4 decorator sense) to declare that
+        a callable object adapts some interfaces (or classes):
+        
+        >>> class IJob(interface.Interface):
+        ...     "A job"
+        
+        >>> class Job:
+        ...     interface.implements(IJob)
+        
+        >>> def personJob(person):
+        ...     return getattr(person, 'job', None)
+        >>> personJob = interface.implementer(IJob)(personJob)
+        >>> personJob = component.adapter(IPerson)(personJob)
+        
+        In Python 2.4, the example can be written:
+        
+        >>> @interface.implementer(IJob)
+        ... @component.adapter(IPerson)
+        ... def personJob(person):
+        ...     return getattr(person, 'job', None)
+        
+        which looks a bit nicer.
+        
+        In this example, the personJob function simply returns the person's
+        `job` attribute if present, or None if it's not present.  An adapter
+        factory can return None to indicate that adaptation wasn't possible.
+        Let's register this adapter and try it out:
+        
+        >>> component.provideAdapter(personJob)
+        >>> sally = Person("Sally")
+        >>> IJob(sally) # doctest: +ELLIPSIS
+        Traceback (most recent call last):
+        ...
+        TypeError: ('Could not adapt', ...
+        
+        The adaptation failed because sally didn't have a job.  Let's give her
+        one:
+        
+        >>> job = Job()
+        >>> sally.job = job
+        >>> IJob(sally) is job
+        True
+        
+        Subscription Adapters
+        ---------------------
+        
+        Unlike regular adapters, subscription adapters are used when we want
+        all of the adapters that adapt an object to a particular adapter.
+        
+        Consider a validation problem.  We have objects and we want to assess
+        whether they meet some sort of standards.  We define a validation
+        interface:
+        
+        >>> class IValidate(interface.Interface):
+        ...     def validate(ob):
+        ...         """Determine whether the object is valid
+        ...
+        ...         Return a string describing a validation problem.
+        ...         An empty string is returned to indicate that the
+        ...         object is valid.
+        ...         """
+        
+        Perhaps we have documents:
+        
+        >>> class IDocument(interface.Interface):
+        ...     summary = interface.Attribute("Document summary")
+        ...     body = interface.Attribute("Document text")
+        
+        >>> class Document:
+        ...     interface.implements(IDocument)
+        ...     def __init__(self, summary, body):
+        ...         self.summary, self.body = summary, body
+        
+        Now, we may want to specify various validation rules for
+        documents. For example, we might require that the summary be a single
+        line:
+        
+        >>> class SingleLineSummary:
+        ...     component.adapts(IDocument)
+        ...     interface.implements(IValidate)
+        ...
+        ...     def __init__(self, doc):
+        ...         self.doc = doc
+        ...
+        ...     def validate(self):
+        ...         if '\n' in self.doc.summary:
+        ...             return 'Summary should only have one line'
+        ...         else:
+        ...             return ''
+        
+        Or we might require the body to be at least 1000 characters in length:
+        
+        >>> class AdequateLength:
+        ...     component.adapts(IDocument)
+        ...     interface.implements(IValidate)
+        ...
+        ...     def __init__(self, doc):
+        ...         self.doc = doc
+        ...
+        ...     def validate(self):
+        ...         if len(self.doc.body) < 1000:
+        ...             return 'too short'
+        ...         else:
+        ...             return ''
+        
+        We can register these as subscription adapters [1]_:
+        
+        >>> component.provideSubscriptionAdapter(SingleLineSummary)
+        >>> component.provideSubscriptionAdapter(AdequateLength)
+        
+        We can then use the subscribers to validate objects:
+        
+        >>> doc = Document("A\nDocument", "blah")
+        >>> [adapter.validate()
+        ...  for adapter in component.subscribers([doc], IValidate)
+        ...  if adapter.validate()]
+        ['Summary should only have one line', 'too short']
+        
+        >>> doc = Document("A\nDocument", "blah" * 1000)
+        >>> [adapter.validate()
+        ...  for adapter in component.subscribers([doc], IValidate)
+        ...  if adapter.validate()]
+        ['Summary should only have one line']
+        
+        >>> doc = Document("A Document", "blah")
+        >>> [adapter.validate()
+        ...  for adapter in component.subscribers([doc], IValidate)
+        ...  if adapter.validate()]
+        ['too short']
+        
+        Handlers
+        --------
+        
+        Handlers are subscription adapter factories that don't produce
+        anything.  They do all of their work when called.  Handlers
+        are typically used to handle events.
+        
+        Event subscribers are different from other subscription adapters in
+        that the caller of event subscribers doesn't expect to interact with
+        them in any direct way.  For example, an event publisher doesn't
+        expect to get any return value.  Because subscribers don't need to
+        provide an API to their callers, it is more natural to define them
+        with functions, rather than classes.  For example, in a
+        document-management system, we might want to record creation times for
+        documents:
+        
+        >>> import datetime
+        
+        >>> def documentCreated(event):
+        ...     event.doc.created = datetime.datetime.utcnow()
+        
+        In this example, we have a function that takes an event and performs
+        some processing.  It doesn't actually return anything.  This is a
+        special case of a subscription adapter that adapts an event to
+        nothing.  All of the work is done when the adapter "factory" is
+        called.  We call subscribers that don't actually create anything
+        "handlers".  There are special APIs for registering and calling
+        them.
+        
+        To register the subscriber above, we define a document-created event:
+        
+        >>> class IDocumentCreated(interface.Interface):
+        ...     doc = interface.Attribute("The document that was created")
+        
+        >>> class DocumentCreated:
+        ...     interface.implements(IDocumentCreated)
+        ...
+        ...     def __init__(self, doc):
+        ...         self.doc = doc
+        
+        We'll also change our handler definition to:
+        
+        >>> def documentCreated(event):
+        ...     event.doc.created = datetime.datetime.utcnow()
+        
+        >>> documentCreated = component.adapter(IDocumentCreated)(documentCreated)
+        
+        Note that in Python 2.4, this can be written:
+        
+        >>> @component.adapter(IDocumentCreated)
+        ... def documentCreated(event):
+        ...     event.doc.created = datetime.datetime.utcnow()
+        
+        This marks the handler as an adapter of `IDocumentCreated` events.
+        
+        Now we'll register the handler  [1]_:
+        
+        >>> component.provideHandler(documentCreated)
+        
+        Now, if we can create an event and use the `handle` function to call
+        handlers registered for the event:
+        
+        >>> component.handle(DocumentCreated(doc))
+        >>> doc.created.__class__.__name__
+        'datetime'
+        
+        
+        
+        .. [1] CAUTION: This API should only be used from test or
+        application-setup code. This API shouldn't be used by regular
+        library modules, as component registration is a configuration
+        activity.
+        
+        Events
+        ======
+        
+        The Component Architecture provides a way to dispatch events to event
+        handlers.  Event handlers are registered as *subscribers*
+        a.k.a. *handlers*.
+        
+        Before we can start we need to import ``zope.component.event`` to make
+        the dispatching effective:
+        
+        >>> import zope.component.event
+        
+        Consider two event classes:
+        
+        >>> class Event1(object):
+        ...     pass
+        
+        >>> class Event2(Event1):
+        ...     pass
+        
+        Now consider two handlers for these event classes:
+        
+        >>> called = []
+        
+        >>> import zope.component
+        >>> @zope.component.adapter(Event1)
+        ... def handler1(event):
+        ...     called.append(1)
+        
+        >>> @zope.component.adapter(Event2)
+        ... def handler2(event):
+        ...     called.append(2)
+        
+        We can register them with the Component Architecture:
+        
+        >>> zope.component.provideHandler(handler1)
+        >>> zope.component.provideHandler(handler2)
+        
+        Now let's go through the events.  We'll see that the handlers have been
+        called accordingly:
+        
+        >>> from zope.event import notify
+        >>> notify(Event1())
+        >>> called
+        [1]
+        
+        >>> del called[:]
+        >>> notify(Event2())
+        >>> called.sort()
+        >>> called
+        [1, 2]
+        
+        
+        
+        Object events
+        -------------
+        
+        
+        The ``objectEventNotify`` function is a subscriber to dispatch
+        ObjectEvents to interested adapters.
+        
+        First create an object class:
+        
+        >>> class IUseless(zope.interface.Interface):
+        ...     """Useless object"""
+        
+        >>> class UselessObject(object):
+        ...     """Useless object"""
+        ...     zope.interface.implements(IUseless)
+        
+        Then create an event class:
+        
+        >>> class IObjectThrownEvent(zope.component.interfaces.IObjectEvent):
+        ...     """An object has been thrown away"""
+        
+        >>> class ObjectThrownEvent(zope.component.interfaces.ObjectEvent):
+        ...     """An object has been thrown away"""
+        ...     zope.interface.implements(IObjectThrownEvent)
+        
+        Create an object and an event:
+        
+        >>> hammer = UselessObject()
+        >>> event = ObjectThrownEvent(hammer)
+        
+        Then notify the event to the subscribers.
+        Since the subscribers list is empty, nothing happens.
+        
+        >>> zope.component.event.objectEventNotify(event)
+        
+        Now create an handler for the event:
+        
+        >>> events = []
+        >>> def record(*args):
+        ...     events.append(args)
+        
+        >>> zope.component.provideHandler(record, [IUseless, IObjectThrownEvent])
+        
+        The event is notified to the subscriber:
+        
+        >>> zope.component.event.objectEventNotify(event)
+        >>> events == [(hammer, event)]
+        True
+        
+        Following test demonstrates how a subscriber can raise an exception
+        to prevent an action.
+        
+        >>> zope.component.provideHandler(zope.component.event.objectEventNotify)
+        
+        Let's create a container:
+        
+        >>> class ToolBox(dict):
+        ...     def __delitem__(self, key):
+        ...         notify(ObjectThrownEvent(self[key]))
+        ...         return super(ToolBox,self).__delitem__(key)
+        
+        >>> container = ToolBox()
+        
+        And put the object into the container:
+        
+        >>> container['Red Hammer'] = hammer
+        
+        Create an handler function that will raise an error when called:
+        
+        >>> class Veto(Exception):
+        ...     pass
+        
+        >>> def callback(item, event):
+        ...     assert(item == event.object)
+        ...     raise Veto
+        
+        Register the handler:
+        
+        >>> zope.component.provideHandler(callback, [IUseless, IObjectThrownEvent])
+        
+        Then if we try to remove the object, an ObjectThrownEvent is fired:
+        
+        >>> del container['Red Hammer']
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        raise Veto
+        Veto
+        
+        Factories
+        =========
+        
+        
+        The Factory Class
+        -----------------
+        
+        >>> from zope.interface import Interface
+        >>> class IFunction(Interface):
+        ...     pass
+        
+        >>> class IKlass(Interface):
+        ...     pass
+        
+        >>> from zope.interface import implements
+        >>> class Klass(object):
+        ...     implements(IKlass)
+        ...
+        ...     def __init__(self, *args, **kw):
+        ...         self.args = args
+        ...         self.kw = kw
+        
+        >>> from zope.component.factory import Factory
+        >>> factory = Factory(Klass, 'Klass', 'Klassier')
+        >>> factory2 = Factory(lambda x: x, 'Func', 'Function')
+        >>> factory3 = Factory(lambda x: x, 'Func', 'Function', (IFunction,))
+        
+        Calling a Factory
+        ~~~~~~~~~~~~~~~~~
+        
+        Here we test whether the factory correctly creates the objects and
+        including the correct handling of constructor elements.
+        
+        First we create a factory that creates instanace of the `Klass` class:
+        
+        >>> factory = Factory(Klass, 'Klass', 'Klassier')
+        
+        Now we use the factory to create the instance
+        
+        >>> kl = factory(1, 2, foo=3, bar=4)
+        
+        and make sure that the correct class was used to create the object:
+        
+        >>> kl.__class__
+        <class 'Klass'>
+        
+        Since we passed in a couple positional and keyword arguments
+        
+        >>> kl.args
+        (1, 2)
+        >>> kl.kw
+        {'foo': 3, 'bar': 4}
+        
+        >>> factory2(3)
+        3
+        >>> factory3(3)
+        3
+        
+        
+        Title and Description
+        ~~~~~~~~~~~~~~~~~~~~~
+        
+        >>> factory.title
+        'Klass'
+        >>> factory.description
+        'Klassier'
+        >>> factory2.title
+        'Func'
+        >>> factory2.description
+        'Function'
+        >>> factory3.title
+        'Func'
+        >>> factory3.description
+        'Function'
+        
+        
+        Provided Interfaces
+        ~~~~~~~~~~~~~~~~~~~
+        
+        >>> implemented = factory.getInterfaces()
+        >>> implemented.isOrExtends(IKlass)
+        True
+        >>> list(implemented)
+        [<InterfaceClass __builtin__.IKlass>]
+        
+        >>> implemented2 = factory2.getInterfaces()
+        >>> list(implemented2)
+        []
+        
+        >>> implemented3 = factory3.getInterfaces()
+        >>> list(implemented3)
+        [<InterfaceClass __builtin__.IFunction>]
+        
+        
+        The Component Architecture Factory API
+        --------------------------------------
+        
+        >>> import zope.component
+        >>> factory = Factory(Klass, 'Klass', 'Klassier')
+        >>> gsm = zope.component.getGlobalSiteManager()
+        
+        >>> from zope.component.interfaces import IFactory
+        >>> gsm.registerUtility(factory, IFactory, 'klass')
+        
+        Creating an Object
+        ~~~~~~~~~~~~~~~~~~
+        
+        >>> kl = zope.component.createObject('klass', 1, 2, foo=3, bar=4)
+        >>> isinstance(kl, Klass)
+        True
+        >>> kl.args
+        (1, 2)
+        >>> kl.kw
+        {'foo': 3, 'bar': 4}
+        
+        Accessing Provided Interfaces
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        >>> implemented = zope.component.getFactoryInterfaces('klass')
+        >>> implemented.isOrExtends(IKlass)
+        True
+        >>> [iface for iface in implemented]
+        [<InterfaceClass __builtin__.IKlass>]
+        
+        List of All Factories
+        ~~~~~~~~~~~~~~~~~~~~~
+        
+        >>> [(name, fac.__class__) for name, fac in
+        ...  zope.component.getFactoriesFor(IKlass)]
+        [(u'klass', <class 'zope.component.factory.Factory'>)]
+        
+        
+        Component-Management objects
+        ============================
+        
+        Component-management objects provide a higher-level
+        component-management API over the basic adapter-registration API
+        provided by the zope.interface package.  In particular, it provides:
+        
+        - utilities
+        
+        - support for computing adapters, rather than just looking up adapter
+        factories.
+        
+        - management of registration comments
+        
+        The zope.component.registry.Components class provides an
+        implementation of zope.component.interfaces.IComponents that provides
+        these features.
+        
+        >>> from zope.component import registry
+        >>> from zope.component import tests
+        >>> components = registry.Components('comps')
+        
+        As components are registered, events are generated.  Let's register
+        an event subscriber, so we can see the events generated:
+        
+        >>> import zope.event
+        >>> def logevent(event):
+        ...     print event
+        >>> zope.event.subscribers.append(logevent)
+        
+        Utilities
+        ---------
+        
+        You can register Utilities using registerUtility:
+        
+        >>> components.registerUtility(tests.U1(1))
+        Registered event:
+        UtilityRegistration(<Components comps>, I1, u'', 1, None, u'')
+        
+        Here we didn't specify an interface or name.  An unnamed utility was
+        registered for interface I1, since that is only interface implemented
+        by the U1 class:
+        
+        >>> components.getUtility(tests.I1)
+        U1(1)
+        
+        You can also register a utility using a factory instead of a utility instance:
+        
+        >>> def factory():
+        ...    return tests.U1(1)
+        >>> components.registerUtility(factory=factory)
+        Registered event:
+        UtilityRegistration(<Components comps>, I1, u'', 1, <function factory at <SOME ADDRESS>>, u'')
+        
+        
+        If a component implements other than one interface or no interface,
+        then an error will be raised:
+        
+        >>> components.registerUtility(tests.U12(2))
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The utility doesn't provide a single interface and
+        no provided interface was specified.
+        
+        >>> components.registerUtility(tests.A)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The utility doesn't provide a single interface and
+        no provided interface was specified.
+        
+        
+        We can provide an interface if desired:
+        
+        >>> components.registerUtility(tests.U12(2), tests.I2)
+        Registered event:
+        UtilityRegistration(<Components comps>, I2, u'', 2, None, u'')
+        
+        and we can specify a name:
+        
+        >>> components.registerUtility(tests.U12(3), tests.I2, u'three')
+        Registered event:
+        UtilityRegistration(<Components comps>, I2, u'three', 3, None, u'')
+        
+        >>> components.getUtility(tests.I2)
+        U12(2)
+        
+        >>> components.getUtility(tests.I2, 'three')
+        U12(3)
+        
+        If you try to get a utility that doesn't exist, you'll get a component
+        lookup error:
+        
+        >>> components.getUtility(tests.I3)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        ComponentLookupError:
+        (<InterfaceClass zope.component.tests.I3>, u'')
+        
+        Unless you use queryUtility:
+        
+        >>> components.queryUtility(tests.I3)
+        >>> components.queryUtility(tests.I3, default=42)
+        42
+        
+        You can get information about registered utilities with the
+        registeredUtilities method:
+        
+        >>> for registration in sorted(components.registeredUtilities()):
+        ...     print registration.provided, registration.name
+        ...     print registration.component, registration.info
+        <InterfaceClass zope.component.tests.I1>
+        U1(1)
+        <InterfaceClass zope.component.tests.I2>
+        U12(2)
+        <InterfaceClass zope.component.tests.I2> three
+        U12(3)
+        
+        Duplicate registrations replace existing ones:
+        
+        >>> components.registerUtility(tests.U1(4), info=u'use 4 now')
+        Registered event:
+        UtilityRegistration(<Components comps>, I1, u'', 4, None, u'use 4 now')
+        >>> components.getUtility(tests.I1)
+        U1(4)
+        
+        >>> for registration in sorted(components.registeredUtilities()):
+        ...     print registration.provided, registration.name
+        ...     print registration.component, registration.info
+        <InterfaceClass zope.component.tests.I1>
+        U1(4) use 4 now
+        <InterfaceClass zope.component.tests.I2>
+        U12(2)
+        <InterfaceClass zope.component.tests.I2> three
+        U12(3)
+        
+        As shown in the this example, you can provide an "info" argumemnt when
+        registering utilities.  This provides extra documentation about the
+        registration itself that is shown when listing registrations.
+        
+        You can also unregister utilities:
+        
+        >>> components.unregisterUtility(provided=tests.I1)
+        Unregistered event:
+        UtilityRegistration(<Components comps>, I1, u'', 4, None, u'use 4 now')
+        True
+        
+        A boolean is returned indicating whether anything changed:
+        
+        >>> components.queryUtility(tests.I1)
+        >>> for registration in sorted(components.registeredUtilities()):
+        ...     print registration.provided, registration.name
+        ...     print registration.component, registration.info
+        <InterfaceClass zope.component.tests.I2>
+        U12(2)
+        <InterfaceClass zope.component.tests.I2> three
+        U12(3)
+        
+        When you unregister, you can specify a component.  If the component
+        doesn't match the one registered, then nothing happens:
+        
+        >>> u5 = tests.U1(5)
+        >>> components.registerUtility(u5)
+        Registered event:
+        UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+        >>> components.unregisterUtility(tests.U1(6))
+        False
+        >>> components.queryUtility(tests.I1)
+        U1(5)
+        >>> components.unregisterUtility(u5)
+        Unregistered event:
+        UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+        True
+        >>> components.queryUtility(tests.I1)
+        
+        You can get the name and utility for all of the utilities that provide
+        an interface using getUtilitiesFor:
+        
+        >>> sorted(components.getUtilitiesFor(tests.I2))
+        [(u'', U12(2)), (u'three', U12(3))]
+        
+        getAllUtilitiesRegisteredFor is similar to getUtilitiesFor except that
+        it includes utilities that are overridden.  For example, we'll
+        register a utility that for an extending interface of I2:
+        
+        >>> util = tests.U('ext')
+        >>> components.registerUtility(util, tests.I2e)
+        Registered event:
+        UtilityRegistration(<Components comps>, I2e, u'', ext, None, u'')
+        
+        We don't get the new utility for getUtilitiesFor:
+        
+        >>> sorted(components.getUtilitiesFor(tests.I2))
+        [(u'', U12(2)), (u'three', U12(3))]
+        
+        but we do get it from getAllUtilitiesRegisteredFor:
+        
+        >>> sorted(map(str, components.getAllUtilitiesRegisteredFor(tests.I2)))
+        ['U(ext)', 'U12(2)', 'U12(3)']
+        
+        Removing a utility also makes it disappear from getUtilitiesFor:
+        
+        >>> components.unregisterUtility(util, tests.I2e)
+        Unregistered event:
+        UtilityRegistration(<Components comps>, I2e, u'', ext, None, u'')
+        True
+        >>> list(components.getAllUtilitiesRegisteredFor(tests.I2e))
+        []
+        
+        Adapters
+        --------
+        
+        You can register adapters with registerAdapter:
+        
+        >>> components.registerAdapter(tests.A12_1)
+        Registered event:
+        AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+        
+        Here, we didn't specify required interfaces, a provided interface, or
+        a name.  The required interfaces were determined from the factory
+        s __component_adapts__ attribute and the provided interface was
+        determined by introspecting what the factory implements.
+        
+        >>> components.getMultiAdapter((tests.U1(6), tests.U12(7)), tests.IA1)
+        A12_1(U1(6), U12(7))
+        
+        If a factory implements more than one interface, an exception will be
+        raised:
+        
+        >>> components.registerAdapter(tests.A1_12)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't implement a single
+        interface and no provided interface was specified.
+        
+        Unless the provided interface is specified:
+        
+        >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
+        Registered event:
+        AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+        
+        If a factory doesn't declare an implemented interface, an exception will be
+        raised:
+        
+        >>> components.registerAdapter(tests.A12_)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't implement a single
+        interface and no provided interface was specified.
+        
+        Unless the provided interface is specified:
+        
+        >>> components.registerAdapter(tests.A12_, provided=tests.IA2)
+        Registered event:
+        AdapterRegistration(<Components comps>, [I1, I2], IA2, u'', A12_, u'')
+        
+        The required interface needs to be specified in the registration if
+        the factory doesn't have a __component_adapts__ attribute:
+        
+        >>> components.registerAdapter(tests.A_2)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't have a __component_adapts__
+        attribute and no required specifications were specified
+        
+        Unless the required specifications specified:
+        
+        >>> components.registerAdapter(tests.A_2, required=[tests.I3])
+        Registered event:
+        AdapterRegistration(<Components comps>, [I3], IA2, u'', A_2, u'')
+        
+        Classes can be specified in place of specifications, in which case the
+        implementedBy specification for the class is used:
+        
+        >>> components.registerAdapter(tests.A_3, required=[tests.U],
+        ...                            info="Really class specific")
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Registered event:
+        AdapterRegistration(<Components comps>, [zope.component.tests.U], IA3, u'',
+        A_3, 'Really class specific')
+        
+        We can see the adapters that have been registered using the
+        registeredAdapters method:
+        
+        >>> for registration in sorted(components.registeredAdapters()):
+        ...     print registration.required
+        ...     print registration.provided, registration.name
+        ...     print registration.factory, registration.info
+        ... # doctest: +NORMALIZE_WHITESPACE
+        (<InterfaceClass zope.component.tests.I1>,
+        <InterfaceClass zope.component.tests.I2>)
+        <InterfaceClass zope.component.tests.IA1>
+        zope.component.tests.A12_1
+        (<InterfaceClass zope.component.tests.I1>,
+        <InterfaceClass zope.component.tests.I2>)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A12_
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A1_12
+        (<InterfaceClass zope.component.tests.I3>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A_2
+        (<implementedBy zope.component.tests.U>,)
+        <InterfaceClass zope.component.tests.IA3>
+        zope.component.tests.A_3 Really class specific
+        
+        As with utilities, we can provide registration information when
+        registering adapters.
+        
+        If you try to fetch an adapter that isn't registered, you'll get a
+        component-lookup error:
+        
+        >>> components.getMultiAdapter((tests.U(8), ), tests.IA1)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        ComponentLookupError: ((U(8),),
+        <InterfaceClass zope.component.tests.IA1>, u'')
+        
+        unless you use queryAdapter:
+        
+        >>> components.queryMultiAdapter((tests.U(8), ), tests.IA1)
+        >>> components.queryMultiAdapter((tests.U(8), ), tests.IA1, default=42)
+        42
+        
+        When looking up an adapter for a single object, you can use the
+        slightly simpler getAdapter and queryAdapter calls:
+        
+        >>> components.getAdapter(tests.U1(9), tests.IA2)
+        A1_12(U1(9))
+        
+        >>> components.queryAdapter(tests.U1(9), tests.IA2)
+        A1_12(U1(9))
+        
+        >>> components.getAdapter(tests.U(8), tests.IA1)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        ComponentLookupError: (U(8),
+        <InterfaceClass zope.component.tests.IA1>, u'')
+        
+        >>> components.queryAdapter(tests.U(8), tests.IA2)
+        >>> components.queryAdapter(tests.U(8), tests.IA2, default=42)
+        42
+        
+        You can unregister an adapter.  If a factory is provided and if the
+        rewuired and provided interfaces, can be infered, then they need not
+        be provided:
+        
+        >>> components.unregisterAdapter(tests.A12_1)
+        Unregistered event:
+        AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+        True
+        
+        >>> for registration in sorted(components.registeredAdapters()):
+        ...     print registration.required
+        ...     print registration.provided, registration.name
+        ...     print registration.factory, registration.info
+        ... # doctest: +NORMALIZE_WHITESPACE
+        (<InterfaceClass zope.component.tests.I1>,
+        <InterfaceClass zope.component.tests.I2>)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A12_
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A1_12
+        (<InterfaceClass zope.component.tests.I3>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A_2
+        (<implementedBy zope.component.tests.U>,)
+        <InterfaceClass zope.component.tests.IA3>
+        zope.component.tests.A_3 Really class specific
+        
+        A boolean is returned indicating whether a change was made.
+        
+        If a factory implements more than one interface, an exception will be
+        raised:
+        
+        >>> components.unregisterAdapter(tests.A1_12)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't implement a single
+        interface and no provided interface was specified.
+        
+        Unless the provided interface is specified:
+        
+        >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2)
+        Unregistered event:
+        AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+        True
+        
+        If a factory doesn't declare an implemented interface, an exception will be
+        raised:
+        
+        >>> components.unregisterAdapter(tests.A12_)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't implement a single
+        interface and no provided interface was specified.
+        
+        Unless the provided interface is specified:
+        
+        >>> components.unregisterAdapter(tests.A12_, provided=tests.IA2)
+        Unregistered event:
+        AdapterRegistration(<Components comps>, [I1, I2], IA2, u'', A12_, u'')
+        True
+        
+        The required interface needs to be specified if the factory doesn't
+        have a __component_adapts__ attribute:
+        
+        >>> components.unregisterAdapter(tests.A_2)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't have a __component_adapts__
+        attribute and no required specifications were specified
+        
+        >>> components.unregisterAdapter(tests.A_2, required=[tests.I3])
+        Unregistered event:
+        AdapterRegistration(<Components comps>, [I3], IA2, u'', A_2, u'')
+        True
+        
+        >>> for registration in sorted(components.registeredAdapters()):
+        ...     print registration.required
+        ...     print registration.provided, registration.name
+        ...     print registration.factory, registration.info
+        ... # doctest: +NORMALIZE_WHITESPACE
+        (<implementedBy zope.component.tests.U>,)
+        <InterfaceClass zope.component.tests.IA3>
+        zope.component.tests.A_3 Really class specific
+        
+        If a factory is unregistered that is not registered, False is
+        returned:
+        
+        
+        >>> components.unregisterAdapter(tests.A_2, required=[tests.I3])
+        False
+        >>> components.unregisterAdapter(tests.A12_1, required=[tests.U])
+        False
+        
+        The factory can be omitted, to unregister *any* factory that matches
+        specified required and provided interfaces:
+        
+        >>> components.unregisterAdapter(required=[tests.U], provided=tests.IA3)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Unregistered event:
+        AdapterRegistration(<Components comps>, [zope.component.tests.U],
+        IA3, u'', A_3, 'Really class specific')
+        True
+        
+        >>> for registration in sorted(components.registeredAdapters()):
+        ...     print registration
+        
+        Adapters can be named:
+        
+        >>> components.registerAdapter(tests.A1_12, provided=tests.IA2,
+        ...                            name=u'test')
+        Registered event:
+        AdapterRegistration(<Components comps>, [I1], IA2, u'test', A1_12, u'')
+        
+        >>> components.queryMultiAdapter((tests.U1(9), ), tests.IA2)
+        >>> components.queryMultiAdapter((tests.U1(9), ), tests.IA2, name=u'test')
+        A1_12(U1(9))
+        
+        >>> components.queryAdapter(tests.U1(9), tests.IA2)
+        >>> components.queryAdapter(tests.U1(9), tests.IA2, name=u'test')
+        A1_12(U1(9))
+        >>> components.getAdapter(tests.U1(9), tests.IA2, name=u'test')
+        A1_12(U1(9))
+        
+        It is possible to look up all of the adapters that provide an
+        interface:
+        
+        >>> components.registerAdapter(tests.A1_23, provided=tests.IA2,
+        ...                            name=u'test 2')
+        Registered event:
+        AdapterRegistration(<Components comps>, [I1], IA2, u'test 2', A1_23, u'')
+        
+        >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
+        Registered event:
+        AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+        
+        >>> for name, adapter in sorted(components.getAdapters((tests.U1(9), ),
+        ...                                                    tests.IA2)):
+        ...     print name, adapter
+        A1_12(U1(9))
+        test A1_12(U1(9))
+        test 2 A1_23(U1(9))
+        
+        
+        getAdapters is most commonly used as the basis of menu systems.
+        
+        If an adapter factory returns None, it is equivalent to there being no
+        factory:
+        
+        >>> components.registerAdapter(tests.noop,
+        ...                            required=[tests.IA1], provided=tests.IA2,
+        ...                            name=u'test noop')
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Registered event:
+        AdapterRegistration(<Components comps>, [IA1], IA2, u'test noop',
+        noop, u'')
+        >>> components.queryAdapter(tests.U1(9), tests.IA2, name=u'test noop')
+        
+        >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
+        Registered event:
+        AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+        
+        >>> for name, adapter in sorted(components.getAdapters((tests.U1(9), ),
+        ...                                                    tests.IA2)):
+        ...     print name, adapter
+        A1_12(U1(9))
+        test A1_12(U1(9))
+        test 2 A1_23(U1(9))
+        
+        
+        >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2,
+        ...                              name=u'test')
+        Unregistered event:
+        AdapterRegistration(<Components comps>, [I1], IA2, u'test', A1_12, u'')
+        True
+        >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2)
+        Unregistered event:
+        AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+        True
+        >>> for registration in sorted(components.registeredAdapters()):
+        ...     print registration.required
+        ...     print registration.provided, registration.name
+        ...     print registration.factory, registration.info
+        ... # doctest: +NORMALIZE_WHITESPACE
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2> test 2
+        zope.component.tests.A1_23
+        (<InterfaceClass zope.component.tests.IA1>,)
+        <InterfaceClass zope.component.tests.IA2> test noop
+        <function noop at 0xb79a1064>
+        
+        
+        Subscribers
+        -----------
+        
+        Subscribers provide a way to get multiple adapters of a given type.
+        In this regard, subscribers are like named adapters, except that there
+        isn't any concept of the most specific adapter for a given name.
+        
+        Subscribers are registered by calling registerSubscriptionAdapter:
+        
+        >>> components.registerSubscriptionAdapter(tests.A1_2)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Registered event:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+        
+        >>> components.registerSubscriptionAdapter(
+        ...     tests.A1_12, provided=tests.IA2)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Registered event:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+        
+        >>> components.registerSubscriptionAdapter(
+        ...     tests.A, [tests.I1], tests.IA2,
+        ...     info='a sample comment')
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Registered event:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'',
+        A, 'a sample comment')
+        
+        The same rules, with regard to when required and provided interfaces
+        have to be specified apply as with adapters:
+        
+        >>> components.registerSubscriptionAdapter(tests.A1_12)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't implement a single
+        interface and no provided interface was specified.
+        
+        >>> components.registerSubscriptionAdapter(tests.A)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't implement a single interface and
+        no provided interface was specified.
+        
+        >>> components.registerSubscriptionAdapter(tests.A, required=[tests.IA1])
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't implement a single interface
+        and no provided interface was specified.
+        
+        Note that we provided the info argument as a keyword argument above.
+        That's because there is a name argument that's reserved for future
+        use. We can give a name, as long as it is an empty string:
+        
+        >>> components.registerSubscriptionAdapter(
+        ...     tests.A, [tests.I1], tests.IA2, u'', 'a sample comment')
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Registered event:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'',
+        A, 'a sample comment')
+        
+        >>> components.registerSubscriptionAdapter(
+        ...     tests.A, [tests.I1], tests.IA2, u'oops', 'a sample comment')
+        Traceback (most recent call last):
+        ...
+        TypeError: Named subscribers are not yet supported
+        
+        Subscribers are looked up using the subscribers method:
+        
+        >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
+        ...    print s
+        A1_2(U1(1))
+        A1_12(U1(1))
+        A(U1(1),)
+        A(U1(1),)
+        
+        Note that, because we created multiple subscriptions for A, we got multiple
+        subscriber instances.
+        
+        As with normal adapters, if a factory returns None, the result is skipped:
+        
+        >>> components.registerSubscriptionAdapter(
+        ...     tests.noop, [tests.I1], tests.IA2)
+        Registered event:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'', noop, u'')
+        
+        >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
+        ...    print s
+        A1_2(U1(1))
+        A1_12(U1(1))
+        A(U1(1),)
+        A(U1(1),)
+        
+        We can get registration information for subscriptions:
+        
+        >>> for registration in sorted(
+        ...     components.registeredSubscriptionAdapters()):
+        ...     print registration.required
+        ...     print registration.provided, registration.name
+        ...     print registration.factory, registration.info
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A a sample comment
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A a sample comment
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A1_12
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A1_2
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        <function noop at 0xb796ff7c>
+        
+        We can also unregister subscriptions in much the same way we can for adapters:
+        
+        >>> components.unregisterSubscriptionAdapter(tests.A1_2)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Unregistered event:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, '')
+        True
+        
+        >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
+        ...    print s
+        A1_12(U1(1))
+        A(U1(1),)
+        A(U1(1),)
+        
+        >>> for registration in sorted(
+        ...     components.registeredSubscriptionAdapters()):
+        ...     print registration.required
+        ...     print registration.provided, registration.name
+        ...     print registration.factory, registration.info
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A a sample comment
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A a sample comment
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A1_12
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        <function noop at 0xb796ff7c>
+        
+        >>> components.unregisterSubscriptionAdapter(
+        ...     tests.A, [tests.I1], tests.IA2)
+        Unregistered event:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A, '')
+        True
+        
+        >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
+        ...    print s
+        A1_12(U1(1))
+        
+        >>> for registration in sorted(
+        ...     components.registeredSubscriptionAdapters()):
+        ...     print registration.required
+        ...     print registration.provided, registration.name
+        ...     print registration.factory, registration.info
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        zope.component.tests.A1_12
+        (<InterfaceClass zope.component.tests.I1>,)
+        <InterfaceClass zope.component.tests.IA2>
+        <function noop at 0xb796ff7c>
+        
+        Note here that both registrations for A were removed.
+        
+        If we omit the factory, we must specify the required and provided interfaces:
+        
+        >>> components.unregisterSubscriptionAdapter(required=[tests.I1])
+        Traceback (most recent call last):
+        ...
+        TypeError: Must specify one of factory and provided
+        
+        >>> components.unregisterSubscriptionAdapter(provided=tests.IA2)
+        Traceback (most recent call last):
+        ...
+        TypeError: Must specify one of factory and required
+        
+        >>> components.unregisterSubscriptionAdapter(
+        ...     required=[tests.I1], provided=tests.IA2)
+        Unregistered event:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'', None, '')
+        True
+        
+        >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
+        ...    print s
+        
+        >>> for registration in sorted(
+        ...     components.registeredSubscriptionAdapters()):
+        ...     print registration.factory
+        
+        As when registering, an error is raised if the registration
+        information can't be determined from the factory and isn't specified:
+        
+        >>> components.unregisterSubscriptionAdapter(tests.A1_12)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't implement a single
+        interface and no provided interface was specified.
+        
+        >>> components.unregisterSubscriptionAdapter(tests.A)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't implement a single interface and
+        no provided interface was specified.
+        
+        >>> components.unregisterSubscriptionAdapter(tests.A, required=[tests.IA1])
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't implement a single interface
+        and no provided interface was specified.
+        
+        If you unregister something that's not registered, nothing will be
+        changed and False will be returned:
+        
+        
+        >>> components.unregisterSubscriptionAdapter(
+        ...     required=[tests.I1], provided=tests.IA2)
+        False
+        
+        Handlers
+        --------
+        
+        Handlers are used when you want to perform some function in response
+        to an event.  Handlers aren't expected to return anything when called
+        and are not registered to provide any interface.
+        
+        >>> from zope import component
+        >>> @component.adapter(tests.I1)
+        ... def handle1(x):
+        ...     print 'handle1', x
+        
+        >>> components.registerHandler(handle1, info="First handler")
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Registered event:
+        HandlerRegistration(<Components comps>, [I1], u'',
+        handle1, 'First handler')
+        >>> components.handle(tests.U1(1))
+        handle1 U1(1)
+        
+        >>> @component.adapter(tests.I1, tests.I2)
+        ... def handle12(x, y):
+        ...     print 'handle12', x, y
+        
+        >>> components.registerHandler(handle12)
+        Registered event:
+        HandlerRegistration(<Components comps>, [I1, I2], u'', handle12, u'')
+        >>> components.handle(tests.U1(1), tests.U12(2))
+        handle12 U1(1) U12(2)
+        
+        If a handler doesn't document interfaces it handles, then
+        the required interfaces must be specified:
+        
+        >>> def handle(*objects):
+        ...     print 'handle', objects
+        
+        >>> components.registerHandler(handle)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't have a __component_adapts__
+        attribute and no required specifications were specified
+        
+        >>> components.registerHandler(handle, required=[tests.I1],
+        ...                            info="a comment")
+        Registered event:
+        HandlerRegistration(<Components comps>, [I1], u'', handle, 'a comment')
+        
+        Handlers can also be registered for classes:
+        
+        >>> components.registerHandler(handle, required=[tests.U],
+        ...                            info="handle a class")
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Registered event:
+        HandlerRegistration(<Components comps>, [zope.component.tests.U], u'',
+        handle, 'handle a class')
+        
+        
+        >>> components.handle(tests.U1(1))
+        handle (U1(1),)
+        handle1 U1(1)
+        handle (U1(1),)
+        
+        We can list the handler registrations:
+        
+        >>> for registration in components.registeredHandlers():
+        ...     print registration.required
+        ...     print registration.handler, registration.info
+        ... # doctest: +NORMALIZE_WHITESPACE
+        (<InterfaceClass zope.component.tests.I1>,)
+        <function handle1 at 0xb78f5bfc> First handler
+        (<InterfaceClass zope.component.tests.I1>,
+        <InterfaceClass zope.component.tests.I2>)
+        <function handle12 at 0xb78f5c34>
+        (<InterfaceClass zope.component.tests.I1>,)
+        <function handle at 0xb78f5ca4> a comment
+        (<implementedBy zope.component.tests.U>,)
+        <function handle at 0xb78f5ca4> handle a class
+        
+        and we can unregister handlers:
+        
+        >>> components.unregisterHandler(required=[tests.U])
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Unregistered event:
+        HandlerRegistration(<Components comps>, [zope.component.tests.U], u'',
+        None, '')
+        True
+        
+        >>> for registration in components.registeredHandlers():
+        ...     print registration.required
+        ...     print registration.handler, registration.info
+        ... # doctest: +NORMALIZE_WHITESPACE
+        (<InterfaceClass zope.component.tests.I1>,)
+        <function handle1 at 0xb78f5bfc> First handler
+        (<InterfaceClass zope.component.tests.I1>,
+        <InterfaceClass zope.component.tests.I2>)
+        <function handle12 at 0xb78f5c34>
+        (<InterfaceClass zope.component.tests.I1>,)
+        <function handle at 0xb78f5ca4> a comment
+        
+        >>> components.unregisterHandler(handle12)
+        Unregistered event:
+        HandlerRegistration(<Components comps>, [I1, I2], u'', handle12, '')
+        True
+        
+        >>> for registration in components.registeredHandlers():
+        ...     print registration.required
+        ...     print registration.handler, registration.info
+        (<InterfaceClass zope.component.tests.I1>,)
+        <function handle1 at 0xb78f5bfc> First handler
+        (<InterfaceClass zope.component.tests.I1>,)
+        <function handle at 0xb78f5ca4> a comment
+        
+        >>> components.unregisterHandler(handle12)
+        False
+        
+        >>> components.unregisterHandler()
+        Traceback (most recent call last):
+        ...
+        TypeError: Must specify one of factory and required
+        
+        >>> components.registerHandler(handle)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        TypeError: The adapter factory doesn't have a __component_adapts__
+        attribute and no required specifications were specified
+        
+        Extending
+        ---------
+        
+        Component-management objects can extend other component-management
+        objects.
+        
+        >>> c1 = registry.Components('1')
+        >>> c1.__bases__
+        ()
+        
+        >>> c2 = registry.Components('2', (c1, ))
+        >>> c2.__bases__ == (c1, )
+        True
+        
+        >>> c1.registerUtility(tests.U1(1))
+        Registered event:
+        UtilityRegistration(<Components 1>, I1, u'', 1, None, u'')
+        
+        >>> c1.queryUtility(tests.I1)
+        U1(1)
+        >>> c2.queryUtility(tests.I1)
+        U1(1)
+        >>> c1.registerUtility(tests.U1(2))
+        Registered event:
+        UtilityRegistration(<Components 1>, I1, u'', 2, None, u'')
+        
+        >>> c2.queryUtility(tests.I1)
+        U1(2)
+        
+        We can use multiple inheritence:
+        
+        >>> c3 = registry.Components('3', (c1, ))
+        >>> c4 = registry.Components('4', (c2, c3))
+        >>> c4.queryUtility(tests.I1)
+        U1(2)
+        
+        >>> c1.registerUtility(tests.U12(1), tests.I2)
+        Registered event:
+        UtilityRegistration(<Components 1>, I2, u'', 1, None, u'')
+        
+        >>> c4.queryUtility(tests.I2)
+        U12(1)
+        
+        >>> c3.registerUtility(tests.U12(3), tests.I2)
+        Registered event:
+        UtilityRegistration(<Components 3>, I2, u'', 3, None, u'')
+        >>> c4.queryUtility(tests.I2)
+        U12(3)
+        
+        >>> c1.registerHandler(handle1, info="First handler")
+        Registered event:
+        HandlerRegistration(<Components 1>, [I1], u'', handle1, 'First handler')
+        
+        >>> c2.registerHandler(handle, required=[tests.U])
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Registered event:
+        HandlerRegistration(<Components 2>, [zope.component.tests.U], u'',
+        handle, u'')
+        
+        >>> @component.adapter(tests.I1)
+        ... def handle3(x):
+        ...     print 'handle3', x
+        >>> c3.registerHandler(handle3)
+        Registered event:
+        HandlerRegistration(<Components 3>, [I1], u'', handle3, u'')
+        
+        >>> @component.adapter(tests.I1)
+        ... def handle4(x):
+        ...     print 'handle4', x
+        >>> c4.registerHandler(handle4)
+        Registered event:
+        HandlerRegistration(<Components 4>, [I1], u'', handle4, u'')
+        
+        >>> c4.handle(tests.U1(1))
+        handle1 U1(1)
+        handle3 U1(1)
+        handle (U1(1),)
+        handle4 U1(1)
+        
+        Redispatch of registration events
+        ---------------------------------
+        
+        Some handlers are available that, if registered, redispatch
+        registration events to the objects being registered.  They depend on
+        being dispatched to by the object-event dispatcher:
+        
+        >>> from zope import component
+        >>> import zope.component.event
+        >>> zope.component.getGlobalSiteManager().registerHandler(
+        ...      zope.component.event.objectEventNotify)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Registered event:
+        HandlerRegistration(<BaseGlobalComponents base>,
+        [IObjectEvent], u'', objectEventNotify, u'')
+        
+        To see this, we'll first register a multi-handler to show is when
+        handlers are called on 2 objects:
+        
+        >>> @zope.component.adapter(None, None)
+        ... def double_handler(o1, o2):
+        ...     print 'Double dispatch:'
+        ...     print ' ', o1
+        ...     print ' ', o2
+        >>> zope.component.getGlobalSiteManager().registerHandler(double_handler)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Double dispatch:
+        HandlerRegistration(<BaseGlobalComponents base>,
+        [Interface, Interface], u'', double_handler, u'')
+        Registered event:
+        HandlerRegistration(<BaseGlobalComponents base>,
+        [Interface, Interface], u'', double_handler, u'')
+        Registered event:
+        HandlerRegistration(<BaseGlobalComponents base>,
+        [Interface, Interface], u'', double_handler, u'')
+        
+        In the example above, the double_handler reported it's own registration. :)
+        
+        Now we'll register our handlers:
+        
+        >>> zope.component.getGlobalSiteManager().registerHandler(
+        ...     registry.dispatchUtilityRegistrationEvent)
+        ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+        Double dispatch:
+        ...
+        
+        >>> zope.component.getGlobalSiteManager().registerHandler(
+        ...     registry.dispatchAdapterRegistrationEvent)
+        ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+        Double dispatch:
+        ...
+        
+        >>> zope.component.getGlobalSiteManager().registerHandler(
+        ...     registry.dispatchSubscriptionAdapterRegistrationEvent)
+        ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+        Double dispatch:
+        ...
+        
+        >>> zope.component.getGlobalSiteManager().registerHandler(
+        ...     registry.dispatchHandlerRegistrationEvent)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Double dispatch:
+        HandlerRegistration(<BaseGlobalComponents base>,
+        [IHandlerRegistration, IRegistrationEvent], u'',
+        dispatchHandlerRegistrationEvent, u'')
+        Registered event:
+        HandlerRegistration(<BaseGlobalComponents base>,
+        [IHandlerRegistration, IRegistrationEvent], u'',
+        dispatchHandlerRegistrationEvent, u'')
+        Double dispatch:
+        <function dispatchHandlerRegistrationEvent at 0xb799f72c>
+        Registered event:
+        HandlerRegistration(<BaseGlobalComponents base>,
+        [IHandlerRegistration, IRegistrationEvent], u'',
+        dispatchHandlerRegistrationEvent, u'')
+        Registered event:
+        HandlerRegistration(<BaseGlobalComponents base>,
+        [IHandlerRegistration, IRegistrationEvent], u'',
+        dispatchHandlerRegistrationEvent, u'')
+        
+        In the last example above, we can see that the registration of
+        dispatchHandlerRegistrationEvent was handled by
+        dispatchHandlerRegistrationEvent and redispatched.  This can be seen
+        in the second double-dispatch output, where the first argument is the
+        object being registered, which is dispatchHandlerRegistrationEvent.
+        
+        If we change some other registrations, we can the double dispatch
+        taking place:
+        
+        >>> components.registerUtility(u5)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Double dispatch:
+        UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+        Registered event:
+        UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+        Double dispatch:
+        U1(5)
+        Registered event:
+        UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+        Registered event:
+        UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
+        
+        >>> components.registerAdapter(tests.A12_1)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Double dispatch:
+        AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+        Registered event:
+        AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+        Double dispatch:
+        zope.component.tests.A12_1
+        Registered event:
+        AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+        Registered event:
+        AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+        
+        >>> components.registerSubscriptionAdapter(tests.A1_2)
+        ... # doctest: +NORMALIZE_WHITESPACE
+        Double dispatch:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+        Registered event:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+        Double dispatch:
+        zope.component.tests.A1_2
+        Registered event:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+        Registered event:
+        SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+        
+        Persistent Component Management
+        ===============================
+        
+        Persistent component management allows persistent management of
+        components.  From a usage point of view, there shouldn't be any new
+        behavior beyond what's described in registry.txt.
+        
+        The Zope 3 Component Architecture (Socket Example)
+        ==================================================
+        
+        The component architecture provides an application framework that provides its
+        functionality through loosely-connected components. A *component* can be any
+        Python object and has a particular purpose associated with it. Thus, in a
+        component-based applications you have many small component in contrast to
+        classical object-oriented development, where you have a few big objects.
+        
+        Components communicate via specific APIs, which are formally defined by
+        interfaces, which are provided by the `zope.interface` package. *Interfaces*
+        describe the methods and properties that a component is expected to
+        provide. They are also used as a primary mean to provide developer-level
+        documentation for the components. For more details about interfaces see
+        `zope/interface/README.txt`.
+        
+        The two main types of components are *adapters* and *utilities*. They will be
+        discussed in detail later in this document. Both component types are managed
+        by the *site manager*, with which you can register and access these
+        components. However, most of the site manager's functionality is hidden behind
+        the component architecture's public API, which is documented in
+        `IComponentArchitecture`.
+        
+        
+        Adapters
+        --------
+        
+        Adapters are a well-established pattern. An *adapter* uses an object providing
+        one interface to produce an object that provides another interface. Here an
+        example: Imagine that you purchased an electric shaver in the US, and thus
+        you require the US socket type. You are now traveling in Germany, where another
+        socket style is used. You will need a device, an adapter, that converts from
+        the German to the US socket style.
+        
+        The functionality of adapters is actually natively provided by the
+        `zope.interface` package and is thus well documented there. The `human.txt`
+        file provides a gentle introduction to adapters, whereby `adapter.txt` is
+        aimed at providing a comprehensive insight into adapters, but is too abstract
+        for many as an initial read. Thus, we will only explain adapters in the context
+        of the component architecture's API.
+        
+        So let's say that we have a German socket
+        
+        >>> from zope.interface import Interface, implements
+        
+        >>> class IGermanSocket(Interface):
+        ...     pass
+        
+        >>> class Socket(object):
+        ...     def __repr__(self):
+        ...         return '<instance of %s>' %self.__class__.__name__
+        
+        >>> class GermanSocket(Socket):
+        ...     """German wall socket."""
+        ...     implements(IGermanSocket)
+        
+        and we want to convert it to an US socket
+        
+        >>> class IUSSocket(Interface):
+        ...     pass
+        
+        so that our shaver can be used in Germany. So we go to a German electronics
+        store to look for an adapter that we can plug in the wall:
+        
+        >>> class GermanToUSSocketAdapter(Socket):
+        ...     implements(IUSSocket)
+        ...     __used_for__ = IGermanSocket
+        ...
+        ...     def __init__(self, socket):
+        ...         self.context = socket
+        
+        Note that I could have called the passed in socket any way I like, but
+        `context` is the standard name accepted.
+        
+        
+        Single Adapters
+        ~~~~~~~~~~~~~~~
+        
+        Before we can use the adapter, we have to buy it and make it part of our
+        inventory. In the component architecture we do this by registering the adapter
+        with the framework, more specifically with the global site manager:
+        
+        >>> import zope.component
+        >>> gsm = zope.component.getGlobalSiteManager()
+        >>> gsm.registerAdapter(GermanToUSSocketAdapter, (IGermanSocket,), IUSSocket)
+        
+        `zope.component` is the component architecture API that is being
+        presented by this file. You registered an adapter from `IGermanSocket`
+        to `IUSSocket` having no name (thus the empty string).
+        
+        Anyways, you finally get back to your hotel room and shave, since you have not
+        been able to shave in the plane. In the bathroom you discover a socket:
+        
+        >>> bathroomDE = GermanSocket()
+        >>> IGermanSocket.providedBy(bathroomDE)
+        True
+        
+        You now insert the adapter in the German socket
+        
+        >>> bathroomUS = zope.component.getAdapter(bathroomDE, IUSSocket, '')
+        
+        so that the socket now provides the US version:
+        
+        >>> IUSSocket.providedBy(bathroomUS)
+        True
+        
+        Now you can insert your shaver and get on with your day.
+        
+        After a week you travel for a couple of days to the Prague and you notice that
+        the Czech have yet another socket type:
+        
+        >>> class ICzechSocket(Interface):
+        ...     pass
+        
+        >>> class CzechSocket(Socket):
+        ...     implements(ICzechSocket)
+        
+        >>> czech = CzechSocket()
+        
+        You try to find an adapter for your shaver in your bag, but you fail, since
+        you do not have one:
+        
+        >>> zope.component.getAdapter(czech, IUSSocket, '') \
+        ... #doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        ComponentLookupError: (<instance of CzechSocket>,
+        <InterfaceClass __builtin__.IUSSocket>,
+        '')
+        
+        or the more graceful way:
+        
+        >>> marker = object()
+        >>> socket = zope.component.queryAdapter(czech, IUSSocket, '', marker)
+        >>> socket is marker
+        True
+        
+        In the component architecture API any `get*` method will fail with a specific
+        exception, if a query failed, whereby methods starting with `query*` will
+        always return a `default` value after a failure.
+        
+        
+        Named Adapters
+        ~~~~~~~~~~~~~~
+        
+        You are finally back in Germany. You also brought your DVD player and a couple
+        DVDs with you, which you would like to watch. Your shaver was able to convert
+        automatically from 110 volts to 240 volts, but your DVD player cannot. So you
+        have to buy another adapter that also handles converting the voltage and the
+        frequency of the AC current:
+        
+        >>> class GermanToUSSocketAdapterAndTransformer(object):
+        ...     implements(IUSSocket)
+        ...     __used_for__ = IGermanSocket
+        ...
+        ...     def __init__(self, socket):
+        ...         self.context = socket
+        
+        Now, we need a way to keep the two adapters apart. Thus we register them with
+        a name:
+        
+        >>> gsm.registerAdapter(GermanToUSSocketAdapter,
+        ...                     (IGermanSocket,), IUSSocket, 'shaver',)
+        >>> gsm.registerAdapter(GermanToUSSocketAdapterAndTransformer,
+        ...                     (IGermanSocket,), IUSSocket, 'dvd')
+        
+        Now we simply look up the adapters using their labels (called *name*):
+        
+        >>> socket = zope.component.getAdapter(bathroomDE, IUSSocket, 'shaver')
+        >>> socket.__class__ is GermanToUSSocketAdapter
+        True
+        
+        >>> socket = zope.component.getAdapter(bathroomDE, IUSSocket, 'dvd')
+        >>> socket.__class__ is GermanToUSSocketAdapterAndTransformer
+        True
+        
+        Clearly, we do not have an adapter for the MP3 player
+        
+        >>> zope.component.getAdapter(bathroomDE, IUSSocket, 'mp3') \
+        ... #doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        ComponentLookupError: (<instance of GermanSocket>,
+        <InterfaceClass __builtin__.IUSSocket>,
+        'mp3')
+        
+        but you could use the 'dvd' adapter in this case of course. ;)
+        
+        Sometimes you want to know all adapters that are available. Let's say you want
+        to know about all the adapters that convert a German to a US socket type:
+        
+        >>> sockets = list(zope.component.getAdapters((bathroomDE,), IUSSocket))
+        >>> len(sockets)
+        3
+        >>> names = [name for name, socket in sockets]
+        >>> names.sort()
+        >>> names
+        [u'', u'dvd', u'shaver']
+        
+        `zope.component.getAdapters()` returns a list of tuples. The first
+        entry of the tuple is the name of the adapter and the second is the
+        adapter itself.
+        
+        
+        Multi-Adapters
+        ~~~~~~~~~~~~~~
+        
+        After watching all the DVDs you brought at least twice, you get tired of them
+        and you want to listen to some music using your MP3 player. But darn, the MP3
+        player plug has a ground pin and all the adapters you have do not support
+        that:
+        
+        >>> class IUSGroundedSocket(IUSSocket):
+        ...     pass
+        
+        So you go out another time to buy an adapter. This time, however, you do not
+        buy yet another adapter, but a piece that provides the grounding plug:
+        
+        >>> class IGrounder(Interface):
+        ...     pass
+        
+        >>> class Grounder(object):
+        ...     implements(IGrounder)
+        ...     def __repr__(self):
+        ...         return '<instance of Grounder>'
+        
+        
+        Then together they will provided a grounded us socket:
+        
+        >>> class GroundedGermanToUSSocketAdapter(object):
+        ...     implements(IUSGroundedSocket)
+        ...     __used_for__ = (IGermanSocket, IGrounder)
+        ...     def __init__(self, socket, grounder):
+        ...         self.socket, self.grounder = socket, grounder
+        
+        You now register the combination, so that you know you can create a
+        `IUSGroundedSocket`:
+        
+        >>> gsm.registerAdapter(GroundedGermanToUSSocketAdapter,
+        ...                 (IGermanSocket, IGrounder), IUSGroundedSocket, 'mp3')
+        
+        Given the grounder
+        
+        >>> grounder = Grounder()
+        
+        and a German socket
+        
+        >>> livingroom = GermanSocket()
+        
+        we can now get a grounded US socket:
+        
+        >>> socket = zope.component.getMultiAdapter((livingroom, grounder),
+        ...                                         IUSGroundedSocket, 'mp3')
+        
+        >>> socket.__class__ is GroundedGermanToUSSocketAdapter
+        True
+        >>> socket.socket is livingroom
+        True
+        >>> socket.grounder is grounder
+        True
+        
+        Of course, you do not have a 'dvd' grounded US socket available:
+        
+        >>> zope.component.getMultiAdapter((livingroom, grounder),
+        ...                                IUSGroundedSocket, 'dvd') \
+        ... #doctest: +NORMALIZE_WHITESPACE
+        Traceback (most recent call last):
+        ...
+        ComponentLookupError: ((<instance of GermanSocket>,
+        <instance of Grounder>),
+        <InterfaceClass __builtin__.IUSGroundedSocket>,
+        'dvd')
+        
+        
+        >>> socket = zope.component.queryMultiAdapter(
+        ...     (livingroom, grounder), IUSGroundedSocket, 'dvd', marker)
+        >>> socket is marker
+        True
+        
+        Again, you might want to read `adapter.txt` in `zope.interface` for a more
+        comprehensive coverage of multi-adapters.
+        
+        Subscribers
+        -----------
+        
+        While subscribers are directly supported by the adapter registry and are
+        adapters for all theoretical purposes, practically it might be better to think
+        of them as separate components. Subscribers are particularly useful for
+        events.
+        
+        Let's say one of our adapters overheated and caused a small fire:
+        
+        >>> class IFire(Interface):
+        ...     pass
+        
+        >>> class Fire(object):
+        ...     implements(IFire)
+        
+        >>> fire = Fire()
+        
+        We want to use all available objects to put out the fire:
+        
+        >>> class IFireExtinguisher(Interface):
+        ...     def extinguish():
+        ...         pass
+        
+        >>> class FireExtinguisher(object):
+        ...     def __init__(self, fire):
+        ...         pass
+        ...     def extinguish(self):
+        ...         "Place extinguish code here."
+        ...         print 'Used ' + self.__class__.__name__ + '.'
+        
+        Here some specific methods to put out the fire:
+        
+        >>> class PowderExtinguisher(FireExtinguisher):
+        ...     pass
+        >>> gsm.registerSubscriptionAdapter(PowderExtinguisher,
+        ...                                 (IFire,), IFireExtinguisher)
+        
+        >>> class Blanket(FireExtinguisher):
+        ...     pass
+        >>> gsm.registerSubscriptionAdapter(Blanket, (IFire,), IFireExtinguisher)
+        
+        >>> class SprinklerSystem(FireExtinguisher):
+        ...     pass
+        >>> gsm.registerSubscriptionAdapter(SprinklerSystem,
+        ...                                 (IFire,), IFireExtinguisher)
+        
+        Now let use all these things to put out the fire:
+        
+        >>> extinguishers = zope.component.subscribers((fire,), IFireExtinguisher)
+        >>> extinguishers.sort()
+        >>> for extinguisher in extinguishers:
+        ...     extinguisher.extinguish()
+        Used Blanket.
+        Used PowderExtinguisher.
+        Used SprinklerSystem.
+        
+        If no subscribers are found for a particular object, then an empty list is
+        returned:
+        
+        >>> zope.component.subscribers((object(),), IFireExtinguisher)
+        []
+        
+        
+        Utilities
+        ---------
+        
+        Utilities are the second type of component, the component architecture
+        implements. *Utilities* are simply components that provide an interface. When
+        you register an utility, you always register an instance (in contrast to a
+        factory for adapters) since the initialization and setup process of a utility
+        might be complex and is not well defined. In some ways a utility is much more
+        fundamental than an adapter, because an adapter cannot be used without another
+        component, but a utility is always self-contained. I like to think of
+        utilities as the foundation of your application and adapters as components
+        extending beyond this foundation.
+        
+        Back to our story...
+        
+        After your vacation is over you fly back home to Tampa, Florida. But it is
+        August now, the middle of the Hurricane season. And, believe it or not, you are
+        worried that you will not be able to shave when the power goes out for several
+        days. (You just hate wet shavers.)
+        
+        So you decide to go to your favorite hardware store and by a Diesel-powered
+        electric generator. The generator provides of course a US-style socket:
+        
+        >>> class Generator(object):
+        ...     implements(IUSSocket)
+        ...     def __repr__(self):
+        ...         return '<instance of Generator>'
+        
+        >>> generator = Generator()
+        
+        Like for adapters, we now have to add the newly-acquired generator to our
+        inventory by registering it as a utility:
+        
+        >>> gsm.registerUtility(generator, IUSSocket)
+        
+        We can now get the utility using
+        
+        >>> utility = zope.component.getUtility(IUSSocket)
+        >>> utility is generator
+        True
+        
+        As you can see, it is very simple to register and retrieve utilities. If a
+        utility does not exist for a particular interface, such as the German socket,
+        then the lookup fails
+        
+        >>> zope.component.getUtility(IGermanSocket)
+        Traceback (most recent call last):
+        ...
+        ComponentLookupError: (<InterfaceClass __builtin__.IGermanSocket>, '')
+        
+        or more gracefully when specifying a default value:
+        
+        >>> default = object()
+        >>> utility = zope.component.queryUtility(IGermanSocket, default=default)
+        >>> utility is default
+        True
+        
+        Note: The only difference between `getUtility()` and `queryUtility()` is the
+        fact that you can specify a default value for the latter function, so that it
+        will never cause a `ComponentLookupError`.
+        
+        
+        Named Utilities
+        ~~~~~~~~~~~~~~~
+        
+        It is often desirable to have several utilities providing the same interface
+        per site. This way you can implement any sort of registry using utilities. For
+        this reason, utilities -- like adapters -- can be named.
+        
+        In the context of our story, we might want to do the following: You really do
+        not trust gas stations either. What if the roads are blocked after a hurricane
+        and the gas stations run out of oil. So you look for another renewable power
+        source. Then you think about solar panels! After a storm there is usually very
+        nice weather, so why not? Via the Web you order a set of 110V/120W solar
+        panels that provide a regular US-style socket as output:
+        
+        >>> class SolarPanel(object):
+        ...     implements(IUSSocket)
+        ...     def __repr__(self):
+        ...         return '<instance of Solar Panel>'
+        
+        >>> panel = SolarPanel()
+        
+        Once it arrives, we add it to our inventory:
+        
+        >>> gsm.registerUtility(panel, IUSSocket, 'Solar Panel')
+        
+        You can now access the solar panel using
+        
+        >>> utility = zope.component.getUtility(IUSSocket, 'Solar Panel')
+        >>> utility is panel
+        True
+        
+        Of course, if a utility is not available, then the lookup will simply fail
+        
+        >>> zope.component.getUtility(IUSSocket, 'Wind Mill')
+        Traceback (most recent call last):
+        ...
+        ComponentLookupError: (<InterfaceClass __builtin__.IUSSocket>, 'Wind Mill')
+        
+        or more gracefully when specifying a default value:
+        
+        >>> default = object()
+        >>> utility = zope.component.queryUtility(IUSSocket, 'Wind Mill',
+        ...                                       default=default)
+        >>> utility is default
+        True
+        
+        Now you want to look at all the utilities you have for a particular kind. The
+        following API function will return a list of name/utility pairs:
+        
+        >>> utils = list(zope.component.getUtilitiesFor(IUSSocket))
+        >>> utils.sort()
+        >>> utils #doctest: +NORMALIZE_WHITESPACE
+        [(u'', <instance of Generator>),
+        (u'Solar Panel', <instance of Solar Panel>)]
+        
+        Another method of looking up all utilities is by using
+        `getAllUtilitiesRegisteredFor(iface)`. This function will return an iterable
+        of utilities (without names); however, it will also return overridden
+        utilities. If you are not using multiple site managers, you will not actually
+        need this method.
+        
+        >>> utils = list(zope.component.getAllUtilitiesRegisteredFor(IUSSocket))
+        >>> utils.sort()
+        >>> utils
+        [<instance of Generator>, <instance of Solar Panel>]
+        
+        
+        Factories
+        ~~~~~~~~~
+        
+        A *factory* is a special kind of utility that exists to create other
+        components. A factory is always identified by a name. It also provides a title
+        and description and is able to tell the developer what interfaces the created
+        object will provide. The advantage of using a factory to create an object
+        instead of directly instantiating a class or executing any other callable is
+        that we can refer to the factory by name. As long as the name stays fixed, the
+        implementation of the callable can be renamed or moved without a breakage in
+        code.
+        
+        Let's say that our solar panel comes in parts and they have to be
+        assembled. This assembly would be done by a factory, so let's create one for
+        the solar panel. To do this, we can use a standard implementation of the
+        `IFactory` interface:
+        
+        >>> from zope.component.factory import Factory
+        >>> factory = Factory(SolarPanel,
+        ...                   'Solar Panel',
+        ...                   'This factory creates a solar panel.')
+        
+        Optionally, I could have also specified the interfaces that the created object
+        will provide, but the factory class is smart enough to determine the
+        implemented interface from the class. We now register the factory:
+        
+        >>> from zope.component.interfaces import IFactory
+        >>> gsm.registerUtility(factory, IFactory, 'SolarPanel')
+        
+        We can now get a list of interfaces the produced object will provide:
+        
+        >>> ifaces = zope.component.getFactoryInterfaces('SolarPanel')
+        >>> IUSSocket in ifaces
+        True
+        
+        By the way, this is equivalent to
+        
+        >>> ifaces2 = factory.getInterfaces()
+        >>> ifaces is ifaces2
+        True
+        
+        Of course you can also just create an object:
+        
+        >>> panel = zope.component.createObject('SolarPanel')
+        >>> panel.__class__ is SolarPanel
+        True
+        
+        Note: Ignore the first argument (`None`) for now; it is the context of the
+        utility lookup, which is usually an optional argument, but cannot be in this
+        case, since all other arguments beside the `name` are passed in as arguments
+        to the specified callable.
+        
+        Once you register several factories
+        
+        >>> gsm.registerUtility(Factory(Generator), IFactory, 'Generator')
+        
+        you can also determine, which available factories will create objects
+        providing a certain interface:
+        
+        >>> factories = zope.component.getFactoriesFor(IUSSocket)
+        >>> factories = [(name, factory.__class__) for name, factory in factories]
+        >>> factories.sort()
+        >>> factories #doctest: +NORMALIZE_WHITESPACE
+        [(u'Generator', <class 'zope.component.factory.Factory'>),
+        (u'SolarPanel', <class 'zope.component.factory.Factory'>)]
+        
+        
+        Site Managers
+        -------------
+        
+        Why do we need site managers? Why is the component architecture API not
+        sufficient? Some applications, including Zope 3, have a concept of
+        locations. It is often desirable to have different configurations for these
+        location; this can be done by overwriting existing or adding new component
+        registrations. Site managers in locations below the root location, should be
+        able to delegate requests to their parent locations. The root site manager is
+        commonly known as *global site manager*, since it is always available. You can
+        always get the global site manager using the API:
+        
+        >>> gsm = zope.component.getGlobalSiteManager()
+        
+        >>> from zope.component import globalSiteManager
+        >>> gsm is globalSiteManager
+        True
+        >>> from zope.component.interfaces import IComponentLookup
+        >>> IComponentLookup.providedBy(gsm)
+        True
+        >>> from zope.component.interfaces import IComponents
+        >>> IComponents.providedBy(gsm)
+        True
+        
+        You can also lookup at site manager in a given context. The only requirement
+        is that the context can be adapted to a site manager. So let's create a
+        special site manager:
+        
+        >>> from zope.component.globalregistry import BaseGlobalComponents
+        >>> sm = BaseGlobalComponents()
+        
+        Now we create a context that adapts to the site manager via the `__conform__`
+        method as specified in PEP 246.
+        
+        >>> class Context(object):
+        ...     def __init__(self, sm):
+        ...         self.sm = sm
+        ...     def __conform__(self, interface):
+        ...         if interface.isOrExtends(IComponentLookup):
+        ...             return self.sm
+        
+        We now instantiate the `Context` with our special site manager:
+        
+        >>> context = Context(sm)
+        >>> context.sm is sm
+        True
+        
+        We can now ask for the site manager of this context:
+        
+        >>> lsm = zope.component.getSiteManager(context)
+        >>> lsm is sm
+        True
+        
+        The site manager instance `lsm` is formally known as a *local site manager* of
+        `context`.
+        
+        CHANGES
+        *******
+        
+        3.7.1 (unreleased)
+        ==================
+        
+        - Nothing changed yet.
+        
+        
+        3.7.0 (2009-05-21)
+        ==================
+        
+        - The HookableTests were not run by the testrunner.
+        
+        - Add in zope:view and zope:resource implementations into
+        zope.component.zcml (dependency loaded with zope.component [zcml]).
+        
+        3.6.0 (2009-03-12)
+        ==================
+        
+        - IMPORTANT: the interfaces that were defined in the
+        zope.component.bbb.interfaces and deprecated for years are
+        now (re)moved. However, some packages, including part of zope
+        framework were still using those interfaces. They will be adapted
+        for this change. If you were using some of those interfaces, you
+        need to adapt your code as well:
+        
+        - The IView and IDefaultViewName were moved to zope.publisher.interfaces.
+        
+        - The IResource was moved to zope.app.publisher.interfaces.
+        
+        - IContextDependent, IPresentation, IPresentationRequest,
+        IResourceFactory, IViewFactory were removed completely.
+        
+        If you used IViewFactory in context of zope.app.form, there's now
+        IWidgetFactory in the zope.app.form.interfaces instead.
+        
+        - Add getNextUtility/queryNextUtility functions that used to be in zope.site
+        earlier (and in zope.app.component even more earlier).
+        
+        - Added a pure-Python 'hookable' implementation, for use when
+        'zope.hookable' is not present.
+        
+        - Removed use of 'zope.deferredimport' by breaking import cycles.
+        
+        - Cleanup package documentation and changelog a bit. Add sphinx-based
+        documentation building command to the buildout.
+        
+        - Remove deprecated code.
+        
+        - Change package's mailing list address to zope-dev at zope.org, because
+        zope3-dev at zope.org is now retired.
+        
+        3.5.1 (2008-07-25)
+        ==================
+        
+        - Fix bug introduced in 3.5.0: <utility factory="..."> no longer supported
+        interfaces declared in Python and always wanted an explicit provides="..."
+        attribute. https://bugs.launchpad.net/zope3/+bug/251865
+        
+        3.5.0 (2008-07-25)
+        ==================
+        
+        - Support registration of utilities via factories through the component registry
+        and return factory information in the registration information. This fixes
+        https://bugs.launchpad.net/zope3/+bug/240631
+        
+        - Optimized un/registerUtility via storing an optimized data structure for
+        efficient retrieval of already registered utilities. This avoids looping over
+        all utilities when registering a new one.
+        
+        3.4.0 (2007-09-29)
+        ==================
+        
+        No further changes since 3.4.0a1.
+        
+        3.4.0a1 (2007-04-22)
+        ====================
+        
+        Corresponds to zope.component from Zope 3.4.0a1.
+        
+        - In the Zope 3.3.x series, ``zope.component`` was simplified yet once
+        more.  See http://wiki.zope.org/zope3/LocalComponentManagementSimplification
+        for the proposal describing the changes.
+        
+        3.2.0.2 (2006-04-15)
+        ====================
+        
+        - Fix packaging bug:  'package_dir' must be a *relative* path.
+        
+        3.2.0.1 (2006-04-14)
+        ====================
+        
+        - Packaging change: suppress inclusion of 'setup.cfg' in 'sdist' builds.
+        
+        3.2.0 (2006-01-05)
+        ==================
+        
+        Corresponds to the verison of the zope.component package shipped as part of
+        the Zope 3.2.0 release.
+        
+        - Deprecated services and related APIs. The adapter and utility registries
+        are now available directly via the site manager's 'adapters' and 'utilities'
+        attributes, respectively.  Services are accessible, but deprecated, and
+        will be removed in Zope 3.3.
+        
+        - Deprectaed all presentation-related APIs, including all view-related
+        API functions. Use the adapter API functions instead.
+        See http://dev.zope.org/Zope3/ImplementViewsAsAdapters`
+        
+        - Deprecated 'contextdependent' package:  site managers are now looked up
+        via a thread global, set during URL traversal.  The 'context' argument
+        is now always optional, and should no longer be passed.
+        
+        3.0.0 (2004-11-07)
+        ==================
+        
+        Corresponds to the verison of the zope.component package shipped as part of
+        the Zope X3.0.0 release.
+        
+        Download
+        ********
+        
+Platform: UNKNOWN

Added: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/SOURCES.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/SOURCES.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/SOURCES.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,44 @@
+CHANGES.txt
+README.txt
+bootstrap.py
+buildout.cfg
+setup.py
+src/zope/__init__.py
+src/zope.component.egg-info/PKG-INFO
+src/zope.component.egg-info/SOURCES.txt
+src/zope.component.egg-info/dependency_links.txt
+src/zope.component.egg-info/namespace_packages.txt
+src/zope.component.egg-info/not-zip-safe
+src/zope.component.egg-info/requires.txt
+src/zope.component.egg-info/top_level.txt
+src/zope/component/README.txt
+src/zope/component/__init__.py
+src/zope/component/_api.py
+src/zope/component/_declaration.py
+src/zope/component/configure.zcml
+src/zope/component/event.py
+src/zope/component/event.txt
+src/zope/component/eventtesting.py
+src/zope/component/factory.py
+src/zope/component/factory.txt
+src/zope/component/globalregistry.py
+src/zope/component/hookable.py
+src/zope/component/index.txt
+src/zope/component/interface.py
+src/zope/component/interfaces.py
+src/zope/component/meta.zcml
+src/zope/component/nexttesting.py
+src/zope/component/persistentregistry.py
+src/zope/component/persistentregistry.txt
+src/zope/component/registry.py
+src/zope/component/registry.txt
+src/zope/component/socketexample.txt
+src/zope/component/standalonetests.py
+src/zope/component/testing.py
+src/zope/component/tests.py
+src/zope/component/zcml.py
+src/zope/component/zcml.txt
+src/zope/component/testfiles/__init__.py
+src/zope/component/testfiles/adapter.py
+src/zope/component/testfiles/components.py
+src/zope/component/testfiles/views.py
\ No newline at end of file


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/SOURCES.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/dependency_links.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/dependency_links.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/dependency_links.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/dependency_links.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/namespace_packages.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/namespace_packages.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/namespace_packages.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+zope


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/namespace_packages.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/not-zip-safe
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/not-zip-safe	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/not-zip-safe	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+

Added: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/requires.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/requires.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/requires.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,24 @@
+setuptools
+zope.interface
+zope.event
+
+[test]
+ZODB3
+zope.testing
+zope.hookable
+zope.location
+
+[docs]
+z3c.recipe.sphinxdoc
+
+[zcml]
+zope.configuration
+zope.security
+zope.proxy
+zope.i18nmessageid
+
+[persistentregistry]
+ZODB3
+
+[hook]
+zope.hookable
\ No newline at end of file


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/requires.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/top_level.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/top_level.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/top_level.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+zope


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.component.egg-info/top_level.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/PKG-INFO
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/PKG-INFO	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/PKG-INFO	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,796 @@
+Metadata-Version: 1.0
+Name: zope.security
+Version: 3.6.4dev
+Summary: Zope3 Security Framework
+Home-page: http://pypi.python.org/pypi/zope.security
+Author: Zope Corporation and Contributors
+Author-email: zope-dev at zope.org
+License: ZPL 2.1
+Description: The Security framework provides a generic mechanism to implement security
+        policies on Python objects.
+        
+        .. contents::
+        
+        ==============
+        Zope3 Security
+        ==============
+        
+        Introduction
+        ------------
+        
+        The Security framework provides a generic mechanism to implement security
+        policies on Python objects.  This introduction provides a tutorial of the
+        framework explaining concepts, design, and going through sample usage from the
+        perspective of a Python programmer using the framework outside of Zope.
+        
+        Definitions
+        -----------
+        
+        Principal
+        ~~~~~~~~~
+        
+        A generalization of a concept of a user.
+        
+        Permission
+        ~~~~~~~~~~
+        
+        A kind of access, i.e. permission to READ vs. permission to WRITE.
+        Fundamentally the whole security framework is organized around checking
+        permissions on objects.
+        
+        Purpose
+        -------
+        
+        The security framework's primary purpose is to guard and check access to
+        Python objects.  It does this by providing mechanisms for explicit and
+        implicit security checks on attribute access for objects.  Attribute names are
+        mapped onto permission names when checking access and the implementation of
+        the security check is defined by the security policy, which receives the
+        object, the permission name, and an interaction.
+        
+        Interactions are objects that represent the use of the system by one or more
+        principals.  An interaction contains a list of participations, which
+        represents the way a single principal participates in the interaction.  An
+        HTTP request is one example of a participation.
+        
+        Its important to keep in mind that the policy provided is just a default, and
+        it can be substituted with one which doesn't care about principals or
+        interactions at all.
+        
+        Framework Components
+        --------------------
+        
+        Low Level Components
+        ~~~~~~~~~~~~~~~~~~~~
+        
+        These components provide the infrastructure for guarding attribute access and
+        providing hooks into the higher level security framework.
+        
+        Checkers
+        ~~~~~~~~
+        
+        A checker is associated with an object kind, and provides the hooks that map
+        attribute checks onto permissions deferring to the security manager (which in
+        turn defers to the policy) to perform the check.
+        
+        Additionally, checkers provide for creating proxies of objects associated with
+        the checker.
+        
+        There are several implementation variants of checkers, such as checkers that
+        grant access based on attribute names.
+        
+        Proxies
+        ~~~~~~~
+        
+        Wrappers around Python objects that implicitly guard access to their wrapped
+        contents by delegating to their associated checker.  Proxies are also viral in
+        nature, in that values returned by proxies are also proxied.
+        
+        High Level Components
+        ---------------------
+        
+        Security Management
+        ~~~~~~~~~~~~~~~~~~~
+        
+        Provides accessors for setting up interactions and the global security policy.
+        
+        Interaction
+        ~~~~~~~~~~~
+        
+        Stores transient information on the list of participations.
+        
+        Participation
+        ~~~~~~~~~~~~~
+        
+        Stores information about a principal participating in the interaction.
+        
+        Security Policy
+        ~~~~~~~~~~~~~~~
+        
+        Provides a single method that accepts the object, the permission, and the
+        interaction of the access being checked and is used to implement the
+        application logic for the security framework.
+        
+        Narrative (agent sandbox)
+        -------------------------
+        
+        As an example we take a look at constructing a multi-agent distributed system,
+        and then adding a security layer using the Zope security model onto it.
+        
+        Scenario
+        ~~~~~~~~
+        
+        Our agent simulation consists of autonomous agents that live in various agent
+        homes/sandboxes and perform actions that access services available at their
+        current home.  Agents carry around authentication tokens which signify their
+        level of access within any given home.  Additionally agents attempt to migrate
+        from home to home randomly.
+        
+        The agent simulation was constructed separately from any security aspects.
+        Now we want to define and integrate a security model into the simulation.  The
+        full code for the simulation and the security model is available separately;
+        we present only relevant code snippets here for illustration as we go through
+        the implementation process.
+        
+        For the agent simulation we want to add a security model such that we group
+        agents into two authentication groups, "norse legends", including the
+        principals thor, odin, and loki, and "greek men", including prometheus,
+        archimedes, and thucydides.
+        
+        We associate permissions with access to services and homes.  We differentiate
+        the homes such that certain authentication groups only have access to services
+        or the home itself based on the local settings of the home in which they
+        reside.
+        
+        We define the homes/sandboxes
+        
+        - origin - all agents start here, and have access to all
+        services here.
+        
+        - valhalla - only agents in the authentication group 'norse
+        legend' can reside here.
+        
+        - jail - all agents can come here, but only 'norse legend's
+        can leave or access services.
+        
+        
+        Process
+        ~~~~~~~
+        
+        Loosely we define a process for implementing this security model
+        
+        - mapping permissions onto actions
+        
+        - mapping authentication tokens onto permissions
+        
+        - implementing checkers and security policies that use our
+        authentication tokens and permissions.
+        
+        - binding checkers to our simulation classes
+        
+        - inserting the hooks into the original simulation code to add
+        proxy wrappers to automatically check security.
+        
+        - inserting hooks into the original simulation to register the
+        agents as the active principal in an interaction.
+        
+        
+        Defining a Permission Model
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        We define the following permissions::
+        
+        NotAllowed = 'Not Allowed'
+        Public = Checker.CheckerPublic
+        TransportAgent = 'Transport Agent'
+        AccessServices = 'Access Services'
+        AccessAgents = 'Access Agents'
+        AccessTimeService = 'Access Time Services'
+        AccessAgentService = 'Access Agent Service'
+        AccessHomeService = 'Access Home Service'
+        
+        and create a dictionary database mapping homes to authentication groups which
+        are linked to associated permissions.
+        
+        
+        Defining and Binding Checkers
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        Checkers are the foundational unit for the security framework.  They define
+        what attributes can be accessed or set on a given instance.  They can be used
+        implicitly via Proxy objects, to guard all attribute access automatically or
+        explicitly to check a given access for an operation.
+        
+        Checker construction expects two functions or dictionaries, one is used to map
+        attribute names to permissions for attribute access and another to do the same
+        for setting attributes.
+        
+        We use the following checker factory function::
+        
+        def PermissionMapChecker(permissions_map={},
+        setattr_permission_func=NoSetAttr):
+        res = {}
+        for k,v in permissions_map.items():
+        for iv in v:
+        res[iv]=k
+        return checker.Checker(res.get, setattr_permission_func)
+        
+        time_service_checker = PermissionMapChecker(
+        # permission : [methods]
+        {'AccessTimeService':['getTime']}
+        )
+        
+        with the NoSetAttr function defined as a lambda which always return the
+        permission `NotAllowed`.
+        
+        To bind the checkers to the simulation classes we register our checkers with
+        the security model's global checker registry::
+        
+        import sandbox_simulation
+        from zope.security.checker import defineChecker
+        defineChecker(sandbox_simulation.TimeService, time_service_checker)
+        
+        
+        Defining a Security Policy
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        We implement our security policy such that it checks the current agent's
+        authentication token against the given permission in the home of the object
+        being accessed::
+        
+        class SimulationSecurityPolicy:
+        
+        implements(ISecurityPolicy)
+        
+        createInteraction = staticmethod(simpleinteraction.createInteraction)
+        
+        def checkPermission(self, permission, object, interaction):
+        
+        home = object.getHome()
+        db = getattr(SimulationSecurityDatabase, home.getId(), None)
+        
+        if db is None:
+        return False
+        
+        allowed = db.get('any', ())
+        if permission in allowed or ALL in allowed:
+        return True
+        
+        if interaction is None:
+        return False
+        if not interaction.participations:
+        return False
+        for participation in interaction.participations:
+        token = participation.principal.getAuthenticationToken()
+        allowed = db.get(token, ())
+        if permission not in allowed:
+        return False
+        
+        return True
+        
+        There are no specific requirements for the interaction class, so we can just
+        use `zope.security.simpleinteraction.Interaction`.
+        
+        Since an interaction can have more than one principal, we check that *all* of
+        them are given the necessary permission.  This is not really necessary since
+        we only create interactions with a single active principal.
+        
+        There is some additional code present to allow for shortcuts in defining the
+        permission database when defining permissions for all auth groups and all
+        permissions.
+        
+        
+        Integration
+        ~~~~~~~~~~~
+        
+        At this point we have implemented our security model, and we need to integrate
+        it with our simulation model.  We do so in three separate steps.
+        
+        First we make it such that agents only access homes that are wrapped in a
+        security proxy.  By doing this all access to homes and services (proxies have
+        proxied return values for their methods) is implicitly guarded by our security
+        policy.
+        
+        The second step is that we want to associate the active agent with the
+        security context so the security policy will know which agent's authentication
+        token to validate against.
+        
+        The third step is to set our security policy as the default policy for the
+        Zope security framework.  It is possible to create custom security policies at
+        a finer grained than global, but such is left as an exercise for the reader.
+        
+        
+        Interaction Access
+        ~~~~~~~~~~~~~~~~~~
+        
+        The *default* implementation of the interaction management interfaces defines
+        interactions on a per thread basis with a function for an accessor.  This
+        model is not appropriate for all systems, as it restricts one to a single
+        active interaction per thread at any given moment.  Reimplementing the
+        interaction access methods though is easily doable and is noted here for
+        completeness.
+        
+        
+        Perspectives
+        ~~~~~~~~~~~~
+        
+        It's important to keep in mind that there is a lot more that is possible using
+        the security framework than what's been presented here.  All of the
+        interactions are interface based, such that if you need to re-implement the
+        semantics to suite your application a new implementation of the interface will
+        be sufficient.  Additional possibilities range from restricted interpreters
+        and dynamic loading of untrusted code to non Zope web application security
+        systems.  Insert imagination here ;-).
+        
+        
+        Zope Perspective
+        ~~~~~~~~~~~~~~~~
+        
+        A Zope3 programmer will never commonly need to interact with the low level
+        security framework.  Zope3 defines a second security package over top the low
+        level framework and authentication sources and checkers are handled via zcml
+        registration.  Still those developing Zope3 will hopefully find this useful as
+        an introduction into the underpinnings of the security framework.
+        
+        
+        Code
+        ~~~~
+        
+        The complete code for this example is available.
+        
+        - sandbox.py - the agent framework
+        
+        - sandbox_security.py - the security implementation and binding to the agent
+        framework.
+        
+        
+        Authors
+        ~~~~~~~
+        
+        - Kapil Thangavelu <hazmat at objectrealms.net>
+        - Guido Wesdorp <guido at infrae.com>
+        - Marius Gedminas <marius at pov.lt>
+        
+        
+        
+        ======================
+        Untrusted interpreters
+        ======================
+        
+        Untrusted programs are executed by untrusted interpreters.  Untrusted
+        interpreters make use of security proxies to prevent un-mediated
+        access to assets.  An untrusted interpreter defines an environment for
+        running untrusted programs. All objects within the environment are
+        either:
+        
+        - "safe" objects created internally by the environment or created in
+        the course of executing the untrusted program, or
+        
+        - "basic" objects
+        
+        - security-proxied non-basic objects
+        
+        The environment includes proxied functions for accessing objects
+        outside of the environment.  These proxied functions provide the only
+        way to access information outside the environment.  Because these
+        functions are proxied, as described below, any access to objects
+        outside the environment is mediated by the target security functions.
+        
+        Safe objects are objects whose operations, except for attribute
+        retrieval, and methods access only information stored within the
+        objects or passed as arguments.  Safe objects contained within the
+        interpreter environment can contain only information that is already
+        in the environment or computed directly from information that is
+        included in the environment. For this reason, safe objects created
+        within the environment cannot be used to directly access information
+        outside the environment.
+        
+        Safe objects have some attributes that could (very) indirectly be used
+        to access assets. For this reason, an untrusted interpreter always
+        proxies the results of attribute accesses on a safe objects.
+        
+        Basic objects are safe objects that are used to represent elemental
+        data values such as strings and numbers.  Basic objects require a
+        lower level of protection than non-basic objects, as will be described
+        detail in a later section.
+        
+        Security proxies mediate all object operations.  Any operation
+        access is checked to see whether a subject is authorized to perform
+        the operation.  All operation results other than basic objects are, in
+        turn, security proxied.  Security proxies will be described in greater
+        detail in a later section.  Any operation on a security proxy that
+        results in a non-basic object is also security proxied.
+        
+        All external resources needed to perform an operation are security
+        proxied.
+        
+        Let's consider the trusted interpreter for evaluating URLs.  In
+        operation 1 of the example, the interpreter uses a proxied method for
+        getting the system root object.  Because the method is proxied, the
+        result of calling the method and the operation is also proxied.
+        
+        The interpreter has a function for traversing objects.  This function
+        is proxied.  When traversing an object, the function is passed an
+        object and a name.  In operation 2, the function is passed the result
+        of operation 1, which is the proxied root object and the name 'A'.  We
+        may traverse an object by invoking an operation on it.  For example,
+        we may use an operation to get a sub-object. Because any operation on a
+        proxied object returns a proxied object or a basic object, the result
+        is either a proxied object or a basic object.  Traversal may also look
+        up a component.  For example, in operation 1, we might look up a
+        presentation component named "A" for the root object.  In this case,
+        the external object is not proxied, but, when it is returned from the
+        traversal function, it is proxied (unless it is a a basic object)
+        because the traversal function is proxied, and the result of calling a
+        proxied function is proxied (unless the result is a basic object).
+        Operation 3 proceeds in the same way.
+        
+        When we get to operation 4, we use a function for computing the
+        default presentation of the result of operation 3. As with traversal,
+        the result of getting the default presentation is either a proxied
+        object or a basic object because the function for getting the default
+        presentation is proxied.
+        
+        When we get to the last operation, we have either a proxied object or a
+        basic object.  If the result of operation 4 is a basic object, we
+        simply convert it to a string and return it as the result page.  If
+        the result of operation 4 is a non-basic object, we invoke a render
+        operation on it and return the result as a string.
+        
+        Note that an untrusted interpreter may or may not provide protection
+        against excessive resource usage.  Different interpreters will provide
+        different levels of service with respect to limitations on resource
+        usage.
+        
+        If an untrusted interpreter performs an attribute access, the trusted
+        interpreter must proxy the result unless the result is a basic object.
+        
+        In summary, an untrusted interpreter assures that any access to assets
+        is mediated through security proxies by creating an environment to run
+        untrusted code and making sure that:
+        
+        - The only way to access anything from outside of the environment is
+        to call functions that are proxied in the environment.
+        
+        - Results of any attribute access in the environment are proxied
+        unless the results are basic objects.
+        
+        Security proxies
+        ----------------
+        
+        Security proxies are objects that wrap and mediate access to objects.
+        
+        The Python programming language used by Zope defines a set of specific
+        named low-level operations.  In addition to operations, Python objects
+        can have attributes, used to represent data and methods.  Attributes
+        are accessed using a dot notation. Applications can, and usually do,
+        define methods to provide extended object behaviors.  Methods are
+        accessed as attributes through the low-level operation named
+        "__getattribute__".  The Python code::
+        
+        a.b()
+        
+        invokes 2 operations:
+        
+        1. Use the low-level `__getattribute__` operation with the name "b".
+        
+        2. Use the low-level '__call__' operation on the result of the first
+        operation.
+        
+        For all operations except the `__getattribute__` and
+        `__setattribute__` operations, security proxies have a permission
+        value defined by the permission-declaration subsystem.  Two special
+        permission values indicate that access is either forbidden (never
+        allowed) or public (always allowed).  For all other permission values,
+        the authorization subsystem is used to decide whether the subject has
+        the permission for the proxied object.  If the subject has the
+        permission, then access to the operation is allowed. Otherwise, access
+        is denied.
+        
+        For getting or setting attributes, a proxy has permissions for getting
+        and a permission for setting attribute values for a given attribute
+        name.  As described above, these permissions may be one of the two
+        special permission values indicating forbidden or public access, or
+        another permission value that must be checked with the authorization
+        system.
+        
+        For all objects, Zope defines the following operations to be always public:
+        
+        comparison
+        "__lt__", "__le__", "__eq__", "__gt__", "__ge__", "__ne__"
+        
+        hash
+        "__hash__"
+        
+        boolean value
+        "__nonzero__"
+        
+        class introspection
+        "__class__"
+        
+        interface introspection
+        "__providedBy__", "__implements__"
+        
+        adaptation
+        "__conform__"
+        
+        low-level string representation
+        "__repr__"
+        
+        The result of an operation on a proxied object is a security proxy
+        unless the result is a basic value.
+        
+        Basic objects
+        -------------
+        
+        Basic objects are safe immutable objects that contain only immutable
+        subobjects. Examples of basic objects include:
+        
+        - Strings,
+        
+        - Integers (long and normal),
+        
+        - Floating-point objects,
+        
+        - Date-time objects,
+        
+        - Boolean objects (True and False), and
+        
+        - The special (nil) object, None.
+        
+        Basic objects are safe, so, as described earlier, operations on basic
+        objects, other than attribute access, use only information contained
+        within the objects or information passed to them.  For this reason,
+        basic objects cannot be used to access information outside of the
+        untrusted interpreter environment.
+        
+        The decision not to proxy basic objects is largely an optimization.
+        It allows low-level safe computation to be performed without
+        unnecessary overhead,
+        
+        Note that a basic object could contain sensitive information, but such
+        a basic object would need to be obtained by making a call on a proxied
+        object.  Therefore, the access to the basic object in the first place
+        is mediated by the security functions.
+        
+        Rationale for mutable safe objects
+        ----------------------------------
+        
+        Some safe objects are not basic. For these objects, we proxy the
+        objects if they originate from outside of the environment.  We do this
+        for two reasons:
+        
+        1. Non-basic objects from outside the environment need to be proxied
+        to prevent unauthorized access to information.
+        
+        2. We need to prevent un-mediated change of information from outside of
+        the environment.
+        
+        We don't proxy safe objects created within the environment.  This is
+        safe to do because such safe objects can contain and provide access to
+        information already in the environment.  Sometimes the interpreter or
+        the interpreted program needs to be able to create simple data
+        containers to hold information computed in the course of the program
+        execution.  Several safe container types are provided for this
+        purpose.
+        
+        
+        =======
+        CHANGES
+        =======
+        
+        3.6.4 (unreleased)
+        ------------------
+        
+        - None so far.
+        
+        3.6.3 (2009-03-23)
+        ------------------
+        
+        - Ensure that simple zope.schema's VocabularyRegistry is used for
+        PermissionVocabulary tests, because it's replaced implicitly in
+        environments with zope.app.schema installed that makes that tests
+        fail.
+        
+        - Fixed a bug in DecoratedSecurityCheckerDescriptor which made
+        security-wrapping location proxied exception instances throw
+        exceptions on Python 2.5.
+        See https://bugs.launchpad.net/zope3/+bug/251848
+        
+        3.6.2 (2009-03-14)
+        ------------------
+        
+        - Add zope.i18nmessageid.Message to non-proxied basic types. It's okay, because
+        messages are immutable. It was done by zope.app.security before.
+        
+        - Add "__name__" and "__parent__" attributes to list of available by default.
+        This was also done by zope.app.security package before.
+        
+        - Added PermissionsVocabulary and PermissionIdsVocabulary vocabularies
+        to the ``zope.security.permission`` module. They were moved from
+        the ``zope.app.security`` package.
+        
+        - Add zcml permission definitions for most common and useful permissions,
+        like "zope.View" and "zope.ManageContent", as well as for the special
+        "zope.Public" permission. They are placed in a separate "permissions.zcml"
+        file, so it can be easily excluded/redefined. They are selected part of
+        permissions moved from ``zope.app.security`` and used by many zope.*
+        packages.
+        
+        - Add `addCheckerPublic` helper function in ``zope.security.testing`` module
+        that registers the "zope.Public" permission as an IPermission utility.
+        
+        - Add security declarations for the ``zope.security.permisson.Permission`` class.
+        
+        - Improve test coverage.
+        
+        3.6.1 (2009-03-10)
+        ------------------
+        
+        - Use ``from`` imports instead of ``zope.deferred`` to avoid circular
+        import problems, thus drop dependency on ``zope.deferredimport``.
+        
+        - Raise NoInteraction when zope.security.checkPermission is called
+        without interaction being active (LP #301565).
+        
+        - Don't define security checkers for deprecated set types from the
+        "sets" module on Python 2.6. It's discouraged to use them and
+        `set` and `frozenset` built-in types should be used instead.
+        
+        - Change package's mailng list address to zope-dev at zope.org as
+        zope3-dev at zope.org is now retired.
+        
+        - Remove old zpkg-related files.
+        
+        3.6.0 (2009-01-31)
+        ------------------
+        
+        - Install decorated security checker support on LocationProxy from the
+        outside.
+        
+        - Added support to bootstrap on Jython.
+        
+        - Moved the `protectclass` module from `zope.app.security` to this
+        package to reduce the number of dependencies on `zope.app.security`.
+        
+        - Moved the <module> directive implementation from `zope.app.security`
+        to this package.
+        
+        - Moved the <class> directive implementation from `zope.app.component`
+        to this package.
+        
+        
+        3.5.2 (2008-07-27)
+        ------------------
+        
+        - Made C code compatible with Python 2.5 on 64bit architectures.
+        
+        
+        3.5.1 (2008-06-04)
+        ------------------
+        
+        - Add `frozenset`, `set`, `reversed`, and `sorted` to the list of safe
+        builtins.
+        
+        
+        3.5.0 (2008-03-05)
+        ------------------
+        
+        - Changed title for ``zope.security.management.system_user`` to be more
+        presentable.
+        
+        
+        3.4.0 (2007-10-02)
+        ------------------
+        
+        - Updated meta-data.
+        
+        
+        3.4.0b5 (2007-08-15)
+        --------------------
+        
+        - Bug: Fixed a circular import in the C implementation.
+        
+        
+        3.4.0b4 (2007-08-14)
+        --------------------
+        
+        - Bug: ``zope.security.management.system_user`` had an ugly/brittle id.
+        
+        
+        3.4.0b3 (2007-08-14)
+        --------------------
+        
+        - ``zope.security`` now works on Python 2.5
+        
+        - Bug: ``zope.security.management.system_user`` wasn't a valid principal
+        (didn't provide IPrincipal).
+        
+        - Bug: Fixed inclusion of doctest to use the doctest module from
+        ``zope.testing``. Now tests can be run multiple times without
+        breaking. (#98250)
+        
+        
+        3.4.0b2 (2007-06-15)
+        --------------------
+        
+        - Bug: Removed stack extraction in newInteraction. When using eggs this is an
+        extremly expensive function. The publisher is now more than 10 times faster
+        when using eggs and about twice as fast with a zope trunk checkout.
+        
+        
+        3.4.0b1
+        -------
+        
+        - Temporarily fixed the hidden (and accidental) dependency on zope.testing to
+        become optional.
+        
+        Note: The releases between 3.2.0 and 3.4.0b1 where not tracked as an
+        individual package and have been documented in the Zope 3 changelog.
+        
+        
+        3.2.0 (2006-01-05)
+        ------------------
+        
+        - Corresponds to the verison of the zope.security package shipped as part of
+        the Zope 3.2.0 release.
+        
+        - Removed deprecated helper functions, 'proxy.trustedRemoveSecurityProxy' and
+        'proxy.getProxiedObject'.
+        
+        - Made handling of 'management.{end,restore}Interaction' more careful w.r.t.
+        edge cases.
+        
+        - Made behavior of 'canWrite' consistent with 'canAccess':  if 'canAccess'
+        does not raise 'ForbiddenAttribute', then neither will 'canWrite'.  See:
+        http://www.zope.org/Collectors/Zope3-dev/506
+        
+        - Code style / documentation / test fixes.
+        
+        
+        3.1.0 (2005-10-03)
+        ------------------
+        
+        - Added support for use of the new Python 2.4 datatypes, 'set' and
+        'frozenset', within checked code.
+        
+        - C security proxy acquired a dependency on the 'proxy.h' header from the
+        'zope.proxy' package.
+        
+        - XXX: the spelling of the '#include' is bizarre!  It seems to be related to
+        'zpkg'-based builds, and should likely be revisited.  For the moment, I have
+        linked in the 'zope.proxy' package into our own 'include' directory.  See
+        the subversion checkin: http://svn.zope.org/Zope3/?rev=37882&view=rev
+        
+        - Updated checker to avoid re-proxying objects which have and explicit
+        '__Security_checker__' assigned.
+        
+        - Corresponds to the verison of the zope.security package shipped as part of
+        the Zope 3.1.0 release.
+        
+        - Clarified contract of 'IChecker' to indicate that its 'check*' methods may
+        raise only 'Forbidden' or 'Unauthorized' exceptions.
+        
+        - Added interfaces, ('IPrincipal', 'IGroupAwarePrincipal', 'IGroup', and
+        'IPermission') specifying contracts of components in the security framework.
+        
+        - Code style / documentation / test fixes.
+        
+        
+        3.0.0 (2004-11-07)
+        ------------------
+        
+        - Corresponds to the version of the zope.security package shipped as part of
+        the Zope X3.0.0 release.
+        
+Keywords: zope security policy principal permission
+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: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Topic :: Internet :: WWW/HTTP
+Classifier: Framework :: Zope3

Added: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/SOURCES.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/SOURCES.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/SOURCES.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,80 @@
+CHANGES.txt
+README.txt
+bootstrap.py
+buildout.cfg
+setup.py
+include/zope.proxy/DEPENDENCIES.cfg
+include/zope.proxy/SETUP.cfg
+include/zope.proxy/__init__.py
+include/zope.proxy/_zope_proxy_proxy.c
+include/zope.proxy/decorator.py
+include/zope.proxy/interfaces.py
+include/zope.proxy/proxy.h
+include/zope.proxy/tests/__init__.py
+include/zope.proxy/tests/test_decorator.py
+include/zope.proxy/tests/test_proxy.py
+src/zope/__init__.py
+src/zope.security.egg-info/PKG-INFO
+src/zope.security.egg-info/SOURCES.txt
+src/zope.security.egg-info/dependency_links.txt
+src/zope.security.egg-info/namespace_packages.txt
+src/zope.security.egg-info/not-zip-safe
+src/zope.security.egg-info/requires.txt
+src/zope.security.egg-info/top_level.txt
+src/zope/security/README.txt
+src/zope/security/__init__.py
+src/zope/security/_definitions.py
+src/zope/security/_proxy.c
+src/zope/security/_zope_security_checker.c
+src/zope/security/adapter.py
+src/zope/security/checker.py
+src/zope/security/configure.zcml
+src/zope/security/decorator.py
+src/zope/security/i18n.py
+src/zope/security/interfaces.py
+src/zope/security/management.py
+src/zope/security/meta.zcml
+src/zope/security/metaconfigure.py
+src/zope/security/metadirectives.py
+src/zope/security/permission.py
+src/zope/security/permissions.zcml
+src/zope/security/protectclass.py
+src/zope/security/proxy.py
+src/zope/security/setup.py
+src/zope/security/simplepolicies.py
+src/zope/security/testing.py
+src/zope/security/untrustedinterpreter.txt
+src/zope/security/zcml.py
+src/zope/security/examples/sandbox.py
+src/zope/security/examples/sandbox_security.py
+src/zope/security/tests/__init__.py
+src/zope/security/tests/adapter.py
+src/zope/security/tests/components.py
+src/zope/security/tests/emptymodule.py
+src/zope/security/tests/exampleclass.py
+src/zope/security/tests/module.py
+src/zope/security/tests/modulehookup.py
+src/zope/security/tests/redefineperms.zcml
+src/zope/security/tests/test_adapter.py
+src/zope/security/tests/test_checker.py
+src/zope/security/tests/test_contentdirective.py
+src/zope/security/tests/test_decorator.py
+src/zope/security/tests/test_directives.py
+src/zope/security/tests/test_location.py
+src/zope/security/tests/test_management.py
+src/zope/security/tests/test_module_directives.py
+src/zope/security/tests/test_permission.py
+src/zope/security/tests/test_protectclass.py
+src/zope/security/tests/test_protectsubclass.py
+src/zope/security/tests/test_proxy.py
+src/zope/security/tests/test_set_checkers.py
+src/zope/security/tests/test_simpleinteraction.py
+src/zope/security/tests/test_standard_checkers.py
+src/zope/security/untrustedpython/__init__.py
+src/zope/security/untrustedpython/builtins.py
+src/zope/security/untrustedpython/builtins.txt
+src/zope/security/untrustedpython/interpreter.py
+src/zope/security/untrustedpython/interpreter.txt
+src/zope/security/untrustedpython/rcompile.py
+src/zope/security/untrustedpython/rcompile.txt
+src/zope/security/untrustedpython/tests.py
\ No newline at end of file


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/SOURCES.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/dependency_links.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/dependency_links.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/dependency_links.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/dependency_links.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/namespace_packages.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/namespace_packages.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/namespace_packages.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+zope


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/namespace_packages.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/not-zip-safe
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/not-zip-safe	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/not-zip-safe	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+

Added: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/requires.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/requires.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/requires.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1,16 @@
+setuptools
+pytz
+zope.component
+zope.configuration
+zope.exceptions
+zope.i18nmessageid
+zope.interface
+zope.location
+zope.proxy >= 3.4.2
+zope.schema
+
+[test]
+RestrictedPython
+
+[untrustedpython]
+RestrictedPython
\ No newline at end of file


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/requires.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/top_level.txt
===================================================================
--- van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/top_level.txt	                        (rev 0)
+++ van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/top_level.txt	2009-05-26 13:14:01 UTC (rev 100399)
@@ -0,0 +1 @@
+zope


Property changes on: van.pydeb/trunk/van/pydeb/tests/zope.security.egg-info/top_level.txt
___________________________________________________________________
Added: svn:eol-style
   + native



More information about the Checkins mailing list