Merge branch 'master' into refactor_highlighter

This commit is contained in:
Takeshi KOMIYA 2018-07-29 11:21:36 +09:00 committed by GitHub
commit 104bd42f51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1838 additions and 342 deletions

View File

@ -24,8 +24,12 @@ matrix:
env:
- TOXENV=py36
- PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
- python: 'nightly'
- python: '3.7'
env: TOXENV=py37
dist: xenial
sudo: true
- python: 'nightly'
env: TOXENV=py38
- python: '3.6'
env: TOXENV=docs
- python: '3.6'

View File

@ -112,6 +112,7 @@ Deprecated
* ``sphinx.ext.mathbase.eqref`` node is deprecated
* ``sphinx.ext.mathbase.is_in_section_title()`` is deprecated
* ``sphinx.ext.mathbase.MathDomain`` is deprecated
* ``sphinx.ext.mathbase.setup_math()`` is deprecated
* ``sphinx.highlighting.PygmentsBridge.unhighlight()`` is deprecated
* The ``trim_doctest_flags`` argument of ``sphinx.highlighting.PygmentsBridge``
is deprecated
@ -176,6 +177,7 @@ Features added
* #4976: ``SphinxLoggerAdapter.info()`` now supports ``location`` parameter
* #5122: setuptools: support nitpicky option
* #2820: autoclass directive supports nested class
* Add ``app.add_html_math_renderer()`` to register a math renderer for HTML
* Apply :confval:`trim_doctest_flags` to all builders (cf. text, manpages)
Bugs fixed

View File

@ -93,6 +93,8 @@ package.
.. automethod:: Sphinx.add_html_theme(name, theme_path)
.. automethod:: Sphinx.add_html_math_renderer(name, inline_renderers, block_renderers)
.. automethod:: Sphinx.add_message_catalog(catalog, locale_dir)
.. automethod:: Sphinx.is_parallel_allowed(typ)

View File

@ -147,6 +147,11 @@ The following is a list of deprecated interface.
- 3.0
- ``sphinx.domains.math.MathDomain``
* - ``sphinx.ext.mathbase.setup_math()``
- 1.8
- 3.0
- :meth:`~sphinx.application.Sphinx.add_html_math_renderer()`
* - ``sphinx.ext.mathbase.is_in_section_title()``
- 1.8
- 3.0

View File

@ -773,6 +773,35 @@ documentation on :ref:`intl` for details.
Added ``{path}`` and ``{basename}`` tokens.
.. _math-options:
Options for Math
----------------
These options influence Math notations.
.. confval:: math_number_all
Set this option to ``True`` if you want all displayed math to be numbered.
The default is ``False``.
.. confval:: math_eqref_format
A string that are used for format of label of references to equations.
As a special character, ``{number}`` will be replaced to equaition number.
Example: ``'Eq.{number}'`` is rendered as ``Eq.10``
.. confval:: math_numfig
If ``True``, displayed math equations are numbered across pages when
:confval:`numfig` is enabled. The :confval:`numfig_secnum_depth` setting
is respected. The :rst:role:`eq`, not :rst:role:`numref`, role
must be used to reference equation numbers. Default is ``True``.
.. versionadded:: 1.7
.. _html-options:
Options for HTML output
@ -1290,6 +1319,13 @@ that use Sphinx's HTMLWriter class.
.. versionadded:: 1.3
.. confval:: html_math_renderer
The name of math_renderer extension for HTML output. The default is
``'mathjax'``.
.. versionadded:: 1.8
.. confval:: html_experimental_html5_writer
Output is processed with HTML5 writer. This feature needs docutils 0.13 or

View File

@ -2,123 +2,20 @@
.. _math-support:
Math support in Sphinx
======================
Math support for HTML outputs in Sphinx
=======================================
.. module:: sphinx.ext.mathbase
:synopsis: Common math support for imgmath and mathjax / jsmath.
.. versionadded:: 0.5
.. versionchanged:: 1.8
Math support for non-HTML builders is integrated to sphinx-core.
So mathbase extension is no longer needed.
Since mathematical notation isn't natively supported by HTML in any way, Sphinx
supports math in documentation with several extensions.
The basic math support is contained in :mod:`sphinx.ext.mathbase`. Other math
support extensions should, if possible, reuse that support too.
.. note::
:mod:`.mathbase` is not meant to be added to the :confval:`extensions` config
value, instead, use either :mod:`sphinx.ext.imgmath` or
:mod:`sphinx.ext.mathjax` as described below.
The input language for mathematics is LaTeX markup. This is the de-facto
standard for plain-text math notation and has the added advantage that no
further translation is necessary when building LaTeX output.
Keep in mind that when you put math markup in **Python docstrings** read by
:mod:`autodoc <sphinx.ext.autodoc>`, you either have to double all backslashes,
or use Python raw strings (``r"raw"``).
:mod:`.mathbase` provides the following config values:
.. confval:: math_number_all
Set this option to ``True`` if you want all displayed math to be numbered.
The default is ``False``.
.. confval:: math_eqref_format
A string that are used for format of label of references to equations.
As a special character, ``{number}`` will be replaced to equaition number.
Example: ``'Eq.{number}'`` is rendered as ``Eq.10``
.. confval:: math_numfig
If ``True``, displayed math equations are numbered across pages when
:confval:`numfig` is enabled. The :confval:`numfig_secnum_depth` setting
is respected. The :rst:role:`eq`, not :rst:role:`numref`, role
must be used to reference equation numbers. Default is ``True``.
.. versionadded:: 1.7
:mod:`.mathbase` defines these new markup elements:
.. rst:role:: math
Role for inline math. Use like this::
Since Pythagoras, we know that :math:`a^2 + b^2 = c^2`.
.. rst:directive:: math
Directive for displayed math (math that takes the whole line for itself).
The directive supports multiple equations, which should be separated by a
blank line::
.. math::
(a + b)^2 = a^2 + 2ab + b^2
(a - b)^2 = a^2 - 2ab + b^2
In addition, each single equation is set within a ``split`` environment,
which means that you can have multiple aligned lines in an equation,
aligned at ``&`` and separated by ``\\``::
.. math::
(a + b)^2 &= (a + b)(a + b) \\
&= a^2 + 2ab + b^2
For more details, look into the documentation of the `AmSMath LaTeX
package`_.
When the math is only one line of text, it can also be given as a directive
argument::
.. math:: (a + b)^2 = a^2 + 2ab + b^2
Normally, equations are not numbered. If you want your equation to get a
number, use the ``label`` option. When given, it selects an internal label
for the equation, by which it can be cross-referenced, and causes an equation
number to be issued. See :rst:role:`eq` for an example. The numbering
style depends on the output format.
There is also an option ``nowrap`` that prevents any wrapping of the given
math in a math environment. When you give this option, you must make sure
yourself that the math is properly set up. For example::
.. math::
:nowrap:
\begin{eqnarray}
y & = & ax^2 + bx + c \\
f(x) & = & x^2 + 2xy + y^2
\end{eqnarray}
.. rst:role:: eq
Role for cross-referencing equations via their label. Example::
.. math:: e^{i\pi} + 1 = 0
:label: euler
Euler's identity, equation :eq:`euler`, was elected one of the most
beautiful mathematical formulas.
gives a math support to HTML document with several extensions.
:mod:`sphinx.ext.imgmath` -- Render math as images
--------------------------------------------------
@ -299,4 +196,3 @@ package jsMath_. It provides this config value:
.. _MathJax: https://www.mathjax.org/
.. _jsMath: http://www.math.union.edu/~dpvc/jsmath/
.. _preview-latex package: https://www.gnu.org/software/auctex/preview-latex.html
.. _AmSMath LaTeX package: https://www.ams.org/publications/authors/tex/amslatex

View File

@ -1005,9 +1005,63 @@ this reason, the following directive exists:
Math
----
.. todo:: Move this in here.
The input language for mathematics is LaTeX markup. This is the de-facto
standard for plain-text math notation and has the added advantage that no
further translation is necessary when building LaTeX output.
See :ref:`math-support`.
Keep in mind that when you put math markup in **Python docstrings** read by
:mod:`autodoc <sphinx.ext.autodoc>`, you either have to double all backslashes,
or use Python raw strings (``r"raw"``).
.. rst:directive:: math
Directive for displayed math (math that takes the whole line for itself).
The directive supports multiple equations, which should be separated by a
blank line::
.. math::
(a + b)^2 = a^2 + 2ab + b^2
(a - b)^2 = a^2 - 2ab + b^2
In addition, each single equation is set within a ``split`` environment,
which means that you can have multiple aligned lines in an equation,
aligned at ``&`` and separated by ``\\``::
.. math::
(a + b)^2 &= (a + b)(a + b) \\
&= a^2 + 2ab + b^2
For more details, look into the documentation of the `AmSMath LaTeX
package`_.
When the math is only one line of text, it can also be given as a directive
argument::
.. math:: (a + b)^2 = a^2 + 2ab + b^2
Normally, equations are not numbered. If you want your equation to get a
number, use the ``label`` option. When given, it selects an internal label
for the equation, by which it can be cross-referenced, and causes an equation
number to be issued. See :rst:role:`eq` for an example. The numbering
style depends on the output format.
There is also an option ``nowrap`` that prevents any wrapping of the given
math in a math environment. When you give this option, you must make sure
yourself that the math is properly set up. For example::
.. math::
:nowrap:
\begin{eqnarray}
y & = & ax^2 + bx + c \\
f(x) & = & x^2 + 2xy + y^2
\end{eqnarray}
.. _AmSMath LaTeX package: https://www.ams.org/publications/authors/tex/amslatex
Grammar production displays

View File

@ -277,6 +277,26 @@ The following role creates a cross-reference to a term in a
during build.
Math
----
.. rst:role:: math
Role for inline math. Use like this::
Since Pythagoras, we know that :math:`a^2 + b^2 = c^2`.
.. rst:role:: eq
Role for cross-referencing equations via their label. Example::
.. math:: e^{i\pi} + 1 = 0
:label: euler
Euler's identity, equation :eq:`euler`, was elected one of the most
beautiful mathematical formulas.
Other semantic markup
---------------------

View File

