Files
sphinx/tests/test_util/test_util_fileutil.py
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

171 lines
6.1 KiB
Python
Raw Normal View History

2016-06-26 22:22:25 +09:00
"""Tests sphinx.util.fileutil functions."""
from __future__ import annotations
import re
2025-02-07 13:51:42 +00:00
from pathlib import Path
from typing import TYPE_CHECKING
from unittest import mock
2016-06-26 22:22:25 +09:00
import pytest
from sphinx._cli.util.errors import strip_escape_sequences
2018-02-19 22:39:14 +09:00
from sphinx.jinja2glue import BuiltinTemplateLoader
from sphinx.util.fileutil import _template_basename, copy_asset, copy_asset_file
from sphinx.util.template import BaseRenderer
2018-02-19 22:39:14 +09:00
if TYPE_CHECKING:
from sphinx.testing.util import SphinxTestApp
2016-06-26 22:22:25 +09:00
class DummyTemplateLoader(BuiltinTemplateLoader, BaseRenderer):
2024-10-03 20:17:40 +01:00
def __init__(self) -> None:
2018-12-15 08:25:47 -08:00
super().__init__()
builder = mock.Mock()
2016-06-26 22:22:25 +09:00
builder.config.templates_path = []
2025-02-16 04:25:08 +00:00
builder._translator = None
2016-06-26 22:22:25 +09:00
self.init(builder)
def test_copy_asset_file(tmp_path: Path) -> None:
2016-06-26 22:22:25 +09:00
renderer = DummyTemplateLoader()
# copy normal file
2024-08-11 14:58:56 +01:00
src = tmp_path / 'asset.txt'
2023-08-10 20:48:04 +01:00
src.write_text('# test data', encoding='utf8')
2024-08-11 14:58:56 +01:00
dest = tmp_path / 'output.txt'
2016-06-26 22:22:25 +09:00
copy_asset_file(src, dest)
assert dest.exists()
2022-04-27 03:04:19 +01:00
assert src.read_text(encoding='utf8') == dest.read_text(encoding='utf8')
2016-06-26 22:22:25 +09:00
# copy template file
2024-08-11 14:58:56 +01:00
src = tmp_path / 'asset.txt.jinja'
2023-08-10 20:48:04 +01:00
src.write_text('# {{var1}} data', encoding='utf8')
2024-08-11 14:58:56 +01:00
dest = tmp_path / 'output.txt.jinja'
2016-06-26 22:22:25 +09:00
copy_asset_file(str(src), str(dest), {'var1': 'template'}, renderer)
2016-06-26 22:22:25 +09:00
assert not dest.exists()
assert (tmp_path / 'output.txt').exists()
assert (tmp_path / 'output.txt').read_text(encoding='utf8') == '# template data'
2016-06-26 22:22:25 +09:00
# copy template file to subdir
2024-08-11 14:58:56 +01:00
src = tmp_path / 'asset.txt.jinja'
2023-08-10 20:48:04 +01:00
src.write_text('# {{var1}} data', encoding='utf8')
2024-08-11 14:58:56 +01:00
subdir1 = tmp_path / 'subdir'
subdir1.mkdir(parents=True, exist_ok=True)
2016-06-26 22:22:25 +09:00
copy_asset_file(src, subdir1, context={'var1': 'template'}, renderer=renderer)
assert (subdir1 / 'asset.txt').exists()
2022-04-27 03:04:19 +01:00
assert (subdir1 / 'asset.txt').read_text(encoding='utf8') == '# template data'
# copy template file without context
2024-08-11 14:58:56 +01:00
src = tmp_path / 'asset.txt.jinja'
subdir2 = tmp_path / 'subdir2'
subdir2.mkdir(parents=True, exist_ok=True)
copy_asset_file(src, subdir2)
assert not (subdir2 / 'asset.txt').exists()
assert (subdir2 / 'asset.txt.jinja').exists()
assert (subdir2 / 'asset.txt.jinja').read_text(encoding='utf8') == '# {{var1}} data'
2016-06-27 11:54:42 +09:00
def test_copy_asset(tmp_path: Path) -> None:
2016-06-27 11:54:42 +09:00
renderer = DummyTemplateLoader()
# prepare source files
2024-08-11 14:58:56 +01:00
source = tmp_path / 'source'
source.mkdir(parents=True, exist_ok=True)
(source / 'index.rst').write_text('index.rst', encoding='utf8')
(source / 'foo.rst.jinja').write_text('{{var1}}.rst', encoding='utf8')
(source / '_static').mkdir(parents=True, exist_ok=True)
(source / '_static' / 'basic.css').write_text('basic.css', encoding='utf8')
(source / '_templates').mkdir(parents=True, exist_ok=True)
(source / '_templates' / 'layout.html').write_text('layout.html', encoding='utf8')
2024-08-11 14:58:56 +01:00
(source / '_templates' / 'sidebar.html.jinja').write_text(
'sidebar: {{var2}}', encoding='utf8'
)
2025-02-21 23:19:10 +00:00
sibling = tmp_path / 'sibling'
sibling.mkdir(parents=True, exist_ok=True)
sibling.joinpath('spam').mkdir(parents=True, exist_ok=True)
sibling.joinpath('spam', 'ham').touch()
2016-06-27 11:54:42 +09:00
# copy a single file
assert not (tmp_path / 'test1').exists()
copy_asset(source / 'index.rst', tmp_path / 'test1')
assert (tmp_path / 'test1').exists()
assert (tmp_path / 'test1/index.rst').exists()
2016-06-27 11:54:42 +09:00
# copy directories
destdir = tmp_path / 'test2'
2024-08-11 14:58:56 +01:00
copy_asset(
source,
destdir,
context={'var1': 'bar', 'var2': 'baz'},
renderer=renderer,
)
2016-06-27 11:54:42 +09:00
assert (destdir / 'index.rst').exists()
assert (destdir / 'foo.rst').exists()
2022-04-27 03:04:19 +01:00
assert (destdir / 'foo.rst').read_text(encoding='utf8') == 'bar.rst'
2016-06-27 11:54:42 +09:00
assert (destdir / '_static' / 'basic.css').exists()
assert (destdir / '_templates' / 'layout.html').exists()
assert (destdir / '_templates' / 'sidebar.html').exists()
2024-08-11 14:58:56 +01:00
sidebar = (destdir / '_templates' / 'sidebar.html').read_text(encoding='utf8')
assert sidebar == 'sidebar: baz'
2016-06-27 11:54:42 +09:00
# copy with exclusion
def excluded(path: str) -> bool:
2024-08-11 14:58:56 +01:00
return 'sidebar.html' in path or 'basic.css' in path
2016-06-27 11:54:42 +09:00
destdir = tmp_path / 'test3'
2024-08-11 14:58:56 +01:00
copy_asset(
source,
destdir,
excluded,
context={'var1': 'bar', 'var2': 'baz'},
renderer=renderer,
)
2016-06-27 11:54:42 +09:00
assert (destdir / 'index.rst').exists()
assert (destdir / 'foo.rst').exists()
assert not (destdir / '_static' / 'basic.css').exists()
assert (destdir / '_templates' / 'layout.html').exists()
assert not (destdir / '_templates' / 'sidebar.html').exists()
2025-02-21 23:19:10 +00:00
# copy sibling
assert not (tmp_path / 'test4').exists()
copy_asset(source / '../sibling', tmp_path / 'test4')
assert (tmp_path / 'test4').is_dir()
assert (tmp_path / 'test4' / 'spam').is_dir()
assert (tmp_path / 'test4' / 'spam' / 'ham').is_file()
assert (tmp_path / 'test4' / 'spam' / 'ham').read_bytes() == b''
@pytest.mark.sphinx('html', testroot='html_assets')
def test_copy_asset_template(app: SphinxTestApp) -> None:
app.build(force_all=True)
2024-08-11 16:58:19 +01:00
expected_msg = r'^Writing evaluated template result to [^\n]*\bAPI.html$'
output = strip_escape_sequences(app.status.getvalue())
2024-08-11 16:58:19 +01:00
assert re.findall(expected_msg, output, flags=re.MULTILINE)
@pytest.mark.sphinx('html', testroot='util-copyasset_overwrite')
def test_copy_asset_overwrite(app: SphinxTestApp) -> None:
app.build()
src = app.srcdir / 'myext_static' / 'custom-styles.css'
dst = app.outdir / '_static' / 'custom-styles.css'
assert strip_escape_sequences(app.warning.getvalue()) == (
f'WARNING: Aborted attempted copy from {src} to {dst} '
'(the destination path has existing data). '
'[misc.copy_overwrite]\n'
)
def test_template_basename() -> None:
2025-02-07 13:51:42 +00:00
assert _template_basename(Path('asset.txt')) is None
assert _template_basename(Path('asset.txt.jinja')) == Path('asset.txt')
assert _template_basename(Path('sidebar.html.jinja')) == Path('sidebar.html')
def test_legacy_template_basename() -> None:
2025-02-07 13:51:42 +00:00
assert _template_basename(Path('asset.txt_t')) == Path('asset.txt')