mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'master' into drop_websupport
This commit is contained in:
commit
c50321d3ca
@ -43,6 +43,7 @@ addons:
|
|||||||
- texlive-xetex
|
- texlive-xetex
|
||||||
- lmodern
|
- lmodern
|
||||||
- latex-xcolor
|
- latex-xcolor
|
||||||
|
- imagemagick
|
||||||
install:
|
install:
|
||||||
- pip install -U pip setuptools
|
- pip install -U pip setuptools
|
||||||
- pip install docutils==$DOCUTILS
|
- pip install docutils==$DOCUTILS
|
||||||
@ -51,4 +52,4 @@ install:
|
|||||||
script:
|
script:
|
||||||
- flake8
|
- flake8
|
||||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then make style-check type-check test-async; fi
|
- if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then make style-check type-check test-async; fi
|
||||||
- if [[ $TRAVIS_PYTHON_VERSION != '3.6' ]]; then make test; fi
|
- if [[ $TRAVIS_PYTHON_VERSION != '3.6' ]]; then SKIP_LATEX_BUILD=1 make test; fi
|
||||||
|
2
AUTHORS
2
AUTHORS
@ -12,6 +12,7 @@ Other co-maintainers:
|
|||||||
* Robert Lehmann <@lehmannro>
|
* Robert Lehmann <@lehmannro>
|
||||||
* Roland Meister <@rolmei>
|
* Roland Meister <@rolmei>
|
||||||
* Takeshi Komiya <@tk0miya>
|
* Takeshi Komiya <@tk0miya>
|
||||||
|
* Jean-François Burnol <@jfbu>
|
||||||
* Yoshiki Shibukawa <@shibu_jp>
|
* Yoshiki Shibukawa <@shibu_jp>
|
||||||
|
|
||||||
Other contributors, listed alphabetically, are:
|
Other contributors, listed alphabetically, are:
|
||||||
@ -21,7 +22,6 @@ Other contributors, listed alphabetically, are:
|
|||||||
* Jakob Lykke Andersen -- Rewritten C++ domain
|
* Jakob Lykke Andersen -- Rewritten C++ domain
|
||||||
* Henrique Bastos -- SVG support for graphviz extension
|
* Henrique Bastos -- SVG support for graphviz extension
|
||||||
* Daniel Bültmann -- todo extension
|
* Daniel Bültmann -- todo extension
|
||||||
* Jean-François Burnol -- LaTeX improvements
|
|
||||||
* Marco Buttu -- doctest extension (pyversion option)
|
* Marco Buttu -- doctest extension (pyversion option)
|
||||||
* Etienne Desautels -- apidoc module
|
* Etienne Desautels -- apidoc module
|
||||||
* Michael Droettboom -- inheritance_diagram extension
|
* Michael Droettboom -- inheritance_diagram extension
|
||||||
|
9
CHANGES
9
CHANGES
@ -45,6 +45,7 @@ Incompatible changes
|
|||||||
* ``Builder.env`` is not filled at instantiation
|
* ``Builder.env`` is not filled at instantiation
|
||||||
* #3594: LaTeX: single raw directive has been considered as block level element
|
* #3594: LaTeX: single raw directive has been considered as block level element
|
||||||
* #3639: If ``html_experimental_html5_writer`` is available, epub builder use it by default.
|
* #3639: If ``html_experimental_html5_writer`` is available, epub builder use it by default.
|
||||||
|
* ``Sphinx.add_source_parser()`` raises an error if duplicated
|
||||||
|
|
||||||
Features removed
|
Features removed
|
||||||
----------------
|
----------------
|
||||||
@ -117,6 +118,8 @@ Features added
|
|||||||
* #3641: Epub theme supports HTML structures that are generated by HTML5 writer.
|
* #3641: Epub theme supports HTML structures that are generated by HTML5 writer.
|
||||||
* #3644 autodoc uses inspect instead of checking types. Thanks to
|
* #3644 autodoc uses inspect instead of checking types. Thanks to
|
||||||
Jeroen Demeyer.
|
Jeroen Demeyer.
|
||||||
|
* Add a new extension; ``sphinx.ext.imgconverter``. It converts images in the
|
||||||
|
document to appropriate format for builders
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
@ -131,6 +134,8 @@ Bugs fixed
|
|||||||
* C++, properly look up ``any`` references.
|
* C++, properly look up ``any`` references.
|
||||||
* #3624: sphinx.ext.intersphinx couldn't load inventories compressed with gzip
|
* #3624: sphinx.ext.intersphinx couldn't load inventories compressed with gzip
|
||||||
* #3551: PDF information dictionary is lacking author and title data
|
* #3551: PDF information dictionary is lacking author and title data
|
||||||
|
* #3351: intersphinx does not refers context like ``py:module``, ``py:class``
|
||||||
|
and so on.
|
||||||
* Fail to load template file if the parent template is archived
|
* Fail to load template file if the parent template is archived
|
||||||
|
|
||||||
Deprecated
|
Deprecated
|
||||||
@ -146,6 +151,8 @@ Deprecated
|
|||||||
instead (as Sphinx does since 1.5.)
|
instead (as Sphinx does since 1.5.)
|
||||||
* ``Sphinx.status_iterator()`` and ``Sphinx.old_status_iterator()`` is now
|
* ``Sphinx.status_iterator()`` and ``Sphinx.old_status_iterator()`` is now
|
||||||
deprecated. Please use ``sphinx.util:status_iterator()`` intead.
|
deprecated. Please use ``sphinx.util:status_iterator()`` intead.
|
||||||
|
* ``Sphinx._directive_helper()`` is deprecated. Please use
|
||||||
|
``sphinx.util.docutils.directive_helper()`` instead.
|
||||||
* ``BuildEnvironment.set_warnfunc()`` is now deprecated
|
* ``BuildEnvironment.set_warnfunc()`` is now deprecated
|
||||||
* Following methods of ``BuildEnvironment`` is now deprecated.
|
* Following methods of ``BuildEnvironment`` is now deprecated.
|
||||||
|
|
||||||
@ -165,6 +172,8 @@ Deprecated
|
|||||||
* #3254: ``sphinx.websupport`` is now separated into independent package;
|
* #3254: ``sphinx.websupport`` is now separated into independent package;
|
||||||
``sphinxcontrib-websupport``. ``sphinx.websupport`` will be removed in
|
``sphinxcontrib-websupport``. ``sphinx.websupport`` will be removed in
|
||||||
Sphinx-2.0.
|
Sphinx-2.0.
|
||||||
|
* #3628: ``sphinx_themes`` entry_point is deprecated. Please use
|
||||||
|
``sphinx.html_themes`` instead.
|
||||||
|
|
||||||
Release 1.5.6 (in development)
|
Release 1.5.6 (in development)
|
||||||
==============================
|
==============================
|
||||||
|
@ -15,6 +15,7 @@ These extensions are built in and can be activated by respective entries in the
|
|||||||
githubpages
|
githubpages
|
||||||
graphviz
|
graphviz
|
||||||
ifconfig
|
ifconfig
|
||||||
|
imgconverter
|
||||||
inheritance
|
inheritance
|
||||||
intersphinx
|
intersphinx
|
||||||
linkcode
|
linkcode
|
||||||
|
30
doc/ext/imgconverter.rst
Normal file
30
doc/ext/imgconverter.rst
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
.. highlight:: rest
|
||||||
|
|
||||||
|
:mod:`sphinx.ext.imgconverter` -- Convert images to appropriate format for builders
|
||||||
|
===================================================================================
|
||||||
|
|
||||||
|
.. module:: sphinx.ext.imgconverter
|
||||||
|
:synopsis: Convert images to appropriate format for builders
|
||||||
|
|
||||||
|
.. versionadded:: 1.6
|
||||||
|
|
||||||
|
This extension converts images in your document to appropriate format for builders.
|
||||||
|
For example, it allows you to use SVG images with LaTeX builder.
|
||||||
|
As a result, you don't mind what image format the builder supports.
|
||||||
|
|
||||||
|
Internally, this extension uses Imagemagick_ to convert images.
|
||||||
|
|
||||||
|
.. _Imagemagick: https://www.imagemagick.org/script/index.php
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. confval:: image_converter
|
||||||
|
|
||||||
|
A path to :command:`convert` command. By default, the imgconverter uses
|
||||||
|
the command from search paths.
|
||||||
|
|
||||||
|
.. confval:: image_converter_args
|
||||||
|
|
||||||
|
Additional command-line arguments to give to :command:`convert`, as a list.
|
||||||
|
The default is an empty list ``[]``.
|
@ -370,6 +370,13 @@ package.
|
|||||||
|
|
||||||
.. versionadded:: 1.4
|
.. versionadded:: 1.4
|
||||||
|
|
||||||
|
.. method:: Sphinx.add_html_theme(name, theme_path)
|
||||||
|
|
||||||
|
Register a HTML Theme. The *name* is a name of theme, and *path* is a
|
||||||
|
full path to the theme (refs: :ref:`distribute-your-theme`).
|
||||||
|
|
||||||
|
.. versionadded:: 1.6
|
||||||
|
|
||||||
.. method:: Sphinx.add_env_collector(collector)
|
.. method:: Sphinx.add_env_collector(collector)
|
||||||
|
|
||||||
Register an environment collector class (refs: :ref:`collector-api`)
|
Register an environment collector class (refs: :ref:`collector-api`)
|
||||||
|
@ -46,34 +46,14 @@ file :file:`blue.zip`, you can put it right in the directory containing
|
|||||||
html_theme = "blue"
|
html_theme = "blue"
|
||||||
html_theme_path = ["."]
|
html_theme_path = ["."]
|
||||||
|
|
||||||
The third form provides your theme path dynamically to Sphinx if the
|
The third form is a python package. If a theme you want to use is distributed
|
||||||
``setuptools`` package is installed. You can provide an entry point section
|
as a python package, you can use it after installing::
|
||||||
called ``sphinx_themes`` in your setup.py file and write a ``get_path`` function
|
|
||||||
that has to return the directory with themes in it::
|
|
||||||
|
|
||||||
# 'setup.py'
|
# installing theme package
|
||||||
|
$ pip install sphinxjp.themes.dotted
|
||||||
|
|
||||||
setup(
|
# use it in your conf.py
|
||||||
...
|
html_theme = "dotted"
|
||||||
entry_points = {
|
|
||||||
'sphinx_themes': [
|
|
||||||
'path = your_package:get_path',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
...
|
|
||||||
)
|
|
||||||
|
|
||||||
# 'your_package.py'
|
|
||||||
|
|
||||||
from os import path
|
|
||||||
package_dir = path.abspath(path.dirname(__file__))
|
|
||||||
template_path = path.join(package_dir, 'themes')
|
|
||||||
|
|
||||||
def get_path():
|
|
||||||
return template_path
|
|
||||||
|
|
||||||
.. versionadded:: 1.2
|
|
||||||
'sphinx_themes' entry_points feature.
|
|
||||||
|
|
||||||
|
|
||||||
.. _builtin-themes:
|
.. _builtin-themes:
|
||||||
@ -310,6 +290,48 @@ Python :mod:`ConfigParser` module) and has the following structure:
|
|||||||
and are accessible from all templates as ``theme_<name>``.
|
and are accessible from all templates as ``theme_<name>``.
|
||||||
|
|
||||||
|
|
||||||
|
.. _distribute-your-theme:
|
||||||
|
|
||||||
|
Distribute your theme as a python package
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
As a way to distribute your theme, you can use python package. Python package
|
||||||
|
brings to users easy setting up ways.
|
||||||
|
|
||||||
|
To distribute your theme as a python package, please define an entry point
|
||||||
|
called ``sphinx.html_themes`` in your setup.py file, and write a ``setup()``
|
||||||
|
function to register your themes using ``add_html_theme()`` API in it::
|
||||||
|
|
||||||
|
# 'setup.py'
|
||||||
|
setup(
|
||||||
|
...
|
||||||
|
entry_points = {
|
||||||
|
'sphinx.html_themes': [
|
||||||
|
'name_of_theme = your_package',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...
|
||||||
|
)
|
||||||
|
|
||||||
|
# 'your_package.py'
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.add_html_theme('name_of_theme', path.abspath(path.dirname(__file__)))
|
||||||
|
|
||||||
|
|
||||||
|
If your theme package contains two or more themes, please call ``add_html_theme()``
|
||||||
|
twice or more.
|
||||||
|
|
||||||
|
.. versionadded:: 1.2
|
||||||
|
'sphinx_themes' entry_points feature.
|
||||||
|
|
||||||
|
.. deprecated:: 1.6
|
||||||
|
``sphinx_themes`` entry_points has been deprecated.
|
||||||
|
|
||||||
|
.. versionadded:: 1.6
|
||||||
|
``sphinx.html_themes`` entry_points feature.
|
||||||
|
|
||||||
Templating
|
Templating
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ from __future__ import print_function
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import types
|
|
||||||
import warnings
|
import warnings
|
||||||
import posixpath
|
import posixpath
|
||||||
from os import path
|
from os import path
|
||||||
@ -24,24 +23,19 @@ from six import iteritems
|
|||||||
from six.moves import cStringIO
|
from six.moves import cStringIO
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.parsers.rst import convert_directive_function, \
|
from docutils.parsers.rst import directives, roles
|
||||||
directives, roles
|
|
||||||
from pkg_resources import iter_entry_points
|
|
||||||
|
|
||||||
import sphinx
|
import sphinx
|
||||||
from sphinx import package_dir, locale
|
from sphinx import package_dir, locale
|
||||||
from sphinx.config import Config
|
from sphinx.config import Config
|
||||||
from sphinx.errors import SphinxError, ExtensionError, VersionRequirementError, \
|
from sphinx.errors import ConfigError, ExtensionError, VersionRequirementError
|
||||||
ConfigError
|
|
||||||
from sphinx.domains import ObjType
|
|
||||||
from sphinx.domains.std import GenericObject, Target, StandardDomain
|
|
||||||
from sphinx.deprecation import RemovedInSphinx17Warning, RemovedInSphinx20Warning
|
from sphinx.deprecation import RemovedInSphinx17Warning, RemovedInSphinx20Warning
|
||||||
from sphinx.environment import BuildEnvironment
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.events import EventManager
|
from sphinx.events import EventManager
|
||||||
from sphinx.extension import load_extension, verify_required_extensions
|
from sphinx.extension import verify_required_extensions
|
||||||
from sphinx.io import SphinxStandaloneReader
|
from sphinx.io import SphinxStandaloneReader
|
||||||
from sphinx.locale import _
|
from sphinx.locale import _
|
||||||
from sphinx.roles import XRefRole
|
from sphinx.registry import SphinxComponentRegistry
|
||||||
from sphinx.util import pycompat # noqa: F401
|
from sphinx.util import pycompat # noqa: F401
|
||||||
from sphinx.util import import_object
|
from sphinx.util import import_object
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
@ -49,7 +43,7 @@ from sphinx.util import status_iterator, old_status_iterator, display_chunk
|
|||||||
from sphinx.util.tags import Tags
|
from sphinx.util.tags import Tags
|
||||||
from sphinx.util.osutil import ENOENT
|
from sphinx.util.osutil import ENOENT
|
||||||
from sphinx.util.console import bold, darkgreen # type: ignore
|
from sphinx.util.console import bold, darkgreen # type: ignore
|
||||||
from sphinx.util.docutils import is_html5_writer_available
|
from sphinx.util.docutils import is_html5_writer_available, directive_helper
|
||||||
from sphinx.util.i18n import find_catalog_source_files
|
from sphinx.util.i18n import find_catalog_source_files
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@ -121,12 +115,10 @@ class Sphinx(object):
|
|||||||
# type: (unicode, unicode, unicode, unicode, unicode, Dict, IO, IO, bool, bool, List[unicode], int, int) -> None # NOQA
|
# type: (unicode, unicode, unicode, unicode, unicode, Dict, IO, IO, bool, bool, List[unicode], int, int) -> None # NOQA
|
||||||
self.verbosity = verbosity
|
self.verbosity = verbosity
|
||||||
self.extensions = {} # type: Dict[unicode, Extension]
|
self.extensions = {} # type: Dict[unicode, Extension]
|
||||||
self._additional_source_parsers = {} # type: Dict[unicode, Parser]
|
|
||||||
self._setting_up_extension = ['?'] # type: List[unicode]
|
self._setting_up_extension = ['?'] # type: List[unicode]
|
||||||
self.domains = {} # type: Dict[unicode, Type[Domain]]
|
|
||||||
self.builderclasses = {} # type: Dict[unicode, Type[Builder]]
|
|
||||||
self.builder = None # type: Builder
|
self.builder = None # type: Builder
|
||||||
self.env = None # type: BuildEnvironment
|
self.env = None # type: BuildEnvironment
|
||||||
|
self.registry = SphinxComponentRegistry()
|
||||||
self.enumerable_nodes = {} # type: Dict[nodes.Node, Tuple[unicode, Callable]] # NOQA
|
self.enumerable_nodes = {} # type: Dict[nodes.Node, Tuple[unicode, Callable]] # NOQA
|
||||||
self.post_transforms = [] # type: List[Transform]
|
self.post_transforms = [] # type: List[Transform]
|
||||||
self.html_themes = {} # type: Dict[unicode, unicode]
|
self.html_themes = {} # type: Dict[unicode, unicode]
|
||||||
@ -154,7 +146,6 @@ class Sphinx(object):
|
|||||||
logging.setup(self, self._status, self._warning)
|
logging.setup(self, self._status, self._warning)
|
||||||
|
|
||||||
self.events = EventManager()
|
self.events = EventManager()
|
||||||
self._translators = {} # type: Dict[unicode, nodes.GenericNodeVisitor]
|
|
||||||
|
|
||||||
# keep last few messages for traceback
|
# keep last few messages for traceback
|
||||||
# This will be filled by sphinx.util.logging.LastMessagesWriter
|
# This will be filled by sphinx.util.logging.LastMessagesWriter
|
||||||
@ -226,9 +217,9 @@ class Sphinx(object):
|
|||||||
verify_required_extensions(self, self.config.needs_extensions)
|
verify_required_extensions(self, self.config.needs_extensions)
|
||||||
|
|
||||||
# check primary_domain if requested
|
# check primary_domain if requested
|
||||||
if self.config.primary_domain and self.config.primary_domain not in self.domains:
|
primary_domain = self.config.primary_domain
|
||||||
logger.warning(_('primary_domain %r not found, ignored.'),
|
if primary_domain and not self.registry.has_domain(primary_domain):
|
||||||
self.config.primary_domain)
|
logger.warning(_('primary_domain %r not found, ignored.'), primary_domain)
|
||||||
|
|
||||||
# create the builder
|
# create the builder
|
||||||
self.builder = self.create_builder(buildername)
|
self.builder = self.create_builder(buildername)
|
||||||
@ -271,28 +262,28 @@ class Sphinx(object):
|
|||||||
|
|
||||||
def _init_source_parsers(self):
|
def _init_source_parsers(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
for suffix, parser in iteritems(self._additional_source_parsers):
|
for suffix, parser in iteritems(self.config.source_parsers):
|
||||||
|
self.add_source_parser(suffix, parser)
|
||||||
|
for suffix, parser in iteritems(self.registry.get_source_parsers()):
|
||||||
if suffix not in self.config.source_suffix:
|
if suffix not in self.config.source_suffix:
|
||||||
self.config.source_suffix.append(suffix)
|
self.config.source_suffix.append(suffix)
|
||||||
if suffix not in self.config.source_parsers:
|
|
||||||
self.config.source_parsers[suffix] = parser
|
|
||||||
|
|
||||||
def _init_env(self, freshenv):
|
def _init_env(self, freshenv):
|
||||||
# type: (bool) -> None
|
# type: (bool) -> None
|
||||||
if freshenv:
|
if freshenv:
|
||||||
self.env = BuildEnvironment(self)
|
self.env = BuildEnvironment(self)
|
||||||
self.env.find_files(self.config, self.builder)
|
self.env.find_files(self.config, self.builder)
|
||||||
for domain in self.domains.keys():
|
for domain in self.registry.create_domains(self.env):
|
||||||
self.env.domains[domain] = self.domains[domain](self.env)
|
self.env.domains[domain.name] = domain
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
logger.info(bold(_('loading pickled environment... ')), nonl=True)
|
logger.info(bold(_('loading pickled environment... ')), nonl=True)
|
||||||
filename = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
|
filename = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
|
||||||
self.env = BuildEnvironment.frompickle(filename, self)
|
self.env = BuildEnvironment.frompickle(filename, self)
|
||||||
self.env.domains = {}
|
self.env.domains = {}
|
||||||
for domain in self.domains.keys():
|
for domain in self.registry.create_domains(self.env):
|
||||||
# this can raise if the data version doesn't fit
|
# this can raise if the data version doesn't fit
|
||||||
self.env.domains[domain] = self.domains[domain](self.env)
|
self.env.domains[domain.name] = domain
|
||||||
logger.info(_('done'))
|
logger.info(_('done'))
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
if isinstance(err, IOError) and err.errno == ENOENT:
|
if isinstance(err, IOError) and err.errno == ENOENT:
|
||||||
@ -301,28 +292,17 @@ class Sphinx(object):
|
|||||||
logger.info(_('failed: %s'), err)
|
logger.info(_('failed: %s'), err)
|
||||||
self._init_env(freshenv=True)
|
self._init_env(freshenv=True)
|
||||||
|
|
||||||
def preload_builder(self, buildername):
|
def preload_builder(self, name):
|
||||||
# type: (unicode) -> None
|
# type: (unicode) -> None
|
||||||
if buildername is None:
|
self.registry.preload_builder(self, name)
|
||||||
return
|
|
||||||
|
|
||||||
if buildername not in self.builderclasses:
|
def create_builder(self, name):
|
||||||
entry_points = iter_entry_points('sphinx.builders', buildername)
|
|
||||||
try:
|
|
||||||
entry_point = next(entry_points)
|
|
||||||
except StopIteration:
|
|
||||||
raise SphinxError(_('Builder name %s not registered or available'
|
|
||||||
' through entry point') % buildername)
|
|
||||||
load_extension(self, entry_point.module_name)
|
|
||||||
|
|
||||||
def create_builder(self, buildername):
|
|
||||||
# type: (unicode) -> Builder
|
# type: (unicode) -> Builder
|
||||||
if buildername is None:
|
if name is None:
|
||||||
buildername = 'html'
|
logger.info(_('No builder selected, using default: html'))
|
||||||
if buildername not in self.builderclasses:
|
name = 'html'
|
||||||
raise SphinxError(_('Builder name %s not registered') % buildername)
|
|
||||||
|
|
||||||
return self.builderclasses[buildername](self)
|
return self.registry.create_builder(self, name)
|
||||||
|
|
||||||
def _init_builder(self):
|
def _init_builder(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
@ -472,7 +452,7 @@ class Sphinx(object):
|
|||||||
# type: (unicode) -> None
|
# type: (unicode) -> None
|
||||||
"""Import and setup a Sphinx extension module. No-op if called twice."""
|
"""Import and setup a Sphinx extension module. No-op if called twice."""
|
||||||
logger.debug('[app] setting up extension: %r', extname)
|
logger.debug('[app] setting up extension: %r', extname)
|
||||||
load_extension(self, extname)
|
self.registry.load_extension(self, extname)
|
||||||
|
|
||||||
def require_sphinx(self, version):
|
def require_sphinx(self, version):
|
||||||
# type: (unicode) -> None
|
# type: (unicode) -> None
|
||||||
@ -516,13 +496,7 @@ class Sphinx(object):
|
|||||||
def add_builder(self, builder):
|
def add_builder(self, builder):
|
||||||
# type: (Type[Builder]) -> None
|
# type: (Type[Builder]) -> None
|
||||||
logger.debug('[app] adding builder: %r', builder)
|
logger.debug('[app] adding builder: %r', builder)
|
||||||
if not hasattr(builder, 'name'):
|
self.registry.add_builder(builder)
|
||||||
raise ExtensionError(_('Builder class %s has no "name" attribute')
|
|
||||||
% builder)
|
|
||||||
if builder.name in self.builderclasses:
|
|
||||||
raise ExtensionError(_('Builder %r already exists (in module %s)') %
|
|
||||||
(builder.name, self.builderclasses[builder.name].__module__))
|
|
||||||
self.builderclasses[builder.name] = builder
|
|
||||||
|
|
||||||
def add_config_value(self, name, default, rebuild, types=()):
|
def add_config_value(self, name, default, rebuild, types=()):
|
||||||
# type: (unicode, Any, Union[bool, unicode], Any) -> None
|
# type: (unicode, Any, Union[bool, unicode], Any) -> None
|
||||||
@ -540,9 +514,9 @@ class Sphinx(object):
|
|||||||
self.events.add(name)
|
self.events.add(name)
|
||||||
|
|
||||||
def set_translator(self, name, translator_class):
|
def set_translator(self, name, translator_class):
|
||||||
# type: (unicode, Any) -> None
|
# type: (unicode, Type[nodes.NodeVisitor]) -> None
|
||||||
logger.info(bold(_('A Translator for the %s builder is changed.') % name))
|
logger.info(bold(_('A Translator for the %s builder is changed.') % name))
|
||||||
self._translators[name] = translator_class
|
self.registry.add_translator(name, translator_class)
|
||||||
|
|
||||||
def add_node(self, node, **kwds):
|
def add_node(self, node, **kwds):
|
||||||
# type: (nodes.Node, Any) -> None
|
# type: (nodes.Node, Any) -> None
|
||||||
@ -560,7 +534,7 @@ class Sphinx(object):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
raise ExtensionError(_('Value for key %r must be a '
|
raise ExtensionError(_('Value for key %r must be a '
|
||||||
'(visit, depart) function tuple') % key)
|
'(visit, depart) function tuple') % key)
|
||||||
translator = self._translators.get(key)
|
translator = self.registry.translators.get(key)
|
||||||
translators = []
|
translators = []
|
||||||
if translator is not None:
|
if translator is not None:
|
||||||
translators.append(translator)
|
translators.append(translator)
|
||||||
@ -593,21 +567,15 @@ class Sphinx(object):
|
|||||||
self.enumerable_nodes[node] = (figtype, title_getter)
|
self.enumerable_nodes[node] = (figtype, title_getter)
|
||||||
self.add_node(node, **kwds)
|
self.add_node(node, **kwds)
|
||||||
|
|
||||||
def _directive_helper(self, obj, content=None, arguments=None, **options):
|
def _directive_helper(self, obj, has_content=None, argument_spec=None, **option_spec):
|
||||||
# type: (Any, unicode, Any, Any) -> Any
|
# type: (Any, bool, Tuple[int, int, bool], Any) -> Any
|
||||||
if isinstance(obj, (types.FunctionType, types.MethodType)):
|
warnings.warn('_directive_helper() is now deprecated. '
|
||||||
obj.content = content # type: ignore
|
'Please use sphinx.util.docutils.directive_helper() instead.',
|
||||||
obj.arguments = arguments or (0, 0, False) # type: ignore
|
RemovedInSphinx17Warning)
|
||||||
obj.options = options # type: ignore
|
return directive_helper(obj, has_content, argument_spec, **option_spec)
|
||||||
return convert_directive_function(obj)
|
|
||||||
else:
|
|
||||||
if content or arguments or options:
|
|
||||||
raise ExtensionError(_('when adding directive classes, no '
|
|
||||||
'additional arguments may be given'))
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def add_directive(self, name, obj, content=None, arguments=None, **options):
|
def add_directive(self, name, obj, content=None, arguments=None, **options):
|
||||||
# type: (unicode, Any, unicode, Any, Any) -> None
|
# type: (unicode, Any, bool, Tuple[int, int, bool], Any) -> None
|
||||||
logger.debug('[app] adding directive: %r',
|
logger.debug('[app] adding directive: %r',
|
||||||
(name, obj, content, arguments, options))
|
(name, obj, content, arguments, options))
|
||||||
if name in directives._directives:
|
if name in directives._directives:
|
||||||
@ -615,8 +583,8 @@ class Sphinx(object):
|
|||||||
'already registered, it will be overridden'),
|
'already registered, it will be overridden'),
|
||||||
self._setting_up_extension[-1], name,
|
self._setting_up_extension[-1], name,
|
||||||
type='app', subtype='add_directive')
|
type='app', subtype='add_directive')
|
||||||
directives.register_directive(
|
directive = directive_helper(obj, content, arguments, **options)
|
||||||
name, self._directive_helper(obj, content, arguments, **options))
|
directives.register_directive(name, directive)
|
||||||
|
|
||||||
def add_role(self, name, role):
|
def add_role(self, name, role):
|
||||||
# type: (unicode, Any) -> None
|
# type: (unicode, Any) -> None
|
||||||
@ -644,43 +612,30 @@ class Sphinx(object):
|
|||||||
def add_domain(self, domain):
|
def add_domain(self, domain):
|
||||||
# type: (Type[Domain]) -> None
|
# type: (Type[Domain]) -> None
|
||||||
logger.debug('[app] adding domain: %r', domain)
|
logger.debug('[app] adding domain: %r', domain)
|
||||||
if domain.name in self.domains:
|
self.registry.add_domain(domain)
|
||||||
raise ExtensionError(_('domain %s already registered') % domain.name)
|
|
||||||
self.domains[domain.name] = domain
|
|
||||||
|
|
||||||
def override_domain(self, domain):
|
def override_domain(self, domain):
|
||||||
# type: (Type[Domain]) -> None
|
# type: (Type[Domain]) -> None
|
||||||
logger.debug('[app] overriding domain: %r', domain)
|
logger.debug('[app] overriding domain: %r', domain)
|
||||||
if domain.name not in self.domains:
|
self.registry.override_domain(domain)
|
||||||
raise ExtensionError(_('domain %s not yet registered') % domain.name)
|
|
||||||
if not issubclass(domain, self.domains[domain.name]):
|
|
||||||
raise ExtensionError(_('new domain not a subclass of registered %s '
|
|
||||||
'domain') % domain.name)
|
|
||||||
self.domains[domain.name] = domain
|
|
||||||
|
|
||||||
def add_directive_to_domain(self, domain, name, obj,
|
def add_directive_to_domain(self, domain, name, obj,
|
||||||
content=None, arguments=None, **options):
|
has_content=None, argument_spec=None, **option_spec):
|
||||||
# type: (unicode, unicode, Any, unicode, Any, Any) -> None
|
# type: (unicode, unicode, Any, bool, Any, Any) -> None
|
||||||
logger.debug('[app] adding directive to domain: %r',
|
logger.debug('[app] adding directive to domain: %r',
|
||||||
(domain, name, obj, content, arguments, options))
|
(domain, name, obj, has_content, argument_spec, option_spec))
|
||||||
if domain not in self.domains:
|
self.registry.add_directive_to_domain(domain, name, obj,
|
||||||
raise ExtensionError(_('domain %s not yet registered') % domain)
|
has_content, argument_spec, **option_spec)
|
||||||
self.domains[domain].directives[name] = \
|
|
||||||
self._directive_helper(obj, content, arguments, **options)
|
|
||||||
|
|
||||||
def add_role_to_domain(self, domain, name, role):
|
def add_role_to_domain(self, domain, name, role):
|
||||||
# type: (unicode, unicode, Any) -> None
|
# type: (unicode, unicode, Any) -> None
|
||||||
logger.debug('[app] adding role to domain: %r', (domain, name, role))
|
logger.debug('[app] adding role to domain: %r', (domain, name, role))
|
||||||
if domain not in self.domains:
|
self.registry.add_role_to_domain(domain, name, role)
|
||||||
raise ExtensionError(_('domain %s not yet registered') % domain)
|
|
||||||
self.domains[domain].roles[name] = role
|
|
||||||
|
|
||||||
def add_index_to_domain(self, domain, index):
|
def add_index_to_domain(self, domain, index):
|
||||||
# type: (unicode, Type[Index]) -> None
|
# type: (unicode, Type[Index]) -> None
|
||||||
logger.debug('[app] adding index to domain: %r', (domain, index))
|
logger.debug('[app] adding index to domain: %r', (domain, index))
|
||||||
if domain not in self.domains:
|
self.registry.add_index_to_domain(domain, index)
|
||||||
raise ExtensionError(_('domain %s not yet registered') % domain)
|
|
||||||
self.domains[domain].indices.append(index)
|
|
||||||
|
|
||||||
def add_object_type(self, directivename, rolename, indextemplate='',
|
def add_object_type(self, directivename, rolename, indextemplate='',
|
||||||
parse_node=None, ref_nodeclass=None, objname='',
|
parse_node=None, ref_nodeclass=None, objname='',
|
||||||
@ -689,19 +644,18 @@ class Sphinx(object):
|
|||||||
logger.debug('[app] adding object type: %r',
|
logger.debug('[app] adding object type: %r',
|
||||||
(directivename, rolename, indextemplate, parse_node,
|
(directivename, rolename, indextemplate, parse_node,
|
||||||
ref_nodeclass, objname, doc_field_types))
|
ref_nodeclass, objname, doc_field_types))
|
||||||
StandardDomain.object_types[directivename] = \
|
self.registry.add_object_type(directivename, rolename, indextemplate, parse_node,
|
||||||
ObjType(objname or directivename, rolename)
|
ref_nodeclass, objname, doc_field_types)
|
||||||
# create a subclass of GenericObject as the new directive
|
|
||||||
new_directive = type(directivename, (GenericObject, object), # type: ignore
|
|
||||||
{'indextemplate': indextemplate,
|
|
||||||
'parse_node': staticmethod(parse_node), # type: ignore
|
|
||||||
'doc_field_types': doc_field_types})
|
|
||||||
StandardDomain.directives[directivename] = new_directive
|
|
||||||
# XXX support more options?
|
|
||||||
StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
|
|
||||||
|
|
||||||
# backwards compatible alias
|
def add_description_unit(self, directivename, rolename, indextemplate='',
|
||||||
add_description_unit = add_object_type
|
parse_node=None, ref_nodeclass=None, objname='',
|
||||||
|
doc_field_types=[]):
|
||||||
|
# type: (unicode, unicode, unicode, Callable, nodes.Node, unicode, List) -> None
|
||||||
|
warnings.warn('app.add_description_unit() is now deprecated. '
|
||||||
|
'Use app.add_object_type() instead.',
|
||||||
|
RemovedInSphinx20Warning)
|
||||||
|
self.add_object_type(directivename, rolename, indextemplate, parse_node,
|
||||||
|
ref_nodeclass, objname, doc_field_types)
|
||||||
|
|
||||||
def add_crossref_type(self, directivename, rolename, indextemplate='',
|
def add_crossref_type(self, directivename, rolename, indextemplate='',
|
||||||
ref_nodeclass=None, objname=''):
|
ref_nodeclass=None, objname=''):
|
||||||
@ -709,14 +663,8 @@ class Sphinx(object):
|
|||||||
logger.debug('[app] adding crossref type: %r',
|
logger.debug('[app] adding crossref type: %r',
|
||||||
(directivename, rolename, indextemplate, ref_nodeclass,
|
(directivename, rolename, indextemplate, ref_nodeclass,
|
||||||
objname))
|
objname))
|
||||||
StandardDomain.object_types[directivename] = \
|
self.registry.add_crossref_type(directivename, rolename,
|
||||||
ObjType(objname or directivename, rolename)
|
indextemplate, ref_nodeclass, objname)
|
||||||
# create a subclass of Target as the new directive
|
|
||||||
new_directive = type(directivename, (Target, object), # type: ignore
|
|
||||||
{'indextemplate': indextemplate})
|
|
||||||
StandardDomain.directives[directivename] = new_directive
|
|
||||||
# XXX support more options?
|
|
||||||
StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
|
|
||||||
|
|
||||||
def add_transform(self, transform):
|
def add_transform(self, transform):
|
||||||
# type: (Type[Transform]) -> None
|
# type: (Type[Transform]) -> None
|
||||||
@ -788,18 +736,18 @@ class Sphinx(object):
|
|||||||
def add_source_parser(self, suffix, parser):
|
def add_source_parser(self, suffix, parser):
|
||||||
# type: (unicode, Parser) -> None
|
# type: (unicode, Parser) -> None
|
||||||
logger.debug('[app] adding search source_parser: %r, %r', suffix, parser)
|
logger.debug('[app] adding search source_parser: %r, %r', suffix, parser)
|
||||||
if suffix in self._additional_source_parsers:
|
self.registry.add_source_parser(suffix, parser)
|
||||||
logger.warning(_('while setting up extension %s: source_parser for %r is '
|
|
||||||
'already registered, it will be overridden'),
|
|
||||||
self._setting_up_extension[-1], suffix,
|
|
||||||
type='app', subtype='add_source_parser')
|
|
||||||
self._additional_source_parsers[suffix] = parser
|
|
||||||
|
|
||||||
def add_env_collector(self, collector):
|
def add_env_collector(self, collector):
|
||||||
# type: (Type[EnvironmentCollector]) -> None
|
# type: (Type[EnvironmentCollector]) -> None
|
||||||
logger.debug('[app] adding environment collector: %r', collector)
|
logger.debug('[app] adding environment collector: %r', collector)
|
||||||
collector().enable(self)
|
collector().enable(self)
|
||||||
|
|
||||||
|
def add_html_theme(self, name, theme_path):
|
||||||
|
# type: (unicode, unicode) -> None
|
||||||
|
logger.debug('[app] adding HTML theme: %r, %r', name, theme_path)
|
||||||
|
self.html_themes[name] = theme_path
|
||||||
|
|
||||||
|
|
||||||
class TemplateBridge(object):
|
class TemplateBridge(object):
|
||||||
"""
|
"""
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
from os import path
|
from os import path
|
||||||
|
import warnings
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
@ -20,6 +21,7 @@ except ImportError:
|
|||||||
from six import itervalues
|
from six import itervalues
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
|
||||||
|
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||||
from sphinx.util import i18n, path_stabilize, logging, status_iterator
|
from sphinx.util import i18n, path_stabilize, logging, status_iterator
|
||||||
from sphinx.util.osutil import SEP, relative_uri
|
from sphinx.util.osutil import SEP, relative_uri
|
||||||
from sphinx.util.i18n import find_catalog
|
from sphinx.util.i18n import find_catalog
|
||||||
@ -53,6 +55,9 @@ class Builder(object):
|
|||||||
name = '' # type: unicode
|
name = '' # type: unicode
|
||||||
#: The builder's output format, or '' if no document output is produced.
|
#: The builder's output format, or '' if no document output is produced.
|
||||||
format = '' # type: unicode
|
format = '' # type: unicode
|
||||||
|
# default translator class for the builder. This will be overrided by
|
||||||
|
# ``app.set_translator()``.
|
||||||
|
default_translator_class = None # type: nodes.NodeVisitor
|
||||||
# doctree versioning method
|
# doctree versioning method
|
||||||
versioning_method = 'none' # type: unicode
|
versioning_method = 'none' # type: unicode
|
||||||
versioning_compare = False
|
versioning_compare = False
|
||||||
@ -101,9 +106,6 @@ class Builder(object):
|
|||||||
self.parallel_ok = False
|
self.parallel_ok = False
|
||||||
self.finish_tasks = None # type: Any
|
self.finish_tasks = None # type: Any
|
||||||
|
|
||||||
# load default translator class
|
|
||||||
self.translator_class = app._translators.get(self.name)
|
|
||||||
|
|
||||||
def set_environment(self, env):
|
def set_environment(self, env):
|
||||||
# type: (BuildEnvironment) -> None
|
# type: (BuildEnvironment) -> None
|
||||||
"""Store BuildEnvironment object."""
|
"""Store BuildEnvironment object."""
|
||||||
@ -111,6 +113,38 @@ class Builder(object):
|
|||||||
self.env.set_versioning_method(self.versioning_method,
|
self.env.set_versioning_method(self.versioning_method,
|
||||||
self.versioning_compare)
|
self.versioning_compare)
|
||||||
|
|
||||||
|
def get_translator_class(self, *args):
|
||||||
|
# type: (Any) -> nodes.NodeVisitor
|
||||||
|
"""Return a class of translator."""
|
||||||
|
return self.app.registry.get_translator_class(self)
|
||||||
|
|
||||||
|
def create_translator(self, *args):
|
||||||
|
# type: (Any) -> nodes.NodeVisitor
|
||||||
|
"""Return an instance of translator.
|
||||||
|
|
||||||
|
This method returns an instance of ``default_translator_class`` by default.
|
||||||
|
Users can replace the translator class with ``app.set_translator()`` API.
|
||||||
|
"""
|
||||||
|
translator_class = self.app.registry.get_translator_class(self)
|
||||||
|
assert translator_class, "translator not found for %s" % self.__class__.__name__
|
||||||
|
return translator_class(*args)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def translator_class(self):
|
||||||
|
# type: () -> Callable[[Any], nodes.NodeVisitor]
|
||||||
|
"""Return a class of translator.
|
||||||
|
|
||||||
|
.. deprecated:: 1.6
|
||||||
|
"""
|
||||||
|
translator_class = self.app.registry.get_translator_class(self)
|
||||||
|
if translator_class is None and self.default_translator_class is None:
|
||||||
|
warnings.warn('builder.translator_class() is now deprecated. '
|
||||||
|
'Please use builder.create_translator() and '
|
||||||
|
'builder.default_translator_class instead.',
|
||||||
|
RemovedInSphinx20Warning)
|
||||||
|
return None
|
||||||
|
return self.create_translator
|
||||||
|
|
||||||
# helper methods
|
# helper methods
|
||||||
def init(self):
|
def init(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
@ -158,7 +158,6 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
|
|
||||||
self.init_templates()
|
self.init_templates()
|
||||||
self.init_highlighter()
|
self.init_highlighter()
|
||||||
self.init_translator_class()
|
|
||||||
if self.config.html_file_suffix is not None:
|
if self.config.html_file_suffix is not None:
|
||||||
self.out_suffix = self.config.html_file_suffix
|
self.out_suffix = self.config.html_file_suffix
|
||||||
|
|
||||||
@ -218,23 +217,18 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
self.highlighter = PygmentsBridge('html', style,
|
self.highlighter = PygmentsBridge('html', style,
|
||||||
self.config.trim_doctest_flags)
|
self.config.trim_doctest_flags)
|
||||||
|
|
||||||
def init_translator_class(self):
|
@property
|
||||||
# type: () -> None
|
def default_translator_class(self):
|
||||||
if self.translator_class is None:
|
if self.config.html_experimental_html5_writer and html5_ready:
|
||||||
use_html5_writer = self.config.html_experimental_html5_writer
|
|
||||||
if use_html5_writer is None:
|
|
||||||
use_html5_writer = self.default_html5_translator and html5_ready
|
|
||||||
|
|
||||||
if use_html5_writer and html5_ready:
|
|
||||||
if self.config.html_use_smartypants:
|
if self.config.html_use_smartypants:
|
||||||
self.translator_class = SmartyPantsHTML5Translator
|
return SmartyPantsHTML5Translator
|
||||||
else:
|
else:
|
||||||
self.translator_class = HTML5Translator
|
return HTML5Translator
|
||||||
else:
|
else:
|
||||||
if self.config.html_use_smartypants:
|
if self.config.html_use_smartypants:
|
||||||
self.translator_class = SmartyPantsHTMLTranslator
|
return SmartyPantsHTMLTranslator
|
||||||
else:
|
else:
|
||||||
self.translator_class = HTMLTranslator
|
return HTMLTranslator
|
||||||
|
|
||||||
def get_outdated_docs(self):
|
def get_outdated_docs(self):
|
||||||
# type: () -> Iterator[unicode]
|
# type: () -> Iterator[unicode]
|
||||||
@ -1200,7 +1194,6 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
|
|||||||
self.current_docname = None
|
self.current_docname = None
|
||||||
self.theme = None # no theme necessary
|
self.theme = None # no theme necessary
|
||||||
self.templates = None # no template bridge necessary
|
self.templates = None # no template bridge necessary
|
||||||
self.init_translator_class()
|
|
||||||
self.init_templates()
|
self.init_templates()
|
||||||
self.init_highlighter()
|
self.init_highlighter()
|
||||||
self.use_index = self.get_builder_config('use_index', 'html')
|
self.use_index = self.get_builder_config('use_index', 'html')
|
||||||
|
@ -31,7 +31,7 @@ from sphinx.util.nodes import inline_all_toctrees
|
|||||||
from sphinx.util.fileutil import copy_asset_file
|
from sphinx.util.fileutil import copy_asset_file
|
||||||
from sphinx.util.osutil import SEP, make_filename
|
from sphinx.util.osutil import SEP, make_filename
|
||||||
from sphinx.util.console import bold, darkgreen # type: ignore
|
from sphinx.util.console import bold, darkgreen # type: ignore
|
||||||
from sphinx.writers.latex import LaTeXWriter
|
from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@ -51,6 +51,7 @@ class LaTeXBuilder(Builder):
|
|||||||
format = 'latex'
|
format = 'latex'
|
||||||
supported_image_types = ['application/pdf', 'image/png', 'image/jpeg']
|
supported_image_types = ['application/pdf', 'image/png', 'image/jpeg']
|
||||||
supported_remote_images = False
|
supported_remote_images = False
|
||||||
|
default_translator_class = LaTeXTranslator
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
@ -23,7 +23,7 @@ from sphinx.util import logging
|
|||||||
from sphinx.util.nodes import inline_all_toctrees
|
from sphinx.util.nodes import inline_all_toctrees
|
||||||
from sphinx.util.osutil import make_filename
|
from sphinx.util.osutil import make_filename
|
||||||
from sphinx.util.console import bold, darkgreen # type: ignore
|
from sphinx.util.console import bold, darkgreen # type: ignore
|
||||||
from sphinx.writers.manpage import ManualPageWriter
|
from sphinx.writers.manpage import ManualPageWriter, ManualPageTranslator
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@ -40,6 +40,7 @@ class ManualPageBuilder(Builder):
|
|||||||
"""
|
"""
|
||||||
name = 'man'
|
name = 'man'
|
||||||
format = 'man'
|
format = 'man'
|
||||||
|
default_translator_class = ManualPageTranslator
|
||||||
supported_image_types = [] # type: List[unicode]
|
supported_image_types = [] # type: List[unicode]
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
|
@ -27,7 +27,7 @@ from sphinx.util.fileutil import copy_asset_file
|
|||||||
from sphinx.util.nodes import inline_all_toctrees
|
from sphinx.util.nodes import inline_all_toctrees
|
||||||
from sphinx.util.osutil import SEP, make_filename
|
from sphinx.util.osutil import SEP, make_filename
|
||||||
from sphinx.util.console import bold, darkgreen # type: ignore
|
from sphinx.util.console import bold, darkgreen # type: ignore
|
||||||
from sphinx.writers.texinfo import TexinfoWriter
|
from sphinx.writers.texinfo import TexinfoWriter, TexinfoTranslator
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@ -99,6 +99,7 @@ class TexinfoBuilder(Builder):
|
|||||||
format = 'texinfo'
|
format = 'texinfo'
|
||||||
supported_image_types = ['image/png', 'image/jpeg',
|
supported_image_types = ['image/png', 'image/jpeg',
|
||||||
'image/gif']
|
'image/gif']
|
||||||
|
default_translator_class = TexinfoTranslator
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
@ -17,7 +17,7 @@ from docutils.io import StringOutput
|
|||||||
from sphinx.builders import Builder
|
from sphinx.builders import Builder
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.osutil import ensuredir, os_path
|
from sphinx.util.osutil import ensuredir, os_path
|
||||||
from sphinx.writers.text import TextWriter
|
from sphinx.writers.text import TextWriter, TextTranslator
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@ -33,6 +33,7 @@ class TextBuilder(Builder):
|
|||||||
format = 'text'
|
format = 'text'
|
||||||
out_suffix = '.txt'
|
out_suffix = '.txt'
|
||||||
allow_parallel = True
|
allow_parallel = True
|
||||||
|
default_translator_class = TextTranslator
|
||||||
|
|
||||||
current_docname = None # type: unicode
|
current_docname = None # type: unicode
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ from os import path
|
|||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.io import StringOutput
|
from docutils.io import StringOutput
|
||||||
|
from docutils.writers.docutils_xml import XMLTranslator
|
||||||
|
|
||||||
from sphinx.builders import Builder
|
from sphinx.builders import Builder
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
@ -38,6 +39,7 @@ class XMLBuilder(Builder):
|
|||||||
allow_parallel = True
|
allow_parallel = True
|
||||||
|
|
||||||
_writer_class = XMLWriter
|
_writer_class = XMLWriter
|
||||||
|
default_translator_class = XMLTranslator
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
@ -308,3 +308,8 @@ class Domain(object):
|
|||||||
if primary:
|
if primary:
|
||||||
return type.lname
|
return type.lname
|
||||||
return _('%s %s') % (self.label, type.lname)
|
return _('%s %s') % (self.label, type.lname)
|
||||||
|
|
||||||
|
def get_full_qualified_name(self, node):
|
||||||
|
# type: (nodes.Node) -> unicode
|
||||||
|
"""Return full qualified name for given node."""
|
||||||
|
return None
|
||||||
|
@ -5032,6 +5032,20 @@ class CPPDomain(Domain):
|
|||||||
newestId = symbol.declaration.get_newest_id()
|
newestId = symbol.declaration.get_newest_id()
|
||||||
yield (name, name, objectType, docname, newestId, 1)
|
yield (name, name, objectType, docname, newestId, 1)
|
||||||
|
|
||||||
|
def get_full_qualified_name(self, node):
|
||||||
|
# type: (nodes.Node) -> unicode
|
||||||
|
target = node.get('reftarget', None)
|
||||||
|
if target is None:
|
||||||
|
return None
|
||||||
|
parentKey = node.get("cpp:parent_key", None)
|
||||||
|
if parentKey is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
rootSymbol = self.data['root_symbol']
|
||||||
|
parentSymbol = rootSymbol.direct_lookup(parentKey)
|
||||||
|
parentName = parentSymbol.get_full_nested_name()
|
||||||
|
return '::'.join([text_type(parentName), target])
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[unicode, Any]
|
# type: (Sphinx) -> Dict[unicode, Any]
|
||||||
|
@ -398,6 +398,16 @@ class JavaScriptDomain(Domain):
|
|||||||
yield refname, refname, type, docname, \
|
yield refname, refname, type, docname, \
|
||||||
refname.replace('$', '_S_'), 1
|
refname.replace('$', '_S_'), 1
|
||||||
|
|
||||||
|
def get_full_qualified_name(self, node):
|
||||||
|
# type: (nodes.Node) -> unicode
|
||||||
|
modname = node.get('js:module')
|
||||||
|
prefix = node.get('js:object')
|
||||||
|
target = node.get('reftarget')
|
||||||
|
if target is None:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return '.'.join(filter(None, [modname, prefix, target]))
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[unicode, Any]
|
# type: (Sphinx) -> Dict[unicode, Any]
|
||||||
|
@ -885,6 +885,16 @@ class PythonDomain(Domain):
|
|||||||
if type != 'module': # modules are already handled
|
if type != 'module': # modules are already handled
|
||||||
yield (refname, refname, type, docname, refname, 1)
|
yield (refname, refname, type, docname, refname, 1)
|
||||||
|
|
||||||
|
def get_full_qualified_name(self, node):
|
||||||
|
# type: (nodes.Node) -> unicode
|
||||||
|
modname = node.get('py:module')
|
||||||
|
clsname = node.get('py:class')
|
||||||
|
target = node.get('reftarget')
|
||||||
|
if target is None:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return '.'.join(filter(None, [modname, clsname, target]))
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[unicode, Any]
|
# type: (Sphinx) -> Dict[unicode, Any]
|
||||||
|
@ -849,6 +849,10 @@ class StandardDomain(Domain):
|
|||||||
for doc in self.env.all_docs:
|
for doc in self.env.all_docs:
|
||||||
yield (doc, clean_astext(self.env.titles[doc]), 'doc', doc, '', -1)
|
yield (doc, clean_astext(self.env.titles[doc]), 'doc', doc, '', -1)
|
||||||
for (prog, option), info in iteritems(self.data['progoptions']):
|
for (prog, option), info in iteritems(self.data['progoptions']):
|
||||||
|
if prog:
|
||||||
|
fullname = ".".join([prog, option])
|
||||||
|
yield (fullname, fullname, 'cmdoption', info[0], info[1], 1)
|
||||||
|
else:
|
||||||
yield (option, option, 'cmdoption', info[0], info[1], 1)
|
yield (option, option, 'cmdoption', info[0], info[1], 1)
|
||||||
for (type, name), info in iteritems(self.data['objects']):
|
for (type, name), info in iteritems(self.data['objects']):
|
||||||
yield (name, name, type, info[0], info[1],
|
yield (name, name, type, info[0], info[1],
|
||||||
@ -925,6 +929,15 @@ class StandardDomain(Domain):
|
|||||||
# Maybe it is defined in orphaned document.
|
# Maybe it is defined in orphaned document.
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
def get_full_qualified_name(self, node):
|
||||||
|
# type: (nodes.Node) -> unicode
|
||||||
|
progname = node.get('std:program')
|
||||||
|
target = node.get('reftarget')
|
||||||
|
if progname is None or target is None:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return '.'.join([progname, target])
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[unicode, Any]
|
# type: (Sphinx) -> Dict[unicode, Any]
|
||||||
|
@ -691,7 +691,8 @@ class BuildEnvironment(object):
|
|||||||
codecs.register_error('sphinx', self.warn_and_replace) # type: ignore
|
codecs.register_error('sphinx', self.warn_and_replace) # type: ignore
|
||||||
|
|
||||||
# publish manually
|
# publish manually
|
||||||
reader = SphinxStandaloneReader(self.app, parsers=self.config.source_parsers)
|
reader = SphinxStandaloneReader(self.app,
|
||||||
|
parsers=self.app.registry.get_source_parsers())
|
||||||
pub = Publisher(reader=reader,
|
pub = Publisher(reader=reader,
|
||||||
writer=SphinxDummyWriter(),
|
writer=SphinxDummyWriter(),
|
||||||
destination_class=NullOutput)
|
destination_class=NullOutput)
|
||||||
|
@ -573,7 +573,7 @@ def get_rst_suffix(app):
|
|||||||
# type: (Sphinx) -> unicode
|
# type: (Sphinx) -> unicode
|
||||||
def get_supported_format(suffix):
|
def get_supported_format(suffix):
|
||||||
# type: (unicode) -> Tuple[unicode]
|
# type: (unicode) -> Tuple[unicode]
|
||||||
parser_class = app.config.source_parsers.get(suffix)
|
parser_class = app.registry.get_source_parsers().get(suffix)
|
||||||
if parser_class is None:
|
if parser_class is None:
|
||||||
return ('restructuredtext',)
|
return ('restructuredtext',)
|
||||||
if isinstance(parser_class, string_types):
|
if isinstance(parser_class, string_types):
|
||||||
|
93
sphinx/ext/imgconverter.py
Normal file
93
sphinx/ext/imgconverter.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
sphinx.ext.imgconverter
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Image converter extension for Sphinx
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from sphinx.errors import ExtensionError
|
||||||
|
from sphinx.locale import _
|
||||||
|
from sphinx.transforms.post_transforms.images import ImageConverter
|
||||||
|
from sphinx.util import logging
|
||||||
|
from sphinx.util.osutil import ENOENT, EPIPE, EINVAL
|
||||||
|
|
||||||
|
if False:
|
||||||
|
# For type annotation
|
||||||
|
from typing import Any, Dict # NOQA
|
||||||
|
from sphinx.application import Sphinx # NOQA
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ImagemagickConverter(ImageConverter):
|
||||||
|
conversion_rules = [
|
||||||
|
('image/svg+xml', 'image/png'),
|
||||||
|
('application/pdf', 'image/png'),
|
||||||
|
]
|
||||||
|
|
||||||
|
def is_available(self):
|
||||||
|
# type: () -> bool
|
||||||
|
"""Confirms the converter is available or not."""
|
||||||
|
try:
|
||||||
|
args = [self.config.image_converter, '-version']
|
||||||
|
logger.debug('Invoking %r ...', args)
|
||||||
|
ret = subprocess.call(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
|
if ret == 0:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
except (OSError, IOError):
|
||||||
|
logger.warning(_('convert command %r cannot be run.'
|
||||||
|
'check the image_converter setting'),
|
||||||
|
self.config.image_converter)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def convert(self, _from, _to):
|
||||||
|
# type: (unicode, unicode) -> bool
|
||||||
|
"""Converts the image to expected one."""
|
||||||
|
try:
|
||||||
|
args = ([self.config.image_converter] +
|
||||||
|
self.config.image_converter_args +
|
||||||
|
[_from, _to])
|
||||||
|
logger.debug('Invoking %r ...', args)
|
||||||
|
p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
|
except OSError as err:
|
||||||
|
if err.errno != ENOENT: # No such file or directory
|
||||||
|
raise
|
||||||
|
logger.warning(_('convert command %r cannot be run.'
|
||||||
|
'check the image_converter setting'),
|
||||||
|
self.config.image_converter)
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
stdout, stderr = p.communicate()
|
||||||
|
except (OSError, IOError) as err:
|
||||||
|
if err.errno not in (EPIPE, EINVAL):
|
||||||
|
raise
|
||||||
|
stdout, stderr = p.stdout.read(), p.stderr.read()
|
||||||
|
p.wait()
|
||||||
|
if p.returncode != 0:
|
||||||
|
raise ExtensionError(_('convert exited with error:\n'
|
||||||
|
'[stderr]\n%s\n[stdout]\n%s') %
|
||||||
|
(stderr, stdout))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
# type: (Sphinx) -> Dict[unicode, Any]
|
||||||
|
app.add_post_transform(ImagemagickConverter)
|
||||||
|
app.add_config_value('image_converter', 'convert', 'env')
|
||||||
|
app.add_config_value('image_converter_args', [], 'env')
|
||||||
|
|
||||||
|
return {
|
||||||
|
'version': 'builtin',
|
||||||
|
'parallel_read_safe': True,
|
||||||
|
'parallel_write_safe': True,
|
||||||
|
}
|
@ -292,6 +292,10 @@ def missing_reference(app, env, node, contnode):
|
|||||||
# until Sphinx-1.6, cmdoptions are stored as std:option
|
# until Sphinx-1.6, cmdoptions are stored as std:option
|
||||||
objtypes.append('std:option')
|
objtypes.append('std:option')
|
||||||
to_try = [(inventories.main_inventory, target)]
|
to_try = [(inventories.main_inventory, target)]
|
||||||
|
if domain:
|
||||||
|
full_qualified_name = env.get_domain(domain).get_full_qualified_name(node)
|
||||||
|
if full_qualified_name:
|
||||||
|
to_try.append((inventories.main_inventory, full_qualified_name))
|
||||||
in_set = None
|
in_set = None
|
||||||
if ':' in target:
|
if ':' in target:
|
||||||
# first part may be the foreign doc set name
|
# first part may be the foreign doc set name
|
||||||
@ -299,6 +303,10 @@ def missing_reference(app, env, node, contnode):
|
|||||||
if setname in inventories.named_inventory:
|
if setname in inventories.named_inventory:
|
||||||
in_set = setname
|
in_set = setname
|
||||||
to_try.append((inventories.named_inventory[setname], newtarget))
|
to_try.append((inventories.named_inventory[setname], newtarget))
|
||||||
|
if domain:
|
||||||
|
full_qualified_name = env.get_domain(domain).get_full_qualified_name(node)
|
||||||
|
if full_qualified_name:
|
||||||
|
to_try.append((inventories.named_inventory[setname], full_qualified_name))
|
||||||
for inventory, target in to_try:
|
for inventory, target in to_try:
|
||||||
for objtype in objtypes:
|
for objtype in objtypes:
|
||||||
if objtype not in inventory or target not in inventory[objtype]:
|
if objtype not in inventory or target not in inventory[objtype]:
|
||||||
|
@ -9,30 +9,20 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
from six import iteritems
|
from six import iteritems
|
||||||
|
|
||||||
from sphinx.errors import ExtensionError, VersionRequirementError
|
from sphinx.errors import VersionRequirementError
|
||||||
from sphinx.locale import _
|
from sphinx.locale import _
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Dict # NOQA
|
from typing import Dict # NOQA
|
||||||
from sphinx.application import Sphinx # NOQA
|
from sphinx.application import Sphinx # NOQA
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# list of deprecated extensions. Keys are extension name.
|
|
||||||
# Values are Sphinx version that merge the extension.
|
|
||||||
EXTENSION_BLACKLIST = {
|
|
||||||
"sphinxjp.themecore": "1.2"
|
|
||||||
} # type: Dict[unicode, unicode]
|
|
||||||
|
|
||||||
|
|
||||||
class Extension(object):
|
class Extension(object):
|
||||||
def __init__(self, name, module, **kwargs):
|
def __init__(self, name, module, **kwargs):
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -51,54 +41,6 @@ class Extension(object):
|
|||||||
self.parallel_write_safe = kwargs.pop('parallel_read_safe', True)
|
self.parallel_write_safe = kwargs.pop('parallel_read_safe', True)
|
||||||
|
|
||||||
|
|
||||||
def load_extension(app, extname):
|
|
||||||
# type: (Sphinx, unicode) -> None
|
|
||||||
"""Load a Sphinx extension."""
|
|
||||||
if extname in app.extensions: # alread loaded
|
|
||||||
return
|
|
||||||
if extname in EXTENSION_BLACKLIST:
|
|
||||||
logger.warning(_('the extension %r was already merged with Sphinx since '
|
|
||||||
'version %s; this extension is ignored.'),
|
|
||||||
extname, EXTENSION_BLACKLIST[extname])
|
|
||||||
return
|
|
||||||
|
|
||||||
# update loading context
|
|
||||||
app._setting_up_extension.append(extname)
|
|
||||||
|
|
||||||
try:
|
|
||||||
mod = __import__(extname, None, None, ['setup'])
|
|
||||||
except ImportError as err:
|
|
||||||
logger.verbose(_('Original exception:\n') + traceback.format_exc())
|
|
||||||
raise ExtensionError(_('Could not import extension %s') % extname, err)
|
|
||||||
|
|
||||||
if not hasattr(mod, 'setup'):
|
|
||||||
logger.warning(_('extension %r has no setup() function; is it really '
|
|
||||||
'a Sphinx extension module?'), extname)
|
|
||||||
metadata = {} # type: Dict[unicode, Any]
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
metadata = mod.setup(app)
|
|
||||||
except VersionRequirementError as err:
|
|
||||||
# add the extension name to the version required
|
|
||||||
raise VersionRequirementError(
|
|
||||||
_('The %s extension used by this project needs at least '
|
|
||||||
'Sphinx v%s; it therefore cannot be built with this '
|
|
||||||
'version.') % (extname, err)
|
|
||||||
)
|
|
||||||
|
|
||||||
if metadata is None:
|
|
||||||
metadata = {}
|
|
||||||
if extname == 'rst2pdf.pdfbuilder':
|
|
||||||
metadata['parallel_read_safe'] = True
|
|
||||||
elif not isinstance(metadata, dict):
|
|
||||||
logger.warning(_('extension %r returned an unsupported object from '
|
|
||||||
'its setup() function; it should return None or a '
|
|
||||||
'metadata dictionary'), extname)
|
|
||||||
|
|
||||||
app.extensions[extname] = Extension(extname, mod, **metadata)
|
|
||||||
app._setting_up_extension.pop()
|
|
||||||
|
|
||||||
|
|
||||||
def verify_required_extensions(app, requirements):
|
def verify_required_extensions(app, requirements):
|
||||||
# type: (Sphinx, Dict[unicode, unicode]) -> None
|
# type: (Sphinx, Dict[unicode, unicode]) -> None
|
||||||
"""Verify the required Sphinx extensions are loaded."""
|
"""Verify the required Sphinx extensions are loaded."""
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
from docutils.io import FileInput
|
from docutils.io import FileInput
|
||||||
from docutils.readers import standalone
|
from docutils.readers import standalone
|
||||||
from docutils.writers import UnfilteredWriter
|
from docutils.writers import UnfilteredWriter
|
||||||
from six import string_types, text_type
|
from six import string_types, text_type, iteritems
|
||||||
from typing import Any, Union # NOQA
|
from typing import Any, Union # NOQA
|
||||||
|
|
||||||
from sphinx.transforms import (
|
from sphinx.transforms import (
|
||||||
@ -158,9 +158,8 @@ class SphinxFileInput(FileInput):
|
|||||||
# type: () -> unicode
|
# type: () -> unicode
|
||||||
def get_parser_type(source_path):
|
def get_parser_type(source_path):
|
||||||
# type: (unicode) -> Tuple[unicode]
|
# type: (unicode) -> Tuple[unicode]
|
||||||
for suffix in self.env.config.source_parsers:
|
for suffix, parser_class in iteritems(self.app.registry.get_source_parsers()):
|
||||||
if source_path.endswith(suffix):
|
if source_path.endswith(suffix):
|
||||||
parser_class = self.env.config.source_parsers[suffix]
|
|
||||||
if isinstance(parser_class, string_types):
|
if isinstance(parser_class, string_types):
|
||||||
parser_class = import_object(parser_class, 'source parser') # type: ignore # NOQA
|
parser_class = import_object(parser_class, 'source parser') # type: ignore # NOQA
|
||||||
return parser_class.supported
|
return parser_class.supported
|
||||||
|
226
sphinx/registry.py
Normal file
226
sphinx/registry.py
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
sphinx.registry
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Sphinx component registry.
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from pkg_resources import iter_entry_points
|
||||||
|
from six import itervalues
|
||||||
|
|
||||||
|
from sphinx.errors import ExtensionError, SphinxError, VersionRequirementError
|
||||||
|
from sphinx.extension import Extension
|
||||||
|
from sphinx.domains import ObjType
|
||||||
|
from sphinx.domains.std import GenericObject, Target
|
||||||
|
from sphinx.locale import _
|
||||||
|
from sphinx.roles import XRefRole
|
||||||
|
from sphinx.util import logging
|
||||||
|
from sphinx.util.docutils import directive_helper
|
||||||
|
|
||||||
|
if False:
|
||||||
|
# For type annotation
|
||||||
|
from typing import Any, Callable, Dict, Iterator, List, Type # NOQA
|
||||||
|
from docutils import nodes # NOQA
|
||||||
|
from docutils.parsers import Parser # NOQA
|
||||||
|
from sphinx.application import Sphinx # NOQA
|
||||||
|
from sphinx.builders import Builder # NOQA
|
||||||
|
from sphinx.domains import Domain, Index # NOQA
|
||||||
|
from sphinx.environment import BuildEnvironment # NOQA
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# list of deprecated extensions. Keys are extension name.
|
||||||
|
# Values are Sphinx version that merge the extension.
|
||||||
|
EXTENSION_BLACKLIST = {
|
||||||
|
"sphinxjp.themecore": "1.2"
|
||||||
|
} # type: Dict[unicode, unicode]
|
||||||
|
|
||||||
|
|
||||||
|
class SphinxComponentRegistry(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.builders = {} # type: Dict[unicode, Type[Builder]]
|
||||||
|
self.domains = {} # type: Dict[unicode, Type[Domain]]
|
||||||
|
self.source_parsers = {} # type: Dict[unicode, Parser]
|
||||||
|
self.translators = {} # type: Dict[unicode, nodes.NodeVisitor]
|
||||||
|
|
||||||
|
def add_builder(self, builder):
|
||||||
|
# type: (Type[Builder]) -> None
|
||||||
|
if not hasattr(builder, 'name'):
|
||||||
|
raise ExtensionError(_('Builder class %s has no "name" attribute') % builder)
|
||||||
|
if builder.name in self.builders:
|
||||||
|
raise ExtensionError(_('Builder %r already exists (in module %s)') %
|
||||||
|
(builder.name, self.builders[builder.name].__module__))
|
||||||
|
self.builders[builder.name] = builder
|
||||||
|
|
||||||
|
def preload_builder(self, app, name):
|
||||||
|
# type: (Sphinx, unicode) -> None
|
||||||
|
if name is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if name not in self.builders:
|
||||||
|
entry_points = iter_entry_points('sphinx.builders', name)
|
||||||
|
try:
|
||||||
|
entry_point = next(entry_points)
|
||||||
|
except StopIteration:
|
||||||
|
raise SphinxError(_('Builder name %s not registered or available'
|
||||||
|
' through entry point') % name)
|
||||||
|
|
||||||
|
self.load_extension(app, entry_point.module_name)
|
||||||
|
|
||||||
|
def create_builder(self, app, name):
|
||||||
|
# type: (Sphinx, unicode) -> Builder
|
||||||
|
if name not in self.builders:
|
||||||
|
raise SphinxError(_('Builder name %s not registered') % name)
|
||||||
|
|
||||||
|
return self.builders[name](app)
|
||||||
|
|
||||||
|
def add_domain(self, domain):
|
||||||
|
# type: (Type[Domain]) -> None
|
||||||
|
if domain.name in self.domains:
|
||||||
|
raise ExtensionError(_('domain %s already registered') % domain.name)
|
||||||
|
self.domains[domain.name] = domain
|
||||||
|
|
||||||
|
def has_domain(self, domain):
|
||||||
|
# type: (unicode) -> bool
|
||||||
|
return domain in self.domains
|
||||||
|
|
||||||
|
def create_domains(self, env):
|
||||||
|
# type: (BuildEnvironment) -> Iterator[Domain]
|
||||||
|
for DomainClass in itervalues(self.domains):
|
||||||
|
yield DomainClass(env)
|
||||||
|
|
||||||
|
def override_domain(self, domain):
|
||||||
|
# type: (Type[Domain]) -> None
|
||||||
|
if domain.name not in self.domains:
|
||||||
|
raise ExtensionError(_('domain %s not yet registered') % domain.name)
|
||||||
|
if not issubclass(domain, self.domains[domain.name]):
|
||||||
|
raise ExtensionError(_('new domain not a subclass of registered %s '
|
||||||
|
'domain') % domain.name)
|
||||||
|
self.domains[domain.name] = domain
|
||||||
|
|
||||||
|
def add_directive_to_domain(self, domain, name, obj,
|
||||||
|
has_content=None, argument_spec=None, **option_spec):
|
||||||
|
# type: (unicode, unicode, Any, bool, Any, Any) -> None
|
||||||
|
if domain not in self.domains:
|
||||||
|
raise ExtensionError(_('domain %s not yet registered') % domain)
|
||||||
|
directive = directive_helper(obj, has_content, argument_spec, **option_spec)
|
||||||
|
self.domains[domain].directives[name] = directive
|
||||||
|
|
||||||
|
def add_role_to_domain(self, domain, name, role):
|
||||||
|
# type: (unicode, unicode, Any) -> None
|
||||||
|
if domain not in self.domains:
|
||||||
|
raise ExtensionError(_('domain %s not yet registered') % domain)
|
||||||
|
self.domains[domain].roles[name] = role
|
||||||
|
|
||||||
|
def add_index_to_domain(self, domain, index):
|
||||||
|
# type: (unicode, Type[Index]) -> None
|
||||||
|
if domain not in self.domains:
|
||||||
|
raise ExtensionError(_('domain %s not yet registered') % domain)
|
||||||
|
self.domains[domain].indices.append(index)
|
||||||
|
|
||||||
|
def add_object_type(self, directivename, rolename, indextemplate='',
|
||||||
|
parse_node=None, ref_nodeclass=None, objname='',
|
||||||
|
doc_field_types=[]):
|
||||||
|
# type: (unicode, unicode, unicode, Callable, nodes.Node, unicode, List) -> None
|
||||||
|
# create a subclass of GenericObject as the new directive
|
||||||
|
directive = type(directivename, # type: ignore
|
||||||
|
(GenericObject, object),
|
||||||
|
{'indextemplate': indextemplate,
|
||||||
|
'parse_node': staticmethod(parse_node), # type: ignore
|
||||||
|
'doc_field_types': doc_field_types})
|
||||||
|
|
||||||
|
stddomain = self.domains['std']
|
||||||
|
stddomain.directives[directivename] = directive
|
||||||
|
stddomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
|
||||||
|
stddomain.object_types[directivename] = ObjType(objname or directivename, rolename)
|
||||||
|
|
||||||
|
def add_crossref_type(self, directivename, rolename, indextemplate='',
|
||||||
|
ref_nodeclass=None, objname=''):
|
||||||
|
# type: (unicode, unicode, unicode, nodes.Node, unicode) -> None
|
||||||
|
# create a subclass of Target as the new directive
|
||||||
|
directive = type(directivename, # type: ignore
|
||||||
|
(Target, object),
|
||||||
|
{'indextemplate': indextemplate})
|
||||||
|
|
||||||
|
stddomain = self.domains['std']
|
||||||
|
stddomain.directives[directivename] = directive
|
||||||
|
stddomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
|
||||||
|
stddomain.object_types[directivename] = ObjType(objname or directivename, rolename)
|
||||||
|
|
||||||
|
def add_source_parser(self, suffix, parser):
|
||||||
|
# type: (unicode, Parser) -> None
|
||||||
|
if suffix in self.source_parsers:
|
||||||
|
raise ExtensionError(_('source_parser for %r is already registered') % suffix)
|
||||||
|
self.source_parsers[suffix] = parser
|
||||||
|
|
||||||
|
def get_source_parsers(self):
|
||||||
|
# type: () -> Dict[unicode, Parser]
|
||||||
|
return self.source_parsers
|
||||||
|
|
||||||
|
def add_translator(self, name, translator):
|
||||||
|
# type: (unicode, Type[nodes.NodeVisitor]) -> None
|
||||||
|
self.translators[name] = translator
|
||||||
|
|
||||||
|
def get_translator_class(self, builder):
|
||||||
|
# type: (Builder) -> Type[nodes.NodeVisitor]
|
||||||
|
return self.translators.get(builder.name,
|
||||||
|
builder.default_translator_class)
|
||||||
|
|
||||||
|
def create_translator(self, builder, document):
|
||||||
|
# type: (Builder, nodes.Node) -> nodes.NodeVisitor
|
||||||
|
translator_class = self.get_translator_class(builder)
|
||||||
|
return translator_class(builder, document)
|
||||||
|
|
||||||
|
def load_extension(self, app, extname):
|
||||||
|
# type: (Sphinx, unicode) -> None
|
||||||
|
"""Load a Sphinx extension."""
|
||||||
|
if extname in app.extensions: # alread loaded
|
||||||
|
return
|
||||||
|
if extname in EXTENSION_BLACKLIST:
|
||||||
|
logger.warning(_('the extension %r was already merged with Sphinx since '
|
||||||
|
'version %s; this extension is ignored.'),
|
||||||
|
extname, EXTENSION_BLACKLIST[extname])
|
||||||
|
return
|
||||||
|
|
||||||
|
# update loading context
|
||||||
|
app._setting_up_extension.append(extname)
|
||||||
|
|
||||||
|
try:
|
||||||
|
mod = __import__(extname, None, None, ['setup'])
|
||||||
|
except ImportError as err:
|
||||||
|
logger.verbose(_('Original exception:\n') + traceback.format_exc())
|
||||||
|
raise ExtensionError(_('Could not import extension %s') % extname, err)
|
||||||
|
|
||||||
|
if not hasattr(mod, 'setup'):
|
||||||
|
logger.warning(_('extension %r has no setup() function; is it really '
|
||||||
|
'a Sphinx extension module?'), extname)
|
||||||
|
metadata = {} # type: Dict[unicode, Any]
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
metadata = mod.setup(app)
|
||||||
|
except VersionRequirementError as err:
|
||||||
|
# add the extension name to the version required
|
||||||
|
raise VersionRequirementError(
|
||||||
|
_('The %s extension used by this project needs at least '
|
||||||
|
'Sphinx v%s; it therefore cannot be built with this '
|
||||||
|
'version.') % (extname, err)
|
||||||
|
)
|
||||||
|
|
||||||
|
if metadata is None:
|
||||||
|
metadata = {}
|
||||||
|
if extname == 'rst2pdf.pdfbuilder':
|
||||||
|
metadata['parallel_read_safe'] = True
|
||||||
|
elif not isinstance(metadata, dict):
|
||||||
|
logger.warning(_('extension %r returned an unsupported object from '
|
||||||
|
'its setup() function; it should return None or a '
|
||||||
|
'metadata dictionary'), extname)
|
||||||
|
|
||||||
|
app.extensions[extname] = Extension(extname, mod, **metadata)
|
||||||
|
app._setting_up_extension.pop()
|
@ -12,6 +12,7 @@
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import warnings
|
||||||
from os import path
|
from os import path
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ from six import string_types, iteritems
|
|||||||
from six.moves import configparser
|
from six.moves import configparser
|
||||||
|
|
||||||
from sphinx import package_dir
|
from sphinx import package_dir
|
||||||
|
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||||
from sphinx.errors import ThemeError
|
from sphinx.errors import ThemeError
|
||||||
from sphinx.locale import _
|
from sphinx.locale import _
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
@ -77,6 +79,8 @@ class Theme(object):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
inherit = self.config.get('theme', 'inherit')
|
inherit = self.config.get('theme', 'inherit')
|
||||||
|
except configparser.NoSectionError:
|
||||||
|
raise ThemeError(_('theme %r doesn\'t have "theme" setting') % name)
|
||||||
except configparser.NoOptionError:
|
except configparser.NoOptionError:
|
||||||
raise ThemeError(_('theme %r doesn\'t have "inherit" setting') % name)
|
raise ThemeError(_('theme %r doesn\'t have "inherit" setting') % name)
|
||||||
|
|
||||||
@ -161,7 +165,7 @@ class HTMLThemeFactory(object):
|
|||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
# type: (Sphinx) -> None
|
# type: (Sphinx) -> None
|
||||||
self.confdir = app.confdir
|
self.app = app
|
||||||
self.themes = app.html_themes
|
self.themes = app.html_themes
|
||||||
self.load_builtin_themes()
|
self.load_builtin_themes()
|
||||||
if getattr(app.config, 'html_theme_path', None):
|
if getattr(app.config, 'html_theme_path', None):
|
||||||
@ -178,7 +182,7 @@ class HTMLThemeFactory(object):
|
|||||||
# type: (unicode) -> None
|
# type: (unicode) -> None
|
||||||
"""Load additional themes placed at specified directories."""
|
"""Load additional themes placed at specified directories."""
|
||||||
for theme_path in theme_paths:
|
for theme_path in theme_paths:
|
||||||
abs_theme_path = path.abspath(path.join(self.confdir, theme_path))
|
abs_theme_path = path.abspath(path.join(self.app.confdir, theme_path))
|
||||||
themes = self.find_themes(abs_theme_path)
|
themes = self.find_themes(abs_theme_path)
|
||||||
for name, theme in iteritems(themes):
|
for name, theme in iteritems(themes):
|
||||||
self.themes[name] = theme
|
self.themes[name] = theme
|
||||||
@ -215,6 +219,16 @@ class HTMLThemeFactory(object):
|
|||||||
|
|
||||||
Sphinx refers to ``sphinx_themes`` entry_points.
|
Sphinx refers to ``sphinx_themes`` entry_points.
|
||||||
"""
|
"""
|
||||||
|
# look up for new styled entry_points at first
|
||||||
|
entry_points = pkg_resources.iter_entry_points('sphinx.html_themes', name)
|
||||||
|
try:
|
||||||
|
entry_point = next(entry_points)
|
||||||
|
self.app.registry.load_extension(self.app, entry_point.module_name)
|
||||||
|
return
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# look up for old styled entry_points
|
||||||
for entry_point in pkg_resources.iter_entry_points('sphinx_themes'):
|
for entry_point in pkg_resources.iter_entry_points('sphinx_themes'):
|
||||||
target = entry_point.load()
|
target = entry_point.load()
|
||||||
if callable(target):
|
if callable(target):
|
||||||
@ -228,6 +242,9 @@ class HTMLThemeFactory(object):
|
|||||||
themes = self.find_themes(themedir)
|
themes = self.find_themes(themedir)
|
||||||
for entry, theme in iteritems(themes):
|
for entry, theme in iteritems(themes):
|
||||||
if name == entry:
|
if name == entry:
|
||||||
|
warnings.warn('``sphinx_themes`` entry point is now deprecated. '
|
||||||
|
'Please use ``sphinx.html_themes`` instead.',
|
||||||
|
RemovedInSphinx20Warning)
|
||||||
self.themes[name] = theme
|
self.themes[name] = theme
|
||||||
|
|
||||||
def find_themes(self, theme_path):
|
def find_themes(self, theme_path):
|
||||||
|
@ -52,7 +52,7 @@ def publish_msgstr(app, source, source_path, source_line, config, settings):
|
|||||||
from sphinx.io import SphinxI18nReader
|
from sphinx.io import SphinxI18nReader
|
||||||
reader = SphinxI18nReader(
|
reader = SphinxI18nReader(
|
||||||
app=app,
|
app=app,
|
||||||
parsers=config.source_parsers,
|
parsers=app.registry.get_source_parsers(),
|
||||||
parser_name='restructuredtext', # default parser
|
parser_name='restructuredtext', # default parser
|
||||||
)
|
)
|
||||||
reader.set_lineno_for_reporter(source_line)
|
reader.set_lineno_for_reporter(source_line)
|
||||||
|
@ -24,7 +24,7 @@ from sphinx.util.osutil import ensuredir
|
|||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Dict # NOQA
|
from typing import Any, Dict, List, Tuple # NOQA
|
||||||
from sphinx.application import Sphinx # NOQA
|
from sphinx.application import Sphinx # NOQA
|
||||||
|
|
||||||
|
|
||||||
@ -136,6 +136,107 @@ class DataURIExtractor(BaseImageConverter):
|
|||||||
self.app.env.images.add_file(self.env.docname, path)
|
self.app.env.images.add_file(self.env.docname, path)
|
||||||
|
|
||||||
|
|
||||||
|
def get_filename_for(filename, mimetype):
|
||||||
|
# type: (unicode, unicode) -> unicode
|
||||||
|
basename = os.path.basename(filename)
|
||||||
|
return os.path.splitext(basename)[0] + get_image_extension(mimetype)
|
||||||
|
|
||||||
|
|
||||||
|
class ImageConverter(BaseImageConverter):
|
||||||
|
"""A base class images converter.
|
||||||
|
|
||||||
|
The concrete image converters should derive this class and
|
||||||
|
overrides the following methods and attributes:
|
||||||
|
|
||||||
|
* default_priority (if needed)
|
||||||
|
* conversion_rules
|
||||||
|
* is_available()
|
||||||
|
* convert()
|
||||||
|
"""
|
||||||
|
default_priority = 200
|
||||||
|
|
||||||
|
#: A conversion rules between two mimetypes which this converters supports
|
||||||
|
conversion_rules = [] # type: List[Tuple[unicode, unicode]]
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
# type: (Any, Any) -> None
|
||||||
|
self.available = None # type: bool
|
||||||
|
# the converter is available or not.
|
||||||
|
# Will be checked at first conversion
|
||||||
|
BaseImageConverter.__init__(self, *args, **kwargs) # type: ignore
|
||||||
|
|
||||||
|
def match(self, node):
|
||||||
|
# type: (nodes.Node) -> bool
|
||||||
|
if self.available is None:
|
||||||
|
self.available = self.is_available()
|
||||||
|
|
||||||
|
if not self.available:
|
||||||
|
return False
|
||||||
|
elif set(node['candidates']) & set(self.app.builder.supported_image_types):
|
||||||
|
# builder supports the image; no need to convert
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
rule = self.get_conversion_rule(node)
|
||||||
|
if rule:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_conversion_rule(self, node):
|
||||||
|
# type: (nodes.Node) -> Tuple[unicode, unicode]
|
||||||
|
for candidate in self.guess_mimetypes(node):
|
||||||
|
for supported in self.app.builder.supported_image_types:
|
||||||
|
rule = (candidate, supported)
|
||||||
|
if rule in self.conversion_rules:
|
||||||
|
return rule
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_available(self):
|
||||||
|
# type: () -> bool
|
||||||
|
"""Confirms the converter is available or not."""
|
||||||
|
raise NotImplemented
|
||||||
|
|
||||||
|
def guess_mimetypes(self, node):
|
||||||
|
# type: (nodes.Node) -> List[unicode]
|
||||||
|
if '?' in node['candidates']:
|
||||||
|
return []
|
||||||
|
elif '*' in node['candidates']:
|
||||||
|
from sphinx.util.images import guess_mimetype
|
||||||
|
return [guess_mimetype(node['uri'])]
|
||||||
|
else:
|
||||||
|
return node['candidates'].keys()
|
||||||
|
|
||||||
|
def handle(self, node):
|
||||||
|
# type: (nodes.Node) -> None
|
||||||
|
_from, _to = self.get_conversion_rule(node)
|
||||||
|
|
||||||
|
if _from in node['candidates']:
|
||||||
|
srcpath = node['candidates'][_from]
|
||||||
|
else:
|
||||||
|
srcpath = node['candidates']['*']
|
||||||
|
|
||||||
|
filename = get_filename_for(srcpath, _to)
|
||||||
|
ensuredir(self.imagedir)
|
||||||
|
destpath = os.path.join(self.imagedir, filename)
|
||||||
|
|
||||||
|
abs_srcpath = os.path.join(self.app.srcdir, srcpath)
|
||||||
|
if self.convert(abs_srcpath, destpath):
|
||||||
|
if '*' in node['candidates']:
|
||||||
|
node['candidates']['*'] = destpath
|
||||||
|
else:
|
||||||
|
node['candidates'][_to] = destpath
|
||||||
|
node['uri'] = destpath
|
||||||
|
|
||||||
|
self.env.original_image_uri[destpath] = srcpath
|
||||||
|
self.env.images.add_file(self.env.docname, destpath)
|
||||||
|
|
||||||
|
def convert(self, _from, _to):
|
||||||
|
# type: (unicode, unicode) -> bool
|
||||||
|
"""Converts the image to expected one."""
|
||||||
|
raise NotImplemented
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[unicode, Any]
|
# type: (Sphinx) -> Dict[unicode, Any]
|
||||||
app.add_post_transform(ImageDownloader)
|
app.add_post_transform(ImageDownloader)
|
||||||
|
@ -11,13 +11,16 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import types
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
import docutils
|
import docutils
|
||||||
from docutils.utils import Reporter
|
from docutils.utils import Reporter
|
||||||
from docutils.parsers.rst import directives, roles
|
from docutils.parsers.rst import directives, roles, convert_directive_function
|
||||||
|
|
||||||
|
from sphinx.errors import ExtensionError
|
||||||
|
from sphinx.locale import _
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -154,3 +157,17 @@ class LoggingReporter(Reporter):
|
|||||||
def is_html5_writer_available():
|
def is_html5_writer_available():
|
||||||
# type: () -> bool
|
# type: () -> bool
|
||||||
return __version_info__ > (0, 13, 0)
|
return __version_info__ > (0, 13, 0)
|
||||||
|
|
||||||
|
|
||||||
|
def directive_helper(obj, has_content=None, argument_spec=None, **option_spec):
|
||||||
|
# type: (Any, bool, Tuple[int, int, bool], Any) -> Any
|
||||||
|
if isinstance(obj, (types.FunctionType, types.MethodType)):
|
||||||
|
obj.content = has_content # type: ignore
|
||||||
|
obj.arguments = argument_spec or (0, 0, False) # type: ignore
|
||||||
|
obj.options = option_spec # type: ignore
|
||||||
|
return convert_directive_function(obj)
|
||||||
|
else:
|
||||||
|
if has_content or argument_spec or option_spec:
|
||||||
|
raise ExtensionError(_('when adding directive classes, no '
|
||||||
|
'additional arguments may be given'))
|
||||||
|
return obj
|
||||||
|
@ -52,7 +52,7 @@ class HTMLWriter(Writer):
|
|||||||
def translate(self):
|
def translate(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
# sadly, this is mostly copied from parent class
|
# sadly, this is mostly copied from parent class
|
||||||
self.visitor = visitor = self.builder.translator_class(self.builder,
|
self.visitor = visitor = self.builder.create_translator(self.builder,
|
||||||
self.document)
|
self.document)
|
||||||
self.document.walkabout(visitor)
|
self.document.walkabout(visitor)
|
||||||
self.output = visitor.astext()
|
self.output = visitor.astext()
|
||||||
|
@ -159,14 +159,12 @@ class LaTeXWriter(writers.Writer):
|
|||||||
# type: (Builder) -> None
|
# type: (Builder) -> None
|
||||||
writers.Writer.__init__(self)
|
writers.Writer.__init__(self)
|
||||||
self.builder = builder
|
self.builder = builder
|
||||||
self.translator_class = (
|
|
||||||
self.builder.translator_class or LaTeXTranslator)
|
|
||||||
|
|
||||||
def translate(self):
|
def translate(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
transform = ShowUrlsTransform(self.document)
|
transform = ShowUrlsTransform(self.document)
|
||||||
transform.apply()
|
transform.apply()
|
||||||
visitor = self.translator_class(self.document, self.builder)
|
visitor = self.builder.create_translator(self.document, self.builder)
|
||||||
self.document.walkabout(visitor)
|
self.document.walkabout(visitor)
|
||||||
self.output = visitor.astext()
|
self.output = visitor.astext()
|
||||||
|
|
||||||
|
@ -35,14 +35,12 @@ class ManualPageWriter(Writer):
|
|||||||
# type: (Builder) -> None
|
# type: (Builder) -> None
|
||||||
Writer.__init__(self)
|
Writer.__init__(self)
|
||||||
self.builder = builder
|
self.builder = builder
|
||||||
self.translator_class = (
|
|
||||||
self.builder.translator_class or ManualPageTranslator)
|
|
||||||
|
|
||||||
def translate(self):
|
def translate(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
transform = NestedInlineTransform(self.document)
|
transform = NestedInlineTransform(self.document)
|
||||||
transform.apply()
|
transform.apply()
|
||||||
visitor = self.translator_class(self.builder, self.document)
|
visitor = self.builder.create_translator(self.builder, self.document)
|
||||||
self.visitor = visitor
|
self.visitor = visitor
|
||||||
self.document.walkabout(visitor)
|
self.document.walkabout(visitor)
|
||||||
self.output = visitor.astext()
|
self.output = visitor.astext()
|
||||||
|
@ -133,13 +133,10 @@ class TexinfoWriter(writers.Writer):
|
|||||||
# type: (TexinfoBuilder) -> None
|
# type: (TexinfoBuilder) -> None
|
||||||
writers.Writer.__init__(self)
|
writers.Writer.__init__(self)
|
||||||
self.builder = builder
|
self.builder = builder
|
||||||
self.translator_class = (
|
|
||||||
self.builder.translator_class or TexinfoTranslator)
|
|
||||||
|
|
||||||
def translate(self):
|
def translate(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
self.visitor = visitor = self.translator_class(
|
self.visitor = visitor = self.builder.create_translator(self.document, self.builder)
|
||||||
self.document, self.builder)
|
|
||||||
self.document.walkabout(visitor)
|
self.document.walkabout(visitor)
|
||||||
visitor.finish()
|
visitor.finish()
|
||||||
for attr in self.visitor_attributes:
|
for attr in self.visitor_attributes:
|
||||||
|
@ -159,11 +159,10 @@ class TextWriter(writers.Writer):
|
|||||||
# type: (TextBuilder) -> None
|
# type: (TextBuilder) -> None
|
||||||
writers.Writer.__init__(self)
|
writers.Writer.__init__(self)
|
||||||
self.builder = builder
|
self.builder = builder
|
||||||
self.translator_class = self.builder.translator_class or TextTranslator
|
|
||||||
|
|
||||||
def translate(self):
|
def translate(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
visitor = self.translator_class(self.document, self.builder)
|
visitor = self.builder.create_translator(self.document, self.builder)
|
||||||
self.document.walkabout(visitor)
|
self.document.walkabout(visitor)
|
||||||
self.output = visitor.body
|
self.output = visitor.body
|
||||||
|
|
||||||
|
@ -24,8 +24,7 @@ class XMLWriter(BaseXMLWriter):
|
|||||||
# type: (Builder) -> None
|
# type: (Builder) -> None
|
||||||
BaseXMLWriter.__init__(self)
|
BaseXMLWriter.__init__(self)
|
||||||
self.builder = builder
|
self.builder = builder
|
||||||
if self.builder.translator_class:
|
self.translator_class = self.builder.get_translator_class()
|
||||||
self.translator_class = self.builder.translator_class
|
|
||||||
|
|
||||||
def translate(self, *args, **kwargs):
|
def translate(self, *args, **kwargs):
|
||||||
# type: (Any, Any) -> None
|
# type: (Any, Any) -> None
|
||||||
|
4
tests/roots/test-ext-imgconverter/conf.py
Normal file
4
tests/roots/test-ext-imgconverter/conf.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
master_doc = 'index'
|
||||||
|
extensions = ['sphinx.ext.imgconverter']
|
4
tests/roots/test-ext-imgconverter/index.rst
Normal file
4
tests/roots/test-ext-imgconverter/index.rst
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
test-ext-imgconverter
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. image:: svgimg.svg
|
158
tests/roots/test-ext-imgconverter/svgimg.svg
Normal file
158
tests/roots/test-ext-imgconverter/svgimg.svg
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://web.resource.org/cc/"
|
||||||
|
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://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
height="60"
|
||||||
|
width="60"
|
||||||
|
_SVGFile__filename="oldscale/apps/warning.svg"
|
||||||
|
version="1.0"
|
||||||
|
y="0"
|
||||||
|
x="0"
|
||||||
|
id="svg1"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.41"
|
||||||
|
sodipodi:docname="exclamation.svg"
|
||||||
|
sodipodi:docbase="/home/danny/work/icons/primary/scalable/actions">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0000000"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="7.5136000"
|
||||||
|
inkscape:cx="42.825186"
|
||||||
|
inkscape:cy="24.316071"
|
||||||
|
inkscape:window-width="1020"
|
||||||
|
inkscape:window-height="691"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:current-layer="svg1" />
|
||||||
|
<defs
|
||||||
|
id="defs3">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient1160">
|
||||||
|
<stop
|
||||||
|
style="stop-color: #000000;stop-opacity: 1.0;"
|
||||||
|
id="stop1161"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
id="stop1162"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#linearGradient1160"
|
||||||
|
id="linearGradient1163" />
|
||||||
|
</defs>
|
||||||
|
<metadata
|
||||||
|
id="metadata12">
|
||||||
|
<RDF
|
||||||
|
id="RDF13">
|
||||||
|
<Work
|
||||||
|
about=""
|
||||||
|
id="Work14">
|
||||||
|
<title
|
||||||
|
id="title15">Part of the Flat Icon Collection (Thu Aug 26 14:31:40 2004)</title>
|
||||||
|
<description
|
||||||
|
id="description17" />
|
||||||
|
<subject
|
||||||
|
id="subject18">
|
||||||
|
<Bag
|
||||||
|
id="Bag19">
|
||||||
|
<li
|
||||||
|
id="li20" />
|
||||||
|
</Bag>
|
||||||
|
</subject>
|
||||||
|
<publisher
|
||||||
|
id="publisher21">
|
||||||
|
<Agent
|
||||||
|
about=""
|
||||||
|
id="Agent22">
|
||||||
|
<title
|
||||||
|
id="title23" />
|
||||||
|
</Agent>
|
||||||
|
</publisher>
|
||||||
|
<creator
|
||||||
|
id="creator24">
|
||||||
|
<Agent
|
||||||
|
about=""
|
||||||
|
id="Agent25">
|
||||||
|
<title
|
||||||
|
id="title26">Danny Allen</title>
|
||||||
|
</Agent>
|
||||||
|
</creator>
|
||||||
|
<rights
|
||||||
|
id="rights28">
|
||||||
|
<Agent
|
||||||
|
about=""
|
||||||
|
id="Agent29">
|
||||||
|
<title
|
||||||
|
id="title30">Danny Allen</title>
|
||||||
|
</Agent>
|
||||||
|
</rights>
|
||||||
|
<date
|
||||||
|
id="date32" />
|
||||||
|
<format
|
||||||
|
id="format33">image/svg+xml</format>
|
||||||
|
<type
|
||||||
|
id="type35"
|
||||||
|
resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<license
|
||||||
|
id="license36"
|
||||||
|
resource="http://creativecommons.org/licenses/LGPL/2.1/">
|
||||||
|
<date
|
||||||
|
id="date37" />
|
||||||
|
</license>
|
||||||
|
<language
|
||||||
|
id="language38">en</language>
|
||||||
|
</Work>
|
||||||
|
</RDF>
|
||||||
|
<rdf:RDF
|
||||||
|
id="RDF40">
|
||||||
|
<cc:Work
|
||||||
|
rdf:about=""
|
||||||
|
id="Work41">
|
||||||
|
<dc:format
|
||||||
|
id="format42">image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
id="type44"
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="g2099">
|
||||||
|
<path
|
||||||
|
style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:8.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||||
|
d="M 55.311891,51.920745 L 4.6880989,51.920744 L 29.999995,8.0792542 L 55.311891,51.920745 z "
|
||||||
|
id="path1724" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;fill:#ffe940;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250010;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||||
|
d="M 55.311891,51.920745 L 4.6880989,51.920744 L 29.999995,8.0792542 L 55.311891,51.920745 z "
|
||||||
|
id="path1722" />
|
||||||
|
<path
|
||||||
|
style="font-size:12.000000;font-weight:900;fill:none;fill-opacity:1.0000000;stroke:#ffffff;stroke-width:8.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||||
|
d="M 34.944960,10.779626 L 34.944960,33.186510 C 34.944960,34.752415 34.501979,36.081368 33.616007,37.173380 C 32.750636,38.265402 31.545298,38.811408 29.999995,38.811408 C 28.475302,38.811408 27.269965,38.265402 26.383993,37.173380 C 25.498020,36.060767 25.055030,34.731804 25.055030,33.186510 L 25.055030,10.779626 C 25.055030,9.1931155 25.498020,7.8641562 26.383993,6.7927462 C 27.269965,5.7007332 28.475302,5.1547262 29.999995,5.1547262 C 31.009593,5.1547262 31.885265,5.4019740 32.627010,5.8964706 C 33.389356,6.3909681 33.966274,7.0709005 34.357752,7.9362696 C 34.749221,8.7810349 34.944960,9.7288200 34.944960,10.779626 z "
|
||||||
|
id="path1099" />
|
||||||
|
<path
|
||||||
|
style="font-size:12.000000;font-weight:900;fill:#e71c02;fill-opacity:1.0000000;stroke:none;stroke-width:3.1249981;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1.0000000"
|
||||||
|
d="M 29.999995,3.5986440 C 28.102272,3.5986440 26.318514,4.3848272 25.156245,5.8173940 C 24.028906,7.1806889 23.499995,8.9087770 23.499995,10.786144 L 23.499995,33.192394 C 23.499995,35.036302 24.050685,36.772771 25.156245,38.161144 C 26.318514,39.593721 28.102273,40.379893 29.999995,40.379894 C 31.913354,40.379894 33.697195,39.576736 34.843745,38.129894 C 35.959941,36.754118 36.499995,35.052976 36.499995,33.192394 L 36.499995,10.786144 C 36.499995,9.5413010 36.276626,8.3551469 35.781245,7.2861440 C 35.278844,6.1755772 34.477762,5.2531440 33.468745,4.5986440 C 32.454761,3.9226545 31.264694,3.5986439 29.999995,3.5986440 z "
|
||||||
|
id="path835"
|
||||||
|
sodipodi:nodetypes="cccccccccccc" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:5.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||||
|
d="M 36.506243,49.901522 C 36.506243,53.492972 33.591442,56.407773 29.999991,56.407773 C 26.408541,56.407773 23.493739,53.492972 23.493739,49.901522 C 23.493739,46.310071 26.408541,43.395270 29.999991,43.395270 C 33.591442,43.395270 36.506243,46.310071 36.506243,49.901522 z "
|
||||||
|
id="path1727" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;fill:#e71c02;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||||
|
d="M 36.506243,49.901522 C 36.506243,53.492972 33.591442,56.407773 29.999991,56.407773 C 26.408541,56.407773 23.493739,53.492972 23.493739,49.901522 C 23.493739,46.310071 26.408541,43.395270 29.999991,43.395270 C 33.591442,43.395270 36.506243,46.310071 36.506243,49.901522 z "
|
||||||
|
id="path1725" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7.2 KiB |
4
tests/roots/test-ext-intersphinx-cppdomain/conf.py
Normal file
4
tests/roots/test-ext-intersphinx-cppdomain/conf.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
extensions = ['sphinx.ext.intersphinx']
|
||||||
|
master_doc = 'index'
|
6
tests/roots/test-ext-intersphinx-cppdomain/index.rst
Normal file
6
tests/roots/test-ext-intersphinx-cppdomain/index.rst
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
test-ext-intersphinx-cppdomain
|
||||||
|
==============================
|
||||||
|
|
||||||
|
.. cpp:namespace:: foo
|
||||||
|
|
||||||
|
:cpp:class:`Bar`
|
@ -26,7 +26,7 @@ def teardown_module():
|
|||||||
@pytest.mark.sphinx('html')
|
@pytest.mark.sphinx('html')
|
||||||
def test_html_translator(app, status, warning):
|
def test_html_translator(app, status, warning):
|
||||||
# no set_translator()
|
# no set_translator()
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'SmartyPantsHTMLTranslator'
|
assert translator_class.__name__ == 'SmartyPantsHTMLTranslator'
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ def test_html_translator(app, status, warning):
|
|||||||
'html_use_smartypants': False})
|
'html_use_smartypants': False})
|
||||||
def test_html_with_smartypants(app, status, warning):
|
def test_html_with_smartypants(app, status, warning):
|
||||||
# no set_translator(), html_use_smartypants=False
|
# no set_translator(), html_use_smartypants=False
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'HTMLTranslator'
|
assert translator_class.__name__ == 'HTMLTranslator'
|
||||||
|
|
||||||
@ -43,69 +43,69 @@ def test_html_with_smartypants(app, status, warning):
|
|||||||
@pytest.mark.sphinx('html', testroot='api-set-translator')
|
@pytest.mark.sphinx('html', testroot='api-set-translator')
|
||||||
def test_html_with_set_translator_for_html_(app, status, warning):
|
def test_html_with_set_translator_for_html_(app, status, warning):
|
||||||
# use set_translator()
|
# use set_translator()
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'ConfHTMLTranslator'
|
assert translator_class.__name__ == 'ConfHTMLTranslator'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('singlehtml', testroot='api-set-translator')
|
@pytest.mark.sphinx('singlehtml', testroot='api-set-translator')
|
||||||
def test_singlehtml_set_translator_for_singlehtml(app, status, warning):
|
def test_singlehtml_set_translator_for_singlehtml(app, status, warning):
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'ConfSingleHTMLTranslator'
|
assert translator_class.__name__ == 'ConfSingleHTMLTranslator'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('pickle', testroot='api-set-translator')
|
@pytest.mark.sphinx('pickle', testroot='api-set-translator')
|
||||||
def test_pickle_set_translator_for_pickle(app, status, warning):
|
def test_pickle_set_translator_for_pickle(app, status, warning):
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'ConfPickleTranslator'
|
assert translator_class.__name__ == 'ConfPickleTranslator'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('json', testroot='api-set-translator')
|
@pytest.mark.sphinx('json', testroot='api-set-translator')
|
||||||
def test_json_set_translator_for_json(app, status, warning):
|
def test_json_set_translator_for_json(app, status, warning):
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'ConfJsonTranslator'
|
assert translator_class.__name__ == 'ConfJsonTranslator'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('latex', testroot='api-set-translator')
|
@pytest.mark.sphinx('latex', testroot='api-set-translator')
|
||||||
def test_html_with_set_translator_for_latex(app, status, warning):
|
def test_html_with_set_translator_for_latex(app, status, warning):
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'ConfLaTeXTranslator'
|
assert translator_class.__name__ == 'ConfLaTeXTranslator'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('man', testroot='api-set-translator')
|
@pytest.mark.sphinx('man', testroot='api-set-translator')
|
||||||
def test_html_with_set_translator_for_man(app, status, warning):
|
def test_html_with_set_translator_for_man(app, status, warning):
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'ConfManualPageTranslator'
|
assert translator_class.__name__ == 'ConfManualPageTranslator'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('texinfo', testroot='api-set-translator')
|
@pytest.mark.sphinx('texinfo', testroot='api-set-translator')
|
||||||
def test_html_with_set_translator_for_texinfo(app, status, warning):
|
def test_html_with_set_translator_for_texinfo(app, status, warning):
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'ConfTexinfoTranslator'
|
assert translator_class.__name__ == 'ConfTexinfoTranslator'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('text', testroot='api-set-translator')
|
@pytest.mark.sphinx('text', testroot='api-set-translator')
|
||||||
def test_html_with_set_translator_for_text(app, status, warning):
|
def test_html_with_set_translator_for_text(app, status, warning):
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'ConfTextTranslator'
|
assert translator_class.__name__ == 'ConfTextTranslator'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('xml', testroot='api-set-translator')
|
@pytest.mark.sphinx('xml', testroot='api-set-translator')
|
||||||
def test_html_with_set_translator_for_xml(app, status, warning):
|
def test_html_with_set_translator_for_xml(app, status, warning):
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'ConfXMLTranslator'
|
assert translator_class.__name__ == 'ConfXMLTranslator'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('pseudoxml', testroot='api-set-translator')
|
@pytest.mark.sphinx('pseudoxml', testroot='api-set-translator')
|
||||||
def test_html_with_set_translator_for_pseudoxml(app, status, warning):
|
def test_html_with_set_translator_for_pseudoxml(app, status, warning):
|
||||||
translator_class = app.builder.translator_class
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'ConfPseudoXMLTranslator'
|
assert translator_class.__name__ == 'ConfPseudoXMLTranslator'
|
||||||
|
@ -85,13 +85,6 @@ def test_domain_override(app, status, warning):
|
|||||||
@pytest.mark.sphinx(testroot='add_source_parser')
|
@pytest.mark.sphinx(testroot='add_source_parser')
|
||||||
def test_add_source_parser(app, status, warning):
|
def test_add_source_parser(app, status, warning):
|
||||||
assert set(app.config.source_suffix) == set(['.rst', '.md', '.test'])
|
assert set(app.config.source_suffix) == set(['.rst', '.md', '.test'])
|
||||||
assert set(app.config.source_parsers.keys()) == set(['.md', '.test'])
|
assert set(app.registry.get_source_parsers().keys()) == set(['.md', '.test'])
|
||||||
assert app.config.source_parsers['.md'].__name__ == 'DummyMarkdownParser'
|
assert app.registry.get_source_parsers()['.md'].__name__ == 'DummyMarkdownParser'
|
||||||
assert app.config.source_parsers['.test'].__name__ == 'TestSourceParser'
|
assert app.registry.get_source_parsers()['.test'].__name__ == 'TestSourceParser'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx(testroot='add_source_parser-conflicts-with-users-setting')
|
|
||||||
def test_add_source_parser_conflicts_with_users_setting(app, status, warning):
|
|
||||||
assert set(app.config.source_suffix) == set(['.rst', '.test'])
|
|
||||||
assert set(app.config.source_parsers.keys()) == set(['.test'])
|
|
||||||
assert app.config.source_parsers['.test'].__name__ == 'DummyTestParser'
|
|
||||||
|
@ -87,6 +87,14 @@ def compile_latex_document(app):
|
|||||||
app.config.latex_engine, p.returncode)
|
app.config.latex_engine, p.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
def skip_if_requested(testfunc):
|
||||||
|
if 'SKIP_LATEX_BUILD' in os.environ:
|
||||||
|
msg = 'Skip LaTeX builds because SKIP_LATEX_BUILD is set'
|
||||||
|
return skip_if(True, msg)(testfunc)
|
||||||
|
else:
|
||||||
|
return testfunc
|
||||||
|
|
||||||
|
|
||||||
def skip_if_stylefiles_notfound(testfunc):
|
def skip_if_stylefiles_notfound(testfunc):
|
||||||
if kpsetest(*STYLEFILES) is False:
|
if kpsetest(*STYLEFILES) is False:
|
||||||
msg = 'not running latex, the required styles do not seem to be installed'
|
msg = 'not running latex, the required styles do not seem to be installed'
|
||||||
@ -95,6 +103,7 @@ def skip_if_stylefiles_notfound(testfunc):
|
|||||||
return testfunc
|
return testfunc
|
||||||
|
|
||||||
|
|
||||||
|
@skip_if_requested
|
||||||
@skip_if_stylefiles_notfound
|
@skip_if_stylefiles_notfound
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"engine,docclass",
|
"engine,docclass",
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from mock import Mock
|
||||||
|
from docutils import nodes
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
|
from sphinx.domains.javascript import JavaScriptDomain
|
||||||
|
|
||||||
from util import assert_node
|
from util import assert_node
|
||||||
|
|
||||||
@ -133,3 +137,31 @@ def test_domain_js_find_obj(app, status, warning):
|
|||||||
( u'module_a.submodule.ModTopLevel.mod_child_2', (u'module', u'method')))
|
( u'module_a.submodule.ModTopLevel.mod_child_2', (u'module', u'method')))
|
||||||
assert (find_obj(u'module_b.submodule', u'ModTopLevel', u'module_a.submodule', u'mod') ==
|
assert (find_obj(u'module_b.submodule', u'ModTopLevel', u'module_a.submodule', u'mod') ==
|
||||||
( u'module_a.submodule', (u'module', u'module')))
|
( u'module_a.submodule', (u'module', u'module')))
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_full_qualified_name():
|
||||||
|
env = Mock(domaindata={})
|
||||||
|
domain = JavaScriptDomain(env)
|
||||||
|
|
||||||
|
# non-js references
|
||||||
|
node = nodes.reference()
|
||||||
|
assert domain.get_full_qualified_name(node) is None
|
||||||
|
|
||||||
|
# simple reference
|
||||||
|
node = nodes.reference(reftarget='func')
|
||||||
|
assert domain.get_full_qualified_name(node) == 'func'
|
||||||
|
|
||||||
|
# with js:module context
|
||||||
|
kwargs = {'js:module': 'module1'}
|
||||||
|
node = nodes.reference(reftarget='func', **kwargs)
|
||||||
|
assert domain.get_full_qualified_name(node) == 'module1.func'
|
||||||
|
|
||||||
|
# with js:object context
|
||||||
|
kwargs = {'js:object': 'Class'}
|
||||||
|
node = nodes.reference(reftarget='func', **kwargs)
|
||||||
|
assert domain.get_full_qualified_name(node) == 'Class.func'
|
||||||
|
|
||||||
|
# with both js:module and js:object context
|
||||||
|
kwargs = {'js:module': 'module1', 'js:object': 'Class'}
|
||||||
|
node = nodes.reference(reftarget='func', **kwargs)
|
||||||
|
assert domain.get_full_qualified_name(node) == 'module1.Class.func'
|
||||||
|
@ -10,9 +10,12 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from mock import Mock
|
||||||
from six import text_type
|
from six import text_type
|
||||||
|
from docutils import nodes
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.domains.python import py_sig_re, _pseudo_parse_arglist
|
from sphinx.domains.python import py_sig_re, _pseudo_parse_arglist, PythonDomain
|
||||||
|
|
||||||
from util import assert_node
|
from util import assert_node
|
||||||
|
|
||||||
@ -28,7 +31,6 @@ def parse(sig):
|
|||||||
|
|
||||||
|
|
||||||
def test_function_signatures():
|
def test_function_signatures():
|
||||||
|
|
||||||
rv = parse('func(a=1) -> int object')
|
rv = parse('func(a=1) -> int object')
|
||||||
assert text_type(rv) == u'a=1'
|
assert text_type(rv) == u'a=1'
|
||||||
|
|
||||||
@ -165,3 +167,31 @@ def test_domain_py_find_obj(app, status, warning):
|
|||||||
[(u'NestedParentA.NestedChildA.subchild_1', (u'roles', u'method'))])
|
[(u'NestedParentA.NestedChildA.subchild_1', (u'roles', u'method'))])
|
||||||
assert (find_obj(None, u'NestedParentA.NestedChildA', u'subchild_1', u'meth') ==
|
assert (find_obj(None, u'NestedParentA.NestedChildA', u'subchild_1', u'meth') ==
|
||||||
[(u'NestedParentA.NestedChildA.subchild_1', (u'roles', u'method'))])
|
[(u'NestedParentA.NestedChildA.subchild_1', (u'roles', u'method'))])
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_full_qualified_name():
|
||||||
|
env = Mock(domaindata={})
|
||||||
|
domain = PythonDomain(env)
|
||||||
|
|
||||||
|
# non-python references
|
||||||
|
node = nodes.reference()
|
||||||
|
assert domain.get_full_qualified_name(node) is None
|
||||||
|
|
||||||
|
# simple reference
|
||||||
|
node = nodes.reference(reftarget='func')
|
||||||
|
assert domain.get_full_qualified_name(node) == 'func'
|
||||||
|
|
||||||
|
# with py:module context
|
||||||
|
kwargs = {'py:module': 'module1'}
|
||||||
|
node = nodes.reference(reftarget='func', **kwargs)
|
||||||
|
assert domain.get_full_qualified_name(node) == 'module1.func'
|
||||||
|
|
||||||
|
# with py:class context
|
||||||
|
kwargs = {'py:class': 'Class'}
|
||||||
|
node = nodes.reference(reftarget='func', **kwargs)
|
||||||
|
assert domain.get_full_qualified_name(node) == 'Class.func'
|
||||||
|
|
||||||
|
# with both py:module and py:class context
|
||||||
|
kwargs = {'py:module': 'module1', 'py:class': 'Class'}
|
||||||
|
node = nodes.reference(reftarget='func', **kwargs)
|
||||||
|
assert domain.get_full_qualified_name(node) == 'module1.Class.func'
|
||||||
|
@ -57,3 +57,21 @@ def test_process_doc_handle_table_title():
|
|||||||
assert 'testname' in domain.data['labels']
|
assert 'testname' in domain.data['labels']
|
||||||
assert domain.data['labels']['testname'] == (
|
assert domain.data['labels']['testname'] == (
|
||||||
'testdoc', 'testid', 'title text')
|
'testdoc', 'testid', 'title text')
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_full_qualified_name():
|
||||||
|
env = mock.Mock(domaindata={})
|
||||||
|
domain = StandardDomain(env)
|
||||||
|
|
||||||
|
# normal references
|
||||||
|
node = nodes.reference()
|
||||||
|
assert domain.get_full_qualified_name(node) is None
|
||||||
|
|
||||||
|
# simple reference to options
|
||||||
|
node = nodes.reference(reftype='option', reftarget='-l')
|
||||||
|
assert domain.get_full_qualified_name(node) is None
|
||||||
|
|
||||||
|
# options with std:program context
|
||||||
|
kwargs = {'std:program': 'ls'}
|
||||||
|
node = nodes.reference(reftype='option', reftarget='-l', **kwargs)
|
||||||
|
assert domain.get_full_qualified_name(node) == 'ls.-l'
|
||||||
|
22
tests/test_ext_imgconverter.py
Normal file
22
tests/test_ext_imgconverter.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
test_ext_imgconverter
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Test sphinx.ext.imgconverter extension.
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('latex', testroot='ext-imgconverter')
|
||||||
|
def test_ext_imgconverter(app, status, warning):
|
||||||
|
app.builder.build_all()
|
||||||
|
|
||||||
|
content = (app.outdir / 'Python.tex').text()
|
||||||
|
assert '\\sphinxincludegraphics{{svgimg}.png}' in content
|
||||||
|
assert not (app.outdir / 'svgimg.svg').exists()
|
||||||
|
assert (app.outdir / 'svgimg.png').exists()
|
@ -26,6 +26,22 @@ from sphinx.ext.intersphinx import (
|
|||||||
from test_util_inventory import inventory_v2
|
from test_util_inventory import inventory_v2
|
||||||
|
|
||||||
|
|
||||||
|
def fake_node(domain, type, target, content, **attrs):
|
||||||
|
contnode = nodes.emphasis(content, content)
|
||||||
|
node = addnodes.pending_xref('')
|
||||||
|
node['reftarget'] = target
|
||||||
|
node['reftype'] = type
|
||||||
|
node['refdomain'] = domain
|
||||||
|
node.attributes.update(attrs)
|
||||||
|
node += contnode
|
||||||
|
return node, contnode
|
||||||
|
|
||||||
|
|
||||||
|
def reference_check(app, *args, **kwds):
|
||||||
|
node, contnode = fake_node(*args, **kwds)
|
||||||
|
return missing_reference(app, app.env, node, contnode)
|
||||||
|
|
||||||
|
|
||||||
@mock.patch('sphinx.ext.intersphinx.InventoryFile')
|
@mock.patch('sphinx.ext.intersphinx.InventoryFile')
|
||||||
@mock.patch('sphinx.ext.intersphinx._read_from_url')
|
@mock.patch('sphinx.ext.intersphinx._read_from_url')
|
||||||
def test_fetch_inventory_redirection(_read_from_url, InventoryFile, app, status, warning):
|
def test_fetch_inventory_redirection(_read_from_url, InventoryFile, app, status, warning):
|
||||||
@ -88,46 +104,30 @@ def test_missing_reference(tempdir, app, status, warning):
|
|||||||
assert inv['py:module']['module2'] == \
|
assert inv['py:module']['module2'] == \
|
||||||
('foo', '2.0', 'https://docs.python.org/foo.html#module-module2', '-')
|
('foo', '2.0', 'https://docs.python.org/foo.html#module-module2', '-')
|
||||||
|
|
||||||
# create fake nodes and check referencing
|
|
||||||
|
|
||||||
def fake_node(domain, type, target, content, **attrs):
|
|
||||||
contnode = nodes.emphasis(content, content)
|
|
||||||
node = addnodes.pending_xref('')
|
|
||||||
node['reftarget'] = target
|
|
||||||
node['reftype'] = type
|
|
||||||
node['refdomain'] = domain
|
|
||||||
node.attributes.update(attrs)
|
|
||||||
node += contnode
|
|
||||||
return node, contnode
|
|
||||||
|
|
||||||
def reference_check(*args, **kwds):
|
|
||||||
node, contnode = fake_node(*args, **kwds)
|
|
||||||
return missing_reference(app, app.env, node, contnode)
|
|
||||||
|
|
||||||
# check resolution when a target is found
|
# check resolution when a target is found
|
||||||
rn = reference_check('py', 'func', 'module1.func', 'foo')
|
rn = reference_check(app, 'py', 'func', 'module1.func', 'foo')
|
||||||
assert isinstance(rn, nodes.reference)
|
assert isinstance(rn, nodes.reference)
|
||||||
assert rn['refuri'] == 'https://docs.python.org/sub/foo.html#module1.func'
|
assert rn['refuri'] == 'https://docs.python.org/sub/foo.html#module1.func'
|
||||||
assert rn['reftitle'] == '(in foo v2.0)'
|
assert rn['reftitle'] == '(in foo v2.0)'
|
||||||
assert rn[0].astext() == 'foo'
|
assert rn[0].astext() == 'foo'
|
||||||
|
|
||||||
# create unresolvable nodes and check None return value
|
# create unresolvable nodes and check None return value
|
||||||
assert reference_check('py', 'foo', 'module1.func', 'foo') is None
|
assert reference_check(app, 'py', 'foo', 'module1.func', 'foo') is None
|
||||||
assert reference_check('py', 'func', 'foo', 'foo') is None
|
assert reference_check(app, 'py', 'func', 'foo', 'foo') is None
|
||||||
assert reference_check('py', 'func', 'foo', 'foo') is None
|
assert reference_check(app, 'py', 'func', 'foo', 'foo') is None
|
||||||
|
|
||||||
# check handling of prefixes
|
# check handling of prefixes
|
||||||
|
|
||||||
# prefix given, target found: prefix is stripped
|
# prefix given, target found: prefix is stripped
|
||||||
rn = reference_check('py', 'mod', 'py3k:module2', 'py3k:module2')
|
rn = reference_check(app, 'py', 'mod', 'py3k:module2', 'py3k:module2')
|
||||||
assert rn[0].astext() == 'module2'
|
assert rn[0].astext() == 'module2'
|
||||||
|
|
||||||
# prefix given, but not in title: nothing stripped
|
# prefix given, but not in title: nothing stripped
|
||||||
rn = reference_check('py', 'mod', 'py3k:module2', 'module2')
|
rn = reference_check(app, 'py', 'mod', 'py3k:module2', 'module2')
|
||||||
assert rn[0].astext() == 'module2'
|
assert rn[0].astext() == 'module2'
|
||||||
|
|
||||||
# prefix given, but explicit: nothing stripped
|
# prefix given, but explicit: nothing stripped
|
||||||
rn = reference_check('py', 'mod', 'py3k:module2', 'py3k:module2',
|
rn = reference_check(app, 'py', 'mod', 'py3k:module2', 'py3k:module2',
|
||||||
refexplicit=True)
|
refexplicit=True)
|
||||||
assert rn[0].astext() == 'py3k:module2'
|
assert rn[0].astext() == 'py3k:module2'
|
||||||
|
|
||||||
@ -146,23 +146,116 @@ def test_missing_reference(tempdir, app, status, warning):
|
|||||||
assert contnode[0].astext() == 'py3k:unknown'
|
assert contnode[0].astext() == 'py3k:unknown'
|
||||||
|
|
||||||
# check relative paths
|
# check relative paths
|
||||||
rn = reference_check('py', 'mod', 'py3krel:module1', 'foo')
|
rn = reference_check(app, 'py', 'mod', 'py3krel:module1', 'foo')
|
||||||
assert rn['refuri'] == 'py3k/foo.html#module-module1'
|
assert rn['refuri'] == 'py3k/foo.html#module-module1'
|
||||||
|
|
||||||
rn = reference_check('py', 'mod', 'py3krelparent:module1', 'foo')
|
rn = reference_check(app, 'py', 'mod', 'py3krelparent:module1', 'foo')
|
||||||
assert rn['refuri'] == '../../py3k/foo.html#module-module1'
|
assert rn['refuri'] == '../../py3k/foo.html#module-module1'
|
||||||
|
|
||||||
rn = reference_check('py', 'mod', 'py3krel:module1', 'foo', refdoc='sub/dir/test')
|
rn = reference_check(app, 'py', 'mod', 'py3krel:module1', 'foo', refdoc='sub/dir/test')
|
||||||
assert rn['refuri'] == '../../py3k/foo.html#module-module1'
|
assert rn['refuri'] == '../../py3k/foo.html#module-module1'
|
||||||
|
|
||||||
rn = reference_check('py', 'mod', 'py3krelparent:module1', 'foo', refdoc='sub/dir/test')
|
rn = reference_check(app, 'py', 'mod', 'py3krelparent:module1', 'foo',
|
||||||
|
refdoc='sub/dir/test')
|
||||||
assert rn['refuri'] == '../../../../py3k/foo.html#module-module1'
|
assert rn['refuri'] == '../../../../py3k/foo.html#module-module1'
|
||||||
|
|
||||||
# check refs of standard domain
|
# check refs of standard domain
|
||||||
rn = reference_check('std', 'doc', 'docname', 'docname')
|
rn = reference_check(app, 'std', 'doc', 'docname', 'docname')
|
||||||
assert rn['refuri'] == 'https://docs.python.org/docname.html'
|
assert rn['refuri'] == 'https://docs.python.org/docname.html'
|
||||||
|
|
||||||
|
|
||||||
|
def test_missing_reference_pydomain(tempdir, app, status, warning):
|
||||||
|
inv_file = tempdir / 'inventory'
|
||||||
|
inv_file.write_bytes(inventory_v2)
|
||||||
|
app.config.intersphinx_mapping = {
|
||||||
|
'https://docs.python.org/': inv_file,
|
||||||
|
}
|
||||||
|
app.config.intersphinx_cache_limit = 0
|
||||||
|
|
||||||
|
# load the inventory and check if it's done correctly
|
||||||
|
load_mappings(app)
|
||||||
|
|
||||||
|
# no context data
|
||||||
|
kwargs = {}
|
||||||
|
node, contnode = fake_node('py', 'func', 'func', 'func()', **kwargs)
|
||||||
|
rn = missing_reference(app, app.env, node, contnode)
|
||||||
|
assert rn is None
|
||||||
|
|
||||||
|
# py:module context helps to search objects
|
||||||
|
kwargs = {'py:module': 'module1'}
|
||||||
|
node, contnode = fake_node('py', 'func', 'func', 'func()', **kwargs)
|
||||||
|
rn = missing_reference(app, app.env, node, contnode)
|
||||||
|
assert rn.astext() == 'func()'
|
||||||
|
|
||||||
|
|
||||||
|
def test_missing_reference_stddomain(tempdir, app, status, warning):
|
||||||
|
inv_file = tempdir / 'inventory'
|
||||||
|
inv_file.write_bytes(inventory_v2)
|
||||||
|
app.config.intersphinx_mapping = {
|
||||||
|
'https://docs.python.org/': inv_file,
|
||||||
|
}
|
||||||
|
app.config.intersphinx_cache_limit = 0
|
||||||
|
|
||||||
|
# load the inventory and check if it's done correctly
|
||||||
|
load_mappings(app)
|
||||||
|
|
||||||
|
# no context data
|
||||||
|
kwargs = {}
|
||||||
|
node, contnode = fake_node('std', 'option', '-l', '-l', **kwargs)
|
||||||
|
rn = missing_reference(app, app.env, node, contnode)
|
||||||
|
assert rn is None
|
||||||
|
|
||||||
|
# std:program context helps to search objects
|
||||||
|
kwargs = {'std:program': 'ls'}
|
||||||
|
node, contnode = fake_node('std', 'option', '-l', 'ls -l', **kwargs)
|
||||||
|
rn = missing_reference(app, app.env, node, contnode)
|
||||||
|
assert rn.astext() == 'ls -l'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-intersphinx-cppdomain')
|
||||||
|
def test_missing_reference_cppdomain(tempdir, app, status, warning):
|
||||||
|
inv_file = tempdir / 'inventory'
|
||||||
|
inv_file.write_bytes(inventory_v2)
|
||||||
|
app.config.intersphinx_mapping = {
|
||||||
|
'https://docs.python.org/': inv_file,
|
||||||
|
}
|
||||||
|
app.config.intersphinx_cache_limit = 0
|
||||||
|
|
||||||
|
# load the inventory and check if it's done correctly
|
||||||
|
load_mappings(app)
|
||||||
|
|
||||||
|
app.build()
|
||||||
|
html = (app.outdir / 'index.html').text()
|
||||||
|
assert ('<a class="reference external"'
|
||||||
|
' href="https://docs.python.org/index.html#cpp_foo_bar"'
|
||||||
|
' title="(in foo v2.0)"><code class="xref cpp cpp-class docutils literal">'
|
||||||
|
'<span class="pre">Bar</span></code></a>' in html)
|
||||||
|
|
||||||
|
|
||||||
|
def test_missing_reference_jsdomain(tempdir, app, status, warning):
|
||||||
|
inv_file = tempdir / 'inventory'
|
||||||
|
inv_file.write_bytes(inventory_v2)
|
||||||
|
app.config.intersphinx_mapping = {
|
||||||
|
'https://docs.python.org/': inv_file,
|
||||||
|
}
|
||||||
|
app.config.intersphinx_cache_limit = 0
|
||||||
|
|
||||||
|
# load the inventory and check if it's done correctly
|
||||||
|
load_mappings(app)
|
||||||
|
|
||||||
|
# no context data
|
||||||
|
kwargs = {}
|
||||||
|
node, contnode = fake_node('js', 'meth', 'baz', 'baz()', **kwargs)
|
||||||
|
rn = missing_reference(app, app.env, node, contnode)
|
||||||
|
assert rn is None
|
||||||
|
|
||||||
|
# js:module and js:object context helps to search objects
|
||||||
|
kwargs = {'js:module': 'foo', 'js:object': 'bar'}
|
||||||
|
node, contnode = fake_node('js', 'meth', 'baz', 'baz()', **kwargs)
|
||||||
|
rn = missing_reference(app, app.env, node, contnode)
|
||||||
|
assert rn.astext() == 'baz()'
|
||||||
|
|
||||||
|
|
||||||
def test_load_mappings_warnings(tempdir, app, status, warning):
|
def test_load_mappings_warnings(tempdir, app, status, warning):
|
||||||
"""
|
"""
|
||||||
load_mappings issues a warning if new-style mapping
|
load_mappings issues a warning if new-style mapping
|
||||||
|
@ -34,8 +34,15 @@ module1 py:module 0 foo.html#module-module1 Long Module desc
|
|||||||
module2 py:module 0 foo.html#module-$ -
|
module2 py:module 0 foo.html#module-$ -
|
||||||
module1.func py:function 1 sub/foo.html#$ -
|
module1.func py:function 1 sub/foo.html#$ -
|
||||||
CFunc c:function 2 cfunc.html#CFunc -
|
CFunc c:function 2 cfunc.html#CFunc -
|
||||||
|
foo::Bar cpp:class 1 index.html#cpp_foo_bar -
|
||||||
|
foo::Bar::baz cpp:function 1 index.html#cpp_foo_bar_baz -
|
||||||
a term std:term -1 glossary.html#term-a-term -
|
a term std:term -1 glossary.html#term-a-term -
|
||||||
|
ls.-l std:cmdoption 1 index.html#cmdoption-ls-l -
|
||||||
docname std:doc -1 docname.html -
|
docname std:doc -1 docname.html -
|
||||||
|
foo js:module 1 index.html#foo -
|
||||||
|
foo.bar js:class 1 index.html#foo.bar -
|
||||||
|
foo.bar.baz js:method 1 index.html#foo.bar.baz -
|
||||||
|
foo.bar.qux js:data 1 index.html#foo.bar.qux -
|
||||||
a term including:colon std:term -1 glossary.html#term-a-term-including-colon -
|
a term including:colon std:term -1 glossary.html#term-a-term-including-colon -
|
||||||
'''.encode('utf-8'))
|
'''.encode('utf-8'))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user