[Checkins] SVN: z3c.autoinclude/ importing initial version of z3c.autoinclude

Robert Marianski rmarianski at openplans.org
Sun Feb 17 15:06:19 EST 2008


Log message for revision 83991:
  importing initial version of z3c.autoinclude

Changed:
  A   z3c.autoinclude/
  A   z3c.autoinclude/branches/
  A   z3c.autoinclude/tags/
  A   z3c.autoinclude/trunk/
  A   z3c.autoinclude/trunk/README.txt
  A   z3c.autoinclude/trunk/bootstrap.py
  A   z3c.autoinclude/trunk/buildout.cfg
  A   z3c.autoinclude/trunk/setup.py
  A   z3c.autoinclude/trunk/src/
  A   z3c.autoinclude/trunk/src/z3c/
  A   z3c.autoinclude/trunk/src/z3c/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/README.txt
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/include.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/meta.zcml
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/configure.zcml
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/setup.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/configure.zcml
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/setup.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/G/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/G/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/G/meta.zcml
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/configure.zcml
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/meta.zcml
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/setup.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/setup.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/meta.zcml
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/zcml.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/setup.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/y/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/y/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/y/z/
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/y/z/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/__init__.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/tests/tests.py
  A   z3c.autoinclude/trunk/src/z3c/autoinclude/zcml.py

-=-
Added: z3c.autoinclude/trunk/README.txt
===================================================================
--- z3c.autoinclude/trunk/README.txt	                        (rev 0)
+++ z3c.autoinclude/trunk/README.txt	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,20 @@
+z3c.autoinclude
+===============
+
+This package adds a new directive: "autoinclude". This directive
+searches through the dependencies in your setup.py file
+(install_requires), and includes the meta.zcml and configure.zcml
+files in those packages that it finds. Inclusion order matches the
+order in the setup.py file. You can pass a path for the package you
+want to autoinclude for, but typically you pass in the current
+package, as follows: <autoinclude package="." />
+
+The motivation behind this is to prevent having to repeat yourself in
+2 places, the setup.py file, and including the zcml. Common errors,
+especially for beginners, is to add a new dependency, but to forget to
+include the zcml as well. With the autoinclude directive, adding the
+includes for the zcml is no longer necessary.
+
+This can eventually be used with grok, and grokproject. Creating a new
+grokproject can add this directive in the zcml, and then you no longer
+have to worry about including the zcml manually.

Added: z3c.autoinclude/trunk/bootstrap.py
===================================================================
--- z3c.autoinclude/trunk/bootstrap.py	                        (rev 0)
+++ z3c.autoinclude/trunk/bootstrap.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,55 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 75593 2007-05-06 21:11:27Z jim $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+try:
+    import pkg_resources
+except ImportError:
+    ez = {}
+    exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                         ).read() in ez
+    ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)

Added: z3c.autoinclude/trunk/buildout.cfg
===================================================================
--- z3c.autoinclude/trunk/buildout.cfg	                        (rev 0)
+++ z3c.autoinclude/trunk/buildout.cfg	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,12 @@
+[buildout]
+develop = .
+parts = devpython test
+
+[devpython]
+recipe = zc.recipe.egg
+interpreter = devpython
+eggs = z3c.autoinclude
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.autoinclude

