2008-01-27 14:23:25 -06:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
|
|
sphinx.application
|
|
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
Sphinx application object.
|
|
|
|
|
|
|
|
Gracefully adapted from the TextPress system by Armin.
|
|
|
|
|
2009-01-03 04:57:07 -06:00
|
|
|
:copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
|
2008-12-27 05:19:17 -06:00
|
|
|
:license: BSD, see LICENSE for details.
|
2008-01-27 14:23:25 -06:00
|
|
|
"""
|
|
|
|
|
|
|
|
import sys
|
2009-02-19 16:22:36 -06:00
|
|
|
import types
|
2008-08-06 08:04:14 -05:00
|
|
|
import posixpath
|
2009-07-13 14:28:01 -05:00
|
|
|
from os import path
|
2008-11-08 09:28:01 -06:00
|
|
|
from cStringIO import StringIO
|
2008-01-27 14:23:25 -06:00
|
|
|
|
|
|
|
from docutils import nodes
|
|
|
|
from docutils.parsers.rst import directives, roles
|
|
|
|
|
2009-02-12 05:46:25 -06:00
|
|
|
import sphinx
|
2009-07-13 11:02:42 -05:00
|
|
|
from sphinx import package_dir, locale
|
2009-07-05 05:24:27 -05:00
|
|
|
from sphinx.roles import XRefRole
|
2009-02-12 05:46:25 -06:00
|
|
|
from sphinx.config import Config
|
2009-02-24 12:15:39 -06:00
|
|
|
from sphinx.errors import SphinxError, SphinxWarning, ExtensionError
|
2009-07-13 09:59:45 -05:00
|
|
|
from sphinx.domains import all_domains
|
2009-02-12 05:53:48 -06:00
|
|
|
from sphinx.builders import BUILTIN_BUILDERS
|
2009-02-18 12:55:57 -06:00
|
|
|
from sphinx.directives import GenericDesc, Target, additional_xref_types
|
2009-07-13 11:02:42 -05:00
|
|
|
from sphinx.environment import BuildEnvironment, SphinxStandaloneReader
|
2009-06-16 16:38:47 -05:00
|
|
|
from sphinx.util import pycompat
|
2009-02-19 14:56:34 -06:00
|
|
|
from sphinx.util.tags import Tags
|
2009-02-17 09:36:30 -06:00
|
|
|
from sphinx.util.compat import Directive, directive_dwim
|
2009-02-12 05:46:25 -06:00
|
|
|
from sphinx.util.console import bold
|
|
|
|
|
|
|
|
|
2009-02-24 12:15:39 -06:00
|
|
|
# Directive is either new-style or old-style
|
|
|
|
clstypes = (type, types.ClassType)
|
|
|
|
|
2008-03-09 16:31:52 -05:00
|
|
|
# List of all known core events. Maps name to arguments description.
|
2008-01-27 14:23:25 -06:00
|
|
|
events = {
|
2008-02-01 14:44:17 -06:00
|
|
|
'builder-inited': '',
|
2008-11-09 04:56:40 -06:00
|
|
|
'env-purge-doc': 'env, docname',
|
2008-10-16 14:04:45 -05:00
|
|
|
'source-read': 'docname, source text',
|
2008-08-04 10:57:26 -05:00
|
|
|
'doctree-read': 'the doctree before being pickled',
|
|
|
|
'missing-reference': 'env, node, contnode',
|
|
|
|
'doctree-resolved': 'doctree, docname',
|
|
|
|
'env-updated': 'env',
|
2008-05-31 11:14:36 -05:00
|
|
|
'html-page-context': 'pagename, context, doctree or None',
|
2008-08-06 08:04:14 -05:00
|
|
|
'build-finished': 'exception',
|
2008-01-27 14:23:25 -06:00
|
|
|
}
|
|
|
|
|
2008-06-05 03:58:43 -05:00
|
|
|
CONFIG_FILENAME = 'conf.py'
|
2009-07-13 11:02:42 -05:00
|
|
|
ENV_PICKLE_FILENAME = 'environment.pickle'
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2009-02-24 12:15:39 -06:00
|
|
|
|
2008-02-23 09:24:30 -06:00
|
|
|
class Sphinx(object):
|
2008-01-27 14:23:25 -06:00
|
|
|
|
2008-05-02 05:32:08 -05:00
|
|
|
def __init__(self, srcdir, confdir, outdir, doctreedir, buildername,
|
2009-02-17 12:19:09 -06:00
|
|
|
confoverrides, status, warning=sys.stderr, freshenv=False,
|
2009-02-19 14:56:34 -06:00
|
|
|
warningiserror=False, tags=None):
|
2008-01-27 14:23:25 -06:00
|
|
|
self.next_listener_id = 0
|
2009-02-24 06:34:21 -06:00
|
|
|
self._extensions = {}
|
2008-01-27 14:23:25 -06:00
|
|
|
self._listeners = {}
|
2008-11-29 12:56:58 -06:00
|
|
|
self.builderclasses = BUILTIN_BUILDERS.copy()
|
2008-01-27 14:23:25 -06:00
|
|
|
self.builder = None
|
2009-07-13 11:02:42 -05:00
|
|
|
self.env = None
|
2008-01-27 14:23:25 -06:00
|
|
|
|
2008-08-04 17:20:44 -05:00
|
|
|
self.srcdir = srcdir
|
|
|
|
self.confdir = confdir
|
|
|
|
self.outdir = outdir
|
|
|
|
self.doctreedir = doctreedir
|
2008-01-27 14:23:25 -06:00
|
|
|
|
2008-11-08 09:28:01 -06:00
|
|
|
if status is None:
|
|
|
|
self._status = StringIO()
|
|
|
|
self.quiet = True
|
|
|
|
else:
|
|
|
|
self._status = status
|
|
|
|
self.quiet = False
|
2009-02-17 12:19:09 -06:00
|
|
|
|
2008-11-08 09:28:01 -06:00
|
|
|
if warning is None:
|
|
|
|
self._warning = StringIO()
|
|
|
|
else:
|
|
|
|
self._warning = warning
|
2008-02-09 17:09:36 -06:00
|
|
|
self._warncount = 0
|
2009-02-17 12:19:09 -06:00
|
|
|
self.warningiserror = warningiserror
|
2008-01-27 14:23:25 -06:00
|
|
|
|
2008-03-09 16:31:52 -05:00
|
|
|
self._events = events.copy()
|
|
|
|
|
2009-03-15 12:36:00 -05:00
|
|
|
# say hello to the world
|
|
|
|
self.info(bold('Running Sphinx v%s' % sphinx.__released__))
|
|
|
|
|
2008-11-08 09:28:01 -06:00
|
|
|
# status code for command-line application
|
|
|
|
self.statuscode = 0
|
|
|
|
|
2008-01-27 14:23:25 -06:00
|
|
|
# read config
|
2009-02-19 14:56:34 -06:00
|
|
|
self.tags = Tags(tags)
|
|
|
|
self.config = Config(confdir, CONFIG_FILENAME, confoverrides, self.tags)
|
2008-01-27 14:23:25 -06:00
|
|
|
|
|
|
|
# load all extension modules
|
2008-05-24 13:03:56 -05:00
|
|
|
for extension in self.config.extensions:
|
2008-01-27 14:23:25 -06:00
|
|
|
self.setup_extension(extension)
|
2008-04-06 12:38:55 -05:00
|
|
|
# the config file itself can be an extension
|
2008-05-24 13:03:56 -05:00
|
|
|
if self.config.setup:
|
2008-04-06 12:38:55 -05:00
|
|
|
self.config.setup(self)
|
2008-01-27 14:23:25 -06:00
|
|
|
|
2008-06-04 15:25:27 -05:00
|
|
|
# now that we know all config values, collect them from conf.py
|
|
|
|
self.config.init_values()
|
|
|
|
|
2009-07-13 11:02:42 -05:00
|
|
|
# set up translation infrastructure
|
|
|
|
self._init_i18n()
|
|
|
|
# set up the build environment
|
|
|
|
self._init_env(freshenv)
|
|
|
|
# set up the builder
|
|
|
|
self._init_builder(buildername)
|
|
|
|
|
|
|
|
def _init_i18n(self):
|
|
|
|
"""
|
|
|
|
Load translated strings from the configured localedirs if
|
|
|
|
enabled in the configuration.
|
|
|
|
"""
|
|
|
|
if self.config.language is not None:
|
|
|
|
self.info(bold('loading translations [%s]... ' %
|
|
|
|
self.config.language), nonl=True)
|
|
|
|
locale_dirs = [None, path.join(package_dir, 'locale')] + \
|
|
|
|
[path.join(self.srcdir, x) for x in self.config.locale_dirs]
|
|
|
|
else:
|
|
|
|
locale_dirs = []
|
|
|
|
self.translator, has_translation = locale.init(locale_dirs,
|
|
|
|
self.config.language)
|
|
|
|
if self.config.language is not None:
|
|
|
|
if has_translation:
|
|
|
|
self.info('done')
|
|
|
|
else:
|
|
|
|
self.info('locale not available')
|
2009-07-13 09:59:45 -05:00
|
|
|
|
2009-07-13 11:02:42 -05:00
|
|
|
def _init_env(self, freshenv):
|
|
|
|
if freshenv:
|
|
|
|
self.env = BuildEnvironment(self.srcdir, self.doctreedir,
|
|
|
|
self.config)
|
|
|
|
self.env.find_files(self.config)
|
2009-07-13 13:53:11 -05:00
|
|
|
for domain in all_domains.keys():
|
|
|
|
self.env.domains[domain] = all_domains[domain](self.env)
|
2009-07-13 11:02:42 -05:00
|
|
|
else:
|
|
|
|
try:
|
|
|
|
self.info(bold('loading pickled environment... '), nonl=True)
|
|
|
|
self.env = BuildEnvironment.frompickle(self.config,
|
|
|
|
path.join(self.doctreedir, ENV_PICKLE_FILENAME))
|
2009-07-13 13:53:11 -05:00
|
|
|
self.env.domains = {}
|
|
|
|
for domain in all_domains.keys():
|
|
|
|
# this can raise if the data version doesn't fit
|
|
|
|
self.env.domains[domain] = all_domains[domain](self.env)
|
2009-07-13 11:02:42 -05:00
|
|
|
self.info('done')
|
|
|
|
except Exception, err:
|
|
|
|
if type(err) is IOError and err.errno == 2:
|
|
|
|
self.info('not yet created')
|
|
|
|
else:
|
|
|
|
self.info('failed: %s' % err)
|
2009-07-13 13:53:11 -05:00
|
|
|
return self._init_env(freshenv=True)
|
|
|
|
|
2009-07-13 11:02:42 -05:00
|
|
|
self.env.set_warnfunc(self.warn)
|
|
|
|
|
|
|
|
def _init_builder(self, buildername):
|
2008-01-27 14:23:25 -06:00
|
|
|
if buildername is None:
|
2009-07-13 11:02:42 -05:00
|
|
|
print >>self._status, 'No builder selected, using default: html'
|
2008-01-27 14:23:25 -06:00
|
|
|
buildername = 'html'
|
|
|
|
if buildername not in self.builderclasses:
|
2008-08-06 08:04:14 -05:00
|
|
|
raise SphinxError('Builder name %s not registered' % buildername)
|
2008-01-27 14:23:25 -06:00
|
|
|
|
|
|
|
builderclass = self.builderclasses[buildername]
|
2008-11-29 12:56:58 -06:00
|
|
|
if isinstance(builderclass, tuple):
|
|
|
|
# builtin builder
|
|
|
|
mod, cls = builderclass
|
|
|
|
builderclass = getattr(
|
|
|
|
__import__('sphinx.builders.' + mod, None, None, [cls]), cls)
|
2009-07-13 11:02:42 -05:00
|
|
|
self.builder = builderclass(self)
|
2008-01-27 14:23:25 -06:00
|
|
|
self.emit('builder-inited')
|
|
|
|
|
2008-08-06 08:04:14 -05:00
|
|
|
def build(self, all_files, filenames):
|
|
|
|
try:
|
|
|
|
if all_files:
|
|
|
|
self.builder.build_all()
|
|
|
|
elif filenames:
|
|
|
|
self.builder.build_specific(filenames)
|
|
|
|
else:
|
|
|
|
self.builder.build_update()
|
|
|
|
except Exception, err:
|
|
|
|
self.emit('build-finished', err)
|
|
|
|
raise
|
|
|
|
else:
|
|
|
|
self.emit('build-finished', None)
|
2009-02-14 17:07:05 -06:00
|
|
|
self.builder.cleanup()
|
2008-08-06 08:04:14 -05:00
|
|
|
|
2009-03-05 03:06:18 -06:00
|
|
|
def warn(self, message, location=None, prefix='WARNING: '):
|
2009-03-05 02:21:35 -06:00
|
|
|
warntext = location and '%s: %s%s\n' % (location, prefix, message) or \
|
|
|
|
'%s%s\n' % (prefix, message)
|
2009-02-17 12:19:09 -06:00
|
|
|
if self.warningiserror:
|
2009-03-05 02:21:35 -06:00
|
|
|
raise SphinxWarning(warntext)
|
2008-02-09 17:09:36 -06:00
|
|
|
self._warncount += 1
|
2008-12-15 04:35:27 -06:00
|
|
|
try:
|
2009-03-05 02:21:35 -06:00
|
|
|
self._warning.write(warntext)
|
2008-12-15 04:35:27 -06:00
|
|
|
except UnicodeEncodeError:
|
2009-05-17 05:31:39 -05:00
|
|
|
encoding = getattr(self._warning, 'encoding', 'ascii') or 'ascii'
|
2009-03-05 02:21:35 -06:00
|
|
|
self._warning.write(warntext.encode(encoding, 'replace'))
|
2008-01-27 14:23:25 -06:00
|
|
|
|
|
|
|
def info(self, message='', nonl=False):
|
2008-12-15 04:35:27 -06:00
|
|
|
try:
|
2008-01-27 14:23:25 -06:00
|
|
|
self._status.write(message)
|
2008-12-15 04:35:27 -06:00
|
|
|
except UnicodeEncodeError:
|
2009-05-17 05:31:39 -05:00
|
|
|
encoding = getattr(self._status, 'encoding', 'ascii') or 'ascii'
|
2008-12-15 04:35:27 -06:00
|
|
|
self._status.write(message.encode(encoding, 'replace'))
|
|
|
|
if not nonl:
|
|
|
|
self._status.write('\n')
|
2008-01-27 14:23:25 -06:00
|
|
|
self._status.flush()
|
|
|
|
|
|
|
|
# general extensibility interface
|
|
|
|
|
|
|
|
def setup_extension(self, extension):
|
2009-02-24 06:34:21 -06:00
|
|
|
"""Import and setup a Sphinx extension module. No-op if called twice."""
|
|
|
|
if extension in self._extensions:
|
|
|
|
return
|
2008-01-27 14:23:25 -06:00
|
|
|
try:
|
|
|
|
mod = __import__(extension, None, None, ['setup'])
|
|
|
|
except ImportError, err:
|
2009-01-10 14:23:39 -06:00
|
|
|
raise ExtensionError('Could not import extension %s' % extension,
|
|
|
|
err)
|
2009-06-15 10:31:29 -05:00
|
|
|
if not hasattr(mod, 'setup'):
|
|
|
|
self.warn('extension %r has no setup() function; is it really '
|
|
|
|
'a Sphinx extension module?' % extension)
|
|
|
|
else:
|
2008-01-27 14:23:25 -06:00
|
|
|
mod.setup(self)
|
2009-02-24 06:34:21 -06:00
|
|
|
self._extensions[extension] = mod
|
2008-01-27 14:23:25 -06:00
|
|
|
|
|
|
|
def import_object(self, objname, source=None):
|
|
|
|
"""Import an object from a 'module.name' string."""
|
|
|
|
try:
|
|
|
|
module, name = objname.rsplit('.', 1)
|
|
|
|
except ValueError, err:
|
|
|
|
raise ExtensionError('Invalid full object name %s' % objname +
|
2009-01-10 14:23:39 -06:00
|
|
|
(source and ' (needed for %s)' % source or ''),
|
|
|
|
err)
|
2008-01-27 14:23:25 -06:00
|
|
|
try:
|
|
|
|
return getattr(__import__(module, None, None, [name]), name)
|
|
|
|
except ImportError, err:
|
|
|
|
raise ExtensionError('Could not import %s' % module +
|
2009-01-10 14:23:39 -06:00
|
|
|
(source and ' (needed for %s)' % source or ''),
|
|
|
|
err)
|
2008-01-27 14:23:25 -06:00
|
|
|
except AttributeError, err:
|
|
|
|
raise ExtensionError('Could not find %s' % objname +
|
2009-01-10 14:23:39 -06:00
|
|
|
(source and ' (needed for %s)' % source or ''),
|
|
|
|
err)
|
2008-01-27 14:23:25 -06:00
|
|
|
|
|
|
|
# event interface
|
|
|
|
|
|
|
|
def _validate_event(self, event):
|
|
|
|
event = intern(event)
|
2008-03-09 16:31:52 -05:00
|
|
|
if event not in self._events:
|
2008-01-27 14:23:25 -06:00
|
|
|
raise ExtensionError('Unknown event name: %s' % event)
|
|
|
|
|
|
|
|
def connect(self, event, callback):
|
|
|
|
self._validate_event(event)
|
|
|
|
listener_id = self.next_listener_id
|
|
|
|
if event not in self._listeners:
|
|
|
|
self._listeners[event] = {listener_id: callback}
|
|
|
|
else:
|
|
|
|
self._listeners[event][listener_id] = callback
|
|
|
|
self.next_listener_id += 1
|
|
|
|
return listener_id
|
|
|
|
|
|
|
|
def disconnect(self, listener_id):
|
2008-08-04 15:16:18 -05:00
|
|
|
for event in self._listeners.itervalues():
|
2008-01-27 14:23:25 -06:00
|
|
|
event.pop(listener_id, None)
|
|
|
|
|
|
|
|
def emit(self, event, *args):
|
|
|
|
result = []
|
|
|
|
if event in self._listeners:
|
|
|
|
for _, callback in self._listeners[event].iteritems():
|
|
|
|
result.append(callback(self, *args))
|
|
|
|
return result
|
|
|
|
|
2008-08-04 04:54:45 -05:00
|
|
|
def emit_firstresult(self, event, *args):
|
|
|
|
for result in self.emit(event, *args):
|
|
|
|
if result is not None:
|
|
|
|
return result
|
|
|
|
return None
|
|
|
|
|
2008-01-27 14:23:25 -06:00
|
|
|
# registering addon parts
|
|
|
|
|
|
|
|
def add_builder(self, builder):
|
|
|
|
if not hasattr(builder, 'name'):
|
2009-01-10 14:23:39 -06:00
|
|
|
raise ExtensionError('Builder class %s has no "name" attribute'
|
|
|
|
% builder)
|
2008-01-27 14:23:25 -06:00
|
|
|
if builder.name in self.builderclasses:
|
2008-11-29 12:56:58 -06:00
|
|
|
if isinstance(self.builderclasses[builder.name], tuple):
|
|
|
|
raise ExtensionError('Builder %r is a builtin builder' %
|
|
|
|
builder.name)
|
|
|
|
else:
|
2009-01-10 14:23:39 -06:00
|
|
|
raise ExtensionError(
|
|
|
|
'Builder %r already exists (in module %s)' % (
|
2008-11-29 12:56:58 -06:00
|
|
|
builder.name, self.builderclasses[builder.name].__module__))
|
2008-01-27 14:23:25 -06:00
|
|
|
self.builderclasses[builder.name] = builder
|
|
|
|
|
2009-02-19 09:15:36 -06:00
|
|
|
def add_config_value(self, name, default, rebuild):
|
2008-06-05 03:58:43 -05:00
|
|
|
if name in self.config.values:
|
2008-03-09 16:31:52 -05:00
|
|
|
raise ExtensionError('Config value %r already present' % name)
|
2009-02-19 09:15:36 -06:00
|
|
|
if rebuild in (False, True):
|
|
|
|
rebuild = rebuild and 'env' or ''
|
|
|
|
self.config.values[name] = (default, rebuild)
|
2008-01-27 14:23:25 -06:00
|
|
|
|
2008-03-09 16:31:52 -05:00
|
|
|
def add_event(self, name):
|
|
|
|
if name in self._events:
|
|
|
|
raise ExtensionError('Event %r already present' % name)
|
|
|
|
self._events[name] = ''
|
|
|
|
|
2008-08-05 05:25:40 -05:00
|
|
|
def add_node(self, node, **kwds):
|
2008-01-27 14:23:25 -06:00
|
|
|
nodes._add_node_class_names([node.__name__])
|
2008-08-05 05:25:40 -05:00
|
|
|
for key, val in kwds.iteritems():
|
|
|
|
try:
|
|
|
|
visit, depart = val
|
|
|
|
except ValueError:
|
2009-01-10 14:23:39 -06:00
|
|
|
raise ExtensionError('Value for key %r must be a '
|
|
|
|
'(visit, depart) function tuple' % key)
|
2008-08-05 05:25:40 -05:00
|
|
|
if key == 'html':
|
2008-11-29 12:56:58 -06:00
|
|
|
from sphinx.writers.html import HTMLTranslator as translator
|
2008-08-05 05:25:40 -05:00
|
|
|
elif key == 'latex':
|
2008-11-29 12:56:58 -06:00
|
|
|
from sphinx.writers.latex import LaTeXTranslator as translator
|
2008-08-05 05:25:40 -05:00
|
|
|
elif key == 'text':
|
2008-11-29 12:56:58 -06:00
|
|
|
from sphinx.writers.text import TextTranslator as translator
|
2008-08-05 05:25:40 -05:00
|
|
|
else:
|
|
|
|
# ignore invalid keys for compatibility
|
|
|
|
continue
|
|
|
|
setattr(translator, 'visit_'+node.__name__, visit)
|
|
|
|
if depart:
|
|
|
|
setattr(translator, 'depart_'+node.__name__, depart)
|
2008-01-27 14:23:25 -06:00
|
|
|
|
2009-02-17 09:36:30 -06:00
|
|
|
def add_directive(self, name, obj, content=None, arguments=None, **options):
|
2009-02-19 16:22:36 -06:00
|
|
|
if isinstance(obj, clstypes) and issubclass(obj, Directive):
|
2009-02-17 09:36:30 -06:00
|
|
|
if content or arguments or options:
|
|
|
|
raise ExtensionError('when adding directive classes, no '
|
|
|
|
'additional arguments may be given')
|
|
|
|
directives.register_directive(name, directive_dwim(obj))
|
|
|
|
else:
|
|
|
|
obj.content = content
|
|
|
|
obj.arguments = arguments
|
|
|
|
obj.options = options
|
|
|
|
directives.register_directive(name, obj)
|
2008-01-27 14:23:25 -06:00
|
|
|
|
|
|
|
def add_role(self, name, role):
|
2009-02-21 10:25:48 -06:00
|
|
|
roles.register_local_role(name, role)
|
2008-03-09 13:18:41 -05:00
|
|
|
|
2009-01-22 13:01:01 -06:00
|
|
|
def add_generic_role(self, name, nodeclass):
|
2009-02-21 10:36:38 -06:00
|
|
|
# don't use roles.register_generic_role because it uses
|
|
|
|
# register_canonical_role
|
|
|
|
role = roles.GenericRole(name, nodeclass)
|
|
|
|
roles.register_local_role(name, role)
|
2009-01-22 13:01:01 -06:00
|
|
|
|
2009-06-29 10:04:33 -05:00
|
|
|
def add_domain(self, domain):
|
2009-07-13 09:59:45 -05:00
|
|
|
if domain.name in all_domains:
|
2009-06-29 10:04:33 -05:00
|
|
|
raise ExtensionError('domain %s already registered' % domain.name)
|
2009-07-13 09:59:45 -05:00
|
|
|
all_domains[domain.name] = domain
|
2009-06-29 10:04:33 -05:00
|
|
|
|
2008-03-28 13:45:32 -05:00
|
|
|
def add_description_unit(self, directivename, rolename, indextemplate='',
|
|
|
|
parse_node=None, ref_nodeclass=None):
|
2009-01-10 14:23:39 -06:00
|
|
|
additional_xref_types[directivename] = (rolename, indextemplate,
|
|
|
|
parse_node)
|
2009-02-19 16:09:20 -06:00
|
|
|
directives.register_directive(directivename,
|
|
|
|
directive_dwim(GenericDesc))
|
2009-07-05 05:24:27 -05:00
|
|
|
# XXX support more options?
|
2009-07-13 10:27:43 -05:00
|
|
|
role_func = XRefRole(innernodeclass=ref_nodeclass)
|
2009-06-30 09:16:46 -05:00
|
|
|
roles.register_local_role(rolename, role_func)
|
2008-03-28 13:45:32 -05:00
|
|
|
|
|
|
|
def add_crossref_type(self, directivename, rolename, indextemplate='',
|
|
|
|
ref_nodeclass=None):
|
|
|
|
additional_xref_types[directivename] = (rolename, indextemplate, None)
|
2009-02-19 16:09:20 -06:00
|
|
|
directives.register_directive(directivename, directive_dwim(Target))
|
2009-07-05 05:24:27 -05:00
|
|
|
# XXX support more options
|
2009-07-13 10:27:43 -05:00
|
|
|
role_func = XRefRole(innernodeclass=ref_nodeclass)
|
2009-06-30 09:16:46 -05:00
|
|
|
roles.register_local_role(rolename, role_func)
|
2008-04-13 03:20:11 -05:00
|
|
|
|
|
|
|
def add_transform(self, transform):
|
|
|
|
SphinxStandaloneReader.transforms.append(transform)
|
2008-04-13 13:16:55 -05:00
|
|
|
|
2008-08-06 08:04:14 -05:00
|
|
|
def add_javascript(self, filename):
|
2008-11-29 12:56:58 -06:00
|
|
|
from sphinx.builders.html import StandaloneHTMLBuilder
|
2008-08-06 08:04:14 -05:00
|
|
|
StandaloneHTMLBuilder.script_files.append(
|
|
|
|
posixpath.join('_static', filename))
|
2009-06-16 14:05:20 -05:00
|
|
|
|
|
|
|
def add_stylesheet(self, filename):
|
|
|
|
from sphinx.builders.html import StandaloneHTMLBuilder
|
|
|
|
StandaloneHTMLBuilder.css_files.append(
|
|
|
|
posixpath.join('_static', filename))
|
2008-08-06 08:04:14 -05:00
|
|
|
|
2008-11-30 12:58:29 -06:00
|
|
|
def add_lexer(self, alias, lexer):
|
|
|
|
from sphinx.highlighting import lexers
|
|
|
|
if lexers is None:
|
|
|
|
return
|
|
|
|
lexers[alias] = lexer
|
|
|
|
|
2009-02-17 09:36:30 -06:00
|
|
|
def add_autodocumenter(self, cls):
|
|
|
|
from sphinx.ext import autodoc
|
|
|
|
autodoc.add_documenter(cls)
|
|
|
|
self.add_directive('auto' + cls.objtype, autodoc.AutoDirective)
|
|
|
|
|
2009-02-19 15:54:34 -06:00
|
|
|
def add_autodoc_attrgetter(self, type, getter):
|
|
|
|
from sphinx.ext import autodoc
|
|
|
|
autodoc.AutoDirective._special_attrgetters[type] = getter
|
|
|
|
|
2008-04-13 13:16:55 -05:00
|
|
|
|
|
|
|
class TemplateBridge(object):
|
|
|
|
"""
|
2008-05-04 03:28:00 -05:00
|
|
|
This class defines the interface for a "template bridge", that is, a class
|
|
|
|
that renders templates given a template name and a context.
|
2008-04-13 13:16:55 -05:00
|
|
|
"""
|
|
|
|
|
2009-02-21 10:17:21 -06:00
|
|
|
def init(self, builder, theme=None, dirs=None):
|
2008-04-13 13:16:55 -05:00
|
|
|
"""
|
2009-02-21 10:17:21 -06:00
|
|
|
Called by the builder to initialize the template system.
|
|
|
|
|
|
|
|
*builder* is the builder object; you'll probably want to look at the
|
|
|
|
value of ``builder.config.templates_path``.
|
|
|
|
|
|
|
|
*theme* is a :class:`sphinx.theming.Theme` object or None; in the latter
|
|
|
|
case, *dirs* can be list of fixed directories to look for templates.
|
2008-04-13 13:16:55 -05:00
|
|
|
"""
|
|
|
|
raise NotImplementedError('must be implemented in subclasses')
|
|
|
|
|
|
|
|
def newest_template_mtime(self):
|
|
|
|
"""
|
|
|
|
Called by the builder to determine if output files are outdated
|
|
|
|
because of template changes. Return the mtime of the newest template
|
|
|
|
file that was changed. The default implementation returns ``0``.
|
|
|
|
"""
|
|
|
|
return 0
|
|
|
|
|
|
|
|
def render(self, template, context):
|
|
|
|
"""
|
2009-02-15 00:19:48 -06:00
|
|
|
Called by the builder to render a template given as a filename with a
|
|
|
|
specified context (a Python dictionary).
|
|
|
|
"""
|
|
|
|
raise NotImplementedError('must be implemented in subclasses')
|
|
|
|
|
|
|
|
def render_string(self, template, context):
|
|
|
|
"""
|
|
|
|
Called by the builder to render a template given as a string with a
|
|
|
|
specified context (a Python dictionary).
|
2008-04-13 13:16:55 -05:00
|
|
|
"""
|
|
|
|
raise NotImplementedError('must be implemented in subclasses')
|