========================================= 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``. 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')) # doctest: +IGNORECASE [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:: >>> import foo >>> from z3c.autoinclude.utils import distributionForPackage >>> foo_dist = distributionForPackage(foo) >>> 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 >>> from zope.configuration import xmlconfig >>> from pkg_resources import resource_filename >>> from testdirective.zcml import test_log >>> 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; it extends ``base2``s namespace. >>> from testdirective.zcml import clear_test_log >>> clear_test_log() >>> import base2 >>> from pkg_resources import Requirement, resource_filename >>> req = Requirement.parse('base2') >>> import os >>> filename = resource_filename(req, os.path.join('base2', 'configure.zcml')) >>> dummy = xmlconfig.file(filename, package=base2) >>> pprint(test_log) [u'base2.plug has been loaded']