Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Marco Buttu
2017-01-24 13:20:03 +01:00
39 changed files with 627 additions and 240 deletions

53
CHANGES
View File

@@ -8,6 +8,8 @@ Incompatible changes
members by default. Thanks to Luc Saffre.
* LaTeX ``\includegraphics`` command isn't overloaded: only ``\sphinxincludegraphics``
has the custom code to fit image to available width if oversized.
* The subclasses of ``sphinx.domains.Index`` should override ``generate()``
method. The default implementation raises NotImplmentedError
Features removed
----------------
@@ -38,6 +40,8 @@ Features added
* #3136: Add ``:name:`` option to the directives in ``sphinx.ext.graphviz``
* #2336: Add ``imported_members`` option to ``sphinx-autogen`` command to document
imported members.
* C++, add ``:tparam-line-spec:`` option to templated declarations.
When specified, each template parameter will be rendered on a separate line.
Bugs fixed
----------
@@ -55,9 +59,28 @@ Deprecated
instead (as Sphinx does since 1.5.)
* ``Sphinx.status_iterator()` and ``Sphinx.old_status_iterator()`` is now
deprecated. Please use ``sphinx.util:status_iterator()`` intead.
* ``BuildEnvironment.set_warnfunc()`` is now deprecated
Release 1.5.2 (in development)
===============================
Release 1.5.3 (in development)
==============================
Incompatible changes
--------------------
Deprecated
----------
Features added
--------------
Bugs fixed
----------
Testing
--------
Release 1.5.2 (released Jan 22, 2017)
=====================================
Incompatible changes
--------------------
@@ -71,6 +94,8 @@ Features added
* #3194: Refer the $MAKE environment variable to determine ``make`` command
* Emit warning for nested numbered toctrees (refs: #3142)
* #978: `intersphinx_mapping` also allows a list as a parameter
* #3340: (LaTeX) long lines in :dudir:`parsed-literal` are wrapped like in
:rst:dir:`code-block`, inline math and footnotes are fully functional.
Bugs fixed
----------
@@ -90,7 +115,25 @@ Bugs fixed
unserializable exception
* #3315: Bibliography crashes on latex build with docclass 'memoir'
* #3328: Could not refer rubric implicitly
* #3329: emit warnings if po file is invalid and can't read it. Also writing mo too.
* #3329: emit warnings if po file is invalid and can't read it. Also writing mo too
* #3337: Ugly rendering of definition list term's classifier
* #3335: gettext does not extract field_name of a field in a field_list
* #2952: C++, fix refs to operator() functions.
* Fix Unicode super- and subscript digits in :rst:dir:`code-block` and
parsed-literal LaTeX output (ref #3342)
* LaTeX writer: leave ``"`` character inside parsed-literal as is (ref #3341)
* #3234: intersphinx failed for encoded inventories
* #3158: too much space after captions in PDF output
* #3317: An URL in parsed-literal contents gets wrongly rendered in PDF if
with hyphen
* LaTeX crash if the filename of an image inserted in parsed-literal
via a substitution contains an hyphen (ref #3340)
* LaTeX rendering of inserted footnotes in parsed-literal is wrong (ref #3340)
* Inline math in parsed-literal is not rendered well by LaTeX (ref #3340)
* #3308: Parsed-literals don't wrap very long lines with pdf builder (ref #3340)
* #3295: Could not import extension sphinx.builders.linkcheck
* #3285: autosummary: asterisks are escaped twice
* LaTeX, pass dvipdfm option to geometry package for Japanese documents (ref #3363)
Release 1.5.1 (released Dec 13, 2016)
@@ -133,8 +176,8 @@ Incompatible changes
* latex, package ifthen is not any longer a dependency of sphinx.sty
* latex, style file does not modify fancyvrb's Verbatim (also available as
OriginalVerbatim) but uses sphinxVerbatim for name of custom wrapper.
* latex, package newfloat is no longer a dependency of sphinx.sty (ref #2660;
it was shipped with Sphinx since 1.3.4).
* latex, package newfloat is not used (and not included) anymore (ref #2660;
it was used since 1.3.4 and shipped with Sphinx since 1.4).
* latex, literal blocks in tables do not use OriginalVerbatim but
sphinxVerbatimintable which handles captions and wraps lines(ref #2704).
* latex, replace ``pt`` by TeX equivalent ``bp`` if found in ``width`` or

View File

@@ -2,21 +2,25 @@ include README.rst
include LICENSE
include AUTHORS
include CHANGES
include CHANGES.old
include CONTRIBUTING.rst
include EXAMPLES
include TODO
include babel.cfg
include Makefile
include ez_setup.py
include sphinx-autogen.py
include sphinx-build.py
include sphinx-quickstart.py
include sphinx-apidoc.py
include test-reqs.txt
include tox.ini
include sphinx/locale/.tx/config
recursive-include sphinx/templates *
recursive-include sphinx/texinputs *
recursive-include sphinx/themes *
recursive-include sphinx/locale *
recursive-include sphinx/pycode/pgen2 *.c *.pyx
recursive-include sphinx/locale *.js *.pot *.po *.mo
recursive-include sphinx/search/non-minified-js *.js
recursive-include sphinx/ext/autosummary/templates *
recursive-include tests *
@@ -25,3 +29,4 @@ include sphinx/pycode/Grammar-py*
recursive-include doc *
prune doc/_build
prune sphinx/locale/.tx

View File

@@ -54,11 +54,18 @@ clean-patchfiles:
clean-backupfiles:
find . -name '*~' -exec rm -f {} +
find . -name '*.bak' -exec rm -f {} +
find . -name '*.swp' -exec rm -f {} +
find . -name '*.swo' -exec rm -f {} +
clean-generated:
find . -name '.DS_Store' -exec rm -f {} +
rm -f doc/_build/
rm -f sphinx/pycode/*.pickle
rm -f utils/*3.py*
rm -f utils/regression_test.js
clean-testfiles:
rm -rf tests/.coverage
rm -rf tests/build
rm -rf .tox/
rm -rf .cache/

View File

@@ -1523,8 +1523,8 @@ These options influence LaTeX output. See further :doc:`latex`.
backslash or ampersand must be represented by the proper LaTeX commands if
they are to be inserted literally.
* *author*: Author for the LaTeX document. The same LaTeX markup caveat as
for *title* applies. Use ``\and`` to separate multiple authors, as in:
``'John \and Sarah'``.
for *title* applies. Use ``\\and`` to separate multiple authors, as in:
``'John \\and Sarah'`` (backslashes must be Python-escaped to reach LaTeX).
* *documentclass*: Normally, one of ``'manual'`` or ``'howto'`` (provided
by Sphinx and based on ``'report'``, resp. ``'article'``; Japanese
documents use ``'jsbook'``, resp. ``'jreport'``.) "howto" (non-Japanese)
@@ -1656,6 +1656,11 @@ These options influence LaTeX output. See further :doc:`latex`.
``'\\usepackage[margin=1in,marginparwidth=0.5in]{geometry}'``.
.. versionadded:: 1.5
.. versionchanged:: 1.5.2
For Japanese documents also ``dvipdfm`` option is passed to
``geometry``.
``'babel'``
"babel" package inclusion, default ``'\\usepackage{babel}'`` (the
suitable document language string is passed as class option, and

View File

@@ -545,6 +545,10 @@ The C++ Domain
The C++ domain (name **cpp**) supports documenting C++ projects.
Directives
~~~~~~~~~~
The following directives are available. All declarations can start with
a visibility statement (``public``, ``private`` or ``protected``).
@@ -740,6 +744,16 @@ a visibility statement (``public``, ``private`` or ``protected``).
Holder of elements, to which it can provide access via
:cpp:concept:`Iterator` s.
Options
.......
Some directives support options:
- ``:noindex:``, see :ref:`basic-domain-markup`.
- ``:tparam-line-spec:``, for templated declarations.
If specified, each template parameter will be rendered on a separate line.
Constrained Templates
~~~~~~~~~~~~~~~~~~~~~

View File

@@ -94,14 +94,14 @@ This section describe a easy way to translate with sphinx-intl.
$ make gettext
As a result, many pot files are generated under ``_build/locale``
As a result, many pot files are generated under ``_build/gettext``
directory.
#. Setup/Update your `locale_dir`:
.. code-block:: console
$ sphinx-intl update -p _build/locale -l de -l ja
$ sphinx-intl update -p _build/gettext -l de -l ja
Done. You got these directories that contain po files:

View File

@@ -132,25 +132,33 @@ Here are the currently available options together with their default values.
rendering by Sphinx; if in future Sphinx offers various *themes* for LaTeX,
the interface may change.
.. attention::
LaTeX requires for keys with Boolean values to use **lowercase** ``true`` or
``false``.
``verbatimwithframe``
default ``true``. Boolean to specify if :rst:dir:`code-block`\ s and literal
includes are framed. Setting it to ``false`` does not deactivate use of
package "framed", because it is still in use for the optional background
colour (see below).
.. attention::
LaTeX requires ``true`` or ``false`` to be specified in *lowercase*.
``verbatimwrapslines``
default ``true``. Tells whether long lines in :rst:dir:`code-block`\ s
should be wrapped.
default ``true``. Tells whether long lines in :rst:dir:`code-block`\ 's
contents should wrap.
.. (comment) It is theoretically possible to customize this even
more and decide at which characters a line-break can occur and whether
before or after, but this is accessible currently only by re-defining some
macros with complicated LaTeX syntax from :file:`sphinx.sty`.
``parsedliteralwraps``
default ``true``. Tells whether long lines in :dudir:`parsed-literal`\ 's
contents should wrap.
.. versionadded:: 1.5.2
set this option value to ``false`` to recover former behaviour.
``inlineliteralwraps``
default ``true``. Allows linebreaks inside inline literals: but extra
potential break-points (additionally to those allowed by LaTeX at spaces
@@ -160,7 +168,7 @@ Here are the currently available options together with their default values.
(or shrinked) in order to accomodate the linebreak.
.. versionadded:: 1.5
set this option to ``false`` to recover former behaviour.
set this option value to ``false`` to recover former behaviour.
``verbatimvisiblespace``
default ``\textcolor{red}{\textvisiblespace}``. When a long code line is
@@ -319,9 +327,10 @@ Here are the currently available options together with their default values.
(non-breakable) space.
.. versionadded:: 1.5
formerly, footnotes from explicit mark-up were
preceded by a space (hence a linebreak there was possible), but
automatically generated footnotes had no such space.
formerly, footnotes from explicit mark-up (but not automatically
generated ones) were preceded by a space in the output ``.tex`` file
hence a linebreak in PDF was possible. To avoid insertion of this space
one could use ``foo\ [#f1]`` mark-up, but this impacts all builders.
``HeaderFamily``
default ``\sffamily\bfseries``. Sets the font used by headings.

View File

@@ -26,4 +26,4 @@ universal = 1
[flake8]
max-line-length = 95
ignore = E116,E241,E251
exclude = .git,.tox,tests/*,build/*,sphinx/search/*,sphinx/pycode/pgen2/*,doc/ext/example*.py
exclude = .git,.tox,tests/*,build/*,sphinx/search/*,sphinx/pycode/pgen2/*,doc/ext/example*.py

View File

@@ -292,7 +292,6 @@ class Sphinx(object):
# type: (bool) -> None
if freshenv:
self.env = BuildEnvironment(self.srcdir, self.doctreedir, self.config)
self.env.set_warnfunc(self.warn)
self.env.find_files(self.config, self.buildername)
for domain in self.domains.keys():
self.env.domains[domain] = self.domains[domain](self.env)
@@ -301,7 +300,6 @@ class Sphinx(object):
logger.info(bold('loading pickled environment... '), nonl=True)
self.env = BuildEnvironment.frompickle(
self.srcdir, self.config, path.join(self.doctreedir, ENV_PICKLE_FILENAME))
self.env.set_warnfunc(self.warn)
self.env.init_managers()
self.env.domains = {}
for domain in self.domains.keys():
@@ -582,11 +580,11 @@ class Sphinx(object):
# type: (unicode, Any, Union[bool, unicode], Any) -> None
logger.debug('[app] adding config value: %r',
(name, default, rebuild) + ((types,) if types else ())) # type: ignore
if name in self.config.values:
if name in self.config:
raise ExtensionError('Config value %r already present' % name)
if rebuild in (False, True):
rebuild = rebuild and 'env' or ''
self.config.values[name] = (default, rebuild, types)
self.config.add(name, default, rebuild, types)
def add_event(self, name):
# type: (unicode) -> None

View File

@@ -224,7 +224,7 @@ class MessageCatalogBuilder(I18nBuilder):
extract_translations = self.templates.environment.extract_translations
for template in status_iterator(files, 'reading templates... ', "purple",
for template in status_iterator(files, 'reading templates... ', "purple", # type: ignore # NOQA
len(files), self.app.verbosity):
with open(template, 'r', encoding='utf-8') as f: # type: ignore
context = f.read()
@@ -247,7 +247,7 @@ class MessageCatalogBuilder(I18nBuilder):
ctime = datetime.fromtimestamp( # type: ignore
timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'),
)
for textdomain, catalog in status_iterator(iteritems(self.catalogs),
for textdomain, catalog in status_iterator(iteritems(self.catalogs), # type: ignore
"writing message catalogs... ",
"darkgreen", len(self.catalogs),
self.app.verbosity,

View File

@@ -48,7 +48,7 @@ from sphinx.writers.html import HTMLWriter, HTMLTranslator, \
if False:
# For type annotation
from typing import Any, Iterable, Iterator, Tuple, Union # NOQA
from typing import Any, Iterable, Iterator, Type, Tuple, Union # NOQA
from sphinx.domains import Domain, Index # NOQA
from sphinx.application import Sphinx # NOQA
@@ -105,7 +105,7 @@ class StandaloneHTMLBuilder(Builder):
css_files = [] # type: List[unicode]
imgpath = None # type: unicode
domain_indices = [] # type: List[Tuple[unicode, Index, unicode, bool]]
domain_indices = [] # type: List[Tuple[unicode, Type[Index], List[Tuple[unicode, List[List[Union[unicode, int]]]]], bool]] # NOQA
default_sidebars = ['localtoc.html', 'relations.html',
'sourcelink.html', 'searchbox.html']
@@ -190,9 +190,7 @@ class StandaloneHTMLBuilder(Builder):
def get_outdated_docs(self): # type: ignore
# type: () -> Iterator[unicode]
cfgdict = dict((name, self.config[name])
for (name, desc) in iteritems(self.config.values)
if desc[1] == 'html')
cfgdict = dict((confval.name, confval.value) for confval in self.config.filter('html'))
self.config_hash = get_stable_hash(cfgdict)
self.tags_hash = get_stable_hash(sorted(self.tags)) # type: ignore
old_config_hash = old_tags_hash = ''
@@ -297,7 +295,7 @@ class StandaloneHTMLBuilder(Builder):
domain = None # type: Domain
domain = self.env.domains[domain_name]
for indexcls in domain.indices:
indexname = '%s-%s' % (domain.name, indexcls.name)
indexname = '%s-%s' % (domain.name, indexcls.name) # type: unicode
if isinstance(indices_config, list):
if indexname not in indices_config:
continue
@@ -328,10 +326,10 @@ class StandaloneHTMLBuilder(Builder):
self.relations = self.env.collect_relations()
rellinks = []
rellinks = [] # type: List[Tuple[unicode, unicode, unicode, unicode]]
if self.use_index:
rellinks.append(('genindex', _('General Index'), 'I', _('index')))
for indexname, indexcls, content, collapse in self.domain_indices: # type: ignore
for indexname, indexcls, content, collapse in self.domain_indices:
# if it has a short name
if indexcls.shortname:
rellinks.append((indexname, indexcls.localname,

View File

@@ -16,9 +16,8 @@ import threading
from os import path
from requests.exceptions import HTTPError
from six.moves import queue # type: ignore
from six.moves import queue, html_parser # type: ignore
from six.moves.urllib.parse import unquote
from six.moves.html_parser import HTMLParser
from docutils import nodes
# 2015-06-25 barry@python.org. This exception was deprecated in Python 3.3 and
@@ -48,18 +47,17 @@ if False:
logger = logging.getLogger(__name__)
class AnchorCheckParser(HTMLParser):
class AnchorCheckParser(html_parser.HTMLParser):
"""Specialized HTML parser that looks for a specific anchor."""
def __init__(self, search_anchor):
# type: (unicode) -> None
HTMLParser.__init__(self)
html_parser.HTMLParser.__init__(self)
self.search_anchor = search_anchor
self.found = False
def handle_starttag(self, tag, attrs):
# type: (Any, Dict[unicode, unicode]) -> None
for key, value in attrs:
if key in ('id', 'name') and value == self.search_anchor:
self.found = True

View File

@@ -13,6 +13,7 @@ import re
from os import path, getenv
from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integer_types
from typing import Any, NamedTuple, Union
from sphinx.errors import ConfigError
from sphinx.locale import l_
@@ -23,7 +24,7 @@ from sphinx.util.pycompat import execfile_, NoneType
if False:
# For type annotation
from typing import Any, Callable, Tuple # NOQA
from typing import Any, Callable, Iterable, Iterator, Tuple # NOQA
from sphinx.util.tags import Tags # NOQA
logger = logging.getLogger(__name__)
@@ -43,6 +44,13 @@ CONFIG_PERMITTED_TYPE_WARNING = "The config value `{name}' has type `{current.__
CONFIG_TYPE_WARNING = "The config value `{name}' has type `{current.__name__}', " \
"defaults to `{default.__name__}'."
if PY3:
unicode = str # special alias for static typing...
ConfigValue = NamedTuple('ConfigValue', [('name', str),
('value', Any),
('rebuild', Union[bool, unicode])])
class ENUM(object):
"""represents the config value should be a one of candidates.
@@ -307,3 +315,16 @@ class Config(object):
def __contains__(self, name):
# type: (unicode) -> bool
return name in self.values
def __iter__(self):
# type: () -> Iterable[ConfigValue]
for name, value in iteritems(self.values):
yield ConfigValue(name, getattr(self, name), value[1]) # type: ignore
def add(self, name, default, rebuild, types):
# type: (unicode, Any, Union[bool, unicode], Any) -> None
self.values[name] = (default, rebuild, types)
def filter(self, rebuild):
# type: (str) -> Iterator[ConfigValue]
return (value for value in self if value.rebuild == rebuild) # type: ignore

View File

@@ -107,7 +107,7 @@ class Index(object):
Qualifier and description are not rendered e.g. in LaTeX output.
"""
return tuple()
raise NotImplementedError
class Domain(object):

