mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix the serializing and changes builders, and really test them.
This commit is contained in:
@@ -367,11 +367,15 @@ class TemplateBridge(object):
|
||||
that renders templates given a template name and a context.
|
||||
"""
|
||||
|
||||
def init(self, builder):
|
||||
def init(self, builder, theme=None, dirs=None):
|
||||
"""
|
||||
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``.
|
||||
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.
|
||||
"""
|
||||
raise NotImplementedError('must be implemented in subclasses')
|
||||
|
||||
|
||||
@@ -72,23 +72,16 @@ class Builder(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
def init_templates(self):
|
||||
def create_template_bridge(self):
|
||||
"""
|
||||
Initialize the theme and template system.
|
||||
|
||||
Call this method from init() if you need templates in your builder.
|
||||
Return the template bridge configured.
|
||||
"""
|
||||
from sphinx.theming import Theme
|
||||
Theme.init_themes(self)
|
||||
self.theme = Theme(self.config.html_theme)
|
||||
|
||||
if self.config.template_bridge:
|
||||
self.templates = self.app.import_object(
|
||||
self.config.template_bridge, 'template_bridge setting')()
|
||||
else:
|
||||
from sphinx.jinja2glue import BuiltinTemplateLoader
|
||||
self.templates = BuiltinTemplateLoader()
|
||||
self.templates.init(self)
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
"""
|
||||
|
||||
@@ -15,7 +15,8 @@ from os import path
|
||||
from cgi import escape
|
||||
|
||||
from sphinx import package_dir
|
||||
from sphinx.util import ensuredir, os_path
|
||||
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
|
||||
|
||||
@@ -27,7 +28,10 @@ class ChangesBuilder(Builder):
|
||||
name = 'changes'
|
||||
|
||||
def init(self):
|
||||
self.init_templates()
|
||||
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
|
||||
@@ -44,11 +48,13 @@ class ChangesBuilder(Builder):
|
||||
apichanges = []
|
||||
otherchanges = {}
|
||||
if version not in self.env.versionchanges:
|
||||
self.info(bold('no changes in this version.'))
|
||||
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'):
|
||||
@@ -129,12 +135,15 @@ class ChangesBuilder(Builder):
|
||||
f.write(self.templates.render('changes/rstsource.html', ctx))
|
||||
finally:
|
||||
f.close()
|
||||
shutil.copyfile(path.join(package_dir, 'themes', 'default',
|
||||
'static', 'default.css'),
|
||||
path.join(self.outdir, 'default.css'))
|
||||
shutil.copyfile(path.join(package_dir, 'themes', 'basic',
|
||||
'static', 'basic.css'),
|
||||
path.join(self.outdir, 'basic.css'))
|
||||
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)
|
||||
|
||||
@@ -32,8 +32,9 @@ from docutils.readers.doctree import Reader as DoctreeReader
|
||||
|
||||
from sphinx import package_dir, __version__
|
||||
from sphinx.util import SEP, os_path, relative_uri, ensuredir, \
|
||||
movefile, ustrftime
|
||||
movefile, ustrftime, copy_static_entry
|
||||
from sphinx.search import js_index
|
||||
from sphinx.theming import Theme
|
||||
from sphinx.builders import Builder, ENV_PICKLE_FILENAME
|
||||
from sphinx.application import SphinxError
|
||||
from sphinx.highlighting import PygmentsBridge
|
||||
@@ -95,12 +96,20 @@ class StandaloneHTMLBuilder(Builder):
|
||||
if path.isfile(jsfile):
|
||||
self.script_files.append('_static/translations.js')
|
||||
|
||||
def init_templates(self):
|
||||
Theme.init_themes(self)
|
||||
self.theme = Theme(self.config.html_theme)
|
||||
self.create_template_bridge()
|
||||
self.templates.init(self, self.theme)
|
||||
|
||||
def init_highlighter(self):
|
||||
# determine Pygments style and create the highlighter
|
||||
if self.config.pygments_style is not None:
|
||||
style = self.config.pygments_style
|
||||
else:
|
||||
elif self.theme:
|
||||
style = self.theme.get_confstr('theme', 'pygments_style', 'none')
|
||||
else:
|
||||
style = 'sphinx'
|
||||
self.highlighter = PygmentsBridge('html', style)
|
||||
|
||||
def init_translator_class(self):
|
||||
@@ -219,8 +228,10 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
if self.config.html_style is not None:
|
||||
stylename = self.config.html_style
|
||||
else:
|
||||
elif self.theme:
|
||||
stylename = self.theme.get_confstr('theme', 'stylesheet')
|
||||
else:
|
||||
stylename = 'default.css'
|
||||
|
||||
self.globalcontext = dict(
|
||||
embedded = self.embedded,
|
||||
@@ -246,9 +257,11 @@ class StandaloneHTMLBuilder(Builder):
|
||||
logo = logo,
|
||||
favicon = favicon,
|
||||
)
|
||||
self.globalcontext.update(
|
||||
('theme_' + key, val) for (key, val) in
|
||||
self.theme.get_options(self.config.html_theme_options).iteritems())
|
||||
if self.theme:
|
||||
self.globalcontext.update(
|
||||
('theme_' + key, val) for (key, val) in
|
||||
self.theme.get_options(
|
||||
self.config.html_theme_options).iteritems())
|
||||
self.globalcontext.update(self.config.html_context)
|
||||
|
||||
def get_doc_context(self, docname, body, metatags):
|
||||
@@ -509,10 +522,13 @@ class StandaloneHTMLBuilder(Builder):
|
||||
shutil.copyfile(jsfile, path.join(self.outdir, '_static',
|
||||
'translations.js'))
|
||||
# then, copy over all user-supplied static files
|
||||
staticdirnames = [path.join(themepath, 'static')
|
||||
for themepath in self.theme.get_dirchain()[::-1]] + \
|
||||
[path.join(self.confdir, spath)
|
||||
for spath in self.config.html_static_path]
|
||||
if self.theme:
|
||||
staticdirnames = [path.join(themepath, 'static')
|
||||
for themepath in self.theme.get_dirchain()[::-1]]
|
||||
else:
|
||||
staticdirnames = []
|
||||
staticdirnames += [path.join(self.confdir, spath)
|
||||
for spath in self.config.html_static_path]
|
||||
for staticdirname in staticdirnames:
|
||||
if not path.isdir(staticdirname):
|
||||
self.warn('static directory %r does not exist' % staticdirname)
|
||||
@@ -522,23 +538,8 @@ class StandaloneHTMLBuilder(Builder):
|
||||
continue
|
||||
fullname = path.join(staticdirname, filename)
|
||||
targetname = path.join(self.outdir, '_static', filename)
|
||||
if path.isfile(fullname):
|
||||
if fullname.lower().endswith('_t'):
|
||||
# templated!
|
||||
fsrc = open(fullname, 'rb')
|
||||
fdst = open(targetname[:-2], 'wb')
|
||||
fdst.write(self.templates.render_string(
|
||||
fsrc.read(), self.globalcontext))
|
||||
fsrc.close()
|
||||
fdst.close()
|
||||
else:
|
||||
shutil.copyfile(fullname, targetname)
|
||||
elif path.isdir(fullname):
|
||||
if filename in self.config.exclude_dirnames:
|
||||
continue
|
||||
if path.exists(targetname):
|
||||
shutil.rmtree(targetname)
|
||||
shutil.copytree(fullname, targetname)
|
||||
copy_static_entry(fullname, targetname, self,
|
||||
self.globalcontext)
|
||||
# last, copy logo file (handled differently)
|
||||
if self.config.html_logo:
|
||||
logobase = path.basename(self.config.html_logo)
|
||||
@@ -563,7 +564,8 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
def cleanup(self):
|
||||
# clean up theme stuff
|
||||
self.theme.cleanup()
|
||||
if self.theme:
|
||||
self.theme.cleanup()
|
||||
|
||||
def post_process_images(self, doctree):
|
||||
"""
|
||||
@@ -733,9 +735,12 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
|
||||
'image/gif', 'image/jpeg']
|
||||
|
||||
def init(self):
|
||||
self.config_hash = ''
|
||||
self.tags_hash = ''
|
||||
self.theme = None # no theme necessary
|
||||
self.templates = None # no template bridge necessary
|
||||
self.init_translator_class()
|
||||
self.init_highlighter()
|
||||
self.templates = None # no template bridge necessary
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
if docname == 'index':
|
||||
|
||||
@@ -34,13 +34,17 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
|
||||
|
||||
# TemplateBridge interface
|
||||
|
||||
def init(self, builder):
|
||||
self.theme = builder.theme
|
||||
# create a chain of paths to search:
|
||||
# the theme's own dir and its bases' dirs
|
||||
chain = self.theme.get_dirchain()
|
||||
# then the theme parent paths (XXX doc)
|
||||
chain.extend(self.theme.themepath)
|
||||
def init(self, builder, theme=None, dirs=None):
|
||||
# create a chain of paths to search
|
||||
if theme:
|
||||
# the theme's own dir and its bases' dirs
|
||||
chain = theme.get_dirchain()
|
||||
# then the theme parent paths
|
||||
chain.extend(theme.themepath)
|
||||
elif dirs:
|
||||
chain = list(dirs)
|
||||
else:
|
||||
chain = []
|
||||
|
||||
# prepend explicit template paths
|
||||
self.templatepathlen = len(builder.config.templates_path)
|
||||
|
||||
@@ -30,11 +30,11 @@ class Theme(object):
|
||||
"""
|
||||
Represents the theme chosen in the configuration.
|
||||
"""
|
||||
themes = {}
|
||||
|
||||
@classmethod
|
||||
def init_themes(cls, builder):
|
||||
"""Search all theme paths for available themes."""
|
||||
cls.themes = {}
|
||||
|
||||
cls.themepath = list(builder.config.html_theme_path)
|
||||
cls.themepath.append(
|
||||
path.join(path.abspath(path.dirname(__file__)), 'themes'))
|
||||
|
||||
@@ -14,6 +14,7 @@ import re
|
||||
import sys
|
||||
import time
|
||||
import types
|
||||
import shutil
|
||||
import fnmatch
|
||||
import tempfile
|
||||
import posixpath
|
||||
@@ -392,6 +393,25 @@ def movefile(source, dest):
|
||||
os.rename(source, dest)
|
||||
|
||||
|
||||
def copy_static_entry(source, target, builder, context={}):
|
||||
if path.isfile(source):
|
||||
if source.lower().endswith('_t'):
|
||||
# templated!
|
||||
fsrc = open(source, 'rb')
|
||||
fdst = open(target[:-2], 'wb')
|
||||
fdst.write(builder.templates.render_string(fsrc.read(), context))
|
||||
fsrc.close()
|
||||
fdst.close()
|
||||
else:
|
||||
shutil.copyfile(source, target)
|
||||
elif path.isdir(source):
|
||||
if filename in builder.config.exclude_dirnames:
|
||||
return
|
||||
if path.exists(target):
|
||||
shutil.rmtree(target)
|
||||
shutil.copytree(source, target)
|
||||
|
||||
|
||||
# monkey-patch Node.traverse to get more speed
|
||||
# traverse() is called so many times during a build that it saves
|
||||
# on average 20-25% overall build time!
|
||||
|
||||
@@ -16,6 +16,7 @@ source_suffix = '.txt'
|
||||
|
||||
project = 'Sphinx <Tests>'
|
||||
copyright = '2008, Georg Brandl & Team'
|
||||
# If this is changed, remember to update the versionchanges!
|
||||
version = '0.6'
|
||||
release = '0.6alpha1'
|
||||
today_fmt = '%B %d, %Y'
|
||||
|
||||
@@ -84,13 +84,13 @@ Tables
|
||||
Version markup
|
||||
--------------
|
||||
|
||||
.. versionadded:: 0.5
|
||||
.. versionadded:: 0.6
|
||||
Some funny **stuff**.
|
||||
|
||||
.. versionchanged:: 0.5
|
||||
.. versionchanged:: 0.6
|
||||
Even more funny stuff.
|
||||
|
||||
.. deprecated:: 0.4
|
||||
.. deprecated:: 0.6
|
||||
Boring stuff.
|
||||
|
||||
|
||||
|
||||
@@ -239,6 +239,10 @@ def test_latex(app):
|
||||
|
||||
# just let the remaining ones run for now
|
||||
|
||||
@with_app(buildername='pickle')
|
||||
def test_pickle(app):
|
||||
app.builder.build_all()
|
||||
|
||||
@with_app(buildername='linkcheck')
|
||||
def test_linkcheck(app):
|
||||
app.builder.build_all()
|
||||
@@ -247,6 +251,14 @@ def test_linkcheck(app):
|
||||
def test_text(app):
|
||||
app.builder.build_all()
|
||||
|
||||
@with_app(buildername='changes', cleanenv=True)
|
||||
@with_app(buildername='htmlhelp')
|
||||
def test_htmlhelp(app):
|
||||
app.builder.build_all()
|
||||
|
||||
@with_app(buildername='qthelp')
|
||||
def test_qthelp(app):
|
||||
app.builder.build_all()
|
||||
|
||||
@with_app(buildername='changes')
|
||||
def test_changes(app):
|
||||
app.builder.build_all()
|
||||
|
||||
Reference in New Issue
Block a user