/usr/share/pyshared/z3c/autoinclude/dependency.txt is in python-z3c.autoinclude 0.3.5-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | 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.
``APackage`` depends on ``BCPackage``
``BCPackage`` depends on ``SiblingPackage``
Given the distribution for the project named ``APackage``, we can ask
for the requirements of that distribution::
>>> import a
>>> from z3c.autoinclude.utils import distributionForPackage
>>> a_dist = distributionForPackage(a)
>>> 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 a DependencyFinder::
>>> from z3c.autoinclude.dependency import DependencyFinder
>>> a_include_finder = DependencyFinder(a_dist)
>>> b_include_finder = DependencyFinder(b_dist)
>>> import x.y.z
>>> xyz_dist = distributionForPackage(x.y.z)
>>> xyz_include_finder = DependencyFinder(xyz_dist)
>>> import F.G
>>> sibling_dist = distributionForPackage(F.G)
>>> 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 packages::
>>> 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
a namespace package)::
>>> xyz_include_finder.namespaceDottedNames()
['x', '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'],
'overrides.zcml': []}
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'], 'silly.zcml': []}
Note that it will not catch DistributionNotFound errors::
>>> package_includes('NonexistentPackage')
Traceback (most recent call last):
...
DistributionNotFound: NonexistentPackage
|