diff --git a/CHANGES.rst b/CHANGES.rst
index 2ffb8b3..937e63f 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -10,6 +10,10 @@ Breaking changes:
New features:
+- When environment variable ``Z3C_AUTOINCLUDE_DEBUG`` is set,
+ log which packages are being automatically included.
+ Do this in a form that you can copy to a ``configure.zcml`` file.
+
- Add support for Python 3.8.
Bug fixes:
diff --git a/src/z3c/autoinclude/api.py b/src/z3c/autoinclude/api.py
index 31cbd91..8cb6ca8 100644
--- a/src/z3c/autoinclude/api.py
+++ b/src/z3c/autoinclude/api.py
@@ -2,6 +2,7 @@
DEP_KEY = 'Z3C_AUTOINCLUDE_DEPENDENCIES_DISABLED'
PLUGIN_KEY = 'Z3C_AUTOINCLUDE_PLUGINS_DISABLED'
+DEBUG_KEY = 'Z3C_AUTOINCLUDE_DEBUG'
def dependencies_disabled():
@@ -13,7 +14,7 @@ def disable_dependencies():
def enable_dependencies():
- del os.environ[DEP_KEY]
+ os.environ.pop(DEP_KEY, None)
def plugins_disabled():
@@ -25,4 +26,16 @@ def disable_plugins():
def enable_plugins():
- del os.environ[PLUGIN_KEY]
+ os.environ.pop(PLUGIN_KEY, None)
+
+
+def debug_enabled():
+ return DEBUG_KEY in os.environ
+
+
+def disable_debug():
+ os.environ.pop(DEBUG_KEY, None)
+
+
+def enable_debug():
+ os.environ[DEBUG_KEY] = 'True'
diff --git a/src/z3c/autoinclude/api.txt b/src/z3c/autoinclude/api.txt
new file mode 100644
index 0000000..62cc511
--- /dev/null
+++ b/src/z3c/autoinclude/api.txt
@@ -0,0 +1,71 @@
+=============
+API functions
+=============
+
+The ``api.py`` module has some helpful functions.
+
+
+Plugins
+=======
+
+We can disable and enable autoincluding the plugins::
+
+ >>> from z3c.autoinclude import api
+ >>> api.plugins_disabled()
+ False
+ >>> api.disable_plugins()
+ >>> api.plugins_disabled()
+ True
+ >>> api.disable_plugins() # called twice to see if this breaks
+ >>> api.plugins_disabled()
+ True
+ >>> api.enable_plugins()
+ >>> api.plugins_disabled()
+ False
+ >>> api.enable_plugins() # called twice to see if this breaks
+ >>> api.plugins_disabled()
+ False
+
+
+Dependencies
+============
+
+We can disable and enable autoincluding the dependencies::
+
+ >>> from z3c.autoinclude import api
+ >>> api.dependencies_disabled()
+ False
+ >>> api.disable_dependencies()
+ >>> api.dependencies_disabled()
+ True
+ >>> api.disable_dependencies() # called twice to see if this breaks
+ >>> api.dependencies_disabled()
+ True
+ >>> api.enable_dependencies()
+ >>> api.dependencies_disabled()
+ False
+ >>> api.enable_dependencies() # called twice to see if this breaks
+ >>> api.dependencies_disabled()
+ False
+
+
+Debug
+=====
+
+We can disable and enable the debug report of autoincluded packages::
+
+ >>> from z3c.autoinclude import api
+ >>> api.debug_enabled()
+ False
+ >>> api.enable_debug()
+ >>> api.debug_enabled()
+ True
+ >>> api.enable_debug() # called twice to see if this breaks
+ >>> api.debug_enabled()
+ True
+ >>> api.disable_debug()
+ >>> api.debug_enabled()
+ False
+ >>> api.disable_debug() # called twice to see if this breaks
+ >>> api.debug_enabled()
+ False
diff --git a/src/z3c/autoinclude/dependency.py b/src/z3c/autoinclude/dependency.py
index 2c0b1ae..fdeb012 100644
--- a/src/z3c/autoinclude/dependency.py
+++ b/src/z3c/autoinclude/dependency.py
@@ -4,8 +4,10 @@
from pkg_resources import resource_exists
from pkg_resources import get_provider
from pkg_resources import get_distribution
+from z3c.autoinclude.api import debug_enabled
from z3c.autoinclude.utils import DistributionManager
from z3c.autoinclude.utils import ZCMLInfo
+from z3c.autoinclude.utils import create_report
logger = logging.getLogger("z3c.autoinclude")
@@ -42,6 +44,15 @@ def includableInfo(self, zcml_to_look_for):
)
if os.path.isfile(candidate_path):
result[candidate].append(dotted_name)
+
+ if debug_enabled():
+ report = create_report(result)
+ if "overrides.zcml" in zcml_to_look_for:
+ report.insert(0, "includeDependenciesOverrides found in zcml of %s." % self.context.project_name)
+ else:
+ report.insert(0, "includeDependencies found in zcml of %s." % self.context.project_name)
+ logger.info("\n".join(report))
+
return result
diff --git a/src/z3c/autoinclude/plugin.py b/src/z3c/autoinclude/plugin.py
index 5d7d5a1..75aace4 100644
--- a/src/z3c/autoinclude/plugin.py
+++ b/src/z3c/autoinclude/plugin.py
@@ -1,10 +1,16 @@
+import logging
import os
from pkg_resources import iter_entry_points
from pkg_resources import resource_filename
+from z3c.autoinclude.api import debug_enabled
+from z3c.autoinclude.utils import create_report
from z3c.autoinclude.utils import DistributionManager
from z3c.autoinclude.utils import ZCMLInfo
+logger = logging.getLogger("z3c.autoinclude")
+
+
class PluginFinder(object):
def __init__(self, platform_dottedname):
self.dottedname = platform_dottedname
@@ -18,6 +24,15 @@ def includableInfo(self, zcml_to_look_for):
groups = zcml_to_include(plugin_dottedname, zcml_to_look_for)
for zcml_group in groups:
includable_info[zcml_group].append(plugin_dottedname)
+
+ if debug_enabled():
+ report = create_report(includable_info)
+ if "overrides.zcml" in zcml_to_look_for:
+ report.insert(0, "includePluginsOverrides found in zcml of %s." % self.dottedname)
+ else:
+ report.insert(0, "includePlugins found in zcml of %s." % self.dottedname)
+ logger.info("\n".join(report))
+
return includable_info
diff --git a/src/z3c/autoinclude/tests/tests.py b/src/z3c/autoinclude/tests/tests.py
index ad75e38..7491f78 100644
--- a/src/z3c/autoinclude/tests/tests.py
+++ b/src/z3c/autoinclude/tests/tests.py
@@ -118,7 +118,14 @@ def test_suite():
from pprint import pprint
- suite = doctest.DocFileSuite(
+ simple_suite = doctest.DocFileSuite(
+ '../api.txt',
+ globs={'pprint': pprint},
+ checker=IgnoreCaseChecker(),
+ optionflags=doctest.ELLIPSIS,
+ )
+
+ advanced_suite = doctest.DocFileSuite(
'../utils.txt',
'../dependency.txt',
'../plugin.txt',
@@ -129,7 +136,7 @@ def test_suite():
optionflags=doctest.ELLIPSIS,
)
- return unittest.TestSuite((suite,))
+ return unittest.TestSuite((simple_suite, advanced_suite))
if __name__ == '__main__':
diff --git a/src/z3c/autoinclude/utils.py b/src/z3c/autoinclude/utils.py
index 9502789..81fdffc 100644
--- a/src/z3c/autoinclude/utils.py
+++ b/src/z3c/autoinclude/utils.py
@@ -43,6 +43,12 @@ def __init__(self, zcml_to_look_for):
for zcml_group in zcml_to_look_for:
self[zcml_group] = []
+ def __bool__(self):
+ return any(self.values())
+
+ # For Python 2:
+ __nonzero__ = __bool__
+
def subpackageDottedNames(package_path, ns_dottedname=None):
# we do not look for subpackages in zipped eggs
@@ -206,3 +212,29 @@ def find_packages(where='.', exclude=()):
out = [item for item in out if not fnmatchcase(item, pat)]
return out
+
+
+def create_report(info):
+ """Create a report with a list of auto included zcml."""
+ if not info:
+ # Return a comment. Maybe someone wants to automatically include this
+ # in a zcml file, so make it a proper xml comment.
+ return [""]
+ report = []
+ # Try to report meta.zcml first.
+ filenames = list(info)
+ meta = "meta.zcml"
+ if meta in filenames:
+ filenames.remove(meta)
+ filenames.insert(0, meta)
+ for filename in filenames:
+ dotted_names = info[filename]
+ for dotted_name in dotted_names:
+ if filename == "overrides.zcml":
+ line = ' ' % (dotted_name, filename)
+ elif filename == "configure.zcml":
+ line = ' '% dotted_name
+ else:
+ line = ' '% (dotted_name, filename)
+ report.append(line)
+ return report
diff --git a/src/z3c/autoinclude/utils.txt b/src/z3c/autoinclude/utils.txt
index 0256647..8eac153 100644
--- a/src/z3c/autoinclude/utils.txt
+++ b/src/z3c/autoinclude/utils.txt
@@ -45,3 +45,54 @@ package contained within it::
>>> import F.G
>>> distributionForPackage(F.G) # doctest: +IGNORECASE
SiblingPackage 0.0 (...SiblingPackage-0.0...egg)
+
+We have a helper class ZCMLInfo which is a dictionary which automatically gets keys.
+Perhaps a defaultdict would work too now, but let's not change the class at this time.
+
+ >>> from z3c.autoinclude.utils import ZCMLInfo
+ >>> info = ZCMLInfo(['meta.zcml', 'configure.zcml'])
+ >>> sorted(info.keys())
+ ['configure.zcml', 'meta.zcml']
+ >>> list(info.values())
+ [[], []]
+
+When no values are filled in, the boolean should be False.
+
+ >>> bool(info)
+ False
+
+We can create a report of the auto included zcml.
+
+ >>> from z3c.autoinclude.utils import create_report
+ >>> create_report(info)
+ ['']
+
+We add information:
+
+ >>> info['configure.zcml'].append('sample_package')
+ >>> bool(info)
+ True
+ >>> create_report(info)
+ [' ']
+ >>> info['configure.zcml'].append('package2')
+ >>> info['meta.zcml'].append('meta_package')
+ >>> report = create_report(info)
+ >>> len(report)
+ 3
+ >>> report[0]
+ ' '
+ >>> report[1]
+ ' '
+ >>> report[2]
+ ' '
+
+We can only add known filenames:
+
+ >>> info['overrides.zcml'].append('overrides_package')
+ Traceback (most recent call last):
+ ...
+ KeyError: 'overrides.zcml'
+ >>> overrides = ZCMLInfo(['overrides.zcml'])
+ >>> overrides['overrides.zcml'].append('overrides_package')
+ >>> create_report(overrides)
+ [' ']