summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2009-09-04 00:17:41 +0200
committerGeorg Brandl <georg@python.org>2009-09-04 00:17:41 +0200
commit2524b3f01e98bb2b787fdfc44810d9b6441311c6 (patch)
treead5f103bf19d47a95911967612f6c30add7e31b4
parentdf68eadcfd963e1e9e040f2341aa9c54858bd693 (diff)
parentc816d7defda99496824b8eabf66bc909e4b50f49 (diff)
downloadsphinx-2524b3f01e98bb2b787fdfc44810d9b6441311c6.tar.gz
merge with trunk
-rw-r--r--.hgignore18
-rw-r--r--CHANGES4
-rw-r--r--Makefile2
-rw-r--r--doc/builders.rst2
-rw-r--r--doc/config.rst1
-rw-r--r--doc/ext/autosummary.rst2
-rw-r--r--doc/ext/builderapi.rst1
-rw-r--r--doc/markup/desc.rst4
-rw-r--r--setup.cfg1
-rw-r--r--sphinx/__init__.py2
-rw-r--r--sphinx/application.py109
-rw-r--r--sphinx/builders/__init__.py75
-rw-r--r--sphinx/builders/devhelp.py10
-rw-r--r--sphinx/builders/html.py23
-rw-r--r--sphinx/config.py5
-rw-r--r--sphinx/directives/desc.py466
-rw-r--r--sphinx/directives/other.py73
-rw-r--r--sphinx/domains.py779
-rw-r--r--sphinx/environment.py304
-rw-r--r--sphinx/ext/autosummary/__init__.py7
-rw-r--r--sphinx/ext/autosummary/generate.py9
-rw-r--r--sphinx/ext/coverage.py14
-rw-r--r--sphinx/ext/ifconfig.py3
-rw-r--r--sphinx/ext/inheritance_diagram.py4
-rw-r--r--sphinx/jinja2glue.py4
-rw-r--r--sphinx/locale/__init__.py190
-rw-r--r--sphinx/locale/ca/LC_MESSAGES/sphinx.js1
-rw-r--r--sphinx/locale/ca/LC_MESSAGES/sphinx.mobin0 -> 8114 bytes
-rw-r--r--sphinx/locale/ca/LC_MESSAGES/sphinx.po606
-rw-r--r--sphinx/locale/de/LC_MESSAGES/sphinx.mobin8240 -> 8240 bytes
-rw-r--r--sphinx/locale/de/LC_MESSAGES/sphinx.po2
-rw-r--r--sphinx/locale/fi/LC_MESSAGES/sphinx.js2
-rw-r--r--sphinx/locale/fi/LC_MESSAGES/sphinx.mobin7537 -> 7563 bytes
-rw-r--r--sphinx/locale/fi/LC_MESSAGES/sphinx.po2
-rw-r--r--sphinx/locale/sphinx.pot290
-rw-r--r--sphinx/quickstart.py3
-rw-r--r--sphinx/roles.py239
-rw-r--r--sphinx/search.py4
-rw-r--r--sphinx/themes/scrolls/artwork/logo.svg107
-rw-r--r--sphinx/themes/scrolls/genindex.html36
-rw-r--r--sphinx/themes/scrolls/layout.html96
-rw-r--r--sphinx/themes/scrolls/modindex.html43
-rw-r--r--sphinx/themes/scrolls/opensearch.xml9
-rw-r--r--sphinx/themes/scrolls/page.html4
-rw-r--r--sphinx/themes/scrolls/search.html35
-rw-r--r--sphinx/themes/scrolls/static/darkmetal.pngbin0 -> 44361 bytes
-rw-r--r--sphinx/themes/scrolls/static/headerbg.pngbin0 -> 298 bytes
-rw-r--r--sphinx/themes/scrolls/static/logo.pngbin0 -> 11078 bytes
-rw-r--r--sphinx/themes/scrolls/static/metal.pngbin0 -> 21543 bytes
-rw-r--r--sphinx/themes/scrolls/static/navigation.pngbin0 -> 217 bytes
-rw-r--r--sphinx/themes/scrolls/static/print.css5
-rw-r--r--sphinx/themes/scrolls/static/style.css_t398
-rw-r--r--sphinx/themes/scrolls/static/theme_extras.js26
-rw-r--r--sphinx/themes/scrolls/static/watermark.pngbin0 -> 107625 bytes
-rw-r--r--sphinx/themes/scrolls/static/watermark_blur.pngbin0 -> 14470 bytes
-rw-r--r--sphinx/themes/scrolls/theme.conf11
-rw-r--r--sphinx/theming.py2
-rw-r--r--sphinx/util/__init__.py26
-rw-r--r--sphinx/writers/text.py2
-rw-r--r--tests/root/conf.py1
-rw-r--r--tests/root/desc.txt30
-rw-r--r--tests/root/markup.txt113
-rw-r--r--tests/test_build.py57
-rw-r--r--tests/test_config.py2
-rw-r--r--tests/test_env.py17
-rw-r--r--tests/test_theming.py2
66 files changed, 3095 insertions, 1188 deletions
diff --git a/.hgignore b/.hgignore
index f617875e..4e721bf2 100644
--- a/.hgignore
+++ b/.hgignore
@@ -1,11 +1,13 @@
.*\.pyc
.*\.egg
.*\.so
-build/
-dist/
-tests/.coverage
-sphinx/pycode/Grammar.*pickle
-Sphinx.egg-info/
-doc/_build/
-TAGS
-\.ropeproject/
+\.DS_Store$
+^build/
+^dist/
+^tests/.coverage
+^sphinx/pycode/Grammar.*pickle
+^Sphinx.egg-info/
+^doc/_build/
+^TAGS
+^\.ropeproject/
+^env/
diff --git a/CHANGES b/CHANGES
index fec1b2bb..da99816a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,10 @@
Release 1.0 (in development)
============================
+* Added Catalan translation, thanks to Pau Fernández.
+
+* Added new minimal theme called scrolls.
+
* Added ``html_output_encoding`` config value.
* Added ``latexpdf`` target in quickstart Makefile.
diff --git a/Makefile b/Makefile
index dbe7c36e..f405fddc 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ all: clean-pyc check test
check:
@$(PYTHON) utils/check_sources.py -i sphinx/style/jquery.js \
-i sphinx/pycode/pgen2 -i sphinx/util/smartypants.py \
- -i doc/_build -i ez_setup.py -i tests/path.py -i tests/coverage.py .
+ -i doc/_build -i ez_setup.py -i tests/path.py -i tests/coverage.py -i env .
clean: clean-pyc clean-patchfiles
diff --git a/doc/builders.rst b/doc/builders.rst
index 9b001105..7891ce74 100644
--- a/doc/builders.rst
+++ b/doc/builders.rst
@@ -58,7 +58,7 @@ The builder's "name" must be given to the **-b** command-line option of
.. class:: DevhelpBuilder
This builder produces the same output as the standalone HTML builder, but
- also generates `GNOME Devhelp <http://live.gnome.org/devhelp>`__
+ also generates `GNOME Devhelp <http://live.gnome.org/devhelp>`__
support file that allows the GNOME Devhelp reader to view them.
Its name is ``devhelp``.
diff --git a/doc/config.rst b/doc/config.rst
index 3ce8d53b..47fc2bdd 100644
--- a/doc/config.rst
+++ b/doc/config.rst
@@ -240,6 +240,7 @@ Project information
Currently supported languages are:
+ * ``ca`` -- Catalan
* ``cs`` -- Czech
* ``de`` -- German
* ``en`` -- English
diff --git a/doc/ext/autosummary.rst b/doc/ext/autosummary.rst
index 57abd616..f270a67b 100644
--- a/doc/ext/autosummary.rst
+++ b/doc/ext/autosummary.rst
@@ -220,6 +220,6 @@ The following variables available in the templates:
for classes.
.. note::
-
+
You can use the :dir:`autosummary` directive in the stub pages.
Stub pages are generated also based on these directives.
diff --git a/doc/ext/builderapi.rst b/doc/ext/builderapi.rst
index bb11bfe2..3ace2687 100644
--- a/doc/ext/builderapi.rst
+++ b/doc/ext/builderapi.rst
@@ -13,7 +13,6 @@ Writing new builders
These methods are predefined and will be called from the application:
- .. automethod:: load_env
.. automethod:: get_relative_uri
.. automethod:: build_all
.. automethod:: build_specific
diff --git a/doc/markup/desc.rst b/doc/markup/desc.rst
index ec8ede37..4cfba05f 100644
--- a/doc/markup/desc.rst
+++ b/doc/markup/desc.rst
@@ -119,8 +119,8 @@ The directives are:
Describes a "simple" C macro. Simple macros are macros which are used
for code expansion, but which do not take arguments so cannot be described as
functions. This is not to be used for simple constant definitions. Examples
- of its use in the Python documentation include :cmacro:`PyObject_HEAD` and
- :cmacro:`Py_BEGIN_ALLOW_THREADS`.
+ of its use in the Python documentation include :c:macro:`PyObject_HEAD` and
+ :c:macro:`Py_BEGIN_ALLOW_THREADS`.
.. directive:: .. ctype:: name
diff --git a/setup.cfg b/setup.cfg
index 23986bcf..525e24ea 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -8,6 +8,7 @@ release = egg_info -RDb ''
[extract_messages]
mapping_file = babel.cfg
output_file = sphinx/locale/sphinx.pot
+keywords = _ l_ lazy_gettext
[update_catalog]
input_file = sphinx/locale/sphinx.pot
diff --git a/sphinx/__init__.py b/sphinx/__init__.py
index e6fb54b4..e3feebae 100644
--- a/sphinx/__init__.py
+++ b/sphinx/__init__.py
@@ -12,7 +12,7 @@
import sys
from os import path
-__version__ = '1.0'
+__version__ = '1.0pre'
__released__ = '1.0 (hg)' # used when Sphinx builds its own docs
package_dir = path.abspath(path.dirname(__file__))
diff --git a/sphinx/application.py b/sphinx/application.py
index 0c26b131..1296e575 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -14,18 +14,21 @@
import sys
import types
import posixpath
+from os import path
from cStringIO import StringIO
from docutils import nodes
from docutils.parsers.rst import directives, roles
import sphinx
-from sphinx.roles import xfileref_role, innernodetypes
+from sphinx import package_dir, locale
+from sphinx.roles import XRefRole
from sphinx.config import Config
from sphinx.errors import SphinxError, SphinxWarning, ExtensionError
+from sphinx.domains import all_domains
from sphinx.builders import BUILTIN_BUILDERS
from sphinx.directives import GenericDesc, Target, additional_xref_types
-from sphinx.environment import SphinxStandaloneReader
+from sphinx.environment import BuildEnvironment, SphinxStandaloneReader
from sphinx.util import pycompat # imported for side-effects
from sphinx.util.tags import Tags
from sphinx.util.compat import Directive, directive_dwim
@@ -49,6 +52,7 @@ events = {
}
CONFIG_FILENAME = 'conf.py'
+ENV_PICKLE_FILENAME = 'environment.pickle'
class Sphinx(object):
@@ -61,6 +65,7 @@ class Sphinx(object):
self._listeners = {}
self.builderclasses = BUILTIN_BUILDERS.copy()
self.builder = None
+ self.env = None
self.srcdir = srcdir
self.confdir = confdir
@@ -103,8 +108,62 @@ class Sphinx(object):
# now that we know all config values, collect them from conf.py
self.config.init_values()
+ # 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')
+
+ def _init_env(self, freshenv):
+ if freshenv:
+ self.env = BuildEnvironment(self.srcdir, self.doctreedir,
+ self.config)
+ self.env.find_files(self.config)
+ for domain in all_domains.keys():
+ self.env.domains[domain] = all_domains[domain](self.env)
+ else:
+ try:
+ self.info(bold('loading pickled environment... '), nonl=True)
+ self.env = BuildEnvironment.frompickle(self.config,
+ path.join(self.doctreedir, ENV_PICKLE_FILENAME))
+ 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)
+ 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)
+ return self._init_env(freshenv=True)
+
+ self.env.set_warnfunc(self.warn)
+
+ def _init_builder(self, buildername):
if buildername is None:
- print >>status, 'No builder selected, using default: html'
+ print >>self._status, 'No builder selected, using default: html'
buildername = 'html'
if buildername not in self.builderclasses:
raise SphinxError('Builder name %s not registered' % buildername)
@@ -115,9 +174,7 @@ class Sphinx(object):
mod, cls = builderclass
builderclass = getattr(
__import__('sphinx.builders.' + mod, None, None, [cls]), cls)
- self.builder = builderclass(self, freshenv=freshenv)
- self.builder.tags = self.tags
- self.builder.tags.add(self.builder.format)
+ self.builder = builderclass(self)
self.emit('builder-inited')
def build(self, all_files, filenames):
@@ -277,17 +334,21 @@ class Sphinx(object):
if depart:
setattr(translator, 'depart_'+node.__name__, depart)
- def add_directive(self, name, obj, content=None, arguments=None, **options):
+ def _directive_helper(self, obj, content=None, arguments=None, **options):
if isinstance(obj, clstypes) and issubclass(obj, Directive):
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))
+ return directive_dwim(obj)
else:
obj.content = content
obj.arguments = arguments
obj.options = options
- directives.register_directive(name, obj)
+ return obj
+
+ def add_directive(self, name, obj, content=None, arguments=None, **options):
+ directives.register_directive(
+ name, self._directive_helper(obj, content, arguments, **options))
def add_role(self, name, role):
roles.register_local_role(name, role)
@@ -298,23 +359,41 @@ class Sphinx(object):
role = roles.GenericRole(name, nodeclass)
roles.register_local_role(name, role)
+ def add_domain(self, domain):
+ # XXX needs to be documented
+ if domain.name in all_domains:
+ raise ExtensionError('domain %s already registered' % domain.name)
+ all_domains[domain.name] = domain
+
+ def add_directive_to_domain(self, domain, name, obj):
+ # XXX needs to be documented
+ if domain not in all_domains:
+ raise ExtensionError('domain %s not yet registered' % domain)
+ all_domains[domain].directives[name] = self._directive_helper(obj)
+
+ def add_role_to_domain(self, domain, name, role):
+ # XXX needs to be documented
+ if domain not in all_domains:
+ raise ExtensionError('domain %s not yet registered' % domain)
+ all_domains[domain].roles[name] = role
+
def add_description_unit(self, directivename, rolename, indextemplate='',
parse_node=None, ref_nodeclass=None):
additional_xref_types[directivename] = (rolename, indextemplate,
parse_node)
directives.register_directive(directivename,
directive_dwim(GenericDesc))
- roles.register_local_role(rolename, xfileref_role)
- if ref_nodeclass is not None:
- innernodetypes[rolename] = ref_nodeclass
+ # XXX support more options?
+ role_func = XRefRole(innernodeclass=ref_nodeclass)
+ roles.register_local_role(rolename, role_func)
def add_crossref_type(self, directivename, rolename, indextemplate='',
ref_nodeclass=None):
additional_xref_types[directivename] = (rolename, indextemplate, None)
directives.register_directive(directivename, directive_dwim(Target))
- roles.register_local_role(rolename, xfileref_role)
- if ref_nodeclass is not None:
- innernodetypes[rolename] = ref_nodeclass
+ # XXX support more options
+ role_func = XRefRole(innernodeclass=ref_nodeclass)
+ roles.register_local_role(rolename, role_func)
def add_transform(self, transform):
SphinxStandaloneReader.transforms.append(transform)
diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py
index a8fc8871..08628c7b 100644
--- a/sphinx/builders/__init__.py
+++ b/sphinx/builders/__init__.py
@@ -15,9 +15,7 @@ from os import path
from docutils import nodes
-from sphinx import package_dir, locale
from sphinx.util import SEP, relative_uri
-from sphinx.environment import BuildEnvironment
from sphinx.util.console import bold, purple, darkgreen, term_width_line
# side effect: registers roles and directives
@@ -25,9 +23,6 @@ from sphinx import roles
from sphinx import directives
-ENV_PICKLE_FILENAME = 'environment.pickle'
-
-
class Builder(object):
"""
Builds target formats from the reST sources.
@@ -38,7 +33,8 @@ class Builder(object):
# builder's output format, or '' if no document output is produced
format = ''
- def __init__(self, app, env=None, freshenv=False):
+ def __init__(self, app):
+ self.env = app.env
self.srcdir = app.srcdir
self.confdir = app.confdir
self.outdir = app.outdir
@@ -50,21 +46,15 @@ class Builder(object):
self.warn = app.warn
self.info = app.info
self.config = app.config
-
- self.load_i18n()
+ self.tags = app.tags
+ self.tags.add(self.format)
# images that need to be copied over (source -> dest)
self.images = {}
- # if None, this is set in load_env()
- self.env = env
- self.freshenv = freshenv
-
self.init()
- self.load_env()
# helper methods
-
def init(self):
"""
Load necessary templates and perform initialization. The default
@@ -167,62 +157,6 @@ class Builder(object):
# build methods
- def load_i18n(self):
- """
- Load translated strings from the configured localedirs if
- enabled in the configuration.
- """
- self.translator = None
- if self.config.language is not None:
- self.info(bold('loading translations [%s]... ' %
- self.config.language), nonl=True)
- # the None entry is the system's default locale path
- locale_dirs = [None, path.join(package_dir, 'locale')] + \
- [path.join(self.srcdir, x) for x in self.config.locale_dirs]
- for dir_ in locale_dirs:
- try:
- trans = gettext.translation('sphinx', localedir=dir_,
- languages=[self.config.language])
- if self.translator is None:
- self.translator = trans
- else:
- self.translator._catalog.update(trans.catalog)
- except Exception:
- # Language couldn't be found in the specified path
- pass
- if self.translator is not None:
- self.info('done')
- else:
- self.info('locale not available')
- if self.translator is None:
- self.translator = gettext.NullTranslations()
- self.translator.install(unicode=True)
- locale.init() # translate common labels
-
- def load_env(self):
- """Set up the build environment."""
- if self.env:
- return
- if not self.freshenv:
- try:
- self.info(bold('loading pickled environment... '), nonl=True)
- self.env = BuildEnvironment.frompickle(self.config,
- path.join(self.doctreedir, ENV_PICKLE_FILENAME))
- self.info('done')
- except Exception, err:
- if type(err) is IOError and err.errno == 2:
- self.info('not found')
- else:
- self.info('failed: %s' % err)
- self.env = BuildEnvironment(self.srcdir, self.doctreedir,
- self.config)
- self.env.find_files(self.config)
- else:
- self.env = BuildEnvironment(self.srcdir, self.doctreedir,
- self.config)
- self.env.find_files(self.config)
- self.env.set_warnfunc(self.warn)
-
def build_all(self):
"""Build all source files."""
self.build(None, summary='all source files', method='all')
@@ -302,6 +236,7 @@ class Builder(object):
if updated_docnames:
# save the environment
+ from sphinx.application import ENV_PICKLE_FILENAME
self.info(bold('pickling environment... '), nonl=True)
self.env.topickle(path.join(self.doctreedir, ENV_PICKLE_FILENAME))
self.info('done')
diff --git a/sphinx/builders/devhelp.py b/sphinx/builders/devhelp.py
index ba117e62..e5a9a453 100644
--- a/sphinx/builders/devhelp.py
+++ b/sphinx/builders/devhelp.py
@@ -12,6 +12,7 @@
"""
import os
+import re
import cgi
import sys
from os import path
@@ -30,7 +31,7 @@ except ImportError:
try:
import elementtree.ElementTree as etree
except ImportError:
- import cElementTree.ElemenTree as etree
+ import cElementTree as etree
try:
import gzip
@@ -114,11 +115,14 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
else:
for i, ref in enumerate(refs):
etree.SubElement(functions, 'function',
- name="%s [%d]" % (title, i), link=ref)
+ name="[%d] %s" % (i, title),
+ link=ref)
if subitems:
+ parent_title = re.sub(r'\s*\(.*\)\s*$', '', title)
for subitem in subitems:
- write_index(subitem[0], subitem[1], [])
+ write_index("%s %s" % (parent_title, subitem[0]),
+ subitem[1], [])
for (key, group) in index:
for title, (refs, subitems) in group:
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 54327fa1..02f62164 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -33,7 +33,8 @@ from sphinx.util import SEP, os_path, relative_uri, ensuredir, \
from sphinx.errors import SphinxError
from sphinx.search import js_index
from sphinx.theming import Theme
-from sphinx.builders import Builder, ENV_PICKLE_FILENAME
+from sphinx.builders import Builder
+from sphinx.application import ENV_PICKLE_FILENAME
from sphinx.highlighting import PygmentsBridge
from sphinx.util.console import bold
from sphinx.writers.html import HTMLWriter, HTMLTranslator, \
@@ -239,7 +240,9 @@ class StandaloneHTMLBuilder(Builder):
rellinks = []
if self.config.html_use_index:
rellinks.append(('genindex', _('General Index'), 'I', _('index')))
- if self.config.html_use_modindex and self.env.modules:
+ # XXX generalization of modindex?
+ if self.config.html_use_modindex and \
+ self.env.domaindata['py']['modules']:
rellinks.append(('modindex', _('Global Module Index'),
'M', _('modules')))
@@ -404,12 +407,13 @@ class StandaloneHTMLBuilder(Builder):
# the global module index
- if self.config.html_use_modindex and self.env.modules:
+ moduleindex = self.env.domaindata['py']['modules']
+ if self.config.html_use_modindex and moduleindex:
# the sorted list of all modules, for the global module index
modules = sorted(((mn, (self.get_relative_uri('modindex', fn) +
'#module-' + mn, sy, pl, dep))
for (mn, (fn, sy, pl, dep)) in
- self.env.modules.iteritems()),
+ moduleindex.iteritems()),
key=lambda x: x[0].lower())
# collect all platforms
platforms = set()
@@ -709,14 +713,15 @@ class StandaloneHTMLBuilder(Builder):
self.info(bold('dumping object inventory... '), nonl=True)
f = open(path.join(self.outdir, INVENTORY_FILENAME), 'w')
try:
+ # XXX inventory version 2
f.write('# Sphinx inventory version 1\n')
f.write('# Project: %s\n' % self.config.project.encode('utf-8'))
f.write('# Version: %s\n' % self.config.version)
- for modname, info in self.env.modules.iteritems():
- f.write('%s mod %s\n' % (modname, self.get_target_uri(info[0])))
- for refname, (docname, desctype) in self.env.descrefs.iteritems():
- f.write('%s %s %s\n' % (refname, desctype,
- self.get_target_uri(docname)))
+ #for modname, info in self.env.modules.iteritems():
+ # f.write('%s mod %s\n' % (modname, self.get_target_uri(info[0])))
+ #for refname, (docname, desctype) in self.env.descrefs.iteritems():
+ # f.write('%s %s %s\n' % (refname, desctype,
+ # self.get_target_uri(docname)))
finally:
f.close()
self.info('done')
diff --git a/sphinx/config.py b/sphinx/config.py
index b2ef29fb..dbe569fb 100644
--- a/sphinx/config.py
+++ b/sphinx/config.py
@@ -55,6 +55,7 @@ class Config(object):
modindex_common_prefix = ([], 'html'),
rst_epilog = (None, 'env'),
trim_doctest_flags = (True, 'env'),
+ default_domain = ('py', 'env'),
# HTML options
html_theme = ('default', 'html'),
@@ -112,6 +113,10 @@ class Config(object):
latex_docclass = ({}, None),
# now deprecated - use latex_elements
latex_preamble = ('', None),
+
+ # text options
+ text_sectionchars = ('*=-~"+`', 'text'),
+ text_windows_newlines = (False, 'text'),
)
def __init__(self, dirname, filename, overrides, tags):
diff --git a/sphinx/directives/desc.py b/sphinx/directives/desc.py
index db261a87..6deb1f03 100644
--- a/sphinx/directives/desc.py
+++ b/sphinx/directives/desc.py
@@ -14,6 +14,7 @@ from docutils import nodes
from docutils.parsers.rst import directives
from sphinx import addnodes
+from sphinx.locale import l_
from sphinx.util import ws_re
from sphinx.util.compat import Directive, directive_dwim
@@ -31,39 +32,10 @@ def _is_only_paragraph(node):
return False
-# REs for Python signatures
-py_sig_re = re.compile(
- r'''^ ([\w.]*\.)? # class name(s)
- (\w+) \s* # thing name
- (?: \((.*)\) # optional: arguments
- (?:\s* -> \s* (.*))? # return annotation
- )? $ # and nothing more
- ''', re.VERBOSE)
-
-py_paramlist_re = re.compile(r'([\[\],])') # split at '[', ']' and ','
-
-# REs for C signatures
-c_sig_re = re.compile(
- r'''^([^(]*?) # return type
- ([\w:]+) \s* # thing name (colon allowed for C++ class names)
- (?: \((.*)\) )? # optionally arguments
- (\s+const)? $ # const specifier
- ''', re.VERBOSE)
-c_funcptr_sig_re = re.compile(
- r'''^([^(]+?) # return type
- (\( [^()]+ \)) \s* # name in parentheses
- \( (.*) \) # arguments
- (\s+const)? $ # const specifier
- ''', re.VERBOSE)
-c_funcptr_name_re = re.compile(r'^\(\s*\*\s*(.*?)\s*\)$')
-
# RE for option descriptions
option_desc_re = re.compile(
r'((?:/|-|--)[-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)')
-# RE to split at word boundaries
-wsplit_re = re.compile(r'(\W+)')
-
# RE to strip backslash escapes
strip_backslash_re = re.compile(r'\\(?=[^\\])')
@@ -83,8 +55,6 @@ class DescDirective(Directive):
'module': directives.unchanged,
}
- _ = lambda x: x # make gettext extraction in constants possible
-
doc_fields_with_arg = {
'param': '%param',
'parameter': '%param',
@@ -94,23 +64,23 @@ class DescDirective(Directive):
'kwarg': '%param',
'kwparam': '%param',
'type': '%type',
- 'raises': _('Raises'),
- 'raise': 'Raises',
- 'exception': 'Raises',
- 'except': 'Raises',
- 'var': _('Variable'),
- 'ivar': 'Variable',
- 'cvar': 'Variable',
- 'returns': _('Returns'),
- 'return': 'Returns',
+ 'raises': l_('Raises'),
+ 'raise': l_('Raises'),
+ 'exception': l_('Raises'),
+ 'except': l_('Raises'),
+ 'var': l_('Variable'),
+ 'ivar': l_('Variable'),
+ 'cvar': l_('Variable'),
+ 'returns': l_('Returns'),
+ 'return': l_('Returns'),
}
doc_fields_with_linked_arg = ('raises', 'raise', 'exception', 'except')
doc_fields_without_arg = {
- 'returns': 'Returns',
- 'return': 'Returns',
- 'rtype': _('Return type'),
+ 'returns': l_('Returns'),
+ 'return': l_('Returns'),
+ 'rtype': l_('Return type'),
}
def handle_doc_fields(self, node):
@@ -131,7 +101,7 @@ class DescDirective(Directive):
fname, fbody = field
try:
typ, obj = fname.astext().split(None, 1)
- typdesc = _(self.doc_fields_with_arg[typ])
+ typdesc = self.doc_fields_with_arg[typ]
if _is_only_paragraph(fbody):
children = fbody.children[0].children
else:
@@ -175,7 +145,7 @@ class DescDirective(Directive):
except (KeyError, ValueError):
fnametext = fname.astext()
try:
- typ = _(self.doc_fields_without_arg[fnametext])
+ typ = self.doc_fields_without_arg[fnametext]
except KeyError:
# at least capitalize the field name
typ = fnametext.capitalize()
@@ -234,7 +204,10 @@ class DescDirective(Directive):
pass
def run(self):
- self.desctype = self.name
+ if ':' in self.name:
+ self.domain, self.desctype = self.name.split(':', 1)
+ else:
+ self.domain, self.desctype = '', self.name
self.env = self.state.document.settings.env
self.indexnode = addnodes.index(entries=[])
@@ -278,360 +251,6 @@ class DescDirective(Directive):
return [self.indexnode, node]
-class PythonDesc(DescDirective):
- """
- Description of a general Python object.
- """
-
- def get_signature_prefix(self, sig):
- """
- May return a prefix to put before the object name in the signature.
- """
- return ''
-
- def needs_arglist(self):
- """
- May return true if an empty argument list is to be generated even if
- the document contains none.
- """
- return False
-
- def parse_signature(self, sig, signode):
- """
- Transform a Python signature into RST nodes.
- Returns (fully qualified name of the thing, classname if any).
-
- If inside a class, the current class name is handled intelligently:
- * it is stripped from the displayed name if present
- * it is added to the full name (return value) if not present
- """
- m = py_sig_re.match(sig)
- if m is None:
- raise ValueError
- classname, name, arglist, retann = m.groups()
-
- if self.env.currclass:
- add_module = False
- if classname and classname.startswith(self.env.currclass):
- fullname = classname + name
- # class name is given again in the signature
- classname = classname[len(self.env.currclass):].lstrip('.')
- elif classname:
- # class name is given in the signature, but different
- # (shouldn't happen)
- fullname = self.env.currclass + '.' + classname + name
- else:
- # class name is not given in the signature
- fullname = self.env.currclass + '.' + name
- else:
- add_module = True
- fullname = classname and classname + name or name
-
- prefix = self.get_signature_prefix(sig)
- if prefix:
- signode += addnodes.desc_annotation(prefix, prefix)
-
- if classname:
- signode += addnodes.desc_addname(classname, classname)
- # exceptions are a special case, since they are documented in the
- # 'exceptions' module.
- elif add_module and self.env.config.add_module_names:
- modname = self.options.get('module', self.env.currmodule)
- if modname and modname != 'exceptions':
- nodetext = modname + '.'
- signode += addnodes.desc_addname(nodetext, nodetext)
-
- signode += addnodes.desc_name(name, name)
- if not arglist:
- if self.needs_arglist():
- # for callables, add an empty parameter list
- signode += addnodes.desc_parameterlist()
- if retann:
- signode += addnodes.desc_returns(retann, retann)
- return fullname, classname
- signode += addnodes.desc_parameterlist()
-
- stack = [signode[-1]]
- for token in py_paramlist_re.split(arglist):
- if token == '[':
- opt = addnodes.desc_optional()
- stack[-1] += opt
- stack.append(opt)
- elif token == ']':
- try:
- stack.pop()
- except IndexError:
- raise ValueError
- elif not token or token == ',' or token.isspace():
- pass
- else:
- token = token.strip()
- stack[-1] += addnodes.desc_parameter(token, token)
- if len(stack) != 1:
- raise ValueError
- if retann:
- signode += addnodes.desc_returns(retann, retann)
- return fullname, classname
-
- def get_index_text(self, modname, name):
- """
- Return the text for the index entry of the object.
- """
- raise NotImplementedError('must be implemented in subclasses')
-
- def add_target_and_index(self, name_cls, sig, signode):
- modname = self.options.get('module', self.env.currmodule)
- fullname = (modname and modname + '.' or '') + name_cls[0]
- # note target
- if fullname not in self.state.document.ids:
- signode['names'].append(fullname)
- signode['ids'].append(fullname)
- signode['first'] = (not self.names)
- self.state.document.note_explicit_target(signode)
- self.env.note_descref(fullname, self.desctype, self.lineno)
-
- indextext = self.get_index_text(modname, name_cls)
- if indextext:
- self.indexnode['entries'].append(('single', indextext,
- fullname, fullname))
-
- def before_content(self):
- # needed for automatic qualification of members (reset in subclasses)
- self.clsname_set = False
-
- def after_content(self):
- if self.clsname_set:
- self.env.currclass = None
-
-
-class ModulelevelDesc(PythonDesc):
- """
- Description of an object on module level (functions, data).
- """
-
- def needs_arglist(self):
- return self.desctype == 'function'
-
- def get_index_text(self, modname, name_cls):
- if self.desctype == 'function':
- if not modname:
- return _('%s() (built-in function)') % name_cls[0]
- return _('%s() (in module %s)') % (name_cls[0], modname)
- elif self.desctype == 'data':
- if not modname:
- return _('%s (built-in variable)') % name_cls[0]
- return _('%s (in module %s)') % (name_cls[0], modname)
- else:
- return ''
-
-
-class ClasslikeDesc(PythonDesc):
- """
- Description of a class-like object (classes, interfaces, exceptions).
- """
-
- def get_signature_prefix(self, sig):
- return self.desctype + ' '
-
- def get_index_text(self, modname, name_cls):
- if self.desctype == 'class':
- if not modname:
- return _('%s (built-in class)') % name_cls[0]
- return _('%s (class in %s)') % (name_cls[0], modname)
- elif self.desctype == 'exception':
- return name_cls[0]
- else:
- return ''
-
- def before_content(self):
- PythonDesc.before_content(self)
- if self.names:
- self.env.currclass = self.names[0][0]
- self.clsname_set = True
-
-
-class ClassmemberDesc(PythonDesc):
- """
- Description of a class member (methods, attributes).
- """
-
- def needs_arglist(self):
- return self.desctype.endswith('method')
-
- def get_signature_prefix(self, sig):
- if self.desctype == 'staticmethod':
- return 'static '
- elif self.desctype == 'classmethod':
- return 'classmethod '
- return ''
-
- def get_index_text(self, modname, name_cls):
- name, cls = name_cls
- add_modules = self.env.config.add_module_names
- if self.desctype == 'method':
- try:
- clsname, methname = name.rsplit('.', 1)
- except ValueError:
- if modname:
- return _('%s() (in module %s)') % (name, modname)
- else:
- return '%s()' % name
- if modname and add_modules:
- return _('%s() (%s.%s method)') % (methname, modname, clsname)
- else:
- return _('%s() (%s method)') % (methname, clsname)
- elif self.desctype == 'staticmethod':
- try:
- clsname, methname = name.rsplit('.', 1)
- except ValueError:
- if modname:
- return _('%s() (in module %s)') % (name, modname)
- else:
- return '%s()' % name
- if modname and add_modules:
- return _('%s() (%s.%s static method)') % (methname, modname,
- clsname)
- else:
- return _('%s() (%s static method)') % (methname, clsname)
- elif self.desctype == 'classmethod':
- try:
- clsname, methname = name.rsplit('.', 1)
- except ValueError:
- if modname:
- return '%s() (in module %s)' % (name, modname)
- else:
- return '%s()' % name
- if modname:
- return '%s() (%s.%s class method)' % (methname, modname,
- clsname)
- else:
- return '%s() (%s class method)' % (methname, clsname)
- elif self.desctype == 'attribute':
- try:
- clsname, attrname = name.rsplit('.', 1)
- except ValueError:
- if modname:
- return _('%s (in module %s)') % (name, modname)
- else:
- return name
- if modname and add_modules:
- return _('%s (%s.%s attribute)') % (attrname, modname, clsname)
- else:
- return _('%s (%s attribute)') % (attrname, clsname)
- else:
- return ''
-
- def before_content(self):
- PythonDesc.before_content(self)
- if self.names and self.names[-1][1] and not self.env.currclass:
- self.env.currclass = self.names[-1][1].strip('.')
- self.clsname_set = True
-
-
-class CDesc(DescDirective):
- """
- Description of a C language object.
- """
-
- # These C types aren't described anywhere, so don't try to create
- # a cross-reference to them
- stopwords = set(('const', 'void', 'char', 'int', 'long', 'FILE', 'struct'))
-
- def _parse_type(self, node, ctype):
- # add cross-ref nodes for all words
- for part in filter(None, wsplit_re.split(ctype)):
- tnode = nodes.Text(part, part)
- if part[0] in string.ascii_letters+'_' and \
- part not in self.stopwords:
- pnode = addnodes.pending_xref(
- '', reftype='ctype', reftarget=part,
- modname=None, classname=None)
- pnode += tnode
- node += pnode
- else:
- node += tnode
-
- def parse_signature(self, sig, signode):
- """Transform a C (or C++) signature into RST nodes."""
- # first try the function pointer signature regex, it's more specific
- m = c_funcptr_sig_re.match(sig)
- if m is None:
- m = c_sig_re.match(sig)
- if m is None:
- raise ValueError('no match')
- rettype, name, arglist, const = m.groups()
-
- signode += addnodes.desc_type('', '')
- self._parse_type(signode[-1], rettype)
- try:
- classname, funcname = name.split('::', 1)
- classname += '::'
- signode += addnodes.desc_addname(classname, classname)
- signode += addnodes.desc_name(funcname, funcname)
- # name (the full name) is still both parts
- except ValueError:
- signode += addnodes.desc_name(name, name)
- # clean up parentheses from canonical name
- m = c_funcptr_name_re.match(name)
- if m:
- name = m.group(1)
- if not arglist:
- if self.desctype == 'cfunction':
- # for functions, add an empty parameter list
- signode += addnodes.desc_parameterlist()
- if const:
- signode += addnodes.desc_addname(const, const)
- return name
-
- paramlist = addnodes.desc_parameterlist()
- arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
- # this messes up function pointer types, but not too badly ;)
- args = arglist.split(',')
- for arg in args:
- arg = arg.strip()
- param = addnodes.desc_parameter('', '', noemph=True)
- try:
- ctype, argname = arg.rsplit(' ', 1)
- except ValueError:
- # no argument name given, only the type
- self._parse_type(param, arg)
- else:
- self._parse_type(param, ctype)
- param += nodes.emphasis(' '+argname, ' '+argname)
- paramlist += param
- signode += paramlist
- if const:
- signode += addnodes.desc_addname(const, const)
- return name
-
- def get_index_text(self, name):
- if self.desctype == 'cfunction':
- return _('%s (C function)') % name
- elif self.desctype == 'cmember':
- return _('%s (C member)') % name
- elif self.desctype == 'cmacro':
- return _('%s (C macro)') % name
- elif self.desctype == 'ctype':
- return _('%s (C type)') % name
- elif self.desctype == 'cvar':
- return _('%s (C variable)') % name
- else:
- return ''
-
- def add_target_and_index(self, name, sig, signode):
- # note target
- if name not in self.state.document.ids:
- signode['names'].append(name)
- signode['ids'].append(name)
- signode['first'] = (not self.names)
- self.state.document.note_explicit_target(signode)
- self.env.note_descref(name, self.desctype, self.lineno)
-
- indextext = self.get_index_text(name)
- if indextext:
- self.indexnode['entries'].append(('single', indextext, name, name))
-
-
class CmdoptionDesc(DescDirective):
"""
Description of a command-line option (.. cmdoption).
@@ -681,7 +300,7 @@ class GenericDesc(DescDirective):
else:
signode.clear()
signode += addnodes.desc_name(sig, sig)
- # normalize whitespace like xfileref_role does
+ # normalize whitespace like XRefRole does
name = ws_re.sub('', sig)
return name
@@ -691,7 +310,7 @@ class GenericDesc(DescDirective):
signode['ids'].append(targetname)
self.state.document.note_explicit_target(signode)
if indextemplate:
- indexentry = _(indextemplate) % (name,)
+ indexentry = indextemplate % (name,)
indextype = 'single'
colon = indexentry.find(':')
if colon != -1:
@@ -716,7 +335,7 @@ class Target(Directive):
def run(self):
env = self.state.document.settings.env
rolename, indextemplate, foo = additional_xref_types[self.name]
- # normalize whitespace in fullname like xfileref_role does
+ # normalize whitespace in fullname like XRefRole does
fullname = ws_re.sub('', self.arguments[0].strip())
targetname = '%s-%s' % (rolename, fullname)
node = nodes.target('', '', ids=[targetname])
@@ -735,37 +354,36 @@ class Target(Directive):
env.note_reftarget(rolename, fullname, targetname)
return ret
+
+class DefaultDomain(Directive):
+ """
+ Directive to (re-)set the default domain for this source file.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ domain_name = arguments[0]
+ env.default_domain = env.domains.get(domain_name)
+
+
# Note: the target directive is not registered here, it is used by the
# application when registering additional xref types.
-_ = lambda x: x
-
# Generic cross-reference types; they can be registered in the application;
# the directives are either desc_directive or target_directive.
additional_xref_types = {
# directive name: (role name, index text, function to parse the desc node)
- 'envvar': ('envvar', _('environment variable; %s'), None),
+ 'envvar': ('envvar', l_('environment variable; %s'), None),
}
-del _
-
+directives.register_directive('default-domain', directive_dwim(DefaultDomain))
directives.register_directive('describe', directive_dwim(DescDirective))
-
-directives.register_directive('function', directive_dwim(ModulelevelDesc))
-directives.register_directive('data', directive_dwim(ModulelevelDesc))
-directives.register_directive('class', directive_dwim(ClasslikeDesc))
-directives.register_directive('exception', directive_dwim(ClasslikeDesc))
-directives.register_directive('method', directive_dwim(ClassmemberDesc))
-directives.register_directive('classmethod', directive_dwim(ClassmemberDesc))
-directives.register_directive('staticmethod', directive_dwim(ClassmemberDesc))
-directives.register_directive('attribute', directive_dwim(ClassmemberDesc))
-
-directives.register_directive('cfunction', directive_dwim(CDesc))
-directives.register_directive('cmember', directive_dwim(CDesc))
-directives.register_directive('cmacro', directive_dwim(CDesc))
-directives.register_directive('ctype', directive_dwim(CDesc))
-directives.register_directive('cvar', directive_dwim(CDesc))
-
directives.register_directive('cmdoption', directive_dwim(CmdoptionDesc))
directives.register_directive('envvar', directive_dwim(GenericDesc))
diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py
index 50db49ce..225c1816 100644
--- a/sphinx/directives/other.py
+++ b/sphinx/directives/other.py
@@ -104,75 +104,6 @@ class TocTree(Directive):
return ret
-class Module(Directive):
- """
- Directive to mark description of a new module.
- """
-
- has_content = False
- required_arguments = 1
- optional_arguments = 0
- final_argument_whitespace = False
- option_spec = {
- 'platform': lambda x: x,
- 'synopsis': lambda x: x,
- 'noindex': directives.flag,
- 'deprecated': directives.flag,
- }
-
- def run(self):
- env = self.state.document.settings.env
- modname = self.arguments[0].strip()
- noindex = 'noindex' in self.options
- env.currmodule = modname
- env.note_module(modname, self.options.get('synopsis', ''),
- self.options.get('platform', ''),
- 'deprecated' in self.options)
- modulenode = addnodes.module()
- modulenode['modname'] = modname
- modulenode['synopsis'] = self.options.get('synopsis', '')
- targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True)
- self.state.document.note_explicit_target(targetnode)
- ret = [modulenode, targetnode]
- if 'platform' in self.options:
- platform = self.options['platform']
- modulenode['platform'] = platform
- node = nodes.paragraph()
- node += nodes.emphasis('', _('Platforms: '))
- node += nodes.Text(platform, platform)
- ret.append(node)
- # the synopsis isn't printed; in fact, it is only used in the
- # modindex currently
- if not noindex:
- indextext = _('%s (module)') % modname
- inode = addnodes.index(entries=[('single', indextext,
- 'module-' + modname, modname)])
- ret.insert(0, inode)
- return ret
-
-
-class CurrentModule(Directive):
- """
- This directive is just to tell Sphinx that we're documenting
- stuff in module foo, but links to module foo won't lead here.
- """
-
- has_content = False
- required_arguments = 1
- optional_arguments = 0
- final_argument_whitespace = False
- option_spec = {}
-
- def run(self):
- env = self.state.document.settings.env
- modname = self.arguments[0].strip()
- if modname == 'None':
- env.currmodule = None
- else:
- env.currmodule = modname
- return []
-
-
class Author(Directive):
"""
Directive to give the name of the author of the current document
@@ -330,7 +261,7 @@ class SeeAlso(Directive):
return ret
-token_re = re.compile('`([a-z_]+)`')
+token_re = re.compile('`([a-z_][a-z0-9_]*)`')
def token_xrefs(text, env):
retnodes = []
@@ -561,8 +492,6 @@ class Only(Directive):
directives.register_directive('toctree', directive_dwim(TocTree))
-directives.register_directive('module', directive_dwim(Module))
-directives.register_directive('currentmodule', directive_dwim(CurrentModule))
directives.register_directive('sectionauthor', directive_dwim(Author))
directives.register_directive('moduleauthor', directive_dwim(Author))
directives.register_directive('program', directive_dwim(Program))
diff --git a/sphinx/domains.py b/sphinx/domains.py
new file mode 100644
index 00000000..6e00d540
--- /dev/null
+++ b/sphinx/domains.py
@@ -0,0 +1,779 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.domains
+ ~~~~~~~~~~~~~~
+
+ Support for domains, which are groupings of description directives
+ and roles describing e.g. constructs of one programming language.
+
+ :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import string
+
+from docutils import nodes
+from docutils.parsers.rst import directives
+
+from sphinx import addnodes
+from sphinx.roles import XRefRole
+from sphinx.directives import DescDirective
+from sphinx.util import make_refnode
+from sphinx.util.compat import Directive
+
+
+class Domain(object):
+ """
+ A Domain is meant to be a group of "object" description directives for
+ objects of a similar nature, and corresponding roles to create references to
+ them. Examples would be Python modules, classes, functions etc., elements
+ of a templating language, Sphinx roles and directives, etc.
+
+ Each domain has a separate storage for information about existing objects
+ and how to reference them in `data`, which must be a dictionary. It also
+ must implement several functions that expose the object information in a
+ uniform way to parts of Sphinx that allow the user to reference or search
+ for objects in a domain-agnostic way.
+
+ About `self.data`: since all object and cross-referencing information is
+ stored on a BuildEnvironment instance, the `domain.data` object is also
+ stored in the `env.domaindata` dict under the key `domain.name`. Before the
+ build process starts, every active domain is instantiated and given the
+ environment object; the `domaindata` dict must then either be nonexistent or
+ a dictionary whose 'version' key is equal to the domain class'
+ `data_version` attribute. Otherwise, `IOError` is raised and the pickled
+ environment is discarded.
+ """
+
+ name = ''
+ directives = {}
+ roles = {}
+ label = ''
+
+ # data value for a fresh environment
+ initial_data = {}
+ # data version
+ data_version = 0
+
+ def __init__(self, env):
+ self.env = env
+ if self.name not in env.domaindata:
+ assert isinstance(self.initial_data, dict)
+ new_data = self.initial_data.copy()
+ new_data['version'] = self.data_version
+ self.data = env.domaindata[self.name] = new_data
+ else:
+ self.data = env.domaindata[self.name]
+ if self.data['version'] != self.data_version:
+ raise IOError('data of %r domain out of date' % self.label)
+ self._role_cache = {}
+ self._directive_cache = {}
+
+ def clear_doc(self, docname):
+ """
+ Remove traces of a document in the domain-specific inventories.
+ """
+ pass
+
+ def role(self, name):
+ """
+ Return a role adapter function that always gives the registered
+ role its full name ('domain:name') as the first argument.
+ """
+ if name in self._role_cache:
+ return self._role_cache[name]
+ if name not in self.roles:
+ return None
+ fullname = '%s:%s' % (self.name, name)
+ def role_adapter(typ, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ return self.roles[name](fullname, rawtext, text, lineno,
+ inliner, options, content)
+ self._role_cache[name] = role_adapter
+ return role_adapter
+
+ def directive(self, name):
+ """
+ Return a directive adapter class that always gives the registered
+ directive its full name ('domain:name') as ``self.name``.
+ """
+ if name in self._directive_cache:
+ return self._directive_cache[name]
+ if name not in self.directives:
+ return None
+ fullname = '%s:%s' % (self.name, name)
+ # XXX what about function-style directives?
+ BaseDirective = self.directives[name]
+ class DirectiveAdapter(BaseDirective):
+ def run(self):
+ self.name = fullname
+ return BaseDirective.run(self)
+ self._directive_cache[name] = DirectiveAdapter
+ return DirectiveAdapter
+
+ def resolve_xref(self, typ, target, node, contnode):
+ """
+ Resolve the ``pending_xref`` *node* with the given *typ* and *target*.
+
+ This method should return a new node, to replace the xref node,
+ containing the *contnode* which is the markup content of the
+ cross-reference.
+
+ If no resolution can be found, None can be returned; the xref node will
+ then given to the 'missing-reference' event, and if that yields no
+ resolution, replaced by *contnode*.
+
+ The method can also raise `sphinx.environment.NoUri` to suppress the
+ 'missing-reference' event being emitted.
+ """
+ pass
+
+
+# REs for Python signatures
+py_sig_re = re.compile(
+ r'''^ ([\w.]*\.)? # class name(s)
+ (\w+) \s* # thing name
+ (?: \((.*)\) # optional: arguments
+ (?:\s* -> \s* (.*))? # return annotation
+ )? $ # and nothing more
+ ''', re.VERBOSE)
+
+py_paramlist_re = re.compile(r'([\[\],])') # split at '[', ']' and ','
+
+
+class PythonDesc(DescDirective):
+ """
+ Description of a general Python object.
+ """
+
+ def get_signature_prefix(self, sig):
+ """
+ May return a prefix to put before the object name in the signature.
+ """
+ return ''
+
+ def needs_arglist(self):
+ """
+ May return true if an empty argument list is to be generated even if
+ the document contains none.
+ """
+ return False
+
+ def parse_signature(self, sig, signode):
+ """
+ Transform a Python signature into RST nodes.
+ Returns (fully qualified name of the thing, classname if any).
+
+ If inside a class, the current class name is handled intelligently:
+ * it is stripped from the displayed name if present
+ * it is added to the full name (return value) if not present
+ """
+ m = py_sig_re.match(sig)
+ if m is None:
+ raise ValueError
+ classname, name, arglist, retann = m.groups()
+
+ if self.env.currclass:
+ add_module = False
+ if classname and classname.startswith(self.env.currclass):
+ fullname = classname + name
+ # class name is given again in the signature
+ classname = classname[len(self.env.currclass):].lstrip('.')
+ elif classname:
+ # class name is given in the signature, but different
+ # (shouldn't happen)
+ fullname = self.env.currclass + '.' + classname + name
+ else:
+ # class name is not given in the signature
+ fullname = self.env.currclass + '.' + name
+ else:
+ add_module = True
+ fullname = classname and classname + name or name
+
+ prefix = self.get_signature_prefix(sig)
+ if prefix:
+ signode += addnodes.desc_annotation(prefix, prefix)
+
+ if classname:
+ signode += addnodes.desc_addname(classname, classname)
+ # exceptions are a special case, since they are documented in the
+ # 'exceptions' module.
+ elif add_module and self.env.config.add_module_names:
+ modname = self.options.get('module', self.env.currmodule)
+ if modname and modname != 'exceptions':
+ nodetext = modname + '.'
+ signode += addnodes.desc_addname(nodetext, nodetext)
+
+ signode += addnodes.desc_name(name, name)
+ if not arglist:
+ if self.needs_arglist():
+ # for callables, add an empty parameter list
+ signode += addnodes.desc_parameterlist()
+ if retann:
+ signode += addnodes.desc_returns(retann, retann)
+ return fullname, classname
+ signode += addnodes.desc_parameterlist()
+
+ stack = [signode[-1]]
+ for token in py_paramlist_re.split(arglist):
+ if token == '[':
+ opt = addnodes.desc_optional()
+ stack[-1] += opt
+ stack.append(opt)
+ elif token == ']':
+ try:
+ stack.pop()
+ except IndexError:
+ raise ValueError
+ elif not token or token == ',' or token.isspace():
+ pass
+ else:
+ token = token.strip()
+ stack[-1] += addnodes.desc_parameter(token, token)
+ if len(stack) != 1:
+ raise ValueError
+ if retann:
+ signode += addnodes.desc_returns(retann, retann)
+ return fullname, classname
+
+ def get_index_text(self, modname, name):
+ """
+ Return the text for the index entry of the object.
+ """
+ raise NotImplementedError('must be implemented in subclasses')
+
+ def add_target_and_index(self, name_cls, sig, signode):
+ modname = self.options.get('module', self.env.currmodule)
+ fullname = (modname and modname + '.' or '') + name_cls[0]
+ # note target
+ if fullname not in self.state.document.ids:
+ signode['names'].append(fullname)
+ signode['ids'].append(fullname)
+ signode['first'] = (not self.names)
+ self.state.document.note_explicit_target(signode)
+ objects = self.env.domaindata['py']['objects']
+ if fullname in objects:
+ self.env.warn(
+ self.env.docname,
+ 'duplicate object description of %s, ' % fullname +
+ 'other instance in ' +
+ self.env.doc2path(objects[fullname][0]),
+ self.lineno)
+ objects[fullname] = (self.env.docname, self.desctype)
+
+ indextext = self.get_index_text(modname, name_cls)
+ if indextext:
+ self.indexnode['entries'].append(('single', indextext,
+ fullname, fullname))
+
+ def before_content(self):
+ # needed for automatic qualification of members (reset in subclasses)
+ self.clsname_set = False
+
+ def after_content(self):
+ if self.clsname_set:
+ self.env.currclass = None
+
+
+class ModulelevelDesc(PythonDesc):
+ """
+ Description of an object on module level (functions, data).
+ """
+
+ def needs_arglist(self):
+ return self.desctype == 'function'
+
+ def get_index_text(self, modname, name_cls):
+ if self.desctype == 'function':
+ if not modname:
+ return _('%s() (built-in function)') % name_cls[0]
+ return _('%s() (in module %s)') % (name_cls[0], modname)
+ elif self.desctype == 'data':
+ if not modname:
+ return _('%s (built-in variable)') % name_cls[0]
+ return _('%s (in module %s)') % (name_cls[0], modname)
+ else:
+ return ''
+
+
+class ClasslikeDesc(PythonDesc):
+ """
+ Description of a class-like object (classes, interfaces, exceptions).
+ """
+
+ def get_signature_prefix(self, sig):
+ return self.desctype + ' '
+
+ def get_index_text(self, modname, name_cls):
+ if self.desctype == 'class':
+ if not modname:
+ return _('%s (built-in class)') % name_cls[0]
+ return _('%s (class in %s)') % (name_cls[0], modname)
+ elif self.desctype == 'exception':
+ return name_cls[0]
+ else:
+ return ''
+
+ def before_content(self):
+ PythonDesc.before_content(self)
+ if self.names:
+ self.env.currclass = self.names[0][0]
+ self.clsname_set = True
+
+
+class ClassmemberDesc(PythonDesc):
+ """
+ Description of a class member (methods, attributes).
+ """
+
+ def needs_arglist(self):
+ return self.desctype.endswith('method')
+
+ def get_signature_prefix(self, sig):
+ if self.desctype == 'staticmethod':
+ return 'static '
+ elif self.desctype == 'classmethod':
+ return 'classmethod '
+ return ''
+
+ def get_index_text(self, modname, name_cls):
+ name, cls = name_cls
+ add_modules = self.env.config.add_module_names
+ if self.desctype == 'method':
+ try:
+ clsname, methname = name.rsplit('.', 1)
+ except ValueError:
+ if modname:
+ return _('%s() (in module %s)') % (name, modname)
+ else:
+ return '%s()' % name
+ if modname and add_modules:
+ return _('%s() (%s.%s method)') % (methname, modname, clsname)
+ else:
+ return _('%s() (%s method)') % (methname, clsname)
+ elif self.desctype == 'staticmethod':
+ try:
+ clsname, methname = name.rsplit('.', 1)
+ except ValueError:
+ if modname:
+ return _('%s() (in module %s)') % (name, modname)
+ else:
+ return '%s()' % name
+ if modname and add_modules:
+ return _('%s() (%s.%s static method)') % (methname, modname,
+ clsname)
+ else:
+ return _('%s() (%s static method)') % (methname, clsname)
+ elif self.desctype == 'classmethod':
+ try:
+ clsname, methname = name.rsplit('.', 1)
+ except ValueError:
+ if modname:
+ return _('%s() (in module %s)') % (name, modname)
+ else:
+ return '%s()' % name
+ if modname:
+ return _('%s() (%s.%s class method)') % (methname, modname,
+ clsname)
+ else:
+ return _('%s() (%s class method)') % (methname, clsname)
+ elif self.desctype == 'attribute':
+ try:
+ clsname, attrname = name.rsplit('.', 1)
+ except ValueError:
+ if modname:
+ return _('%s (in module %s)') % (name, modname)
+ else:
+ return name
+ if modname and add_modules:
+ return _('%s (%s.%s attribute)') % (attrname, modname, clsname)
+ else:
+ return _('%s (%s attribute)') % (attrname, clsname)
+ else:
+ return ''
+
+ def before_content(self):
+ PythonDesc.before_content(self)
+ if self.names and self.names[-1][1] and not self.env.currclass:
+ self.env.currclass = self.names[-1][1].strip('.')
+ self.clsname_set = True
+
+
+class PyModule(Directive):
+ """
+ Directive to mark description of a new module.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {
+ 'platform': lambda x: x,
+ 'synopsis': lambda x: x,
+ 'noindex': directives.flag,
+ 'deprecated': directives.flag,
+ }
+
+ def run(self):
+ env = self.state.document.settings.env
+ modname = self.arguments[0].strip()
+ noindex = 'noindex' in self.options
+ env.currmodule = modname
+ env.domaindata['py']['modules'][modname] = \
+ (env.docname, self.options.get('synopsis', ''),
+ self.options.get('platform', ''), 'deprecated' in self.options)
+ modulenode = addnodes.module()
+ modulenode['modname'] = modname
+ modulenode['synopsis'] = self.options.get('synopsis', '')
+ targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True)
+ self.state.document.note_explicit_target(targetnode)
+ ret = [modulenode, targetnode]
+ if 'platform' in self.options:
+ platform = self.options['platform']
+ modulenode['platform'] = platform
+ node = nodes.paragraph()
+ node += nodes.emphasis('', _('Platforms: '))
+ node += nodes.Text(platform, platform)
+ ret.append(node)
+ # the synopsis isn't printed; in fact, it is only used in the
+ # modindex currently
+ if not noindex:
+ indextext = _('%s (module)') % modname
+ inode = addnodes.index(entries=[('single', indextext,
+ 'module-' + modname, modname)])
+ ret.insert(0, inode)
+ return ret
+
+
+class PyCurrentModule(Directive):
+ """
+ This directive is just to tell Sphinx that we're documenting
+ stuff in module foo, but links to module foo won't lead here.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ modname = self.arguments[0].strip()
+ if modname == 'None':
+ env.currmodule = None
+ else:
+ env.currmodule = modname
+ return []
+
+
+class PyXRefRole(XRefRole):
+ def process_link(self, env, pnode, has_explicit_title, title, target):
+ pnode['modname'] = env.currmodule
+ pnode['classname'] = env.currclass
+ if not has_explicit_title:
+ title = title.lstrip('.') # only has a meaning for the target
+ target = target.lstrip('~') # only has a meaning for the title
+ # if the first character is a tilde, don't display the module/class
+ # parts of the contents
+ if title[0:1] == '~':
+ title = title[1:]
+ dot = title.rfind('.')
+ if dot != -1:
+ title = title[dot+1:]
+ # if the first character is a dot, search more specific namespaces first
+ # else search builtins first
+ if target[0:1] == '.':
+ target = target[1:]
+ pnode['refspecific'] = True
+ return title, target
+
+
+class PythonDomain(Domain):
+ """Python language domain."""
+ name = 'py'
+ label = 'Python'
+ directives = {
+ 'function': ModulelevelDesc,
+ 'data': ModulelevelDesc,
+ 'class': ClasslikeDesc,
+ 'exception': ClasslikeDesc,
+ 'method': ClassmemberDesc,
+ 'classmethod': ClassmemberDesc,
+ 'staticmethod': ClassmemberDesc,
+ 'attribute': ClassmemberDesc,
+ 'module': PyModule,
+ 'currentmodule': PyCurrentModule,
+ }
+ roles = {
+ 'data': PyXRefRole(),
+ 'exc': PyXRefRole(),
+ 'func': PyXRefRole(fix_parens=True),
+ 'class': PyXRefRole(),
+ 'const': PyXRefRole(),
+ 'attr': PyXRefRole(),
+ 'meth': PyXRefRole(fix_parens=True),
+ 'mod': PyXRefRole(),
+ 'obj': PyXRefRole(),
+ }
+ initial_data = {
+ 'objects': {}, # fullname -> docname, desctype
+ 'modules': {}, # modname -> docname, synopsis, platform, deprecated
+ }
+
+ def clear_doc(self, docname):
+ for fullname, (fn, _) in self.data['objects'].items():
+ if fn == docname:
+ del self.data['objects'][fullname]
+ for modname, (fn, _, _, _) in self.data['modules'].items():
+ if fn == docname:
+ del self.data['modules'][modname]
+
+ def find_desc(self, env, modname, classname, name, type, searchorder=0):
+ """
+ Find a Python object description for "name", perhaps using the given
+ module and/or classname.
+ """
+ # skip parens
+ if name[-2:] == '()':
+ name = name[:-2]
+
+ if not name:
+ return None, None
+
+ objects = self.data['objects']
+
+ newname = None
+ if searchorder == 1:
+ if modname and classname and \
+ modname + '.' + classname + '.' + name in objects:
+ newname = modname + '.' + classname + '.' + name
+ elif modname and modname + '.' + name in objects:
+ newname = modname + '.' + name
+ elif name in objects:
+ newname = name
+ else:
+ if name in objects:
+ newname = name
+ elif modname and modname + '.' + name in objects:
+ newname = modname + '.' + name
+ elif modname and classname and \
+ modname + '.' + classname + '.' + name in objects:
+ newname = modname + '.' + classname + '.' + name
+ # special case: builtin exceptions have module "exceptions" set
+ elif type == 'exc' and '.' not in name and \
+ 'exceptions.' + name in objects:
+ newname = 'exceptions.' + name
+ # special case: object methods
+ elif type in ('func', 'meth') and '.' not in name and \
+ 'object.' + name in objects:
+ newname = 'object.' + name
+ if newname is None:
+ return None, None
+ return newname, objects[newname]
+
+ def resolve_xref(self, env, fromdocname, builder,
+ typ, target, node, contnode):
+ if (typ == 'mod' or
+ typ == 'obj' and target in self.data['modules']):
+ docname, synopsis, platform, deprecated = \
+ self.data['modules'].get(target, ('','','', ''))
+ if not docname:
+ return None
+ elif docname == fromdocname:
+ # don't link to self
+ return contnode
+ else:
+ title = '%s%s%s' % ((platform and '(%s) ' % platform),
+ synopsis,
+ (deprecated and ' (deprecated)' or ''))
+ return make_refnode(builder, fromdocname, docname,
+ 'module-' + target, contnode, title)
+ else:
+ modname = node['modname']
+ clsname = node['classname']
+ searchorder = node.hasattr('refspecific') and 1 or 0
+ name, desc = self.find_desc(env, modname, clsname,
+ target, typ, searchorder)
+ if not desc:
+ return None
+ else:
+ return make_refnode(builder, fromdocname, desc[0], name,
+ contnode, name)
+
+
+
+# RE to split at word boundaries
+wsplit_re = re.compile(r'(\W+)')
+
+# REs for C signatures
+c_sig_re = re.compile(
+ r'''^([^(]*?) # return type
+ ([\w:]+) \s* # thing name (colon allowed for C++ class names)
+ (?: \((.*)\) )? # optionally arguments
+ (\s+const)? $ # const specifier
+ ''', re.VERBOSE)
+c_funcptr_sig_re = re.compile(
+ r'''^([^(]+?) # return type
+ (\( [^()]+ \)) \s* # name in parentheses
+ \( (.*) \) # arguments
+ (\s+const)? $ # const specifier
+ ''', re.VERBOSE)
+c_funcptr_name_re = re.compile(r'^\(\s*\*\s*(.*?)\s*\)$')
+
+
+class CDesc(DescDirective):
+ """
+ Description of a C language object.
+ """
+
+ # These C types aren't described anywhere, so don't try to create
+ # a cross-reference to them
+ stopwords = set(('const', 'void', 'char', 'int', 'long', 'FILE', 'struct'))
+
+ def _parse_type(self, node, ctype):
+ # add cross-ref nodes for all words
+ for part in filter(None, wsplit_re.split(ctype)):
+ tnode = nodes.Text(part, part)
+ if part[0] in string.ascii_letters+'_' and \
+ part not in self.stopwords:
+ pnode = addnodes.pending_xref(
+ '', refdomain='c', reftype='type', reftarget=part,
+ modname=None, classname=None)
+ pnode += tnode
+ node += pnode
+ else:
+ node += tnode
+
+ def parse_signature(self, sig, signode):
+ """Transform a C (or C++) signature into RST nodes."""
+ # first try the function pointer signature regex, it's more specific
+ m = c_funcptr_sig_re.match(sig)
+ if m is None:
+ m = c_sig_re.match(sig)
+ if m is None:
+ raise ValueError('no match')
+ rettype, name, arglist, const = m.groups()
+
+ signode += addnodes.desc_type('', '')
+ self._parse_type(signode[-1], rettype)
+ try:
+ classname, funcname = name.split('::', 1)
+ classname += '::'
+ signode += addnodes.desc_addname(classname, classname)
+ signode += addnodes.desc_name(funcname, funcname)
+ # name (the full name) is still both parts
+ except ValueError:
+ signode += addnodes.desc_name(name, name)
+ # clean up parentheses from canonical name
+ m = c_funcptr_name_re.match(name)
+ if m:
+ name = m.group(1)
+ if not arglist:
+ if self.desctype == 'cfunction':
+ # for functions, add an empty parameter list
+ signode += addnodes.desc_parameterlist()
+ if const:
+ signode += addnodes.desc_addname(const, const)
+ return name
+
+ paramlist = addnodes.desc_parameterlist()
+ arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
+ # this messes up function pointer types, but not too badly ;)
+ args = arglist.split(',')
+ for arg in args:
+ arg = arg.strip()
+ param = addnodes.desc_parameter('', '', noemph=True)
+ try:
+ ctype, argname = arg.rsplit(' ', 1)
+ except ValueError:
+ # no argument name given, only the type
+ self._parse_type(param, arg)
+ else:
+ self._parse_type(param, ctype)
+ param += nodes.emphasis(' '+argname, ' '+argname)
+ paramlist += param
+ signode += paramlist
+ if const:
+ signode += addnodes.desc_addname(const, const)
+ return name
+
+ def get_index_text(self, name):
+ if self.desctype == 'cfunction':
+ return _('%s (C function)') % name
+ elif self.desctype == 'cmember':
+ return _('%s (C member)') % name
+ elif self.desctype == 'cmacro':
+ return _('%s (C macro)') % name
+ elif self.desctype == 'ctype':
+ return _('%s (C type)') % name
+ elif self.desctype == 'cvar':
+ return _('%s (C variable)') % name
+ else:
+ return ''
+
+ def add_target_and_index(self, name, sig, signode):
+ # note target
+ if name not in self.state.document.ids:
+ signode['names'].append(name)
+ signode['ids'].append(name)
+ signode['first'] = (not self.names)
+ self.state.document.note_explicit_target(signode)
+ inv = self.env.domaindata['c']['objects']
+ if name in inv:
+ self.env.warn(
+ self.env.docname,
+ 'duplicate C object description of %s, ' % name +
+ 'other instance in ' + self.env.doc2path(inv[name][0]),
+ self.lineno)
+ inv[name] = (self.env.docname, self.desctype)
+
+ indextext = self.get_index_text(name)
+ if indextext:
+ self.indexnode['entries'].append(('single', indextext, name, name))
+
+
+class CDomain(Domain):
+ """C language domain."""
+ name = 'c'
+ label = 'C'
+ directives = {
+ 'function': CDesc,
+ 'member': CDesc,
+ 'macro': CDesc,
+ 'type': CDesc,
+ 'var': CDesc,
+ }
+ roles = {
+ 'member': XRefRole(),
+ 'macro': XRefRole(),
+ 'func' : XRefRole(fix_parens=True),
+ 'data': XRefRole(),
+ 'type': XRefRole(),
+ }
+ initial_data = {
+ 'objects': {}, # fullname -> docname, desctype
+ }
+
+ def clear_doc(self, docname):
+ for fullname, (fn, _) in self.data['objects'].items():
+ if fn == docname:
+ del self.data['objects'][fullname]
+
+ def resolve_xref(self, env, fromdocname, builder,
+ typ, target, node, contnode):
+ # strip pointer asterisk
+ target = target.rstrip(' *')
+ if target not in self.data:
+ return None
+ desc = self.data[target]
+ return make_refnode(builder, fromdocname, desc[0], contnode, target)
+
+
+# this contains all registered domains
+all_domains = {
+ 'py': PythonDomain,
+ 'c': CDomain,
+}
diff --git a/sphinx/environment.py b/sphinx/environment.py
index d04fcbf9..bd93c91c 100644
--- a/sphinx/environment.py
+++ b/sphinx/environment.py
@@ -28,7 +28,7 @@ from docutils.io import FileInput, NullOutput
from docutils.core import Publisher
from docutils.utils import Reporter, relative_path
from docutils.readers import standalone
-from docutils.parsers.rst import roles
+from docutils.parsers.rst import roles, directives
from docutils.parsers.rst.languages import en as english
from docutils.parsers.rst.directives.html import MetaBody
from docutils.writers import UnfilteredWriter
@@ -37,10 +37,13 @@ from docutils.transforms.parts import ContentsFilter
from sphinx import addnodes
from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \
- docname_join, FilenameUniqDict, url_re
-from sphinx.errors import SphinxError
+ docname_join, FilenameUniqDict, url_re, make_refnode
+from sphinx.errors import SphinxError, ExtensionError
from sphinx.directives import additional_xref_types
+orig_role_function = roles.role
+orig_directive_function = directives.directive
+
default_settings = {
'embed_stylesheet': False,
'cloak_email_addresses': True,
@@ -53,7 +56,7 @@ default_settings = {
# This is increased every time an environment attribute is added
# or changed to properly invalidate pickle files.
-ENV_VERSION = 30
+ENV_VERSION = 31
default_substitutions = set([
@@ -204,9 +207,9 @@ class BuildEnvironment:
env = pickle.load(picklefile)
finally:
picklefile.close()
- env.config.values = config.values
if env.version != ENV_VERSION:
raise IOError('env version not current')
+ env.config.values = config.values
return env
def topickle(self, filename):
@@ -215,6 +218,8 @@ class BuildEnvironment:
self.set_warnfunc(None)
values = self.config.values
del self.config.values
+ domains = self.domains
+ del self.domains
# first write to a temporary file, so that if dumping fails,
# the existing environment won't be overwritten
picklefile = open(filename + '.tmp', 'wb')
@@ -231,6 +236,7 @@ class BuildEnvironment:
picklefile.close()
movefile(filename + '.tmp', filename)
# reset attributes
+ self.domains = domains
self.config.values = values
self.set_warnfunc(warnfunc)
@@ -244,6 +250,9 @@ class BuildEnvironment:
# the application object; only set while update() runs
self.app = None
+ # all the registered domains, set by the application
+ self.domains = {}
+
# the docutils settings for building
self.settings = default_settings.copy()
self.settings['env'] = self
@@ -282,11 +291,10 @@ class BuildEnvironment:
self.glob_toctrees = set() # docnames that have :glob: toctrees
self.numbered_toctrees = set() # docnames that have :numbered: toctrees
+ # domain-specific inventories, here to be pickled
+ self.domaindata = {} # domainname -> domain-specific object
+
# X-ref target inventory
- self.descrefs = {} # fullname -> docname, desctype
- self.filemodules = {} # docname -> [modules]
- self.modules = {} # modname -> docname, synopsis,
- # platform, deprecated
self.labels = {} # labelname -> docname, labelid, sectionname
self.anonlabels = {} # labelname -> docname, labelid
self.progoptions = {} # (program, name) -> docname, labelid
@@ -305,6 +313,7 @@ class BuildEnvironment:
# These are set while parsing a file
self.docname = None # current document name
+ # XXX remove currmodule and currclass from here
self.currmodule = None # current module name
self.currclass = None # current class name
self.currdesc = None # current descref name
@@ -344,7 +353,6 @@ class BuildEnvironment:
self.toc_secnumbers.pop(docname, None)
self.toc_num_entries.pop(docname, None)
self.toctree_includes.pop(docname, None)
- self.filemodules.pop(docname, None)
self.indexentries.pop(docname, None)
self.glob_toctrees.discard(docname)
self.numbered_toctrees.discard(docname)
@@ -355,12 +363,6 @@ class BuildEnvironment:
fnset.discard(docname)
if not fnset:
del self.files_to_rebuild[subfn]
- for fullname, (fn, _) in self.descrefs.items():
- if fn == docname:
- del self.descrefs[fullname]
- for modname, (fn, _, _, _) in self.modules.items():
- if fn == docname:
- del self.modules[modname]
for labelname, (fn, _, _) in self.labels.items():
if fn == docname:
del self.labels[labelname]
@@ -374,6 +376,10 @@ class BuildEnvironment:
new = [change for change in changes if change[1] != docname]
changes[:] = new
+ # XXX why does this not work inside the if?
+ for domain in self.domains.values():
+ domain.clear_doc(docname)
+
def doc2path(self, docname, base=True, suffix=None):
"""
Return the filename for the document name.
@@ -553,6 +559,7 @@ class BuildEnvironment:
# remove all inventory entries for that file
if app:
app.emit('env-purge-doc', self, docname)
+
self.clear_doc(docname)
if src_path is None:
@@ -591,6 +598,44 @@ class BuildEnvironment:
else:
return data
+ # defaults to the global default, but can be re-set in a document
+ self.default_domain = self.domains.get(self.config.default_domain)
+
+ # monkey-patch, so that domain directives take precedence
+ def directive(directive_name, language_module, document):
+ directive_name = directive_name.lower()
+ if ':' in directive_name:
+ domain_name, directive_name = directive_name.split(':', 1)
+ if domain_name in self.domains:
+ domain = self.domains[domain_name]
+ directive = domain.directive(directive_name)
+ if directive is not None:
+ return directive, []
+ elif self.default_domain is not None:
+ directive = self.default_domain.directive(directive_name)
+ if directive is not None:
+ return directive, []
+ return orig_directive_function(directive_name, language_module,
+ document)
+ directives.directive = directive
+
+ def role(role_name, language_module, lineno, reporter):
+ role_name = role_name.lower()
+ if ':' in role_name:
+ domain_name, role_name = role_name.split(':', 1)
+ if domain_name in self.domains:
+ domain = self.domains[domain_name]
+ role = domain.role(role_name)
+ if role is not None:
+ return role, []
+ elif self.default_domain is not None:
+ role = self.default_domain.role(role_name)
+ if role is not None:
+ return role, []
+ return orig_role_function(role_name, language_module,
+ lineno, reporter)
+ roles.role = role
+
# publish manually
pub = Publisher(reader=SphinxStandaloneReader(),
writer=SphinxDummyWriter(),
@@ -636,6 +681,7 @@ class BuildEnvironment:
self.docname = None
self.currmodule = None
self.currclass = None
+ self.default_domain = None
self.gloss_entries = set()
if save_parsed:
@@ -945,19 +991,6 @@ class BuildEnvironment:
# -------
# these are called from docutils directives and therefore use self.docname
#
- def note_descref(self, fullname, desctype, line):
- if fullname in self.descrefs:
- self.warn(self.docname,
- 'duplicate canonical description name %s, ' % fullname +
- 'other instance in ' +
- self.doc2path(self.descrefs[fullname][0]),
- line)
- self.descrefs[fullname] = (self.docname, desctype)
-
- def note_module(self, modname, synopsis, platform, deprecated):
- self.modules[modname] = (self.docname, synopsis, platform, deprecated)
- self.filemodules.setdefault(self.docname, []).append(modname)
-
def note_progoption(self, optname, labelid):
self.progoptions[self.currprogram, optname] = (self.docname, labelid)
@@ -973,6 +1006,14 @@ class BuildEnvironment:
self.dependencies.setdefault(self.docname, set()).add(filename)
# -------
+ def get_domain(self, domainname):
+ """Return the domain instance with the specified name.
+ Raises an ExtensionError if the domain is not registered."""
+ try:
+ return self.domains[domainname]
+ except KeyError:
+ raise ExtensionError('Domain %r is not registered' % domainname)
+
# --------- RESOLVING REFERENCES AND TOCTREES ------------------------------
def get_doctree(self, docname):
@@ -1155,11 +1196,8 @@ class BuildEnvironment:
docname, refnode['refuri']) + refnode['anchorname']
return newnode
- descroles = frozenset(('data', 'exc', 'func', 'class', 'const',
- 'attr', 'obj', 'meth', 'cfunc', 'cmember',
- 'cdata', 'ctype', 'cmacro'))
-
def resolve_references(self, doctree, fromdocname, builder):
+ # XXX remove this
reftarget_roles = set(('token', 'term', 'citation'))
# add all custom xref types too
reftarget_roles.update(i[0] for i in additional_xref_types.values())
@@ -1172,7 +1210,15 @@ class BuildEnvironment:
target = node['reftarget']
try:
- if typ == 'ref':
+ if node.has_key('refdomain') and node['refdomain']:
+ # let the domain try to resolve the reference
+ try:
+ domain = self.domains[node['refdomain']]
+ except KeyError:
+ raise NoUri
+ newnode = domain.resolve_xref(self, fromdocname, builder,
+ typ, target, node, contnode)
+ elif typ == 'ref':
if node['refcaption']:
# reference to anonymous label; the reference uses
# the supplied link caption
@@ -1237,13 +1283,8 @@ class BuildEnvironment:
#self.warn(fromdocname, 'unknown keyword: %s' % target)
newnode = contnode
else:
- newnode = nodes.reference('', '')
- if docname == fromdocname:
- newnode['refid'] = labelid
- else:
- newnode['refuri'] = builder.get_relative_uri(
- fromdocname, docname) + '#' + labelid
- newnode.append(contnode)
+ newnode = make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
elif typ == 'option':
progname = node['refprogram']
docname, labelid = self.progoptions.get((progname, target),
@@ -1251,13 +1292,8 @@ class BuildEnvironment:
if not docname:
newnode = contnode
else:
- newnode = nodes.reference('', '')
- if docname == fromdocname:
- newnode['refid'] = labelid
- else:
- newnode['refuri'] = builder.get_relative_uri(
- fromdocname, docname) + '#' + labelid
- newnode.append(contnode)
+ newnode = make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
elif typ in reftarget_roles:
docname, labelid = self.reftargets.get((typ, target),
('', ''))
@@ -1272,62 +1308,19 @@ class BuildEnvironment:
node.line)
newnode = contnode
else:
- newnode = nodes.reference('', '')
- if docname == fromdocname:
- newnode['refid'] = labelid
- else:
- newnode['refuri'] = builder.get_relative_uri(
- fromdocname, docname, typ) + '#' + labelid
- newnode.append(contnode)
- elif typ == 'mod' or \
- typ == 'obj' and target in self.modules:
- docname, synopsis, platform, deprecated = \
- self.modules.get(target, ('','','', ''))
- if not docname:
- newnode = builder.app.emit_firstresult(
- 'missing-reference', self, node, contnode)
- if not newnode:
- newnode = contnode
- elif docname == fromdocname:
- # don't link to self
- newnode = contnode
- else:
- newnode = nodes.reference('', '')
- newnode['refuri'] = builder.get_relative_uri(
- fromdocname, docname) + '#module-' + target
- newnode['reftitle'] = '%s%s%s' % (
- (platform and '(%s) ' % platform),
- synopsis, (deprecated and ' (deprecated)' or ''))
- newnode.append(contnode)
- elif typ in self.descroles:
- # "descrefs"
- modname = node['modname']
- clsname = node['classname']
- searchorder = node.hasattr('refspecific') and 1 or 0
- name, desc = self.find_desc(modname, clsname,
- target, typ, searchorder)
- if not desc:
- newnode = builder.app.emit_firstresult(
- 'missing-reference', self, node, contnode)
- if not newnode:
- newnode = contnode
- else:
- newnode = nodes.reference('', '')
- if desc[0] == fromdocname:
- newnode['refid'] = name
- else:
- newnode['refuri'] = (
- builder.get_relative_uri(fromdocname, desc[0])
- + '#' + name)
- newnode['reftitle'] = name
- newnode.append(contnode)
+ newnode = make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
else:
raise RuntimeError('unknown xfileref node encountered: %s'
% node)
+
+ # no new node found? try the missing-reference event
+ if newnode is None:
+ newnode = builder.app.emit_firstresult(
+ 'missing-reference', self, node, contnode)
except NoUri:
newnode = contnode
- if newnode:
- node.replace_self(newnode)
+ node.replace_self(newnode or contnode)
for node in doctree.traverse(addnodes.only):
try:
@@ -1558,116 +1551,3 @@ class BuildEnvironment:
# the master file is not included anywhere ;)
continue
self.warn(docname, 'document isn\'t included in any toctree')
-
- # --------- QUERYING -------------------------------------------------------
-
- def find_desc(self, modname, classname, name, type, searchorder=0):
- """Find a description node matching "name", perhaps using
- the given module and/or classname."""
- # skip parens
- if name[-2:] == '()':
- name = name[:-2]
-
- if not name:
- return None, None
-
- # don't add module and class names for C things
- if type[0] == 'c' and type not in ('class', 'const'):
- # skip trailing star and whitespace
- name = name.rstrip(' *')
- if name in self.descrefs and self.descrefs[name][1][0] == 'c':
- return name, self.descrefs[name]
- return None, None
-
- newname = None
- if searchorder == 1:
- if modname and classname and \
- modname + '.' + classname + '.' + name in self.descrefs:
- newname = modname + '.' + classname + '.' + name
- elif modname and modname + '.' + name in self.descrefs:
- newname = modname + '.' + name
- elif name in self.descrefs:
- newname = name
- else:
- if name in self.descrefs:
- newname = name
- elif modname and modname + '.' + name in self.descrefs:
- newname = modname + '.' + name
- elif modname and classname and \
- modname + '.' + classname + '.' + name in self.descrefs:
- newname = modname + '.' + classname + '.' + name
- # special case: builtin exceptions have module "exceptions" set
- elif type == 'exc' and '.' not in name and \
- 'exceptions.' + name in self.descrefs:
- newname = 'exceptions.' + name
- # special case: object methods
- elif type in ('func', 'meth') and '.' not in name and \
- 'object.' + name in self.descrefs:
- newname = 'object.' + name
- if newname is None:
- return None, None
- return newname, self.descrefs[newname]
-
- def find_keyword(self, keyword, avoid_fuzzy=False, cutoff=0.6, n=20):
- """
- Find keyword matches for a keyword. If there's an exact match,
- just return it, else return a list of fuzzy matches if avoid_fuzzy
- isn't True.
-
- Keywords searched are: first modules, then descrefs.
-
- Returns: None if nothing found
- (type, docname, anchorname) if exact match found
- list of (quality, type, docname, anchorname, description)
- if fuzzy
- """
-
- if keyword in self.modules:
- docname, title, system, deprecated = self.modules[keyword]
- return 'module', docname, 'module-' + keyword
- if keyword in self.descrefs:
- docname, ref_type = self.descrefs[keyword]
- return ref_type, docname, keyword
- # special cases
- if '.' not in keyword:
- # exceptions are documented in the exceptions module
- if 'exceptions.'+keyword in self.descrefs:
- docname, ref_type = self.descrefs['exceptions.'+keyword]
- return ref_type, docname, 'exceptions.'+keyword
- # special methods are documented as object methods
- if 'object.'+keyword in self.descrefs:
- docname, ref_type = self.descrefs['object.'+keyword]
- return ref_type, docname, 'object.'+keyword
-
- if avoid_fuzzy:
- return
-
- # find fuzzy matches
- s = difflib.SequenceMatcher()
- s.set_seq2(keyword.lower())
-
- def possibilities():
- for title, (fn, desc, _, _) in self.modules.iteritems():
- yield ('module', fn, 'module-'+title, desc)
- for title, (fn, desctype) in self.descrefs.iteritems():
- yield (desctype, fn, title, '')
-
- def dotsearch(string):
- parts = string.lower().split('.')
- for idx in xrange(0, len(parts)):
- yield '.'.join(parts[idx:])
-
- result = []
- for type, docname, title, desc in possibilities():
- best_res = 0
- for part in dotsearch(title):
- s.set_seq1(part)
- if s.real_quick_ratio() >= cutoff and \
- s.quick_ratio() >= cutoff and \
- s.ratio() >= cutoff and \
- s.ratio() > best_res:
- best_res = s.ratio()
- if best_res:
- result.append((best_res, type, docname, title, desc))
-
- return heapq.nlargest(n, result)
diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py
index dc641674..09212eed 100644
--- a/sphinx/ext/autosummary/__init__.py
+++ b/sphinx/ext/autosummary/__init__.py
@@ -226,7 +226,7 @@ class Autosummary(Directive):
``[(name, signature, summary_string, real_name), ...]``.
"""
env = self.state.document.settings.env
-
+
prefixes = ['']
if env.currmodule:
prefixes.insert(0, env.currmodule)
@@ -443,8 +443,9 @@ def autolink_role(typ, rawtext, etext, lineno, inliner,
Expands to ':obj:`text`' if `text` is an object that can be imported;
otherwise expands to '*text*'.
"""
- r = roles.xfileref_role('obj', rawtext, etext, lineno, inliner,
- options, content)
+ env = inliner.document.settings.env
+ r = env.get_domain('py').role('obj')(
+ 'obj', rawtext, etext, lineno, inliner, options, content)
pnode = r[0][0]
prefixes = [None]
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py
index f8447e94..568ee99f 100644
--- a/sphinx/ext/autosummary/generate.py
+++ b/sphinx/ext/autosummary/generate.py
@@ -233,9 +233,12 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
corresponding options set.
"""
autosummary_re = re.compile(r'^\s*\.\.\s+autosummary::\s*')
- automodule_re = re.compile(r'^\s*\.\.\s+automodule::\s*([A-Za-z0-9_.]+)\s*$')
- module_re = re.compile(r'^\s*\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$')
- autosummary_item_re = re.compile(r'^\s+(~?[_a-zA-Z][a-zA-Z0-9_.]*)\s*.*?')
+ automodule_re = re.compile(
+ r'^\s*\.\.\s+automodule::\s*([A-Za-z0-9_.]+)\s*$')
+ module_re = re.compile(
+ r'^\s*\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$')
+ autosummary_item_re = re.compile(
+ r'^\s+(~?[_a-zA-Z][a-zA-Z0-9_.]*)\s*.*?')
toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$')
template_arg_re = re.compile(r'^\s+:template:\s*(.*?)\s*$')
diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py
index 964e58ee..ed5d92a4 100644
--- a/sphinx/ext/coverage.py
+++ b/sphinx/ext/coverage.py
@@ -79,6 +79,7 @@ class CoverageBuilder(Builder):
def build_c_coverage(self):
# Fetch all the info from the header files
+ c_objects = self.env.domaindata['c']['objects']
for filename in self.c_sourcefiles:
undoc = []
f = open(filename, 'r')
@@ -88,7 +89,7 @@ class CoverageBuilder(Builder):
match = regex.match(line)
if match:
name = match.groups()[0]
- if name not in self.env.descrefs:
+ if name not in c_objects:
for exp in self.c_ignorexps.get(key, ()):
if exp.match(name):
break
@@ -116,7 +117,10 @@ class CoverageBuilder(Builder):
op.close()
def build_py_coverage(self):
- for mod_name in self.env.modules:
+ objects = self.env.domaindata['py']['objects']
+ modules = self.env.domaindata['py']['modules']
+
+ for mod_name in modules:
ignore = False
for exp in self.mod_ignorexps:
if exp.match(mod_name):
@@ -151,7 +155,7 @@ class CoverageBuilder(Builder):
full_name = '%s.%s' % (mod_name, name)
if inspect.isfunction(obj):
- if full_name not in self.env.descrefs:
+ if full_name not in objects:
for exp in self.fun_ignorexps:
if exp.match(name):
break
@@ -162,7 +166,7 @@ class CoverageBuilder(Builder):
if exp.match(name):
break
else:
- if full_name not in self.env.descrefs:
+ if full_name not in objects:
# not documented at all
classes[name] = []
continue
@@ -176,7 +180,7 @@ class CoverageBuilder(Builder):
continue
full_attr_name = '%s.%s' % (full_name, attr_name)
- if full_attr_name not in self.env.descrefs:
+ if full_attr_name not in objects:
attrs.append(attr_name)
if attrs:
diff --git a/sphinx/ext/ifconfig.py b/sphinx/ext/ifconfig.py
index 90cd2b2c..1bc66af8 100644
--- a/sphinx/ext/ifconfig.py
+++ b/sphinx/ext/ifconfig.py
@@ -41,7 +41,8 @@ class IfConfig(Directive):
node.document = self.state.document
node.line = self.lineno
node['expr'] = self.arguments[0]
- self.state.nested_parse(self.content, self.content_offset, node)
+ self.state.nested_parse(self.content, self.content_offset,
+ node, match_titles=1)
return [node]
diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py
index 35790731..e464adb5 100644
--- a/sphinx/ext/inheritance_diagram.py
+++ b/sphinx/ext/inheritance_diagram.py
@@ -47,7 +47,6 @@ except ImportError:
from docutils import nodes
from docutils.parsers.rst import directives
-from sphinx.roles import xfileref_role
from sphinx.ext.graphviz import render_dot_html, render_dot_latex
from sphinx.util.compat import Directive
@@ -280,6 +279,7 @@ class InheritanceDiagram(Directive):
node.document = self.state.document
env = self.state.document.settings.env
class_names = self.arguments[0].split()
+ class_role = env.get_domain('py').role('class')
# Create a graph starting with the list of classes
try:
@@ -293,7 +293,7 @@ class InheritanceDiagram(Directive):
# references to real URLs later. These nodes will eventually be
# removed from the doctree after we're done with them.
for name in graph.get_all_class_names():
- refnodes, x = xfileref_role(
+ refnodes, x = class_role(
'class', ':class:`%s`' % name, name, 0, self.state)
node.extend(refnodes)
# Store the graph object so we can use it to generate the
diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py
index 91f7c101..e2c96a96 100644
--- a/sphinx/jinja2glue.py
+++ b/sphinx/jinja2glue.py
@@ -93,7 +93,7 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
# make the paths into loaders
self.loaders = map(SphinxFileSystemLoader, chain)
- use_i18n = builder.translator is not None
+ use_i18n = builder.app.translator is not None
extensions = use_i18n and ['jinja2.ext.i18n'] or []
self.environment = SandboxedEnvironment(loader=self,
extensions=extensions)
@@ -101,7 +101,7 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
self.environment.globals['debug'] = contextfunction(pformat)
self.environment.globals['accesskey'] = contextfunction(accesskey)
if use_i18n:
- self.environment.install_gettext_translations(builder.translator)
+ self.environment.install_gettext_translations(builder.app.translator)
def render(self, template, context):
return self.environment.get_template(template).render(context)
diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py
index 36fabc61..63b5caf0 100644
--- a/sphinx/locale/__init__.py
+++ b/sphinx/locale/__init__.py
@@ -8,41 +8,179 @@
:copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+import gettext
+import UserString
+
+from sphinx import package_dir
+
+
+class _TranslationProxy(UserString.UserString, object):
+ """Class for proxy strings from gettext translations. This is a helper
+ for the lazy_* functions from this module.
+
+ The proxy implementation attempts to be as complete as possible, so that
+ the lazy objects should mostly work as expected, for example for sorting.
+
+ This inherits from UserString because some docutils versions use UserString
+ for their Text nodes, which then checks its argument for being either a
+ basestring or UserString, otherwise calls str() -- not unicode() -- on it.
+ This also inherits from object to make the __new__ method work.
+ """
+ __slots__ = ('_func', '_args')
+
+ def __new__(cls, func, *args):
+ if not args:
+ # not called with "function" and "arguments", but a plain string
+ return unicode(func)
+ return object.__new__(cls)
+
+ def __init__(self, func, *args):
+ self._func = func
+ self._args = args
+
+ data = property(lambda x: x._func(*x._args))
+
+ def __contains__(self, key):
+ return key in self.data
+
+ def __nonzero__(self):
+ return bool(self.data)
+
+ def __dir__(self):
+ return dir(unicode)
+
+ def __iter__(self):
+ return iter(self.data)
+
+ def __len__(self):
+ return len(self.data)
+
+ def __str__(self):
+ return str(self.data)
+
+ def __unicode__(self):
+ return unicode(self.data)
+
+ def __add__(self, other):
+ return self.data + other
+
+ def __radd__(self, other):
+ return other + self.data
+
+ def __mod__(self, other):
+ return self.data % other
+
+ def __rmod__(self, other):
+ return other % self.data
+
+ def __mul__(self, other):
+ return self.data * other
+
+ def __rmul__(self, other):
+ return other * self.data
+
+ def __lt__(self, other):
+ return self.data < other
+
+ def __le__(self, other):
+ return self.data <= other
+
+ def __eq__(self, other):
+ return self.data == other
+
+ def __ne__(self, other):
+ return self.data != other
+
+ def __gt__(self, other):
+ return self.data > other
+
+ def __ge__(self, other):
+ return self.data >= other
+
+ def __getattr__(self, name):
+ if name == '__members__':
+ return self.__dir__()
+ return getattr(self.data, name)
+
+ def __getstate__(self):
+ return self._func, self._args
+
+ def __setstate__(self, tup):
+ self._func, self._args = tup
+
+ def __getitem__(self, key):
+ return self.data[key]
+
+ def __copy__(self):
+ return self
+
+ def __repr__(self):
+ try:
+ return 'i' + repr(unicode(self.data))
+ except:
+ return '<%s broken>' % self.__class__.__name__
+
+def mygettext(string):
+ """Used instead of _ when creating TranslationProxies, because _ is
+ not bound yet at that time."""
+ return _(string)
+
+def lazy_gettext(string):
+ """A lazy version of `gettext`."""
+ #if isinstance(string, _TranslationProxy):
+ # return string
+ return _TranslationProxy(mygettext, string)
+
+l_ = lazy_gettext
-_ = lambda x: x
admonitionlabels = {
- 'attention': _('Attention'),
- 'caution': _('Caution'),
- 'danger': _('Danger'),
- 'error': _('Error'),
- 'hint': _('Hint'),
- 'important': _('Important'),
- 'note': _('Note'),
- 'seealso': _('See Also'),
- 'tip': _('Tip'),
- 'warning': _('Warning'),
+ 'attention': l_('Attention'),
+ 'caution': l_('Caution'),
+ 'danger': l_('Danger'),
+ 'error': l_('Error'),
+ 'hint': l_('Hint'),
+ 'important': l_('Important'),
+ 'note': l_('Note'),
+ 'seealso': l_('See Also'),
+ 'tip': l_('Tip'),
+ 'warning': l_('Warning'),
}
versionlabels = {
- 'versionadded': _('New in version %s'),
- 'versionchanged': _('Changed in version %s'),
- 'deprecated': _('Deprecated since version %s'),
+ 'versionadded': l_('New in version %s'),
+ 'versionchanged': l_('Changed in version %s'),
+ 'deprecated': l_('Deprecated since version %s'),
}
pairindextypes = {
- 'module': _('module'),
- 'keyword': _('keyword'),
- 'operator': _('operator'),
- 'object': _('object'),
- 'exception': _('exception'),
- 'statement': _('statement'),
- 'builtin': _('built-in function'),
+ 'module': l_('module'),
+ 'keyword': l_('keyword'),
+ 'operator': l_('operator'),
+ 'object': l_('object'),
+ 'exception': l_('exception'),
+ 'statement': l_('statement'),
+ 'builtin': l_('built-in function'),
}
-del _
-def init():
- for dct in (admonitionlabels, versionlabels, pairindextypes):
- for key in dct:
- dct[key] = _(dct[key])
+def init(locale_dirs, language):
+ # the None entry is the system's default locale path
+ translator = None
+ has_translation = True
+ for dir_ in locale_dirs:
+ try:
+ trans = gettext.translation('sphinx', localedir=dir_,
+ languages=[language])
+ if translator is None:
+ translator = trans
+ else:
+ translator._catalog.update(trans.catalog)
+ except Exception:
+ # Language couldn't be found in the specified path
+ pass
+ if translator is None:
+ translator = gettext.NullTranslations()
+ has_translation = False
+ translator.install(unicode=True)
+ return translator, has_translation
diff --git a/sphinx/locale/ca/LC_MESSAGES/sphinx.js b/sphinx/locale/ca/LC_MESSAGES/sphinx.js
new file mode 100644
index 00000000..8ad043b0
--- /dev/null
+++ b/sphinx/locale/ca/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "ca", "plural_expr": "(n != 1)", "messages": {"Search Results": "Resultats de la Cerca", "Preparing search...": "Preparant la cerca...", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "La teva cerca no ha donat resultats. Assegura't que totes les paraules estan ben escrites i que has seleccionat prou categories.", "Search finished, found %s page(s) matching the search query.": "Cerca finalitzada, s'han trobat %s p\u00e0gin(a/es) de resultats.", ", in ": ", a ", "Permalink to this headline": "Link permanent a aquest t\u00edtol", "Searching": "Cercant", "Permalink to this definition": "Link permanent a aquesta definici\u00f3", "module, in ": "m\u00f2dule, a ", "Hide Search Matches": "Oculta Resultats de Cerca"}}); \ No newline at end of file
diff --git a/sphinx/locale/ca/LC_MESSAGES/sphinx.mo b/sphinx/locale/ca/LC_MESSAGES/sphinx.mo
new file mode 100644
index 00000000..d9cc44ce
--- /dev/null
+++ b/sphinx/locale/ca/LC_MESSAGES/sphinx.mo
Binary files differ
diff --git a/sphinx/locale/ca/LC_MESSAGES/sphinx.po b/sphinx/locale/ca/LC_MESSAGES/sphinx.po
new file mode 100644
index 00000000..440b0594
--- /dev/null
+++ b/sphinx/locale/ca/LC_MESSAGES/sphinx.po
@@ -0,0 +1,606 @@
+# Catalan translations for Sphinx.
+# Copyright (C) 2009 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx 1.0\n"
+"Report-Msgid-Bugs-To: pau.fernandez@upc.edu\n"
+"POT-Creation-Date: 2009-05-22 18:51+0200\n"
+"PO-Revision-Date: 2009-06-07 14:20+0200\n"
+"Last-Translator: Pau Fernández <pau.fernandez@upc.edu>\n"
+"Language-Team: ca <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.4\n"
+
+#: sphinx/environment.py:104 sphinx/writers/latex.py:184
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d de %B de %Y"
+
+#: sphinx/environment.py:323 sphinx/themes/basic/genindex-single.html:2
+#: sphinx/themes/basic/genindex-split.html:2
+#: sphinx/themes/basic/genindex-split.html:5
+#: sphinx/themes/basic/genindex.html:2 sphinx/themes/basic/genindex.html:5
+#: sphinx/themes/basic/genindex.html:48 sphinx/themes/basic/layout.html:131
+#: sphinx/writers/latex.py:190
+msgid "Index"
+msgstr "Índex"
+
+#: sphinx/environment.py:324 sphinx/writers/latex.py:189
+msgid "Module Index"
+msgstr "Índex de Mòduls"
+
+#: sphinx/environment.py:325 sphinx/themes/basic/defindex.html:16
+msgid "Search Page"
+msgstr "Pàgina de Cerca"
+
+#: sphinx/roles.py:55 sphinx/directives/desc.py:747
+#, python-format
+msgid "environment variable; %s"
+msgstr "variable d'entorn; %s"
+
+#: sphinx/roles.py:62
+#, python-format
+msgid "Python Enhancement Proposals!PEP %s"
+msgstr "Python Enhancement Proposals!PEP %s"
+
+#: sphinx/builders/changes.py:71
+msgid "Builtins"
+msgstr "Mòduls Interns"
+
+#: sphinx/builders/changes.py:73
+msgid "Module level"
+msgstr "Nivell de mòdul"
+
+#: sphinx/builders/html.py:219
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d %b, %Y"
+
+#: sphinx/builders/html.py:238 sphinx/themes/basic/defindex.html:21
+msgid "General Index"
+msgstr "Índex General"
+
+#: sphinx/builders/html.py:238
+msgid "index"
+msgstr "índex"
+
+#: sphinx/builders/html.py:240 sphinx/builders/htmlhelp.py:184
+#: sphinx/builders/qthelp.py:132 sphinx/themes/basic/defindex.html:19
+#: sphinx/themes/basic/modindex.html:2 sphinx/themes/basic/modindex.html:13
+msgid "Global Module Index"
+msgstr "Índex Global de Mòduls"
+
+#: sphinx/builders/html.py:241
+msgid "modules"
+msgstr "mòduls"
+
+#: sphinx/builders/html.py:296
+msgid "next"
+msgstr "següent"
+
+#: sphinx/builders/html.py:305
+msgid "previous"
+msgstr "anterior"
+
+#: sphinx/builders/latex.py:162
+msgid " (in "
+msgstr " (a "
+
+#: sphinx/directives/desc.py:97
+msgid "Raises"
+msgstr "Llença"
+
+#: sphinx/directives/desc.py:101
+msgid "Variable"
+msgstr "Variable"
+
+#: sphinx/directives/desc.py:104
+msgid "Returns"
+msgstr "Retorna"
+
+#: sphinx/directives/desc.py:113
+msgid "Return type"
+msgstr "Tipus de retorn"
+
+#: sphinx/directives/desc.py:186
+msgid "Parameter"
+msgstr "Paràmetre"
+
+#: sphinx/directives/desc.py:190
+msgid "Parameters"
+msgstr "Paràmetres"
+
+#: sphinx/directives/desc.py:418
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (funció interna)"
+
+#: sphinx/directives/desc.py:419 sphinx/directives/desc.py:476
+#: sphinx/directives/desc.py:488
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (al mòdul %s)"
+
+#: sphinx/directives/desc.py:422
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (variable interna)"
+
+#: sphinx/directives/desc.py:423 sphinx/directives/desc.py:514
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (al mòdul %s)"
+
+#: sphinx/directives/desc.py:439
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (classe interna)"
+
+#: sphinx/directives/desc.py:440
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (class a %s)"
+
+#: sphinx/directives/desc.py:480
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (mètode %s.%s)"
+
+#: sphinx/directives/desc.py:482
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (mètode %s)"
+
+#: sphinx/directives/desc.py:492
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (mètode estàtic %s.%s)"
+
+#: sphinx/directives/desc.py:495
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (mètode estàtic %s)"
+
+#: sphinx/directives/desc.py:518
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (atribut %s.%s)"
+
+#: sphinx/directives/desc.py:520
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (atribut %s)"
+
+#: sphinx/directives/desc.py:609
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (funció de C)"
+
+#: sphinx/directives/desc.py:611
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (membre de C)"
+
+#: sphinx/directives/desc.py:613
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (macro de C)"
+
+#: sphinx/directives/desc.py:615
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (tipus de C)"
+
+#: sphinx/directives/desc.py:617
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (variable de C)"
+
+#: sphinx/directives/desc.py:665
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "opció de línia de comandes %s; %s"
+
+#: sphinx/directives/other.py:138
+msgid "Platforms: "
+msgstr "Plataformes: "
+
+#: sphinx/directives/other.py:144
+#, python-format
+msgid "%s (module)"
+msgstr "%s (mòdul)"
+
+#: sphinx/directives/other.py:193
+msgid "Section author: "
+msgstr "Autor de la secció:"
+
+#: sphinx/directives/other.py:195
+msgid "Module author: "
+msgstr "Autor del mòdul: "
+
+#: sphinx/directives/other.py:197
+msgid "Author: "
+msgstr "Autor: "
+
+#: sphinx/directives/other.py:317
+msgid "See also"
+msgstr "Vegeu també"
+
+#: sphinx/ext/autodoc.py:888
+#, python-format
+msgid " Bases: %s"
+msgstr " Bases: %s"
+
+#: sphinx/ext/autodoc.py:919
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "àlies de :class:`%s`"
+
+#: sphinx/ext/todo.py:41
+msgid "Todo"
+msgstr "Pendent"
+
+#: sphinx/ext/todo.py:99
+#, python-format
+msgid "(The original entry is located in %s, line %d and can be found "
+msgstr "(La entrada original està a %s, línia %d i es pot trobar "
+
+#: sphinx/ext/todo.py:105
+msgid "here"
+msgstr "aquí"
+
+#: sphinx/locale/__init__.py:15
+msgid "Attention"
+msgstr "Atenció"
+
+#: sphinx/locale/__init__.py:16
+msgid "Caution"
+msgstr "Compte"
+
+#: sphinx/locale/__init__.py:17
+msgid "Danger"
+msgstr "Perill"
+
+#: sphinx/locale/__init__.py:18
+msgid "Error"
+msgstr "Error"
+
+#: sphinx/locale/__init__.py:19
+msgid "Hint"
+msgstr "Suggerència"
+
+#: sphinx/locale/__init__.py:20
+msgid "Important"
+msgstr "Important"
+
+#: sphinx/locale/__init__.py:21
+msgid "Note"
+msgstr "Nota"
+
+#: sphinx/locale/__init__.py:22
+msgid "See Also"
+msgstr "Vegeu També"
+
+#: sphinx/locale/__init__.py:23
+msgid "Tip"
+msgstr "Truc"
+
+#: sphinx/locale/__init__.py:24
+msgid "Warning"
+msgstr "Avís"
+
+#: sphinx/locale/__init__.py:28
+#, python-format
+msgid "New in version %s"
+msgstr "Novetat de la versió %s"
+
+#: sphinx/locale/__init__.py:29
+#, python-format
+msgid "Changed in version %s"
+msgstr "Canviat a la versió %s"
+
+#: sphinx/locale/__init__.py:30
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Obsolet desde la versió %s"
+
+#: sphinx/locale/__init__.py:34
+msgid "module"
+msgstr "mòdul"
+
+#: sphinx/locale/__init__.py:35
+msgid "keyword"
+msgstr "paraula clau"
+
+#: sphinx/locale/__init__.py:36
+msgid "operator"
+msgstr "operador"
+
+#: sphinx/locale/__init__.py:37
+msgid "object"
+msgstr "objecte"
+
+#: sphinx/locale/__init__.py:38
+msgid "exception"
+msgstr "excepció"
+
+#: sphinx/locale/__init__.py:39
+msgid "statement"
+msgstr "sentència"
+
+#: sphinx/locale/__init__.py:40
+msgid "built-in function"
+msgstr "funció interna"
+
+#: sphinx/themes/basic/defindex.html:2
+msgid "Overview"
+msgstr "Resum"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Indices and tables:"
+msgstr "Índexs i taules:"
+
+#: sphinx/themes/basic/defindex.html:14
+msgid "Complete Table of Contents"
+msgstr "Taula de Contingut Completa"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "lists all sections and subsections"
+msgstr "llista totes les seccions i subseccions"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "search this documentation"
+msgstr "cerca aquesta documentació"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "quick access to all modules"
+msgstr "accés ràpid a tots els mòduls"
+
+#: sphinx/themes/basic/defindex.html:22
+msgid "all functions, classes, terms"
+msgstr "totes les funcions, classes, termes"
+
+#: sphinx/themes/basic/genindex-single.html:5
+#, python-format
+msgid "Index &ndash; %(key)s"
+msgstr "Índes &ndash; %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:44
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex-split.html:27
+#: sphinx/themes/basic/genindex.html:54
+msgid "Full index on one page"
+msgstr "Índex complet en una pàgina"
+
+#: sphinx/themes/basic/genindex-split.html:7
+msgid "Index pages by letter"
+msgstr "Pàgines d'índex per lletra"
+
+#: sphinx/themes/basic/genindex-split.html:15
+msgid "can be huge"
+msgstr "pot ser gegant"
+
+#: sphinx/themes/basic/layout.html:10
+msgid "Navigation"
+msgstr "Navegació"
+
+#: sphinx/themes/basic/layout.html:42
+msgid "Table Of Contents"
+msgstr "Taula de Contingut"
+
+#: sphinx/themes/basic/layout.html:48
+msgid "Previous topic"
+msgstr "Tema anterior"
+
+#: sphinx/themes/basic/layout.html:50
+msgid "previous chapter"
+msgstr "capítol anterior"
+
+#: sphinx/themes/basic/layout.html:53
+msgid "Next topic"
+msgstr "Tema següent"
+
+#: sphinx/themes/basic/layout.html:55
+msgid "next chapter"
+msgstr "capítol següent"
+
+#: sphinx/themes/basic/layout.html:60
+msgid "This Page"
+msgstr "Aquesta Pàgina"
+
+#: sphinx/themes/basic/layout.html:63
+msgid "Show Source"
+msgstr "Mostra Codi Font"
+
+#: sphinx/themes/basic/layout.html:73
+msgid "Quick search"
+msgstr "Cerca ràpida"
+
+#: sphinx/themes/basic/layout.html:76
+msgid "Go"
+msgstr "Ves a"
+
+#: sphinx/themes/basic/layout.html:81
+msgid "Enter search terms or a module, class or function name."
+msgstr "Entra paraules de cerca o el nom d'un mòdul, classe o funció."
+
+#: sphinx/themes/basic/layout.html:119
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Cerca dins de %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:128
+msgid "About these documents"
+msgstr "Quant a aquests documents"
+
+#: sphinx/themes/basic/layout.html:134 sphinx/themes/basic/search.html:2
+#: sphinx/themes/basic/search.html:5
+msgid "Search"
+msgstr "Cerca"
+
+#: sphinx/themes/basic/layout.html:137
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:184
+#, python-format
+msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "&copy; <a href=\\\"%(path)s\\\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:186
+#, python-format
+msgid "&copy; Copyright %(copyright)s."
+msgstr "&copy; Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:190
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Última actualització el %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:193
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Creat amb <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/modindex.html:36
+msgid "Deprecated"
+msgstr "Obsolet"
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Cercar a %(docstitle)s"
+
+#: sphinx/themes/basic/search.html:9
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Activa JavaScript per utilitzar la funcionalitat\n"
+"de cerca."
+
+#: sphinx/themes/basic/search.html:14
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Des d'aquí pots fer cerques en aquests documents. Entra les \n"
+"paraules de la teva cerca i clica el botó \"cerca\". Tingues en compte\n"
+"que la cerca inclourà totes les paraules que posis. Les pàgines que no\n"
+"tenen totes les paraules no sortiràn."
+
+#: sphinx/themes/basic/search.html:21
+msgid "search"
+msgstr "cerca"
+
+#: sphinx/themes/basic/search.html:25
+#: sphinx/themes/basic/static/searchtools.js:462
+msgid "Search Results"
+msgstr "Resultats de la Cerca"
+
+#: sphinx/themes/basic/search.html:27
+msgid "Your search did not match any results."
+msgstr "La teva cerca no té resultats."
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s &mdash; %(docstitle)s"
+msgstr "Canvis a la Versió %(version)s &mdash; %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s &mdash; %(docstitle)s"
+msgstr "%(filename)s &mdash; %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Llista de canvis de la versió %(version)s generada automàticament"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Canvis a la llibreria"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Canvis a la API de C"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Altres canvis"
+
+#: sphinx/themes/basic/static/doctools.js:139 sphinx/writers/html.py:473
+#: sphinx/writers/html.py:478
+msgid "Permalink to this headline"
+msgstr "Link permanent a aquest títol"
+
+#: sphinx/themes/basic/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr "Link permanent a aquesta definició"
+
+#: sphinx/themes/basic/static/doctools.js:174
+msgid "Hide Search Matches"
+msgstr "Oculta Resultats de Cerca"
+
+#: sphinx/themes/basic/static/searchtools.js:274
+msgid "Searching"
+msgstr "Cercant"
+
+#: sphinx/themes/basic/static/searchtools.js:279
+msgid "Preparing search..."
+msgstr "Preparant la cerca..."
+
+#: sphinx/themes/basic/static/searchtools.js:347
+msgid "module, in "
+msgstr "mòdule, a "
+
+#: sphinx/themes/basic/static/searchtools.js:356
+msgid ", in "
+msgstr ", a "
+
+#: sphinx/themes/basic/static/searchtools.js:464
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"La teva cerca no ha donat resultats. Assegura't que totes les paraules "
+"estan ben escrites i que has seleccionat prou categories."
+
+#: sphinx/themes/basic/static/searchtools.js:466
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "Cerca finalitzada, s'han trobat %s pàgin(a/es) de resultats."
+
+#: sphinx/writers/latex.py:187
+msgid "Release"
+msgstr "Versió"
+
+#: sphinx/writers/latex.py:639
+msgid "continued from previous page"
+msgstr "ve de la pàgina anterior"
+
+#: sphinx/writers/latex.py:643
+msgid "Continued on next page"
+msgstr "Continua a la pàgina següent"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "Plataforma: %s"
+
+#: sphinx/writers/text.py:428
+msgid "[image]"
+msgstr "[imatge]"
+
diff --git a/sphinx/locale/de/LC_MESSAGES/sphinx.mo b/sphinx/locale/de/LC_MESSAGES/sphinx.mo
index a8905259..681091ce 100644
--- a/sphinx/locale/de/LC_MESSAGES/sphinx.mo
+++ b/sphinx/locale/de/LC_MESSAGES/sphinx.mo
Binary files differ
diff --git a/sphinx/locale/de/LC_MESSAGES/sphinx.po b/sphinx/locale/de/LC_MESSAGES/sphinx.po
index e1d61a20..9483de79 100644
--- a/sphinx/locale/de/LC_MESSAGES/sphinx.po
+++ b/sphinx/locale/de/LC_MESSAGES/sphinx.po
@@ -248,7 +248,7 @@ msgstr "Zu tun"
#: sphinx/ext/todo.py:99
#, python-format
msgid "(The original entry is located in %s, line %d and can be found "
-msgstr "(Der ursprüngliche Eintrag steht in %s, Zeile %s, siehe "
+msgstr "(Der ursprüngliche Eintrag steht in %s, Zeile %d, siehe "
#: sphinx/ext/todo.py:105
msgid "here"
diff --git a/sphinx/locale/fi/LC_MESSAGES/sphinx.js b/sphinx/locale/fi/LC_MESSAGES/sphinx.js
index f654e7e1..82f02c29 100644
--- a/sphinx/locale/fi/LC_MESSAGES/sphinx.js
+++ b/sphinx/locale/fi/LC_MESSAGES/sphinx.js
@@ -1 +1 @@
-Documentation.addTranslations({"locale": "fi", "plural_expr": "(n != 1)", "messages": {"module, in ": "", "Preparing search...": "Valmistellaan etsint\u00e4\u00e4...", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "Ei l\u00f6ytynyt yht\u00e4\u00e4n. Tarkista hakuehdot, sanahaku, ei sen osia", "Search finished, found %s page(s) matching the search query.": "Etsint\u00e4 tehty, l\u00f6ydetty %s sivu(a).", ", in ": "", "Permalink to this headline": "", "Searching": "Etsit\u00e4\u00e4n", "Permalink to this definition": "", "Hide Search Matches": "Piilota l\u00f6ydetyt", "Search Results": "Etsinn\u00e4n tulos"}}); \ No newline at end of file
+Documentation.addTranslations({"locale": "fi", "plural_expr": "(n != 1)", "messages": {"Search Results": "Etsinn\u00e4n tulos", "Preparing search...": "Valmistellaan etsint\u00e4\u00e4...", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "Ei l\u00f6ytynyt yht\u00e4\u00e4n. Tarkista hakuehdot, sanahaku, ei sen osia", "Search finished, found %s page(s) matching the search query.": "Etsint\u00e4 tehty, l\u00f6ydetty %s sivu(a).", ", in ": "", "Permalink to this headline": "", "Searching": "Etsit\u00e4\u00e4n", "Permalink to this definition": "", "module, in ": "", "Hide Search Matches": "Piilota l\u00f6ydetyt"}}); \ No newline at end of file
diff --git a/sphinx/locale/fi/LC_MESSAGES/sphinx.mo b/sphinx/locale/fi/LC_MESSAGES/sphinx.mo
index 44d19f8c..54b25dc8 100644
--- a/sphinx/locale/fi/LC_MESSAGES/sphinx.mo
+++ b/sphinx/locale/fi/LC_MESSAGES/sphinx.mo
Binary files differ
diff --git a/sphinx/locale/fi/LC_MESSAGES/sphinx.po b/sphinx/locale/fi/LC_MESSAGES/sphinx.po
index 3794a648..97cdace1 100644
--- a/sphinx/locale/fi/LC_MESSAGES/sphinx.po
+++ b/sphinx/locale/fi/LC_MESSAGES/sphinx.po
@@ -594,7 +594,7 @@ msgstr "Hakemisto yhtenä luettelona"
#: sphinx/writers/text.py:166
#, fuzzy, python-format
msgid "Platform: %s"
-msgstr "Ympäristö"
+msgstr "Ympäristö: %s"
#: sphinx/writers/text.py:428
msgid "[image]"
diff --git a/sphinx/locale/sphinx.pot b/sphinx/locale/sphinx.pot
index d6337cf7..438d247d 100644
--- a/sphinx/locale/sphinx.pot
+++ b/sphinx/locale/sphinx.pot
@@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: Sphinx 1.0\n"
+"Project-Id-Version: Sphinx 1.0pre/4bacd76a2cdc+a18846601c6e+\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2009-08-06 23:04+0200\n"
+"POT-Creation-Date: 2009-08-09 22:45+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,218 +17,232 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.4\n"
-#: sphinx/environment.py:103 sphinx/writers/latex.py:184
+#: sphinx/domains.py:290
#, python-format
-msgid "%B %d, %Y"
+msgid "%s() (built-in function)"
msgstr ""
-#: sphinx/environment.py:324 sphinx/themes/basic/genindex-single.html:2
-#: sphinx/themes/basic/genindex-split.html:2
-#: sphinx/themes/basic/genindex-split.html:5
-#: sphinx/themes/basic/genindex.html:2 sphinx/themes/basic/genindex.html:5
-#: sphinx/themes/basic/genindex.html:48 sphinx/themes/basic/layout.html:134
-#: sphinx/writers/latex.py:190
-msgid "Index"
+#: sphinx/domains.py:291 sphinx/domains.py:348 sphinx/domains.py:360
+#: sphinx/domains.py:373
+#, python-format
+msgid "%s() (in module %s)"
msgstr ""
-#: sphinx/environment.py:325 sphinx/writers/latex.py:189
-msgid "Module Index"
+#: sphinx/domains.py:294
+#, python-format
+msgid "%s (built-in variable)"
msgstr ""
-#: sphinx/environment.py:326 sphinx/themes/basic/defindex.html:16
-msgid "Search Page"
+#: sphinx/domains.py:295 sphinx/domains.py:386
+#, python-format
+msgid "%s (in module %s)"
msgstr ""
-#: sphinx/roles.py:55 sphinx/directives/desc.py:747
+#: sphinx/domains.py:311
#, python-format
-msgid "environment variable; %s"
+msgid "%s (built-in class)"
msgstr ""
-#: sphinx/roles.py:62
+#: sphinx/domains.py:312
#, python-format
-msgid "Python Enhancement Proposals!PEP %s"
+msgid "%s (class in %s)"
msgstr ""
-#: sphinx/builders/changes.py:71
-msgid "Builtins"
+#: sphinx/domains.py:352
+#, python-format
+msgid "%s() (%s.%s method)"
msgstr ""
-#: sphinx/builders/changes.py:73
-msgid "Module level"
+#: sphinx/domains.py:354
+#, python-format
+msgid "%s() (%s method)"
msgstr ""
-#: sphinx/builders/html.py:222
+#: sphinx/domains.py:364
#, python-format
-msgid "%b %d, %Y"
+msgid "%s() (%s.%s static method)"
msgstr ""
-#: sphinx/builders/html.py:241 sphinx/themes/basic/defindex.html:21
-msgid "General Index"
+#: sphinx/domains.py:367
+#, python-format
+msgid "%s() (%s static method)"
msgstr ""
-#: sphinx/builders/html.py:241
-msgid "index"
+#: sphinx/domains.py:377
+#, python-format
+msgid "%s() (%s.%s class method)"
msgstr ""
-#: sphinx/builders/html.py:243 sphinx/builders/htmlhelp.py:219
-#: sphinx/builders/qthelp.py:133 sphinx/themes/basic/defindex.html:19
-#: sphinx/themes/basic/modindex.html:2 sphinx/themes/basic/modindex.html:13
-msgid "Global Module Index"
+#: sphinx/domains.py:380
+#, python-format
+msgid "%s() (%s class method)"
msgstr ""
-#: sphinx/builders/html.py:244
-msgid "modules"
+#: sphinx/domains.py:390
+#, python-format
+msgid "%s (%s.%s attribute)"
msgstr ""
-#: sphinx/builders/html.py:300
-msgid "next"
+#: sphinx/domains.py:392
+#, python-format
+msgid "%s (%s attribute)"
msgstr ""
-#: sphinx/builders/html.py:309
-msgid "previous"
+#: sphinx/domains.py:437
+msgid "Platforms: "
msgstr ""
-#: sphinx/builders/latex.py:162
-msgid " (in "
+#: sphinx/domains.py:443
+#, python-format
+msgid "%s (module)"
msgstr ""
-#: sphinx/directives/desc.py:97
-msgid "Raises"
+#: sphinx/domains.py:705
+#, python-format
+msgid "%s (C function)"
msgstr ""
-#: sphinx/directives/desc.py:101
-msgid "Variable"
+#: sphinx/domains.py:707
+#, python-format
+msgid "%s (C member)"
msgstr ""
-#: sphinx/directives/desc.py:104
-msgid "Returns"
+#: sphinx/domains.py:709
+#, python-format
+msgid "%s (C macro)"
msgstr ""
-#: sphinx/directives/desc.py:113
-msgid "Return type"
+#: sphinx/domains.py:711
+#, python-format
+msgid "%s (C type)"
msgstr ""
-#: sphinx/directives/desc.py:186
-msgid "Parameter"
+#: sphinx/domains.py:713
+#, python-format
+msgid "%s (C variable)"
msgstr ""
-#: sphinx/directives/desc.py:190
-msgid "Parameters"
+#: sphinx/environment.py:106 sphinx/writers/latex.py:184
+#, python-format
+msgid "%B %d, %Y"
msgstr ""
-#: sphinx/directives/desc.py:418
-#, python-format
-msgid "%s() (built-in function)"
+#: sphinx/environment.py:333 sphinx/themes/basic/genindex-single.html:2
+#: sphinx/themes/basic/genindex-split.html:2
+#: sphinx/themes/basic/genindex-split.html:5
+#: sphinx/themes/basic/genindex.html:2 sphinx/themes/basic/genindex.html:5
+#: sphinx/themes/basic/genindex.html:48 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:190
+msgid "Index"
msgstr ""
-#: sphinx/directives/desc.py:419 sphinx/directives/desc.py:476
-#: sphinx/directives/desc.py:488
-#, python-format
-msgid "%s() (in module %s)"
+#: sphinx/environment.py:334 sphinx/writers/latex.py:189
+msgid "Module Index"
msgstr ""
-#: sphinx/directives/desc.py:422
-#, python-format
-msgid "%s (built-in variable)"
+#: sphinx/environment.py:335 sphinx/themes/basic/defindex.html:16
+msgid "Search Page"
msgstr ""
-#: sphinx/directives/desc.py:423 sphinx/directives/desc.py:514
+#: sphinx/roles.py:139 sphinx/directives/desc.py:382
#, python-format
-msgid "%s (in module %s)"
+msgid "environment variable; %s"
msgstr ""
-#: sphinx/directives/desc.py:439
+#: sphinx/roles.py:146
#, python-format
-msgid "%s (built-in class)"
+msgid "Python Enhancement Proposals!PEP %s"
msgstr ""
-#: sphinx/directives/desc.py:440
-#, python-format
-msgid "%s (class in %s)"
+#: sphinx/builders/changes.py:71
+msgid "Builtins"
msgstr ""
-#: sphinx/directives/desc.py:480
-#, python-format
-msgid "%s() (%s.%s method)"
+#: sphinx/builders/changes.py:73
+msgid "Module level"
msgstr ""
-#: sphinx/directives/desc.py:482
+#: sphinx/builders/html.py:223
#, python-format
-msgid "%s() (%s method)"
+msgid "%b %d, %Y"
msgstr ""
-#: sphinx/directives/desc.py:492
-#, python-format
-msgid "%s() (%s.%s static method)"
+#: sphinx/builders/html.py:242 sphinx/themes/basic/defindex.html:21
+msgid "General Index"
msgstr ""
-#: sphinx/directives/desc.py:495
-#, python-format
-msgid "%s() (%s static method)"
+#: sphinx/builders/html.py:242
+msgid "index"
msgstr ""
-#: sphinx/directives/desc.py:518
-#, python-format
-msgid "%s (%s.%s attribute)"
+#: sphinx/builders/html.py:246 sphinx/builders/htmlhelp.py:219
+#: sphinx/builders/qthelp.py:133 sphinx/themes/basic/defindex.html:19
+#: sphinx/themes/basic/modindex.html:2 sphinx/themes/basic/modindex.html:13
+#: sphinx/themes/scrolls/modindex.html:2 sphinx/themes/scrolls/modindex.html:13
+msgid "Global Module Index"
msgstr ""
-#: sphinx/directives/desc.py:520
-#, python-format
-msgid "%s (%s attribute)"
+#: sphinx/builders/html.py:247
+msgid "modules"
msgstr ""
-#: sphinx/directives/desc.py:609
-#, python-format
-msgid "%s (C function)"
+#: sphinx/builders/html.py:303
+msgid "next"
msgstr ""
-#: sphinx/directives/desc.py:611
-#, python-format
-msgid "%s (C member)"
+#: sphinx/builders/html.py:312
+msgid "previous"
msgstr ""
-#: sphinx/directives/desc.py:613
-#, python-format
-msgid "%s (C macro)"
+#: sphinx/builders/latex.py:162
+msgid " (in "
msgstr ""
-#: sphinx/directives/desc.py:615
-#, python-format
-msgid "%s (C type)"
+#: sphinx/directives/desc.py:67 sphinx/directives/desc.py:68
+#: sphinx/directives/desc.py:69 sphinx/directives/desc.py:70
+msgid "Raises"
msgstr ""
-#: sphinx/directives/desc.py:617
-#, python-format
-msgid "%s (C variable)"
+#: sphinx/directives/desc.py:71 sphinx/directives/desc.py:72
+#: sphinx/directives/desc.py:73
+msgid "Variable"
msgstr ""
-#: sphinx/directives/desc.py:665
-#, python-format
-msgid "%scommand line option; %s"
+#: sphinx/directives/desc.py:74 sphinx/directives/desc.py:75
+#: sphinx/directives/desc.py:81 sphinx/directives/desc.py:82
+msgid "Returns"
msgstr ""
-#: sphinx/directives/other.py:140
-msgid "Platforms: "
+#: sphinx/directives/desc.py:83
+msgid "Return type"
msgstr ""
-#: sphinx/directives/other.py:146
+#: sphinx/directives/desc.py:156
+msgid "Parameter"
+msgstr ""
+
+#: sphinx/directives/desc.py:160
+msgid "Parameters"
+msgstr ""
+
+#: sphinx/directives/desc.py:284
#, python-format
-msgid "%s (module)"
+msgid "%scommand line option; %s"
msgstr ""
-#: sphinx/directives/other.py:195
+#: sphinx/directives/other.py:126
msgid "Section author: "
msgstr ""
-#: sphinx/directives/other.py:197
+#: sphinx/directives/other.py:128
msgid "Module author: "
msgstr ""
-#: sphinx/directives/other.py:199
+#: sphinx/directives/other.py:130
msgid "Author: "
msgstr ""
-#: sphinx/directives/other.py:319
+#: sphinx/directives/other.py:250
msgid "See also"
msgstr ""
@@ -255,86 +269,86 @@ msgstr ""
msgid "here"
msgstr ""
-#: sphinx/locale/__init__.py:15
+#: sphinx/locale/__init__.py:138
msgid "Attention"
msgstr ""
-#: sphinx/locale/__init__.py:16
+#: sphinx/locale/__init__.py:139
msgid "Caution"
msgstr ""
-#: sphinx/locale/__init__.py:17
+#: sphinx/locale/__init__.py:140
msgid "Danger"
msgstr ""
-#: sphinx/locale/__init__.py:18
+#: sphinx/locale/__init__.py:141
msgid "Error"
msgstr ""
-#: sphinx/locale/__init__.py:19
+#: sphinx/locale/__init__.py:142
msgid "Hint"
msgstr ""
-#: sphinx/locale/__init__.py:20
+#: sphinx/locale/__init__.py:143
msgid "Important"
msgstr ""
-#: sphinx/locale/__init__.py:21
+#: sphinx/locale/__init__.py:144
msgid "Note"
msgstr ""
-#: sphinx/locale/__init__.py:22
+#: sphinx/locale/__init__.py:145
msgid "See Also"
msgstr ""
-#: sphinx/locale/__init__.py:23
+#: sphinx/locale/__init__.py:146
msgid "Tip"
msgstr ""
-#: sphinx/locale/__init__.py:24
+#: sphinx/locale/__init__.py:147
msgid "Warning"
msgstr ""
-#: sphinx/locale/__init__.py:28
+#: sphinx/locale/__init__.py:151
#, python-format
msgid "New in version %s"
msgstr ""
-#: sphinx/locale/__init__.py:29
+#: sphinx/locale/__init__.py:152
#, python-format
msgid "Changed in version %s"
msgstr ""
-#: sphinx/locale/__init__.py:30
+#: sphinx/locale/__init__.py:153
#, python-format
msgid "Deprecated since version %s"
msgstr ""
-#: sphinx/locale/__init__.py:34
+#: sphinx/locale/__init__.py:157
msgid "module"
msgstr ""
-#: sphinx/locale/__init__.py:35
+#: sphinx/locale/__init__.py:158
msgid "keyword"
msgstr ""
-#: sphinx/locale/__init__.py:36
+#: sphinx/locale/__init__.py:159
msgid "operator"
msgstr ""
-#: sphinx/locale/__init__.py:37
+#: sphinx/locale/__init__.py:160
msgid "object"
msgstr ""
-#: sphinx/locale/__init__.py:38
+#: sphinx/locale/__init__.py:161
msgid "exception"
msgstr ""
-#: sphinx/locale/__init__.py:39
+#: sphinx/locale/__init__.py:162
msgid "statement"
msgstr ""
-#: sphinx/locale/__init__.py:40
+#: sphinx/locale/__init__.py:163
msgid "built-in function"
msgstr ""
@@ -448,29 +462,29 @@ msgstr ""
msgid "Copyright"
msgstr ""
-#: sphinx/themes/basic/layout.html:187
+#: sphinx/themes/basic/layout.html:187 sphinx/themes/scrolls/layout.html:83
#, python-format
msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr ""
-#: sphinx/themes/basic/layout.html:189
+#: sphinx/themes/basic/layout.html:189 sphinx/themes/scrolls/layout.html:85
#, python-format
msgid "&copy; Copyright %(copyright)s."
msgstr ""
-#: sphinx/themes/basic/layout.html:193
+#: sphinx/themes/basic/layout.html:193 sphinx/themes/scrolls/layout.html:89
#, python-format
msgid "Last updated on %(last_updated)s."
msgstr ""
-#: sphinx/themes/basic/layout.html:196
+#: sphinx/themes/basic/layout.html:196 sphinx/themes/scrolls/layout.html:92
#, python-format
msgid ""
"Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
"%(sphinx_version)s."
msgstr ""
-#: sphinx/themes/basic/modindex.html:36
+#: sphinx/themes/basic/modindex.html:36 sphinx/themes/scrolls/modindex.html:37
msgid "Deprecated"
msgstr ""
diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py
index 914d9567..c2446924 100644
--- a/sphinx/quickstart.py
+++ b/sphinx/quickstart.py
@@ -333,7 +333,8 @@ devhelp:
\t@echo "Build finished."
\t@echo "To view the help file:"
\t@echo "# mkdir -p $$HOME/.local/share/devhelp/%(project_fn)s"
-\t@echo "# ln -s %(rbuilddir)s/devhelp $$HOME/.local/share/devhelp/%(project_fn)s"
+\t@echo "# ln -s %(rbuilddir)s/devhelp \
+$$HOME/.local/share/devhelp/%(project_fn)s"
\t@echo "# devhelp"
latex:
diff --git a/sphinx/roles.py b/sphinx/roles.py
index af574b98..db231463 100644
--- a/sphinx/roles.py
+++ b/sphinx/roles.py
@@ -10,6 +10,7 @@
"""
import re
+import warnings
from docutils import nodes, utils
from docutils.parsers.rst import roles
@@ -28,7 +29,7 @@ generic_docroles = {
'manpage' : addnodes.literal_emphasis,
'mimetype' : addnodes.literal_emphasis,
'newsgroup' : addnodes.literal_emphasis,
- 'program' : nodes.strong,
+ 'program' : nodes.strong, # XXX should be an x-ref
'regexp' : nodes.literal,
}
@@ -37,6 +38,89 @@ for rolename, nodeclass in generic_docroles.iteritems():
roles.register_local_role(rolename, role)
+# -- generic cross-reference roles ---------------------------------------------
+
+class XRefRole(object):
+ """XXX add docstring"""
+
+ nodeclass = addnodes.pending_xref
+ innernodeclass = nodes.literal
+
+ def __init__(self, fix_parens=False, lowercase=False,
+ nodeclass=None, innernodeclass=None):
+ self.fix_parens = fix_parens
+ if nodeclass is not None:
+ self.nodeclass = nodeclass
+ if innernodeclass is not None:
+ self.innernodeclass = innernodeclass
+
+ def process_link(self, env, pnode, has_explicit_title, title, target):
+ return title, ws_re.sub(' ', target)
+
+ def normalize_func_parens(self, env, has_explicit_title, title, target):
+ if not has_explicit_title:
+ if title.endswith('()'):
+ # remove parentheses
+ title = title[:-2]
+ if env.config.add_function_parentheses:
+ # add them back to all occurrences if configured
+ title += '()'
+ # remove parentheses from the target too
+ if target.endswith('()'):
+ target = target[:-2]
+ return title, target
+
+ def __call__(self, typ, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ env = inliner.document.settings.env
+ if not typ:
+ typ = env.config.default_role
+ else:
+ typ = typ.lower()
+ if ':' not in typ:
+ domain, role = '', typ
+ else:
+ domain, role = typ.split(':', 1)
+ text = utils.unescape(text)
+ # if the first character is a bang, don't cross-reference at all
+ if text[0:1] == '!':
+ if self.fix_parens:
+ text, _ = self.normalize_func_parens(env, False, text[1:], "")
+ return [self.innernodeclass(rawtext, text, classes=['xref'])], []
+ # split title and target in role content
+ has_explicit_title, title, target = split_explicit_title(text)
+ # we want a cross-reference, create the reference node
+ pnode = self.nodeclass(rawtext, reftype=role, refdomain=domain,
+ refcaption=has_explicit_title)
+ # we may need the line number for warnings
+ pnode.line = lineno
+ title, target = self.process_link(env, pnode,
+ has_explicit_title, title, target)
+ pnode['reftarget'] = target
+ pnode += self.innernodeclass(rawtext, title, classes=['xref'])
+ return [pnode], []
+
+
+class OptionXRefRole(XRefRole):
+ innernodeclass = addnodes.literal_emphasis
+
+ def process_link(self, env, pnode, has_explicit_title, title, target):
+ program = env.currprogram
+ if not has_explicit_title:
+ if ' ' in title and not (title.startswith('/') or
+ title.startswith('-')):
+ program, target = re.split(' (?=-|--|/)', title, 1)
+ program = ws_re.sub('-', program)
+ target = target.strip()
+ elif ' ' in target:
+ program, target = re.split(' (?=-|--|/)', target, 1)
+ program = ws_re.sub('-', program)
+ pnode['refprogram'] = program
+ return title, target
+
+
+_EnvvarXrefRole = XRefRole()
+
def indexmarkup_role(typ, rawtext, etext, lineno, inliner,
options={}, content=[]):
env = inliner.document.settings.env
@@ -54,8 +138,8 @@ def indexmarkup_role(typ, rawtext, etext, lineno, inliner,
indexnode['entries'] = [('single', text, targetid, text),
('single', _('environment variable; %s') % text,
targetid, text)]
- xref_nodes = xfileref_role(typ, rawtext, etext, lineno, inliner,
- options, content)[0]
+ xref_nodes = _EnvvarXrefRole(typ, rawtext, etext, lineno, inliner,
+ options, content)[0]
return [indexnode, targetnode] + xref_nodes, []
elif typ == 'pep':
indexnode['entries'] = [
@@ -89,117 +173,12 @@ def indexmarkup_role(typ, rawtext, etext, lineno, inliner,
rn += sn
return [indexnode, targetnode, rn], []
-roles.register_local_role('envvar', indexmarkup_role)
-roles.register_local_role('pep', indexmarkup_role)
-roles.register_local_role('rfc', indexmarkup_role)
-
-
-# default is `literal`
-innernodetypes = {
- 'ref': nodes.emphasis,
- 'term': nodes.emphasis,
- 'token': nodes.strong,
- 'envvar': nodes.strong,
- 'download': nodes.strong,
- 'option': addnodes.literal_emphasis,
-}
-
-def _fix_parens(typ, text, env):
- if typ in ('func', 'meth', 'cfunc'):
- if text.endswith('()'):
- # remove parentheses
- text = text[:-2]
- if env.config.add_function_parentheses:
- # add them back to all occurrences if configured
- text += '()'
- return text
-
-def xfileref_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
- env = inliner.document.settings.env
- if not typ:
- typ = env.config.default_role
- else:
- typ = typ.lower()
- text = utils.unescape(text)
- # if the first character is a bang, don't cross-reference at all
- if text[0:1] == '!':
- text = _fix_parens(typ, text[1:], env)
- return [innernodetypes.get(typ, nodes.literal)(
- rawtext, text, classes=['xref'])], []
- # we want a cross-reference, create the reference node
- nodeclass = (typ == 'download') and addnodes.download_reference or \
- addnodes.pending_xref
- pnode = nodeclass(rawtext, reftype=typ, refcaption=False,
- modname=env.currmodule, classname=env.currclass)
- # we may need the line number for warnings
- pnode.line = lineno
- # look if explicit title and target are given with `foo <bar>` syntax
- has_explicit_title, title, target = split_explicit_title(text)
- if has_explicit_title:
- pnode['refcaption'] = True
- # special target for Python object cross-references
- if typ in ('data', 'exc', 'func', 'class', 'const', 'attr',
- 'meth', 'mod', 'obj'):
- # fix-up parentheses in link title
- if not has_explicit_title:
- title = title.lstrip('.') # only has a meaning for the target
- target = target.lstrip('~') # only has a meaning for the title
- title = _fix_parens(typ, title, env)
- # if the first character is a tilde, don't display the module/class
- # parts of the contents
- if title[0:1] == '~':
- title = title[1:]
- dot = title.rfind('.')
- if dot != -1:
- title = title[dot+1:]
- # remove parentheses from the target too
- if target.endswith('()'):
- target = target[:-2]
- # if the first character is a dot, search more specific namespaces first
- # else search builtins first
- if target[0:1] == '.':
- target = target[1:]
- pnode['refspecific'] = True
- # some other special cases for the target
- elif typ == 'option':
- program = env.currprogram
- if not has_explicit_title:
- if ' ' in title and not (title.startswith('/') or
- title.startswith('-')):
- program, target = re.split(' (?=-|--|/)', title, 1)
- program = ws_re.sub('-', program)
- target = target.strip()
- elif ' ' in target:
- program, target = re.split(' (?=-|--|/)', target, 1)
- program = ws_re.sub('-', program)
- pnode['refprogram'] = program
- elif typ == 'term':
- # normalize whitespace in definition terms (if the term reference is
- # broken over a line, a newline will be in target)
- target = ws_re.sub(' ', target).lower()
- elif typ == 'ref':
- # reST label names are always lowercased
- target = ws_re.sub('', target).lower()
- elif typ == 'cfunc':
- # fix-up parens for C functions too
- if not has_explicit_title:
- title = _fix_parens(typ, title, env)
- # remove parentheses from the target too
- if target.endswith('()'):
- target = target[:-2]
- else:
- # remove all whitespace to avoid referencing problems
- target = ws_re.sub('', target)
- pnode['reftarget'] = target
- pnode += innernodetypes.get(typ, nodes.literal)(rawtext, title,
- classes=['xref'])
- return [pnode], []
-
def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
return [nodes.emphasis(
rawtext,
utils.unescape(text).replace('-->', u'\N{TRIANGULAR BULLET}'))], []
+ return role
_litvar_re = re.compile('{([^}]+)}')
@@ -233,30 +212,17 @@ def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
specific_docroles = {
- 'data': xfileref_role,
- 'exc': xfileref_role,
- 'func': xfileref_role,
- 'class': xfileref_role,
- 'const': xfileref_role,
- 'attr': xfileref_role,
- 'meth': xfileref_role,
- 'obj': xfileref_role,
- 'cfunc' : xfileref_role,
- 'cmember': xfileref_role,
- 'cdata': xfileref_role,
- 'ctype': xfileref_role,
- 'cmacro': xfileref_role,
-
- 'mod': xfileref_role,
-
- 'keyword': xfileref_role,
- 'ref': xfileref_role,
- 'token': xfileref_role,
- 'term': xfileref_role,
- 'option': xfileref_role,
- 'doc': xfileref_role,
- 'download': xfileref_role,
-
+ 'keyword': XRefRole(),
+ 'ref': XRefRole(lowercase=True, innernodeclass=nodes.emphasis),
+ 'token': XRefRole(),
+ 'term': XRefRole(lowercase=True, innernodeclass=nodes.emphasis),
+ 'option': OptionXRefRole(innernodeclass=addnodes.literal_emphasis),
+ 'doc': XRefRole(),
+ 'download': XRefRole(nodeclass=addnodes.download_reference),
+
+ 'envvar': indexmarkup_role,
+ 'pep': indexmarkup_role,
+ 'rfc': indexmarkup_role,
'menuselection': menusel_role,
'file': emph_literal_role,
'samp': emph_literal_role,
@@ -265,3 +231,10 @@ specific_docroles = {
for rolename, func in specific_docroles.iteritems():
roles.register_local_role(rolename, func)
+
+
+# compatibility alias
+def xfileref_role(*args, **kwds):
+ warnings.warn('xfileref_role is deprecated, use XRefRole',
+ DeprecationWarning, stacklevel=2)
+ return XRefRole()(*args, **kwds)
diff --git a/sphinx/search.py b/sphinx/search.py
index 9bfa9d92..7f1a87a9 100644
--- a/sphinx/search.py
+++ b/sphinx/search.py
@@ -148,6 +148,8 @@ class IndexBuilder(object):
def get_modules(self, fn2index):
rv = {}
+ # XXX implement search capability
+ return rv
for name, (doc, _, _, _) in self.env.modules.iteritems():
if doc in fn2index:
rv[name] = fn2index[doc]
@@ -156,6 +158,8 @@ class IndexBuilder(object):
def get_descrefs(self, fn2index):
rv = {}
dt = self._desctypes
+ # XXX implement search capability
+ return rv
for fullname, (doc, desctype) in self.env.descrefs.iteritems():
if doc not in fn2index:
continue
diff --git a/sphinx/themes/scrolls/artwork/logo.svg b/sphinx/themes/scrolls/artwork/logo.svg
new file mode 100644
index 00000000..0907a4ea
--- /dev/null
+++ b/sphinx/themes/scrolls/artwork/logo.svg
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="200"
+ height="80"
+ id="svg2766"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="logo.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs2768">
+ <linearGradient
+ id="linearGradient6558">
+ <stop
+ style="stop-color:#575757;stop-opacity:1;"
+ offset="0"
+ id="stop6560" />
+ <stop
+ style="stop-color:#2f2f2f;stop-opacity:1;"
+ offset="1"
+ id="stop6562" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective2774" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6558"
+ id="radialGradient2797"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7160081,0,0,0.6767021,-34.98413,-3.3035294e-2)"
+ cx="61.297766"
+ cy="60.910986"
+ fx="61.297766"
+ fy="60.910986"
+ r="44.688254" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="6.1848684"
+ inkscape:cx="95.923838"
+ inkscape:cy="34.518668"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1440"
+ inkscape:window-height="852"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata2771">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="opacity:1;fill:url(#radialGradient2797);fill-opacity:1;fill-rule:evenodd;stroke:#323232;stroke-width:0.71600807000000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 72.4375 8.6875 L 3.0625 18.71875 L 20.84375 29.0625 L 20.6875 44.09375 L 7.75 36.1875 L 8.40625 71.75 L 17.125 65.625 L 29.09375 67.5625 L 33.15625 39.90625 L 25.875 43.78125 L 26.1875 33.59375 L 46.875 31.34375 L 47.21875 42.96875 L 39.28125 40.5625 L 42.6875 67.71875 L 52.375 66.75 L 60.3125 71.75 L 62.90625 33.4375 L 53.03125 43.625 L 53.03125 28.25 L 72.4375 8.6875 z M 48.03125 22.125 L 47.0625 26.46875 L 28.46875 28.09375 L 28.46875 25.1875 L 48.03125 22.125 z M 58.375 45.0625 L 57.40625 62.875 L 51.40625 60.59375 L 45.90625 61.71875 L 43 46.21875 L 53.84375 49.9375 L 58.375 45.0625 z M 12.125 46.53125 L 22 49.75 L 26.53125 47.03125 L 25.21875 62.0625 L 16.96875 60.4375 L 12.125 63.65625 L 12.125 46.53125 z "
+ id="path2783" />
+ <path
+ style="opacity:1;fill:#e7eef6;fill-opacity:1;fill-rule:nonzero;stroke:#e1e8f3;stroke-width:0.52748101999999997;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 75.632462,22.265877 L 64.489624,64.880679 L 92.7889,40.941187 L 91.373937,61.872575 L 128.87048,23.519253 L 116.84328,58.36312 L 144.25821,44.450641 L 145.49631,65.632704 L 169.02007,38.183758 L 170.78877,60.493861 L 193.07447,18.631085 L 176.09491,36.554369 L 176.44864,19.633786 L 152.0405,44.701316 L 156.81601,27.655396 L 128.87048,44.325304 L 137.00652,14.494942 L 99.863721,44.325304 L 100.74807,27.028707 L 76.163076,45.829355 L 75.632462,22.265877 z"
+ id="path2804" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;opacity:1;fill:#1752b4;fill-opacity:1;fill-rule:nonzero;stroke:#28437f;stroke-width:0.71600807000000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
+ x="68.40242"
+ y="54.03759"
+ id="text2800"><tspan
+ sodipodi:role="line"
+ id="tspan2802"
+ x="68.40242"
+ y="54.03759"
+ style="font-size:36px;fill:#1752b4;fill-opacity:1;fill-rule:nonzero;stroke:#28437f;stroke-width:0.71600807000000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate">Project</tspan></text>
+ </g>
+</svg>
diff --git a/sphinx/themes/scrolls/genindex.html b/sphinx/themes/scrolls/genindex.html
new file mode 100644
index 00000000..9add6e95
--- /dev/null
+++ b/sphinx/themes/scrolls/genindex.html
@@ -0,0 +1,36 @@
+{% extends "layout.html" %}
+{% set title = 'Index' %}
+{% block body %}
+
+ <h1 id="index">Index</h1>
+
+ {% for key, dummy in genindexentries -%}
+ <a href="#{{ key }}"><strong>{{ key }}</strong></a> {% if not loop.last %}| {% endif %}
+ {%- endfor %}
+ <hr>
+
+ {% for key, entries in genindexentries %}
+ <h2 id="{{ key }}">{{ key }}</h2>
+ <table class="indextable"><tr>
+ {%- for column in entries|slice(2) if column %}
+ <td><dl>
+ {%- for entryname, (links, subitems) in column %}
+ <dt>{% if links %}<a href="{{ links[0] }}">{{ entryname|e }}</a>
+ {% for link in links[1:] %}, <a href="{{ link }}">[Link]</a>{% endfor %}
+ {%- else %}{{ entryname|e }}{% endif %}</dt>
+ {%- if subitems %}
+ <dd><dl>
+ {%- for subentryname, subentrylinks in subitems %}
+ <dt><a href="{{ subentrylinks[0] }}">{{ subentryname|e }}</a>
+ {%- for link in subentrylinks[1:] %}, <a href="{{ link }}">[Link]</a>{% endfor -%}
+ </dt>
+ {%- endfor %}
+ </dl></dd>
+ {%- endif -%}
+ {%- endfor %}
+ </dl></td>
+ {%- endfor %}
+ </tr></table>
+ {% endfor %}
+
+{% endblock %}
diff --git a/sphinx/themes/scrolls/layout.html b/sphinx/themes/scrolls/layout.html
new file mode 100644
index 00000000..d1c66ae2
--- /dev/null
+++ b/sphinx/themes/scrolls/layout.html
@@ -0,0 +1,96 @@
+<!doctype html>
+<html>
+ <head>
+ {%- if not embedded %}
+ {%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
+ {%- else %}
+ {%- set titlesuffix = "" %}
+ {%- endif %}
+ <title>{{ title|striptags }}{{ titlesuffix }}</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" href="{{ pathto('_static/style.css', 1) }}" type="text/css">
+ <link rel="stylesheet" href="{{ pathto('_static/print.css', 1) }}" type="text/css" media="print">
+ <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css">
+ {%- if builder != 'htmlhelp' %}
+ <script type="text/javascript">
+ var DOCUMENTATION_OPTIONS = {
+ URL_ROOT: '{{ pathto("", 1) }}',
+ VERSION: '{{ release|e }}',
+ COLLAPSE_MODINDEX: false,
+ FILE_SUFFIX: '{{ file_suffix }}',
+ HAS_SOURCE: {{ has_source|lower }}
+ };
+ </script>
+ <script type="text/javascript" src="{{ pathto('_static/jquery.js', 1) }}"></script>
+ <script type="text/javascript" src="{{ pathto('_static/interface.js', 1) }}"></script>
+ <script type="text/javascript" src="{{ pathto('_static/doctools.js', 1) }}"></script>
+ <script type="text/javascript" src="{{ pathto('_static/theme_extras.js', 1) }}"></script>
+ {%- endif %}
+ {%- if use_opensearch and builder != 'htmlhelp' %}
+ <link rel="search" type="application/opensearchdescription+xml"
+ title="Search within {{ docstitle }}"
+ href="{{ pathto('_static/opensearch.xml', 1) }}">
+ {%- endif %}
+ {%- if hasdoc('about') %}
+ <link rel="author" title="About these documents" href="{{ pathto('about') }}">
+ {%- endif %}
+ <link rel="contents" title="Global table of contents" href="{{ pathto('contents') }}">
+ <link rel="index" title="Global index" href="{{ pathto('genindex') }}">
+ <link rel="search" title="Search" href="{{ pathto('search') }}">
+ {%- if hasdoc('copyright') %}
+ <link rel="copyright" title="Copyright" href="{{ pathto('copyright') }}">
+ {%- endif %}
+ <link rel="top" title="{{ docstitle }}" href="{{ pathto('index') }}">
+ {%- if parents %}
+ <link rel="up" title="{{ parents[-1].title|striptags }}" href="{{ parents[-1].link|e }}">
+ {%- endif %}
+ {%- if next %}
+ <link rel="next" title="{{ next.title|striptags }}" href="{{ next.link|e }}">
+ {%- endif %}
+ {%- if prev %}
+ <link rel="prev" title="{{ prev.title|striptags }}" href="{{ prev.link|e }}">
+ {%- endif %}
+ {% block extrahead %}{% endblock %}
+ </head>
+ <body>
+ <div id="content">
+ <div class="header">
+ <h1 class="heading"><a href="{{ pathto('index') }}"
+ title="back to the documentation overview"><span>{{ title|striptags }}</span></a></h1>
+ </div>
+ <div class="relnav">
+ {%- if prev %}
+ <a href="{{ prev.link|e }}">&laquo; {{ prev.title }}</a> |
+ {%- endif %}
+ <a href="{{ pathto(current_page_name) if current_page_name else '#' }}">{{ title }}</a>
+ {%- if next %}
+ | <a href="{{ next.link|e }}">{{ next.title }} &raquo;</a>
+ {%- endif %}
+ </div>
+ <div id="contentwrapper">
+ {%- if display_toc %}
+ <div id="toc">
+ <h3>Table Of Contents</h3>
+ {{ toc }}
+ </div>
+ {%- endif %}
+ {% block body %}{% endblock %}
+ </div>
+ </div>
+ <div class="footer">
+ {%- if show_copyright %}
+ {%- if hasdoc('copyright') %}
+ {% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
+ {%- else %}
+ {% trans copyright=copyright|e %}&copy; Copyright {{ copyright }}.{% endtrans %}
+ {%- endif %}
+ {%- endif %}
+ {%- if last_updated %}
+ {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
+ {%- endif %}
+ {%- if show_sphinx %}
+ {% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
+ {%- endif %}
+ </div>
+ </body>
+</html>
diff --git a/sphinx/themes/scrolls/modindex.html b/sphinx/themes/scrolls/modindex.html
new file mode 100644
index 00000000..314ebdd9
--- /dev/null
+++ b/sphinx/themes/scrolls/modindex.html
@@ -0,0 +1,43 @@
+{% extends "layout.html" %}
+{% set title = _('Global Module Index') %}
+{% block extrahead %}
+{{ super() }}
+{% if not embedded and collapse_modindex %}
+ <script type="text/javascript">
+ DOCUMENTATION_OPTIONS.COLLAPSE_MODINDEX = true;
+ </script>
+{% endif %}
+{% endblock %}
+{% block body %}
+
+ <h1 id="global-module-index">{{ _('Global Module Index') }}</h1>
+
+ <div class="modindex-jumpbox">
+ {%- for letter in letters %}
+ <a href="#cap-{{ letter }}"><strong>{{ letter }}</strong></a> {% if not loop.last %}| {% endif %}
+ {%- endfor %}
+ </div>
+
+ <table class="modindextable">
+ {%- for modname, collapse, cgroup, indent, fname, synops, pform, dep, stripped in modindexentries %}
+ {%- if not modname -%}
+ <tr class="pcap"><td></td><td>&nbsp;</td><td></td></tr>
+ <tr class="cap"><td></td><td><a name="cap-{{ fname }}"><strong>{{ fname }}</strong></a></td><td></td></tr>
+ {%- else -%}
+ <tr{% if indent %} class="cg-{{ cgroup }}"{% endif %}>
+ <td>{% if collapse -%}
+ <img src="{{ pathto('_static/minus.png', 1) }}" id="toggle-{{ cgroup }}"
+ class="toggler" style="display: none" alt="-" />
+ {%- endif %}</td>
+ <td>{% if indent %}&nbsp;&nbsp;&nbsp;{% endif %}
+ {% if fname %}<a href="{{ fname }}">{% endif -%}
+ <tt class="xref">{{ stripped|e }}{{ modname|e }}</tt>
+ {%- if fname %}</a>{% endif %}
+ {%- if pform and pform[0] %} <em>({{ pform|join(', ') }})</em>{% endif -%}
+ </td><td>{% if dep %}<strong>{{ _('Deprecated')}}:</strong>{% endif %}
+ <em>{{ synops|e }}</em></td></tr>
+ {%- endif -%}
+ {% endfor %}
+ </table>
+
+{% endblock %}
diff --git a/sphinx/themes/scrolls/opensearch.xml b/sphinx/themes/scrolls/opensearch.xml
new file mode 100644
index 00000000..9f2fa427
--- /dev/null
+++ b/sphinx/themes/scrolls/opensearch.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <ShortName>{{ project }}</ShortName>
+ <Description>Search {{ docstitle }}</Description>
+ <InputEncoding>utf-8</InputEncoding>
+ <Url type="text/html" method="get"
+ template="{{ use_opensearch }}/{{ pathto('search') }}?q={searchTerms}&amp;check_keywords=yes&amp;area=default"/>
+ <LongName>{{ docstitle }}</LongName>
+</OpenSearchDescription>
diff --git a/sphinx/themes/scrolls/page.html b/sphinx/themes/scrolls/page.html
new file mode 100644
index 00000000..ee6cad3d
--- /dev/null
+++ b/sphinx/themes/scrolls/page.html
@@ -0,0 +1,4 @@
+{% extends 'layout.html' %}
+{% block body %}
+ {{ body }}
+{% endblock %}
diff --git a/sphinx/themes/scrolls/search.html b/sphinx/themes/scrolls/search.html
new file mode 100644
index 00000000..0c942b70
--- /dev/null
+++ b/sphinx/themes/scrolls/search.html
@@ -0,0 +1,35 @@
+{% extends "layout.html" %}
+{% set title = 'Search' %}
+{% block extrahead %}
+ <script type="text/javascript" src="{{ pathto('_static/searchtools.js', 1) }}"></script>
+{% endblock %}
+{% block body %}
+ <h1 id="search-documentation">Search</h1>
+ <p>
+ From here you can search these documents. Enter your search
+ words into the box below and click "search". Note that the search
+ function will automatically search for all of the words. Pages
+ containing less words won't appear in the result list.
+ </p>
+ <form action="" method="get"><p>
+ <input type="text" name="q" value="">
+ <input type="submit" value="search">
+ </p></form>
+ {% if search_performed %}
+ <h2>Search Results</h2>
+ {% if not search_results %}
+ <p>Your search did not match any results.</p>
+ {% endif %}
+ {% endif %}
+ <div id="search-results">
+ {% if search_results %}
+ <ul>
+ {% for href, caption, context in search_results %}
+ <li><a href="{{ pathto(item.href) }}">{{ caption }}</a>
+ <div class="context">{{ context|e }}</div>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </div>
+{% endblock %}
diff --git a/sphinx/themes/scrolls/static/darkmetal.png b/sphinx/themes/scrolls/static/darkmetal.png
new file mode 100644
index 00000000..e8c9ff62
--- /dev/null
+++ b/sphinx/themes/scrolls/static/darkmetal.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/headerbg.png b/sphinx/themes/scrolls/static/headerbg.png
new file mode 100644
index 00000000..0c5b3657
--- /dev/null
+++ b/sphinx/themes/scrolls/static/headerbg.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/logo.png b/sphinx/themes/scrolls/static/logo.png
new file mode 100644
index 00000000..d1961cf0
--- /dev/null
+++ b/sphinx/themes/scrolls/static/logo.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/metal.png b/sphinx/themes/scrolls/static/metal.png
new file mode 100644
index 00000000..97166f13
--- /dev/null
+++ b/sphinx/themes/scrolls/static/metal.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/navigation.png b/sphinx/themes/scrolls/static/navigation.png
new file mode 100644
index 00000000..1e248d4d
--- /dev/null
+++ b/sphinx/themes/scrolls/static/navigation.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/print.css b/sphinx/themes/scrolls/static/print.css
new file mode 100644
index 00000000..fb633d87
--- /dev/null
+++ b/sphinx/themes/scrolls/static/print.css
@@ -0,0 +1,5 @@
+div.header, div.relnav, #toc { display: none; }
+#contentwrapper { padding: 0; margin: 0; border: none; }
+body { color: black; background-color: white; }
+div.footer { border-top: 1px solid #888; color: #888; margin-top: 1cm; }
+div.footer a { text-decoration: none; }
diff --git a/sphinx/themes/scrolls/static/style.css_t b/sphinx/themes/scrolls/static/style.css_t
new file mode 100644
index 00000000..0c346d04
--- /dev/null
+++ b/sphinx/themes/scrolls/static/style.css_t
@@ -0,0 +1,398 @@
+body {
+ background-color: #222;
+ margin: 0;
+ padding: 0;
+ font-family: 'Georgia', serif;
+ font-size: 15px;
+ color: #eee;
+}
+
+div.footer {
+ border-top: 1px solid #111;
+ padding: 8px;
+ font-size: 11px;
+ text-align: center;
+ letter-spacing: 0.5px;
+}
+
+div.footer a {
+ color: #eee;
+}
+
+div.header {
+ margin: 0 -15px 0 -15px;
+ background: url(headerbg.png) repeat-x;
+ border-top: 6px solid {{ theme_headerbordercolor }};
+}
+
+div.relnav {
+ border-bottom: 1px solid #111;
+ background: url(navigation.png);
+ margin: 0 -15px 0 -15px;
+ padding: 2px 20px 0 28px;
+ line-height: 25px;
+ color: #aaa;
+ font-size: 12px;
+ text-align: center;
+}
+
+div.relnav a {
+ color: #eee;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+div.relnav a:hover {
+ text-decoration: underline;
+}
+
+#content {
+ background-color: white;
+ color: #111;
+ border-bottom: 1px solid black;
+ background: url(watermark.png) center 0;
+ padding: 0 15px 0 15px;
+ margin: 0;
+}
+
+h1 {
+ margin: 0;
+ padding: 15px 0 0 0;
+}
+
+h1.heading {
+ margin: 0;
+ padding: 0;
+ height: 80px;
+}
+
+h1.heading:hover {
+ background: #222;
+}
+
+h1.heading a {
+ background: url({{ logo if logo else 'logo.png' }}) no-repeat center 0;
+ display: block;
+ width: 100%;
+ height: 80px;
+}
+
+h1.heading a:focus {
+ -moz-outline: none;
+ outline: none;
+}
+
+h1.heading span {
+ display: none;
+}
+
+#jinjalogo {
+ background-image: url(jinjalogo.png);
+ background-repeat: no-repeat;
+ width: 400px;
+ height: 160px;
+}
+
+#contentwrapper {
+ max-width: 680px;
+ padding: 0 18px 20px 18px;
+ margin: 0 auto 0 auto;
+ border-right: 1px solid #eee;
+ border-left: 1px solid #eee;
+ background: url(watermark_blur.png) center -114px;
+}
+
+#contentwrapper h2,
+#contentwrapper h2 a {
+ color: #222;
+ font-size: 24px;
+ margin: 20px 0 0 0;
+}
+
+#contentwrapper h3,
+#contentwrapper h3 a {
+ color: {{ theme_subheadlinecolor }};
+ font-size: 20px;
+ margin: 20px 0 0 0;
+}
+
+table.docutils {
+ border-collapse: collapse;
+ border: 2px solid #aaa;
+ margin: 0.5em 1.5em 0.5em 1.5em;
+}
+
+table.docutils td {
+ padding: 2px;
+ border: 1px solid #ddd;
+}
+
+p, li, dd, dt, blockquote {
+ color: #333;
+}
+
+blockquote {
+ margin: 10px 0 10px 20px;
+}
+
+p {
+ line-height: 20px;
+ margin-bottom: 0;
+ margin-top: 10px;
+}
+
+hr {
+ border-top: 1px solid #ccc;
+ border-bottom: 0;
+ border-right: 0;
+ border-left: 0;
+ margin-bottom: 10px;
+ margin-top: 20px;
+}
+
+dl {
+ margin-left: 10px;
+}
+
+li, dt {
+ margin-top: 5px;
+}
+
+dt {
+ font-weight: bold;
+ color: #000;
+}
+
+dd {
+ margin-top: 10px;
+ line-height: 20px;
+}
+
+th {
+ text-align: left;
+ padding: 3px;
+ background-color: #f2f2f2;
+}
+
+a {
+ color: {{ theme_linkcolor }};
+}
+
+a:hover {
+ color: {{ theme_visitedlinkcolor }};
+}
+
+pre {
+ background: #ededed url(metal.png);
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+ padding: 5px;
+ font-size: 13px;
+ font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+}
+
+tt {
+ font-size: 13px;
+ font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+ color: black;
+ padding: 1px 2px 1px 2px;
+ background-color: #fafafa;
+ border-bottom: 1px solid #eee;
+}
+
+a.reference:hover tt {
+ border-bottom-color: #aaa;
+}
+
+cite {
+ /* abusing <cite>, it's generated by ReST for `x` */
+ font-size: 13px;
+ font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+ font-weight: bold;
+ font-style: normal;
+}
+
+div.admonition {
+ margin: 10px 0 10px 0;
+ padding: 10px;
+ border: 1px solid #ccc;
+}
+
+div.admonition p.admonition-title {
+ background-color: {{ theme_admonitioncolor }};
+ color: white;
+ margin: -10px -10px 10px -10px;
+ padding: 4px 10px 4px 10px;
+ font-weight: bold;
+ font-size: 15px;
+}
+
+div.admonition p.admonition-title a {
+ color: white!important;
+}
+
+a.headerlink {
+ color: #B4B4B4!important;
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none!important;
+ visibility: hidden;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink,
+dt:hover > a.headerlink {
+ visibility: visible;
+}
+
+a.headerlink:hover {
+ background-color: #B4B4B4;
+ color: #F0F0F0!important;
+}
+
+table.indextable {
+ width: 100%;
+}
+
+table.indextable td {
+ vertical-align: top;
+ width: 50%;
+}
+
+table.indextable dl dd {
+ font-size: 11px;
+}
+
+table.indextable dl dd a {
+ color: #000;
+}
+
+div.modindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+table.modindextable {
+ width: 100%;
+ border: none;
+}
+
+table.modindextable img.toggler {
+ margin-right: 10px;
+}
+
+dl.function dt,
+dl.class dt,
+dl.exception dt,
+dl.method dt,
+dl.attribute dt {
+ font-weight: normal;
+}
+
+dt .descname {
+ font-weight: bold;
+ margin-right: 4px;
+}
+
+dt .descname, dt .descclassname {
+ padding: 0;
+ background: transparent;
+ border-bottom: 1px solid #111;
+}
+
+dt .descclassname {
+ margin-left: 2px;
+}
+
+dl dt big {
+ font-size: 100%;
+}
+
+ul.search {
+ margin: 10px 0 0 30px;
+ padding: 0;
+}
+
+ul.search li {
+ margin: 10px 0 0 0;
+ padding: 0;
+}
+
+ul.search div.context {
+ font-size: 12px;
+ padding: 4px 0 0 20px;
+ color: #888;
+}
+
+span.highlight {
+ background-color: #eee;
+ border: 1px solid #ccc;
+}
+
+#toc {
+ margin: 0 -17px 0 -17px;
+ display: none;
+}
+
+#toc h3 {
+ float: right;
+ margin: 5px 5px 0 0;
+ padding: 0;
+ font-size: 12px;
+ color: #777;
+}
+
+#toc h3:hover {
+ color: #333;
+ cursor: pointer;
+}
+
+.expandedtoc {
+ background: #222 url(darkmetal.png);
+ border-bottom: 1px solid #111;
+ outline-bottom: 1px solid #000;
+ padding: 5px;
+}
+
+.expandedtoc h3 {
+ color: #aaa;
+ margin: 0!important;
+}
+
+.expandedtoc h3:hover {
+ color: white!important;
+}
+
+#tod h3:hover {
+ color: white;
+}
+
+#toc a {
+ color: #ddd;
+ text-decoration: none;
+}
+
+#toc a:hover {
+ color: white;
+ text-decoration: underline;
+}
+
+#toc ul {
+ margin: 5px 0 12px 17px;
+ padding: 0 7px 0 7px;
+}
+
+#toc ul ul {
+ margin-bottom: 0;
+}
+
+#toc ul li {
+ margin: 2px 0 0 0;
+}
diff --git a/sphinx/themes/scrolls/static/theme_extras.js b/sphinx/themes/scrolls/static/theme_extras.js
new file mode 100644
index 00000000..1c042187
--- /dev/null
+++ b/sphinx/themes/scrolls/static/theme_extras.js
@@ -0,0 +1,26 @@
+$(function() {
+
+ var
+ toc = $('#toc').show(),
+ items = $('#toc > ul').hide();
+
+ $('#toc h3')
+ .click(function() {
+ if (items.is(':visible')) {
+ items.animate({
+ height: 'hide',
+ opacity: 'hide'
+ }, 300, function() {
+ toc.removeClass('expandedtoc');
+ });
+ }
+ else {
+ items.animate({
+ height: 'show',
+ opacity: 'show'
+ }, 400);
+ toc.addClass('expandedtoc');
+ }
+ });
+
+});
diff --git a/sphinx/themes/scrolls/static/watermark.png b/sphinx/themes/scrolls/static/watermark.png
new file mode 100644
index 00000000..eb1b6be9
--- /dev/null
+++ b/sphinx/themes/scrolls/static/watermark.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/watermark_blur.png b/sphinx/themes/scrolls/static/watermark_blur.png
new file mode 100644
index 00000000..563f6cde
--- /dev/null
+++ b/sphinx/themes/scrolls/static/watermark_blur.png
Binary files differ
diff --git a/sphinx/themes/scrolls/theme.conf b/sphinx/themes/scrolls/theme.conf
new file mode 100644
index 00000000..b4205046
--- /dev/null
+++ b/sphinx/themes/scrolls/theme.conf
@@ -0,0 +1,11 @@
+[theme]
+inherit = default
+stylesheet = scrolls.css
+pygments_style = tango
+
+[options]
+headerbordercolor = #1752b4
+subheadlinecolor = #0d306b
+linkcolor = #1752b4
+visitedlinkcolor = #444
+admonitioncolor = #28437f
diff --git a/sphinx/theming.py b/sphinx/theming.py
index e5807029..217dd81c 100644
--- a/sphinx/theming.py
+++ b/sphinx/theming.py
@@ -78,7 +78,7 @@ class Theme(object):
dirname = path.dirname(name)
if not path.isdir(path.join(self.themedir, dirname)):
os.makedirs(path.join(self.themedir, dirname))
- fp = open(path.join(self.themedir, name), 'w')
+ fp = open(path.join(self.themedir, name), 'wb')
fp.write(tinfo.read(name))
fp.close()
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index 50c5bd3f..87b08095 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -446,6 +446,23 @@ def split_explicit_title(text):
return True, match.group(1), match.group(2)
return False, text, text
+
+from docutils import nodes
+
+def make_refnode(builder, fromdocname, todocname, targetid, child, title=None):
+ """Shortcut to create a reference node."""
+ node = nodes.reference('', '')
+ if fromdocname == todocname:
+ node['refid'] = targetid
+ else:
+ node['refuri'] = (builder.get_relative_uri(fromdocname, todocname)
+ + '#' + targetid)
+ if title:
+ node['reftitle'] = title
+ node.append(child)
+ return node
+
+
# 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!
@@ -475,8 +492,7 @@ def _new_traverse(self, condition=None,
return self._old_traverse(condition, include_self,
descend, siblings, ascend)
-import docutils.nodes
-docutils.nodes.Node._old_traverse = docutils.nodes.Node.traverse
-docutils.nodes.Node._all_traverse = _all_traverse
-docutils.nodes.Node._fast_traverse = _fast_traverse
-docutils.nodes.Node.traverse = _new_traverse
+nodes.Node._old_traverse = nodes.Node.traverse
+nodes.Node._all_traverse = _all_traverse
+nodes.Node._fast_traverse = _fast_traverse
+nodes.Node.traverse = _new_traverse
diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py
index ceca5c8a..9e7bb63d 100644
--- a/sphinx/writers/text.py
+++ b/sphinx/writers/text.py
@@ -47,7 +47,7 @@ STDINDENT = 3
class TextTranslator(nodes.NodeVisitor):
- sectionchars = '*=-~"+'
+ sectionchars = '*=-~"+`'
def __init__(self, document, builder):
nodes.NodeVisitor.__init__(self, document)
diff --git a/tests/root/conf.py b/tests/root/conf.py
index fd82be7d..a82602ff 100644
--- a/tests/root/conf.py
+++ b/tests/root/conf.py
@@ -25,6 +25,7 @@ today_fmt = '%B %d, %Y'
exclude_trees = ['_build']
keep_warnings = True
pygments_style = 'sphinx'
+show_authors = True
rst_epilog = '.. |subst| replace:: global substitution'
diff --git a/tests/root/desc.txt b/tests/root/desc.txt
index d6915dc2..ee70b050 100644
--- a/tests/root/desc.txt
+++ b/tests/root/desc.txt
@@ -43,15 +43,35 @@ Testing description units
C items
=======
-.. cfunction:: Sphinx_DoSomething()
+.. c:function:: Sphinx_DoSomething()
-.. cmember:: SphinxStruct.member
+.. c:member:: SphinxStruct.member
-.. cmacro:: SPHINX_USE_PYTHON
+.. c:macro:: SPHINX_USE_PYTHON
-.. ctype:: SphinxType
+.. c:type:: SphinxType
-.. cvar:: sphinx_global
+.. c:var:: sphinx_global
+
+
+References
+==========
+
+:c:func:`CFunction`. :c:func:`!malloc`.
+
+
+Others
+======
+
+.. envvar:: HOME
+
+.. program:: python
+
+.. cmdoption:: -c command
+
+.. program:: perl
+
+.. cmdoption:: -c
Testing references
diff --git a/tests/root/markup.txt b/tests/root/markup.txt
index 32b037ee..c5022b32 100644
--- a/tests/root/markup.txt
+++ b/tests/root/markup.txt
@@ -5,7 +5,11 @@
Testing various markup
======================
+Meta markup
+-----------
+
.. sectionauthor:: Georg Brandl
+.. moduleauthor:: Georg Brandl
.. contents:: TOC
@@ -13,7 +17,11 @@ Testing various markup
:author: Me
:keywords: docs, sphinx
-A |subst|.
+
+Generic reST
+------------
+
+A |subst| (the definition is in rst_epilog).
.. _label:
@@ -21,22 +29,14 @@ A |subst|.
some code
-Admonitions
------------
-
-.. note:: Note
- Note text.
-
-.. warning:: Warning
-
- Warning text.
+Option list:
-.. tip::
- Tip text.
+-h help
+--help also help
Body directives
----------------
+^^^^^^^^^^^^^^^
.. topic:: Title
@@ -69,7 +69,67 @@ Body directives
b
-
+
+Admonitions
+^^^^^^^^^^^
+
+.. admonition:: My Admonition
+
+ Admonition text.
+
+.. note::
+ Note text.
+
+.. warning::
+
+ Warning text.
+
+.. tip::
+ Tip text.
+
+
+Inline markup
+-------------
+
+*Generic inline markup*
+
+* :command:`command`
+* :dfn:`dfn`
+* :guilabel:`guilabel`
+* :kbd:`kbd`
+* :mailheader:`mailheader`
+* :makevar:`makevar`
+* :manpage:`manpage`
+* :mimetype:`mimetype`
+* :newsgroup:`newsgroup`
+* :program:`program`
+* :regexp:`regexp`
+* :menuselection:`File --> Close`
+* :file:`a/{varpart}/b`
+* :samp:`print {i}`
+
+*Linking inline markup*
+
+* :pep:`8`
+* :rfc:`1`
+* :envvar:`HOME`
+* :keyword:`with`
+* :token:`try statement <try_stmt>`
+* :doc:`subdir/includes`
+* ``:download:`` is tested in includes.txt
+* :option:`Python -c option <python -c>`
+
+Test :abbr:`abbr (abbreviation)` and another :abbr:`abbr (abbreviation)`.
+
+
+.. _with:
+
+With
+----
+
+(Empty section.)
+
+
Tables
------
@@ -96,6 +156,17 @@ Version markup
Boring stuff.
+Code blocks
+-----------
+
+.. code-block:: ruby
+ :linenos:
+
+ def ruby?
+ false
+ end
+
+
Misc stuff
----------
@@ -124,11 +195,6 @@ This is a side note.
This tests :CLASS:`role names in uppercase`.
-Option list:
-
--h help
---help also help
-
.. centered:: LICENSE AGREEMENT
.. acks::
@@ -146,7 +212,7 @@ Option list:
Particle with half-integer spin.
.. productionlist::
- try_stmt: try1_stmt | try2_stmt
+ try_stmt: `try1_stmt` | `try2_stmt`
try1_stmt: "try" ":" `suite`
: ("except" [`expression` ["," `target`]] ":" `suite`)+
: ["else" ":" `suite`]
@@ -154,7 +220,6 @@ Option list:
try2_stmt: "try" ":" `suite`
: "finally" ":" `suite`
-Test :abbr:`abbr (abbreviation)` and another :abbr:`abbr (abbreviation)`.
Index markup
------------
@@ -179,11 +244,6 @@ Invalid index markup...
Testing öäü...
-Object markup
--------------
-
-:cfunc:`CFunction`.
-
Only directive
--------------
@@ -207,3 +267,4 @@ Only directive
.. rubric:: Footnotes
.. [#] Like footnotes.
+
diff --git a/tests/test_build.py b/tests/test_build.py
index 6668e245..e0a59e19 100644
--- a/tests/test_build.py
+++ b/tests/test_build.py
@@ -84,17 +84,62 @@ HTML_XPATH = {
".//dd": r'Return spam\.',
},
'markup.html': {
+ ".//title": 'set by title directive',
+ ".//p/em": 'Section author: Georg Brandl',
+ ".//p/em": 'Module author: Georg Brandl',
+ # created by the meta directive
".//meta[@name='author'][@content='Me']": '',
".//meta[@name='keywords'][@content='docs, sphinx']": '',
- ".//a[@href='contents.html#ref1']": '',
+ # a label created by ``.. _label:``
".//div[@id='label']": '',
+ # code with standard code blocks
+ ".//pre": '^some code$',
+ # an option list
".//span[@class='option']": '--help',
+ # admonitions
+ ".//p[@class='first admonition-title']": 'My Admonition',
+ ".//p[@class='last']": 'Note text.',
+ ".//p[@class='last']": 'Warning text.',
+ # inline markup
+ ".//li/strong": '^command$',
+ ".//li/strong": '^program$',
+ ".//li/em": '^dfn$',
+ ".//li/tt/span[@class='pre']": '^kbd$',
+ ".//li/em": u'File \N{TRIANGULAR BULLET} Close',
+ ".//li/tt/span[@class='pre']": '^a/$',
+ ".//li/tt/em/span[@class='pre']": '^varpart$',
+ ".//li/tt/em/span[@class='pre']": '^i$',
+ ".//a[@href='http://www.python.org/dev/peps/pep-0008']/strong": 'PEP 8',
+ ".//a[@href='http://tools.ietf.org/html/rfc1.html']/strong": 'RFC 1',
+ ".//a[@href='desc.html#envvar-HOME']/tt/span[@class='pre']": 'HOME',
+ ".//a[@href='#with']/tt/span[@class='pre']": '^with$',
+ ".//a[@href='#grammar-token-try_stmt']/tt/span": '^statement$',
+ ".//a[@href='subdir/includes.html']/em": 'Including in subdir',
+ ".//a[@href='desc.html#cmdoption-python-c']/em": 'Python -c option',
+ # abbreviations
+ ".//abbr[@title='abbreviation']": '^abbr$',
+ # version stuff
+ ".//span[@class='versionmodified']": 'New in version 0.6',
+ # footnote reference
+ ".//a[@class='footnote-reference']": r'\[1\]',
+ # created by reference lookup
+ ".//a[@href='contents.html#ref1']": '',
+ # ``seealso`` directive
+ ".//div/p[@class='first admonition-title']": 'See also',
+ # a ``hlist`` directive
+ ".//table[@class='hlist']/tr/td/ul/li": '^This$',
+ # a ``centered`` directive
+ ".//p[@class='centered']/strong": 'LICENSE',
+ # a glossary
+ ".//dl/dt[@id='term-boson']": 'boson',
+ # a production list
+ ".//pre/strong": 'try_stmt',
+ ".//pre/a[@href='#grammar-token-try1_stmt']/tt/span": 'try1_stmt',
+ # tests for ``only`` directive
".//p": 'A global substitution.',
".//p": 'In HTML.',
".//p": 'In both.',
".//p": 'Always present',
- ".//title": 'set by title directive',
- ".//span[@class='pre']": 'CFunction()',
},
'desc.html': {
".//dt[@id='mod.Cls.meth1']": '',
@@ -103,6 +148,7 @@ HTML_XPATH = {
".//dl[@class='userdesc']": '',
".//dt[@id='userdescrole-myobj']": '',
".//a[@href='#userdescrole-myobj']": '',
+ ".//span[@class='pre']": 'CFunction()',
},
'contents.html': {
".//meta[@name='hc'][@content='hcval']": '',
@@ -110,10 +156,13 @@ HTML_XPATH = {
#".//td[@class='label']": r'\[Ref1\]', # docutils 0.5 only
".//td[@class='label']": '',
".//li[@class='toctree-l1']/a": 'Testing various markup',
- ".//li[@class='toctree-l2']/a": 'Admonitions',
+ ".//li[@class='toctree-l2']/a": 'Inline markup',
".//title": 'Sphinx <Tests>',
".//div[@class='footer']": 'Georg Brandl & Team',
".//a[@href='http://python.org/']": '',
+ ".//li/a[@href='genindex.html']/em": 'Index',
+ ".//li/a[@href='modindex.html']/em": 'Module Index',
+ ".//li/a[@href='search.html']/em": 'Search Page',
},
'bom.html': {
".//title": " File with UTF-8 BOM",
diff --git a/tests/test_config.py b/tests/test_config.py
index b3aa4eea..1560c257 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -32,7 +32,7 @@ def test_core_config(app):
# simple default values
assert 'exclude_dirs' not in cfg.__dict__
assert cfg.exclude_dirs == []
- assert cfg.show_authors == False
+ assert cfg.trim_footnote_reference_space == False
# complex default values
assert 'html_title' not in cfg.__dict__
diff --git a/tests/test_env.py b/tests/test_env.py
index a06656d6..e9118a63 100644
--- a/tests/test_env.py
+++ b/tests/test_env.py
@@ -20,8 +20,8 @@ warnings = []
def setup_module():
global app, env
- app = TestApp(srcdir='(temp)')
- env = BuildEnvironment(app.srcdir, app.doctreedir, app.config)
+ app = TestApp(srcdir='(temp)', freshenv=True)
+ env = app.env
env.set_warnfunc(lambda *args: warnings.append(args))
def teardown_module():
@@ -51,7 +51,7 @@ def test_images():
tree = env.get_doctree('images')
app._warning.reset()
- htmlbuilder = StandaloneHTMLBuilder(app, env)
+ htmlbuilder = StandaloneHTMLBuilder(app)
htmlbuilder.post_process_images(tree)
assert "no matching candidate for image URI u'foo.*'" in \
app._warning.content[-1]
@@ -61,7 +61,7 @@ def test_images():
set(['img.png', 'img1.png', 'simg.png', 'svgimg.svg'])
app._warning.reset()
- latexbuilder = LaTeXBuilder(app, env)
+ latexbuilder = LaTeXBuilder(app)
latexbuilder.post_process_images(tree)
assert "no matching candidate for image URI u'foo.*'" in \
app._warning.content[-1]
@@ -92,7 +92,7 @@ def test_second_update():
assert 'autodoc' not in env.found_docs
def test_object_inventory():
- refs = env.descrefs
+ refs = env.domaindata['py']['objects']
assert 'func_without_module' in refs
assert refs['func_without_module'] == ('desc', 'function')
@@ -109,5 +109,8 @@ def test_object_inventory():
assert 'func_in_module' not in refs
assert 'func_noindex' not in refs
- assert 'mod' in env.modules
- assert env.modules['mod'] == ('desc', 'Module synopsis.', 'UNIX', False)
+ assert env.domaindata['py']['modules']['mod'] == \
+ ('desc', 'Module synopsis.', 'UNIX', False)
+
+ assert env.domains['py'].data is env.domaindata['py']
+ assert env.domains['c'].data is env.domaindata['c']
diff --git a/tests/test_theming.py b/tests/test_theming.py
index 349a9ce4..1c894c2b 100644
--- a/tests/test_theming.py
+++ b/tests/test_theming.py
@@ -24,7 +24,7 @@ def test_theme_api(app):
# test Theme class API
assert set(Theme.themes.keys()) == \
- set(['basic', 'default', 'sphinxdoc', 'traditional',
+ set(['basic', 'default', 'scrolls', 'sphinxdoc', 'traditional',
'testtheme', 'ziptheme'])
assert Theme.themes['testtheme'][1] is None
assert isinstance(Theme.themes['ziptheme'][1], zipfile.ZipFile)