diff options
Diffstat (limited to 'sphinx/builders/changes.py')
| -rw-r--r-- | sphinx/builders/changes.py | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py new file mode 100644 index 00000000..e07b06d8 --- /dev/null +++ b/sphinx/builders/changes.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +""" + sphinx.builders.changes + ~~~~~~~~~~~~~~~~~~~~~~~ + + Changelog builder. + + :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import codecs +import shutil +from os import path +from cgi import escape + +from sphinx import package_dir +from sphinx.util import ensuredir, os_path, copy_static_entry +from sphinx.theming import Theme +from sphinx.builders import Builder +from sphinx.util.console import bold + + +class ChangesBuilder(Builder): + """ + Write a summary with all versionadded/changed directives. + """ + name = 'changes' + + def init(self): + self.create_template_bridge() + Theme.init_themes(self) + self.theme = Theme('default') + self.templates.init(self, self.theme) + + def get_outdated_docs(self): + return self.outdir + + typemap = { + 'versionadded': 'added', + 'versionchanged': 'changed', + 'deprecated': 'deprecated', + } + + def write(self, *ignored): + version = self.config.version + libchanges = {} + apichanges = [] + otherchanges = {} + if version not in self.env.versionchanges: + self.info(bold('no changes in version %s.' % version)) + return + self.info(bold('writing summary file...')) + for type, docname, lineno, module, descname, content in \ + self.env.versionchanges[version]: + if isinstance(descname, tuple): + descname = descname[0] + ttext = self.typemap[type] + context = content.replace('\n', ' ') + if descname and docname.startswith('c-api'): + if not descname: + continue + if context: + entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, + context) + else: + entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext) + apichanges.append((entry, docname, lineno)) + elif descname or module: + if not module: + module = _('Builtins') + if not descname: + descname = _('Module level') + if context: + entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, + context) + else: + entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext) + libchanges.setdefault(module, []).append((entry, docname, + lineno)) + else: + if not context: + continue + entry = '<i>%s:</i> %s' % (ttext.capitalize(), context) + title = self.env.titles[docname].astext() + otherchanges.setdefault((docname, title), []).append( + (entry, docname, lineno)) + + ctx = { + 'project': self.config.project, + 'version': version, + 'docstitle': self.config.html_title, + 'shorttitle': self.config.html_short_title, + 'libchanges': sorted(libchanges.iteritems()), + 'apichanges': sorted(apichanges), + 'otherchanges': sorted(otherchanges.iteritems()), + 'show_sphinx': self.config.html_show_sphinx, + } + f = codecs.open(path.join(self.outdir, 'index.html'), 'w', 'utf8') + try: + f.write(self.templates.render('changes/frameset.html', ctx)) + finally: + f.close() + f = codecs.open(path.join(self.outdir, 'changes.html'), 'w', 'utf8') + try: + f.write(self.templates.render('changes/versionchanges.html', ctx)) + finally: + f.close() + + hltext = ['.. versionadded:: %s' % version, + '.. versionchanged:: %s' % version, + '.. deprecated:: %s' % version] + + def hl(no, line): + line = '<a name="L%s"> </a>' % no + escape(line) + for x in hltext: + if x in line: + line = '<span class="hl">%s</span>' % line + break + return line + + self.info(bold('copying source files...')) + for docname in self.env.all_docs: + f = codecs.open(self.env.doc2path(docname), 'r', 'latin1') + lines = f.readlines() + targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html' + ensuredir(path.dirname(targetfn)) + f = codecs.open(targetfn, 'w', 'latin1') + try: + text = ''.join(hl(i+1, line) for (i, line) in enumerate(lines)) + ctx = { + 'filename': self.env.doc2path(docname, None), + 'text': text + } + f.write(self.templates.render('changes/rstsource.html', ctx)) + finally: + f.close() + themectx = dict(('theme_' + key, val) for (key, val) in + self.theme.get_options({}).iteritems()) + copy_static_entry(path.join(package_dir, 'themes', 'default', + 'static', 'default.css_t'), + path.join(self.outdir, 'default.css_t'), + self, themectx) + copy_static_entry(path.join(package_dir, 'themes', 'basic', + 'static', 'basic.css'), + path.join(self.outdir, 'basic.css'), self) + + def hl(self, text, version): + text = escape(text) + for directive in ['versionchanged', 'versionadded', 'deprecated']: + text = text.replace('.. %s:: %s' % (directive, version), + '<b>.. %s:: %s</b>' % (directive, version)) + return text + + def finish(self): + pass |