Added: z3c.autoinclude/trunk/setup.py
===================================================================
--- z3c.autoinclude/trunk/setup.py	                        (rev 0)
+++ z3c.autoinclude/trunk/setup.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,39 @@
+from setuptools import setup, find_packages
+
+version = '0.1'
+
+setup(name='z3c.autoinclude',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[
+        "Framework :: Zope3",
+        "Programming Language :: Python",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+        ],
+      keywords='',
+      author='',
+      author_email='',
+      url='',
+      license='Public Domain',
+      packages=find_packages('src'),
+      package_dir={'': 'src'},
+      namespace_packages=['z3c'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+          'zope.dottedname',
+	  'zope.interface',
+	  'zope.configuration',
+	  'zope.schema',
+          'zc.buildout',
+          # -*- Extra requirements: -*-
+      ],
+      extras_require={'test': ['zc.buildout',]},
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Added: z3c.autoinclude/trunk/src/z3c/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/README.txt
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/README.txt	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/README.txt	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,182 @@
+============================
+Auto inclusion of zcml files
+============================
+
+This package provides a facility to automatically include zcml
+dependencies such as configure.zcml and meta.zcml based on
+install_requires in the project's setup.py.
+
+We have created a test environment to simulate setuptools
+dependencies.
+
+``APackage`` depends on ``BCPackage``
+``BCPackage`` depends on ``SiblingPackage``
+
+First, we need to have some infrastructure to install projects::
+
+    >>> from zc.buildout.easy_install import install
+    >>> from pkg_resources import working_set
+    >>> import os
+    >>> def install_projects(projects, target_dir):
+    ...  links = []
+    ...  for project in projects:
+    ...    project_dir = join(projects_dir, project)
+    ...    dist_dir = join(project_dir, 'dist')
+    ...    if os.path.isdir(dist_dir):
+    ...      rmdir(dist_dir)
+    ...    dummy = system(join('bin', 'buildout') + ' setup ' + \
+    ...              project_dir + ' bdist_egg')
+    ...    links.append(dist_dir)
+    ...
+    ...  return install(projects, target_dir, links=links,
+    ...                 working_set=working_set)
+
+We ensure the projects are installed into a temporary directory so
+that we can use them in our tests::
+
+    >>> target_dir = tmpdir('target_dir')
+    >>> ws = install_projects(['APackage', 'BCPackage', 'XYZPackage',
+    ...                        'SiblingPackage', 'TestDirective'],
+    ...                       target_dir)
+    >>> for dist in ws:
+    ...   dist.activate()
+    ...   if dist.project_name == 'APackage':
+    ...     a_dist = dist
+    ...   if dist.project_name == 'XYZPackage':
+    ...     xyz_dist = dist
+    ...   if dist.project_name == 'SiblingPackage':
+    ...	    sibling_dist = dist
+
+Given the distribution for the project named ``APackage``, we can ask
+for the requirements of that distribution::
+
+    >>> reqs = a_dist.requires()
+    >>> pprint(sorted(reqs, key=lambda r:r.project_name))
+    [Requirement.parse('BCPackage'),
+     Requirement.parse('TestDirective'),
+     Requirement.parse('z3c.autoinclude')]
+
+We can turn this requirement into a distribution::
+
+    >>> from pkg_resources import get_provider
+    >>> b_dist = get_provider(reqs[0])
+
+We can adapt a distribution to an IncludeFinder::
+
+    >>> from z3c.autoinclude.include import IncludeFinder
+    >>> a_include_finder = IncludeFinder(a_dist)
+    >>> b_include_finder = IncludeFinder(b_dist)
+    >>> xyz_include_finder = IncludeFinder(xyz_dist)
+    >>> sibling_include_finder = IncludeFinder(sibling_dist)
+
+The include finder provides functionality to determine what namespace
+packages exist in the distribution. In the case of ``APackage``, there
+are no namespace package::
+
+    >>> a_include_finder.namespaceDottedNames()
+    []
+
+``BPackage`` does have a namespace package, ``b``::
+
+    >>> b_include_finder.namespaceDottedNames()
+    ['b']
+
+``XYZPackage`` has a namespace package too, ``x.y`` (``x`` is also
+implicitly a namespace package)::
+
+    >>> xyz_include_finder.namespaceDottedNames()
+    ['x.y']
+
+We can also get the dotted names of the actual packages that we want
+to inspect in a distribution. For a project without namespace packages,
+this will be the packages directly in the packages::
+
+    >>> a_include_finder.dottedNames()
+    ['a']
+
+For a project with namespace packages, it will be the packages that
+are in the namespace packages::
+
+    >>> b_include_finder.dottedNames()
+    ['b.c']
+
+For a nested namespace package, it should still be the innermost package::
+
+    >>> xyz_include_finder.dottedNames()
+    ['x.y.z']
+
+What we need to know in the end is which packages in the requirements
+of a distribution have files we want to include (``configure.zcml``,
+``meta.zcml``). So, given a distribution, let's retrieve all packages
+that it depends on that have ``configure.zcml`` or ``meta.zcml``.
+Note that the individual lists within ``includableInfo`` preserve the
+package order defined in ``setup.py``::
+
+    >>> a_include_finder.includableInfo(['configure.zcml', 'meta.zcml'])
+    {'configure.zcml': ['b.c'], 'meta.zcml': ['z3c.autoinclude', 'testdirective']}
+
+For a nested namespace package with two siblings ``SiblingPackage``,
+we should get the same expected results. The sibling package
+``SiblingPackage`` does have a namespace package::
+
+    >>> sibling_include_finder.namespaceDottedNames()
+    ['F']
+
+For a namespace package with 2 sibling namespaces, we get both sibling
+packages::
+
+    >>> sibling_include_finder.dottedNames()
+    ['F.G', 'F.H']
+
+And we should be able to pick up the files we need to include from
+both dotted names::
+
+    >>> pprint(b_include_finder.includableInfo(['configure.zcml',
+    ...                                         'meta.zcml']))
+    {'configure.zcml': ['F.H'], 'meta.zcml': ['testdirective', 'F.G', 'F.H']}
+
+``APackage`` depends on ``BCPackage``, which depends on
+``SiblingPackage``. ``APackage`` and ``BCPackage`` both contain the
+autoinclude directive, which will automatically include any meta.zcml
+and configure.zcml files (in that order) that their dependencies
+contain. These dependencies' zcml actually contain a test directive
+that will append a logging message to a global variable in
+testdirective.zcml. So let's trigger the loading of the configure.zcml
+in ``APackage`` and see whether its ``BCPackage`` dependency, and
+``BCPackage``'s dependencies, were indeed loaded and in the correct
+order::
+
+    >>> from pkg_resources import resource_filename
+    >>> from zope.configuration import xmlconfig
+    >>> import a
+    >>> dummy = xmlconfig.file(resource_filename('a', 'configure.zcml'),
+    ...                        package=a)
+    >>> from testdirective.zcml import test_log
+    >>> pprint(test_log)
+    [u'f.g meta has been loaded',
+     u'f.h has been loaded',
+     u'BCPackage has been loaded']
+
+There is also a directive for including overrides, which calls
+``autoIncludeOverridesDirective``; however, I have no idea how to test
+this.
+
+Finally, there is a convenience API for finding the files we need to
+include from the requirements of a given package::
+
+    >>> from z3c.autoinclude import package_includes
+    >>> pprint(package_includes('BCPackage'))
+    {'configure.zcml': ['F.H'], 'meta.zcml': ['testdirective', 'F.G', 'F.H']}
+
+As with ``includableInfo``, we can also supply a list of ZCML filenames to search for::
+
+    >>> pprint(package_includes('BCPackage', ['configure.zcml', 'silly.zcml']))
+    {'configure.zcml': ['F.H']}
+    
+Note that it will not catch DistributionNotFound errors::
+
+     >>> package_includes('NonexistentPackage')
+     Traceback (most recent call last):
+     ...
+     DistributionNotFound: NonexistentPackage
+

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,2 @@
+#
+from include import package_includes

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/include.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/include.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/include.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,101 @@
+import os
+from zope.dottedname.resolve import resolve
+from pkg_resources import resource_exists
+from pkg_resources import get_provider
+from pkg_resources import get_distribution
+import logging
+
+log = logging.getLogger("z3c.autoinclude")
+
+class IncludeFinder(object):
+    def __init__(self, dist):
+        self.context = dist
+
+    def namespaceDottedNames(self):
+        """Return dotted names of all namespace packages in distribution.
+        """
+        try:
+            return list(self.context.get_metadata_lines('namespace_packages.txt'))
+        except IOError:
+            return []
+        
+    def dottedNames(self):
+        """Return dotted names of all relevant packages in a distribution.
+
+        Relevant packages are those packages that are directly under the
+        namespace packages in the distribution, but not the namespace packages
+        themselves. If no namespace packages exist, return those packages that
+        are directly in the distribution.
+        """
+        dist_path = self.context.location
+        ns_dottednames = self.namespaceDottedNames()
+        if not ns_dottednames:
+            return subpackageDottedNames(dist_path)
+        result = []
+        for ns_dottedname in ns_dottednames:
+            path = os.path.join(dist_path, *ns_dottedname.split('.'))
+            result.extend(subpackageDottedNames(path, ns_dottedname))
+        return result
+
+    def includableInfo(self, include_candidates):
+        """Return the packages in the dependencies which are includable.
+
+        include_candidates - a list of include files we are looking for
+
+        Returns a dictionary with the include candidates as keys, and lists
+        of dotted names of packages that contain the include candidates as
+        values.
+        """
+        result = {}
+        for req in self.context.requires():
+            include_finder = IncludeFinder(get_provider(req))
+            for dotted_name in include_finder.dottedNames():
+                module = resolve(dotted_name)
+                for candidate in include_candidates:
+                    candidate_path = os.path.join(
+                        os.path.dirname(module.__file__), candidate)
+                    if os.path.isfile(candidate_path):
+                        result.setdefault(candidate, []).append(dotted_name)
+        return result
+
+    
+def subpackageDottedNames(package_path, ns_dottedname=None):
+    # we do not look for subpackages in zipped eggs
+    if not os.path.isdir(package_path):
+        return []
+
+    result = []
+    for subpackage_name in os.listdir(package_path):
+        full_path = os.path.join(package_path, subpackage_name)
+        if isPythonPackage(full_path):
+            if ns_dottedname:
+                result.append('%s.%s' % (ns_dottedname, subpackage_name))
+            else:
+                result.append(subpackage_name)
+    return result
+
+def isPythonPackage(path):
+    if not os.path.isdir(path):
+        return False
+    for init_variant in ['__init__.py', '__init__.pyc', '__init__.pyo']:
+        if os.path.isfile(os.path.join(path, init_variant)):
+            return True
+    return False
+
+def package_includes(project_name, zcml_filenames=None):
+    """
+    Convenience function for finding zcml to load from requirements for
+    a given project. Takes a project name. DistributionNotFound errors
+    will be raised for uninstalled projects.
+    """
+    if zcml_filenames is None:
+        zcml_filenames = ['meta.zcml', 'configure.zcml', 'overrides.zcml']
+    dist = get_distribution(project_name)
+    include_finder = IncludeFinder(dist)
+    return include_finder.includableInfo(zcml_filenames)
+
+def debug_includes(dist, include_type, dotted_names):
+    if not dotted_names:
+        return
+    log.debug('%s - autoinclude %s: %r', dist.project_name,
+              include_type, list(dotted_names))

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/meta.zcml
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/meta.zcml	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/meta.zcml	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,19 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:meta="http://namespaces.zope.org/meta">
+
+  <meta:directives namespace="http://namespaces.zope.org/zope">
+    <meta:directive
+        name="autoinclude"
+        schema=".zcml.IAutoIncludeDirective"
+        handler=".zcml.autoIncludeDirective"
+        />
+    <meta:directive
+        name="autoincludeOverrides"
+        schema=".zcml.IAutoIncludeDirective"
+        handler=".zcml.autoIncludeOverridesDirective"
+        />
+
+  </meta:directives>
+
+</configure>
\ No newline at end of file

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1 @@
+#

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/configure.zcml
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/configure.zcml	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/configure.zcml	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,8 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+   <include package="z3c.autoinclude" file="meta.zcml" />
+   <autoinclude package="." />
+   <!-- APackage is autoincluded. 
+   This means that BCPackage and TestDirective will be included, in no particular order.
+   TestDirective has a meta.zcml.
+   -->
+</configure>

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/setup.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/setup.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/setup.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,29 @@
+from setuptools import setup, find_packages
+import sys, os
+
+version = '0.0'
+
+setup(name='APackage',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+      keywords='',
+      author='',
+      author_email='',
+      url='',
+      license='',
+      package_data = {'': ['*.zcml',]},
+      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+        'BCPackage',
+	'z3c.autoinclude',
+	'TestDirective',
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,2 @@
+#
+#sanity test

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/configure.zcml
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/configure.zcml	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/configure.zcml	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,10 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+  <include package="z3c.autoinclude" file="meta.zcml" />
+  <autoinclude package="." />
+  <test test_string="BCPackage has been loaded" />
+  <!-- BCPackage is autoincluded.
+  This means that SiblingPackage and TestDirective will be included, in no particular order.
+  TestDirective has a meta.zcml.
+  SiblingPackage has a meta.zcml.
+  -->
+</configure>

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/setup.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/setup.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/setup.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,32 @@
+from setuptools import setup, find_packages
+
+version = '0.1'
+
+setup(name='BCPackage',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[
+      ],
+      keywords='',
+      author='',
+      author_email='',
+      url='',
+      license='',
+      package_data = {'': ['*.zcml',]},
+      packages=find_packages(),
+      namespace_packages=['b'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+	  'TestDirective',
+	  'SiblingPackage',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/G/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/G/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/G/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1 @@
+#

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/G/meta.zcml
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/G/meta.zcml	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/G/meta.zcml	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,5 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:meta="http://namespaces.zope.org/meta">
+  <test test_string="f.g meta has been loaded" />
+</configure>

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1 @@
+#

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/configure.zcml
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/configure.zcml	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/configure.zcml	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,3 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+  <test test_string="f.h has been loaded" />
+</configure>
\ No newline at end of file

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/meta.zcml
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/meta.zcml	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/H/meta.zcml	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,2 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+</configure>
\ No newline at end of file

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/F/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/setup.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/setup.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/SiblingPackage/setup.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,30 @@
+from setuptools import setup, find_packages
+
+version = '0.1'
+
+setup(name='SiblingPackage',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+      keywords='',
+      author='',
+      author_email='',
+      url='',
+      license='GPL',
+      package_data = {'': ['*.zcml',]},
+      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+      namespace_packages=['F'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+	  'TestDirective',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/setup.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/setup.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/setup.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,27 @@
+from setuptools import setup, find_packages
+import sys, os
+
+version = '0.0'
+
+setup(name='TestDirective',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+      keywords='',
+      author='',
+      author_email='',
+      url='',
+      license='',
+      package_data = {'': ['*.zcml',]},
+      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1 @@
+#

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/meta.zcml
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/meta.zcml	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/meta.zcml	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,13 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:meta="http://namespaces.zope.org/meta">
+
+  <meta:directives namespace="http://namespaces.zope.org/zope">
+    <meta:directive
+        name="test"
+        schema=".zcml.ITestDirective"
+        handler=".zcml.testDirective"
+        />
+  </meta:directives>
+
+</configure>

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/zcml.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/zcml.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/zcml.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,18 @@
+from zope.interface import Interface
+from zope.schema import TextLine
+
+test_log = []
+
+class ITestDirective(Interface):
+    """Auto-include any ZCML in the dependencies of this package."""
+    
+    test_string = TextLine(
+        title=u"Test package string",
+        description=u"""
+        Append a value to a global variable to inspect later
+        """,
+        required=True,
+        )
+
+def testDirective(_context, test_string):
+    test_log.append(test_string)

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/setup.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/setup.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/setup.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,32 @@
+from setuptools import setup, find_packages
+
+version = '0.1'
+
+setup(name='XYZPackage',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[
+        "Framework :: Zope3",
+        "Programming Language :: Python",
+        ],
+      keywords='',
+      author='',
+      author_email='',
+      url='',
+      license="''",
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['x.y'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+	  'TestDirective',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/y/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/y/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/y/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/XYZPackage/x/y/z/__init__.py
===================================================================

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/__init__.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/__init__.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1 @@
+#

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/tests.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/tests.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/tests.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,19 @@
+import doctest
+import unittest
+import os
+from zc.buildout import testing
+from pprint import pprint
+
+def test_suite():
+    projects_dir = os.path.dirname(__file__)
+    base_suite = doctest.DocFileSuite('../README.txt',
+                                      setUp=testing.buildoutSetUp,
+                                      tearDown=testing.buildoutTearDown,
+                                      globs=dict(projects_dir=projects_dir,
+                                                 pprint=pprint),
+                                      optionflags=doctest.ELLIPSIS)
+    return unittest.TestSuite((base_suite,
+                               ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Added: z3c.autoinclude/trunk/src/z3c/autoinclude/zcml.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/zcml.py	                        (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/zcml.py	2008-02-17 20:06:18 UTC (rev 83991)
@@ -0,0 +1,54 @@
+import sys
+
+from pkg_resources import find_distributions
+from zope.interface import Interface
+from zope.configuration.xmlconfig import include, includeOverrides
+from zope.configuration.fields import GlobalObject
+from zope.dottedname.resolve import resolve
+
+from z3c.autoinclude.include import IncludeFinder
+from z3c.autoinclude.include import debug_includes
+
+class IAutoIncludeDirective(Interface):
+    """Auto-include any ZCML in the dependencies of this package."""
+    
+    package = GlobalObject(
+        title=u"Package to auto-include for",
+        description=u"""
+        Auto-include all dependencies of this package.
+        """,
+        required=True,
+        )
+
+def autoIncludeOverridesDirective(_context, package):
+    dist = distributionForPackage(package)
+    info = IncludeFinder(dist).includableInfo(['overrides.zcml'])
+
+    overrides_zcml = list(info.get('overrides.zcml', []))
+    debug_includes(dist, 'overrides.zcml', overrides_zcml)
+    for dotted_name in overrides_zcml:
+        dependency_package = resolve(dotted_name)
+        includeOverrides(_context, 'overrides.zcml', dependency_package)
+
+def autoIncludeDirective(_context, package):
+    dist = distributionForPackage(package)
+    info = IncludeFinder(dist).includableInfo(['configure.zcml', 'meta.zcml'])
+
+    meta_zcml = list(info.get('meta.zcml', []))
+    debug_includes(dist, 'meta.zcml', meta_zcml)
+    for dotted_name in meta_zcml:
+        dependency_package = resolve(dotted_name)
+        include(_context, 'meta.zcml', dependency_package)
+
+    configure_zcml = list(info.get('configure.zcml', []))
+    debug_includes(dist, 'configure.zcml', configure_zcml)
+    for dotted_name in configure_zcml:
+        dependency_package = resolve(dotted_name)
+        include(_context, 'configure.zcml', dependency_package)
+    
+def distributionForPackage(package):
+    package_filename = package.__file__
+    for path in sys.path:
+        if package_filename.startswith(path):
+            break
+    return list(find_distributions(path, True))[0]



More information about the Checkins mailing list