From 1aed5875f76bf2be9ae67f963251117c159d1a04 Mon Sep 17 00:00:00 2001 From: Ryan Kelly Date: Mon, 11 Jul 2011 09:54:13 +1000 Subject: [PATCH] sphinx plugin: add some docs and extra sanity checks --- hyde/ext/plugins/sphinx.py | 57 +++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/hyde/ext/plugins/sphinx.py b/hyde/ext/plugins/sphinx.py index 78cefe0..05d0c7f 100644 --- a/hyde/ext/plugins/sphinx.py +++ b/hyde/ext/plugins/sphinx.py @@ -3,7 +3,7 @@ Sphinx plugin. This plugin lets you easily include sphinx-generated documentation as part -of your Hyde site. +of your Hyde site. It is simultaneously a Hyde plugin and a Sphinx plugin. """ # We need absolute import so that we can import the main "sphinx" @@ -18,6 +18,7 @@ import tempfile from hyde.plugin import Plugin from hyde.fs import File, Folder from hyde.model import Expando +from hyde.ext.plugins.meta import MetaPlugin as _MetaPlugin import sphinx from sphinx.builders.html import JSONHTMLBuilder @@ -85,6 +86,12 @@ class SphinxPlugin(Plugin): return self._sphinx_config def begin_site(self): + """Event hook for when site processing begins. + + This hook checks that the site is correctly configured for building + with sphinx, and adjusts any sphinx-controlled resources so that + hyde will process them correctly. + """ settings = self.settings if settings.sanity_check: self._sanity_check() @@ -102,10 +109,14 @@ class SphinxPlugin(Plugin): resource.meta.default_block = None def begin_text_resource(self,resource,text): - """If this is a sphinx input file, replace it with the generated docs. + """Event hook for processing an individual resource. + + If the input resource is a sphinx input file, this method will replace + replace the text of the file with the sphinx-generated documentation. - This method will replace the text of the file with the sphinx-generated - documentation, lazily running sphinx if it has not yet been called. + Sphinx itself is run lazily the first time this method is called. + This means that if no sphinx-related resources need updating, then + we entirely avoid running sphinx. """ suffix = self.sphinx_config.get("source_suffix",".rst") if not resource.source_file.path.endswith(suffix): @@ -132,6 +143,10 @@ class SphinxPlugin(Plugin): return "\n".join(output) def site_complete(self): + """Event hook for when site processing ends. + + This simply cleans up any temorary build file. + """ if self.sphinx_build_dir is not None: self.sphinx_build_dir.delete() @@ -173,6 +188,19 @@ class SphinxPlugin(Plugin): logger.error("sphinx conf.py file.") logger.info("(set sphinx.sanity_check=false to disable this check)") raise RuntimeError("sphinx is not configured correctly") + # Check that I am *before* the other plugins, + # with the possible exception of MetaPlugin + for plugin in self.site.plugins: + if plugin is self: + break + if not isinstance(plugin,_MetaPlugin): + logger.error("The sphinx plugin is installed after the") + logger.error("plugin %r.",plugin.__class__.__name__) + logger.error("It's quite likely that this will break things.") + logger.error("Please move the sphinx plugin to the top") + logger.error("of the plugins list.") + logger.info("(sphinx.sanity_check=false to disable this check)") + raise RuntimeError("sphinx is not configured correctly") def _run_sphinx(self): """Run sphinx to generate the necessary output files. @@ -194,6 +222,13 @@ class SphinxPlugin(Plugin): raise RuntimeError("sphinx build failed") def _get_sphinx_output(self,resource): + """Get the sphinx output for a given resource. + + This returns a dict mapping block names to HTML text fragments. + The most important fragment is "body" which contains the main text + of the document. The other fragments are for things like navigation, + related pages and so-on. + """ relpath = File(resource.relative_path) relpath = relpath.parent.child(relpath.name_without_extension+".fjson") with open(self.sphinx_build_dir.child(relpath),"rb") as f: @@ -202,12 +237,26 @@ class SphinxPlugin(Plugin): class HydeJSONHTMLBuilder(JSONHTMLBuilder): + """A slightly-customised JSONHTMLBuilder, for use by Hyde. + + This is a Sphinx builder that serilises the generated HTML fragments into + a JSON docuent, so they can be later retrieved and dealt with at will. + + The only customistion we do over the standard JSONHTMLBuilder is to + reference documents with a .html suffix, so that internal link will + work correctly once things have been processed by Hyde. + """ name = "hyde_json" def get_target_uri(self, docname, typ=None): return docname + ".html" def setup(app): + """Sphinx plugin setup function. + + This function allows the module to act as a Sphinx plugin as well as a + Hyde plugin. It simply registers the HydeJSONHTMLBuilder class. + """ app.add_builder(HydeJSONHTMLBuilder)