mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '4.x'
This commit is contained in:
commit
0f6afa5992
74
CHANGES
74
CHANGES
@ -26,12 +26,54 @@ Bugs fixed
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 4.3.0 (in development)
|
||||
Release 4.4.0 (in development)
|
||||
==============================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 4.3.1 (in development)
|
||||
==============================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 4.3.0 (released Nov 11, 2021)
|
||||
=====================================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
* Support Python 3.10
|
||||
|
||||
Incompatible changes
|
||||
@ -51,7 +93,7 @@ Incompatible changes
|
||||
* #9695: The rendering of Javascript domain declarations is implemented
|
||||
with more docutils nodes to allow better CSS styling.
|
||||
It may break existing styling.
|
||||
|
||||
* #9450: mathjax: Load MathJax via "defer" strategy
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
@ -71,6 +113,8 @@ Features added
|
||||
* #9691: C, added new info-field ``retval``
|
||||
for :rst:dir:`c:function` and :rst:dir:`c:macro`.
|
||||
* C++, added new info-field ``retval`` for :rst:dir:`cpp:function`.
|
||||
* #9618: i18n: Add :confval:`gettext_allow_fuzzy_translations` to allow "fuzzy"
|
||||
messages for translation
|
||||
* #9672: More CSS classes on Python domain descriptions
|
||||
* #9695: More CSS classes on Javascript domain descriptions
|
||||
* #9683: Revert the removal of ``add_stylesheet()`` API. It will be kept until
|
||||
@ -80,6 +124,8 @@ Features added
|
||||
inventory specification. Specific types of cross-references can be disabled,
|
||||
e.g., ``std:doc`` or all cross-references in a specific domain,
|
||||
e.g., ``std:*``.
|
||||
* #9623: Allow to suppress "toctree contains reference to excluded document"
|
||||
warnings using :confval:`suppress_warnings`
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
@ -123,30 +169,6 @@ Bugs fixed
|
||||
* Intersphinx, for unresolved references with an explicit inventory,
|
||||
e.g., ``proj:myFunc``, leave the inventory prefix in the unresolved text.
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 4.2.1 (in development)
|
||||
==============================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 4.2.0 (released Sep 12, 2021)
|
||||
=====================================
|
||||
|
||||
|
@ -329,6 +329,8 @@ General configuration
|
||||
* ``ref.python``
|
||||
* ``misc.highlighting_failure``
|
||||
* ``toc.circular``
|
||||
* ``toc.excluded``
|
||||
* ``toc.not_readable``
|
||||
* ``toc.secnum``
|
||||
* ``epub.unknown_project_files``
|
||||
* ``epub.duplicated_toc_entry``
|
||||
@ -360,6 +362,10 @@ General configuration
|
||||
|
||||
Added ``epub.duplicated_toc_entry``
|
||||
|
||||
.. versionchanged:: 4.3
|
||||
|
||||
Added ``toc.excluded`` and ``toc.not_readable``
|
||||
|
||||
.. confval:: needs_sphinx
|
||||
|
||||
If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will
|
||||
@ -802,6 +808,13 @@ documentation on :ref:`intl` for details.
|
||||
.. versionchanged:: 1.5
|
||||
Use ``locales`` directory as a default value
|
||||
|
||||
.. confval:: gettext_allow_fuzzy_translations
|
||||
|
||||
If true, "fuzzy" messages in the message catalogs are used for translation.
|
||||
The default is ``False``.
|
||||
|
||||
.. versionadded:: 4.3
|
||||
|
||||
.. confval:: gettext_compact
|
||||
|
||||
.. versionadded:: 1.1
|
||||
|
@ -38,7 +38,11 @@ __released__ = '5.0.0' # used when Sphinx builds its own docs
|
||||
#:
|
||||
#: .. versionadded:: 1.2
|
||||
#: Before version 1.2, check the string ``sphinx.__version__``.
|
||||
<<<<<<< HEAD
|
||||
version_info = (5, 0, 0, 'final', 0)
|
||||
=======
|
||||
version_info = (4, 4, 0, 'beta', 0)
|
||||
>>>>>>> 4.x
|
||||
|
||||
package_dir = path.abspath(path.dirname(__file__))
|
||||
|
||||
|
@ -284,7 +284,8 @@ class Sphinx:
|
||||
self.config.language, self.config.source_encoding)
|
||||
for catalog in repo.catalogs:
|
||||
if catalog.domain == 'sphinx' and catalog.is_outdated():
|
||||
catalog.write_mo(self.config.language)
|
||||
catalog.write_mo(self.config.language,
|
||||
self.config.gettext_allow_fuzzy_translations)
|
||||
|
||||
locale_dirs: List[Optional[str]] = list(repo.locale_dirs)
|
||||
locale_dirs += [None]
|
||||
|
@ -217,7 +217,8 @@ class Builder:
|
||||
for catalog in status_iterator(catalogs, __('writing output... '), "darkgreen",
|
||||
len(catalogs), self.app.verbosity,
|
||||
stringify_func=cat2relpath):
|
||||
catalog.write_mo(self.config.language)
|
||||
catalog.write_mo(self.config.language,
|
||||
self.config.gettext_allow_fuzzy_translations)
|
||||
|
||||
def compile_all_catalogs(self) -> None:
|
||||
repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
|
||||
|
@ -103,6 +103,7 @@ class Config:
|
||||
'language': (None, 'env', [str]),
|
||||
'locale_dirs': (['locales'], 'env', []),
|
||||
'figure_language_filename': ('{root}.{language}{ext}', 'env', [str]),
|
||||
'gettext_allow_fuzzy_translations': (False, 'gettext', []),
|
||||
|
||||
'master_doc': ('index', 'env', []),
|
||||
'root_doc': (lambda config: config.master_doc, 'env', []),
|
||||
|
@ -18,8 +18,8 @@ from docutils.parsers.rst.directives.misc import Include as BaseInclude
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.domains.changeset import VersionChange # NOQA # for compatibility
|
||||
from sphinx.locale import _
|
||||
from sphinx.util import docname_join, url_re
|
||||
from sphinx.locale import _, __
|
||||
from sphinx.util import docname_join, logging, url_re
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
from sphinx.util.matching import Matcher, patfilter
|
||||
from sphinx.util.nodes import explicit_title_re
|
||||
@ -30,6 +30,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
glob_re = re.compile(r'.*[*?\[].*')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def int_or_nothing(argument: str) -> int:
|
||||
@ -106,9 +107,8 @@ class TocTree(SphinxDirective):
|
||||
toctree['entries'].append((None, docname))
|
||||
toctree['includefiles'].append(docname)
|
||||
if not docnames:
|
||||
ret.append(self.state.document.reporter.warning(
|
||||
'toctree glob pattern %r didn\'t match any documents'
|
||||
% entry, line=self.lineno))
|
||||
logger.warning(__('toctree glob pattern %r didn\'t match any documents'),
|
||||
entry, location=toctree)
|
||||
else:
|
||||
if explicit:
|
||||
ref = explicit.group(2)
|
||||
@ -128,20 +128,21 @@ class TocTree(SphinxDirective):
|
||||
toctree['entries'].append((title, ref))
|
||||
elif docname not in self.env.found_docs:
|
||||
if excluded(self.env.doc2path(docname, None)):
|
||||
message = 'toctree contains reference to excluded document %r'
|
||||
message = __('toctree contains reference to excluded document %r')
|
||||
subtype = 'excluded'
|
||||
else:
|
||||
message = 'toctree contains reference to nonexisting document %r'
|
||||
message = __('toctree contains reference to nonexisting document %r')
|
||||
subtype = 'not_readable'
|
||||
|
||||
ret.append(self.state.document.reporter.warning(message % docname,
|
||||
line=self.lineno))
|
||||
logger.warning(message, docname, type='toc', subtype=subtype,
|
||||
location=toctree)
|
||||
self.env.note_reread()
|
||||
else:
|
||||
if docname in all_docnames:
|
||||
all_docnames.remove(docname)
|
||||
else:
|
||||
message = 'duplicated entry found in toctree: %s'
|
||||
ret.append(self.state.document.reporter.warning(message % docname,
|
||||
line=self.lineno))
|
||||
logger.warning(__('duplicated entry found in toctree: %s'), docname,
|
||||
location=toctree)
|
||||
|
||||
toctree['entries'].append((title, docname))
|
||||
toctree['includefiles'].append(docname)
|
||||
@ -250,8 +251,9 @@ class Acks(SphinxDirective):
|
||||
self.state.nested_parse(self.content, self.content_offset, node)
|
||||
if len(node.children) != 1 or not isinstance(node.children[0],
|
||||
nodes.bullet_list):
|
||||
reporter = self.state.document.reporter
|
||||
return [reporter.warning('.. acks content is not a list', line=self.lineno)]
|
||||
logger.warning(__('.. acks content is not a list'),
|
||||
location=(self.env.docname, self.lineno))
|
||||
return []
|
||||
return [node]
|
||||
|
||||
|
||||
@ -274,8 +276,9 @@ class HList(SphinxDirective):
|
||||
self.state.nested_parse(self.content, self.content_offset, node)
|
||||
if len(node.children) != 1 or not isinstance(node.children[0],
|
||||
nodes.bullet_list):
|
||||
reporter = self.state.document.reporter
|
||||
return [reporter.warning('.. hlist content is not a list', line=self.lineno)]
|
||||
logger.warning(__('.. hlist content is not a list'),
|
||||
location=(self.env.docname, self.lineno))
|
||||
return []
|
||||
fulllist = node.children[0]
|
||||
# create a hlist node where the items are distributed
|
||||
npercol, nmore = divmod(len(fulllist), ncolumns)
|
||||
|
@ -26,7 +26,7 @@ from sphinx import addnodes
|
||||
from sphinx.addnodes import desc_signature, pending_xref, pending_xref_condition
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.deprecation import RemovedInSphinx50Warning
|
||||
from sphinx.deprecation import RemovedInSphinx50Warning, RemovedInSphinx60Warning
|
||||
from sphinx.directives import ObjectDescription
|
||||
from sphinx.domains import Domain, Index, IndexEntry, ObjType
|
||||
from sphinx.environment import BuildEnvironment
|
||||
@ -495,7 +495,17 @@ class PyObject(ObjectDescription[Tuple[str, str]]):
|
||||
|
||||
sig_prefix = self.get_signature_prefix(sig)
|
||||
if sig_prefix:
|
||||
signode += addnodes.desc_annotation(str(sig_prefix), '', *sig_prefix)
|
||||
if type(sig_prefix) is str:
|
||||
warnings.warn(
|
||||
"Python directive method get_signature_prefix()"
|
||||
" returning a string is deprecated."
|
||||
" It must now return a list of nodes."
|
||||
" Return value was '{}'.".format(sig_prefix),
|
||||
RemovedInSphinx60Warning)
|
||||
signode += addnodes.desc_annotation(sig_prefix, '', # type: ignore
|
||||
nodes.Text(sig_prefix)) # type: ignore
|
||||
else:
|
||||
signode += addnodes.desc_annotation(str(sig_prefix), '', *sig_prefix)
|
||||
|
||||
if prefix:
|
||||
signode += addnodes.desc_addname(prefix, prefix)
|
||||
|
@ -81,7 +81,7 @@ def install_mathjax(app: Sphinx, pagename: str, templatename: str, context: Dict
|
||||
domain = cast(MathDomain, app.env.get_domain('math'))
|
||||
if app.registry.html_assets_policy == 'always' or domain.has_equations(pagename):
|
||||
# Enable mathjax only if equations exists
|
||||
options = {'async': 'async'}
|
||||
options = {'defer': 'defer'}
|
||||
if app.config.mathjax_options:
|
||||
options.update(app.config.mathjax_options)
|
||||
app.add_js_file(app.config.mathjax_path, **options) # type: ignore
|
||||
|
@ -8,11 +8,11 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from distutils.version import LooseVersion
|
||||
from functools import partial
|
||||
from importlib import import_module
|
||||
from typing import Any, Dict
|
||||
|
||||
from packaging import version
|
||||
from pygments import __version__ as pygmentsversion
|
||||
from pygments import highlight
|
||||
from pygments.filters import ErrorToken
|
||||
@ -64,7 +64,7 @@ _LATEX_ADD_STYLES_FIXPYG = r'''
|
||||
{\let\fcolorbox\spx@fixpyg@fcolorbox\PYG@do{#2}}}
|
||||
\makeatother
|
||||
'''
|
||||
if tuple(LooseVersion(pygmentsversion).version) <= (2, 7, 4):
|
||||
if version.parse(pygmentsversion).release <= (2, 7, 4):
|
||||
_LATEX_ADD_STYLES += _LATEX_ADD_STYLES_FIXPYG
|
||||
|
||||
|
||||
|
@ -12,7 +12,6 @@ import os
|
||||
import re
|
||||
from contextlib import contextmanager
|
||||
from copy import copy
|
||||
from distutils.version import LooseVersion
|
||||
from os import path
|
||||
from types import ModuleType
|
||||
from typing import (IO, TYPE_CHECKING, Any, Callable, Dict, Generator, List, Optional, Set,
|
||||
@ -26,6 +25,7 @@ from docutils.parsers.rst import Directive, directives, roles
|
||||
from docutils.parsers.rst.states import Inliner
|
||||
from docutils.statemachine import State, StateMachine, StringList
|
||||
from docutils.utils import Reporter, unescape
|
||||
from packaging import version
|
||||
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.locale import _
|
||||
@ -41,7 +41,7 @@ if TYPE_CHECKING:
|
||||
from sphinx.environment import BuildEnvironment
|
||||
|
||||
|
||||
__version_info__ = tuple(LooseVersion(docutils.__version__).version)
|
||||
__version_info__ = version.parse(docutils.__version__).release
|
||||
additional_nodes: Set[Type[Element]] = set()
|
||||
|
||||
|
||||
|
@ -59,7 +59,7 @@ class CatalogInfo(LocaleFileInfoBase):
|
||||
not path.exists(self.mo_path) or
|
||||
path.getmtime(self.mo_path) < path.getmtime(self.po_path))
|
||||
|
||||
def write_mo(self, locale: str) -> None:
|
||||
def write_mo(self, locale: str, use_fuzzy: bool = False) -> None:
|
||||
with open(self.po_path, encoding=self.charset) as file_po:
|
||||
try:
|
||||
po = read_po(file_po, locale)
|
||||
@ -69,7 +69,7 @@ class CatalogInfo(LocaleFileInfoBase):
|
||||
|
||||
with open(self.mo_path, 'wb') as file_mo:
|
||||
try:
|
||||
write_mo(file_mo, po)
|
||||
write_mo(file_mo, po, use_fuzzy)
|
||||
except Exception as exc:
|
||||
logger.warning(__('writing error: %s, %s'), self.mo_path, exc)
|
||||
|
||||
|
@ -10,13 +10,13 @@
|
||||
|
||||
import os
|
||||
import re
|
||||
from distutils.version import LooseVersion
|
||||
from itertools import chain, cycle
|
||||
from unittest.mock import ANY, call, patch
|
||||
|
||||
import pygments
|
||||
import pytest
|
||||
from html5lib import HTMLParser
|
||||
from packaging import version
|
||||
|
||||
from sphinx.builders.html import validate_html_extra_path, validate_html_static_path
|
||||
from sphinx.errors import ConfigError
|
||||
@ -30,6 +30,9 @@ else:
|
||||
FIGURE_CAPTION = ".//figure/figcaption/p"
|
||||
|
||||
|
||||
PYGMENTS_VERSION = version.parse(pygments.__version__).release
|
||||
|
||||
|
||||
ENV_WARNINGS = """\
|
||||
%(root)s/autodoc_fodder.py:docstring of autodoc_fodder.MarkupError:\\d+: \
|
||||
WARNING: Explicit markup ends without a blank line; unexpected unindent.
|
||||
@ -1576,8 +1579,7 @@ def test_html_codeblock_linenos_style_table(app):
|
||||
app.build()
|
||||
content = (app.outdir / 'index.html').read_text()
|
||||
|
||||
pygments_version = tuple(LooseVersion(pygments.__version__).version)
|
||||
if pygments_version >= (2, 8):
|
||||
if PYGMENTS_VERSION >= (2, 8):
|
||||
assert ('<div class="linenodiv"><pre><span class="normal">1</span>\n'
|
||||
'<span class="normal">2</span>\n'
|
||||
'<span class="normal">3</span>\n'
|
||||
@ -1592,8 +1594,7 @@ def test_html_codeblock_linenos_style_inline(app):
|
||||
app.build()
|
||||
content = (app.outdir / 'index.html').read_text()
|
||||
|
||||
pygments_version = tuple(LooseVersion(pygments.__version__).version)
|
||||
if pygments_version > (2, 7):
|
||||
if PYGMENTS_VERSION > (2, 7):
|
||||
assert '<span class="linenos">1</span>' in content
|
||||
else:
|
||||
assert '<span class="lineno">1 </span>' in content
|
||||
|
@ -71,7 +71,7 @@ def test_mathjax_options(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
content = (app.outdir / 'index.html').read_text()
|
||||
assert ('<script async="async" integrity="sha384-0123456789" '
|
||||
assert ('<script defer="defer" integrity="sha384-0123456789" '
|
||||
'src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">'
|
||||
'</script>' in content)
|
||||
|
||||
|
@ -1301,6 +1301,44 @@ def getwarning(warnings):
|
||||
return strip_escseq(warnings.getvalue().replace(os.sep, '/'))
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='basic',
|
||||
srcdir='gettext_allow_fuzzy_translations',
|
||||
confoverrides={
|
||||
'language': 'de',
|
||||
'gettext_allow_fuzzy_translations': True
|
||||
})
|
||||
def test_gettext_allow_fuzzy_translations(app):
|
||||
locale_dir = app.srcdir / 'locales' / 'de' / 'LC_MESSAGES'
|
||||
locale_dir.makedirs()
|
||||
with (locale_dir / 'index.po').open('wb') as f:
|
||||
catalog = Catalog()
|
||||
catalog.add('features', 'FEATURES', flags=('fuzzy',))
|
||||
pofile.write_po(f, catalog)
|
||||
|
||||
app.build()
|
||||
content = (app.outdir / 'index.html').read_text()
|
||||
assert 'FEATURES' in content
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='basic',
|
||||
srcdir='gettext_disallow_fuzzy_translations',
|
||||
confoverrides={
|
||||
'language': 'de',
|
||||
'gettext_allow_fuzzy_translations': False
|
||||
})
|
||||
def test_gettext_disallow_fuzzy_translations(app):
|
||||
locale_dir = app.srcdir / 'locales' / 'de' / 'LC_MESSAGES'
|
||||
locale_dir.makedirs()
|
||||
with (locale_dir / 'index.po').open('wb') as f:
|
||||
catalog = Catalog()
|
||||
catalog.add('features', 'FEATURES', flags=('fuzzy',))
|
||||
pofile.write_po(f, catalog)
|
||||
|
||||
app.build()
|
||||
content = (app.outdir / 'index.html').read_text()
|
||||
assert 'FEATURES' not in content
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='basic', confoverrides={'language': 'de'})
|
||||
def test_customize_system_message(make_app, app_params, sphinx_test_tempdir):
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user