mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Verify that an asset file to be copied exists (#12183)
This commit is contained in:
@@ -131,6 +131,9 @@ Bugs fixed
|
||||
may be used,
|
||||
when multiple suffixes are specified in :confval:`source_suffix`.
|
||||
Patch by Sutou Kouhei.
|
||||
* #10786: improve the error message when a file to be copied (e.g., an asset)
|
||||
is removed during Sphinx execution.
|
||||
Patch by Bénédikt Tran.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
@@ -11,13 +11,14 @@ import sys
|
||||
import unicodedata
|
||||
from io import StringIO
|
||||
from os import path
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sphinx.deprecation import _deprecation_warning
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator
|
||||
from types import TracebackType
|
||||
from typing import Any
|
||||
|
||||
# SEP separates path elements in the canonical file names
|
||||
#
|
||||
@@ -89,8 +90,16 @@ def copytimes(source: str | os.PathLike[str], dest: str | os.PathLike[str]) -> N
|
||||
def copyfile(source: str | os.PathLike[str], dest: str | os.PathLike[str]) -> None:
|
||||
"""Copy a file and its modification times, if possible.
|
||||
|
||||
Note: ``copyfile`` skips copying if the file has not been changed
|
||||
:param source: An existing source to copy.
|
||||
:param dest: The destination path.
|
||||
:raise FileNotFoundError: The *source* does not exist.
|
||||
|
||||
.. note:: :func:`copyfile` is a no-op if *source* and *dest* are identical.
|
||||
"""
|
||||
if not path.exists(source):
|
||||
msg = f'{os.fsdecode(source)} does not exist'
|
||||
raise FileNotFoundError(msg)
|
||||
|
||||
if not path.exists(dest) or not filecmp.cmp(source, dest):
|
||||
shutil.copyfile(source, dest)
|
||||
with contextlib.suppress(OSError):
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Test the HTML builder and check output against XPath."""
|
||||
|
||||
import os
|
||||
import posixpath
|
||||
import re
|
||||
|
||||
@@ -8,6 +9,7 @@ import pytest
|
||||
from sphinx.builders.html import validate_html_extra_path, validate_html_static_path
|
||||
from sphinx.deprecation import RemovedInSphinx80Warning
|
||||
from sphinx.errors import ConfigError
|
||||
from sphinx.util.console import strip_colors
|
||||
from sphinx.util.inventory import InventoryFile
|
||||
|
||||
FIGURE_CAPTION = ".//figure/figcaption/p"
|
||||
@@ -387,3 +389,25 @@ def test_html_signaturereturn_icon(app):
|
||||
content = (app.outdir / 'index.html').read_text(encoding='utf8')
|
||||
|
||||
assert ('<span class="sig-return-icon">→</span>' in content)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='root', srcdir=os.urandom(4).hex())
|
||||
def test_html_remove_sources_before_write_gh_issue_10786(app, warning):
|
||||
# see: https://github.com/sphinx-doc/sphinx/issues/10786
|
||||
target = app.srcdir / 'img.png'
|
||||
|
||||
def handler(app):
|
||||
assert target.exists()
|
||||
target.unlink()
|
||||
return []
|
||||
|
||||
app.connect('html-collect-pages', handler)
|
||||
assert target.exists()
|
||||
app.build()
|
||||
assert not target.exists()
|
||||
|
||||
ws = strip_colors(warning.getvalue()).splitlines()
|
||||
assert len(ws) >= 1
|
||||
|
||||
file = os.fsdecode(target)
|
||||
assert f'WARNING: cannot copy image file {file!r}: {file!s} does not exist' == ws[-1]
|
||||
|
||||
Reference in New Issue
Block a user