diff --git a/CHANGES.rst b/CHANGES.rst index 13ef88a..d0b7d04 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -23,6 +23,11 @@ it properly lets the default Sphinx theme be used (by setting both ``default.css`` and ``layout.html`` to empty values). +- Ignore bad eggs in the documentation working set. Previously they + would raise internal errors without any explanation. Now, they log a + warning pinpointing the bad egg. Fixes `issue 6 + `_. + 1.0.0 (2013-02-23) ================== diff --git a/setup.py b/setup.py index 24b4ec6..d8b23d5 100755 --- a/setup.py +++ b/setup.py @@ -70,6 +70,7 @@ def read(*rnames): ], extras_require={ 'test': [ + 'zope.testing', 'zope.testrunner', ], }, diff --git a/src/z3c/recipe/sphinxdoc/__init__.py b/src/z3c/recipe/sphinxdoc/__init__.py index 23d2245..4f3c5ac 100644 --- a/src/z3c/recipe/sphinxdoc/__init__.py +++ b/src/z3c/recipe/sphinxdoc/__init__.py @@ -12,6 +12,7 @@ # ############################################################################## from __future__ import print_function + import sys import os from os.path import join, dirname, isdir, normpath @@ -28,6 +29,8 @@ # Py3 location changed. from urllib.request import urlopen +logger = __import__('logging').getLogger(__name__) + confPyTemplate = """ templates_path = ['%(templatesDir)s'] source_suffix = '.rst' @@ -91,7 +94,7 @@ def install(self): eggs, workingSet = self.egg.working_set() if 'doc-eggs' in self.options: eggs = self.options['doc-eggs'].split() - docs = [workingSet.find(pkg_resources.Requirement.parse(spec)) + docs = [(workingSet.find(pkg_resources.Requirement.parse(spec)), spec) for spec in eggs] # Create parts directory for configuration files. @@ -105,8 +108,12 @@ def install(self): projectsData = {} # Preserve projectsData for testing self._projectsData = projectsData - #for each egg listed as a buildout option, create a configuration space. - for doc in docs: + # for each egg listed as a buildout option, create a configuration space. + for doc, egg_name in docs: + if not doc: + logger.warning("Specified egg '%s' cannot be resolved, ignoring.", egg_name) + continue + partDir = join(installDir, doc.project_name) if not isdir(partDir): os.mkdir(partDir) diff --git a/src/z3c/recipe/sphinxdoc/tests/test_sphinxdoc.py b/src/z3c/recipe/sphinxdoc/tests/test_sphinxdoc.py index 4580a2b..d744041 100644 --- a/src/z3c/recipe/sphinxdoc/tests/test_sphinxdoc.py +++ b/src/z3c/recipe/sphinxdoc/tests/test_sphinxdoc.py @@ -12,6 +12,7 @@ # ############################################################################## +import logging import shutil import subprocess import sys @@ -38,10 +39,21 @@ def setUp(self): os.chdir(self.tmpdir) os.mkdir('bin') + # Sphinx likes to install handlers when you call its main methods. + # If we pass -W (and we do) those turn warnings into hard errors. + # This pollutes later tests. So be sure to tear those down. + self.handlers_before_set_up = logging.getLogger().handlers[:] + def tearDown(self): os.chdir(self.here) shutil.rmtree(self.tmpdir) + root_logger = logging.getLogger() + for handler in root_logger.handlers[:]: + root_logger.removeHandler(handler) + for handler in self.handlers_before_set_up: + root_logger.addHandler(handler) + def _makeOne(self, name='docs', options=None): opts = { 'doc-eggs': 'z3c.recipe.sphinxdoc', @@ -96,8 +108,8 @@ def test_openfile_falls_to_url(self): self.assertRaises(IOError, docs.openfile, 'file:///') - def test_basic_install(self): - docs, _ = self._makeOne() + def test_basic_install(self, options=None): + docs, _ = self._makeOne(options=options) docs.install() self._check_conf_py_can_be_evald() conf = self._read_conf_file() @@ -126,6 +138,22 @@ def test_basic_install(self): sphinxdoc.main(docs._projectsData, argv=['docs'], exit_on_error=True) + def test_install_with_bad_doc_egg(self): + from zope.testing.loggingsupport import InstalledHandler + handler = InstalledHandler('z3c.recipe.sphinxdoc') + self.addCleanup(handler.uninstall) + + self.test_basic_install(options={ + 'doc-eggs': 'z3c.recipe.sphinxdoc this.egg.is.not.installed' + }) + + log_records = handler.records + self.assertEqual(1, len(log_records)) + record = log_records[0] + self.assertEqual("WARNING", record.levelname) + self.assertEqual("Specified egg 'this.egg.is.not.installed' cannot be resolved, ignoring.", + record.getMessage()) + def test_override_css(self): docs, _ = self._makeOne(options={'default.css': EMPTY_FILE}) docs.install()