@ -1221,6 +1221,20 @@ class Sphinx(object):
logger.debug('[app] adding HTML theme: %r, %r', name, theme_path)
self.html_themes[name] = theme_path
def add_html_math_renderer(self, name, inline_renderers=None, block_renderers=None):
# type: (unicode, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None
"""Register a math renderer for HTML.
The *name* is a name of the math renderer. Both *inline_renderers* and
*block_renderes* are used as visitor functions for HTML writer.
*inline_renderers* is used for inline math node (``nodes.math`)). The
another is used for block math node (``nodes.math_block``). About
visitor functions, see :meth:`add_node` for more details.
.. versionadded:: 1.8
"""
self.registry.add_html_math_renderer(name, inline_renderers, block_renderers)
def add_message_catalog(self, catalog, locale_dir):
# type: (unicode, unicode) -> None
"""Register a message catalog.

View File

@ -36,7 +36,7 @@ from sphinx.deprecation import RemovedInSphinx20Warning, RemovedInSphinx30Warnin
from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.environment.adapters.indexentries import IndexEntries
from sphinx.environment.adapters.toctree import TocTree
from sphinx.errors import ThemeError
from sphinx.errors import ConfigError, ThemeError
from sphinx.highlighting import PygmentsBridge
from sphinx.locale import _, __
from sphinx.search import js_index
@ -437,6 +437,27 @@ class StandaloneHTMLBuilder(Builder):
else:
return HTMLTranslator
@property
def math_renderer_name(self):
# type: () -> unicode
name = self.get_builder_config('math_renderer', 'html')
if name is not None:
# use given name
return name
else:
# not given: choose a math_renderer from registered ones as possible
renderers = list(self.app.registry.html_inline_math_renderers)
if len(renderers) == 1:
# only default math_renderer (mathjax) is registered
return renderers[0]
elif len(renderers) == 2:
# default and another math_renderer are registered; prior the another
renderers.remove('mathjax')
return renderers[0]
else:
# many math_renderers are registered. can't choose automatically!
return None
def get_outdated_docs(self):
# type: () -> Iterator[unicode]
try:
@ -1624,6 +1645,19 @@ def setup_js_tag_helper(app, pagename, templatexname, context, doctree):
context['js_tag'] = js_tag
def validate_math_renderer(app):
# type: (Sphinx) -> None
if app.builder.format != 'html':
return
name = app.builder.math_renderer_name # type: ignore
if name is None:
raise ConfigError(__('Many math_renderers are registered. '
'But no math_renderer is selected.'))
elif name not in app.registry.html_inline_math_renderers:
raise ConfigError(__('Unknown math_renderer %r is given.') % name)
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
# builders
@ -1673,12 +1707,17 @@ def setup(app):
app.add_config_value('html_scaled_image_link', True, 'html')
app.add_config_value('html_experimental_html5_writer', None, 'html')
app.add_config_value('html_baseurl', '', 'html')
app.add_config_value('html_math_renderer', None, 'env')
# event handlers
app.connect('config-inited', convert_html_css_files)
app.connect('config-inited', convert_html_js_files)
app.connect('builder-inited', validate_math_renderer)
app.connect('html-page-context', setup_js_tag_helper)
# load default math renderer
app.setup_extension('sphinx.ext.mathjax')
return {
'version': 'builtin',
'parallel_read_safe': True,

View File

@ -22,9 +22,9 @@ from docutils import nodes
from six import text_type
import sphinx
from sphinx.errors import SphinxError, ExtensionError
from sphinx.errors import SphinxError
from sphinx.ext.mathbase import get_node_equation_number
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
from sphinx.ext.mathbase import wrap_displaymath
from sphinx.locale import _, __
from sphinx.util import logging
from sphinx.util.osutil import ensuredir, ENOENT, cd
@ -349,10 +349,9 @@ def html_visit_displaymath(self, node):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
try:
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
except ExtensionError:
raise ExtensionError('sphinx.ext.imgmath: other math package is already loaded')
app.add_html_math_renderer('imgmath',
(html_visit_math, None),
(html_visit_displaymath, None))
app.add_config_value('imgmath_image_format', 'png', 'html')
app.add_config_value('imgmath_dvipng', 'dvipng', 'html')

View File

@ -15,7 +15,6 @@ from docutils import nodes
import sphinx
from sphinx.errors import ExtensionError
from sphinx.ext.mathbase import get_node_equation_number
from sphinx.ext.mathbase import setup_math as mathbase_setup
from sphinx.locale import _
if False:
@ -61,7 +60,9 @@ def html_visit_displaymath(self, node):
def builder_inited(app):
# type: (Sphinx) -> None
if not app.config.jsmath_path:
if app.builder.format != 'html' or app.builder.math_renderer_name != 'jsmath': # type: ignore # NOQA
pass
elif not app.config.jsmath_path:
raise ExtensionError('jsmath_path config value must be set for the '
'jsmath extension to work')
if app.builder.format == 'html':
@ -70,10 +71,9 @@ def builder_inited(app):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
try:
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
except ExtensionError:
raise ExtensionError('sphinx.ext.jsmath: other math package is already loaded')
app.add_html_math_renderer('jsmath',
(html_visit_math, None),
(html_visit_displaymath, None))
app.add_config_value('jsmath_path', '', False)
app.connect('builder-inited', builder_inited)

View File

@ -13,7 +13,7 @@ import warnings
from docutils import nodes
from sphinx.addnodes import math, math_block as displaymath
from sphinx.addnodes import math, math_block as displaymath # NOQA # to keep compatibility
from sphinx.builders.latex.nodes import math_reference as eqref # NOQA # to keep compatibility
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.domains.math import MathDomain # NOQA # to keep compatibility
@ -44,7 +44,7 @@ def get_node_equation_number(writer, node):
return number
def wrap_displaymath(math, label, numbering):
def wrap_displaymath(text, label, numbering):
# type: (unicode, unicode, bool) -> unicode
def is_equation(part):
# type: (unicode) -> unicode
@ -56,7 +56,7 @@ def wrap_displaymath(math, label, numbering):
labeldef = r'\label{%s}' % label
numbering = True
parts = list(filter(is_equation, math.split('\n\n')))
parts = list(filter(is_equation, text.split('\n\n')))
equations = []
if len(parts) == 0:
return ''
@ -97,8 +97,9 @@ def is_in_section_title(node):
def setup_math(app, htmlinlinevisitors, htmldisplayvisitors):
# type: (Sphinx, Tuple[Callable, Any], Tuple[Callable, Any]) -> None
app.add_node(math, override=True,
html=htmlinlinevisitors)
app.add_node(displaymath, override=True,
html=htmldisplayvisitors)
# type: (Sphinx, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None
warnings.warn('setup_math() is deprecated. '
'Please use app.add_html_math_renderer() instead.',
RemovedInSphinx30Warning)
app.add_html_math_renderer('unknown', htmlinlinevisitors, htmldisplayvisitors)

View File

@ -16,7 +16,6 @@ from docutils import nodes
import sphinx
from sphinx.errors import ExtensionError
from sphinx.ext.mathbase import get_node_equation_number
from sphinx.ext.mathbase import setup_math as mathbase_setup
from sphinx.locale import _
if False:
@ -69,7 +68,9 @@ def html_visit_displaymath(self, node):
def builder_inited(app):
# type: (Sphinx) -> None
if not app.config.mathjax_path:
if app.builder.format != 'html' or app.builder.math_renderer_name != 'mathjax': # type: ignore # NOQA
pass
elif not app.config.mathjax_path:
raise ExtensionError('mathjax_path config value must be set for the '
'mathjax extension to work')
if app.builder.format == 'html':
@ -81,10 +82,9 @@ def builder_inited(app):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
try:
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
except ExtensionError:
raise ExtensionError('sphinx.ext.mathjax: other math package is already loaded')
app.add_html_math_renderer('mathjax',
(html_visit_math, None),
(html_visit_displaymath, None))
# more information for mathjax secure url is here:
# https://docs.mathjax.org/en/latest/start.html#secure-access-to-the-cdn

View File

@ -92,6 +92,11 @@ class SphinxComponentRegistry(object):
#: a dict of node class -> tuple of figtype and title_getter function
self.enumerable_nodes = {} # type: Dict[nodes.Node, Tuple[unicode, TitleGetter]]
#: HTML inline and block math renderers
#: a dict of name -> tuple of visit function and depart function
self.html_inline_math_renderers = {} # type: Dict[unicode, Tuple[Callable, Callable]] # NOQA
self.html_block_math_renderers = {} # type: Dict[unicode, Tuple[Callable, Callable]] # NOQA
#: js_files; list of JS paths or URLs
self.js_files = [] # type: List[Tuple[unicode, Dict[unicode, unicode]]]
@ -439,6 +444,16 @@ class SphinxComponentRegistry(object):
raise ExtensionError(__('enumerable_node %r already registered') % node)
self.enumerable_nodes[node] = (figtype, title_getter)
def add_html_math_renderer(self, name, inline_renderers, block_renderers):
# type: (unicode, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None
logger.debug('[app] adding html_math_renderer: %s, %r, %r',
name, inline_renderers, block_renderers)
if name in self.html_inline_math_renderers:
raise ExtensionError(__('math renderer %s is already registred') % name)
self.html_inline_math_renderers[name] = inline_renderers
self.html_block_math_renderers[name] = block_renderers
def load_extension(self, app, extname):
# type: (Sphinx, unicode) -> None
"""Load a Sphinx extension."""

View File

@ -21,7 +21,7 @@ from distutils.errors import DistutilsOptionError, DistutilsExecError
from six import StringIO, string_types
from sphinx.application import Sphinx
from sphinx.cmdline import handle_exception
from sphinx.cmd.build import handle_exception
from sphinx.util.console import nocolor, color_terminal
from sphinx.util.docutils import docutils_namespace, patch_docutils
from sphinx.util.osutil import abspath

View File

@ -1,6 +1,6 @@
;; -*- coding: utf-8; mode: Lisp; -*-
;; style file for xindy
;; filename: cyrLICRutf8.xdy
;; filename: LICRcyr2utf8.xdy
;; description: style file for xindy which maps back LaTeX Internal
;; Character Representation of Cyrillic to utf-8
;; usage: for use with pdflatex produced .idx files.

View File

@ -0,0 +1,236 @@
;; style file for xindy
;; filename: LICRlatin2utf8.xdy
;; description: style file for xindy which maps back LaTeX Internal
;; Character Representation of letters (as arising in .idx index
;; file) to UTF-8 encoding for correct sorting by xindy.
;; usage: for use with the pdflatex engine,
;; *not* for use with xelatex or lualatex.
;;
;; This is based upon xindy's distributed file tex/inputenc/utf8.xdy.
;; The modifications include:
;;
;; - Updates for compatibility with current LaTeX macro encoding.
;;
;; - Systematic usage of the \IeC {...} mark-up, because mark-up in
;; tex/inputenc/utf8.xdy was using it on seemingly random basis, and
;; Sphinx coercing of xindy usability for both Latin and Cyrillic scripts
;; with pdflatex requires its systematic presence here.
;;
;; - Support for some extra letters: Ÿ, Ŋ, ŋ, Œ, œ, IJ, ij, ȷ and ẞ.
;;
;; Indeed Sphinx needs to support for pdflatex engine all Unicode letters
;; available in TeX T1 font encoding. The above letters are found in
;; that encoding but not in the Latin1, 2, 3 charsets which are those
;; covered by original tex/inputenc/utf8.xdy.
;;
;; - There is a problem that ȷ is not supported out-of-the box by LaTeX
;; with inputenc, one must add explicitely
;; \DeclareUnicodeCharacter{0237}{\j}
;; to preamble of LaTeX document. However this character is not supported
;; by the TeX "times" font used by default by Sphinx for pdflatex engine.
;;
;; - ẞ needs \DeclareUnicodeCharacter{1E9E}{\SS} (but ß needs no extra set-up).
;;
;; - U+02DB (˛) and U+02D9 (˙) are also not supported by inputenc
;; out of the box and require
;; \DeclareUnicodeCharacter{02DB}{\k{}}
;; \DeclareUnicodeCharacter{02D9}{\.{}}
;; to be added to preamble.
;;
;; - U+0127 ħ and U+0126 Ħ are absent from TeX T1+TS1 font encodings.
;;
;; - Characters Ŋ and ŋ are not supported by TeX font "times" used by
;; default by Sphinx for pdflatex engine but they are supported by
;; some TeX fonts, in particular by the default LaTeX font for T1
;; encoding.
;;
;; - " and ~ must be escaped as ~" and resp. ~~ in xindy merge rules.
;;
;; Contributed by the Sphinx team, July 2018.
;;
;; See sphinx.xdy for superior figures, as they are escaped by LaTeX writer.
(merge-rule "\IeC {\textonesuperior }" "¹" :string)
(merge-rule "\IeC {\texttwosuperior }" "²" :string)
(merge-rule "\IeC {\textthreesuperior }" "³" :string)
(merge-rule "\IeC {\'a}" "á" :string)
(merge-rule "\IeC {\'A}" "Á" :string)
(merge-rule "\IeC {\`a}" "à" :string)
(merge-rule "\IeC {\`A}" "À" :string)
(merge-rule "\IeC {\^a}" "â" :string)
(merge-rule "\IeC {\^A}" "Â" :string)
(merge-rule "\IeC {\~"a}" "ä" :string)
(merge-rule "\IeC {\~"A}" "Ä" :string)
(merge-rule "\IeC {\~~a}" "ã" :string)
(merge-rule "\IeC {\~~A}" "Ã" :string)
(merge-rule "\IeC {\c c}" "ç" :string)
(merge-rule "\IeC {\c C}" "Ç" :string)
(merge-rule "\IeC {\'c}" "ć" :string)
(merge-rule "\IeC {\'C}" "Ć" :string)
(merge-rule "\IeC {\^c}" "ĉ" :string)
(merge-rule "\IeC {\^C}" "Ĉ" :string)
(merge-rule "\IeC {\.c}" "ċ" :string)
(merge-rule "\IeC {\.C}" "Ċ" :string)
(merge-rule "\IeC {\c s}" "ş" :string)
(merge-rule "\IeC {\c S}" "Ş" :string)
(merge-rule "\IeC {\c t}" "ţ" :string)
(merge-rule "\IeC {\c T}" "Ţ" :string)
(merge-rule "\IeC {\-}" "­" :string); soft hyphen
(merge-rule "\IeC {\textdiv }" "÷" :string)
(merge-rule "\IeC {\'e}" "é" :string)
(merge-rule "\IeC {\'E}" "É" :string)
(merge-rule "\IeC {\`e}" "è" :string)
(merge-rule "\IeC {\`E}" "È" :string)
(merge-rule "\IeC {\^e}" "ê" :string)
(merge-rule "\IeC {\^E}" "Ê" :string)
(merge-rule "\IeC {\~"e}" "ë" :string)
(merge-rule "\IeC {\~"E}" "Ë" :string)
(merge-rule "\IeC {\^g}" "ĝ" :string)
(merge-rule "\IeC {\^G}" "Ĝ" :string)
(merge-rule "\IeC {\.g}" "ġ" :string)
(merge-rule "\IeC {\.G}" "Ġ" :string)
(merge-rule "\IeC {\^h}" "ĥ" :string)
(merge-rule "\IeC {\^H}" "Ĥ" :string)
(merge-rule "\IeC {\H o}" "ő" :string)
(merge-rule "\IeC {\H O}" "Ő" :string)
(merge-rule "\IeC {\textacutedbl }" "˝" :string)
(merge-rule "\IeC {\H u}" "ű" :string)
(merge-rule "\IeC {\H U}" "Ű" :string)
(merge-rule "\IeC {\ae }" "æ" :string)
(merge-rule "\IeC {\AE }" "Æ" :string)
(merge-rule "\IeC {\textcopyright }" "©" :string)
(merge-rule "\IeC {\c \ }" "¸" :string)
(merge-rule "\IeC {\dh }" "ð" :string)
(merge-rule "\IeC {\DH }" "Ð" :string)
(merge-rule "\IeC {\dj }" "đ" :string)
(merge-rule "\IeC {\DJ }" "Đ" :string)
(merge-rule "\IeC {\guillemotleft }" "«" :string)
(merge-rule "\IeC {\guillemotright }" "»" :string)
(merge-rule "\IeC {\'\i }" "í" :string)
(merge-rule "\IeC {\`\i }" "ì" :string)
(merge-rule "\IeC {\^\i }" "î" :string)
(merge-rule "\IeC {\~"\i }" "ï" :string)
(merge-rule "\IeC {\i }" "ı" :string)
(merge-rule "\IeC {\^\j }" "ĵ" :string)
(merge-rule "\IeC {\k {}}" "˛" :string)
(merge-rule "\IeC {\l }" "ł" :string)
(merge-rule "\IeC {\L }" "Ł" :string)
(merge-rule "\IeC {\nobreakspace }" " " :string)
(merge-rule "\IeC {\o }" "ø" :string)
(merge-rule "\IeC {\O }" "Ø" :string)
(merge-rule "\IeC {\textsterling }" "£" :string)
(merge-rule "\IeC {\textparagraph }" "¶" :string)
(merge-rule "\IeC {\ss }" "ß" :string)
(merge-rule "\IeC {\textsection }" "§" :string)
(merge-rule "\IeC {\textbrokenbar }" "¦" :string)
(merge-rule "\IeC {\textcent }" "¢" :string)
(merge-rule "\IeC {\textcurrency }" "¤" :string)
(merge-rule "\IeC {\textdegree }" "°" :string)
(merge-rule "\IeC {\textexclamdown }" "¡" :string)
(merge-rule "\IeC {\texthbar }" "ħ" :string)
(merge-rule "\IeC {\textHbar }" "Ħ" :string)
(merge-rule "\IeC {\textonehalf }" "½" :string)
(merge-rule "\IeC {\textonequarter }" "¼" :string)
(merge-rule "\IeC {\textordfeminine }" "ª" :string)
(merge-rule "\IeC {\textordmasculine }" "º" :string)
(merge-rule "\IeC {\textperiodcentered }" "·" :string)
(merge-rule "\IeC {\textquestiondown }" "¿" :string)
(merge-rule "\IeC {\textregistered }" "®" :string)
(merge-rule "\IeC {\textthreequarters }" "¾" :string)
(merge-rule "\IeC {\textyen }" "¥" :string)
(merge-rule "\IeC {\th }" "þ" :string)
(merge-rule "\IeC {\TH }" "Þ" :string)
(merge-rule "\IeC {\'I}" "Í" :string)
(merge-rule "\IeC {\`I}" "Ì" :string)
(merge-rule "\IeC {\^I}" "Î" :string)
(merge-rule "\IeC {\~"I}" "Ï" :string)
(merge-rule "\IeC {\.I}" "İ" :string)
(merge-rule "\IeC {\^J}" "Ĵ" :string)
(merge-rule "\IeC {\k a}" "ą" :string)
(merge-rule "\IeC {\k A}" "Ą" :string)
(merge-rule "\IeC {\k e}" "ę" :string)
(merge-rule "\IeC {\k E}" "Ę" :string)
(merge-rule "\IeC {\'l}" "ĺ" :string)
(merge-rule "\IeC {\'L}" "Ĺ" :string)
(merge-rule "\IeC {\textlnot }" "¬" :string)
(merge-rule "\IeC {\textmu }" "µ" :string)
(merge-rule "\IeC {\'n}" "ń" :string)
(merge-rule "\IeC {\'N}" "Ń" :string)
(merge-rule "\IeC {\~~n}" "ñ" :string)
(merge-rule "\IeC {\~~N}" "Ñ" :string)
(merge-rule "\IeC {\'o}" "ó" :string)
(merge-rule "\IeC {\'O}" "Ó" :string)
(merge-rule "\IeC {\`o}" "ò" :string)
(merge-rule "\IeC {\`O}" "Ò" :string)
(merge-rule "\IeC {\^o}" "ô" :string)
(merge-rule "\IeC {\^O}" "Ô" :string)
(merge-rule "\IeC {\~"o}" "ö" :string)
(merge-rule "\IeC {\~"O}" "Ö" :string)
(merge-rule "\IeC {\~~o}" "õ" :string)
(merge-rule "\IeC {\~~O}" "Õ" :string)
(merge-rule "\IeC {\textpm }" "±" :string)
(merge-rule "\IeC {\r a}" "å" :string)
(merge-rule "\IeC {\r A}" "Å" :string)
(merge-rule "\IeC {\'r}" "ŕ" :string)
(merge-rule "\IeC {\'R}" "Ŕ" :string)
(merge-rule "\IeC {\r u}" "ů" :string)
(merge-rule "\IeC {\r U}" "Ů" :string)
(merge-rule "\IeC {\'s}" "ś" :string)
(merge-rule "\IeC {\'S}" "Ś" :string)
(merge-rule "\IeC {\^s}" "ŝ" :string)
(merge-rule "\IeC {\^S}" "Ŝ" :string)
(merge-rule "\IeC {\textasciidieresis }" "¨" :string)
(merge-rule "\IeC {\textasciimacron }" "¯" :string)
(merge-rule "\IeC {\.{}}" "˙" :string)
(merge-rule "\IeC {\textasciiacute }" "´" :string)
(merge-rule "\IeC {\texttimes }" "×" :string)
(merge-rule "\IeC {\u a}" "ă" :string)
(merge-rule "\IeC {\u A}" "Ă" :string)
(merge-rule "\IeC {\u g}" "ğ" :string)
(merge-rule "\IeC {\u G}" "Ğ" :string)
(merge-rule "\IeC {\textasciibreve }" "˘" :string)
(merge-rule "\IeC {\'u}" "ú" :string)
(merge-rule "\IeC {\'U}" "Ú" :string)
(merge-rule "\IeC {\`u}" "ù" :string)
(merge-rule "\IeC {\`U}" "Ù" :string)
(merge-rule "\IeC {\^u}" "û" :string)
(merge-rule "\IeC {\^U}" "Û" :string)
(merge-rule "\IeC {\~"u}" "ü" :string)
(merge-rule "\IeC {\~"U}" "Ü" :string)
(merge-rule "\IeC {\u u}" "ŭ" :string)
(merge-rule "\IeC {\u U}" "Ŭ" :string)
(merge-rule "\IeC {\v c}" "č" :string)
(merge-rule "\IeC {\v C}" "Č" :string)
(merge-rule "\IeC {\v d}" "ď" :string)
(merge-rule "\IeC {\v D}" "Ď" :string)
(merge-rule "\IeC {\v e}" "ě" :string)
(merge-rule "\IeC {\v E}" "Ě" :string)
(merge-rule "\IeC {\v l}" "ľ" :string)
(merge-rule "\IeC {\v L}" "Ľ" :string)
(merge-rule "\IeC {\v n}" "ň" :string)
(merge-rule "\IeC {\v N}" "Ň" :string)
(merge-rule "\IeC {\v r}" "ř" :string)
(merge-rule "\IeC {\v R}" "Ř" :string)
(merge-rule "\IeC {\v s}" "š" :string)
(merge-rule "\IeC {\v S}" "Š" :string)
(merge-rule "\IeC {\textasciicaron }" "ˇ" :string)
(merge-rule "\IeC {\v t}" "ť" :string)
(merge-rule "\IeC {\v T}" "Ť" :string)
(merge-rule "\IeC {\v z}" "ž" :string)
(merge-rule "\IeC {\v Z}" "Ž" :string)
(merge-rule "\IeC {\'y}" "ý" :string)
(merge-rule "\IeC {\'Y}" "Ý" :string)
(merge-rule "\IeC {\~"y}" "ÿ" :string)
(merge-rule "\IeC {\'z}" "ź" :string)
(merge-rule "\IeC {\'Z}" "Ź" :string)
(merge-rule "\IeC {\.z}" "ż" :string)
(merge-rule "\IeC {\.Z}" "Ż" :string)
;; letters not in Latin1, 2, 3 but available in TeX T1 font encoding
(merge-rule "\IeC {\~"Y}" "Ÿ" :string)
(merge-rule "\IeC {\NG }" "Ŋ" :string)
(merge-rule "\IeC {\ng }" "ŋ" :string)
(merge-rule "\IeC {\OE }" "Œ" :string)
(merge-rule "\IeC {\oe }" "œ" :string)
(merge-rule "\IeC {\IJ }" "IJ" :string)
(merge-rule "\IeC {\ij }" "ij" :string)
(merge-rule "\IeC {\j }" "ȷ" :string)
(merge-rule "\IeC {\SS }" "ẞ" :string)

View File

@ -0,0 +1,607 @@
;; style file for xindy
;; filename: LatinRules.xdy
;;
;; It is based upon xindy's files lang/general/utf8.xdy and
;; lang/general/utf8-lang.xdy which implement
;; "a general sorting order for Western European languages"
;;
;; The aim for Sphinx is to be able to index in a Cyrillic document
;; also terms using the Latin alphabets, inclusive of letters
;; with diacritics. To this effect the xindy rules from lang/general
;; got manually re-coded to avoid collisions with the encoding
;; done by xindy for sorting words in Cyrillic languages, which was
;; observed not to use bytes with octal encoding 0o266 or higher.
;;
;; So here we use only 0o266 or higher bytes.
;; (Ŋ, ŋ, IJ, and ij are absent from
;; lang/general/utf8.xdy and not included here)
;; Contributed by the Sphinx team, 2018.
(define-letter-group "A" :prefixes ("¶"))
(define-letter-group "B" :after "A" :prefixes ("·"))
(define-letter-group "C" :after "B" :prefixes ("¸"))
(define-letter-group "D" :after "C" :prefixes ("¹"))
(define-letter-group "E" :after "D" :prefixes ("º"))
(define-letter-group "F" :after "E" :prefixes ("»"))
(define-letter-group "G" :after "F" :prefixes ("¼"))
(define-letter-group "H" :after "G" :prefixes ("½"))
(define-letter-group "I" :after "H" :prefixes ("¾"))
(define-letter-group "J" :after "I" :prefixes ("¿"))
(define-letter-group "K" :after "J" :prefixes ("À"))
(define-letter-group "L" :after "K" :prefixes ("Á"))
(define-letter-group "M" :after "L" :prefixes ("Â"))
(define-letter-group "N" :after "M" :prefixes ("Ã"))
(define-letter-group "O" :after "N" :prefixes ("Ä"))
(define-letter-group "P" :after "O" :prefixes ("È"))
(define-letter-group "Q" :after "P" :prefixes ("Ê"))
(define-letter-group "R" :after "Q" :prefixes ("Ë"))
(define-letter-group "S" :after "R" :prefixes ("Ð"))
(define-letter-group "T" :after "S" :prefixes ("Ú"))
(define-letter-group "U" :after "T" :prefixes ("à"))
(define-letter-group "V" :after "U" :prefixes ("å"))
(define-letter-group "W" :after "V" :prefixes ("æ"))
(define-letter-group "X" :after "W" :prefixes ("ë"))
(define-letter-group "Y" :after "X" :prefixes ("í"))
(define-letter-group "Z" :after "Y" :prefixes ("ð"))
(define-rule-set "sphinx-xy-alphabetize"
:rules (("À" "¶" :string)
("Ä‚" "¶" :string)
("â" "¶" :string)
("Ä" "¶" :string)
("à" "¶" :string)
("Ã…" "¶" :string)
("Ã" "¶" :string)
("Ã<>" "¶" :string)
("á" "¶" :string)
("ã" "¶" :string)
("Â" "¶" :string)
("ă" "¶" :string)
("Ã¥" "¶" :string)
("Ä…" "¶" :string)
("ä" "¶" :string)
("Ä„" "¶" :string)
("æ" "¶º" :string)
("Æ" "¶º" :string)
("ć" "¸" :string)
("ĉ" "¸" :string)
("ç" "¸" :string)
("ÄŒ" "¸" :string)
("Ä<>" "¸" :string)
("Ĉ" "¸" :string)
("Ç" "¸" :string)
("Ć" "¸" :string)
("Ä<>" "¹" :string)
("Ä<>" "¹" :string)
("ÄŽ" "¹" :string)
("Ä‘" "¹" :string)
("ê" "º" :string)
("Ę" "º" :string)
("Äš" "º" :string)
("ë" "º" :string)
("Ä›" "º" :string)
("é" "º" :string)
("È" "º" :string)
("Ë" "º" :string)
("É" "º" :string)
("è" "º" :string)
("Ê" "º" :string)
("Ä™" "º" :string)
("Ä<>" "¼" :string)
("ÄŸ" "¼" :string)
("Äž" "¼" :string)
("Äœ" "¼" :string)
("Ä¥" "½" :string)
("Ĥ" "½" :string)
("Ã<>" "¾" :string)
("Ã<>" "¾" :string)
("ï" "¾" :string)
("ÃŽ" "¾" :string)
("î" "¾" :string)
("ı" "¾" :string)
("İ" "¾" :string)
("í" "¾" :string)
("ÃŒ" "¾" :string)
("ì" "¾" :string)
("Ä´" "¿" :string)
("ĵ" "¿" :string)
("Å‚" "Á" :string)
("Å<>" "Á" :string)
("ľ" "Á" :string)
("Ľ" "Á" :string)
("Å„" "Ã" :string)
("Ń" "Ã" :string)
("ñ" "Ã" :string)
("ň" "Ã" :string)
("Ñ" "Ã" :string)
("Ň" "Ã" :string)
("Õ" "Ä" :string)
("Å<>" "Ä" :string)
("ó" "Ä" :string)
("ö" "Ä" :string)
("ô" "Ä" :string)
("Å‘" "Ä" :string)
("Ø" "Ä" :string)
("Ö" "Ä" :string)
("õ" "Ä" :string)
("Ô" "Ä" :string)
("ø" "Ä" :string)
("Ó" "Ä" :string)
("Ã’" "Ä" :string)
("ò" "Ä" :string)
("œ" "ĺ" :string)
("Œ" "ĺ" :string)
("Ř" "Ë" :string)
("Å™" "Ë" :string)
("Å”" "Ë" :string)
("Å•" "Ë" :string)
("Å<>" "Ð" :string)
("Åš" "Ð" :string)
("È™" "Ð" :string)
("ÅŸ" "Ð" :string)
("Åœ" "Ð" :string)
("Å›" "Ð" :string)
("Ș" "Ð" :string)
("Å¡" "Ð" :string)
("Åž" "Ð" :string)
("Å " "Ð" :string)
("ß" "ÐÐ" :string)
("Èš" "Ú" :string)
("Ť" "Ú" :string)
("È›" "Ú" :string)
("Å¥" "Ú" :string)
("û" "à" :string)
("Å­" "à" :string)
("ů" "à" :string)
("ű" "à" :string)
("ù" "à" :string)
("Ŭ" "à" :string)
("Ù" "à" :string)
("Ű" "à" :string)
("Ü" "à" :string)
("Å®" "à" :string)
("ú" "à" :string)
("Ú" "à" :string)
("Û" "à" :string)
("ü" "à" :string)
("ÿ" "í" :string)
("Ã<>" "í" :string)
("Ÿ" "í" :string)
("ý" "í" :string)
("Å»" "ð" :string)
("Ž" "ð" :string)
("Ź" "ð" :string)
("ž" "ð" :string)
("ż" "ð" :string)
("ź" "ð" :string)
("a" "¶" :string)
("A" "¶" :string)
("b" "·" :string)
("B" "·" :string)
("c" "¸" :string)
("C" "¸" :string)
("d" "¹" :string)
("D" "¹" :string)
("e" "º" :string)
("E" "º" :string)
("F" "»" :string)
("f" "»" :string)
("G" "¼" :string)
("g" "¼" :string)
("H" "½" :string)
("h" "½" :string)
("i" "¾" :string)
("I" "¾" :string)
("J" "¿" :string)
("j" "¿" :string)
("K" "À" :string)
("k" "À" :string)
("L" "Á" :string)
("l" "Á" :string)
("M" "Â" :string)
("m" "Â" :string)
("n" "Ã" :string)
("N" "Ã" :string)
("O" "Ä" :string)
("o" "Ä" :string)
("p" "È" :string)
("P" "È" :string)
("Q" "Ê" :string)
("q" "Ê" :string)
("r" "Ë" :string)
("R" "Ë" :string)
("S" "Ð" :string)
("s" "Ð" :string)
("t" "Ú" :string)
("T" "Ú" :string)
("u" "à" :string)
("U" "à" :string)
("v" "å" :string)
("V" "å" :string)
("W" "æ" :string)
("w" "æ" :string)
("x" "ë" :string)
("X" "ë" :string)
("Y" "í" :string)
("y" "í" :string)
("z" "ð" :string)
("Z" "ð" :string)
))
(define-rule-set "sphinx-xy-resolve-diacritics"
:rules (("Ĥ" "£" :string)
("ó" "£" :string)
("ľ" "£" :string)
("Ř" "£" :string)
("Ä<>" "£" :string)
("Ä<>" "£" :string)
("Äš" "£" :string)
("Ä¥" "£" :string)
("ÄŒ" "£" :string)
("Ä´" "£" :string)
("Ä›" "£" :string)
("ž" "£" :string)
("ÄŽ" "£" :string)
("Å™" "£" :string)
("Ž" "£" :string)
("ı" "£" :string)
("Ť" "£" :string)
("á" "£" :string)
("Ä<>" "£" :string)
("Ã<>" "£" :string)
("ň" "£" :string)
("Å " "£" :string)
("Ň" "£" :string)
("ĵ" "£" :string)
("Å¥" "£" :string)
("Ó" "£" :string)
("ý" "£" :string)
("Äœ" "£" :string)
("Ú" "£" :string)
("Ľ" "£" :string)
("Å¡" "£" :string)
("Ã<>" "£" :string)
("ú" "£" :string)
("Åš" "¤" :string)
("ć" "¤" :string)
("Å<>" "¤" :string)
("Å‚" "¤" :string)
("Å„" "¤" :string)
("À" "¤" :string)
("Ź" "¤" :string)
("à" "¤" :string)
("Ń" "¤" :string)
("Ä<>" "¤" :string)
("ÿ" "¤" :string)
("Å›" "¤" :string)
("Äž" "¤" :string)
("ÄŸ" "¤" :string)
("Ù" "¤" :string)
("İ" "¤" :string)
("Ä‘" "¤" :string)
("ù" "¤" :string)
("Èš" "¤" :string)
("é" "¤" :string)
("Å•" "¤" :string)
("Ć" "¤" :string)
("È›" "¤" :string)
("ò" "¤" :string)
("ź" "¤" :string)
("Ã’" "¤" :string)
("Ÿ" "¤" :string)
("Å”" "¤" :string)
("É" "¤" :string)
("ĉ" "¥" :string)
("ô" "¥" :string)
("Ã<>" "¥" :string)
("Å<>" "¥" :string)
("Å»" "¥" :string)
("Ä‚" "¥" :string)
("Åœ" "¥" :string)
("ñ" "¥" :string)
("Å­" "¥" :string)
("í" "¥" :string)
("È" "¥" :string)
("Ô" "¥" :string)
("Ŭ" "¥" :string)
("ż" "¥" :string)
("Ñ" "¥" :string)
("è" "¥" :string)
("Ĉ" "¥" :string)
("ă" "¥" :string)
("â" "¦" :string)
("û" "¦" :string)
("ê" "¦" :string)
("Õ" "¦" :string)
("õ" "¦" :string)
("È™" "¦" :string)
("ç" "¦" :string)
("Â" "¦" :string)
("Ê" "¦" :string)
("Û" "¦" :string)
("Ç" "¦" :string)
("ì" "¦" :string)
("ÃŒ" "¦" :string)
("Ș" "¦" :string)
("ö" "§" :string)
("Ö" "§" :string)
("ÅŸ" "§" :string)
("ů" "§" :string)
("ë" "§" :string)
("ã" "§" :string)
("î" "§" :string)
("ÃŽ" "§" :string)
("Ã" "§" :string)
("Åž" "§" :string)
("Å®" "§" :string)
("Ë" "§" :string)
("ï" "¨" :string)
("Å<>" "¨" :string)
("Ã<>" "¨" :string)
("Ę" "¨" :string)
("Å‘" "¨" :string)
("Ü" "¨" :string)
("Ã…" "¨" :string)
("ü" "¨" :string)
("Ä™" "¨" :string)
("Ã¥" "¨" :string)
("Ä" "©" :string)
("ű" "©" :string)
("Ø" "©" :string)
("ø" "©" :string)
("Ű" "©" :string)
("ä" "©" :string)
("Ä„" "ª" :string)
("Ä…" "ª" :string)
("Å“" "ÿ" :string)
("ß" "ÿ" :string)
("Æ" "ÿ" :string)
("Å’" "ÿ" :string)
("æ" "ÿ" :string)
("e" "¢" :string)
("t" "¢" :string)
("L" "¢" :string)
("Y" "¢" :string)
("J" "¢" :string)
("a" "¢" :string)
("p" "¢" :string)
("u" "¢" :string)
("j" "¢" :string)
("b" "¢" :string)
("G" "¢" :string)
("U" "¢" :string)
("F" "¢" :string)
("H" "¢" :string)
("i" "¢" :string)
("z" "¢" :string)
("c" "¢" :string)
("l" "¢" :string)
("A" "¢" :string)
("Q" "¢" :string)
("w" "¢" :string)
("D" "¢" :string)
("R" "¢" :string)
("d" "¢" :string)
("s" "¢" :string)
("r" "¢" :string)
("k" "¢" :string)
("v" "¢" :string)
("m" "¢" :string)
("P" "¢" :string)
("y" "¢" :string)
("K" "¢" :string)
("q" "¢" :string)
("S" "¢" :string)
("I" "¢" :string)
("C" "¢" :string)
("M" "¢" :string)
("Z" "¢" :string)
("T" "¢" :string)
("W" "¢" :string)
("B" "¢" :string)
("h" "¢" :string)
("x" "¢" :string)
("X" "¢" :string)
("f" "¢" :string)
("E" "¢" :string)
("V" "¢" :string)
("N" "¢" :string)
("O" "¢" :string)
("o" "¢" :string)
("g" "¢" :string)
("n" "¢" :string)
))
(define-rule-set "sphinx-xy-resolve-case"
:rules (("Ú" "8" :string)
("Ÿ" "8" :string)
("Ç" "8" :string)
("Ĉ" "8" :string)
("Å”" "8" :string)
("Ľ" "8" :string)
("Å®" "8" :string)
("Ã<>" "8" :string)
("É" "8" :string)
("Ë" "8" :string)
("Ș" "8" :string)
("Ì" "8" :string)
("Ê" "8" :string)
("Ň" "8" :string)
("Ä„" "8" :string)
("Å " "8" :string)
("Û" "8" :string)
("Åž" "8" :string)
("Ć" "8" :string)
("Ã’" "8" :string)
("Ĝ" "8" :string)
("Ñ" "8" :string)
("Ó" "8" :string)
("ÃŽ" "8" :string)
("Ã<>" "8" :string)
("Ã" "8" :string)
("Èš" "8" :string)
("Ã…" "8" :string)
("Äž" "8" :string)
("Ü" "8" :string)
("È" "8" :string)
("Ô" "8" :string)
("İ" "8" :string)
("Ű" "8" :string)
("Ù" "8" :string)
("Ŭ" "8" :string)
("Â" "8" :string)
("Ť" "8" :string)
("Ń" "8" :string)
("ÄŽ" "8" :string)
("Ź" "8" :string)
("Ž" "8" :string)
("Ä<>" "8" :string)
("Ŝ" "8" :string)
("Č" "8" :string)
("Ä´" "8" :string)
("Ö" "8" :string)
("Ø" "8" :string)
("Å»" "8" :string)
("Å<>" "8" :string)
("Ä‚" "8" :string)
("Äš" "8" :string)
("Å<>" "8" :string)
("Õ" "8" :string)
("Ę" "8" :string)
("Ã<>" "8" :string)
("À" "8" :string)
("Ĥ" "8" :string)
("Ä" "8" :string)
("Åš" "8" :string)
("Ř" "8" :string)
("Ã<>" "8" :string)
("Å’" "89" :string)
("Æ" "89" :string)
("ì" "9" :string)
("è" "9" :string)
("Ä…" "9" :string)
("Å¡" "9" :string)
("ú" "9" :string)
("Ã¥" "9" :string)
("ă" "9" :string)
("Ä™" "9" :string)
("ü" "9" :string)
("ź" "9" :string)
("ò" "9" :string)
("Å¥" "9" :string)
("È›" "9" :string)
("ĵ" "9" :string)
("Å•" "9" :string)
("ż" "9" :string)
("ä" "9" :string)
("ý" "9" :string)
("ù" "9" :string)
("á" "9" :string)
("é" "9" :string)
("Ä<>" "9" :string)
("ň" "9" :string)
("Å›" "9" :string)
("ø" "9" :string)
("í" "9" :string)
("Ä‘" "9" :string)
("ı" "9" :string)
("ÄŸ" "9" :string)
("î" "9" :string)
("ã" "9" :string)
("à" "9" :string)
("Å™" "9" :string)
("Å‘" "9" :string)
("ů" "9" :string)
("È™" "9" :string)
("ÿ" "9" :string)
("ë" "9" :string)
("Å­" "9" :string)
("ç" "9" :string)
("ű" "9" :string)
("ñ" "9" :string)
("õ" "9" :string)
("Ä›" "9" :string)
("ÅŸ" "9" :string)
("ž" "9" :string)
("Ä<>" "9" :string)
("Å<>" "9" :string)
("Å„" "9" :string)
("û" "9" :string)
("Å‚" "9" :string)
("Ä<>" "9" :string)
("Ä¥" "9" :string)
("ê" "9" :string)
("ô" "9" :string)
("ĉ" "9" :string)
("â" "9" :string)
("ć" "9" :string)
("ï" "9" :string)
("ö" "9" :string)
("ľ" "9" :string)
("ó" "9" :string)
("æ" "99" :string)
("ß" "99" :string)
("Å“" "99" :string)
("N" "8" :string)
("V" "8" :string)
("O" "8" :string)
("X" "8" :string)
("E" "8" :string)
("P" "8" :string)
("K" "8" :string)
("T" "8" :string)
("Z" "8" :string)
("M" "8" :string)
("C" "8" :string)
("I" "8" :string)
("S" "8" :string)
("B" "8" :string)
("W" "8" :string)
("D" "8" :string)
("R" "8" :string)
("H" "8" :string)
("F" "8" :string)
("Q" "8" :string)
("A" "8" :string)
("G" "8" :string)
("U" "8" :string)
("J" "8" :string)
("Y" "8" :string)
("L" "8" :string)
("o" "9" :string)
("n" "9" :string)
("g" "9" :string)
("x" "9" :string)
("f" "9" :string)
("y" "9" :string)
("q" "9" :string)
("h" "9" :string)
("w" "9" :string)
("s" "9" :string)
("d" "9" :string)
("v" "9" :string)
("k" "9" :string)
("r" "9" :string)
("m" "9" :string)
("z" "9" :string)
("c" "9" :string)
("i" "9" :string)
("l" "9" :string)
("b" "9" :string)
("j" "9" :string)
("a" "9" :string)
("p" "9" :string)
("u" "9" :string)
("t" "9" :string)
("e" "9" :string)
))
(use-rule-set :run 0
:rule-set ("sphinx-xy-alphabetize"))
(use-rule-set :run 1
:rule-set ("sphinx-xy-resolve-diacritics"))
(use-rule-set :run 2
:rule-set ("sphinx-xy-resolve-case"))

View File

@ -24,13 +24,18 @@ export LATEXOPTS =
LATEXMKOPTS =
{% if xindy_use -%}
export XINDYOPTS = {{ xindy_lang_option }} -M sphinx.xdy
{% if latex_engine == 'pdflatex' and xindy_cyrillic -%}
XINDYOPTS += -M cyrLICRutf8.xdy
{% if latex_engine == 'pdflatex' -%}
XINDYOPTS += -M LICRlatin2utf8.xdy
{% if xindy_cyrillic -%}
XINDYOPTS += -M LICRcyr2utf8.xdy
{% endif -%}
{% if latex_engine == 'xelatex' or latex_engine == 'lualatex' -%}
{% endif -%}
{% if xindy_cyrillic -%}
XINDYOPTS += -M LatinRules.xdy
{% endif -%}
# also with pdflatex as LICRlatin2utf8.xdy replaces xindy's /tex/inputenc/utf8.xdy
XINDYOPTS += -I xelatex
{% endif -%}
{% endif -%}
# format: pdf or dvi (used only by archive targets)
FMT = pdf

View File

@ -26,7 +26,7 @@
;; man page says to use rather xelatex or lualatex in case of Cyrillic
;; scripts.
;; Sphinx contributes cyrLICRutf8.xdy to provide support for Cyrillic
;; Sphinx contributes LICRcyr2utf8.xdy to provide support for Cyrillic
;; scripts for the pdflatex engine.
;; Another issue caused by xindy ignoring all TeX macros except those
@ -42,6 +42,14 @@
;; Rather it incorporates some suitable extracts from latex.xdy and
;; tex.xdy with additional Sphinx contributed rules.
;; But, this means for pdflatex and Latin scripts that the xindy file
;; tex/inputenc/uf8.xdy is not usable because it refers to the macro
;; \IeC only sporadically, and as tex.xdy is not loaded, a rule such as
;; (merge-rule "\'e" "é" :string)
;; does not work, it must be
;; (merge-rule "\IeC {\'e}" "é" :string)
;; So Sphinx contributes LICRlatin2utf8.xdy to mitigate that problem.
;;;;;;;; extracts from tex.xdy (discarding most original comments):
;;;
@ -84,12 +92,10 @@
;;;;;;;; end of extracts from latex.xdy
;; Sphinx additions, cf sphinx.util.texescape for rationale
;;
;; The LaTeX \index command turns \ into normal character so the TeX macros
;; written to .idx files are not followed by a blank. This is different
;; from non-ascii letters which end up (with pdflatex) as \IeC macros in .idx
;; file, with a blank.
;; file, with a blank space after \IeC
;; Details of the syntax are explained at
;; http://xindy.sourceforge.net/doc/manual-3.html
@ -98,6 +104,8 @@
;; guess, for example "\\_" is not detected as RE but "\\P\{\}" is, so for
;; being sure we apply the :string switch everywhere and do not use \\ etc...
;; Go back from sphinx.util.texescape TeX macros to UTF-8
(merge-rule "\sphinxleftcurlybrace{}" "{" :string)
(merge-rule "\sphinxrightcurlybrace{}" "}" :string)
(merge-rule "\_" "_" :string)
@ -118,12 +126,66 @@
(merge-rule "\(\checkmark\)" "✓" :string)
(merge-rule "\textendash{}" "" :string)
(merge-rule "\textbar{}" "|" :string)
(merge-rule "\(\sp{\text{0}}\)" "⁰" :string)
(merge-rule "\(\sp{\text{1}}\)" "¹" :string)
(merge-rule "\(\sp{\text{2}}\)" "²" :string)
(merge-rule "\(\sp{\text{3}}\)" "³" :string)
(merge-rule "\(\sp{\text{4}}\)" "⁴" :string)
(merge-rule "\(\sp{\text{5}}\)" "⁵" :string)
(merge-rule "\(\sp{\text{6}}\)" "⁶" :string)
(merge-rule "\(\sp{\text{7}}\)" "⁷" :string)
(merge-rule "\(\sp{\text{8}}\)" "⁸" :string)
(merge-rule "\(\sp{\text{9}}\)" "⁹" :string)
(merge-rule "\(\sb{\text{0}}\)" "₀" :string)
(merge-rule "\(\sb{\text{1}}\)" "₁" :string)
(merge-rule "\(\sb{\text{2}}\)" "₂" :string)
(merge-rule "\(\sb{\text{3}}\)" "₃" :string)
(merge-rule "\(\sb{\text{4}}\)" "₄" :string)
(merge-rule "\(\sb{\text{5}}\)" "₅" :string)
(merge-rule "\(\sb{\text{6}}\)" "₆" :string)
(merge-rule "\(\sb{\text{7}}\)" "₇" :string)
(merge-rule "\(\sb{\text{8}}\)" "₈" :string)
(merge-rule "\(\sb{\text{9}}\)" "₉" :string)
(merge-rule "\(\alpha\)" "α" :string)
(merge-rule "\(\beta\)" "β" :string)
(merge-rule "\(\gamma\)" "γ" :string)
(merge-rule "\(\delta\)" "δ" :string)
(merge-rule "\(\epsilon\)" "ε" :string)
(merge-rule "\(\zeta\)" "ζ" :string)
(merge-rule "\(\eta\)" "η" :string)
(merge-rule "\(\theta\)" "θ" :string)
(merge-rule "\(\iota\)" "ι" :string)
(merge-rule "\(\kappa\)" "κ" :string)
(merge-rule "\(\lambda\)" "λ" :string)
(merge-rule "\(\mu\)" "μ" :string)
(merge-rule "\(\nu\)" "ν" :string)
(merge-rule "\(\xi\)" "ξ" :string)
(merge-rule "\(\pi\)" "π" :string)
(merge-rule "\(\rho\)" "ρ" :string)
(merge-rule "\(\sigma\)" "σ" :string)
(merge-rule "\(\tau\)" "τ" :string)
(merge-rule "\(\upsilon\)" "υ" :string)
(merge-rule "\(\phi\)" "φ" :string)
(merge-rule "\(\chi\)" "χ" :string)
(merge-rule "\(\psi\)" "ψ" :string)
(merge-rule "\(\omega\)" "ω" :string)
(merge-rule "\(\Gamma\)" "Γ" :string)
(merge-rule "\(\Delta\)" "Δ" :string)
(merge-rule "\(\Theta\)" "Θ" :string)
(merge-rule "\(\Lambda\)" "Λ" :string)
(merge-rule "\(\Xi\)" "Ξ" :string)
(merge-rule "\(\Pi\)" "Π" :string)
(merge-rule "\(\Sigma\)" "Σ" :string)
(merge-rule "\(\Upsilon\)" "Υ" :string)
(merge-rule "\(\Phi\)" "Φ" :string)
(merge-rule "\(\Psi\)" "Ψ" :string)
(merge-rule "\(\Omega\)" "Ω" :string)
;; This xindy module provides some basic support for "see"
(require "makeindex.xdy")
;; This creates one-letter headings and works fine with utf-8 letters.
;; For Cyrillic and pdflatex necessitates cyrLICRutf8.xdy to be loaded too.
;; For Cyrillic with pdflatex works thanks to LICRcyr2utf8.xdy
(require "latin-lettergroups.xdy")
;; currently we don't (know how to easily) separate "Numbers" from

View File

@ -858,11 +858,29 @@ class HTMLTranslator(BaseTranslator):
def visit_math(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
logger.warning(__('using "math" markup without a Sphinx math extension '
'active, please use one of the math extensions '
'described at http://sphinx-doc.org/en/master/ext/math.html'),
location=(self.builder.current_docname, node.line))
raise nodes.SkipNode
name = self.builder.math_renderer_name
visit, _ = self.builder.app.registry.html_inline_math_renderers[name]
visit(self, node)
def depart_math(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
_, depart = self.builder.app.registry.html_inline_math_renderers[name]
if depart:
depart(self, node)
def visit_math_block(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
visit, _ = self.builder.app.registry.html_block_math_renderers[name]
visit(self, node)
def depart_math_block(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
_, depart = self.builder.app.registry.html_block_math_renderers[name]
if depart:
depart(self, node)
def unknown_visit(self, node):
# type: (nodes.Node) -> None

View File

@ -809,11 +809,29 @@ class HTML5Translator(BaseTranslator):
def visit_math(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
logger.warning(__('using "math" markup without a Sphinx math extension '
'active, please use one of the math extensions '
'described at http://sphinx-doc.org/en/master/ext/math.html'),
location=(self.builder.current_docname, node.line))
raise nodes.SkipNode
name = self.builder.math_renderer_name
visit, _ = self.builder.app.registry.html_inline_math_renderers[name]
visit(self, node)
def depart_math(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
_, depart = self.builder.app.registry.html_inline_math_renderers[name]
if depart:
depart(self, node)
def visit_math_block(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
visit, _ = self.builder.app.registry.html_block_math_renderers[name]
visit(self, node)
def depart_math_block(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
_, depart = self.builder.app.registry.html_block_math_renderers[name]
if depart:
depart(self, node)
def unknown_visit(self, node):
# type: (nodes.Node) -> None

View File

@ -1,8 +1,5 @@
# -*- coding: utf-8 -*-
import os
import sys
extensions = ['sphinx.ext.viewcode']
master_doc = 'index'
exclude_patterns = ['_build']

View File

@ -3,6 +3,7 @@ submodule
"""
raise RuntimeError('This module should not get imported')
def decorator(f):
return f

