From 5008291b3d2ab92309f1dbc087b0c0b1c7f4e29f Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sat, 7 Jan 2023 15:08:04 +0000
Subject: [PATCH 1/5] Ignore more checks in Ruff 0.0.213
---
pyproject.toml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/pyproject.toml b/pyproject.toml
index fa3b3bb95..5884b7fe3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -162,9 +162,12 @@ ignore = [
# flake8-bandit
"S101", # assert used
"S105", # possible hardcoded password
+ "S113", # probable use of requests call without timeout
+ "S324", # probable use of insecure hash functions
# flake8-simplify
"SIM102", # nested 'if' statements
"SIM105", # use contextlib.suppress
+ "SIM108", # use ternary operator
"SIM117", # use single 'with' statement
]
external = [ # Whitelist for RUF100 unkown code warnings
From a1cd19e601f89e1796d1992cbeaf6b476e2be6a0 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Sat, 7 Jan 2023 17:35:21 +0000
Subject: [PATCH 2/5] Fix copying images under parallel execution (#11100)
---
sphinx/builders/_epub_base.py | 11 +++++++----
sphinx/builders/html/__init__.py | 11 +++++++----
sphinx/builders/latex/__init__.py | 11 +++++++----
sphinx/builders/texinfo.py | 11 +++++++----
tests/test_build_epub.py | 20 ++++++++++++++++++++
tests/test_build_html.py | 19 +++++++++++++++++++
tests/test_build_latex.py | 23 +++++++++++++++++++++++
tests/test_build_texinfo.py | 20 ++++++++++++++++++++
8 files changed, 110 insertions(+), 16 deletions(-)
diff --git a/sphinx/builders/_epub_base.py b/sphinx/builders/_epub_base.py
index ef857e9d3..7174914bb 100644
--- a/sphinx/builders/_epub_base.py
+++ b/sphinx/builders/_epub_base.py
@@ -401,9 +401,12 @@ class EpubBuilder(StandaloneHTMLBuilder):
the format and resizing the image if necessary/possible.
"""
ensuredir(path.join(self.outdir, self.imagedir))
- for src in status_iterator(self.images, __('copying images... '), "brown",
- len(self.images), self.app.verbosity):
- dest = self.images[src]
+ 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]
try:
img = Image.open(path.join(self.srcdir, src))
except OSError:
@@ -438,7 +441,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
"""Copy image files to destination directory.
This overwritten method can use Pillow to convert image files.
"""
- if self.images:
+ if self.env.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 0fb64decd..063d19471 100644
--- a/sphinx/builders/html/__init__.py
+++ b/sphinx/builders/html/__init__.py
@@ -764,13 +764,16 @@ class StandaloneHTMLBuilder(Builder):
self.handle_page(indexname, indexcontext, 'domainindex.html')
def copy_image_files(self) -> None:
- if self.images:
+ if self.env.images:
+ converted_images = {*self.env.original_image_uri.values()}
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
ensuredir(path.join(self.outdir, self.imagedir))
- for src in status_iterator(self.images, __('copying images... '), "brown",
- len(self.images), self.app.verbosity,
+ for src in status_iterator(self.env.images, __('copying images... '), "brown",
+ len(self.env.images), self.app.verbosity,
stringify_func=stringify_func):
- dest = self.images[src]
+ if src in converted_images:
+ continue
+ _docnames, dest = self.env.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 edc314dc9..0a9de19e5 100644
--- a/sphinx/builders/latex/__init__.py
+++ b/sphinx/builders/latex/__init__.py
@@ -413,12 +413,15 @@ class LaTeXBuilder(Builder):
copy_asset_file(path.join(self.confdir, filename), self.outdir)
def copy_image_files(self) -> None:
- if self.images:
+ if self.env.images:
+ converted_images = {*self.env.original_image_uri.values()}
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
- for src in status_iterator(self.images, __('copying images... '), "brown",
- len(self.images), self.app.verbosity,
+ for src in status_iterator(self.env.images, __('copying images... '), "brown",
+ len(self.env.images), self.app.verbosity,
stringify_func=stringify_func):
- dest = self.images[src]
+ if src in converted_images:
+ continue
+ _docnames, dest = self.env.images[src]
try:
copy_asset_file(path.join(self.srcdir, src),
path.join(self.outdir, dest))
diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py
index d2ae72ef7..19aeaa5ea 100644
--- a/sphinx/builders/texinfo.py
+++ b/sphinx/builders/texinfo.py
@@ -173,12 +173,15 @@ class TexinfoBuilder(Builder):
self.copy_support_files()
def copy_image_files(self, targetname: str) -> None:
- if self.images:
+ if self.env.images:
+ converted_images = {*self.env.original_image_uri.values()}
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
- for src in status_iterator(self.images, __('copying images... '), "brown",
- len(self.images), self.app.verbosity,
+ for src in status_iterator(self.env.images, __('copying images... '), "brown",
+ len(self.env.images), self.app.verbosity,
stringify_func=stringify_func):
- dest = self.images[src]
+ if src in converted_images:
+ continue
+ _docnames, dest = self.env.images[src]
try:
imagedir = path.join(self.outdir, targetname + '-figures')
ensuredir(imagedir)
diff --git a/tests/test_build_epub.py b/tests/test_build_epub.py
index a50c51e25..86fdae0cd 100644
--- a/tests/test_build_epub.py
+++ b/tests/test_build_epub.py
@@ -2,6 +2,7 @@
import os
import subprocess
+from pathlib import Path
from subprocess import CalledProcessError
from xml.etree import ElementTree
@@ -390,3 +391,22 @@ def test_xml_name_pattern_check():
assert _XML_NAME_PATTERN.match('id-pub')
assert _XML_NAME_PATTERN.match('webpage')
assert not _XML_NAME_PATTERN.match('1bfda21')
+
+
+@pytest.mark.sphinx('epub', testroot='images')
+def test_copy_images(app, status, warning):
+ app.build()
+
+ images_dir = Path(app.outdir) / '_images'
+ images = {image.name for image in images_dir.rglob('*')}
+ 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 5eed5d5ea..89350e82d 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -3,6 +3,7 @@
import os
import re
from itertools import chain, cycle
+from pathlib import Path
from unittest.mock import ANY, call, patch
import pytest
@@ -1770,3 +1771,21 @@ def test_theme_having_multiple_stylesheets(app):
assert '' in content
assert '' in content
+
+
+@pytest.mark.sphinx('html', testroot='images')
+def test_copy_images(app, status, warning):
+ app.build()
+
+ 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 f20fc67c5..3f1206ac8 100644
--- a/tests/test_build_latex.py
+++ b/tests/test_build_latex.py
@@ -4,6 +4,7 @@ import os
import re
import subprocess
from itertools import product
+from pathlib import Path
from shutil import copyfile
from subprocess import CalledProcessError
@@ -1670,3 +1671,25 @@ def test_latex_code_role(app):
common_content + '%\n}} code block') in content
assert (r'\begin{sphinxVerbatim}[commandchars=\\\{\}]' +
'\n' + common_content + '\n' + r'\end{sphinxVerbatim}') in content
+
+
+@pytest.mark.sphinx('latex', testroot='images')
+def test_copy_images(app, status, warning):
+ app.build()
+
+ test_dir = Path(app.outdir)
+ images = {
+ image.name for image in test_dir.rglob('*')
+ if image.suffix in {'.gif', '.pdf', '.png', '.svg'}
+ }
+ 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 974cb1965..aae5689b7 100644
--- a/tests/test_build_texinfo.py
+++ b/tests/test_build_texinfo.py
@@ -3,6 +3,7 @@
import os
import re
import subprocess
+from pathlib import Path
from subprocess import CalledProcessError
from unittest.mock import Mock
@@ -137,3 +138,22 @@ def test_texinfo_samp_with_variable(app, status, warning):
assert '@code{@var{variable_only}}' in output
assert '@code{@var{variable} and text}' in output
assert '@code{Show @var{variable} in the middle}' in output
+
+
+@pytest.mark.sphinx('texinfo', testroot='images')
+def test_copy_images(app, status, warning):
+ app.build()
+
+ images_dir = Path(app.outdir) / 'python-figures'
+ images = {image.name for image in images_dir.rglob('*')}
+ assert images == {
+ 'img.gif',
+ 'img.pdf',
+ 'img.png',
+ 'python-logo.png',
+ 'rimg.png',
+ 'rimg1.png',
+ 'svgimg.pdf',
+ 'svgimg.svg',
+ 'testimäge.png',
+ }
From d8a5dd8364d19f693d5f017f615a8037784a0295 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sat, 7 Jan 2023 17:37:41 +0000
Subject: [PATCH 3/5] Add note to CHANGES for PR 11100
---
CHANGES | 1 +
1 file changed, 1 insertion(+)
diff --git a/CHANGES b/CHANGES
index 51147663b..40ad5db9a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -14,6 +14,7 @@ Bugs fixed
margin since Sphinx 5.1.0
.. _contents: https://docutils.sourceforge.io/docs/ref/rst/directives.html#table-of-contents
+* #11100: Fix copying images when running under parallel mode.
Release 6.1.1 (released Jan 05, 2023)
=====================================
From 393b40825282311a8ba81c830ef3c6fae9335c32 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sat, 7 Jan 2023 17:38:13 +0000
Subject: [PATCH 4/5] Bump to 6.1.2 final
---
CHANGES | 4 ++--
sphinx/__init__.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/CHANGES b/CHANGES
index 40ad5db9a..da4573de9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,5 @@
-Release 6.1.2 (in development)
-==============================
+Release 6.1.2 (released Jan 07, 2023)
+=====================================
Bugs fixed
----------
diff --git a/sphinx/__init__.py b/sphinx/__init__.py
index 410845f09..eeef30345 100644
--- a/sphinx/__init__.py
+++ b/sphinx/__init__.py
@@ -19,7 +19,7 @@ warnings.filterwarnings('ignore', "'U' mode is deprecated",
warnings.filterwarnings('ignore', 'The frontend.Option class .*',
DeprecationWarning, module='docutils.frontend')
-__version__ = '6.1.1'
+__version__ = '6.1.2'
__display_version__ = __version__ # used for command line version
#: Version info for better programmatic use.
@@ -30,7 +30,7 @@ __display_version__ = __version__ # used for command line version
#:
#: .. versionadded:: 1.2
#: Before version 1.2, check the string ``sphinx.__version__``.
-version_info = (6, 1, 1, 'final', 0)
+version_info = (6, 1, 2, 'final', 0)
package_dir = path.abspath(path.dirname(__file__))
From ddbc5b57f467823d600341ed1cfe5bedde5d7b64 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sat, 7 Jan 2023 17:45:46 +0000
Subject: [PATCH 5/5] Bump version
---
CHANGES | 21 +++++++++++++++++++++
sphinx/__init__.py | 6 +++---
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/CHANGES b/CHANGES
index da4573de9..222eea8d8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,24 @@
+Release 6.1.3 (in development)
+==============================
+
+Dependencies
+------------
+
+Incompatible changes
+--------------------
+
+Deprecated
+----------
+
+Features added
+--------------
+
+Bugs fixed
+----------
+
+Testing
+--------
+
Release 6.1.2 (released Jan 07, 2023)
=====================================
diff --git a/sphinx/__init__.py b/sphinx/__init__.py
index eeef30345..5c3e705e2 100644
--- a/sphinx/__init__.py
+++ b/sphinx/__init__.py
@@ -19,7 +19,7 @@ warnings.filterwarnings('ignore', "'U' mode is deprecated",
warnings.filterwarnings('ignore', 'The frontend.Option class .*',
DeprecationWarning, module='docutils.frontend')
-__version__ = '6.1.2'
+__version__ = '6.1.3'
__display_version__ = __version__ # used for command line version
#: Version info for better programmatic use.
@@ -30,11 +30,11 @@ __display_version__ = __version__ # used for command line version
#:
#: .. versionadded:: 1.2
#: Before version 1.2, check the string ``sphinx.__version__``.
-version_info = (6, 1, 2, 'final', 0)
+version_info = (6, 1, 3, 'beta', 0)
package_dir = path.abspath(path.dirname(__file__))
-_in_development = False
+_in_development = True
if _in_development:
# Only import subprocess if needed
import subprocess