View File

@@ -15,7 +15,7 @@ from copy import deepcopy
from six import iteritems, text_type
from docutils import nodes
from docutils.parsers.rst import Directive
from docutils.parsers.rst import Directive, directives
from sphinx import addnodes
from sphinx.roles import XRefRole
@@ -53,13 +53,17 @@ logger = logging.getLogger(__name__)
the index. All of the versions should work as permalinks.
Tagnames
Signature Nodes and Tagnames
----------------------------------------------------------------------------
Each desc_signature node will have the attribute 'sphinx_cpp_tagname' set to
- 'templateParams', if the line is on the form 'template<...>',
- 'templateIntroduction, if the line is on the form 'conceptName{...}'
Each signature is in a desc_signature node, where all children are
desc_signature_line nodes. Each of these lines will have the attribute
'sphinx_cpp_tagname' set to one of the following (prioritized):
- 'declarator', if the line contains the name of the declared object.
- 'templateParams', if the line starts a template parameter list,
- 'templateParams', if the line has template parameters
Note: such lines might get a new tag in the future.
- 'templateIntroduction, if the line is on the form 'conceptName{...}'
No other desc_signature nodes should exist (so far).
@@ -892,6 +896,7 @@ class ASTTemplateParams(ASTBase):
# type: (Any) -> None
assert params is not None
self.params = params
self.isNested = False # whether it's a template template param
def get_id_v2(self):
# type: () -> unicode
@@ -910,17 +915,30 @@ class ASTTemplateParams(ASTBase):
res.append(u"> ")
return ''.join(res)
def describe_signature(self, signode, mode, env, symbol):
# type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol) -> None
signode.sphinx_cpp_tagname = 'templateParams'
signode += nodes.Text("template<")
def describe_signature(self, parentNode, mode, env, symbol, lineSpec=None):
# type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol, bool) -> None
# 'lineSpec' is defaulted becuase of template template parameters
def makeLine(parentNode=parentNode):
signode = addnodes.desc_signature_line()
parentNode += signode
signode.sphinx_cpp_tagname = 'templateParams'
return signode
if self.isNested:
lineNode = parentNode
else:
lineNode = makeLine()
lineNode += nodes.Text("template<")
first = True
for param in self.params:
if not first:
signode += nodes.Text(", ")
lineNode += nodes.Text(", ")
first = False
param.describe_signature(signode, mode, env, symbol)
signode += nodes.Text(">")
if lineSpec:
lineNode = makeLine()
param.describe_signature(lineNode, mode, env, symbol)
if lineSpec and not first:
lineNode = makeLine()
lineNode += nodes.Text(">")
class ASTTemplateIntroductionParameter(ASTBase):
@@ -1005,8 +1023,11 @@ class ASTTemplateIntroduction(ASTBase):
res.append('} ')
return ''.join(res)
def describe_signature(self, signode, mode, env, symbol):
# type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol) -> None
def describe_signature(self, parentNode, mode, env, symbol, lineSpec):
# type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol, bool) -> None
# Note: 'lineSpec' has no effect on template introductions.
signode = addnodes.desc_signature_line()
parentNode += signode
signode.sphinx_cpp_tagname = 'templateIntroduction'
self.concept.describe_signature(signode, 'markType', env, symbol)
signode += nodes.Text('{')
@@ -1043,13 +1064,11 @@ class ASTTemplateDeclarationPrefix(ASTBase):
res.append(text_type(t))
return u''.join(res)
def describe_signature(self, signode, mode, env, symbol):
# type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol) -> None
def describe_signature(self, signode, mode, env, symbol, lineSpec):
# type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol, bool) -> None
_verify_description_mode(mode)
for t in self.templates:
templateNode = addnodes.desc_signature_line()
t.describe_signature(templateNode, 'lastIsName', env, symbol)
signode += templateNode
t.describe_signature(signode, 'lastIsName', env, symbol, lineSpec)
class ASTOperatorBuildIn(ASTBase):
@@ -2722,8 +2741,8 @@ class ASTDeclaration(ASTBase):
res.append(text_type(self.declaration))
return u''.join(res)
def describe_signature(self, signode, mode, env):
# type: (addnodes.desc_signature, unicode, BuildEnvironment) -> None
def describe_signature(self, signode, mode, env, options):
# type: (addnodes.desc_signature, unicode, BuildEnvironment, Dict) -> None
_verify_description_mode(mode)
# The caller of the domain added a desc_signature node.
# Always enable multiline:
@@ -2736,7 +2755,8 @@ class ASTDeclaration(ASTBase):
assert self.symbol
if self.templatePrefix:
self.templatePrefix.describe_signature(signode, mode, env,
symbol=self.symbol)
symbol=self.symbol,
lineSpec=options.get('tparam-line-spec'))
signode += mainDeclNode
if self.visibility and self.visibility != "public":
mainDeclNode += addnodes.desc_annotation(self.visibility + " ",
@@ -4170,6 +4190,7 @@ class DefinitionParser(object):
if self.skip_word('template'):
# declare a tenplate template parameter
nestedParams = self._parse_template_parameter_list()
nestedParams.isNested = True
else:
nestedParams = None
self.skip_ws()
@@ -4390,6 +4411,9 @@ class DefinitionParser(object):
# type: () -> ASTNamespace
templatePrefix = self._parse_template_declaration_prefix(objectType="xref")
name = self._parse_nested_name()
# if there are '()' left, just skip them
self.skip_ws()
self.skip_string('()')
templatePrefix = self._check_template_consistency(name, templatePrefix,
fullSpecShorthand=True)
res = ASTNamespace(name, templatePrefix)
@@ -4420,6 +4444,9 @@ class CPPObject(ObjectDescription):
names=('returns', 'return')),
]
option_spec = dict(ObjectDescription.option_spec)
option_spec['tparam-line-spec'] = directives.flag
def warn(self, msg):
# type: (unicode) -> None
self.state_machine.reporter.warning(msg, line=self.lineno)
@@ -4517,9 +4544,9 @@ class CPPObject(ObjectDescription):
# type: (Any) -> Any
raise NotImplementedError()
def describe_signature(self, signode, ast, parentScope):
# type: (addnodes.desc_signature, Any, Any) -> None
raise NotImplementedError()
def describe_signature(self, signode, ast, options): # type: ignore
# type: (addnodes.desc_signature, Any, Dict) -> None
ast.describe_signature(signode, 'lastIsName', self.env, options)
def handle_signature(self, sig, signode):
# type: (unicode, addnodes.desc_signature) -> Any
@@ -4552,7 +4579,8 @@ class CPPObject(ObjectDescription):
if ast.objectType == 'enumerator':
self._add_enumerator_to_parent(ast)
self.describe_signature(signode, ast)
self.options['tparam-line-spec'] = 'tparam-line-spec' in self.options
self.describe_signature(signode, ast, self.options)
return ast
def before_content(self):
@@ -4576,10 +4604,6 @@ class CPPTypeObject(CPPObject):
# type: (Any) -> Any
return parser.parse_declaration("type")
def describe_signature(self, signode, ast): # type: ignore
# type: (addnodes.desc_signature, Any) -> None
ast.describe_signature(signode, 'lastIsName', self.env)
class CPPConceptObject(CPPObject):
def get_index_text(self, name):
@@ -4590,10 +4614,6 @@ class CPPConceptObject(CPPObject):
# type: (Any) -> Any
return parser.parse_declaration("concept")
def describe_signature(self, signode, ast): # type: ignore
# type: (addnodes.desc_signature, Any) -> None
ast.describe_signature(signode, 'lastIsName', self.env)
class CPPMemberObject(CPPObject):
def get_index_text(self, name):
@@ -4604,10 +4624,6 @@ class CPPMemberObject(CPPObject):
# type: (Any) -> Any
return parser.parse_declaration("member")
def describe_signature(self, signode, ast): # type: ignore
# type: (addnodes.desc_signature, Any) -> None
ast.describe_signature(signode, 'lastIsName', self.env)
class CPPFunctionObject(CPPObject):
def get_index_text(self, name):
@@ -4618,10 +4634,6 @@ class CPPFunctionObject(CPPObject):
# type: (Any) -> Any
return parser.parse_declaration("function")
def describe_signature(self, signode, ast): # type: ignore
# type: (addnodes.desc_signature, Any) -> None
ast.describe_signature(signode, 'lastIsName', self.env)
class CPPClassObject(CPPObject):
def get_index_text(self, name):
@@ -4632,10 +4644,6 @@ class CPPClassObject(CPPObject):
# type: (Any) -> Any
return parser.parse_declaration("class")
def describe_signature(self, signode, ast): # type: ignore
# type: (addnodes.desc_signature, Any) -> None
ast.describe_signature(signode, 'lastIsName', self.env)
class CPPEnumObject(CPPObject):
def get_index_text(self, name):
@@ -4656,10 +4664,6 @@ class CPPEnumObject(CPPObject):
assert False
return ast
def describe_signature(self, signode, ast): # type: ignore
# type: (addnodes.desc_signature, Any) -> None
ast.describe_signature(signode, 'lastIsName', self.env)
class CPPEnumeratorObject(CPPObject):
def get_index_text(self, name):
@@ -4670,10 +4674,6 @@ class CPPEnumeratorObject(CPPObject):
# type: (Any) -> Any
return parser.parse_declaration("enumerator")
def describe_signature(self, signode, ast): # type: ignore
# type: (addnodes.desc_signature, Any) -> None
ast.describe_signature(signode, 'lastIsName', self.env)
class CPPNamespaceObject(Directive):
"""
@@ -4887,10 +4887,12 @@ class CPPDomain(Domain):
if emitWarnings:
logger.warning(msg, location=node)
warner = Warner()
# add parens again for those that could be functions
if typ == 'any' or typ == 'func':
target += '()'
parser = DefinitionParser(target, warner, env.config)
try:
ast = parser.parse_xref_object()
parser.skip_ws()
parser.assert_end()
except DefinitionError as e:
warner.warn('Unparseable C++ cross-reference: %r\n%s'
@@ -4950,11 +4952,26 @@ class CPPDomain(Domain):
name = text_type(fullNestedName).lstrip(':')
docname = s.docname
assert docname
if typ == 'any' and declaration.objectType == 'function':
if env.config.add_function_parentheses:
if not node['refexplicit']:
title = contnode.pop(0).astext()
contnode += nodes.Text(title + '()')
# If it's operator(), we need to add '()' if explicit function parens
# are requested. Then the Sphinx machinery will add another pair.
# Also, if it's an 'any' ref that resolves to a function, we need to add
# parens as well.
addParen = 0
if not node.get('refexplicit', False) and declaration.objectType == 'function':
# this is just the normal haxing for 'any' roles
if env.config.add_function_parentheses and typ == 'any':
addParen += 1
# and now this stuff for operator()
if (env.config.add_function_parentheses and typ == 'function' and
contnode[-1].astext().endswith('operator()')):
addParen += 1
if ((typ == 'any' or typ == 'function') and
contnode[-1].astext().endswith('operator') and
name.endswith('operator()')):
addParen += 1
if addParen > 0:
title = contnode.pop(0).astext()
contnode += nodes.Text(title + '()' * addParen)
return make_refnode(builder, fromdocname, docname,
declaration.get_newest_id(), contnode, name
), declaration.objectType

View File

@@ -16,6 +16,7 @@ import time
import types
import codecs
import fnmatch
import warnings
from os import path
from glob import glob
from collections import defaultdict
@@ -49,6 +50,7 @@ from sphinx.util.websupport import is_commentable
from sphinx.errors import SphinxError, ExtensionError
from sphinx.versioning import add_uids, merge_doctrees
from sphinx.transforms import SphinxContentsFilter
from sphinx.deprecation import RemovedInSphinx20Warning
from sphinx.environment.managers.indexentries import IndexEntries
from sphinx.environment.managers.toctree import Toctree
@@ -122,8 +124,6 @@ class BuildEnvironment(object):
def topickle(self, filename):
# type: (unicode) -> None
# remove unpicklable attributes
warnfunc = self._warnfunc
self.set_warnfunc(None)
values = self.config.values
del self.config.values
domains = self.domains
@@ -142,7 +142,6 @@ class BuildEnvironment(object):
self.attach_managers(managers)
self.domains = domains
self.config.values = values
self.set_warnfunc(warnfunc)
# --------- ENVIRONMENT INITIALIZATION -------------------------------------
@@ -272,8 +271,8 @@ class BuildEnvironment(object):
def set_warnfunc(self, func):
# type: (Callable) -> None
self._warnfunc = func
self.settings['warning_stream'] = WarningStream(func)
warnings.warn('env.set_warnfunc() is now deprecated. Use sphinx.util.logging instead.',
RemovedInSphinx20Warning)
def set_versioning_method(self, method, compare):
# type: (unicode, bool) -> None
@@ -533,10 +532,8 @@ class BuildEnvironment(object):
else:
# check if a config value was changed that affects how
# doctrees are read
for key, descr in iteritems(config.values):
if descr[1] != 'env':
continue
if self.config[key] != config[key]:
for confval in config.filter('env'):
if self.config[confval.name] != confval.value:
msg = '[config changed] '
config_changed = True
break
@@ -641,12 +638,9 @@ class BuildEnvironment(object):
def read_process(docs):
# type: (List[unicode]) -> BuildEnvironment
self.app = app
self.warnings = [] # type: List[Tuple]
self.set_warnfunc(lambda *args, **kwargs: self.warnings.append((args, kwargs)))
for docname in docs:
self.read_doc(docname, app)
# allow pickling self to send it back
self.set_warnfunc(None)
del self.app
del self.domains
del self.config.values
@@ -655,13 +649,11 @@ class BuildEnvironment(object):
def merge(docs, otherenv):
# type: (List[unicode], BuildEnvironment) -> None
warnings.extend(otherenv.warnings)
self.merge_info_from(docs, otherenv, app)
tasks = ParallelTasks(nproc)
chunks = make_chunks(docnames, nproc)
warnings = [] # type: List[Tuple]
for chunk in status_iterator(chunks, 'reading sources... ', "purple",
len(chunks), self.app.verbosity):
tasks.add_task(read_process, chunk, merge)
@@ -670,9 +662,6 @@ class BuildEnvironment(object):
logger.info(bold('waiting for workers...'))
tasks.join()
for warning, kwargs in warnings:
self._warnfunc(*warning, **kwargs)
def check_dependents(self, already):
# type: (Set[unicode]) -> Iterator[unicode]
to_rewrite = (self.toctree.assign_section_numbers() + # type: ignore

View File

@@ -72,7 +72,7 @@ class Toctree(EnvironmentManager):
self.numbered_toctrees.add(docname)
for subfn, fnset in other.files_to_rebuild.items():
self.files_to_rebuild.setdefault(subfn, set()).update(fnset & docnames)
self.files_to_rebuild.setdefault(subfn, set()).update(fnset & set(docnames))
def process_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None

View File

@@ -319,7 +319,6 @@ class Autosummary(Directive):
else:
max_chars = max(10, max_item_chars - len(display_name))
sig = mangle_signature(sig, max_chars=max_chars)
sig = sig.replace('*', r'\*')
# -- Grab the summary

View File

@@ -57,7 +57,7 @@ class IfConfig(Directive):
def process_ifconfig_nodes(app, doctree, docname):
# type: (Sphinx, nodes.Node, unicode) -> None
ns = dict((k, app.config[k]) for k in app.config.values)
ns = dict((confval.name, confval.value) for confval in app.config) # type: ignore
ns.update(app.config.__dict__.copy())
ns['builder'] = app.builder.name
for node in doctree.traverse(ifconfig):

View File

@@ -29,6 +29,7 @@ from __future__ import print_function
import time
import zlib
import codecs
import functools
import posixpath
from os import path
import re
@@ -185,6 +186,9 @@ def _read_from_url(url, config=None):
r = requests.get(url, stream=True, config=config, timeout=config.intersphinx_timeout)
r.raise_for_status()
r.raw.url = r.url
# decode content-body based on the header.
# ref: https://github.com/kennethreitz/requests/issues/2155
r.raw.read = functools.partial(r.raw.read, decode_content=True)
return r.raw

View File

View File

@@ -1,6 +1,6 @@
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{footnotehyper-sphinx}%
[2016/10/27 v0.9f hyperref aware footnote.sty for sphinx (JFB)]
[2017/01/16 v1.5.2 hyperref aware footnote.sty for sphinx (JFB)]
%%
%% Package: footnotehyper-sphinx
%% Version: based on footnotehyper.sty v0.9f (2016/10/03)
@@ -15,6 +15,7 @@
%% 4. \sphinxfootnotemark, and use of \spx@opt@BeforeFootnote from sphinx.sty.
%% Note: with \footnotemark[N]/\footnotetext[N] syntax, hyperref
%% does not insert an hyperlink. This is _not_ improved here.
%% 5. use of \sphinxunactivateextrasandspace for parsed literals
%%
\DeclareOption*{\PackageWarning{footnotehyper}{Option `\CurrentOption' is unknown}}%
\ProcessOptions\relax
@@ -92,7 +93,8 @@
%% \spx@opt@BeforeFootnote is defined in sphinx.sty
\def\FNH@fixed@footnote {\spx@opt@BeforeFootnote\ifx\@currenvir\fn@footnote
\expandafter\FNH@footnoteenv\else\expandafter\fn@latex@@footnote\fi }%
\def\FNH@footnoteenv {\@ifnextchar[\FNH@xfootnoteenv%]
\def\FNH@footnoteenv {\catcode13=5\sphinxunactivateextrasandspace
\@ifnextchar[\FNH@xfootnoteenv%]
{\stepcounter\@mpfn
\protected@xdef\@thefnmark{\thempfn}\@footnotemark
\def\FNH@endfntext@next{\FNH@endfntext@link}\fn@startfntext}}%

View File

@@ -6,7 +6,7 @@
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesPackage{sphinx}[2017/01/09 v1.6 LaTeX package (Sphinx markup)]
\ProvidesPackage{sphinx}[2017/01/16 v1.6 LaTeX package (Sphinx markup)]
% we delay handling of options to after having loaded packages, because
% of the need to use \definecolor.
@@ -91,6 +91,8 @@
\DeclareBoolOption[true]{verbatimwithframe}
\DeclareBoolOption[true]{verbatimwrapslines}
\DeclareBoolOption[true]{inlineliteralwraps}
% parsed literal
\DeclareBoolOption[true]{parsedliteralwraps}
% \textvisiblespace for compatibility with fontspec+XeTeX/LuaTeX
\DeclareStringOption[\textcolor{red}{\textvisiblespace}]{verbatimvisiblespace}
\DeclareStringOption % must use braces to hide the brackets
@@ -118,7 +120,7 @@
% some font styling.
\DeclareStringOption[\sffamily\bfseries]{HeaderFamily}
% colours
% same problems as for dimensions: we want the key handler to use \definecolor
% same problems as for dimensions: we want the key handler to use \definecolor.
% first, some colours with no prefix, for backwards compatibility
\newcommand*{\sphinxDeclareColorOption}[2]{%
\definecolor{#1}#2%
@@ -160,8 +162,8 @@
% user interface: options can be changed midway in a document!
\newcommand\sphinxsetup[1]{\setkeys{sphinx}{#1}}
% this is the \ltx@ifundefined of ltxcmds.sty, which is loaded by
% hyperref.sty, but we need it before, and the first release of
% this is the \ltx@ifundefined of ltxcmds.sty, which was loaded by
% kvoptions already, (and later by hyperref), but the first release of
% ltxcmds.sty as in TL2009/Debian has wrong definition.
\newcommand{\spx@ifundefined}[1]{%
\ifcsname #1\endcsname
@@ -209,7 +211,8 @@
\pagestyle{empty} % start this way
% Use this to set the font family for headers and other decor:
% Since Sphinx 1.5, users should use HeaderFamily key to 'sphinxsetup' rather
% than defining their own \py@HeaderFamily command (which is still possible).
\newcommand{\py@HeaderFamily}{\spx@opt@HeaderFamily}
% Redefine the 'normal' header/footer style when using "fancyhdr" package:
@@ -285,9 +288,9 @@
% - with possibly of a top caption, non-separable by pagebreak.
% - and usable inside tables or footnotes ("footnotehyper-sphinx").
% For maintaining compatibility with Sphinx < 1.5, we define and use these
% when (unmodified) Verbatim will be needed. But Sphinx >= 1.5 does not modify
% original Verbatim anyhow.
% For extensions which use \OriginalVerbatim and compatibility with Sphinx <
% 1.5, we define and use these when (unmodified) Verbatim will be needed. But
% Sphinx >= 1.5 does not modify the \Verbatim macro anymore.
\let\OriginalVerbatim \Verbatim
\let\endOriginalVerbatim\endVerbatim
@@ -374,7 +377,7 @@
% {, <, #, %, $, ' and ": go to next line.
% _, }, ^, &, >, - and ~: stay at end of broken line.
% Use of \textquotesingle for straight quote.
% FIXME: convert this to package options
% FIXME: convert this to package options ?
\newcommand*\sphinxbreaksbeforelist {%
\do\PYGZob\{\do\PYGZlt\<\do\PYGZsh\#\do\PYGZpc\%% {, <, #, %,
\do\PYGZdl\$\do\PYGZdq\"% $, "
@@ -396,7 +399,8 @@
\def\sphinx@verbatim@nolig@list {\do \`}%
% Some characters . , ; ? ! / are not pygmentized.
% This macro makes them "active" and they will insert potential linebreaks
% This macro makes them "active" and they will insert potential linebreaks.
% Not compatible with math mode (cf \sphinxunactivateextras).
\newcommand*\sphinxbreaksbeforeactivelist {}% none
\newcommand*\sphinxbreaksafteractivelist {\do\.\do\,\do\;\do\?\do\!\do\/}
\newcommand*\sphinxbreaksviaactive {%
@@ -411,6 +415,15 @@
\lccode`\~`\~
}
% If the linebreak is at a space, the latter will be displayed as visible
% space at end of first line, and a continuation symbol starts next line.
% Stretch/shrink are however usually zero for typewriter font.
\def\spx@verbatim@space {%
\nobreak\hskip\z@ plus\fontdimen3\font minus\fontdimen4\font
\discretionary{\copy\sphinxvisiblespacebox}{\sphinxafterbreak}
{\kern\fontdimen2\font}%
}%
% needed to create wrapper environments of fancyvrb's Verbatim
\newcommand*{\sphinxVerbatimEnvironment}{\gdef\FV@EnvironName{sphinxVerbatim}}
% Sphinx <1.5 optional argument was in fact mandatory. It is now really
@@ -466,14 +479,7 @@
\doublehyphendemerits\z@\finalhyphendemerits\z@
\strut ##1\strut}%
}%
% If the linebreak is at a space, the latter will be displayed as visible
% space at end of first line, and a continuation symbol starts next line.
% Stretch/shrink are however usually zero for typewriter font.
\def\FV@Space {%
\nobreak\hskip\z@ plus\fontdimen3\font minus\fontdimen4\font
\discretionary{\copy\sphinxvisiblespacebox}{\sphinxafterbreak}
{\kern\fontdimen2\font}%
}%
\let\FV@Space\spx@verbatim@space
% Allow breaks at special characters using \PYG... macros.
\sphinxbreaksatspecials
% Breaks at punctuation characters . , ; ? ! and / (needs catcode activation)
@@ -535,6 +541,72 @@
\begin{sphinxVerbatim}}
{\end{sphinxVerbatim}}
% Parsed literal: allow long lines to wrap like they do in code-blocks
% this should be kept in sync with definitions in sphinx.util.texescape
\newcommand*\sphinxbreaksattexescapedchars{%
\def\do##1##2% put potential break point before character
{\def##1{\discretionary{}{\sphinxafterbreak\char`##2}{\char`##2}}}%
\do\{\{\do\textless\<\do\#\#\do\%\%\do\$\$% {, <, #, %, $
\def\do##1##2% put potential break point after character
{\def##1{\discretionary{\char`##2}{\sphinxafterbreak}{\char`##2}}}%
\do\_\_\do\}\}\do\textasciicircum\^\do\&\&% _, }, ^, &,
\do\textgreater\>\do\textasciitilde\~% >, ~
}
\newcommand*\sphinxbreaksviaactiveinparsedliteral{%
\sphinxbreaksviaactive % by default handles . , ; ? ! /
\do\-% we need also the hyphen character (ends up "as is" in parsed-literal)
\lccode`\~`\~ %
% update \dospecials as it is used by \url
% but deactivation will already have been done hence this is unneeded:
% \expandafter\def\expandafter\dospecials\expandafter{\dospecials
% \sphinxbreaksbeforeactivelist\sphinxbreaksafteractivelist\do\-}%
}
\newcommand*\sphinxbreaksatspaceinparsedliteral{%
\lccode`~32 \lowercase{\let~}\spx@verbatim@space\lccode`\~`\~
}
% now the hack for \url to work (hyperref is assumed in use):
% the aim it to deactivate - . , ; ? ! / in \url's argument.
% also the space token, but not end of lines which we assume don't arise there.
\def\spx@hack@hyper@normalise {%
\expandafter\spx@hack@hyper@normalise@aux\hyper@normalise
\spx@hack@hyper@normalise@aux\hyper@n@rmalise\relax\spx@undefined
}%
\long\def\spx@hack@hyper@normalise@aux#1\hyper@n@rmalise#2#3\spx@undefined{%
\ifx\spx@hack@hyper@normalise@aux#2%
\def\hyper@normalise{#1\sphinxunactivateextrasandspace\hyper@n@rmalise}%
\else
\PackageWarning{sphinx}{Could not patch \string\url\space command.%
^^J Not using extra active characters in alltt environment}%
\sphinxunactivateextras
\fi
}%
\newcommand*{\sphinxunactivateextras}{\let\do\@makeother
\sphinxbreaksbeforeactivelist\sphinxbreaksafteractivelist\do\-}%
% the \catcode13=5\relax (deactivate end of input lines) is left to callers
\newcommand*{\sphinxunactivateextrasandspace}{\catcode32=10\relax
\sphinxunactivateextras}%
% now for the modified alltt environment
\newenvironment{sphinxalltt}
{% at start of next line to work around Emacs/AUCTeX issue with this file
\begin{alltt}%
\ifspx@opt@parsedliteralwraps
\sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}%
\sbox\sphinxvisiblespacebox {\spx@opt@verbatimvisiblespace}%
\sphinxbreaksattexescapedchars
\sphinxbreaksviaactiveinparsedliteral
\sphinxbreaksatspaceinparsedliteral
\spx@hack@hyper@normalise
% alltt takes care of the ' as derivative ("prime") in math mode
\everymath\expandafter{\the\everymath\sphinxunactivateextrasandspace
\catcode`\<=12\catcode`\>=12\catcode`\^=7\catcode`\_=8 }%
% not sure if displayed math (align,...) can end up in parsed-literal, anyway
\everydisplay\expandafter{\the\everydisplay
\catcode13=5\sphinxunactivateextrasandspace
\catcode`\<=12\catcode`\>=12\catcode`\^=7\catcode`\_=8 }%
\fi }
{\end{alltt}}
% Topic boxes
% Again based on use of "framed.sty", this allows breakable framed boxes.

View File

@@ -45,7 +45,7 @@ from sphinx.util.matching import patfilter # noqa
if False:
# For type annotation
from typing import Any, Callable, Iterable, Iterator, Pattern, Sequence, Tuple # NOQA
from typing import Any, Callable, Iterable, Iterator, Pattern, Sequence, Tuple, Union # NOQA
logger = logging.getLogger(__name__)
@@ -149,7 +149,7 @@ class FilenameUniqDict(dict):
def merge_other(self, docnames, other):
# type: (List[unicode], Dict[unicode, Tuple[Set[unicode], Any]]) -> None
for filename, (docs, unique) in other.items():
for doc in docs & docnames:
for doc in docs & set(docnames):
self.add_file(doc, filename)
def __getstate__(self):
@@ -565,7 +565,7 @@ def old_status_iterator(iterable, summary, color="darkgreen", stringify_func=dis
# new version with progress info
def status_iterator(iterable, summary, color="darkgreen", length=0, verbosity=0,
stringify_func=display_chunk):
# type: (Iterable, unicode, str, int, int, Callable[[Any], unicode]) -> Iterable
# type: (Iterable, unicode, str, int, int, Callable[[Any], unicode]) -> Iterable # NOQA
if length == 0:
for item in old_status_iterator(iterable, summary, color, stringify_func):
yield item

View File

@@ -299,6 +299,7 @@ class DocFieldTransformer(object):
translatable_content = nodes.inline(fieldbody.rawsource,
translatable=True)
translatable_content.document = fieldbody.parent.document
translatable_content.source = fieldbody.parent.source
translatable_content.line = fieldbody.parent.line
translatable_content += content

View File

@@ -75,17 +75,12 @@ def apply_source_workaround(node):
if node.source and node.rawsource:
return
# workaround: docutils-0.10.0 or older's nodes.caption for nodes.figure
# and nodes.title for nodes.admonition doesn't have source, line.
# this issue was filed to Docutils tracker:
# sf.net/tracker/?func=detail&aid=3599485&group_id=38414&atid=422032
# sourceforge.net/p/docutils/patches/108/
# workaround: some docutils nodes doesn't have source, line.
if (isinstance(node, (
nodes.caption,
nodes.title,
nodes.rubric,
nodes.line,
nodes.image,
nodes.rubric, # #1305 rubric directive
nodes.line, # #1477 line node
nodes.image, # #3093 image directive in substitution
nodes.field_name, # #3335 field list syntax
))):
node.source = find_source_node(node)
node.line = 0 # need fix docutils to get `node.line`

View File

@@ -48,26 +48,26 @@ tex_replacements = [
('', r'\textbar{}'),
('', r'e'),
('', r'i'),
('', r'$^\text{0}$'),
('¹', r'$^\text{1}$'),
('²', r'$^\text{2}$'),
('³', r'$^\text{3}$'),
('', r'$^\text{4}$'),
('', r'$^\text{5}$'),
('', r'$^\text{6}$'),
('', r'$^\text{7}$'),
('', r'$^\text{8}$'),
('', r'$^\text{9}$'),
('', r'$_\text{0}$'),
('', r'$_\text{1}$'),
('', r'$_\text{2}$'),
('', r'$_\text{3}$'),
('', r'$_\text{4}$'),
('', r'$_\text{5}$'),
('', r'$_\text{6}$'),
('', r'$_\text{7}$'),
('', r'$_\text{8}$'),
('', r'$_\text{9}$'),
('', r'\(\sp{\text{0}}\)'),
('¹', r'\(\sp{\text{1}}\)'),
('²', r'\(\sp{\text{2}}\)'),
('³', r'\(\sp{\text{3}}\)'),
('', r'\(\sp{\text{4}}\)'),
('', r'\(\sp{\text{5}}\)'),
('', r'\(\sp{\text{6}}\)'),
('', r'\(\sp{\text{7}}\)'),
('', r'\(\sp{\text{8}}\)'),
('', r'\(\sp{\text{9}}\)'),
('', r'\(\sb{\text{0}}\)'),
('', r'\(\sb{\text{1}}\)'),
('', r'\(\sb{\text{2}}\)'),
('', r'\(\sb{\text{3}}\)'),
('', r'\(\sb{\text{4}}\)'),
('', r'\(\sb{\text{5}}\)'),
('', r'\(\sb{\text{6}}\)'),
('', r'\(\sb{\text{7}}\)'),
('', r'\(\sb{\text{8}}\)'),
('', r'\(\sb{\text{9}}\)'),
# map Greek alphabet
('α', r'\(\alpha\)'),
('β', r'\(\beta\)'),

View File

@@ -698,24 +698,6 @@ class HTMLTranslator(BaseTranslator):
def depart_abbreviation(self, node):
self.body.append('</abbr>')
# overwritten (but not changed) to keep pair of visit/depart_term
def visit_term(self, node):
self.body.append(self.starttag(node, 'dt', ''))
# overwritten to add '</dt>' in 'depart_term' state.
def depart_term(self, node):
self.body.append('</dt>\n')
# overwritten to do not add '</dt>' in 'visit_definition' state.
def visit_definition(self, node):
self.generate_targets_for_listing(node)
self.body.append(self.starttag(node, 'dd', ''))
self.set_first_last(node)
# overwritten (but not changed) to keep pair of visit/depart_definition
def depart_definition(self, node):
self.body.append('</dd>\n')
def visit_manpage(self, node):
return self.visit_literal_emphasis(node)

View File

@@ -126,6 +126,8 @@ ADDITIONAL_SETTINGS = {
},
'platex': {
'latex_engine': 'platex',
'geometry': ('\\usepackage[margin=1in,marginparwidth=0.5in,dvipdfm]'
'{geometry}'),
},
} # type: Dict[unicode, Dict[unicode, unicode]]
@@ -379,6 +381,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.this_is_the_title = 1
self.literal_whitespace = 0
self.no_contractions = 0
self.in_parsed_literal = 0
self.compact_list = 0
self.first_param = 0
self.remember_multirow = {} # type: Dict[int, int]
@@ -652,34 +655,34 @@ class LaTeXTranslator(nodes.NodeVisitor):
figure = self.builder.config.numfig_format['figure'].split('%s', 1)
if len(figure) == 1:
ret.append('\\def\\fnum@figure{%s}\n' %
escape_abbr(text_type(figure[0]).translate(tex_escape_map)))
text_type(figure[0]).strip().translate(tex_escape_map))
else:
definition = escape_abbr(text_type(figure[0]).translate(tex_escape_map))
definition = text_type(figure[0]).strip().translate(tex_escape_map)
ret.append(self.babel_renewcommand('\\figurename', definition))
if figure[1]:
ret.append('\\makeatletter\n')
ret.append('\\def\\fnum@figure{\\figurename\\thefigure%s}\n' %
escape_abbr(text_type(figure[1]).translate(tex_escape_map)))
text_type(figure[1]).strip().translate(tex_escape_map))
ret.append('\\makeatother\n')
table = self.builder.config.numfig_format['table'].split('%s', 1)
if len(table) == 1:
ret.append('\\def\\fnum@table{%s}\n' %
escape_abbr(text_type(table[0]).translate(tex_escape_map)))
text_type(table[0]).strip().translate(tex_escape_map))
else:
definition = escape_abbr(text_type(table[0]).translate(tex_escape_map))
definition = text_type(table[0]).strip().translate(tex_escape_map)
ret.append(self.babel_renewcommand('\\tablename', definition))
if table[1]:
ret.append('\\makeatletter\n')
ret.append('\\def\\fnum@table{\\tablename\\thetable%s}\n' %
escape_abbr(text_type(table[1]).translate(tex_escape_map)))
text_type(table[1]).strip().translate(tex_escape_map))
ret.append('\\makeatother\n')
codeblock = self.builder.config.numfig_format['code-block'].split('%s', 1)
if len(codeblock) == 1:
pass # FIXME
else:
definition = escape_abbr(text_type(codeblock[0]).translate(tex_escape_map))
definition = text_type(codeblock[0]).strip().translate(tex_escape_map)
ret.append(self.babel_renewcommand('\\literalblockname', definition))
if codeblock[1]:
pass # FIXME
@@ -1125,15 +1128,21 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('%%\n\\begin{footnotetext}[%s]'
'\\sphinxAtStartFootnote\n' % node['number'])
else:
self.body.append('%%\n\\begin{footnote}[%s]'
'\\sphinxAtStartFootnote\n' % node['number'])
if self.in_parsed_literal:
self.body.append('\\begin{footnote}[%s]' % node['number'])
else:
self.body.append('%%\n\\begin{footnote}[%s]' % node['number'])
self.body.append('\\sphinxAtStartFootnote\n')
def depart_collected_footnote(self, node):
# type: (nodes.Node) -> None
if 'footnotetext' in node:
self.body.append('%\n\\end{footnotetext}')
else:
self.body.append('%\n\\end{footnote}')
if self.in_parsed_literal:
self.body.append('\\end{footnote}')
else:
self.body.append('%\n\\end{footnote}')
self.in_footnote -= 1
def visit_label(self, node):
@@ -1568,8 +1577,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_image(self, node):
# type: (nodes.Node) -> None
attrs = node.attributes
pre = [] # in reverse order
post = []
pre = [] # type: List[unicode]
# in reverse order
post = [] # type: List[unicode]
if self.in_parsed_literal:
pre = ['\\begingroup\\sphinxunactivateextrasandspace\\relax ']
post = ['\\endgroup ']
include_graphics_options = []
is_inline = self.is_inline(node)
if 'width' in attrs:
@@ -2112,7 +2125,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
# type: (nodes.Node) -> None
if node.rawsource != node.astext():
# most probably a parsed-literal block -- don't highlight
self.body.append('\\begin{alltt}\n')
self.in_parsed_literal += 1
self.body.append('\\begin{sphinxalltt}\n')
else:
ids = '' # type: unicode
for id in self.pop_hyperlink_ids('code-block'):
@@ -2172,7 +2186,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_literal_block(self, node):
# type: (nodes.Node) -> None
self.body.append('\n\\end{alltt}\n')
self.body.append('\n\\end{sphinxalltt}\n')
self.in_parsed_literal -= 1
visit_doctest_block = visit_literal_block
depart_doctest_block = depart_literal_block
@@ -2416,7 +2431,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_Text(self, node):
# type: (nodes.Node) -> None
text = self.encode(node.astext())
if not self.no_contractions:
if not self.no_contractions and not self.in_parsed_literal:
text = educate_quotes_latex(text)
self.body.append(text)

View File

@@ -71,5 +71,5 @@ class C:
'''
def func(arg_):
def func(arg_, *args, **kwargs):
"""Test function take an argument ended with underscore."""

View File

@@ -11,3 +11,7 @@ any role
* ref function with parens :cpp:any:`paren_2()`
* ref function without parens, explicit title :cpp:any:`paren_3_title <paren_3>`
* ref function with parens, explicit title :cpp:any:`paren_4_title <paren_4()>`
* ref op call without parens :cpp:any:`paren_5::operator()`
* ref op call with parens :cpp:any:`paren_6::operator()()`
* ref op call without parens, explicit title :cpp:any:`paren_7_title <paren_7::operator()>`
* ref op call with parens, explicit title :cpp:any:`paren_8_title <paren_8::operator()()>`

View File

@@ -38,9 +38,10 @@ directives
.. cpp:function:: void paren_1(int, float)
.. cpp:function:: void paren_2(int, float)
.. cpp:function:: void paren_3(int, float)
.. cpp:function:: void paren_4(int, float)
.. cpp:function:: void paren_5::operator()(int)
.. cpp:function:: void paren_6::operator()(int)
.. cpp:function:: void paren_7::operator()(int)
.. cpp:function:: void paren_8::operator()(int)

View File

@@ -11,3 +11,7 @@ roles
* ref function with parens :cpp:func:`paren_2()`
* ref function without parens, explicit title :cpp:func:`paren_3_title <paren_3>`
* ref function with parens, explicit title :cpp:func:`paren_4_title <paren_4()>`
* ref op call without parens :cpp:func:`paren_5::operator()`
* ref op call with parens :cpp:func:`paren_6::operator()()`
* ref op call without parens, explicit title :cpp:func:`paren_7_title <paren_7::operator()>`
* ref op call with parens, explicit title :cpp:func:`paren_8_title <paren_8::operator()()>`

View File

@@ -178,9 +178,9 @@ def test_numref(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
assert '\\addto\\captionsenglish{\\renewcommand{\\figurename}{Fig.\\@ }}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Table }}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\literalblockname}{Listing }}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\figurename}{Fig.}}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Table}}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\literalblockname}{Listing}}' in result
assert ('\\hyperref[\\detokenize{index:fig1}]'
'{Fig.\\@ \\ref{\\detokenize{index:fig1}}}') in result
assert ('\\hyperref[\\detokenize{baz:fig22}]'
@@ -261,7 +261,7 @@ def test_numref_with_prefix2(app, status, warning):
print(status.getvalue())
print(warning.getvalue())
assert '\\addto\\captionsenglish{\\renewcommand{\\figurename}{Figure:}}' in result
assert '\\def\\fnum@figure{\\figurename\\thefigure.\\@}' in result
assert '\\def\\fnum@figure{\\figurename\\thefigure.}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Tab\\_}}' in result
assert '\\def\\fnum@table{\\tablename\\thetable:}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\literalblockname}{Code-}}' in result
@@ -296,9 +296,9 @@ def test_numref_with_language_ja(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
assert u'\\renewcommand{\\figurename}{\u56f3 }' in result
assert '\\renewcommand{\\tablename}{TABLE }' in result
assert '\\renewcommand{\\literalblockname}{LIST }' in result
assert u'\\renewcommand{\\figurename}{\u56f3}' in result
assert '\\renewcommand{\\tablename}{TABLE}' in result
assert '\\renewcommand{\\literalblockname}{LIST}' in result
assert (u'\\hyperref[\\detokenize{index:fig1}]'
u'{\u56f3 \\ref{\\detokenize{index:fig1}}}') in result
assert ('\\hyperref[\\detokenize{baz:fig22}]'
@@ -344,8 +344,8 @@ def test_babel_with_no_language_settings(app, status, warning):
assert '\\usepackage[Bjarne]{fncychap}' in result
assert ('\\addto\\captionsenglish{\\renewcommand{\\contentsname}{Table of content}}\n'
in result)
assert '\\addto\\captionsenglish{\\renewcommand{\\figurename}{Fig.\\@ }}\n' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Table.\\@ }}\n' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\figurename}{Fig.}}\n' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Table.}}\n' in result
assert '\\addto\\extrasenglish{\\def\\pageautorefname{page}}\n' in result
assert '\\shorthandoff' not in result
@@ -365,8 +365,8 @@ def test_babel_with_language_de(app, status, warning):
assert '\\usepackage[Sonny]{fncychap}' in result
assert ('\\addto\\captionsngerman{\\renewcommand{\\contentsname}{Table of content}}\n'
in result)
assert '\\addto\\captionsngerman{\\renewcommand{\\figurename}{Fig.\\@ }}\n' in result
assert '\\addto\\captionsngerman{\\renewcommand{\\tablename}{Table.\\@ }}\n' in result
assert '\\addto\\captionsngerman{\\renewcommand{\\figurename}{Fig.}}\n' in result
assert '\\addto\\captionsngerman{\\renewcommand{\\tablename}{Table.}}\n' in result
assert '\\addto\\extrasngerman{\\def\\pageautorefname{Seite}}\n' in result
assert '\\shorthandoff{"}' in result
@@ -386,8 +386,8 @@ def test_babel_with_language_ru(app, status, warning):
assert '\\usepackage[Sonny]{fncychap}' in result
assert ('\\addto\\captionsrussian{\\renewcommand{\\contentsname}{Table of content}}\n'
in result)
assert '\\addto\\captionsrussian{\\renewcommand{\\figurename}{Fig.\\@ }}\n' in result
assert '\\addto\\captionsrussian{\\renewcommand{\\tablename}{Table.\\@ }}\n' in result
assert '\\addto\\captionsrussian{\\renewcommand{\\figurename}{Fig.}}\n' in result
assert '\\addto\\captionsrussian{\\renewcommand{\\tablename}{Table.}}\n' in result
assert (u'\\addto\\extrasrussian{\\def\\pageautorefname'
u'{\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430}}\n' in result)
assert '\\shorthandoff' not in result
@@ -408,8 +408,8 @@ def test_babel_with_language_tr(app, status, warning):
assert '\\usepackage[Sonny]{fncychap}' in result
assert ('\\addto\\captionsturkish{\\renewcommand{\\contentsname}{Table of content}}\n'
in result)
assert '\\addto\\captionsturkish{\\renewcommand{\\figurename}{Fig.\\@ }}\n' in result
assert '\\addto\\captionsturkish{\\renewcommand{\\tablename}{Table.\\@ }}\n' in result
assert '\\addto\\captionsturkish{\\renewcommand{\\figurename}{Fig.}}\n' in result
assert '\\addto\\captionsturkish{\\renewcommand{\\tablename}{Table.}}\n' in result
assert '\\addto\\extrasturkish{\\def\\pageautorefname{sayfa}}\n' in result
assert '\\shorthandoff{=}' in result
@@ -428,8 +428,8 @@ def test_babel_with_language_ja(app, status, warning):
assert '\\usepackage{times}' in result
assert '\\usepackage[Sonny]{fncychap}' not in result
assert '\\renewcommand{\\contentsname}{Table of content}\n' in result
assert '\\renewcommand{\\figurename}{Fig.\\@ }\n' in result
assert '\\renewcommand{\\tablename}{Table.\\@ }\n' in result
assert '\\renewcommand{\\figurename}{Fig.}\n' in result
assert '\\renewcommand{\\tablename}{Table.}\n' in result
assert u'\\def\\pageautorefname{ページ}\n' in result
assert '\\shorthandoff' not in result
@@ -449,8 +449,8 @@ def test_babel_with_unknown_language(app, status, warning):
assert '\\usepackage[Sonny]{fncychap}' in result
assert ('\\addto\\captionsenglish{\\renewcommand{\\contentsname}{Table of content}}\n'
in result)
assert '\\addto\\captionsenglish{\\renewcommand{\\figurename}{Fig.\\@ }}\n' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Table.\\@ }}\n' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\figurename}{Fig.}}\n' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Table.}}\n' in result
assert '\\addto\\extrasenglish{\\def\\pageautorefname{page}}\n' in result
assert '\\shorthandoff' not in result

View File

@@ -56,7 +56,7 @@ def check(name, input, idv1output=None, idv2output=None, output=None):
parentNode = addnodes.desc()
signode = addnodes.desc_signature(input, '')
parentNode += signode
ast.describe_signature(signode, 'lastIsName', symbol)
ast.describe_signature(signode, 'lastIsName', symbol, options={})
if idv2output:
idv2output = "_CPPv2" + idv2output
@@ -524,7 +524,11 @@ def test_build_domain_cpp_with_add_function_parentheses_is_True(app, status, war
('ref function without parens ', 'paren_1\(\)'),
('ref function with parens ', 'paren_2\(\)'),
('ref function without parens, explicit title ', 'paren_3_title'),
('ref function with parens, explicit title ', 'paren_4_title')
('ref function with parens, explicit title ', 'paren_4_title'),
('ref op call without parens ', 'paren_5::operator\(\)\(\)'),
('ref op call with parens ', 'paren_6::operator\(\)\(\)'),
('ref op call without parens, explicit title ', 'paren_7_title'),
('ref op call with parens, explicit title ', 'paren_8_title')
]
f = 'roles.html'
@@ -562,7 +566,11 @@ def test_build_domain_cpp_with_add_function_parentheses_is_False(app, status, wa
('ref function without parens ', 'paren_1'),
('ref function with parens ', 'paren_2'),
('ref function without parens, explicit title ', 'paren_3_title'),
('ref function with parens, explicit title ', 'paren_4_title')
('ref function with parens, explicit title ', 'paren_4_title'),
('ref op call without parens ', 'paren_5::operator\(\)'),
('ref op call with parens ', 'paren_6::operator\(\)'),
('ref op call without parens, explicit title ', 'paren_7_title'),
('ref op call with parens, explicit title ', 'paren_8_title')
]
f = 'roles.html'

View File

@@ -95,3 +95,11 @@ def test_get_items_summary(app, status, warning):
for key, expected in iteritems(expected_values):
assert autosummary_items[key][2] == expected, 'Summary for %s was %r -'\
' expected %r' % (key, autosummary_items[key], expected)
# check an item in detail
assert 'func' in autosummary_items
func_attrs = ('func',
'(arg_, *args, **kwargs)',
'Test function take an argument ended with underscore.',
'dummy_module.func')
assert autosummary_items['func'] == func_attrs

17
utils/CHANGES_template Normal file
View File

@@ -0,0 +1,17 @@
Release x.y.z (in development)
==============================
Incompatible changes
--------------------
Deprecated
----------
Features added
--------------
Bugs fixed
----------
Testing
--------

170
utils/bump_version.py Executable file
View File

@@ -0,0 +1,170 @@
#!/usr/bin/env python
from __future__ import print_function
import os
import re
import sys
from datetime import datetime
from contextlib import contextmanager
script_dir = os.path.dirname(__file__)
package_dir = os.path.abspath(os.path.join(script_dir, '..'))
RELEASE_TYPE = {'a': 'alpha', 'b': 'beta'}
def stringify_version(version_info):
if version_info[2] == 0:
return '.'.join(str(v) for v in version_info[:2])
else:
return '.'.join(str(v) for v in version_info[:3])
def bump_version(path, version_info):
version = stringify_version(version_info)
release = version
if version_info[3] != 'final':
version += '+'
with open(path, 'r+') as f:
body = f.read()
body = re.sub("(?<=__version__ = ')[^']+", version, body)
body = re.sub("(?<=__released__ = ')[^']+", release, body)
body = re.sub("(?<=version_info = )\(.*\)", str(version_info), body)
f.seek(0)
f.truncate(0)
f.write(body)
def parse_version(version):
matched = re.search('^(\d+)\.(\d+)$', version)
if matched:
major, minor = matched.groups()
return (int(major), int(minor), 0, 'final', 0)
matched = re.search('^(\d+)\.(\d+)\.(\d+)$', version)
if matched:
major, minor, rev = matched.groups()
return (int(major), int(minor), int(rev), 'final', 0)
matched = re.search('^(\d+)\.(\d+)\s*(a|b|alpha|beta)(\d+)$', version)
if matched:
major, minor, typ, relver = matched.groups()
release = RELEASE_TYPE.get(typ, typ)
return (int(major), int(minor), 0, release, int(relver))
matched = re.search('^(\d+)\.(\d+)\.(\d+)\s*(a|b|alpha|beta)(\d+)$', version)
if matched:
major, minor, rev, typ, relver = matched.groups()
release = RELEASE_TYPE.get(typ, typ)
return (int(major), int(minor), int(rev), release, int(relver))
raise RuntimeError('Unknown vesion: %s' % version)
class Skip(Exception):
pass
@contextmanager
def processing(message):
try:
print(message + ' ... ', end='')
yield
except Skip as exc:
print('skip: %s' % exc)
except:
print('error')
raise
else:
print('done')
class Changes(object):
def __init__(self, path):
self.path = path
self.fetch_version()
def fetch_version(self):
with open(self.path) as f:
version = f.readline().strip()
matched = re.search('^Release (.*) \((.*)\)$', version)
if matched is None:
raise RuntimeError('Unknown CHANGES format: %s' % version)
self.version, self.release_date = matched.groups()
self.version_info = parse_version(self.version)
if self.release_date == 'in development':
self.in_development = True
else:
self.in_development = False
def finalize_release_date(self):
release_date = datetime.now().strftime('%b %d, %Y')
heading = 'Release %s (released %s)' % (self.version, release_date)
with open(self.path, 'r+') as f:
f.readline() # skip first two lines
f.readline()
body = f.read()
f.seek(0)
f.truncate(0)
f.write(heading + '\n')
f.write('=' * len(heading) + '\n')
f.write(body)
def add_release(self, version_info):
if version_info[-2:] in (('beta', 0), ('final', 0)):
version = stringify_version(version_info)
else:
reltype = version_info[3]
version = '%s %s%s' % (stringify_version(version_info),
RELEASE_TYPE.get(reltype, reltype),
version_info[4] or '')
heading = 'Release %s (in development)' % version
with open(os.path.join(script_dir, 'CHANGES_template')) as f:
f.readline() # skip first two lines
f.readline()
tmpl = f.read()
with open(self.path, 'r+') as f:
body = f.read()
f.seek(0)
f.truncate(0)
f.write(heading + '\n')
f.write('=' * len(heading) + '\n')
f.write(tmpl)
f.write('\n')
f.write(body)
def main():
if len(sys.argv) != 2:
print("bump_version.py [version]")
return -1
version_info = parse_version(sys.argv[-1])
with processing("Rewriting sphinx/__init__.py"):
bump_version(os.path.join(package_dir, 'sphinx/__init__.py'), version_info)
with processing('Rewriting CHANGES'):
changes = Changes(os.path.join(package_dir, 'CHANGES'))
if changes.version_info == version_info:
if changes.in_development:
changes.finalize_release_date()
else:
raise Skip('version not changed')
else:
if changes.in_development:
print('WARNING: last version is not released yet: %s' % changes.version)
changes.add_release(version_info)
if __name__ == '__main__':
main()

View File

@@ -9,19 +9,20 @@ Release checklist
* Run `(cd sphinx/locale; tx pull -a -f)`
* Run `python setup.py compile_catalog`
* Update version info in sphinx/__init__.py
* Update release date in CHANGES
* `python utils/bump_version.py x.y.z`
* Check diff by `git diff`
* `git commit -am 'Bump to x.y.z final'`
* `make clean`
* `python setup.py compile_grammar`
* `python setup.py release bdist_wheel sdist upload --identity=[your key]`
* Check PyPI release page for obvious errors
* open https://pypi.python.org/pypi/Sphinx and check there are no obvious errors
* `git tag x.y.z` with version number
* Merge default into stable if final major release
* `git push origin stable --tags`
* open https://readthedocs.org/dashboard/sphinx/versions/ and enable the released version
* Add new version/milestone to tracker categories
* Update version info, add new CHANGES entry for next version
* `python utils/bump_version.py a.b.cb0` (ex. 1.5.3b0)
* Check diff by `git diff`
* `git commit -am 'Bump version'`
* `git push origin stable`
* `git checkout master`