From 6ecc9224cd0e9a986c63eccb21fb6672fad81478 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sat, 25 Jan 2020 15:56:38 +0100 Subject: [PATCH 01/15] C++, fix rendering of expr lists --- CHANGES | 9 ++++++--- sphinx/domains/cpp.py | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index bef70360a..cc474d182 100644 --- a/CHANGES +++ b/CHANGES @@ -16,9 +16,12 @@ Features added Bugs fixed ---------- -* C++, don't crash when using the ``struct`` role in some cases. -* C++, don't warn when using the ``var``/``member`` role for function - parameters. +* C++: + + - Don't crash when using the ``struct`` role in some cases. + - Don't warn when using the ``var``/``member`` role for function + parameters. + - Render call and braced-init expressions correctly. Testing -------- diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 53722b124..d7b6d1bd2 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -3262,7 +3262,7 @@ class ASTParenExprList(ASTBase): signode.append(nodes.Text(', ')) else: first = False - e.describe_signature(signode, mode, env, symbol) + e.describe_signature(signode, mode, env, symbol) signode.append(nodes.Text(')')) @@ -3292,7 +3292,7 @@ class ASTBracedInitList(ASTBase): signode.append(nodes.Text(', ')) else: first = False - e.describe_signature(signode, mode, env, symbol) + e.describe_signature(signode, mode, env, symbol) if self.trailingComma: signode.append(nodes.Text(',')) signode.append(nodes.Text('}')) From 580afe5b5056d68d307e468808d427296c951974 Mon Sep 17 00:00:00 2001 From: s-weigand Date: Mon, 3 Feb 2020 19:37:43 +0100 Subject: [PATCH 02/15] Added code to replace problematic characters in filenames when using ImageConverter --- sphinx/transforms/post_transforms/images.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sphinx/transforms/post_transforms/images.py b/sphinx/transforms/post_transforms/images.py index 69a939731..31f1c149a 100644 --- a/sphinx/transforms/post_transforms/images.py +++ b/sphinx/transforms/post_transforms/images.py @@ -9,6 +9,7 @@ """ import os +import re from hashlib import sha1 from math import ceil from typing import Any, Dict, List, Tuple @@ -27,6 +28,7 @@ from sphinx.util.osutil import ensuredir, movefile logger = logging.getLogger(__name__) MAX_FILENAME_LEN = 32 +CRITICAL_PATH_CHAR_RE = re.compile('[:;<>|*" ]') class BaseImageConverter(SphinxTransform): @@ -146,6 +148,7 @@ class DataURIExtractor(BaseImageConverter): def get_filename_for(filename: str, mimetype: str) -> str: basename = os.path.basename(filename) + basename = re.sub(CRITICAL_PATH_CHAR_RE, "_", basename) return os.path.splitext(basename)[0] + get_image_extension(mimetype) From 7f93bbf39724bfcd3d610c184c958253c350ef8d Mon Sep 17 00:00:00 2001 From: s-weigand Date: Tue, 4 Feb 2020 14:01:51 +0100 Subject: [PATCH 03/15] Added entry to CHANGES --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index cc474d182..e1ca210d7 100644 --- a/CHANGES +++ b/CHANGES @@ -33,6 +33,11 @@ Bugs fixed ---------- * #6936: sphinx-autogen: raises AttributeError +* Filenames of images generated by + ``sphinx.transforms.post_transforms.images.ImageConverter`` + or its subclasses (used for latex build) are now sanitized, + to prevent broken paths + Release 2.3.0 (released Dec 15, 2019) ===================================== From ca0f1c49c9c3b5fdea090650ec72dfed7b4b4656 Mon Sep 17 00:00:00 2001 From: s-weigand Date: Tue, 4 Feb 2020 17:32:33 +0100 Subject: [PATCH 04/15] Also added sanitizing to 'ImageDownloader' --- sphinx/transforms/post_transforms/images.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx/transforms/post_transforms/images.py b/sphinx/transforms/post_transforms/images.py index 31f1c149a..d9c5535f8 100644 --- a/sphinx/transforms/post_transforms/images.py +++ b/sphinx/transforms/post_transforms/images.py @@ -67,6 +67,7 @@ class ImageDownloader(BaseImageConverter): if basename == '' or len(basename) > MAX_FILENAME_LEN: filename, ext = os.path.splitext(node['uri']) basename = sha1(filename.encode()).hexdigest() + ext + basename = re.sub(CRITICAL_PATH_CHAR_RE, "_", basename) dirname = node['uri'].replace('://', '/').translate({ord("?"): "/", ord("&"): "/"}) From 41eb2575f1a03fe41666e6af6253a9ced44a86b9 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 6 Feb 2020 00:51:40 +0900 Subject: [PATCH 05/15] Update CHANGES for PR #7097 --- CHANGES | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index e1ca210d7..69e7c50b9 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,11 @@ Bugs fixed parameters. - Render call and braced-init expressions correctly. +* #7097: Filenames of images generated by + ``sphinx.transforms.post_transforms.images.ImageConverter`` + or its subclasses (used for latex build) are now sanitized, + to prevent broken paths + Testing -------- @@ -33,11 +38,6 @@ Bugs fixed ---------- * #6936: sphinx-autogen: raises AttributeError -* Filenames of images generated by - ``sphinx.transforms.post_transforms.images.ImageConverter`` - or its subclasses (used for latex build) are now sanitized, - to prevent broken paths - Release 2.3.0 (released Dec 15, 2019) ===================================== From 13ca2323a9f498699ba2764746f5eca29f372fc4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 6 Feb 2020 23:19:03 +0900 Subject: [PATCH 06/15] Fix #7095: dirhtml: Cross references are broken via intersphinx and :doc: --- CHANGES | 1 + sphinx/util/inventory.py | 2 +- tests/roots/test-builder-dirhtml/bar.rst | 4 ++ tests/roots/test-builder-dirhtml/conf.py | 0 .../roots/test-builder-dirhtml/foo/foo_1.rst | 4 ++ .../roots/test-builder-dirhtml/foo/foo_2.rst | 4 ++ .../roots/test-builder-dirhtml/foo/index.rst | 9 ++++ tests/roots/test-builder-dirhtml/index.rst | 9 ++++ tests/test_build_dirhtml.py | 47 +++++++++++++++++++ 9 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 tests/roots/test-builder-dirhtml/bar.rst create mode 100644 tests/roots/test-builder-dirhtml/conf.py create mode 100644 tests/roots/test-builder-dirhtml/foo/foo_1.rst create mode 100644 tests/roots/test-builder-dirhtml/foo/foo_2.rst create mode 100644 tests/roots/test-builder-dirhtml/foo/index.rst create mode 100644 tests/roots/test-builder-dirhtml/index.rst create mode 100644 tests/test_build_dirhtml.py diff --git a/CHANGES b/CHANGES index 7e8d70b2b..448fbd7f6 100644 --- a/CHANGES +++ b/CHANGES @@ -83,6 +83,7 @@ Bugs fixed * #6889: autodoc: Trailing comma in ``:members::`` option causes cryptic warning * #7055: linkcheck: redirect is treated as an error * #7090: std domain: Can't assign numfig-numbers for custom container nodes +* #7095: dirhtml: Cross references are broken via intersphinx and ``:doc:`` role Testing -------- diff --git a/sphinx/util/inventory.py b/sphinx/util/inventory.py index 64f4ef4e3..9b647ccac 100644 --- a/sphinx/util/inventory.py +++ b/sphinx/util/inventory.py @@ -122,7 +122,7 @@ class InventoryFile: for line in stream.read_compressed_lines(): # be careful to handle names with embedded spaces correctly - m = re.match(r'(?x)(.+?)\s+(\S*:\S*)\s+(-?\d+)\s+(\S+)\s+(.*)', + m = re.match(r'(?x)(.+?)\s+(\S*:\S*)\s+(-?\d+)\s+?(\S*)\s+(.*)', line.rstrip()) if not m: continue diff --git a/tests/roots/test-builder-dirhtml/bar.rst b/tests/roots/test-builder-dirhtml/bar.rst new file mode 100644 index 000000000..11f287a18 --- /dev/null +++ b/tests/roots/test-builder-dirhtml/bar.rst @@ -0,0 +1,4 @@ +.. _bar: + +bar +=== diff --git a/tests/roots/test-builder-dirhtml/conf.py b/tests/roots/test-builder-dirhtml/conf.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/roots/test-builder-dirhtml/foo/foo_1.rst b/tests/roots/test-builder-dirhtml/foo/foo_1.rst new file mode 100644 index 000000000..6db0ea57e --- /dev/null +++ b/tests/roots/test-builder-dirhtml/foo/foo_1.rst @@ -0,0 +1,4 @@ +.. _foo_1: + +foo/foo_1 +========= diff --git a/tests/roots/test-builder-dirhtml/foo/foo_2.rst b/tests/roots/test-builder-dirhtml/foo/foo_2.rst new file mode 100644 index 000000000..fae7f26ef --- /dev/null +++ b/tests/roots/test-builder-dirhtml/foo/foo_2.rst @@ -0,0 +1,4 @@ +.. _foo_2: + +foo/foo_2 +========= diff --git a/tests/roots/test-builder-dirhtml/foo/index.rst b/tests/roots/test-builder-dirhtml/foo/index.rst new file mode 100644 index 000000000..92d473c6b --- /dev/null +++ b/tests/roots/test-builder-dirhtml/foo/index.rst @@ -0,0 +1,9 @@ +.. _foo: + +foo/index +========= + +.. toctree:: + + foo_1 + foo_2 diff --git a/tests/roots/test-builder-dirhtml/index.rst b/tests/roots/test-builder-dirhtml/index.rst new file mode 100644 index 000000000..274e17793 --- /dev/null +++ b/tests/roots/test-builder-dirhtml/index.rst @@ -0,0 +1,9 @@ +.. _index: + +index +===== + +.. toctree:: + + foo/index + bar diff --git a/tests/test_build_dirhtml.py b/tests/test_build_dirhtml.py new file mode 100644 index 000000000..715db1146 --- /dev/null +++ b/tests/test_build_dirhtml.py @@ -0,0 +1,47 @@ +""" + test_build_dirhtml + ~~~~~~~~~~~~~~~~~~ + + Test dirhtml builder. + + :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import posixpath + +import pytest + +from sphinx.util.inventory import InventoryFile + + +@pytest.mark.sphinx(buildername='dirhtml', testroot='builder-dirhtml') +def test_dirhtml(app, status, warning): + app.build() + + assert (app.outdir / 'index.html').exists() + assert (app.outdir / 'foo/index.html').exists() + assert (app.outdir / 'foo/foo_1/index.html').exists() + assert (app.outdir / 'foo/foo_2/index.html').exists() + assert (app.outdir / 'bar/index.html').exists() + + content = (app.outdir / 'index.html').text() + assert 'href="foo/"' in content + assert 'href="foo/foo_1/"' in content + assert 'href="foo/foo_2/"' in content + assert 'href="bar/"' in content + + # objects.inv (refs: #7095) + f = (app.outdir / 'objects.inv').open('rb') + invdata = InventoryFile.load(f, 'path/to', posixpath.join) + assert 'index' in invdata.get('std:doc') + assert ('Python', '', 'path/to/', '-') == invdata['std:doc']['index'] + + assert 'foo/index' in invdata.get('std:doc') + assert ('Python', '', 'path/to/foo/', '-') == invdata['std:doc']['foo/index'] + + assert 'index' in invdata.get('std:label') + assert ('Python', '', 'path/to/#index', '-') == invdata['std:label']['index'] + + assert 'foo' in invdata.get('std:label') + assert ('Python', '', 'path/to/foo/#foo', 'foo/index') == invdata['std:label']['foo'] From 9d301e5b8146c5810a66b2f60a4b79d99934e3fb Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 8 Feb 2020 17:53:48 +0900 Subject: [PATCH 07/15] refactor: apidoc.shall_skip() --- CHANGES | 1 + doc/extdev/deprecated.rst | 5 +++++ sphinx/ext/apidoc.py | 40 ++++++++++++++++++++++++++++++++++----- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 0d72f3e62..c73dc30f5 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,7 @@ Deprecated * ``sphinx.environment.temp_data['gloss_entries']`` * ``sphinx.environment.BuildEnvironment.indexentries`` * ``sphinx.environment.collectors.indexentries.IndexEntriesCollector`` +* ``sphinx.ext.apidoc.shall_skip()`` * ``sphinx.io.FiletypeNotFoundError`` * ``sphinx.io.get_filetype()`` * ``sphinx.pycode.ModuleAnalyzer.encoding`` diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst index 8a084be4d..29a01ede4 100644 --- a/doc/extdev/deprecated.rst +++ b/doc/extdev/deprecated.rst @@ -56,6 +56,11 @@ The following is a list of deprecated interfaces. - 4.0 - ``sphinx.errors.FiletypeNotFoundError`` + * - ``sphinx.ext.apidoc.shall_skip()`` + - 2.4 + - 4.0 + - ``sphinx.ext.apidoc.is_skipped_package`` + * - ``sphinx.io.get_filetype()`` - 2.4 - 4.0 diff --git a/sphinx/ext/apidoc.py b/sphinx/ext/apidoc.py index 99cf67016..38cc12f25 100644 --- a/sphinx/ext/apidoc.py +++ b/sphinx/ext/apidoc.py @@ -66,6 +66,16 @@ def makename(package: str, module: str) -> str: return name +def is_initpy(filename: str) -> bool: + """Check *filename* is __init__ file or not.""" + basename = path.basename(filename) + for suffix in sorted(PY_SUFFIXES, key=len, reverse=True): + if basename == '__init__' + suffix: + return True + else: + return False + + def module_join(*modnames: str) -> str: """Join module names with dots.""" return '.'.join(filter(None, modnames)) @@ -132,11 +142,10 @@ def create_package_file(root: str, master_package: str, subroot: str, py_files: opts: Any, subs: List[str], is_namespace: bool, excludes: List[str] = [], user_template_dir: str = None) -> None: """Build the text of the file and write the file.""" - # build a list of sub packages (directories containing an INITPY file) - subpackages = [sub for sub in subs if not - shall_skip(path.join(root, sub, INITPY), opts, excludes)] + # build a list of sub packages (directories containing an __init__ file) subpackages = [module_join(master_package, subroot, pkgname) - for pkgname in subpackages] + for pkgname in subs + if not is_skipped_package(path.join(root, pkgname), opts, excludes)] # build a list of sub modules submodules = [sub.split('.')[0] for sub in py_files if not is_skipped_module(path.join(root, sub), opts, excludes) and @@ -189,6 +198,8 @@ def create_modules_toc_file(modules: List[str], opts: Any, name: str = 'modules' def shall_skip(module: str, opts: Any, excludes: List[str] = []) -> bool: """Check if we want to skip this module.""" + warnings.warn('shall_skip() is deprecated.', + RemovedInSphinx40Warning) # skip if the file doesn't exist and not using implicit namespaces if not opts.implicit_namespaces and not path.exists(module): return True @@ -213,6 +224,25 @@ def shall_skip(module: str, opts: Any, excludes: List[str] = []) -> bool: return False +def is_skipped_package(dirname: str, opts: Any, excludes: List[str] = []) -> bool: + """Check if we want to skip this module.""" + if not path.isdir(dirname): + return False + + files = glob.glob(path.join(dirname, '*.py')) + regular_package = any(f for f in files if is_initpy(f)) + if not regular_package and not opts.implicit_namespaces: + # *dirname* is not both a regular package and an implicit namespace pacage + return True + + # Check there is some showable module inside package + if all(is_excluded(path.join(dirname, f), excludes) for f in files): + # all submodules are excluded + return True + else: + return False + + def is_skipped_module(filename: str, opts: Any, excludes: List[str]) -> bool: """Check if we want to skip this module.""" if not path.exists(filename): @@ -269,7 +299,7 @@ def recurse_tree(rootpath: str, excludes: List[str], opts: Any, if is_pkg or is_namespace: # we are in a package with something to document - if subs or len(py_files) > 1 or not shall_skip(path.join(root, INITPY), opts): + if subs or len(py_files) > 1 or not is_skipped_package(root, opts): subpackage = root[len(rootpath):].lstrip(path.sep).\ replace(path.sep, '.') # if this is not a namespace or From dee8b9eddb1c9341036f56fd6ca905d1a1c66cd6 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 8 Feb 2020 18:04:48 +0900 Subject: [PATCH 08/15] Fix #6327: apidoc: Support a python package consisted of __init__.so file --- CHANGES | 2 ++ doc/extdev/deprecated.rst | 5 +++++ sphinx/ext/apidoc.py | 39 ++++++++++++++++++++++++++++----------- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index c73dc30f5..9d2cdef9e 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,7 @@ Deprecated * ``sphinx.environment.temp_data['gloss_entries']`` * ``sphinx.environment.BuildEnvironment.indexentries`` * ``sphinx.environment.collectors.indexentries.IndexEntriesCollector`` +* ``sphinx.ext.apidoc.INITPY`` * ``sphinx.ext.apidoc.shall_skip()`` * ``sphinx.io.FiletypeNotFoundError`` * ``sphinx.io.get_filetype()`` @@ -77,6 +78,7 @@ Bugs fixed * #6559: Wrong node-ids are generated in glossary directive * #6986: apidoc: misdetects module name for .so file inside module * #6899: apidoc: private members are not shown even if ``--private`` given +* #6327: apidoc: Support a python package consisted of __init__.so file * #6999: napoleon: fails to parse tilde in :exc: role * #7019: gettext: Absolute path used in message catalogs * #7023: autodoc: nested partial functions are not listed diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst index 29a01ede4..d009454ea 100644 --- a/doc/extdev/deprecated.rst +++ b/doc/extdev/deprecated.rst @@ -56,6 +56,11 @@ The following is a list of deprecated interfaces. - 4.0 - ``sphinx.errors.FiletypeNotFoundError`` + * - ``sphinx.ext.apidoc.INITPY`` + - 2.4 + - 4.0 + - N/A + * - ``sphinx.ext.apidoc.shall_skip()`` - 2.4 - 4.0 diff --git a/sphinx/ext/apidoc.py b/sphinx/ext/apidoc.py index 38cc12f25..a9196d3a6 100644 --- a/sphinx/ext/apidoc.py +++ b/sphinx/ext/apidoc.py @@ -29,7 +29,7 @@ from typing import Any, List, Tuple import sphinx.locale from sphinx import __display_version__, package_dir from sphinx.cmd.quickstart import EXTENSIONS -from sphinx.deprecation import RemovedInSphinx40Warning +from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias from sphinx.locale import __ from sphinx.util import rst from sphinx.util.osutil import FileAvoidWrite, ensuredir @@ -46,7 +46,6 @@ else: 'show-inheritance', ] -INITPY = '__init__.py' PY_SUFFIXES = ('.py', '.pyx') + tuple(EXTENSION_SUFFIXES) template_dir = path.join(package_dir, 'templates', 'apidoc') @@ -81,6 +80,16 @@ def module_join(*modnames: str) -> str: return '.'.join(filter(None, modnames)) +def is_packagedir(dirname: str = None, files: List[str] = None) -> bool: + """Check given *files* contains __init__ file.""" + if files is None and dirname is None: + return False + + if files is None: + files = os.listdir(dirname) + return any(f for f in files if is_initpy(f)) + + def write_file(name: str, text: str, opts: Any) -> None: """Write the output file for module/package .""" quiet = getattr(opts, 'quiet', None) @@ -149,7 +158,7 @@ def create_package_file(root: str, master_package: str, subroot: str, py_files: # build a list of sub modules submodules = [sub.split('.')[0] for sub in py_files if not is_skipped_module(path.join(root, sub), opts, excludes) and - sub != INITPY] + not is_initpy(sub)] submodules = [module_join(master_package, subroot, modname) for modname in submodules] options = copy(OPTIONS) @@ -205,7 +214,7 @@ def shall_skip(module: str, opts: Any, excludes: List[str] = []) -> bool: return True # Are we a package (here defined as __init__.py, not the folder in itself) - if os.path.basename(module) == INITPY: + if is_initpy(module): # Yes, check if we have any non-excluded modules at all here all_skipped = True basemodule = path.dirname(module) @@ -218,8 +227,7 @@ def shall_skip(module: str, opts: Any, excludes: List[str] = []) -> bool: # skip if it has a "private" name and this is selected filename = path.basename(module) - if filename != '__init__.py' and filename.startswith('_') and \ - not opts.includeprivate: + if is_initpy(filename) and filename.startswith('_') and not opts.includeprivate: return True return False @@ -266,7 +274,7 @@ def recurse_tree(rootpath: str, excludes: List[str], opts: Any, implicit_namespaces = getattr(opts, 'implicit_namespaces', False) # check if the base directory is a package and get its name - if INITPY in os.listdir(rootpath) or implicit_namespaces: + if is_packagedir(rootpath) or implicit_namespaces: root_package = rootpath.split(path.sep)[-1] else: # otherwise, the base is a directory with packages @@ -278,11 +286,13 @@ def recurse_tree(rootpath: str, excludes: List[str], opts: Any, py_files = sorted(f for f in files if f.endswith(PY_SUFFIXES) and not is_excluded(path.join(root, f), excludes)) - is_pkg = INITPY in py_files - is_namespace = INITPY not in py_files and implicit_namespaces + is_pkg = is_packagedir(None, py_files) + is_namespace = not is_pkg and implicit_namespaces if is_pkg: - py_files.remove(INITPY) - py_files.insert(0, INITPY) + for f in py_files[:]: + if is_initpy(f): + py_files.remove(f) + py_files.insert(0, f) elif root != rootpath: # only accept non-package at toplevel unless using implicit namespaces if not implicit_namespaces: @@ -505,6 +515,13 @@ def main(argv: List[str] = sys.argv[1:]) -> int: return 0 +deprecated_alias('sphinx.ext.apidoc', + { + 'INITPY': '__init__.py', + }, + RemovedInSphinx40Warning) + + # So program can be started with "python -m sphinx.apidoc ..." if __name__ == "__main__": main() From 0f21a12834bad939d58fa4e670982a6575b343a1 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 8 Feb 2020 00:40:39 +0900 Subject: [PATCH 09/15] Fix #7106: std domain: enumerated nodes are marked as duplicated --- CHANGES | 2 ++ sphinx/transforms/__init__.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 0d72f3e62..298e7de62 100644 --- a/CHANGES +++ b/CHANGES @@ -89,6 +89,8 @@ Bugs fixed modifier keys are ignored, which means the feature can interfere with browser features * #7090: std domain: Can't assign numfig-numbers for custom container nodes +* #7106: std domain: enumerated nodes are marked as duplicated when extensions + call ``note_explicit_target()`` Testing -------- diff --git a/sphinx/transforms/__init__.py b/sphinx/transforms/__init__.py index 922b22e46..a00f04fdf 100644 --- a/sphinx/transforms/__init__.py +++ b/sphinx/transforms/__init__.py @@ -173,7 +173,9 @@ class AutoNumbering(SphinxTransform): domain = self.env.get_domain('std') # type: StandardDomain for node in self.document.traverse(nodes.Element): - if domain.is_enumerable_node(node) and domain.get_numfig_title(node) is not None: + if (domain.is_enumerable_node(node) and + domain.get_numfig_title(node) is not None and + node['ids'] == []): self.document.note_implicit_target(node) From 46e58d3989d692e4c5501c3bad7a56a0c28d06aa Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 9 Feb 2020 00:27:56 +0900 Subject: [PATCH 10/15] Close #7115: LaTeX: Allow to override LATEXOPTS and LATEXMKOPTS via envvars --- CHANGES | 2 ++ sphinx/texinputs/Makefile_t | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 0d72f3e62..764cb6d72 100644 --- a/CHANGES +++ b/CHANGES @@ -42,6 +42,8 @@ Features added * #6446: duration: Add ``sphinx.ext.durations`` to inspect which documents slow down the build * #6837: LaTeX: Support a nested table +* #7115: LaTeX: Allow to override LATEXOPTS and LATEXMKOPTS via environment + variable * #6966: graphviz: Support ``:class:`` option * #6696: html: ``:scale:`` option of image/figure directive not working for SVG images (imagesize-1.2.0 or above is required) diff --git a/sphinx/texinputs/Makefile_t b/sphinx/texinputs/Makefile_t index 405b34a58..08ddd2f0a 100644 --- a/sphinx/texinputs/Makefile_t +++ b/sphinx/texinputs/Makefile_t @@ -15,13 +15,13 @@ ALLIMGS = $(wildcard *.png *.gif *.jpg *.jpeg) # Prefix for archive names ARCHIVEPREFIX = # Additional LaTeX options (passed via variables in latexmkrc/latexmkjarc file) -export LATEXOPTS = +export LATEXOPTS ?= # Additional latexmk options {% if latex_engine == 'xelatex' -%} # with latexmk version 4.52b or higher set LATEXMKOPTS to -xelatex either here # or on command line for faster builds. {% endif -%} -LATEXMKOPTS = +LATEXMKOPTS ?= {% if xindy_use -%} export XINDYOPTS = {{ xindy_lang_option }} -M sphinx.xdy {% if latex_engine == 'pdflatex' -%} From 2dd02729bc675dfaa267059ee69076bc798c9034 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 8 Feb 2020 22:04:14 +0900 Subject: [PATCH 11/15] Fix #7112: html: SVG image is not layouted as float even if aligned --- CHANGES | 1 + sphinx/writers/html.py | 2 +- sphinx/writers/html5.py | 8 ++------ 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index f9c881f1f..57564563c 100644 --- a/CHANGES +++ b/CHANGES @@ -71,6 +71,7 @@ Bugs fixed ---------- * #6925: html: Remove redundant type="text/javascript" from