diff --git a/CHANGES b/CHANGES
index 7e6b60c41bf..d6833a325de 100644
--- a/CHANGES
+++ b/CHANGES
@@ -27,7 +27,7 @@ Bugs fixed
Testing
--------
-Release 6.1.3 (in development)
+Release 6.1.4 (in development)
==============================
Dependencies
@@ -48,6 +48,16 @@ Bugs fixed
Testing
--------
+Release 6.1.3 (released Jan 10, 2023)
+=====================================
+
+Bugs fixed
+----------
+
+* #11116: Reverted to previous Sphinx 5 node copying method
+* #11117: Reverted changes to parallel image processing from Sphinx 6.1.0
+* #11119: Supress ``ValueError`` in the ``linkcheck`` builder
+
Release 6.1.2 (released Jan 07, 2023)
=====================================
diff --git a/sphinx/builders/_epub_base.py b/sphinx/builders/_epub_base.py
index 7174914bb6c..ef857e9d358 100644
--- a/sphinx/builders/_epub_base.py
+++ b/sphinx/builders/_epub_base.py
@@ -401,12 +401,9 @@ def copy_image_files_pil(self) -> None:
the format and resizing the image if necessary/possible.
"""
ensuredir(path.join(self.outdir, self.imagedir))
- converted_images = {*self.env.original_image_uri.values()}
- for src in status_iterator(self.env.images, __('copying images... '), "brown",
- len(self.env.images), self.app.verbosity):
- if src in converted_images:
- continue
- _docnames, dest = self.env.images[src]
+ for src in status_iterator(self.images, __('copying images... '), "brown",
+ len(self.images), self.app.verbosity):
+ dest = self.images[src]
try:
img = Image.open(path.join(self.srcdir, src))
except OSError:
@@ -441,7 +438,7 @@ def copy_image_files(self) -> None:
"""Copy image files to destination directory.
This overwritten method can use Pillow to convert image files.
"""
- if self.env.images:
+ if self.images:
if self.config.epub_fix_images or self.config.epub_max_image_width:
if not Image:
logger.warning(__('Pillow not found - copying image files'))
diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py
index e6793459185..0ea33fbc780 100644
--- a/sphinx/builders/html/__init__.py
+++ b/sphinx/builders/html/__init__.py
@@ -655,9 +655,6 @@ def get_doc_context(self, docname: str, body: str, metatags: str) -> dict[str, A
}
def write_doc(self, docname: str, doctree: nodes.document) -> None:
- self.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir)
- self.post_process_images(doctree)
-
title_node = self.env.longtitles.get(docname)
title = self.render_partial(title_node)['title'] if title_node else ''
self.index_page(docname, doctree, title)
@@ -667,6 +664,7 @@ def write_doc(self, docname: str, doctree: nodes.document) -> None:
self.secnumbers = self.env.toc_secnumbers.get(docname, {})
self.fignumbers = self.env.toc_fignumbers.get(docname, {})
+ self.imgpath = relative_uri(self.get_target_uri(docname), '_images')
self.dlpath = relative_uri(self.get_target_uri(docname), '_downloads')
self.current_docname = docname
self.docwriter.write(doctree, destination)
@@ -677,6 +675,10 @@ def write_doc(self, docname: str, doctree: nodes.document) -> None:
ctx = self.get_doc_context(docname, body, metatags)
self.handle_page(docname, ctx, event_arg=doctree)
+ def write_doc_serialized(self, docname: str, doctree: nodes.document) -> None:
+ self.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir)
+ self.post_process_images(doctree)
+
def finish(self) -> None:
self.finish_tasks.add_task(self.gen_indices)
self.finish_tasks.add_task(self.gen_pages_from_extensions)
@@ -763,16 +765,13 @@ def write_domain_indices(self) -> None:
self.handle_page(indexname, indexcontext, 'domainindex.html')
def copy_image_files(self) -> None:
- if self.env.images:
- converted_images = {*self.env.original_image_uri.values()}
+ if self.images:
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
ensuredir(path.join(self.outdir, self.imagedir))
- for src in status_iterator(self.env.images, __('copying images... '), "brown",
- len(self.env.images), self.app.verbosity,
+ for src in status_iterator(self.images, __('copying images... '), "brown",
+ len(self.images), self.app.verbosity,
stringify_func=stringify_func):
- if src in converted_images:
- continue
- _docnames, dest = self.env.images[src]
+ dest = self.images[src]
try:
copyfile(path.join(self.srcdir, src),
path.join(self.outdir, self.imagedir, dest))
diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py
index 0a9de19e54c..edc314dc93f 100644
--- a/sphinx/builders/latex/__init__.py
+++ b/sphinx/builders/latex/__init__.py
@@ -413,15 +413,12 @@ def copy_latex_additional_files(self) -> None:
copy_asset_file(path.join(self.confdir, filename), self.outdir)
def copy_image_files(self) -> None:
- if self.env.images:
- converted_images = {*self.env.original_image_uri.values()}
+ if self.images:
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
- for src in status_iterator(self.env.images, __('copying images... '), "brown",
- len(self.env.images), self.app.verbosity,
+ for src in status_iterator(self.images, __('copying images... '), "brown",
+ len(self.images), self.app.verbosity,
stringify_func=stringify_func):
- if src in converted_images:
- continue
- _docnames, dest = self.env.images[src]
+ dest = self.images[src]
try:
copy_asset_file(path.join(self.srcdir, src),
path.join(self.outdir, dest))
diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py
index 8b750df2d6b..b7baa719d3f 100644
--- a/sphinx/builders/linkcheck.py
+++ b/sphinx/builders/linkcheck.py
@@ -509,7 +509,10 @@ def add_uri(uri: str, node: nodes.Element) -> None:
if newuri:
uri = newuri
- lineno = get_node_line(node)
+ try:
+ lineno = get_node_line(node)
+ except ValueError:
+ lineno = None
uri_info = Hyperlink(uri, self.env.docname, lineno)
if uri not in hyperlinks:
hyperlinks[uri] = uri_info
diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py
index 19aeaa5ea8e..d2ae72ef7b6 100644
--- a/sphinx/builders/texinfo.py
+++ b/sphinx/builders/texinfo.py
@@ -173,15 +173,12 @@ def finish(self) -> None:
self.copy_support_files()
def copy_image_files(self, targetname: str) -> None:
- if self.env.images:
- converted_images = {*self.env.original_image_uri.values()}
+ if self.images:
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
- for src in status_iterator(self.env.images, __('copying images... '), "brown",
- len(self.env.images), self.app.verbosity,
+ for src in status_iterator(self.images, __('copying images... '), "brown",
+ len(self.images), self.app.verbosity,
stringify_func=stringify_func):
- if src in converted_images:
- continue
- _docnames, dest = self.env.images[src]
+ dest = self.images[src]
try:
imagedir = path.join(self.outdir, targetname + '-figures')
ensuredir(imagedir)
diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py
index 18dd94f4616..9599dbc236c 100644
--- a/sphinx/util/nodes.py
+++ b/sphinx/util/nodes.py
@@ -172,7 +172,10 @@ def apply_source_workaround(node: Element) -> None:
))):
logger.debug('[i18n] PATCH: %r to have source and line: %s',
get_full_module_name(node), repr_domxml(node))
- node.source = get_node_source(node) or ''
+ try:
+ node.source = get_node_source(node)
+ except ValueError:
+ node.source = ''
node.line = 0 # need fix docutils to get `node.line`
return
@@ -561,8 +564,9 @@ def set_role_source_info(inliner: Inliner, lineno: int, node: Node) -> None:
def copy_source_info(src: Element, dst: Element) -> None:
- dst.source = get_node_source(src)
- dst.line = get_node_line(src)
+ with contextlib.suppress(ValueError):
+ dst.source = get_node_source(src)
+ dst.line = get_node_line(src)
NON_SMARTQUOTABLE_PARENT_NODES = (
@@ -608,3 +612,18 @@ def process_only_nodes(document: Node, tags: Tags) -> None:
# the only node, so we make sure docutils can transfer the id to
# something, even if it's just a comment and will lose the id anyway...
node.replace_self(nodes.comment())
+
+
+def _copy_except__document(self: Element) -> Element:
+ """Monkey-patch ```nodes.Element.copy``` to not copy the ``_document``
+ attribute.
+
+ xref: https://github.com/sphinx-doc/sphinx/issues/11116#issuecomment-1376767086
+ """
+ newnode = self.__class__(rawsource=self.rawsource, **self.attributes)
+ newnode.source = self.source
+ newnode.line = self.line
+ return newnode
+
+
+nodes.Element.copy = _copy_except__document # type: ignore
diff --git a/sphinx/writers/_html4.py b/sphinx/writers/_html4.py
index 3d36784cec7..7aec4c892ad 100644
--- a/sphinx/writers/_html4.py
+++ b/sphinx/writers/_html4.py
@@ -287,14 +287,14 @@ def append_fignumber(figtype: str, figure_id: str) -> None:
else:
key = figtype
- if figure_id in self.builder.fignumbers.get(key, {}): # type: ignore[has-type]
+ if figure_id in self.builder.fignumbers.get(key, {}):
self.body.append('')
prefix = self.config.numfig_format.get(figtype)
if prefix is None:
msg = __('numfig_format is not defined for %s') % figtype
logger.warning(msg)
else:
- numbers = self.builder.fignumbers[key][figure_id] # type: ignore[has-type]
+ numbers = self.builder.fignumbers[key][figure_id]
self.body.append(prefix % '.'.join(map(str, numbers)) + ' ')
self.body.append('')
@@ -569,7 +569,7 @@ def visit_download_reference(self, node: Element) -> None:
self.context.append('')
elif 'filename' in node:
atts['class'] += ' internal'
- atts['href'] = posixpath.join(self.builder.dlpath, # type: ignore[has-type]
+ atts['href'] = posixpath.join(self.builder.dlpath,
urllib.parse.quote(node['filename']))
self.body.append(self.starttag(node, 'a', '', **atts))
self.context.append('')
diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py
index 7a62161b54e..edf8bdc237f 100644
--- a/sphinx/writers/html5.py
+++ b/sphinx/writers/html5.py
@@ -293,14 +293,14 @@ def append_fignumber(figtype: str, figure_id: str) -> None:
else:
key = figtype
- if figure_id in self.builder.fignumbers.get(key, {}): # type: ignore[has-type]
+ if figure_id in self.builder.fignumbers.get(key, {}):
self.body.append('')
prefix = self.config.numfig_format.get(figtype)
if prefix is None:
msg = __('numfig_format is not defined for %s') % figtype
logger.warning(msg)
else:
- numbers = self.builder.fignumbers[key][figure_id] # type: ignore[has-type]
+ numbers = self.builder.fignumbers[key][figure_id]
self.body.append(prefix % '.'.join(map(str, numbers)) + ' ')
self.body.append('')
@@ -544,7 +544,7 @@ def visit_download_reference(self, node: Element) -> None:
self.context.append('')
elif 'filename' in node:
atts['class'] += ' internal'
- atts['href'] = posixpath.join(self.builder.dlpath, # type: ignore[has-type]
+ atts['href'] = posixpath.join(self.builder.dlpath,
urllib.parse.quote(node['filename']))
self.body.append(self.starttag(node, 'a', '', **atts))
self.context.append('')
diff --git a/tests/test_build_epub.py b/tests/test_build_epub.py
index 86fdae0cd68..e183c9c17e1 100644
--- a/tests/test_build_epub.py
+++ b/tests/test_build_epub.py
@@ -399,14 +399,11 @@ def test_copy_images(app, status, warning):
images_dir = Path(app.outdir) / '_images'
images = {image.name for image in images_dir.rglob('*')}
+ images.discard('python-logo.png')
assert images == {
- 'img.gif',
- 'img.pdf',
'img.png',
- 'python-logo.png',
'rimg.png',
'rimg1.png',
- 'svgimg.pdf',
'svgimg.svg',
'testimäge.png',
}
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index 89350e82d0c..5a0ca59feda 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -1780,12 +1780,9 @@ def test_copy_images(app, status, warning):
images_dir = Path(app.outdir) / '_images'
images = {image.name for image in images_dir.rglob('*')}
assert images == {
- 'img.gif',
- 'img.pdf',
'img.png',
'rimg.png',
'rimg1.png',
- 'svgimg.pdf',
'svgimg.svg',
'testimäge.png',
}
diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py
index 1090dbfecfb..0a56282b46b 100644
--- a/tests/test_build_latex.py
+++ b/tests/test_build_latex.py
@@ -1685,14 +1685,9 @@ def test_copy_images(app, status, warning):
image.name for image in test_dir.rglob('*')
if image.suffix in {'.gif', '.pdf', '.png', '.svg'}
}
+ images.discard('python-logo.png')
assert images == {
- 'img.gif',
'img.pdf',
- 'img.png',
- 'python-logo.png',
'rimg.png',
- 'rimg1.png',
- 'svgimg.pdf',
- 'svgimg.svg',
'testimäge.png',
}
diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py
index aae5689b709..fa23fdb5920 100644
--- a/tests/test_build_texinfo.py
+++ b/tests/test_build_texinfo.py
@@ -146,14 +146,9 @@ def test_copy_images(app, status, warning):
images_dir = Path(app.outdir) / 'python-figures'
images = {image.name for image in images_dir.rglob('*')}
+ images.discard('python-logo.png')
assert images == {
- 'img.gif',
- 'img.pdf',
'img.png',
- 'python-logo.png',
'rimg.png',
- 'rimg1.png',
- 'svgimg.pdf',
- 'svgimg.svg',
'testimäge.png',
}