View File

@ -1,4 +1,4 @@
"""
r"""
Test with a class diagram like this::

View File

@ -2,4 +2,3 @@
master_doc = 'equations'
extensions = ['sphinx.ext.imgmath']

View File

@ -12,7 +12,6 @@ import pytest
from docutils import nodes
from sphinx.errors import ExtensionError
from sphinx.domains import Domain
from sphinx.testing.util import strip_escseq
from sphinx.util import logging

View File

@ -10,6 +10,7 @@
:license: BSD, see LICENSE for details.
"""
import re
import sys
from warnings import catch_warnings
@ -20,12 +21,24 @@ from six import PY3
from sphinx.ext.autodoc import (
AutoDirective, ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL
)
from sphinx.ext.autodoc.directive import DocumenterBridge, process_documenter_options
from sphinx.testing.util import SphinxTestApp, Struct # NOQA
from sphinx.util import logging
from sphinx.util.docutils import LoggingReporter
app = None
def do_autodoc(app, objtype, name, options={}):
doccls = app.registry.documenters[objtype]
docoptions = process_documenter_options(doccls, app.config, options)
bridge = DocumenterBridge(app.env, LoggingReporter(''), docoptions, 1)
documenter = doccls(bridge, name)
documenter.generate()
return bridge.result
@pytest.fixture(scope='module', autouse=True)
def setup_module(rootdir, sphinx_test_tempdir):
try:
@ -756,178 +769,549 @@ def test_generate():
assert_result_contains('.. py:class:: Class(arg)', 'module', 'target')
assert_result_contains('.. py:exception:: CustomEx', 'module', 'target')
# test noindex flag
options.members = []
options.noindex = True
assert_result_contains(' :noindex:', 'module', 'target')
assert_result_contains(' :noindex:', 'class', 'Base')
# okay, now let's get serious about mixing Python and C signature stuff
assert_result_contains('.. py:class:: CustomDict', 'class', 'CustomDict',
all_members=True)
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_noindex(app):
options = {"noindex": True}
actual = do_autodoc(app, 'module', 'target', options)
assert list(actual) == [
'',
'.. py:module:: target',
' :noindex:',
''
]
# test inner class handling
assert_processes([('class', 'target.Outer'),
('class', 'target.Outer.Inner'),
('method', 'target.Outer.Inner.meth')],
'class', 'Outer', all_members=True)
assert_processes([('class', 'target.Outer.Inner'),
('method', 'target.Outer.Inner.meth')],
'class', 'target.Outer.Inner', all_members=True)
# TODO: :noindex: should be propagated to children of target item.
# test descriptor docstrings
assert_result_contains(' Descriptor instance docstring.',
'attribute', 'target.Class.descr')
actual = do_autodoc(app, 'class', 'target.Base', options)
assert list(actual) == [
'',
'.. py:class:: Base',
' :noindex:',
' :module: target',
''
]
# test generation for C modules (which have no source file)
directive.env.ref_context['py:module'] = 'time'
assert_processes([('function', 'time.asctime')], 'function', 'asctime')
assert_processes([('function', 'time.asctime')], 'function', 'asctime')
# test autodoc_member_order == 'source'
directive.env.ref_context['py:module'] = 'target'
options.private_members = True
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_subclass_of_builtin_class(app):
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.CustomDict', options)
assert list(actual) == [
'',
'.. py:class:: CustomDict',
' :module: target',
'',
' Docstring.',
' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_inner_class(app):
if PY3:
roger_line = ' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)'
builtins = ' alias of :class:`builtins.dict`'
else:
roger_line = ' .. py:classmethod:: Class.roger(a, e=5, f=6)'
assert_order(['.. py:class:: Class(arg)',
' .. py:attribute:: Class.descr',
' .. py:method:: Class.meth()',
' .. py:method:: Class.undocmeth()',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.prop',
' .. py:attribute:: Class.docattr',
' .. py:attribute:: Class.udocattr',
' .. py:attribute:: Class.mdocattr',
roger_line,
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class._private_inst_attr',
' .. py:classmethod:: Class.inheritedclassmeth()',
' .. py:method:: Class.inheritedmeth()',
' .. py:staticmethod:: Class.inheritedstaticmeth(cls)',
],
'class', 'Class', member_order='bysource', all_members=True)
del directive.env.ref_context['py:module']
builtins = ' alias of :class:`__builtin__.dict`'
# test attribute initialized to class instance from other module
directive.env.temp_data['autodoc:class'] = 'target.Class'
assert_result_contains(u' should be documented as well - s\xfc\xdf',
'attribute', 'mdocattr')
del directive.env.temp_data['autodoc:class']
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.Outer', options)
assert list(actual) == [
'',
'.. py:class:: Outer',
' :module: target',
'',
' Foo',
' ',
' ',
' .. py:class:: Outer.Inner',
' :module: target',
' ',
' Foo',
' ',
' ',
' .. py:method:: Outer.Inner.meth()',
' :module: target',
' ',
' Foo',
' ',
' ',
' .. py:attribute:: Outer.factory',
' :module: target',
' ',
builtins
]
# test autodoc_docstring_signature
assert_result_contains(
'.. py:method:: DocstringSig.meth(FOO, BAR=1) -> BAZ', 'method',
'target.DocstringSig.meth')
assert_result_contains(
' rest of docstring', 'method', 'target.DocstringSig.meth')
assert_result_contains(
'.. py:method:: DocstringSig.meth2()', 'method',
'target.DocstringSig.meth2')
assert_result_contains(
' indented line', 'method',
'target.DocstringSig.meth2')
assert_result_contains(
'.. py:classmethod:: Class.moore(a, e, f) -> happiness', 'method',
'target.Class.moore')
actual = do_autodoc(app, 'class', 'target.Outer.Inner', options)
assert list(actual) == [
'',
'.. py:class:: Inner',
' :module: target.Outer',
'',
' Foo',
' ',
' ',
' .. py:method:: Inner.meth()',
' :module: target.Outer',
' ',
' Foo',
' ',
]
# test new attribute documenter behavior
directive.env.ref_context['py:module'] = 'target'
options.undoc_members = True
assert_processes([('class', 'target.AttCls'),
('attribute', 'target.AttCls.a1'),
('attribute', 'target.AttCls.a2'),
], 'class', 'AttCls')
assert_result_contains(
' :annotation: = hello world', 'attribute', 'AttCls.a1')
assert_result_contains(
' :annotation: = None', 'attribute', 'AttCls.a2')
# test explicit members with instance attributes
del directive.env.temp_data['autodoc:class']
del directive.env.temp_data['autodoc:module']
directive.env.ref_context['py:module'] = 'target'
options.inherited_members = False
options.undoc_members = False
options.members = ALL
assert_processes([
('class', 'target.InstAttCls'),
('attribute', 'target.InstAttCls.ca1'),
('attribute', 'target.InstAttCls.ca2'),
('attribute', 'target.InstAttCls.ca3'),
('attribute', 'target.InstAttCls.ia1'),
('attribute', 'target.InstAttCls.ia2'),
], 'class', 'InstAttCls')
del directive.env.temp_data['autodoc:class']
del directive.env.temp_data['autodoc:module']
options.members = ['ca1', 'ia1']
assert_processes([
('class', 'target.InstAttCls'),
('attribute', 'target.InstAttCls.ca1'),
('attribute', 'target.InstAttCls.ia1'),
], 'class', 'InstAttCls')
del directive.env.temp_data['autodoc:class']
del directive.env.temp_data['autodoc:module']
del directive.env.ref_context['py:module']
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_descriptor(app):
actual = do_autodoc(app, 'attribute', 'target.Class.descr')
assert list(actual) == [
'',
'.. py:attribute:: Class.descr',
' :module: target',
'',
' Descriptor instance docstring.',
' '
]
# test members with enum attributes
directive.env.ref_context['py:module'] = 'target'
options.inherited_members = False
options.undoc_members = True
options.members = ALL
assert_processes([
('class', 'target.EnumCls'),
('attribute', 'target.EnumCls.val1'),
('attribute', 'target.EnumCls.val2'),
('attribute', 'target.EnumCls.val3'),
('attribute', 'target.EnumCls.val4'),
], 'class', 'EnumCls')
assert_result_contains(
' :annotation: = 12', 'attribute', 'EnumCls.val1')
assert_result_contains(
' :annotation: = 23', 'attribute', 'EnumCls.val2')
assert_result_contains(
' :annotation: = 34', 'attribute', 'EnumCls.val3')
del directive.env.temp_data['autodoc:class']
del directive.env.temp_data['autodoc:module']
# test descriptor class documentation
options.members = ['CustomDataDescriptor', 'CustomDataDescriptor2']
assert_result_contains('.. py:class:: CustomDataDescriptor(doc)',
'module', 'target')
assert_result_contains(' .. py:method:: CustomDataDescriptor.meth()',
'module', 'target')
assert_result_contains('.. py:class:: CustomDataDescriptor2(doc)',
'module', 'target')
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_c_module(app):
actual = do_autodoc(app, 'function', 'time.asctime')
assert list(actual) == [
'',
'.. py:function:: asctime([tuple]) -> string',
' :module: time',
'',
" Convert a time tuple to a string, e.g. 'Sat Jun 06 16:26:11 1998'.",
' When the time tuple is not present, current time as returned by localtime()',
' is used.',
' '
]
# test mocked module imports
options.members = ['TestAutodoc']
options.undoc_members = False
assert_result_contains('.. py:class:: TestAutodoc',
'module', 'autodoc_missing_imports')
assert_result_contains(' .. py:method:: TestAutodoc.decoratedMethod()',
'module', 'autodoc_missing_imports')
options.members = ['decoratedFunction']
assert_result_contains('.. py:function:: decoratedFunction()',
'module', 'autodoc_missing_imports')
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_member_order(app):
if PY3:
roger_method = ' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)'
else:
roger_method = ' .. py:classmethod:: Class.roger(a, e=5, f=6)'
# case member-order='bysource'
options = {"members": None,
'member-order': 'bysource',
"undoc-members": True,
'private-members': True}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
' .. py:attribute:: Class.descr',
' .. py:method:: Class.meth()',
' .. py:method:: Class.undocmeth()',
' .. py:method:: Class.skipmeth()',
' .. py:method:: Class.excludemeth()',
' .. py:attribute:: Class.skipattr',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.prop',
' .. py:attribute:: Class.docattr',
' .. py:attribute:: Class.udocattr',
' .. py:attribute:: Class.mdocattr',
roger_method,
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class._private_inst_attr'
]
# case member-order='groupwise'
options = {"members": None,
'member-order': 'groupwise',
"undoc-members": True,
'private-members': True}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
' .. py:method:: Class.excludemeth()',
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
roger_method,
' .. py:method:: Class.skipmeth()',
' .. py:method:: Class.undocmeth()',
' .. py:attribute:: Class._private_inst_attr',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.descr',
' .. py:attribute:: Class.docattr',
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class.mdocattr',
' .. py:attribute:: Class.prop',
' .. py:attribute:: Class.skipattr',
' .. py:attribute:: Class.udocattr'
]
# case member-order=None
options = {"members": None,
"undoc-members": True,
'private-members': True}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
' .. py:attribute:: Class._private_inst_attr',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.descr',
' .. py:attribute:: Class.docattr',
' .. py:method:: Class.excludemeth()',
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class.mdocattr',
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.prop',
roger_method,
' .. py:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()',
' .. py:attribute:: Class.udocattr',
' .. py:method:: Class.undocmeth()'
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_module_scope(app):
def convert(s):
return re.sub('<.*>', '<FILTERED>', s) # for py2/py3
app.env.temp_data['autodoc:module'] = 'target'
actual = do_autodoc(app, 'attribute', 'Class.mdocattr')
assert list(map(convert, actual)) == [
u'',
u'.. py:attribute:: Class.mdocattr',
u' :module: target',
u' :annotation: = <FILTERED>',
u'',
u' should be documented as well - süß',
u' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_class_scope(app):
def convert(s):
return re.sub('<.*>', '<FILTERED>', s) # for py2/py3
app.env.temp_data['autodoc:module'] = 'target'
app.env.temp_data['autodoc:class'] = 'Class'
actual = do_autodoc(app, 'attribute', 'mdocattr')
assert list(map(convert, actual)) == [
u'',
u'.. py:attribute:: Class.mdocattr',
u' :module: target',
u' :annotation: = <FILTERED>',
u'',
u' should be documented as well - süß',
u' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_docstring_signature(app):
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.DocstringSig', options)
assert list(actual) == [
'',
'.. py:class:: DocstringSig',
' :module: target',
'',
' ',
' .. py:method:: DocstringSig.meth(FOO, BAR=1) -> BAZ',
' :module: target',
' ',
' First line of docstring',
' ',
' rest of docstring',
' ',
' ',
' .. py:method:: DocstringSig.meth2()',
' :module: target',
' ',
' First line, no signature',
' Second line followed by indentation::',
' ',
' indented line',
' ',
' ',
' .. py:attribute:: DocstringSig.prop1',
' :module: target',
' ',
' First line of docstring',
' ',
' ',
' .. py:attribute:: DocstringSig.prop2',
' :module: target',
' ',
' First line of docstring',
' Second line of docstring',
' '
]
# disable autodoc_docstring_signature
app.config.autodoc_docstring_signature = False
actual = do_autodoc(app, 'class', 'target.DocstringSig', options)
assert list(actual) == [
u'',
u'.. py:class:: DocstringSig',
u' :module: target',
u'',
u' ',
u' .. py:method:: DocstringSig.meth()',
u' :module: target',
u' ',
u' meth(FOO, BAR=1) -> BAZ',
u' First line of docstring',
u' ',
u' rest of docstring',
u' ',
u' ',
u' ',
u' .. py:method:: DocstringSig.meth2()',
u' :module: target',
u' ',
u' First line, no signature',
u' Second line followed by indentation::',
u' ',
u' indented line',
u' ',
u' ',
u' .. py:attribute:: DocstringSig.prop1',
u' :module: target',
u' ',
u' DocstringSig.prop1(self)',
u' First line of docstring',
u' ',
u' ',
u' .. py:attribute:: DocstringSig.prop2',
u' :module: target',
u' ',
u' First line of docstring',
u' Second line of docstring',
u' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_class_attributes(app):
options = {"members": None,
"undoc-members": True}
actual = do_autodoc(app, 'class', 'target.AttCls', options)
assert list(actual) == [
'',
'.. py:class:: AttCls',
' :module: target',
'',
' ',
' .. py:attribute:: AttCls.a1',
' :module: target',
' :annotation: = hello world',
' ',
' ',
' .. py:attribute:: AttCls.a2',
' :module: target',
' :annotation: = None',
' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_instance_attributes(app):
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.InstAttCls', options)
assert list(actual) == [
'',
'.. py:class:: InstAttCls()',
' :module: target',
'',
' Class with documented class and instance attributes.',
' ',
' ',
' .. py:attribute:: InstAttCls.ca1',
' :module: target',
" :annotation: = 'a'",
' ',
' Doc comment for class attribute InstAttCls.ca1.',
' It can have multiple lines.',
' ',
' ',
' .. py:attribute:: InstAttCls.ca2',
' :module: target',
" :annotation: = 'b'",
' ',
' Doc comment for InstAttCls.ca2. One line only.',
' ',
' ',
' .. py:attribute:: InstAttCls.ca3',
' :module: target',
" :annotation: = 'c'",
' ',
' Docstring for class attribute InstAttCls.ca3.',
' ',
' ',
' .. py:attribute:: InstAttCls.ia1',
' :module: target',
' :annotation: = None',
' ',
' Doc comment for instance attribute InstAttCls.ia1',
' ',
' ',
' .. py:attribute:: InstAttCls.ia2',
' :module: target',
' :annotation: = None',
' ',
' Docstring for instance attribute InstAttCls.ia2.',
' '
]
# pick up arbitrary attributes
options = {"members": 'ca1,ia1'}
actual = do_autodoc(app, 'class', 'target.InstAttCls', options)
assert list(actual) == [
'',
'.. py:class:: InstAttCls()',
' :module: target',
'',
' Class with documented class and instance attributes.',
' ',
' ',
' .. py:attribute:: InstAttCls.ca1',
' :module: target',
" :annotation: = 'a'",
' ',
' Doc comment for class attribute InstAttCls.ca1.',
' It can have multiple lines.',
' ',
' ',
' .. py:attribute:: InstAttCls.ia1',
' :module: target',
' :annotation: = None',
' ',
' Doc comment for instance attribute InstAttCls.ia1',
' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_enum_class(app):
options = {"members": None,
"undoc-members": True}
actual = do_autodoc(app, 'class', 'target.EnumCls', options)
assert list(actual) == [
'',
'.. py:class:: EnumCls',
' :module: target',
'',
' this is enum class',
' ',
' ',
' .. py:attribute:: EnumCls.val1',
' :module: target',
' :annotation: = 12',
' ',
' doc for val1',
' ',
' ',
' .. py:attribute:: EnumCls.val2',
' :module: target',
' :annotation: = 23',
' ',
' doc for val2',
' ',
' ',
' .. py:attribute:: EnumCls.val3',
' :module: target',
' :annotation: = 34',
' ',
' doc for val3',
' ',
' ',
' .. py:attribute:: EnumCls.val4',
' :module: target',
' :annotation: = 34',
' '
]
# checks for an attribute of EnumClass
actual = do_autodoc(app, 'attribute', 'target.EnumCls.val1')
assert list(actual) == [
'',
'.. py:attribute:: EnumCls.val1',
' :module: target',
' :annotation: = 12',
'',
' doc for val1',
' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_descriptor_class(app):
options = {"members": 'CustomDataDescriptor,CustomDataDescriptor2'}
actual = do_autodoc(app, 'module', 'target', options)
assert list(actual) == [
'',
'.. py:module:: target',
'',
'',
'.. py:class:: CustomDataDescriptor(doc)',
' :module: target',
'',
' Descriptor class docstring.',
' ',
' ',
' .. py:method:: CustomDataDescriptor.meth()',
' :module: target',
' ',
' Function.',
' ',
'',
'.. py:class:: CustomDataDescriptor2(doc)',
' :module: target',
'',
' Descriptor class with custom metaclass docstring.',
' '
]
@pytest.mark.sphinx('html', testroot='root')
def test_mocked_module_imports(app):
options = {"members": 'TestAutodoc,decoratedFunction'}
actual = do_autodoc(app, 'module', 'autodoc_missing_imports', options)
assert list(actual) == [
'',
'.. py:module:: autodoc_missing_imports',
'',
'',
'.. py:class:: TestAutodoc',
' :module: autodoc_missing_imports',
'',
' TestAutodoc docstring.',
' ',
' ',
' .. py:method:: TestAutodoc.decoratedMethod()',
' :module: autodoc_missing_imports',
' ',
' TestAutodoc::decoratedMethod docstring',
' ',
'',
'.. py:function:: decoratedFunction()',
' :module: autodoc_missing_imports',
'',
' decoratedFunction docstring',
' '
]
@pytest.mark.skipif(sys.version_info < (3, 4),
reason='functools.partialmethod is available on py34 or above')
@pytest.mark.usefixtures('setup_test')
def test_partialmethod():
def call_autodoc(objtype, name):
inst = app.registry.documenters[objtype](directive, name)
inst.generate()
result = list(directive.result)
del directive.result[:]
return result
options.inherited_members = True
options.undoc_members = True
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_partialmethod(app):
expected = [
'',
'.. py:class:: Cell',
@ -962,4 +1346,27 @@ def test_partialmethod():
# TODO: this condition should be updated after 3.7-final release.
expected = '\n'.join(expected).replace(' -> None', '').split('\n')
assert call_autodoc('class', 'target.partialmethod.Cell') == expected
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.partialmethod.Cell', options)
assert list(actual) == expected
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_default_flags(app):
# no settings
actual = do_autodoc(app, 'class', 'target.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' not in actual
assert ' .. py:attribute:: EnumCls.val4' not in actual
# with :members:
app.config.autodoc_default_flags = ['members']
actual = do_autodoc(app, 'class', 'target.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' in actual
assert ' .. py:attribute:: EnumCls.val4' not in actual
# with :members: and :undoc-members:
app.config.autodoc_default_flags = ['members',
'undoc-members']
actual = do_autodoc(app, 'class', 'target.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' in actual
assert ' .. py:attribute:: EnumCls.val4' in actual

View File

@ -175,8 +175,8 @@ def test_gettext_template_msgid_order_in_sphinxpot(app):
result = (app.outdir / 'sphinx.pot').text(encoding='utf-8')
assert re.search(
('msgid "Template 1".*'
'msgid "This is Template 1\.".*'
'msgid "This is Template 1\\.".*'
'msgid "Template 2".*'
'msgid "This is Template 2\.".*'),
'msgid "This is Template 2\\.".*'),
result,
flags=re.S)

View File

@ -18,6 +18,7 @@ import pytest
from html5lib import getTreeBuilder, HTMLParser
from six import PY3
from sphinx.errors import ConfigError
from sphinx.testing.util import remove_unicode_literals, strip_escseq
from sphinx.util.inventory import InventoryFile
@ -1327,3 +1328,62 @@ def test_html_baseurl_and_html_file_suffix(app, status, warning):
result = (app.outdir / 'qux' / 'index.htm').text(encoding='utf8')
assert '<link rel="canonical" href="https://example.com/subdir/qux/index.htm" />' in result
@pytest.mark.sphinx('html', testroot='basic')
def test_default_html_math_renderer(app, status, warning):
assert app.builder.math_renderer_name == 'mathjax'
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_html_math_renderer_is_mathjax(app, status, warning):
assert app.builder.math_renderer_name == 'mathjax'
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.imgmath']})
def test_html_math_renderer_is_imgmath(app, status, warning):
assert app.builder.math_renderer_name == 'imgmath'
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.jsmath',
'sphinx.ext.imgmath']})
def test_html_math_renderer_is_duplicated(make_app, app_params):
try:
args, kwargs = app_params
make_app(*args, **kwargs)
assert False
except ConfigError as exc:
assert str(exc) == ('Many math_renderers are registered. '
'But no math_renderer is selected.')
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.imgmath',
'sphinx.ext.mathjax']})
def test_html_math_renderer_is_duplicated2(app, status, warning):
# case of both mathjax and another math_renderer is loaded
assert app.builder.math_renderer_name == 'imgmath' # The another one is chosen
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.jsmath',
'sphinx.ext.imgmath'],
'html_math_renderer': 'imgmath'})
def test_html_math_renderer_is_chosen(app, status, warning):
assert app.builder.math_renderer_name == 'imgmath'
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.jsmath',
'sphinx.ext.mathjax'],
'html_math_renderer': 'imgmath'})
def test_html_math_renderer_is_mismatched(make_app, app_params):
try:
args, kwargs = app_params
make_app(*args, **kwargs)
assert False
except ConfigError as exc:
assert str(exc) == "Unknown math_renderer 'imgmath' is given."

View File

@ -172,20 +172,20 @@ def make_app_with_empty_project(make_app, tempdir):
def test_needs_sphinx(make_app_with_empty_project):
make_app = make_app_with_empty_project
# micro version
app = make_app(confoverrides={'needs_sphinx': '1.3.3'}) # OK: less
app = make_app(confoverrides={'needs_sphinx': '1.3.4'}) # OK: equals
make_app(confoverrides={'needs_sphinx': '1.3.3'}) # OK: less
make_app(confoverrides={'needs_sphinx': '1.3.4'}) # OK: equals
with pytest.raises(VersionRequirementError):
make_app(confoverrides={'needs_sphinx': '1.3.5'}) # NG: greater
# minor version
app = make_app(confoverrides={'needs_sphinx': '1.2'}) # OK: less
app = make_app(confoverrides={'needs_sphinx': '1.3'}) # OK: equals
make_app(confoverrides={'needs_sphinx': '1.2'}) # OK: less
make_app(confoverrides={'needs_sphinx': '1.3'}) # OK: equals
with pytest.raises(VersionRequirementError):
make_app(confoverrides={'needs_sphinx': '1.4'}) # NG: greater
# major version
app = make_app(confoverrides={'needs_sphinx': '0'}) # OK: less
app = make_app(confoverrides={'needs_sphinx': '1'}) # OK: equals
make_app(confoverrides={'needs_sphinx': '0'}) # OK: less
make_app(confoverrides={'needs_sphinx': '1'}) # OK: equals
with pytest.raises(VersionRequirementError):
make_app(confoverrides={'needs_sphinx': '2'}) # NG: greater

View File

@ -760,9 +760,9 @@ def test_xref_consistency(app, status, warning):
def classes(role, tag):
pattern = (r'{role}-role:.*?'
'<(?P<tag>{tag}) .*?class=["\'](?P<classes>.*?)["\'].*?>'
'.*'
'</(?P=tag)>').format(role=role, tag=tag)
r'<(?P<tag>{tag}) .*?class=["\'](?P<classes>.*?)["\'].*?>'
r'.*'
r'</(?P=tag)>').format(role=role, tag=tag)
result = re.search(pattern, output)
expect = '''\
Pattern for role `{role}` with tag `{tag}`
@ -783,17 +783,17 @@ not found in `{test}`
self.content_classes[tag] = classes(role, tag)
# not actually used as a reference point
#code_role = RoleClasses('code', 'code', [])
# code_role = RoleClasses('code', 'code', [])
any_role = RoleClasses('any', 'a', ['code'])
cpp_any_role = RoleClasses('cpp-any', 'a', ['code'])
# NYI: consistent looks
#texpr_role = RoleClasses('cpp-texpr', 'span', ['a', 'code'])
# texpr_role = RoleClasses('cpp-texpr', 'span', ['a', 'code'])
expr_role = RoleClasses('cpp-expr', 'code', ['a'])
texpr_role = RoleClasses('cpp-texpr', 'span', ['a', 'span'])
# XRefRole-style classes
## any and cpp:any do not put these classes at the root
# any and cpp:any do not put these classes at the root
# n.b. the generic any machinery finds the specific 'cpp-class' object type
expect = 'any uses XRefRole classes'

View File

@ -113,7 +113,8 @@ def test_glob(app):
maxdepth=-1, numbered=0, includefiles=includefiles,
entries=[(None, 'foo'), (None, 'bar/index'), (None, 'bar/bar_1'),
(None, 'bar/bar_2'), (None, 'bar/bar_3'), (None, 'baz'),
(None, 'qux/index'), ('hyperref', 'https://sphinx-doc.org/?q=sphinx')])
(None, 'qux/index'),
('hyperref', 'https://sphinx-doc.org/?q=sphinx')])
assert_node(toctree[0][1][1],
[list_item, ([compact_paragraph, reference, "reversed order"],
[bullet_list, addnodes.toctree])]) # [0][1][1][1][0]

View File

@ -387,8 +387,6 @@ def extract_toc(path):
coderoot='test-apidoc-subpackage-in-toc',
options=['--separate']
)
def test_subpackage_in_toc(make_app, apidoc):
"""Make sure that empty subpackages with non-empty subpackages in them
are not skipped (issue #4520)

View File

@ -9,6 +9,7 @@
:license: BSD, see LICENSE for details.
"""
import os
import pytest
from packaging.specifiers import InvalidSpecifier
from packaging.version import InvalidVersion

View File

@ -1,13 +1,13 @@
[tox]
minversion = 2.0
envlist = docs,flake8,mypy,coverage,py{27,34,35,36,py},du{11,12,13,14}
envlist = docs,flake8,mypy,coverage,py{27,34,35,36,37,38,py},du{11,12,13,14}
[testenv]
usedevelop = True
passenv =
https_proxy http_proxy no_proxy PERL PERL5LIB PYTEST_ADDOPTS EPUBCHECK_PATH
description =
py{27,34,35,36,py}: Run unit tests against {envname}.
py{27,34,35,36,37,38,py}: Run unit tests against {envname}.
du{11,12,13,14}: Run unit tests with the given version of docutils.
# TODO(stephenfin) Replace this with the 'extras' config option when tox 2.4 is