mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'master' into 5163_hlist_aligned_to_top
This commit is contained in:
commit
f84df710e1
43
CHANGES
43
CHANGES
@ -4,6 +4,11 @@ Release 1.8.0 (in development)
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
* LaTeX: :confval:`latex_use_xindy`, if ``True`` (default for
|
||||
``xelatex/lualatex``), instructs ``make latexpdf`` to use :program:`xindy`
|
||||
for general index. Make sure your LaTeX distribution includes it.
|
||||
(refs: #5134)
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
@ -39,6 +44,10 @@ Incompatible changes
|
||||
Please use ``app.add_js_file()`` instead.
|
||||
* #5072: Save environment object also with only new documents
|
||||
* #5035: qthelp builder allows dashes in :confval:`qthelp_namespace`
|
||||
* LaTeX: with lualatex or xelatex use by default :program:`xindy` as
|
||||
UTF-8 able replacement of :program:`makeindex` (refs: #5134). After
|
||||
upgrading Sphinx, please clean latex build repertory of existing project
|
||||
before new build.
|
||||
* #5163: html: hlist items are now aligned to top
|
||||
|
||||
Deprecated
|
||||
@ -144,6 +153,14 @@ Features added
|
||||
for mathjax
|
||||
* #4362: latex: Don't overwrite .tex file if document not changed
|
||||
* #1431: latex: Add alphanumeric enumerated list support
|
||||
* Extend to all projects not using the Sphinx LaTeX Makefile a workaround for
|
||||
`issue rtfd/readthedocs.org#2857`__ about insufficient number of
|
||||
``pdflatex`` runs for index to show up in PDF bookmarks (refs: #3742)
|
||||
|
||||
__ https://github.com/rtfd/readthedocs.org/issues/2857
|
||||
* Add :confval:`latex_use_xindy` for UTF-8 savvy indexing, defaults to ``True``
|
||||
if :confval:`latex_engine` is ``'xelatex'`` or ``'lualatex'``.
|
||||
* #4976: ``SphinxLoggerAdapter.info()`` now supports ``location`` parameter
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
@ -153,6 +170,9 @@ Bugs fixed
|
||||
* #4945: i18n: fix lang_COUNTRY not fallback correctly for IndexBuilder. Thanks
|
||||
to Shengjing Zhu.
|
||||
* #4983: productionlist directive generates invalid IDs for the tokens
|
||||
* #5132: (lualatex) PDF build fails if indexed word starts with Unicode character
|
||||
* #5133: latex: index headings "Symbols" and "Numbers" not internationalized
|
||||
* #5114: sphinx-build: Handle errors on scanning documents
|
||||
|
||||
Testing
|
||||
--------
|
||||
@ -168,7 +188,7 @@ Documentation
|
||||
* #5083: Fix wrong make.bat option for internationalization.
|
||||
* #5115: napoleon: add admonitions added by #4613 to the docs.
|
||||
|
||||
Release 1.7.6 (in development)
|
||||
Release 1.7.7 (in development)
|
||||
==============================
|
||||
|
||||
Dependencies
|
||||
@ -186,6 +206,15 @@ Features added
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 1.7.6 (released Jul 17, 2018)
|
||||
=====================================
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #5037: LaTeX ``\sphinxupquote{}`` breaks in Russian
|
||||
* sphinx.testing uses deprecated pytest API; ``Node.get_marker(name)``
|
||||
* #5016: crashed when recommonmark.AutoStrictify is enabled
|
||||
@ -203,6 +232,7 @@ Bugs fixed
|
||||
* #5091: latex: curly braces in index entries are not handled correctly
|
||||
* #5070: epub: Wrong internal href fragment links
|
||||
* #5104: apidoc: Interface of ``sphinx.apidoc:main()`` has changed
|
||||
* #4272: PDF builds of French projects have issues with XeTeX
|
||||
* #5076: napoleon raises RuntimeError with python 3.7
|
||||
* #5125: sphinx-build: Interface of ``sphinx:main()`` has changed
|
||||
* sphinx-build: ``sphinx.cmd.build.main()`` refers ``sys.argv`` instead of given
|
||||
@ -212,9 +242,14 @@ Bugs fixed
|
||||
* autosummary: warnings of autosummary indicates wrong location (refs: #5146)
|
||||
* #5143: autodoc: crashed on inspecting dict like object which does not support
|
||||
sorting
|
||||
|
||||
Testing
|
||||
--------
|
||||
* #5139: autodoc: Enum argument missing if it shares value with another
|
||||
* #4946: py domain: rtype field could not handle "None" as a type
|
||||
* #5176: LaTeX: indexing of terms containing ``@``, ``!``, or ``"`` fails
|
||||
* #5161: html: crashes if copying static files are failed
|
||||
* #5167: autodoc: Fix formatting type annotations for tuples with more than two
|
||||
arguments
|
||||
* #3329: i18n: crashed by auto-symbol footnote references
|
||||
* #5158: autosummary: module summary has been broken when it starts with heading
|
||||
|
||||
Release 1.7.5 (released May 29, 2018)
|
||||
=====================================
|
||||
|
@ -64,14 +64,10 @@ latex_elements = {
|
||||
'passoptionstopackages': '\\PassOptionsToPackage{svgnames}{xcolor}',
|
||||
'preamble': '\\DeclareUnicodeCharacter{229E}{\\ensuremath{\\boxplus}}',
|
||||
'fvset': '\\fvset{fontsize=auto}',
|
||||
# fix missing index entry due to RTD doing only once pdflatex after makeindex
|
||||
'printindex': r'''
|
||||
\IfFileExists{\jobname.ind}
|
||||
{\footnotesize\raggedright\printindex}
|
||||
{\begin{sphinxtheindex}\end{sphinxtheindex}}
|
||||
''',
|
||||
'printindex': '\\footnotesize\\raggedright\\sphinxprintindex',
|
||||
}
|
||||
latex_show_urls = 'footnote'
|
||||
latex_use_xindy = True
|
||||
|
||||
autodoc_member_order = 'groupwise'
|
||||
todo_include_todos = True
|
||||
|
@ -50,6 +50,10 @@ Logging API
|
||||
If true, the logger does not fold lines at the end of the log message.
|
||||
The default is ``False``.
|
||||
|
||||
**location**
|
||||
Where the message emitted. For more detail, see
|
||||
:meth:`SphinxLoggerAdapter.warning`.
|
||||
|
||||
**color**
|
||||
The color of logs. By default, debug level logs are
|
||||
colored as ``"darkgray"``, and debug2 level ones are ``"lightgray"``.
|
||||
|
@ -12,7 +12,7 @@ __ http://docutils.sourceforge.net/docs/dev/hacking.html#parsing-the-document
|
||||
|
||||
In Sphinx, the parser modules works as same as docutils. The parsers are
|
||||
registered to Sphinx by extensions using Application APIs;
|
||||
:meth:`.Sphinx.add_source_suffix()` and :meth:`.Sphinx.add_source_parsers()`.
|
||||
:meth:`.Sphinx.add_source_suffix()` and :meth:`.Sphinx.add_source_parser()`.
|
||||
|
||||
The *source suffix* is a mapping from file suffix to file type. For example,
|
||||
``.rst`` file is mapped to ``'restructuredtext'`` type. Sphinx uses the
|
||||
|
@ -55,7 +55,7 @@ example::
|
||||
\setlength{\cftsecnumwidth}{1.25cm}
|
||||
''',
|
||||
'fncychap': r'\usepackage[Bjornstrup]{fncychap}',
|
||||
'printindex': r'\footnotesize\raggedright\printindex',
|
||||
'printindex': r'\footnotesize\raggedright\sphinxprintindex',
|
||||
}
|
||||
latex_show_urls = 'footnote'
|
||||
|
||||
@ -399,6 +399,23 @@ Macros
|
||||
:file:`sphinxmanual.cls` and :file:`sphinxhowto.cls`.
|
||||
- the citation reference is typeset via ``\sphinxcite`` which is a wrapper
|
||||
of standard ``\cite``.
|
||||
- regarding the general index, the :confval:`latex_elements` dictionary has a
|
||||
``'printindex'`` key which defaults to ``'\\sphinxprintindex'``. It often
|
||||
proves advantageous to use::
|
||||
|
||||
'printindex': '\\footnotesize\\raggedright\\sphinxprintindex',
|
||||
|
||||
especially if the index contains long entries. The LaTeX class for Japanese
|
||||
``'manual'``-type documents already does the font size and text
|
||||
justification change, so the above is not needed then.
|
||||
|
||||
.. tip::
|
||||
|
||||
Advanced LaTeX users can also, via :confval:`latex_additional_files`, use
|
||||
a custom :program:`makeindex` style file :file:`python.ist`, or a custom
|
||||
:program:`xindy` style file :file:`sphinx.xdy` (see
|
||||
:confval:`latex_use_xindy`) in order to modify how the general index is
|
||||
typeset.
|
||||
|
||||
Environments
|
||||
~~~~~~~~~~~~
|
||||
@ -453,7 +470,8 @@ Environments
|
||||
- the bibliography uses ``sphinxthebibliography`` and the Python Module index
|
||||
as well as the general index both use ``sphinxtheindex``; these environments
|
||||
are wrappers of the ``thebibliography`` and respectively ``theindex``
|
||||
environments as provided by the document class (or packages).
|
||||
environments, needed mainly to insert a corresponding entry in the PDF
|
||||
bookmarks and table of contents.
|
||||
|
||||
.. versionchanged:: 1.5
|
||||
formerly, the original environments were modified by Sphinx.
|
||||
|
@ -1727,8 +1727,8 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
|
||||
Options for LaTeX output
|
||||
------------------------
|
||||
|
||||
These options influence LaTeX output. Refer to :doc:`/latex` for more
|
||||
information.
|
||||
These options influence LaTeX output. For customization of LaTeX
|
||||
macros and environments, see also :doc:`/latex`.
|
||||
|
||||
.. confval:: latex_engine
|
||||
|
||||
@ -1872,6 +1872,40 @@ information.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
.. confval:: latex_use_xindy
|
||||
|
||||
If ``True``, the PDF build from the LaTeX files created by Sphinx
|
||||
will use :program:`xindy` (doc__) rather than :program:`makeindex`
|
||||
for preparing the index of general terms (from :rst:dir:`index`
|
||||
usage). This means that words with UTF-8 characters will get
|
||||
ordered correctly for the :confval:`language`.
|
||||
|
||||
__ http://xindy.sourceforge.net/
|
||||
|
||||
- This option is ignored if :confval:`latex_engine` is ``'platex'``
|
||||
(Japanese documents) as :program:`mendex` is used in that case.
|
||||
|
||||
- The default is ``True`` for ``'xelatex'`` or ``'lualatex'`` as
|
||||
:program:`makeindex`, if any indexed term starts with a non-ascii
|
||||
character, creates ``.ind`` file containing invalid bytes for
|
||||
UTF-8 encoding. With ``'lualatex'`` this then breaks the PDF
|
||||
build. Notice that :program:`xindy` supports most but not
|
||||
all European languages.
|
||||
|
||||
- The default is ``False`` for ``'pdflatex'`` but ``True`` is
|
||||
recommended for non-English documents as soon as some indexed
|
||||
terms use non-ascii characters from the language script.
|
||||
Cyrillic scripts are (transparently) supported with
|
||||
``'pdflatex'`` thanks to a specific Sphinx-contributed ``xindy``
|
||||
style file :file:`cyrLICRutf8.xdy`.
|
||||
|
||||
As :program:`xindy` does not support the same range of languages
|
||||
as ``LaTeX/babel`` does, the default :program:`makeindex` for
|
||||
``'pdflatex'`` may be preferred in some circumstances, although
|
||||
the index will be ill-formed probably.
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
.. confval:: latex_elements
|
||||
|
||||
.. versionadded:: 0.5
|
||||
@ -2108,11 +2142,14 @@ information.
|
||||
Remove unneeded ``{}`` after ``\\hrule``.
|
||||
|
||||
``'printindex'``
|
||||
"printindex" call, the last thing in the file, default
|
||||
``'\\printindex'``. Override if you want to generate the index
|
||||
differently or append some content after the index. For example
|
||||
``'\\footnotesize\\raggedright\\printindex'`` is advisable when the
|
||||
index is full of long entries.
|
||||
"printindex" call, the last thing in the file.
|
||||
|
||||
.. versionchanged:: 1.8
|
||||
Former default ``'\\printindex'`` now ``'\\sphinxprintindex'``.
|
||||
This macro works around an issue__ with PDF builds at RTD doing too
|
||||
few ``pdflatex`` runs.
|
||||
|
||||
__ https://github.com/rtfd/readthedocs.org/issues/2857
|
||||
|
||||
``'fvset'``
|
||||
Customization of ``fancyvrb`` LaTeX package. Defaults to
|
||||
|
@ -127,7 +127,7 @@ directory in which you want to place the built documentation.
|
||||
The :option:`-b <sphinx-build -b>` option selects a builder; in this example
|
||||
Sphinx will build HTML files.
|
||||
|
||||
|more| Refer to the :program:`sphinx-build man page <sphinx-build>` for all
|
||||
|more| Refer to the :doc:`sphinx-build man page </man/sphinx-build>` for all
|
||||
options that :program:`sphinx-build` supports.
|
||||
|
||||
However, :program:`sphinx-quickstart` script creates a :file:`Makefile` and a
|
||||
@ -331,7 +331,7 @@ More topics to be covered
|
||||
|
||||
.. [#] This is the usual layout. However, :file:`conf.py` can also live in
|
||||
another directory, the :term:`configuration directory`. Refer to the
|
||||
:program:`sphinx-build man page <sphinx-build>` for more information.
|
||||
:doc:`sphinx-build man page </man/sphinx-build>` for more information.
|
||||
|
||||
.. |more| image:: /_static/more.png
|
||||
:align: middle
|
||||
|
@ -31,7 +31,7 @@ directory = sphinx/locale/
|
||||
|
||||
[flake8]
|
||||
max-line-length = 95
|
||||
ignore = E116,E241,E251,E741,I101
|
||||
ignore = E116,E241,E251,E741,W504,I101
|
||||
exclude = .git,.tox,.venv,tests/*,build/*,doc/_build/*,sphinx/search/*,doc/usage/extensions/example*.py
|
||||
application-import-names = sphinx
|
||||
import-order-style = smarkets
|
||||
|
@ -848,85 +848,94 @@ class StandaloneHTMLBuilder(Builder):
|
||||
try:
|
||||
copyfile(path.join(self.srcdir, src),
|
||||
path.join(self.outdir, '_downloads', dest))
|
||||
except Exception as err:
|
||||
except EnvironmentError as err:
|
||||
logger.warning(__('cannot copy downloadable file %r: %s'),
|
||||
path.join(self.srcdir, src), err)
|
||||
|
||||
def copy_static_files(self):
|
||||
# type: () -> None
|
||||
# copy static files
|
||||
logger.info(bold(__('copying static files... ')), nonl=True)
|
||||
ensuredir(path.join(self.outdir, '_static'))
|
||||
# first, create pygments style file
|
||||
with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f:
|
||||
f.write(self.highlighter.get_stylesheet()) # type: ignore
|
||||
# then, copy translations JavaScript file
|
||||
if self.config.language is not None:
|
||||
jsfile = self._get_translations_js()
|
||||
if jsfile:
|
||||
copyfile(jsfile, path.join(self.outdir, '_static',
|
||||
'translations.js'))
|
||||
try:
|
||||
# copy static files
|
||||
logger.info(bold(__('copying static files... ')), nonl=True)
|
||||
ensuredir(path.join(self.outdir, '_static'))
|
||||
# first, create pygments style file
|
||||
with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f:
|
||||
f.write(self.highlighter.get_stylesheet()) # type: ignore
|
||||
# then, copy translations JavaScript file
|
||||
if self.config.language is not None:
|
||||
jsfile = self._get_translations_js()
|
||||
if jsfile:
|
||||
copyfile(jsfile, path.join(self.outdir, '_static',
|
||||
'translations.js'))
|
||||
|
||||
# copy non-minified stemmer JavaScript file
|
||||
if self.indexer is not None:
|
||||
jsfile = self.indexer.get_js_stemmer_rawcode()
|
||||
if jsfile:
|
||||
copyfile(jsfile, path.join(self.outdir, '_static', '_stemmer.js'))
|
||||
# copy non-minified stemmer JavaScript file
|
||||
if self.indexer is not None:
|
||||
jsfile = self.indexer.get_js_stemmer_rawcode()
|
||||
if jsfile:
|
||||
copyfile(jsfile, path.join(self.outdir, '_static', '_stemmer.js'))
|
||||
|
||||
ctx = self.globalcontext.copy()
|
||||
ctx = self.globalcontext.copy()
|
||||
|
||||
# add context items for search function used in searchtools.js_t
|
||||
if self.indexer is not None:
|
||||
ctx.update(self.indexer.context_for_searchtool())
|
||||
# add context items for search function used in searchtools.js_t
|
||||
if self.indexer is not None:
|
||||
ctx.update(self.indexer.context_for_searchtool())
|
||||
|
||||
# then, copy over theme-supplied static files
|
||||
if self.theme:
|
||||
for theme_path in self.theme.get_theme_dirs()[::-1]:
|
||||
entry = path.join(theme_path, 'static')
|
||||
copy_asset(entry, path.join(self.outdir, '_static'), excluded=DOTFILES,
|
||||
# then, copy over theme-supplied static files
|
||||
if self.theme:
|
||||
for theme_path in self.theme.get_theme_dirs()[::-1]:
|
||||
entry = path.join(theme_path, 'static')
|
||||
copy_asset(entry, path.join(self.outdir, '_static'), excluded=DOTFILES,
|
||||
context=ctx, renderer=self.templates)
|
||||
# then, copy over all user-supplied static files
|
||||
excluded = Matcher(self.config.exclude_patterns + ["**/.*"])
|
||||
for static_path in self.config.html_static_path:
|
||||
entry = path.join(self.confdir, static_path)
|
||||
if not path.exists(entry):
|
||||
logger.warning(__('html_static_path entry %r does not exist'), entry)
|
||||
continue
|
||||
copy_asset(entry, path.join(self.outdir, '_static'), excluded,
|
||||
context=ctx, renderer=self.templates)
|
||||
# then, copy over all user-supplied static files
|
||||
excluded = Matcher(self.config.exclude_patterns + ["**/.*"])
|
||||
for static_path in self.config.html_static_path:
|
||||
entry = path.join(self.confdir, static_path)
|
||||
if not path.exists(entry):
|
||||
logger.warning(__('html_static_path entry %r does not exist'), entry)
|
||||
continue
|
||||
copy_asset(entry, path.join(self.outdir, '_static'), excluded,
|
||||
context=ctx, renderer=self.templates)
|
||||
# copy logo and favicon files if not already in static path
|
||||
if self.config.html_logo:
|
||||
logobase = path.basename(self.config.html_logo)
|
||||
logotarget = path.join(self.outdir, '_static', logobase)
|
||||
if not path.isfile(path.join(self.confdir, self.config.html_logo)):
|
||||
logger.warning(__('logo file %r does not exist'), self.config.html_logo)
|
||||
elif not path.isfile(logotarget):
|
||||
copyfile(path.join(self.confdir, self.config.html_logo),
|
||||
logotarget)
|
||||
if self.config.html_favicon:
|
||||
iconbase = path.basename(self.config.html_favicon)
|
||||
icontarget = path.join(self.outdir, '_static', iconbase)
|
||||
if not path.isfile(path.join(self.confdir, self.config.html_favicon)):
|
||||
logger.warning(__('favicon file %r does not exist'), self.config.html_favicon)
|
||||
elif not path.isfile(icontarget):
|
||||
copyfile(path.join(self.confdir, self.config.html_favicon),
|
||||
icontarget)
|
||||
logger.info('done')
|
||||
# copy logo and favicon files if not already in static path
|
||||
if self.config.html_logo:
|
||||
logobase = path.basename(self.config.html_logo)
|
||||
logotarget = path.join(self.outdir, '_static', logobase)
|
||||
if not path.isfile(path.join(self.confdir, self.config.html_logo)):
|
||||
logger.warning(__('logo file %r does not exist'), self.config.html_logo)
|
||||
elif not path.isfile(logotarget):
|
||||
copyfile(path.join(self.confdir, self.config.html_logo),
|
||||
logotarget)
|
||||
if self.config.html_favicon:
|
||||
iconbase = path.basename(self.config.html_favicon)
|
||||
icontarget = path.join(self.outdir, '_static', iconbase)
|
||||
if not path.isfile(path.join(self.confdir, self.config.html_favicon)):
|
||||
logger.warning(__('favicon file %r does not exist'),
|
||||
self.config.html_favicon)
|
||||
elif not path.isfile(icontarget):
|
||||
copyfile(path.join(self.confdir, self.config.html_favicon),
|
||||
icontarget)
|
||||
logger.info('done')
|
||||
except EnvironmentError as err:
|
||||
# TODO: In py3, EnvironmentError (and IOError) was merged into OSError.
|
||||
# So it should be replaced by IOError on dropping py2 support
|
||||
logger.warning(__('cannot copy static file %r'), err)
|
||||
|
||||
def copy_extra_files(self):
|
||||
# type: () -> None
|
||||
# copy html_extra_path files
|
||||
logger.info(bold(__('copying extra files... ')), nonl=True)
|
||||
excluded = Matcher(self.config.exclude_patterns)
|
||||
try:
|
||||
# copy html_extra_path files
|
||||
logger.info(bold(__('copying extra files... ')), nonl=True)
|
||||
excluded = Matcher(self.config.exclude_patterns)
|
||||
|
||||
for extra_path in self.config.html_extra_path:
|
||||
entry = path.join(self.confdir, extra_path)
|
||||
if not path.exists(entry):
|
||||
logger.warning(__('html_extra_path entry %r does not exist'), entry)
|
||||
continue
|
||||
for extra_path in self.config.html_extra_path:
|
||||
entry = path.join(self.confdir, extra_path)
|
||||
if not path.exists(entry):
|
||||
logger.warning(__('html_extra_path entry %r does not exist'), entry)
|
||||
continue
|
||||
|
||||
copy_asset(entry, self.outdir, excluded)
|
||||
logger.info(__('done'))
|
||||
copy_asset(entry, self.outdir, excluded)
|
||||
logger.info(__('done'))
|
||||
except EnvironmentError as err:
|
||||
logger.warning(__('cannot copy extra file %r'), err)
|
||||
|
||||
def write_buildinfo(self):
|
||||
# type: () -> None
|
||||
|
@ -44,6 +44,67 @@ if False:
|
||||
from sphinx.config import Config # NOQA
|
||||
|
||||
|
||||
XINDY_LANG_OPTIONS = {
|
||||
# language codes from docutils.writers.latex2e.Babel
|
||||
# ! xindy language names may differ from those in use by LaTeX/babel
|
||||
# ! xindy does not support all Latin scripts as recognized by LaTeX/babel
|
||||
# ! not all xindy-supported languages appear in Babel.language_codes
|
||||
# cd /usr/local/texlive/2018/texmf-dist/xindy/modules/lang
|
||||
# find . -name '*utf8.xdy'
|
||||
# LATIN
|
||||
'sq': '-L albanian -C utf8 ',
|
||||
'hr': '-L croatian -C utf8 ',
|
||||
'cs': '-L czech -C utf8 ',
|
||||
'da': '-L danish -C utf8 ',
|
||||
'nl': '-L dutch -C ij-as-ij-utf8 ',
|
||||
'en': '-L english -C utf8 ',
|
||||
'eo': '-L esperanto -C utf8 ',
|
||||
'et': '-L estonian -C utf8 ',
|
||||
'fi': '-L finnish -C utf8 ',
|
||||
'fr': '-L french -C utf8 ',
|
||||
'de': '-L german -C din5007-utf8 ',
|
||||
'is': '-L icelandic -C utf8 ',
|
||||
'it': '-L italian -C utf8 ',
|
||||
'la': '-L latin -C utf8 ',
|
||||
'lv': '-L latvian -C utf8 ',
|
||||
'lt': '-L lithuanian -C utf8 ',
|
||||
'dsb': '-L lower-sorbian -C utf8 ',
|
||||
'ds': '-L lower-sorbian -C utf8 ', # trick, no conflict
|
||||
'nb': '-L norwegian -C utf8 ',
|
||||
'no': '-L norwegian -C utf8 ', # and what about nynorsk?
|
||||
'pl': '-L polish -C utf8 ',
|
||||
'pt': '-L portuguese -C utf8 ',
|
||||
'ro': '-L romanian -C utf8 ',
|
||||
'sk': '-L slovak -C small-utf8 ', # there is also slovak-large
|
||||
'sl': '-L slovenian -C utf8 ',
|
||||
'es': '-L spanish -C modern-utf8 ', # there is also spanish-traditional
|
||||
'sv': '-L swedish -C utf8 ',
|
||||
'tr': '-L turkish -C utf8 ',
|
||||
'hsb': '-L upper-sorbian -C utf8 ',
|
||||
'hs': '-L upper-sorbian -C utf8 ', # trick, no conflict
|
||||
'vi': '-L vietnamese -C utf8 ',
|
||||
# CYRILLIC
|
||||
# for usage with pdflatex, needs also cyrLICRutf8.xdy module
|
||||
'be': '-L belarusian -C utf8 ',
|
||||
'bg': '-L bulgarian -C utf8 ',
|
||||
'mk': '-L macedonian -C utf8 ',
|
||||
'mn': '-L mongolian -C cyrillic-utf8 ',
|
||||
'ru': '-L russian -C utf8 ',
|
||||
'sr': '-L serbian -C utf8 ',
|
||||
'sh-cyrl': '-L serbian -C utf8 ',
|
||||
'sh': '-L serbian -C utf8 ', # trick, no conflict
|
||||
'uk': '-L ukrainian -C utf8 ',
|
||||
# GREEK
|
||||
# can work only with xelatex/lualatex, not supported by texindy+pdflatex
|
||||
'el': '-L greek -C utf8 ',
|
||||
# FIXME, not compatible with [:2] slice but does Sphinx support Greek ?
|
||||
'el-polyton': '-L greek -C polytonic-utf8 ',
|
||||
} # type: Dict[unicode, unicode]
|
||||
|
||||
XINDY_CYRILLIC_SCRIPTS = [
|
||||
'be', 'bg', 'mk', 'mn', 'ru', 'sr', 'sh', 'uk',
|
||||
] # type: List[unicode]
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -232,7 +293,23 @@ class LaTeXBuilder(Builder):
|
||||
self.copy_image_files()
|
||||
|
||||
# copy TeX support files from texinputs
|
||||
context = {'latex_engine': self.config.latex_engine}
|
||||
# configure usage of xindy (impacts Makefile and latexmkrc)
|
||||
# FIXME: convert this rather to a confval with suitable default
|
||||
# according to language ? but would require extra documentation
|
||||
if self.config.language:
|
||||
xindy_lang_option = \
|
||||
XINDY_LANG_OPTIONS.get(self.config.language[:2],
|
||||
'-L general -C utf8 ')
|
||||
xindy_cyrillic = self.config.language[:2] in XINDY_CYRILLIC_SCRIPTS
|
||||
else:
|
||||
xindy_lang_option = '-L english -C utf8 '
|
||||
xindy_cyrillic = False
|
||||
context = {
|
||||
'latex_engine': self.config.latex_engine,
|
||||
'xindy_use': self.config.latex_use_xindy,
|
||||
'xindy_lang_option': xindy_lang_option,
|
||||
'xindy_cyrillic': xindy_cyrillic,
|
||||
}
|
||||
logger.info(bold(__('copying TeX support files...')))
|
||||
staticdirname = path.join(package_dir, 'texinputs')
|
||||
for filename in os.listdir(staticdirname):
|
||||
@ -317,6 +394,12 @@ def default_latex_docclass(config):
|
||||
return {}
|
||||
|
||||
|
||||
def default_latex_use_xindy(config):
|
||||
# type: (Config) -> bool
|
||||
""" Better default latex_use_xindy settings for specific engines. """
|
||||
return config.latex_engine in {'xelatex', 'lualatex'}
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[unicode, Any]
|
||||
app.add_builder(LaTeXBuilder)
|
||||
@ -334,6 +417,7 @@ def setup(app):
|
||||
app.add_config_value('latex_logo', None, None, string_classes)
|
||||
app.add_config_value('latex_appendices', [], None)
|
||||
app.add_config_value('latex_use_latex_multicolumn', False, None)
|
||||
app.add_config_value('latex_use_xindy', default_latex_use_xindy, None)
|
||||
app.add_config_value('latex_toplevel_sectioning', None, None,
|
||||
ENUM(None, 'part', 'chapter', 'section'))
|
||||
app.add_config_value('latex_domain_indices', True, None, [list])
|
||||
|
@ -160,7 +160,7 @@ class CheckExternalLinksBuilder(Builder):
|
||||
# the server and the network
|
||||
response = requests.head(req_url, config=self.app.config, **kwargs)
|
||||
response.raise_for_status()
|
||||
except HTTPError as err:
|
||||
except HTTPError:
|
||||
# retry with GET request if that fails, some servers
|
||||
# don't like HEAD requests.
|
||||
response = requests.get(req_url, stream=True, config=self.app.config,
|
||||
|
@ -168,7 +168,15 @@ class PyXrefMixin(object):
|
||||
|
||||
|
||||
class PyField(PyXrefMixin, Field):
|
||||
pass
|
||||
def make_xref(self, rolename, domain, target,
|
||||
innernode=nodes.emphasis, contnode=None, env=None):
|
||||
# type: (unicode, unicode, unicode, nodes.Node, nodes.Node, BuildEnvironment) -> nodes.Node # NOQA
|
||||
if rolename == 'class' and target == 'None':
|
||||
# None is not a type, so use obj role instead.
|
||||
rolename = 'obj'
|
||||
|
||||
return super(PyField, self).make_xref(rolename, domain, target,
|
||||
innernode, contnode, env)
|
||||
|
||||
|
||||
class PyGroupedField(PyXrefMixin, GroupedField):
|
||||
|
@ -25,7 +25,7 @@ from sphinx import addnodes
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning, RemovedInSphinx30Warning
|
||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
from sphinx.errors import SphinxError, BuildEnvironmentError, ExtensionError
|
||||
from sphinx.errors import SphinxError, BuildEnvironmentError, DocumentError, ExtensionError
|
||||
from sphinx.locale import __
|
||||
from sphinx.transforms import SphinxTransformer
|
||||
from sphinx.util import get_matching_docs, FilenameUniqDict
|
||||
@ -416,37 +416,40 @@ class BuildEnvironment(object):
|
||||
"""Find all source files in the source dir and put them in
|
||||
self.found_docs.
|
||||
"""
|
||||
matchers = compile_matchers(
|
||||
config.exclude_patterns[:] +
|
||||
config.templates_path +
|
||||
builder.get_asset_paths() +
|
||||
['**/_sources', '.#*', '**/.#*', '*.lproj/**']
|
||||
)
|
||||
self.found_docs = set()
|
||||
for docname in get_matching_docs(self.srcdir, config.source_suffix, # type: ignore
|
||||
exclude_matchers=matchers):
|
||||
if os.access(self.doc2path(docname), os.R_OK):
|
||||
self.found_docs.add(docname)
|
||||
else:
|
||||
logger.warning(__("document not readable. Ignored."), location=docname)
|
||||
try:
|
||||
matchers = compile_matchers(
|
||||
config.exclude_patterns[:] +
|
||||
config.templates_path +
|
||||
builder.get_asset_paths() +
|
||||
['**/_sources', '.#*', '**/.#*', '*.lproj/**']
|
||||
)
|
||||
self.found_docs = set()
|
||||
for docname in get_matching_docs(self.srcdir, config.source_suffix, # type: ignore
|
||||
exclude_matchers=matchers):
|
||||
if os.access(self.doc2path(docname), os.R_OK):
|
||||
self.found_docs.add(docname)
|
||||
else:
|
||||
logger.warning(__("document not readable. Ignored."), location=docname)
|
||||
|
||||
# Current implementation is applying translated messages in the reading
|
||||
# phase.Therefore, in order to apply the updated message catalog, it is
|
||||
# necessary to re-process from the reading phase. Here, if dependency
|
||||
# is set for the doc source and the mo file, it is processed again from
|
||||
# the reading phase when mo is updated. In the future, we would like to
|
||||
# move i18n process into the writing phase, and remove these lines.
|
||||
if builder.use_message_catalog:
|
||||
# add catalog mo file dependency
|
||||
for docname in self.found_docs:
|
||||
catalog_files = find_catalog_files(
|
||||
docname,
|
||||
self.srcdir,
|
||||
self.config.locale_dirs,
|
||||
self.config.language,
|
||||
self.config.gettext_compact)
|
||||
for filename in catalog_files:
|
||||
self.dependencies[docname].add(filename)
|
||||
# Current implementation is applying translated messages in the reading
|
||||
# phase.Therefore, in order to apply the updated message catalog, it is
|
||||
# necessary to re-process from the reading phase. Here, if dependency
|
||||
# is set for the doc source and the mo file, it is processed again from
|
||||
# the reading phase when mo is updated. In the future, we would like to
|
||||
# move i18n process into the writing phase, and remove these lines.
|
||||
if builder.use_message_catalog:
|
||||
# add catalog mo file dependency
|
||||
for docname in self.found_docs:
|
||||
catalog_files = find_catalog_files(
|
||||
docname,
|
||||
self.srcdir,
|
||||
self.config.locale_dirs,
|
||||
self.config.language,
|
||||
self.config.gettext_compact)
|
||||
for filename in catalog_files:
|
||||
self.dependencies[docname].add(filename)
|
||||
except EnvironmentError as exc:
|
||||
raise DocumentError(__('Failed to scan documents in %s: %r') % (self.srcdir, exc))
|
||||
|
||||
def get_outdated_files(self, config_changed):
|
||||
# type: (bool) -> Tuple[Set[unicode], Set[unicode], Set[unicode]]
|
||||
|
@ -82,6 +82,11 @@ class ConfigError(SphinxError):
|
||||
category = 'Configuration error'
|
||||
|
||||
|
||||
class DocumentError(SphinxError):
|
||||
"""Document error."""
|
||||
category = 'Document error'
|
||||
|
||||
|
||||
class ThemeError(SphinxError):
|
||||
"""Theme error."""
|
||||
category = 'Theme error'
|
||||
|
@ -221,12 +221,21 @@ def get_object_members(subject, objpath, attrgetter, analyzer=None):
|
||||
for name, value in subject.__members__.items():
|
||||
obj_dict[name] = value
|
||||
|
||||
members = {}
|
||||
members = {} # type: Dict[str, Attribute]
|
||||
|
||||
# enum members
|
||||
if isenumclass(subject):
|
||||
for name, value in subject.__members__.items():
|
||||
if name not in members:
|
||||
members[name] = Attribute(name, True, value)
|
||||
|
||||
# other members
|
||||
for name in dir(subject):
|
||||
try:
|
||||
value = attrgetter(subject, name)
|
||||
directly_defined = name in obj_dict
|
||||
members[name] = Attribute(name, directly_defined, value)
|
||||
if name not in members:
|
||||
members[name] = Attribute(name, directly_defined, value)
|
||||
except AttributeError:
|
||||
continue
|
||||
|
||||
|
@ -473,21 +473,32 @@ def extract_summary(doc, document):
|
||||
doc = doc[:i]
|
||||
break
|
||||
|
||||
# Try to find the "first sentence", which may span multiple lines
|
||||
sentences = periods_re.split(" ".join(doc)) # type: ignore
|
||||
if len(sentences) == 1:
|
||||
summary = sentences[0].strip()
|
||||
if doc == []:
|
||||
return ''
|
||||
|
||||
# parse the docstring
|
||||
state_machine = RSTStateMachine(state_classes, 'Body')
|
||||
node = new_document('', document.settings)
|
||||
node.reporter = NullReporter()
|
||||
state_machine.run(doc, node)
|
||||
|
||||
if not isinstance(node[0], nodes.paragraph):
|
||||
# document starts with non-paragraph: pick up the first line
|
||||
summary = doc[0].strip()
|
||||
else:
|
||||
summary = ''
|
||||
state_machine = RSTStateMachine(state_classes, 'Body')
|
||||
while sentences:
|
||||
summary += sentences.pop(0) + '.'
|
||||
node = new_document('', document.settings)
|
||||
node.reporter = NullReporter()
|
||||
state_machine.run([summary], node)
|
||||
if not node.traverse(nodes.system_message):
|
||||
# considered as that splitting by period does not break inline markups
|
||||
break
|
||||
# Try to find the "first sentence", which may span multiple lines
|
||||
sentences = periods_re.split(" ".join(doc)) # type: ignore
|
||||
if len(sentences) == 1:
|
||||
summary = sentences[0].strip()
|
||||
else:
|
||||
summary = ''
|
||||
while sentences:
|
||||
summary += sentences.pop(0) + '.'
|
||||
node[:] = []
|
||||
state_machine.run([summary], node)
|
||||
if not node.traverse(nodes.system_message):
|
||||
# considered as that splitting by period does not break inline markups
|
||||
break
|
||||
|
||||
# strip literal notation mark ``::`` from tail of summary
|
||||
summary = literal_re.sub('.', summary)
|
||||
|
@ -269,7 +269,7 @@ def find_autosummary_in_docstring(name, module=None, filename=None):
|
||||
pass
|
||||
except ImportError as e:
|
||||
print("Failed to import '%s': %s" % (name, e))
|
||||
except SystemExit as e:
|
||||
except SystemExit:
|
||||
print("Failed to import '%s'; the module executes module level "
|
||||
"statement and it might call sys.exit()." % name)
|
||||
return []
|
||||
|
@ -39,6 +39,7 @@ if False:
|
||||
from docutils.transforms import Transform # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.builders import Builder # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.domains import Domain, Index # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
from sphinx.ext.autodoc import Documenter # NOQA
|
||||
@ -270,7 +271,7 @@ class SphinxComponentRegistry(object):
|
||||
# type: (unicode, unicode, bool) -> None
|
||||
logger.debug('[app] adding source_suffix: %r, %r', suffix, filetype)
|
||||
if suffix in self.source_suffix and not override:
|
||||
raise ExtensionError(__('source_parser for %r is already registered') % suffix)
|
||||
raise ExtensionError(__('source_suffix %r is already registered') % suffix)
|
||||
else:
|
||||
self.source_suffix[suffix] = filetype
|
||||
|
||||
@ -290,7 +291,7 @@ class SphinxComponentRegistry(object):
|
||||
parser = args[1]
|
||||
|
||||
if suffix:
|
||||
self.add_source_suffix(suffix, suffix)
|
||||
self.add_source_suffix(suffix, suffix, override=True)
|
||||
|
||||
if len(parser.supported) == 0:
|
||||
warnings.warn('Old source_parser has been detected. Please fill Parser.supported '
|
||||
@ -493,8 +494,8 @@ class SphinxComponentRegistry(object):
|
||||
return envversion
|
||||
|
||||
|
||||
def merge_source_suffix(app):
|
||||
# type: (Sphinx) -> None
|
||||
def merge_source_suffix(app, config):
|
||||
# type: (Sphinx, Config) -> None
|
||||
"""Merge source_suffix which specified by user and added by extensions."""
|
||||
for suffix, filetype in iteritems(app.registry.source_suffix):
|
||||
if suffix not in app.config.source_suffix:
|
||||
@ -510,7 +511,7 @@ def merge_source_suffix(app):
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[unicode, Any]
|
||||
app.connect('builder-inited', merge_source_suffix)
|
||||
app.connect('config-inited', merge_source_suffix)
|
||||
|
||||
return {
|
||||
'version': 'builtin',
|
||||
|
@ -13,6 +13,11 @@
|
||||
\ifdefined\pdfpxdimen
|
||||
\let\sphinxpxdimen\pdfpxdimen\else\newdimen\sphinxpxdimen
|
||||
\fi \sphinxpxdimen=<%= pxunit %>\relax
|
||||
<% if use_xindy -%>
|
||||
%% turn off hyperref patch of \index as sphinx.xdy xindy module takes care of
|
||||
%% suitable \hyperpage mark-up, working around hyperref-xindy incompatibility
|
||||
\PassOptionsToPackage{hyperindex=false}{hyperref}
|
||||
<% endif -%>
|
||||
<%= passoptionstopackages %>
|
||||
\PassOptionsToPackage{warn}{textcomp}
|
||||
<%= inputenc %>
|
||||
@ -31,7 +36,7 @@
|
||||
<%= hyperref %>
|
||||
<%= contentsname %>
|
||||
<%= numfig_format %>
|
||||
<%= literalblockpto %>
|
||||
<%= translatablestrings %>
|
||||
<%= pageautorefname %>
|
||||
<%= tocdepth %>
|
||||
<%= secnumdepth %>
|
||||
|
@ -22,6 +22,15 @@ export LATEXOPTS =
|
||||
# or on command line for faster builds.
|
||||
{% endif -%}
|
||||
LATEXMKOPTS =
|
||||
{% if xindy_use -%}
|
||||
export XINDYOPTS = {{ xindy_lang_option }} -M sphinx.xdy
|
||||
{% if latex_engine == 'pdflatex' and xindy_cyrillic -%}
|
||||
XINDYOPTS += -M cyrLICRutf8.xdy
|
||||
{% endif -%}
|
||||
{% if latex_engine == 'xelatex' or latex_engine == 'lualatex' -%}
|
||||
XINDYOPTS += -I xelatex
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
# format: pdf or dvi (used only by archive targets)
|
||||
FMT = pdf
|
||||
|
||||
|
101
sphinx/texinputs/cyrLICRutf8.xdy
Normal file
101
sphinx/texinputs/cyrLICRutf8.xdy
Normal file
@ -0,0 +1,101 @@
|
||||
;; -*- coding: utf-8; mode: Lisp; -*-
|
||||
;; style file for xindy
|
||||
;; filename: cyrLICRutf8.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.
|
||||
;; Contributed by the Sphinx team, July 2018.
|
||||
(merge-rule "\IeC {\'\CYRG }" "Ѓ" :string)
|
||||
(merge-rule "\IeC {\'\CYRK }" "Ќ" :string)
|
||||
(merge-rule "\IeC {\'\cyrg }" "ѓ" :string)
|
||||
(merge-rule "\IeC {\'\cyrk }" "ќ" :string)
|
||||
(merge-rule "\IeC {\CYRA }" "А" :string)
|
||||
(merge-rule "\IeC {\CYRB }" "Б" :string)
|
||||
(merge-rule "\IeC {\CYRC }" "Ц" :string)
|
||||
(merge-rule "\IeC {\CYRCH }" "Ч" :string)
|
||||
(merge-rule "\IeC {\CYRD }" "Д" :string)
|
||||
(merge-rule "\IeC {\CYRDJE }" "Ђ" :string)
|
||||
(merge-rule "\IeC {\CYRDZE }" "Ѕ" :string)
|
||||
(merge-rule "\IeC {\CYRDZHE }" "Џ" :string)
|
||||
(merge-rule "\IeC {\CYRE }" "Е" :string)
|
||||
(merge-rule "\IeC {\CYREREV }" "Э" :string)
|
||||
(merge-rule "\IeC {\CYRERY }" "Ы" :string)
|
||||
(merge-rule "\IeC {\CYRF }" "Ф" :string)
|
||||
(merge-rule "\IeC {\CYRG }" "Г" :string)
|
||||
(merge-rule "\IeC {\CYRGUP }" "Ґ" :string)
|
||||
(merge-rule "\IeC {\CYRH }" "Х" :string)
|
||||
(merge-rule "\IeC {\CYRHRDSN }" "Ъ" :string)
|
||||
(merge-rule "\IeC {\CYRI }" "И" :string)
|
||||
(merge-rule "\IeC {\CYRIE }" "Є" :string)
|
||||
(merge-rule "\IeC {\CYRII }" "І" :string)
|
||||
(merge-rule "\IeC {\CYRISHRT }" "Й" :string)
|
||||
(merge-rule "\IeC {\CYRJE }" "Ј" :string)
|
||||
(merge-rule "\IeC {\CYRK }" "К" :string)
|
||||
(merge-rule "\IeC {\CYRL }" "Л" :string)
|
||||
(merge-rule "\IeC {\CYRLJE }" "Љ" :string)
|
||||
(merge-rule "\IeC {\CYRM }" "М" :string)
|
||||
(merge-rule "\IeC {\CYRN }" "Н" :string)
|
||||
(merge-rule "\IeC {\CYRNJE }" "Њ" :string)
|
||||
(merge-rule "\IeC {\CYRO }" "О" :string)
|
||||
(merge-rule "\IeC {\CYRP }" "П" :string)
|
||||
(merge-rule "\IeC {\CYRR }" "Р" :string)
|
||||
(merge-rule "\IeC {\CYRS }" "С" :string)
|
||||
(merge-rule "\IeC {\CYRSFTSN }" "Ь" :string)
|
||||
(merge-rule "\IeC {\CYRSH }" "Ш" :string)
|
||||
(merge-rule "\IeC {\CYRSHCH }" "Щ" :string)
|
||||
(merge-rule "\IeC {\CYRT }" "Т" :string)
|
||||
(merge-rule "\IeC {\CYRTSHE }" "Ћ" :string)
|
||||
(merge-rule "\IeC {\CYRU }" "У" :string)
|
||||
(merge-rule "\IeC {\CYRUSHRT }" "Ў" :string)
|
||||
(merge-rule "\IeC {\CYRV }" "В" :string)
|
||||
(merge-rule "\IeC {\CYRYA }" "Я" :string)
|
||||
(merge-rule "\IeC {\CYRYI }" "Ї" :string)
|
||||
(merge-rule "\IeC {\CYRYO }" "Ё" :string)
|
||||
(merge-rule "\IeC {\CYRYU }" "Ю" :string)
|
||||
(merge-rule "\IeC {\CYRZ }" "З" :string)
|
||||
(merge-rule "\IeC {\CYRZH }" "Ж" :string)
|
||||
(merge-rule "\IeC {\cyra }" "а" :string)
|
||||
(merge-rule "\IeC {\cyrb }" "б" :string)
|
||||
(merge-rule "\IeC {\cyrc }" "ц" :string)
|
||||
(merge-rule "\IeC {\cyrch }" "ч" :string)
|
||||
(merge-rule "\IeC {\cyrd }" "д" :string)
|
||||
(merge-rule "\IeC {\cyrdje }" "ђ" :string)
|
||||
(merge-rule "\IeC {\cyrdze }" "ѕ" :string)
|
||||
(merge-rule "\IeC {\cyrdzhe }" "џ" :string)
|
||||
(merge-rule "\IeC {\cyre }" "е" :string)
|
||||
(merge-rule "\IeC {\cyrerev }" "э" :string)
|
||||
(merge-rule "\IeC {\cyrery }" "ы" :string)
|
||||
(merge-rule "\IeC {\cyrf }" "ф" :string)
|
||||
(merge-rule "\IeC {\cyrg }" "г" :string)
|
||||
(merge-rule "\IeC {\cyrgup }" "ґ" :string)
|
||||
(merge-rule "\IeC {\cyrh }" "х" :string)
|
||||
(merge-rule "\IeC {\cyrhrdsn }" "ъ" :string)
|
||||
(merge-rule "\IeC {\cyri }" "и" :string)
|
||||
(merge-rule "\IeC {\cyrie }" "є" :string)
|
||||
(merge-rule "\IeC {\cyrii }" "і" :string)
|
||||
(merge-rule "\IeC {\cyrishrt }" "й" :string)
|
||||
(merge-rule "\IeC {\cyrje }" "ј" :string)
|
||||
(merge-rule "\IeC {\cyrk }" "к" :string)
|
||||
(merge-rule "\IeC {\cyrl }" "л" :string)
|
||||
(merge-rule "\IeC {\cyrlje }" "љ" :string)
|
||||
(merge-rule "\IeC {\cyrm }" "м" :string)
|
||||
(merge-rule "\IeC {\cyrn }" "н" :string)
|
||||
(merge-rule "\IeC {\cyrnje }" "њ" :string)
|
||||
(merge-rule "\IeC {\cyro }" "о" :string)
|
||||
(merge-rule "\IeC {\cyrp }" "п" :string)
|
||||
(merge-rule "\IeC {\cyrr }" "р" :string)
|
||||
(merge-rule "\IeC {\cyrs }" "с" :string)
|
||||
(merge-rule "\IeC {\cyrsftsn }" "ь" :string)
|
||||
(merge-rule "\IeC {\cyrsh }" "ш" :string)
|
||||
(merge-rule "\IeC {\cyrshch }" "щ" :string)
|
||||
(merge-rule "\IeC {\cyrt }" "т" :string)
|
||||
(merge-rule "\IeC {\cyrtshe }" "ћ" :string)
|
||||
(merge-rule "\IeC {\cyru }" "у" :string)
|
||||
(merge-rule "\IeC {\cyrushrt }" "ў" :string)
|
||||
(merge-rule "\IeC {\cyrv }" "в" :string)
|
||||
(merge-rule "\IeC {\cyrya }" "я" :string)
|
||||
(merge-rule "\IeC {\cyryi }" "ї" :string)
|
||||
(merge-rule "\IeC {\cyryo }" "ё" :string)
|
||||
(merge-rule "\IeC {\cyryu }" "ю" :string)
|
||||
(merge-rule "\IeC {\cyrz }" "з" :string)
|
||||
(merge-rule "\IeC {\cyrzh }" "ж" :string)
|
@ -10,7 +10,11 @@ $pdflatex = 'xelatex ' . $ENV{'LATEXOPTS'} . ' %O %S';
|
||||
{% endif -%}
|
||||
$lualatex = 'lualatex ' . $ENV{'LATEXOPTS'} . ' %O %S';
|
||||
$xelatex = 'xelatex --no-pdf ' . $ENV{'LATEXOPTS'} . ' %O %S';
|
||||
{% if xindy_use -%}
|
||||
$makeindex = 'xindy ' . $ENV{'XINDYOPTS'} . ' %O -o %D %S';
|
||||
{% else -%}
|
||||
$makeindex = 'makeindex -s python.ist %O -o %D %S';
|
||||
{% endif -%}
|
||||
add_cus_dep( "glo", "gls", 0, "makeglo" );
|
||||
sub makeglo {
|
||||
return system( "makeindex -s gglo.ist -o '$_[0].gls' '$_[0].glo'" );
|
||||
|
@ -3,11 +3,11 @@ headings_flag 1
|
||||
heading_prefix " \\bigletter "
|
||||
|
||||
preamble "\\begin{sphinxtheindex}
|
||||
\\def\\bigletter#1{{\\Large\\sffamily#1}\\nopagebreak\\vspace{1mm}}
|
||||
\\let\\bigletter\\sphinxstyleindexlettergroup
|
||||
|
||||
"
|
||||
|
||||
postamble "\n\n\\end{sphinxtheindex}\n"
|
||||
|
||||
symhead_positive "{Symbols}"
|
||||
numhead_positive "{Numbers}"
|
||||
symhead_positive "{\\sphinxsymbolsname}"
|
||||
numhead_positive "{\\sphinxnumbersname}"
|
||||
|
@ -6,7 +6,7 @@
|
||||
%
|
||||
|
||||
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||
\ProvidesPackage{sphinx}[2018/03/28 v1.8 LaTeX package (Sphinx markup)]
|
||||
\ProvidesPackage{sphinx}[2018/06/30 v1.8 LaTeX package (Sphinx markup)]
|
||||
|
||||
% provides \ltx@ifundefined
|
||||
% (many packages load ltxcmds: graphicx does for pdftex and lualatex but
|
||||
@ -459,6 +459,14 @@
|
||||
}
|
||||
\fi
|
||||
|
||||
% provide \sphinxprintindex as variant of \printindex designed to workaround
|
||||
% rtfd/readthedocs.org#2857 regarding "Index" entry in PDF bookmarks
|
||||
\newcommand*{\sphinxprintindex}{%
|
||||
\IfFileExists{\jobname.ind}
|
||||
{\printindex}
|
||||
{\begin{sphinxtheindex}\end{sphinxtheindex}}%
|
||||
}%
|
||||
|
||||
% make commands known to non-Sphinx document classes
|
||||
\providecommand*{\sphinxtableofcontents}{\tableofcontents}
|
||||
\ltx@ifundefined{sphinxthebibliography}
|
||||
@ -470,6 +478,11 @@
|
||||
{\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}}%
|
||||
{}% else clause of \ltx@ifundefined
|
||||
|
||||
% for usage with xindy: this string gets internationalized in preamble
|
||||
\newcommand*{\sphinxnonalphabeticalgroupname}{}
|
||||
% redefined in preamble, headings for makeindex produced index
|
||||
\newcommand*{\sphinxsymbolsname}{}
|
||||
\newcommand*{\sphinxnumbersname}{}
|
||||
|
||||
%% COLOR (general)
|
||||
%
|
||||
@ -1591,10 +1604,13 @@
|
||||
{\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}}
|
||||
|
||||
% additional customizable styling
|
||||
% FIXME: convert this to package options ?
|
||||
\protected\def\sphinxstyleindexentry #1{\texttt{#1}}
|
||||
\protected\def\sphinxstyleindexextra #1{ \emph{(#1)}}
|
||||
\protected\def\sphinxstyleindexpageref #1{, \pageref{#1}}
|
||||
\def\sphinxstyleindexentry #1{\texttt{#1}}
|
||||
\def\sphinxstyleindexextra #1{ \emph{(#1)}}
|
||||
\def\sphinxstyleindexpageref #1{, \pageref{#1}}
|
||||
\def\sphinxstyleindexlettergroup #1%
|
||||
{{\Large\sffamily#1}\nopagebreak\vspace{1mm}}
|
||||
\def\sphinxstyleindexlettergroupDefault #1%
|
||||
{{\Large\sffamily\sphinxnonalphabeticalgroupname}\nopagebreak\vspace{1mm}}
|
||||
\protected\def\sphinxstyletopictitle #1{\textbf{#1}\par\medskip}
|
||||
\let\sphinxstylesidebartitle\sphinxstyletopictitle
|
||||
\protected\def\sphinxstyleothertitle #1{\textbf{#1}}
|
||||
|
141
sphinx/texinputs/sphinx.xdy
Normal file
141
sphinx/texinputs/sphinx.xdy
Normal file
@ -0,0 +1,141 @@
|
||||
;;; -*- mode: lisp; coding: utf-8; -*-
|
||||
|
||||
;; Unfortunately xindy is out-of-the-box hyperref-incompatible. This
|
||||
;; configuration is a workaround, which requires to pass option
|
||||
;; hyperindex=false to hyperref.
|
||||
;; textit and emph not currently used by Sphinx LaTeX writer.
|
||||
(define-attributes (("textbf" "textit" "emph" "default")))
|
||||
(markup-locref :open "\textbf{\hyperpage{" :close "}}" :attr "textbf")
|
||||
(markup-locref :open "\textit{\hyperpage{" :close "}}" :attr "textit")
|
||||
(markup-locref :open "\emph{\hyperpage{" :close "}}" :attr "emph")
|
||||
(markup-locref :open "\hyperpage{" :close "}" :attr "default")
|
||||
|
||||
(require "numeric-sort.xdy")
|
||||
|
||||
;; xindy base module latex.xdy loads tex.xdy and the latter instructs
|
||||
;; xindy to ignore **all** TeX macros in .idx entries, except those
|
||||
;; explicitely described in merge rule. But when after applying all
|
||||
;; merge rules an empty string results, xindy raises an error:
|
||||
|
||||
;; ERROR: CHAR: index 0 should be less than the length of the string
|
||||
|
||||
;; For example when using pdflatex with utf-8 characters the index
|
||||
;; file will contain \IeC macros and they will get ignored except if
|
||||
;; suitable merge rules are loaded early. The texindy script coming
|
||||
;; with xindy provides this, but only for Latin scripts. The texindy
|
||||
;; man page says to use rather xelatex or lualatex in case of Cyrillic
|
||||
;; scripts.
|
||||
|
||||
;; Sphinx contributes cyrLICRutf8.xdy to provide support for Cyrillic
|
||||
;; scripts for the pdflatex engine.
|
||||
|
||||
;; Another issue caused by xindy ignoring all TeX macros except those
|
||||
;; explicitely declared reveals itself when attempting to index ">>>",
|
||||
;; as the ">" is converted to "\textgreater{}" by Sphinx's LaTeX
|
||||
;; escaping.
|
||||
|
||||
;; To fix this, Sphinx does **not** use texindy, and does not even
|
||||
;; load the xindy latex.xdy base module.
|
||||
|
||||
;(require "latex.xdy")
|
||||
|
||||
;; Rather it incorporates some suitable extracts from latex.xdy and
|
||||
;; tex.xdy with additional Sphinx contributed rules.
|
||||
|
||||
;;;;;;;; extracts from tex.xdy (discarding most original comments):
|
||||
|
||||
;;;
|
||||
;;; TeX conventions
|
||||
;;;
|
||||
|
||||
;; Discard leading and trailing white space. Collapse multiple white
|
||||
;; space characters to blank.
|
||||
|
||||
(merge-rule "^ +" "" :eregexp)
|
||||
(merge-rule " +$" "" :eregexp)
|
||||
(merge-rule " +" " " :eregexp)
|
||||
|
||||
;; Handle TeX markup
|
||||
|
||||
(merge-rule "\\([{}$%&#])" "\1" :eregexp)
|
||||
|
||||
;;;;;;;; end of extracts from xindy's tex.xdy
|
||||
|
||||
;;;;;;;; extracts from latex.xdy:
|
||||
|
||||
;; Standard location classes: arabic and roman numbers, and alphabets.
|
||||
|
||||
(define-location-class "arabic-page-numbers" ("arabic-numbers"))
|
||||
(define-location-class "roman-page-numbers" ("roman-numbers-lowercase"))
|
||||
(define-location-class "Roman-page-numbers" ("roman-numbers-uppercase"))
|
||||
(define-location-class "alpha-page-numbers" ("alpha"))
|
||||
(define-location-class "Alpha-page-numbers" ("ALPHA"))
|
||||
|
||||
;; Output Markup
|
||||
|
||||
(markup-letter-group-list :sep "~n~n \indexspace~n")
|
||||
|
||||
(markup-indexentry :open "~n \item " :depth 0)
|
||||
(markup-indexentry :open "~n \subitem " :depth 1)
|
||||
(markup-indexentry :open "~n \subsubitem " :depth 2)
|
||||
|
||||
(markup-locclass-list :open ", " :sep ", ")
|
||||
(markup-locref-list :sep ", ")
|
||||
|
||||
;;;;;;;; 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.
|
||||
|
||||
;; Details of the syntax are explained at
|
||||
;; http://xindy.sourceforge.net/doc/manual-3.html
|
||||
;; In absence of :string, "xindy uses an auto-detection mechanism to decide,
|
||||
;; if the pattern is a regular expression or not". But it is not obvious to
|
||||
;; 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...
|
||||
|
||||
(merge-rule "\sphinxleftcurlybrace{}" "{" :string)
|
||||
(merge-rule "\sphinxrightcurlybrace{}" "}" :string)
|
||||
(merge-rule "\_" "_" :string)
|
||||
(merge-rule "{[}" "[" :string)
|
||||
(merge-rule "{]}" "]" :string)
|
||||
(merge-rule "{}`" "`" :string)
|
||||
(merge-rule "\textbackslash{}" "\" :string) ; " for Emacs syntax highlighting
|
||||
(merge-rule "\textasciitilde{}" "~~" :string); the ~~ escape is needed here
|
||||
(merge-rule "\textless{}" "<" :string)
|
||||
(merge-rule "\textgreater{}" ">" :string)
|
||||
(merge-rule "\textasciicircum{}" "^" :string)
|
||||
(merge-rule "\P{}" "¶" :string)
|
||||
(merge-rule "\S{}" "§" :string)
|
||||
(merge-rule "\texteuro{}" "€" :string)
|
||||
(merge-rule "\(\infty\)" "∞" :string)
|
||||
(merge-rule "\(\pm\)" "±" :string)
|
||||
(merge-rule "\(\rightarrow\)" "→" :string)
|
||||
(merge-rule "\(\checkmark\)" "✓" :string)
|
||||
(merge-rule "\textendash{}" "–" :string)
|
||||
(merge-rule "\textbar{}" "|" :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.
|
||||
(require "latin-lettergroups.xdy")
|
||||
|
||||
;; currently we don't (know how to easily) separate "Numbers" from
|
||||
;; "Symbols" with xindy as is the case with makeindex.
|
||||
(markup-index :open "\begin{sphinxtheindex}
|
||||
\let\lettergroup\sphinxstyleindexlettergroup
|
||||
\let\lettergroupDefault\sphinxstyleindexlettergroupDefault
|
||||
|
||||
"
|
||||
:close "
|
||||
|
||||
\end{sphinxtheindex}
|
||||
"
|
||||
:tree)
|
||||
|
@ -276,10 +276,9 @@ class Locale(SphinxTransform):
|
||||
continue # skip
|
||||
|
||||
# auto-numbered foot note reference should use original 'ids'.
|
||||
def is_autonumber_footnote_ref(node):
|
||||
def is_autofootnote_ref(node):
|
||||
# type: (nodes.Node) -> bool
|
||||
return isinstance(node, nodes.footnote_reference) and \
|
||||
node.get('auto') == 1
|
||||
return isinstance(node, nodes.footnote_reference) and node.get('auto')
|
||||
|
||||
def list_replace_or_append(lst, old, new):
|
||||
# type: (List, Any, Any) -> None
|
||||
@ -287,8 +286,8 @@ class Locale(SphinxTransform):
|
||||
lst[lst.index(old)] = new
|
||||
else:
|
||||
lst.append(new)
|
||||
old_foot_refs = node.traverse(is_autonumber_footnote_ref)
|
||||
new_foot_refs = patch.traverse(is_autonumber_footnote_ref)
|
||||
old_foot_refs = node.traverse(is_autofootnote_ref)
|
||||
new_foot_refs = patch.traverse(is_autofootnote_ref)
|
||||
if len(old_foot_refs) != len(new_foot_refs):
|
||||
old_foot_ref_rawsources = [ref.rawsource for ref in old_foot_refs]
|
||||
new_foot_ref_rawsources = [ref.rawsource for ref in new_foot_refs]
|
||||
@ -309,8 +308,14 @@ class Locale(SphinxTransform):
|
||||
new['ids'] = old['ids']
|
||||
for id in new['ids']:
|
||||
self.document.ids[id] = new
|
||||
list_replace_or_append(
|
||||
self.document.autofootnote_refs, old, new)
|
||||
|
||||
if new['auto'] == 1:
|
||||
# autofootnote_refs
|
||||
list_replace_or_append(self.document.autofootnote_refs, old, new)
|
||||
else:
|
||||
# symbol_footnote_refs
|
||||
list_replace_or_append(self.document.symbol_footnote_refs, old, new)
|
||||
|
||||
if refname:
|
||||
list_replace_or_append(
|
||||
self.document.footnote_refs.setdefault(refname, []),
|
||||
|
@ -532,6 +532,13 @@ class Signature(object):
|
||||
|
||||
if annotation.__module__ == 'builtins':
|
||||
return annotation.__qualname__ # type: ignore
|
||||
elif (hasattr(typing, 'TupleMeta') and
|
||||
isinstance(annotation, typing.TupleMeta) and # type: ignore
|
||||
not hasattr(annotation, '__tuple_params__')):
|
||||
# This is for Python 3.6+, 3.5 case is handled below
|
||||
params = annotation.__args__
|
||||
param_str = ', '.join(self.format_annotation(p) for p in params)
|
||||
return '%s[%s]' % (qualified_name, param_str)
|
||||
elif (hasattr(typing, 'GenericMeta') and # for py36 or below
|
||||
isinstance(annotation, typing.GenericMeta)):
|
||||
# In Python 3.5.2+, all arguments are stored in __args__,
|
||||
|
@ -24,7 +24,7 @@ from sphinx.util.console import colorize
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, Generator, IO, List, Tuple, Union # NOQA
|
||||
from typing import Any, Dict, Generator, IO, List, Tuple, Type, Union # NOQA
|
||||
from docutils import nodes # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
@ -94,22 +94,33 @@ def convert_serializable(records):
|
||||
r.location = get_node_location(location) # type: ignore
|
||||
|
||||
|
||||
class SphinxWarningLogRecord(logging.LogRecord):
|
||||
class SphinxLogRecord(logging.LogRecord):
|
||||
"""Log record class supporting location"""
|
||||
prefix = ''
|
||||
location = None # type: Any
|
||||
|
||||
def getMessage(self):
|
||||
# type: () -> str
|
||||
message = super(SphinxWarningLogRecord, self).getMessage()
|
||||
message = super(SphinxLogRecord, self).getMessage()
|
||||
location = getattr(self, 'location', None)
|
||||
if location:
|
||||
message = '%s: WARNING: %s' % (location, message)
|
||||
elif 'WARNING:' not in message:
|
||||
message = 'WARNING: %s' % message
|
||||
message = '%s: %s%s' % (location, self.prefix, message)
|
||||
elif self.prefix not in message:
|
||||
message = self.prefix + message
|
||||
|
||||
return message
|
||||
|
||||
|
||||
class SphinxInfoLogRecord(SphinxLogRecord):
|
||||
"""Info log record class supporting location"""
|
||||
prefix = '' # do not show any prefix for INFO messages
|
||||
|
||||
|
||||
class SphinxWarningLogRecord(SphinxLogRecord):
|
||||
"""Warning log record class supporting location"""
|
||||
prefix = 'WARNING: '
|
||||
|
||||
|
||||
class SphinxLoggerAdapter(logging.LoggerAdapter):
|
||||
"""LoggerAdapter allowing ``type`` and ``subtype`` keywords."""
|
||||
|
||||
@ -412,21 +423,23 @@ class DisableWarningIsErrorFilter(logging.Filter):
|
||||
return True
|
||||
|
||||
|
||||
class WarningLogRecordTranslator(logging.Filter):
|
||||
class SphinxLogRecordTranslator(logging.Filter):
|
||||
"""Converts a log record to one Sphinx expects
|
||||
|
||||
* Make a instance of SphinxWarningLogRecord
|
||||
* Make a instance of SphinxLogRecord
|
||||
* docname to path if location given
|
||||
"""
|
||||
LogRecordClass = None # type: Type[logging.LogRecord]
|
||||
|
||||
def __init__(self, app):
|
||||
# type: (Sphinx) -> None
|
||||
self.app = app
|
||||
super(WarningLogRecordTranslator, self).__init__()
|
||||
super(SphinxLogRecordTranslator, self).__init__()
|
||||
|
||||
def filter(self, record): # type: ignore
|
||||
# type: (SphinxWarningLogRecord) -> bool
|
||||
if isinstance(record, logging.LogRecord):
|
||||
record.__class__ = SphinxWarningLogRecord # force subclassing to handle location
|
||||
record.__class__ = self.LogRecordClass # force subclassing to handle location
|
||||
|
||||
location = getattr(record, 'location', None)
|
||||
if isinstance(location, tuple):
|
||||
@ -445,6 +458,16 @@ class WarningLogRecordTranslator(logging.Filter):
|
||||
return True
|
||||
|
||||
|
||||
class InfoLogRecordTranslator(SphinxLogRecordTranslator):
|
||||
"""LogRecordTranslator for INFO level log records."""
|
||||
LogRecordClass = SphinxInfoLogRecord
|
||||
|
||||
|
||||
class WarningLogRecordTranslator(SphinxLogRecordTranslator):
|
||||
"""LogRecordTranslator for WARNING level log records."""
|
||||
LogRecordClass = SphinxWarningLogRecord
|
||||
|
||||
|
||||
def get_node_location(node):
|
||||
# type: (nodes.Node) -> str
|
||||
(source, line) = get_source_line(node)
|
||||
@ -518,6 +541,7 @@ def setup(app, status, warning):
|
||||
|
||||
info_handler = NewLineStreamHandler(SafeEncodingWriter(status)) # type: ignore
|
||||
info_handler.addFilter(InfoFilter())
|
||||
info_handler.addFilter(InfoLogRecordTranslator(app))
|
||||
info_handler.setLevel(VERBOSITY_MAP[app.verbosity])
|
||||
info_handler.setFormatter(ColorizeFormatter())
|
||||
|
||||
|
@ -124,13 +124,13 @@ DEFAULT_SETTINGS = {
|
||||
'maketitle': '\\maketitle',
|
||||
'tableofcontents': '\\sphinxtableofcontents',
|
||||
'atendofbody': '',
|
||||
'printindex': '\\printindex',
|
||||
'printindex': '\\sphinxprintindex',
|
||||
'transition': '\n\n\\bigskip\\hrule\\bigskip\n\n',
|
||||
'figure_align': 'htbp',
|
||||
'tocdepth': '',
|
||||
'secnumdepth': '',
|
||||
'pageautorefname': '',
|
||||
'literalblockpto': '',
|
||||
'translatablestrings': '',
|
||||
} # type: Dict[unicode, unicode]
|
||||
|
||||
ADDITIONAL_SETTINGS = {
|
||||
@ -485,6 +485,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
# sort out some elements
|
||||
self.elements = DEFAULT_SETTINGS.copy()
|
||||
self.elements.update(ADDITIONAL_SETTINGS.get(builder.config.latex_engine, {}))
|
||||
# for xelatex+French, don't use polyglossia
|
||||
if self.elements['latex_engine'] == 'xelatex':
|
||||
if builder.config.language:
|
||||
if builder.config.language[:2] == 'fr':
|
||||
self.elements.update({
|
||||
'polyglossia': '',
|
||||
'babel': '\\usepackage{babel}',
|
||||
})
|
||||
# allow the user to override them all
|
||||
self.check_latex_elements()
|
||||
self.elements.update(builder.config.latex_elements)
|
||||
@ -497,6 +505,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
'release': self.encode(builder.config.release),
|
||||
'author': document.settings.author, # treat as a raw LaTeX code
|
||||
'indexname': _('Index'),
|
||||
'use_xindy': builder.config.latex_use_xindy,
|
||||
})
|
||||
if not self.elements['releasename'] and self.elements['release']:
|
||||
self.elements.update({
|
||||
@ -667,12 +676,21 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
if self.elements['extraclassoptions']:
|
||||
self.elements['classoptions'] += ',' + \
|
||||
self.elements['extraclassoptions']
|
||||
self.elements['literalblockpto'] = (
|
||||
self.elements['translatablestrings'] = (
|
||||
self.babel_renewcommand(
|
||||
'\\literalblockcontinuedname', self.encode(_('continued from previous page'))
|
||||
) +
|
||||
self.babel_renewcommand(
|
||||
'\\literalblockcontinuesname', self.encode(_('continues on next page'))
|
||||
) +
|
||||
self.babel_renewcommand(
|
||||
'\\sphinxnonalphabeticalgroupname', self.encode(_('Non-alphabetical'))
|
||||
) +
|
||||
self.babel_renewcommand(
|
||||
'\\sphinxsymbolsname', self.encode(_('Symbols'))
|
||||
) +
|
||||
self.babel_renewcommand(
|
||||
'\\sphinxnumbersname', self.encode(_('Numbers'))
|
||||
)
|
||||
)
|
||||
self.elements['pageautorefname'] = \
|
||||
@ -856,8 +874,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
def generate(content, collapsed):
|
||||
# type: (List[Tuple[unicode, List[Tuple[unicode, unicode, unicode, unicode, unicode]]]], bool) -> None # NOQA
|
||||
ret.append('\\begin{sphinxtheindex}\n')
|
||||
ret.append('\\def\\bigletter#1{{\\Large\\sffamily#1}'
|
||||
'\\nopagebreak\\vspace{1mm}}\n')
|
||||
ret.append('\\let\\bigletter\\sphinxstyleindexlettergroup\n')
|
||||
for i, (letter, entries) in enumerate(content):
|
||||
if i > 0:
|
||||
ret.append('\\indexspace\n')
|
||||
@ -866,7 +883,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
for entry in entries:
|
||||
if not entry[3]:
|
||||
continue
|
||||
ret.append('\\item {\\sphinxstyleindexentry{%s}}' % self.encode(entry[0]))
|
||||
ret.append('\\item\\relax\\sphinxstyleindexentry{%s}' %
|
||||
self.encode(entry[0]))
|
||||
if entry[4]:
|
||||
# add "extra" info
|
||||
ret.append('\\sphinxstyleindexextra{%s}' % self.encode(entry[4]))
|
||||
@ -1919,8 +1937,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
# type: (nodes.Node, Pattern) -> None
|
||||
def escape(value):
|
||||
value = self.encode(value)
|
||||
value = value.replace(r'\{', r'{\sphinxleftcurlybrace}')
|
||||
value = value.replace(r'\}', r'{\sphinxrightcurlybrace}')
|
||||
value = value.replace(r'\{', r'\sphinxleftcurlybrace{}')
|
||||
value = value.replace(r'\}', r'\sphinxrightcurlybrace{}')
|
||||
value = value.replace('"', '""')
|
||||
value = value.replace('@', '"@')
|
||||
value = value.replace('!', '"!')
|
||||
return value
|
||||
|
||||
if not node.get('inline', True):
|
||||
|
@ -233,3 +233,4 @@ class EnumCls(enum.Enum):
|
||||
val2 = 23 #: doc for val2
|
||||
val3 = 34
|
||||
"""doc for val3"""
|
||||
val4 = 34
|
||||
|
@ -19,8 +19,8 @@ msgstr ""
|
||||
msgid "i18n with Footnote"
|
||||
msgstr "I18N WITH FOOTNOTE"
|
||||
|
||||
msgid "[100]_ Contents [#]_ for `i18n with Footnote`_ [ref]_ [#named]_."
|
||||
msgstr "`I18N WITH FOOTNOTE`_ INCLUDE THIS CONTENTS [#named]_ [ref]_ [#]_ [100]_."
|
||||
msgid "[100]_ Contents [#]_ for `i18n with Footnote`_ [ref]_ [#named]_ [*]_."
|
||||
msgstr "`I18N WITH FOOTNOTE`_ INCLUDE THIS CONTENTS [#named]_ [ref]_ [#]_ [100]_ [*]_."
|
||||
|
||||
msgid "This is a auto numbered footnote."
|
||||
msgstr "THIS IS A AUTO NUMBERED FOOTNOTE."
|
||||
@ -34,3 +34,5 @@ msgstr "THIS IS A NUMBERED FOOTNOTE."
|
||||
msgid "This is a auto numbered named footnote."
|
||||
msgstr "THIS IS A AUTO NUMBERED NAMED FOOTNOTE."
|
||||
|
||||
msgid "This is a auto symbol footnote."
|
||||
msgstr "THIS IS A AUTO SYMBOL FOOTNOTE."
|
||||
|
@ -4,9 +4,10 @@ i18n with Footnote
|
||||
==================
|
||||
.. #955 cant-build-html-with-footnotes-when-using
|
||||
|
||||
[100]_ Contents [#]_ for `i18n with Footnote`_ [ref]_ [#named]_.
|
||||
[100]_ Contents [#]_ for `i18n with Footnote`_ [ref]_ [#named]_ [*]_.
|
||||
|
||||
.. [#] This is a auto numbered footnote.
|
||||
.. [ref] This is a named footnote.
|
||||
.. [100] This is a numbered footnote.
|
||||
.. [#named] This is a auto numbered named footnote.
|
||||
.. [*] This is a auto symbol footnote.
|
||||
|
@ -873,13 +873,14 @@ def test_generate():
|
||||
# test members with enum attributes
|
||||
directive.env.ref_context['py:module'] = 'target'
|
||||
options.inherited_members = False
|
||||
options.undoc_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')
|
||||
|
@ -1201,7 +1201,7 @@ def test_latex_index(app, status, warning):
|
||||
result = (app.outdir / 'Python.tex').text(encoding='utf8')
|
||||
assert 'A \\index{famous}famous \\index{equation}equation:\n' in result
|
||||
assert '\n\\index{Einstein}\\index{relativity}\\ignorespaces \nand' in result
|
||||
assert '\n\\index{main {\\sphinxleftcurlybrace}}\\ignorespaces ' in result
|
||||
assert '\n\\index{main \\sphinxleftcurlybrace{}}\\ignorespaces ' in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='latex-equations')
|
||||
|
@ -85,6 +85,11 @@ def test_extract_summary(capsys):
|
||||
doc = ['blah blah::']
|
||||
assert extract_summary(doc, document) == 'blah blah.'
|
||||
|
||||
# heading
|
||||
doc = ['blah blah',
|
||||
'=========']
|
||||
assert extract_summary(doc, document) == 'blah blah'
|
||||
|
||||
_, err = capsys.readouterr()
|
||||
assert err == ''
|
||||
|
||||
|
@ -794,7 +794,7 @@ def test_xml_footnotes(app, warning):
|
||||
assert_elem(
|
||||
para0[0],
|
||||
['I18N WITH FOOTNOTE', 'INCLUDE THIS CONTENTS',
|
||||
'2', '[ref]', '1', '100', '.'],
|
||||
'2', '[ref]', '1', '100', '*', '.'],
|
||||
['i18n-with-footnote', 'ref'])
|
||||
|
||||
footnote0 = secs[0].findall('footnote')
|
||||
@ -813,6 +813,11 @@ def test_xml_footnotes(app, warning):
|
||||
['2', 'THIS IS A AUTO NUMBERED NAMED FOOTNOTE.'],
|
||||
None,
|
||||
['named'])
|
||||
assert_elem(
|
||||
footnote0[3],
|
||||
['*', 'THIS IS A AUTO SYMBOL FOOTNOTE.'],
|
||||
None,
|
||||
None)
|
||||
|
||||
citation0 = secs[0].findall('citation')
|
||||
assert_elem(
|
||||
|
@ -231,7 +231,7 @@ def test_Signature_partialmethod():
|
||||
@pytest.mark.skipif(sys.version_info < (3, 5),
|
||||
reason='type annotation test is available on py35 or above')
|
||||
def test_Signature_annotations():
|
||||
from typing_test_data import f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11
|
||||
from typing_test_data import f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12
|
||||
|
||||
# Class annotations
|
||||
sig = inspect.Signature(f0).format_args()
|
||||
@ -284,6 +284,10 @@ def test_Signature_annotations():
|
||||
sig = inspect.Signature(f11, has_retval=False).format_args()
|
||||
assert sig == '(x: CustomAnnotation, y: 123)'
|
||||
|
||||
# tuple with more than two items
|
||||
sig = inspect.Signature(f12).format_args()
|
||||
assert sig == '() -> Tuple[int, str, int]'
|
||||
|
||||
|
||||
def test_safe_getattr_with_default():
|
||||
class Foo(object):
|
||||
|
@ -171,6 +171,37 @@ def test_warningiserror(app, status, warning):
|
||||
logger.warning('%s')
|
||||
|
||||
|
||||
def test_info_location(app, status, warning):
|
||||
logging.setup(app, status, warning)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
logger.info('message1', location='index')
|
||||
assert 'index.txt: message1' in status.getvalue()
|
||||
|
||||
logger.info('message2', location=('index', 10))
|
||||
assert 'index.txt:10: message2' in status.getvalue()
|
||||
|
||||
logger.info('message3', location=None)
|
||||
assert '\nmessage3' in status.getvalue()
|
||||
|
||||
node = nodes.Node()
|
||||
node.source, node.line = ('index.txt', 10)
|
||||
logger.info('message4', location=node)
|
||||
assert 'index.txt:10: message4' in status.getvalue()
|
||||
|
||||
node.source, node.line = ('index.txt', None)
|
||||
logger.info('message5', location=node)
|
||||
assert 'index.txt:: message5' in status.getvalue()
|
||||
|
||||
node.source, node.line = (None, 10)
|
||||
logger.info('message6', location=node)
|
||||
assert '<unknown>:10: message6' in status.getvalue()
|
||||
|
||||
node.source, node.line = (None, None)
|
||||
logger.info('message7', location=node)
|
||||
assert '\nmessage7' in status.getvalue()
|
||||
|
||||
|
||||
def test_warning_location(app, status, warning):
|
||||
logging.setup(app, status, warning)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -62,3 +62,7 @@ class CustomAnnotation:
|
||||
|
||||
def f11(x: CustomAnnotation(), y: 123) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def f12() -> Tuple[int, str, int]:
|
||||
pass
|
||||
|
Loading…
Reference in New Issue
Block a user