[Checkins] SVN: z3c.autoinclude/trunk/ merge adding-salt branch to
trunk
Ethan Jucovy
ejucovy at openplans.org
Fri Apr 18 13:36:42 EDT 2008
Log message for revision 85470:
merge adding-salt branch to trunk
Changed:
U z3c.autoinclude/trunk/README.txt
U z3c.autoinclude/trunk/src/z3c/autoinclude/README.txt
U z3c.autoinclude/trunk/src/z3c/autoinclude/__init__.py
A z3c.autoinclude/trunk/src/z3c/autoinclude/dependency.py
D z3c.autoinclude/trunk/src/z3c/autoinclude/include.py
U z3c.autoinclude/trunk/src/z3c/autoinclude/meta.zcml
A z3c.autoinclude/trunk/src/z3c/autoinclude/plugin.py
U z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/configure.zcml
U z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/configure.zcml
A z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BasePackage/
A z3c.autoinclude/trunk/src/z3c/autoinclude/tests/FooPackage/
U z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/setup.py
U z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/zcml.py
A z3c.autoinclude/trunk/src/z3c/autoinclude/tests/base2/
A z3c.autoinclude/trunk/src/z3c/autoinclude/tests/base2_plug/
A z3c.autoinclude/trunk/src/z3c/autoinclude/utils.py
U z3c.autoinclude/trunk/src/z3c/autoinclude/zcml.py
-=-
Modified: z3c.autoinclude/trunk/README.txt
===================================================================
--- z3c.autoinclude/trunk/README.txt 2008-04-18 17:31:30 UTC (rev 85469)
+++ z3c.autoinclude/trunk/README.txt 2008-04-18 17:36:41 UTC (rev 85470)
@@ -1,12 +1,12 @@
-This package adds a new ZCML directive: "autoinclude". This directive
-searches through the dependencies in your setup.py file
+This package adds a new ZCML directive: "includeDependencies". 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::
+want to include dependencies for, but typically you pass in the
+current package, as follows::
- <autoinclude package="." />
+ <includeDependencies package="." />
The motivation behind this is to prevent having to repeat yourself in
two places when you want to depend on a Zope 3 or Grok-based
@@ -21,19 +21,19 @@
The next versions of Grok_ and grokproject_ will use this functionality
out of the box. The grokproject command will automatically add the
-``autoinclude`` directive in the ZCML of the project it generates. You
-can then stop worrying about manual ZCML inclusion in the vast
+``includeDependencies`` directive in the ZCML of the project it generates.
+You can then stop worrying about manual ZCML inclusion in the vast
majority of cases.
-The ``autoinclude`` directive automatically includes
+The ``includeDependencies`` directive automatically includes
``configure.zcml`` and ``meta.zcml`` files that in the main package
directories. In some cases, a package may use unusual names or
locations for its ZCML files. In that case you will need to modify
your package's ``configure.zcml`` and ``meta.zcml`` yourself to
include the ZCML using the manual ``include`` directive.
-To make the ``autoinclude`` directive available for use in your
-application or framework, you need to include it (in your
+To make the ``includeDependencies`` directive available for use in
+your application or framework, you need to include it (in your
``meta.zcml`` for instance), like this::
<include package="z3c.autoinclude" file="meta.zcml" />
Modified: z3c.autoinclude/trunk/src/z3c/autoinclude/README.txt
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/README.txt 2008-04-18 17:31:30 UTC (rev 85469)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/README.txt 2008-04-18 17:36:41 UTC (rev 85470)
@@ -2,10 +2,37 @@
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.
+This package provides a facility to automatically load zcml files
+such as configure.zcml and meta.zcml for a project's dependencies
+and extension packages.
+Autoinclusion is signalled by custom zcml directives defined in
+z3c.autoinclude's meta.zcml file.
+
+To trigger autoinclusion of a package's dependencies, include the
+following directive::
+
+ <includeDependencies package='.' />
+
+To trigger autoinclusion of a package's extensions, include the
+following directive::
+
+ <includePlugins package='.' />
+
+And to signal a package as an extension to a base package, use
+the following entry point (in your project's setup.py)::
+
+ [z3c.autoinclude.plugin]
+ target = basepackage.dotted.modulename
+
+
+Automatic inclusion of package dependencies
+===========================================
+
+The z3c.autoinclude.dependency module uses an egg's install_requires
+information (in the project's setup.py) to find and implicitly load
+zcml from all dependencies of a project.
+
We have created a test environment to simulate setuptools
dependencies.
@@ -61,17 +88,17 @@
>>> from pkg_resources import get_provider
>>> b_dist = get_provider(reqs[0])
-We can adapt a distribution to an IncludeFinder::
+We can adapt a distribution to a DependencyFinder::
- >>> 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)
+ >>> from z3c.autoinclude.dependency import DependencyFinder
+ >>> a_include_finder = DependencyFinder(a_dist)
+ >>> b_include_finder = DependencyFinder(b_dist)
+ >>> xyz_include_finder = DependencyFinder(xyz_dist)
+ >>> sibling_include_finder = DependencyFinder(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::
+are no namespace packages::
>>> a_include_finder.namespaceDottedNames()
[]
@@ -180,3 +207,104 @@
...
DistributionNotFound: NonexistentPackage
+Now let's just clean up our test log in preparation for the next test::
+
+ >>> from testdirective.zcml import clear_test_log
+ >>> clear_test_log()
+ >>> pprint(test_log)
+ []
+
+
+=========================================
+Automatic inclusion of extension packages
+=========================================
+
+There is additional functionality for registering and autoincluding
+extension packages for a particular platform.
+
+In this test environment, ``BasePackage`` provides the ``basepackage``
+module which we will treat as our platform. ``FooPackage`` wants to
+broadcast itself as a plugin for ``basepackage`` and thereby register
+its ZCML as a candidate for automatic inclusion. ``TestDirective``
+also broadcasts itself as a plugin for ``basepackage``.
+
+So, once again, we must first set up our testing infrastructure::
+
+ >>> ws = install_projects(['BasePackage', 'FooPackage', 'TestDirective',
+ ... 'base2', 'base2_plug'],
+ ... target_dir)
+ >>> for dist in ws:
+ ... dist.activate()
+ ... if dist.project_name == 'FooPackage':
+ ... foo_dist = dist
+ ... elif dist.project_name == 'BasePackage':
+ ... base_dist = dist
+
+Given a module name, we can ask for distributions which have been broadcast
+themselves as plugging into that module via entry points::
+
+ >>> from z3c.autoinclude.plugin import find_plugins
+ >>> sorted(find_plugins('basepackage'))
+ [FooPackage 0.0 (...), TestDirective 0.0 (...)]
+
+Armed with a valid module name we can find the ZCML files within it
+which must be loaded::
+
+ >>> from z3c.autoinclude.plugin import zcml_to_include
+ >>> zcml_to_include('foo')
+ ['configure.zcml']
+
+By default the function looks for the standard ZCML files ``meta.zcml``,
+``configure.zcml``, and ``overrides.zcml`` but this behavior can be
+overridden::
+
+ >>> zcml_to_include('foo', ['meta.zcml'])
+ []
+
+Finally, we know how to get a list of all module dottednames within
+a distribution, through the DistributionManager adapter::
+
+ >>> from z3c.autoinclude.utils import DistributionManager
+ >>> DistributionManager(foo_dist).dottedNames()
+ ['foo']
+
+So between these functions we can now get a dictionary of all
+extension modules which must be loaded for each ZCML group given
+a base platform.
+
+For consistency, we use the same API as with dependency autoinclusion.
+This time we adapt a base platform (represented by a string referring
+to an importable dotted module name) to a PluginFinder and call its
+`includableInfo` method::
+
+ >>> from z3c.autoinclude.plugin import PluginFinder
+ >>> pprint(PluginFinder('basepackage').includableInfo(['configure.zcml',
+ ... 'meta.zcml']))
+ {'configure.zcml': ['foo'], 'meta.zcml': ['testdirective']}
+
+``FooPackage`` has a test-logging directive in its configure.zcml
+which is defined in meta.zcml in ``TestDirective``. ``FooPackage``
+does not know anything about ``TestDirective`` and does not explicitly
+include its ZCML; so for the test-logging directive to succeed when
+the ZCML of ``FooPackage`` is loaded, the meta.zcml from ``TestDirective``
+must be loaded first. Since ``TestDirective`` offers itself as a
+plugin for ``BasePackage`` and zcmlgroups are loaded in the
+conventional order with all meta.zcml first, none of this should
+explode when we load the ZCML from ``BasePackage`` and the test log
+should accurately reflect that the ``FooPackage`` ZCML has been loaded::
+
+ >>> import basepackage
+ >>> dummy = xmlconfig.file(resource_filename('basepackage', 'configure.zcml'),
+ ... package=basepackage)
+ >>> pprint(test_log)
+ [u'foo has been loaded']
+
+
+``base2`` is a namespace package. ``base2.plug`` is a package that
+defines a plugin for base2.
+
+# >>> import base2
+# >>> dummy = xmlconfig.file(resource_filename('base2', 'configure.zcml'),
+# ... package=base2)
+# >>> pprint(test_log)
+# [u'base2.plug has been loaded']
Modified: z3c.autoinclude/trunk/src/z3c/autoinclude/__init__.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/__init__.py 2008-04-18 17:31:30 UTC (rev 85469)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/__init__.py 2008-04-18 17:36:41 UTC (rev 85470)
@@ -1,2 +1,2 @@
#
-from include import package_includes
+from dependency import package_includes
Copied: z3c.autoinclude/trunk/src/z3c/autoinclude/dependency.py (from rev 85469, z3c.autoinclude/branches/adding-salt/src/z3c/autoinclude/dependency.py)
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/dependency.py (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/dependency.py 2008-04-18 17:36:41 UTC (rev 85470)
@@ -0,0 +1,43 @@
+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
+from z3c.autoinclude.utils import DistributionManager
+
+log = logging.getLogger("z3c.autoinclude")
+
+class DependencyFinder(DistributionManager):
+ 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():
+ dist_manager = DistributionManager(get_provider(req))
+ for dotted_name in dist_manager.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 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 = DependencyFinder(dist)
+ return include_finder.includableInfo(zcml_filenames)
Deleted: z3c.autoinclude/trunk/src/z3c/autoinclude/include.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/include.py 2008-04-18 17:31:30 UTC (rev 85469)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/include.py 2008-04-18 17:36:41 UTC (rev 85470)
@@ -1,101 +0,0 @@
-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))
Modified: z3c.autoinclude/trunk/src/z3c/autoinclude/meta.zcml
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/meta.zcml 2008-04-18 17:31:30 UTC (rev 85469)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/meta.zcml 2008-04-18 17:36:41 UTC (rev 85470)
@@ -4,16 +4,34 @@
<meta:directives namespace="http://namespaces.zope.org/zope">
<meta:directive
- name="autoinclude"
+ name="includeDependencies"
schema=".zcml.IAutoIncludeDirective"
handler=".zcml.autoIncludeDirective"
/>
<meta:directive
- name="autoincludeOverrides"
+ name="includeDependenciesOverrides"
schema=".zcml.IAutoIncludeDirective"
handler=".zcml.autoIncludeOverridesDirective"
/>
+ <!-- deprecated -->
+ <meta:directive
+ name="autoinclude"
+ schema=".zcml.IAutoIncludeDirective"
+ handler=".zcml.deprecatedAutoIncludeDirective"
+ />
+ <meta:directive
+ name="autoincludeOverrides"
+ schema=".zcml.IAutoIncludeDirective"
+ handler=".zcml.deprecatedAutoIncludeOverridesDirective"
+ />
+
+ <meta:directive
+ name="includePlugins"
+ schema=".zcml.IIncludePluginsDirective"
+ handler=".zcml.includePluginsDirective"
+ />
+
</meta:directives>
</configure>
\ No newline at end of file
Copied: z3c.autoinclude/trunk/src/z3c/autoinclude/plugin.py (from rev 85469, z3c.autoinclude/branches/adding-salt/src/z3c/autoinclude/plugin.py)
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/plugin.py (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/plugin.py 2008-04-18 17:36:41 UTC (rev 85470)
@@ -0,0 +1,41 @@
+import os
+from pkg_resources import iter_entry_points
+from pkg_resources import resource_filename
+from z3c.autoinclude.utils import DistributionManager
+from z3c.autoinclude.utils import distributionForDottedName
+
+class PluginFinder(DistributionManager):
+ def __init__(self, platform_dottedname):
+ self.context = distributionForDottedName(platform_dottedname)
+ self.dottedname = platform_dottedname
+
+ def includableInfo(self, include_candidates):
+ includable_info = {}
+
+ for plugin_distribution in find_plugins(self.dottedname):
+ include_finder = DistributionManager(plugin_distribution)
+ for plugin_dottedname in include_finder.dottedNames():
+ groups = zcml_to_include(plugin_dottedname, include_candidates)
+ for group in groups:
+ includable_info.setdefault(group, []).append(plugin_dottedname)
+ return includable_info
+
+
+def find_plugins(dotted_name):
+ plugins = []
+ for ep in iter_entry_points('z3c.autoinclude.plugin'):
+ if ep.module_name == dotted_name:
+ plugins.append(ep.dist)
+ return plugins
+
+def zcml_to_include(dotted_name, zcmlgroups=None):
+ if zcmlgroups is None:
+ zcmlgroups = ('meta.zcml', 'configure.zcml', 'overrides.zcml')
+
+ includable_info = []
+
+ for zcmlgroup in zcmlgroups:
+ filename = resource_filename(dotted_name, zcmlgroup)
+ if os.path.isfile(filename):
+ includable_info.append(zcmlgroup)
+ return includable_info
Modified: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/configure.zcml
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/configure.zcml 2008-04-18 17:31:30 UTC (rev 85469)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/APackage/a/configure.zcml 2008-04-18 17:36:41 UTC (rev 85470)
@@ -1,6 +1,6 @@
<configure xmlns="http://namespaces.zope.org/zope">
<include package="z3c.autoinclude" file="meta.zcml" />
- <autoinclude package="." />
+ <includeDependencies package="." />
<!-- APackage is autoincluded.
This means that BCPackage and TestDirective will be included, in no particular order.
TestDirective has a meta.zcml.
Modified: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/configure.zcml
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/configure.zcml 2008-04-18 17:31:30 UTC (rev 85469)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BCPackage/b/c/configure.zcml 2008-04-18 17:36:41 UTC (rev 85470)
@@ -1,6 +1,6 @@
<configure xmlns="http://namespaces.zope.org/zope">
<include package="z3c.autoinclude" file="meta.zcml" />
- <autoinclude package="." />
+ <includeDependencies package="." />
<test test_string="BCPackage has been loaded" />
<!-- BCPackage is autoincluded.
This means that SiblingPackage and TestDirective will be included, in no particular order.
Copied: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/BasePackage (from rev 85469, z3c.autoinclude/branches/adding-salt/src/z3c/autoinclude/tests/BasePackage)
Copied: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/FooPackage (from rev 85469, z3c.autoinclude/branches/adding-salt/src/z3c/autoinclude/tests/FooPackage)
Modified: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/setup.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/setup.py 2008-04-18 17:31:30 UTC (rev 85469)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/setup.py 2008-04-18 17:36:41 UTC (rev 85470)
@@ -23,5 +23,7 @@
],
entry_points="""
# -*- Entry points: -*-
+ [z3c.autoinclude.plugin]
+ target = basepackage
""",
)
Modified: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/zcml.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/zcml.py 2008-04-18 17:31:30 UTC (rev 85469)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/tests/TestDirective/testdirective/zcml.py 2008-04-18 17:36:41 UTC (rev 85470)
@@ -3,6 +3,10 @@
test_log = []
+def clear_test_log():
+ while test_log:
+ test_log.pop()
+
class ITestDirective(Interface):
"""Auto-include any ZCML in the dependencies of this package."""
Copied: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/base2 (from rev 85469, z3c.autoinclude/branches/adding-salt/src/z3c/autoinclude/tests/base2)
Copied: z3c.autoinclude/trunk/src/z3c/autoinclude/tests/base2_plug (from rev 85469, z3c.autoinclude/branches/adding-salt/src/z3c/autoinclude/tests/base2_plug)
Copied: z3c.autoinclude/trunk/src/z3c/autoinclude/utils.py (from rev 85469, z3c.autoinclude/branches/adding-salt/src/z3c/autoinclude/utils.py)
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/utils.py (rev 0)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/utils.py 2008-04-18 17:36:41 UTC (rev 85470)
@@ -0,0 +1,79 @@
+import logging
+import os
+from pkg_resources import find_distributions
+import sys
+from zope.dottedname.resolve import resolve
+
+log = logging.getLogger("z3c.autoinclude")
+
+class DistributionManager(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 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 distributionForPackage(package):
+
+ package_filename = package.__file__
+ for path in sys.path:
+ if package_filename.startswith(path):
+ break
+ dists = list(find_distributions(path, True))
+ assert dists, "No distributions found for package %s/%s" % (path, package_filename)
+ return dists[0]
+
+def distributionForDottedName(dotted_name):
+ return distributionForPackage(resolve(dotted_name))
+
+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))
Modified: z3c.autoinclude/trunk/src/z3c/autoinclude/zcml.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/zcml.py 2008-04-18 17:31:30 UTC (rev 85469)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/zcml.py 2008-04-18 17:36:41 UTC (rev 85470)
@@ -1,13 +1,12 @@
-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
+from z3c.autoinclude.dependency import DependencyFinder
+from z3c.autoinclude.utils import debug_includes
+from z3c.autoinclude.utils import distributionForPackage
+from z3c.autoinclude.plugin import PluginFinder
class IAutoIncludeDirective(Interface):
"""Auto-include any ZCML in the dependencies of this package."""
@@ -20,35 +19,56 @@
required=True,
)
+def includeZCMLGroup(_context, dist, info, zcmlgroup, override=False):
+ includable_zcml = list(info.get(zcmlgroup, []))
+ debug_includes(dist, zcmlgroup, includable_zcml)
+ for dotted_name in includable_zcml:
+ includable_package = resolve(dotted_name)
+ if override:
+ includeOverrides(_context, zcmlgroup, includable_package)
+ else:
+ include(_context, zcmlgroup, includable_package)
+
def autoIncludeOverridesDirective(_context, package):
dist = distributionForPackage(package)
- info = IncludeFinder(dist).includableInfo(['overrides.zcml'])
+ info = DependencyFinder(dist).includableInfo(['overrides.zcml'])
+ includeZCMLGroup(_context, dist, info, 'overrides.zcml', override=True)
- 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'])
+ info = DependencyFinder(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)
+ includeZCMLGroup(_context, dist, info, 'meta.zcml')
+ includeZCMLGroup(_context, dist, info, 'configure.zcml')
- 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)
+class IIncludePluginsDirective(Interface):
+ """Auto-include any ZCML in the dependencies of this 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]
+ package = GlobalObject(
+ title=u"Package to auto-include for",
+ description=u"""
+ Auto-include all dependencies of this package.
+ """,
+ required=True,
+ )
+
+def includePluginsDirective(_context, package):
+ dist = distributionForPackage(package)
+ dotted_name = package.__name__
+ info = PluginFinder(dotted_name).includableInfo(['meta.zcml',
+ 'configure.zcml',
+ 'overrides.zcml'])
+
+ includeZCMLGroup(_context, dist, info, 'meta.zcml')
+ includeZCMLGroup(_context, dist, info, 'configure.zcml')
+ includeZCMLGroup(_context, dist, info, 'overrides.zcml', override=True)
+
+import warnings
+def deprecatedAutoIncludeDirective(_context, package):
+ warnings.warn("The <autoinclude> directive is deprecated and will be removed in z3c.autoinclude 0.3. Please use <includeDependencies> instead.", DeprecationWarning, stacklevel=2)
+ autoIncludeDirective(_context, package)
+
+def deprecatedAutoIncludeOverridesDirective(_context, package):
+ warnings.warn("The <autoincludeOverrides> directive is deprecated and will be removed in z3c.autoinclude 0.3. Please use <includeDependenciesOverrides> instead.", DeprecationWarning, stacklevel=2)
+ autoIncludeOverridesDirective(_context, package)
+
More information about the Checkins
mailing list