diff options
author | Daniel Neuhäuser <ich@danielneuhaeuser.de> | 2010-08-15 13:50:54 +0200 |
---|---|---|
committer | Daniel Neuhäuser <ich@danielneuhaeuser.de> | 2010-08-15 13:50:54 +0200 |
commit | 948304bf7d217ecd5fcf8a63339f5b1cf9e84308 (patch) | |
tree | 5e395d913bec89e56cb392af86b519c7418093e8 /sphinx/builders/websupport.py | |
parent | 568bb63f0d73c8c7228374d228ea72f0d70c0ccf (diff) | |
parent | 06d50c45aad20ff9e14fabd68cfbe6e0c2c0992c (diff) | |
download | sphinx-git-948304bf7d217ecd5fcf8a63339f5b1cf9e84308.tar.gz |
Automated merge with ssh://bitbucket.org/DasIch/sphinx-version-tracking
Diffstat (limited to 'sphinx/builders/websupport.py')
-rw-r--r-- | sphinx/builders/websupport.py | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/sphinx/builders/websupport.py b/sphinx/builders/websupport.py new file mode 100644 index 000000000..283cff4fc --- /dev/null +++ b/sphinx/builders/websupport.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +""" + sphinx.builders.websupport + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Builder for the web support package. + + :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import cPickle as pickle +from os import path +from cgi import escape +import os +import posixpath +import shutil + +from docutils.io import StringOutput +from docutils.utils import Reporter + +from sphinx.util.osutil import os_path, relative_uri, ensuredir, copyfile +from sphinx.util.jsonimpl import dumps as dump_json +from sphinx.util.websupport import is_commentable +from sphinx.builders.html import StandaloneHTMLBuilder +from sphinx.writers.websupport import WebSupportTranslator +from sphinx.environment import WarningStream +from sphinx.versioning import add_uids, merge_doctrees + + +class WebSupportBuilder(StandaloneHTMLBuilder): + """ + Builds documents for the web support package. + """ + name = 'websupport' + out_suffix = '.fpickle' + + def init(self): + StandaloneHTMLBuilder.init(self) + for root, dirs, files in os.walk(self.doctreedir): + for fn in files: + fp = path.join(root, fn) + if fp.endswith('.doctree'): + copyfile(fp, fp + '.old') + + def init_translator_class(self): + self.translator_class = WebSupportTranslator + + def get_old_doctree(self, docname): + fp = self.env.doc2path(docname, self.doctreedir, '.doctree.old') + try: + f = open(fp, 'rb') + try: + doctree = pickle.load(f) + finally: + f.close() + except IOError: + return None + doctree.settings.env = self.env + doctree.reporter = Reporter(self.env.doc2path(docname), 2, 5, + stream=WarningStream(self.env._warnfunc)) + return doctree + + def resave_doctree(self, docname, doctree): + # make it picklable, save the reporter, it's needed later. + reporter = doctree.reporter + doctree.reporter = None + doctree.settings.warning_stream = None + doctree.settings.env = None + doctree.settings.record_dependencies = None + + fp = self.env.doc2path(docname, self.doctreedir, '.doctree') + f = open(fp, 'wb') + try: + pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL) + finally: + f.close() + + doctree.reporter = reporter + + def write_doc(self, docname, doctree): + destination = StringOutput(encoding='utf-8') + doctree.settings = self.docsettings + + old_doctree = self.get_old_doctree(docname) + if old_doctree: + list(merge_doctrees(old_doctree, doctree, is_commentable)) + else: + list(add_uids(doctree, is_commentable)) + self.resave_doctree(docname, doctree) + + self.cur_docname = docname + self.secnumbers = self.env.toc_secnumbers.get(docname, {}) + self.imgpath = '/' + posixpath.join(self.app.staticdir, '_images') + self.post_process_images(doctree) + self.dlpath = '/' + posixpath.join(self.app.staticdir, '_downloads') + self.docwriter.write(doctree, destination) + self.docwriter.assemble_parts() + body = self.docwriter.parts['fragment'] + metatags = self.docwriter.clean_meta + + ctx = self.get_doc_context(docname, body, metatags) + self.index_page(docname, doctree, ctx.get('title', '')) + self.handle_page(docname, ctx, event_arg=doctree) + + def get_target_uri(self, docname, typ=None): + return docname + + def load_indexer(self, docnames): + self.indexer = self.app.search + self.indexer.init_indexing(changed=docnames) + + def handle_page(self, pagename, addctx, templatename='page.html', + outfilename=None, event_arg=None): + # This is mostly copied from StandaloneHTMLBuilder. However, instead + # of rendering the template and saving the html, create a context + # dict and pickle it. + ctx = self.globalcontext.copy() + ctx['pagename'] = pagename + + def pathto(otheruri, resource=False, + baseuri=self.get_target_uri(pagename)): + if not resource: + otheruri = self.get_target_uri(otheruri) + return relative_uri(baseuri, otheruri) or '#' + else: + return '/' + posixpath.join(self.app.staticdir, otheruri) + ctx['pathto'] = pathto + ctx['hasdoc'] = lambda name: name in self.env.all_docs + ctx['encoding'] = encoding = self.config.html_output_encoding + ctx['toctree'] = lambda **kw: self._get_local_toctree(pagename, **kw) + self.add_sidebars(pagename, ctx) + ctx.update(addctx) + + self.app.emit('html-page-context', pagename, templatename, + ctx, event_arg) + + # Create a dict that will be pickled and used by webapps. + css = '<link rel="stylesheet" href="%s" type=text/css />' % \ + pathto('_static/pygments.css', 1) + doc_ctx = {'body': ctx.get('body', ''), + 'title': ctx.get('title', ''), + 'css': css, + 'js': self._make_js(ctx)} + # Partially render the html template to proved a more useful ctx. + template = self.templates.environment.get_template(templatename) + template_module = template.make_module(ctx) + if hasattr(template_module, 'sidebar'): + doc_ctx['sidebar'] = template_module.sidebar() + if hasattr(template_module, 'relbar'): + doc_ctx['relbar'] = template_module.relbar() + + if not outfilename: + outfilename = path.join(self.outdir, 'pickles', + os_path(pagename) + self.out_suffix) + + ensuredir(path.dirname(outfilename)) + f = open(outfilename, 'wb') + try: + pickle.dump(doc_ctx, f, pickle.HIGHEST_PROTOCOL) + finally: + f.close() + + # if there is a source file, copy the source file for the + # "show source" link + if ctx.get('sourcename'): + source_name = path.join(self.app.builddir, self.app.staticdir, + '_sources', os_path(ctx['sourcename'])) + ensuredir(path.dirname(source_name)) + copyfile(self.env.doc2path(pagename), source_name) + + def handle_finish(self): + StandaloneHTMLBuilder.handle_finish(self) + directories = ['_images', '_static'] + for directory in directories: + src = path.join(self.outdir, directory) + dst = path.join(self.app.builddir, self.app.staticdir, directory) + if path.isdir(src): + if path.isdir(dst): + shutil.rmtree(dst) + shutil.move(src, dst) + + for root, dirs, files in os.walk(self.doctreedir): + for fn in files: + fp = path.join(root, fn) + if fp.endswith('.doctree.old'): + os.remove(fp) + + def dump_search_index(self): + self.indexer.finish_indexing() + + def _make_js(self, ctx): + def make_script(file): + path = ctx['pathto'](file, 1) + return '<script type="text/javascript" src="%s"></script>' % path + + opts = { + 'URL_ROOT': ctx.get('url_root', ''), + 'VERSION': ctx['release'], + 'COLLAPSE_INDEX': False, + 'FILE_SUFFIX': '', + 'HAS_SOURCE': ctx['has_source'] + } + scripts = [make_script(file) for file in ctx['script_files']] + scripts.append(make_script('_static/websupport.js')) + return '\n'.join([ + '<script type="text/javascript">' + 'var DOCUMENTATION_OPTIONS = %s;' % dump_json(opts), + '</script>' + ] + scripts) |