From 49d830467098cc149390bc8349c19b7501e0920f Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Fri, 28 Jul 2023 00:39:12 +0100
Subject: [PATCH] Start using ``pathlib.Path`` and deprecate
``sphinx.testing.path`` (#11526)
---
CHANGES | 5 +
doc/extdev/deprecated.rst | 5 +
sphinx/application.py | 14 +-
sphinx/builders/__init__.py | 2 +-
sphinx/builders/_epub_base.py | 7 +-
sphinx/builders/changes.py | 2 +-
sphinx/builders/gettext.py | 6 +-
sphinx/builders/html/__init__.py | 10 +-
sphinx/cmd/build.py | 4 +-
sphinx/config.py | 6 +-
sphinx/directives/code.py | 2 +-
sphinx/environment/__init__.py | 7 +-
sphinx/ext/autosummary/generate.py | 6 +-
sphinx/ext/imgmath.py | 7 +-
sphinx/project.py | 8 +-
sphinx/testing/comparer.py | 97 ------------
sphinx/testing/fixtures.py | 25 +--
sphinx/testing/path.py | 7 +
sphinx/testing/util.py | 22 +--
sphinx/util/fileutil.py | 11 +-
sphinx/util/i18n.py | 2 +-
sphinx/util/matching.py | 2 +-
sphinx/util/osutil.py | 40 ++---
sphinx/util/template.py | 28 ++--
tests/conftest.py | 32 +---
tests/test_application.py | 5 +-
tests/test_build.py | 12 +-
tests/test_build_gettext.py | 16 +-
tests/test_build_html.py | 24 +--
tests/test_build_latex.py | 8 +-
tests/test_build_texinfo.py | 2 +-
tests/test_catalogs.py | 39 ++---
tests/test_config.py | 58 +++----
tests/test_directive_code.py | 4 +-
tests/test_domain_c.py | 6 +-
tests/test_domain_cpp.py | 6 +-
tests/test_environment.py | 22 +--
tests/test_ext_apidoc.py | 218 +++++++++++++-------------
tests/test_ext_autosummary.py | 13 +-
tests/test_ext_inheritance_diagram.py | 2 +-
tests/test_ext_intersphinx.py | 74 ++++-----
tests/test_intl.py | 33 ++--
tests/test_project.py | 12 +-
tests/test_pycode.py | 2 +-
tests/test_quickstart.py | 72 ++++-----
tests/test_theming.py | 6 +-
tests/test_util.py | 4 -
tests/test_util_fileutil.py | 50 +++---
tests/test_util_i18n.py | 58 +++----
tests/test_util_inventory.py | 14 +-
tests/test_versioning.py | 3 +-
51 files changed, 490 insertions(+), 630 deletions(-)
delete mode 100644 sphinx/testing/comparer.py
diff --git a/CHANGES b/CHANGES
index 023bb734403..e74ec0e63e9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -14,10 +14,15 @@ Deprecated
* #11512: Deprecate ``sphinx.util.md5`` and ``sphinx.util.sha1``.
Use ``hashlib`` instead.
+* #11526: Deprecate ``sphinx.testing.path``.
+ Use ``os.path`` or ``pathlib`` instead.
Features added
--------------
+* #11526: Support ``os.PathLike`` types and ``pathlib.Path`` objects
+ in many more places.
+
Bugs fixed
----------
diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst
index 1c73a478178..71bfad02e4d 100644
--- a/doc/extdev/deprecated.rst
+++ b/doc/extdev/deprecated.rst
@@ -22,6 +22,11 @@ The following is a list of deprecated interfaces.
- Removed
- Alternatives
+ * - ``sphinx.testing.path``
+ - 7.2
+ - 9.0
+ - ``os.path`` or ``pathlib``
+
* - ``sphinx.util.md5``
- 7.2
- 9.0
diff --git a/sphinx/application.py b/sphinx/application.py
index a3711ce59ef..44432f8a6e7 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -11,6 +11,7 @@
from collections import deque
from io import StringIO
from os import path
+from pathlib import Path
from typing import IO, TYPE_CHECKING, Any, Callable
from docutils import nodes
@@ -41,7 +42,7 @@
from sphinx.util.display import progress_message
from sphinx.util.i18n import CatalogRepository
from sphinx.util.logging import prefixed_warnings
-from sphinx.util.osutil import abspath, ensuredir, relpath
+from sphinx.util.osutil import ensuredir, relpath
from sphinx.util.tags import Tags
from sphinx.util.typing import RoleFunction, TitleGetter
@@ -132,7 +133,8 @@ class Sphinx:
warningiserror: bool
_warncount: int
- def __init__(self, srcdir: str, confdir: str | None, outdir: str, doctreedir: str,
+ def __init__(self, srcdir: str | os.PathLike[str], confdir: str | os.PathLike[str] | None,
+ outdir: str | os.PathLike[str], doctreedir: str | os.PathLike[str],
buildername: str, confoverrides: dict | None = None,
status: IO | None = sys.stdout, warning: IO | None = sys.stderr,
freshenv: bool = False, warningiserror: bool = False,
@@ -145,9 +147,9 @@ def __init__(self, srcdir: str, confdir: str | None, outdir: str, doctreedir: st
self.registry = SphinxComponentRegistry()
# validate provided directories
- self.srcdir = abspath(srcdir)
- self.outdir = abspath(outdir)
- self.doctreedir = abspath(doctreedir)
+ self.srcdir = Path(srcdir).resolve()
+ self.outdir = Path(outdir).resolve()
+ self.doctreedir = Path(doctreedir).resolve()
if not path.isdir(self.srcdir):
raise ApplicationError(__('Cannot find source directory (%s)') %
@@ -203,7 +205,7 @@ def __init__(self, srcdir: str, confdir: str | None, outdir: str, doctreedir: st
self.confdir = self.srcdir
self.config = Config({}, confoverrides or {})
else:
- self.confdir = abspath(confdir)
+ self.confdir = Path(confdir).resolve()
self.config = Config.read(self.confdir, confoverrides or {}, self.tags)
# initialize some limited config variables before initialize i18n and loading
diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py
index d393a131d95..8f639b23f2d 100644
--- a/sphinx/builders/__init__.py
+++ b/sphinx/builders/__init__.py
@@ -262,7 +262,7 @@ def build_specific(self, filenames: list[str]) -> None:
filename)
continue
- if not filename.startswith(self.srcdir):
+ if not filename.startswith(str(self.srcdir)):
logger.warning(__('file %r given on command line is not under the '
'source directory, ignoring'), filename)
continue
diff --git a/sphinx/builders/_epub_base.py b/sphinx/builders/_epub_base.py
index 6bfa03f981c..9765f79363c 100644
--- a/sphinx/builders/_epub_base.py
+++ b/sphinx/builders/_epub_base.py
@@ -21,7 +21,7 @@
from sphinx.util import logging
from sphinx.util.display import status_iterator
from sphinx.util.fileutil import copy_asset_file
-from sphinx.util.osutil import copyfile, ensuredir
+from sphinx.util.osutil import copyfile, ensuredir, relpath
try:
from PIL import Image
@@ -508,9 +508,6 @@ def build_content(self) -> None:
metadata = self.content_metadata()
# files
- if not self.outdir.endswith(os.sep):
- self.outdir += os.sep
- olen = len(self.outdir)
self.files: list[str] = []
self.ignored_files = ['.buildinfo', 'mimetype', 'content.opf',
'toc.ncx', 'META-INF/container.xml',
@@ -522,7 +519,7 @@ def build_content(self) -> None:
for root, dirs, files in os.walk(self.outdir):
dirs.sort()
for fn in sorted(files):
- filename = path.join(root, fn)[olen:]
+ filename = relpath(path.join(root, fn), self.outdir)
if filename in self.ignored_files:
continue
ext = path.splitext(filename)[-1]
diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py
index 5c118bef933..b4356ec7ce0 100644
--- a/sphinx/builders/changes.py
+++ b/sphinx/builders/changes.py
@@ -34,7 +34,7 @@ def init(self) -> None:
self.templates.init(self, self.theme)
def get_outdated_docs(self) -> str:
- return self.outdir
+ return str(self.outdir)
typemap = {
'versionadded': 'added',
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index b2f66eabef3..d0acdc77ac2 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -28,6 +28,7 @@
from sphinx.util.template import SphinxRenderer
if TYPE_CHECKING:
+ import os
from collections.abc import Generator, Iterable
logger = logging.getLogger(__name__)
@@ -84,11 +85,12 @@ def __init__(self, source: str, line: int) -> None:
class GettextRenderer(SphinxRenderer):
def __init__(
- self, template_path: str | None = None, outdir: str | None = None,
+ self, template_path: list[str | os.PathLike[str]] | None = None,
+ outdir: str | os.PathLike[str] | None = None,
) -> None:
self.outdir = outdir
if template_path is None:
- template_path = path.join(package_dir, 'templates', 'gettext')
+ template_path = [path.join(package_dir, 'templates', 'gettext')]
super().__init__(template_path)
def escape(s: str) -> str:
diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py
index e70324fb5ce..832b9a91a3d 100644
--- a/sphinx/builders/html/__init__.py
+++ b/sphinx/builders/html/__init__.py
@@ -786,7 +786,7 @@ def copy_image_files(self) -> None:
def copy_download_files(self) -> None:
def to_relpath(f: str) -> str:
- return relative_path(self.srcdir, f)
+ return relative_path(self.srcdir, f) # type: ignore[arg-type]
# copy downloadable files
if self.env.dlfiles:
@@ -1254,9 +1254,9 @@ def js_tag(js: JavaScript) -> str:
context['js_tag'] = js_tag
-def _file_checksum(outdir: str, filename: str) -> str:
+def _file_checksum(outdir: str | os.PathLike[str], filename: str | os.PathLike[str]) -> str:
# Don't generate checksums for HTTP URIs
- if '://' in filename:
+ if '://' in str(filename):
return ''
try:
# Ensure universal newline mode is used to avoid checksum differences
@@ -1305,7 +1305,7 @@ def validate_html_extra_path(app: Sphinx, config: Config) -> None:
logger.warning(__('html_extra_path entry %r does not exist'), entry)
config.html_extra_path.remove(entry)
elif (path.splitdrive(app.outdir)[0] == path.splitdrive(extra_path)[0] and
- path.commonpath([app.outdir, extra_path]) == app.outdir):
+ path.commonpath((app.outdir, extra_path)) == path.normpath(app.outdir)):
logger.warning(__('html_extra_path entry %r is placed inside outdir'), entry)
config.html_extra_path.remove(entry)
@@ -1318,7 +1318,7 @@ def validate_html_static_path(app: Sphinx, config: Config) -> None:
logger.warning(__('html_static_path entry %r does not exist'), entry)
config.html_static_path.remove(entry)
elif (path.splitdrive(app.outdir)[0] == path.splitdrive(static_path)[0] and
- path.commonpath([app.outdir, static_path]) == app.outdir):
+ path.commonpath((app.outdir, static_path)) == path.normpath(app.outdir)):
logger.warning(__('html_static_path entry %r is placed inside outdir'), entry)
config.html_static_path.remove(entry)
diff --git a/sphinx/cmd/build.py b/sphinx/cmd/build.py
index 4f427e0628f..e43cfa67de4 100644
--- a/sphinx/cmd/build.py
+++ b/sphinx/cmd/build.py
@@ -24,7 +24,7 @@
from sphinx.util.console import color_terminal, nocolor, red, terminal_safe # type: ignore
from sphinx.util.docutils import docutils_namespace, patch_docutils
from sphinx.util.exceptions import format_exception_cut_frames, save_traceback
-from sphinx.util.osutil import abspath, ensuredir
+from sphinx.util.osutil import ensuredir
def handle_exception(
@@ -234,7 +234,7 @@ def _parse_arguments(argv: list[str] = sys.argv[1:]) -> argparse.Namespace:
if warning and args.warnfile:
try:
- warnfile = abspath(args.warnfile)
+ warnfile = path.abspath(args.warnfile)
ensuredir(path.dirname(warnfile))
warnfp = open(args.warnfile, 'w', encoding="utf-8")
except Exception as exc:
diff --git a/sphinx/config.py b/sphinx/config.py
index 41791ebd176..3d27f25e65a 100644
--- a/sphinx/config.py
+++ b/sphinx/config.py
@@ -21,6 +21,7 @@
from sphinx.util.osutil import _chdir as chdir
if TYPE_CHECKING:
+ import os
from collections.abc import Generator, Iterator, Sequence
from sphinx.application import Sphinx
@@ -168,9 +169,8 @@ def __init__(self, config: dict[str, Any] = {}, overrides: dict[str, Any] = {})
self.extensions: list[str] = config.get('extensions', [])
@classmethod
- def read(
- cls, confdir: str, overrides: dict | None = None, tags: Tags | None = None,
- ) -> Config:
+ def read(cls, confdir: str | os.PathLike[str], overrides: dict | None = None,
+ tags: Tags | None = None) -> Config:
"""Create a Config object from configuration file."""
filename = path.join(confdir, CONFIG_FILENAME)
if not path.isfile(filename):
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py
index c2e97a5aea9..fa5c9dde1e5 100644
--- a/sphinx/directives/code.py
+++ b/sphinx/directives/code.py
@@ -244,7 +244,7 @@ def show_diff(self, location: tuple[str, int] | None = None) -> list[str]:
new_lines = self.read_file(self.filename)
old_filename = self.options['diff']
old_lines = self.read_file(old_filename)
- diff = unified_diff(old_lines, new_lines, old_filename, self.filename)
+ diff = unified_diff(old_lines, new_lines, str(old_filename), str(self.filename))
return list(diff)
def pyobject_filter(
diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py
index 7f0baa07420..116840e5e9e 100644
--- a/sphinx/environment/__init__.py
+++ b/sphinx/environment/__init__.py
@@ -31,6 +31,7 @@
if TYPE_CHECKING:
from collections.abc import Generator, Iterator
+ from pathlib import Path
from sphinx.application import Sphinx
from sphinx.builders import Builder
@@ -147,8 +148,8 @@ class BuildEnvironment:
def __init__(self, app: Sphinx):
self.app: Sphinx = app
- self.doctreedir: str = app.doctreedir
- self.srcdir: str = app.srcdir
+ self.doctreedir: Path = app.doctreedir
+ self.srcdir: Path = app.srcdir
self.config: Config = None # type: ignore[assignment]
self.config_status: int = CONFIG_UNSET
self.config_status_extra: str = ''
@@ -387,7 +388,7 @@ def merge_info_from(self, docnames: list[str], other: BuildEnvironment,
domain.merge_domaindata(docnames, other.domaindata[domainname])
self.events.emit('env-merge-info', self, docnames, other)
- def path2doc(self, filename: str) -> str | None:
+ def path2doc(self, filename: str | os.PathLike[str]) -> str | None:
"""Return the docname for the filename if the file is document.
*filename* should be absolute or relative to the source directory.
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py
index e77a39b8fe8..34cfda14b49 100644
--- a/sphinx/ext/autosummary/generate.py
+++ b/sphinx/ext/autosummary/generate.py
@@ -424,8 +424,10 @@ def _get_modules(
return public, items
-def generate_autosummary_docs(sources: list[str], output_dir: str | None = None,
- suffix: str = '.rst', base_path: str | None = None,
+def generate_autosummary_docs(sources: list[str],
+ output_dir: str | os.PathLike[str] | None = None,
+ suffix: str = '.rst',
+ base_path: str | os.PathLike[str] | None = None,
imported_members: bool = False, app: Any = None,
overwrite: bool = True, encoding: str = 'utf-8') -> None:
showed_sources = sorted(sources)
diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py
index b69af8615d9..1d590e9ffb7 100644
--- a/sphinx/ext/imgmath.py
+++ b/sphinx/ext/imgmath.py
@@ -10,7 +10,7 @@
from hashlib import sha1
from os import path
from subprocess import CalledProcessError
-from typing import Any
+from typing import TYPE_CHECKING, Any
from docutils import nodes
from docutils.nodes import Element
@@ -29,6 +29,9 @@
from sphinx.util.template import LaTeXRenderer
from sphinx.writers.html import HTML5Translator
+if TYPE_CHECKING:
+ import os
+
logger = logging.getLogger(__name__)
templates_path = path.join(package_dir, 'templates', 'imgmath')
@@ -83,7 +86,7 @@ def write_svg_depth(filename: str, depth: int) -> None:
def generate_latex_macro(image_format: str,
math: str,
config: Config,
- confdir: str = '') -> str:
+ confdir: str | os.PathLike[str] = '') -> str:
"""Generate LaTeX macro."""
variables = {
'fontsize': config.imgmath_font_size,
diff --git a/sphinx/project.py b/sphinx/project.py
index 52043d97a93..b75c684db7f 100644
--- a/sphinx/project.py
+++ b/sphinx/project.py
@@ -21,7 +21,7 @@
class Project:
"""A project is the source code set of the Sphinx document(s)."""
- def __init__(self, srcdir: str, source_suffix: dict[str, str]) -> None:
+ def __init__(self, srcdir: str | os.PathLike[str], source_suffix: dict[str, str]) -> None:
#: Source directory.
self.srcdir = srcdir
@@ -61,15 +61,15 @@ def discover(self, exclude_paths: Iterable[str] = (),
return self.docnames
- def path2doc(self, filename: str) -> str | None:
+ def path2doc(self, filename: str | os.PathLike[str]) -> str | None:
"""Return the docname for the filename if the file is a document.
*filename* should be absolute or relative to the source directory.
"""
- if filename.startswith(self.srcdir):
+ if str(filename).startswith(str(self.srcdir)):
filename = relpath(filename, self.srcdir)
for suffix in self.source_suffix:
- if filename.endswith(suffix):
+ if str(filename).endswith(suffix):
filename = path_stabilize(filename)
return filename[:-len(suffix)]
diff --git a/sphinx/testing/comparer.py b/sphinx/testing/comparer.py
deleted file mode 100644
index 4ea57a5751c..00000000000
--- a/sphinx/testing/comparer.py
+++ /dev/null
@@ -1,97 +0,0 @@
-"""Sphinx test comparer for pytest"""
-from __future__ import annotations
-
-import difflib
-import pathlib
-from typing import Any
-
-
-class PathComparer:
- """
- OS-independent path comparison.
-
- Windows path sep and posix path sep:
-
- >>> '\\to\\index' == PathComparer('/to/index')
- True
- >>> '\\to\\index' == PathComparer('/to/index2')
- False
-
- Windows path with drive letters
-
- >>> 'C:\\to\\index' == PathComparer('/to/index')
- True
- >>> 'C:\\to\\index' == PathComparer('C:/to/index')
- True
- >>> 'C:\\to\\index' == PathComparer('D:/to/index')
- False
- """
- def __init__(self, path: str | pathlib.Path):
- """
- :param str path: path string, it will be cast as pathlib.Path.
- """
- self.path = pathlib.Path(path)
-
- def __str__(self) -> str:
- return self.path.as_posix()
-
- def __repr__(self) -> str:
- return f"<{self.__class__.__name__}: '{self}'>"
-
- def __eq__(self, other: str | pathlib.Path) -> bool: # type: ignore
- return not bool(self.ldiff(other))
-
- def diff(self, other: str | pathlib.Path) -> list[str]:
- """compare self and other.
-
- When different is not exist, return empty list.
-
- >>> PathComparer('/to/index').diff('C:\\to\\index')
- []
-
- When different is exist, return unified diff style list as:
-
- >>> PathComparer('/to/index').diff('C:\\to\\index2')
- [
- '- C:/to/index'
- '+ C:/to/index2'
- '? +'
- ]
- """
- return self.ldiff(other)
-
- def ldiff(self, other: str | pathlib.Path) -> list[str]:
- return self._diff(
- self.path,
- pathlib.Path(other),
- )
-
- def rdiff(self, other: str | pathlib.Path) -> list[str]:
- return self._diff(
- pathlib.Path(other),
- self.path,
- )
-
- def _diff(self, lhs: pathlib.Path, rhs: pathlib.Path) -> list[str]:
- if lhs == rhs:
- return []
-
- if lhs.drive or rhs.drive:
- # If either has a drive letter compare by absolute path
- s_path, o_path = lhs.absolute().as_posix(), rhs.absolute().as_posix()
- else:
- s_path, o_path = lhs.as_posix(), rhs.as_posix()
-
- if s_path == o_path:
- return []
-
- return [line.strip() for line in difflib.Differ().compare([s_path], [o_path])]
-
-
-def pytest_assertrepr_compare(op: str, left: Any, right: Any) -> list[str]:
- if isinstance(left, PathComparer) and op == "==":
- return ['Comparing path:'] + left.ldiff(right)
- elif isinstance(right, PathComparer) and op == "==":
- return ['Comparing path:'] + right.rdiff(left)
- else:
- return []
diff --git a/sphinx/testing/fixtures.py b/sphinx/testing/fixtures.py
index 157fe93414a..d8335fd6aae 100644
--- a/sphinx/testing/fixtures.py
+++ b/sphinx/testing/fixtures.py
@@ -2,6 +2,7 @@
from __future__ import annotations
+import shutil
import subprocess
import sys
from collections import namedtuple
@@ -10,11 +11,11 @@
import pytest
-from sphinx.testing import util
from sphinx.testing.util import SphinxTestApp, SphinxTestAppWrapperForSkipBuilding
if TYPE_CHECKING:
from collections.abc import Generator
+ from pathlib import Path
DEFAULT_ENABLED_MARKERS = [
(
@@ -96,7 +97,7 @@ def app_params(request: Any, test_params: dict, shared_result: SharedResult,
# special support for sphinx/tests
if rootdir and not srcdir.exists():
testroot_path = rootdir / ('test-' + testroot)
- testroot_path.copytree(srcdir)
+ shutil.copytree(testroot_path, srcdir)
return namedtuple('app_params', 'args,kwargs')(args, kwargs) # type: ignore
@@ -169,8 +170,6 @@ def make_app(test_params: dict, monkeypatch: Any) -> Generator[Callable, None, N
if you want to initialize 'app' in your test function. please use this
instead of using SphinxTestApp class directory.
"""
- monkeypatch.setattr('sphinx.application.abspath', lambda x: x)
-
apps = []
syspath = sys.path[:]
@@ -218,21 +217,9 @@ def if_graphviz_found(app: SphinxTestApp) -> None: # NoQA: PT004
@pytest.fixture(scope='session')
-def sphinx_test_tempdir(tmpdir_factory: Any) -> util.path:
- """
- Temporary directory wrapped with `path` class.
- """
- tmpdir = tmpdir_factory.getbasetemp()
- return util.path(tmpdir).abspath()
-
-
-@pytest.fixture()
-def tempdir(tmpdir: str) -> util.path:
- """
- Temporary directory wrapped with `path` class.
- This fixture is for back-compatibility with old test implementation.
- """
- return util.path(tmpdir)
+def sphinx_test_tempdir(tmp_path_factory: Any) -> Path:
+ """Temporary directory."""
+ return tmp_path_factory.getbasetemp()
@pytest.fixture()
diff --git a/sphinx/testing/path.py b/sphinx/testing/path.py
index 105b786d5cf..0476f2377f8 100644
--- a/sphinx/testing/path.py
+++ b/sphinx/testing/path.py
@@ -3,11 +3,18 @@
import os
import shutil
import sys
+import warnings
from typing import IO, TYPE_CHECKING, Any, Callable
+from sphinx.deprecation import RemovedInSphinx90Warning
+
if TYPE_CHECKING:
import builtins
+warnings.warn("'sphinx.testing.path' is deprecated. "
+ "Use 'os.path' or 'pathlib' instead.",
+ RemovedInSphinx90Warning, stacklevel=2)
+
FILESYSTEMENCODING = sys.getfilesystemencoding() or sys.getdefaultencoding()
diff --git a/sphinx/testing/util.py b/sphinx/testing/util.py
index 48ae126c210..a6838f26b1e 100644
--- a/sphinx/testing/util.py
+++ b/sphinx/testing/util.py
@@ -15,12 +15,10 @@
from sphinx import application, locale
from sphinx.pycode import ModuleAnalyzer
-from sphinx.testing.path import path
-from sphinx.util.osutil import relpath
if TYPE_CHECKING:
- from collections.abc import Generator
from io import StringIO
+ from pathlib import Path
__all__ = [
'Struct', 'SphinxTestApp', 'SphinxTestAppWrapperForSkipBuilding',
@@ -102,8 +100,8 @@ class SphinxTestApp(application.Sphinx):
def __init__(
self,
buildername: str = 'html',
- srcdir: path | None = None,
- builddir: path | None = None,
+ srcdir: Path | None = None,
+ builddir: Path | None = None,
freshenv: bool = False,
confoverrides: dict | None = None,
status: IO | None = None,
@@ -123,9 +121,9 @@ def __init__(
confdir = srcdir
outdir = builddir.joinpath(buildername)
- outdir.makedirs(exist_ok=True)
+ outdir.mkdir(parents=True, exist_ok=True)
doctreedir = builddir.joinpath('doctrees')
- doctreedir.makedirs(exist_ok=True)
+ doctreedir.mkdir(parents=True, exist_ok=True)
if confoverrides is None:
confoverrides = {}
warningiserror = False
@@ -184,7 +182,7 @@ def __getattr__(self, name: str) -> Any:
return getattr(self.app, name)
def build(self, *args: Any, **kwargs: Any) -> None:
- if not self.app.outdir.listdir(): # type: ignore
+ if not os.listdir(self.app.outdir):
# if listdir is empty, do build.
self.app.build(*args, **kwargs)
# otherwise, we can use built cache
@@ -193,14 +191,6 @@ def build(self, *args: Any, **kwargs: Any) -> None:
_unicode_literals_re = re.compile(r'u(".*?")|u(\'.*?\')')
-def find_files(root: str, suffix: str | None = None) -> Generator[str, None, None]:
- for dirpath, _dirs, files in os.walk(root, followlinks=True):
- dirpath = path(dirpath)
- for f in [f for f in files if not suffix or f.endswith(suffix)]:
- fpath = dirpath / f
- yield relpath(fpath, root)
-
-
def strip_escseq(text: str) -> str:
return re.sub('\x1b.*?m', '', text)
diff --git a/sphinx/util/fileutil.py b/sphinx/util/fileutil.py
index 03928710e88..5dae51c2a81 100644
--- a/sphinx/util/fileutil.py
+++ b/sphinx/util/fileutil.py
@@ -15,7 +15,7 @@
from sphinx.util.template import BaseRenderer
-def copy_asset_file(source: str, destination: str,
+def copy_asset_file(source: str | os.PathLike[str], destination: str | os.PathLike[str],
context: dict | None = None,
renderer: BaseRenderer | None = None) -> None:
"""Copy an asset file to destination.
@@ -34,8 +34,10 @@ def copy_asset_file(source: str, destination: str,
if os.path.isdir(destination):
# Use source filename if destination points a directory
destination = os.path.join(destination, os.path.basename(source))
+ else:
+ destination = str(destination)
- if source.lower().endswith('_t') and context is not None:
+ if os.path.splitext(source)[1].lower().endswith('_t') and context is not None:
if renderer is None:
from sphinx.util.template import SphinxRenderer
renderer = SphinxRenderer()
@@ -49,7 +51,8 @@ def copy_asset_file(source: str, destination: str,
copyfile(source, destination)
-def copy_asset(source: str, destination: str, excluded: PathMatcher = lambda path: False,
+def copy_asset(source: str | os.PathLike[str], destination: str | os.PathLike[str],
+ excluded: PathMatcher = lambda path: False,
context: dict | None = None, renderer: BaseRenderer | None = None,
onerror: Callable[[str, Exception], None] | None = None) -> None:
"""Copy asset files to destination recursively.
@@ -77,7 +80,7 @@ def copy_asset(source: str, destination: str, excluded: PathMatcher = lambda pat
return
for root, dirs, files in os.walk(source, followlinks=True):
- reldir = relative_path(source, root)
+ reldir = relative_path(source, root) # type: ignore[arg-type]
for dir in dirs[:]:
if excluded(posixpath.join(reldir, dir)):
dirs.remove(dir)
diff --git a/sphinx/util/i18n.py b/sphinx/util/i18n.py
index 04c8ccb35fa..11cb5b64ce0 100644
--- a/sphinx/util/i18n.py
+++ b/sphinx/util/i18n.py
@@ -73,7 +73,7 @@ def write_mo(self, locale: str, use_fuzzy: bool = False) -> None:
class CatalogRepository:
"""A repository for message catalogs."""
- def __init__(self, basedir: str, locale_dirs: list[str],
+ def __init__(self, basedir: str | os.PathLike[str], locale_dirs: list[str],
language: str, encoding: str) -> None:
self.basedir = basedir
self._locale_dirs = locale_dirs
diff --git a/sphinx/util/matching.py b/sphinx/util/matching.py
index 04422ed53ab..dd91905d709 100644
--- a/sphinx/util/matching.py
+++ b/sphinx/util/matching.py
@@ -110,7 +110,7 @@ def patfilter(names: Iterable[str], pat: str) -> list[str]:
def get_matching_files(
- dirname: str,
+ dirname: str | os.PathLike[str],
include_patterns: Iterable[str] = ("**",),
exclude_patterns: Iterable[str] = (),
) -> Iterator[str]:
diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py
index f5f0a2e0c96..a2c15c34ca5 100644
--- a/sphinx/util/osutil.py
+++ b/sphinx/util/osutil.py
@@ -18,13 +18,6 @@
if TYPE_CHECKING:
from collections.abc import Iterator
-try:
- # for ALT Linux (#6712)
- from sphinx.testing.path import path as Path
-except ImportError:
- Path = None # type: ignore
-
-
# SEP separates path elements in the canonical file names
#
# Define SEP as a manifest constant, not so much because we expect it to change
@@ -37,12 +30,12 @@ def os_path(canonicalpath: str) -> str:
return canonicalpath.replace(SEP, path.sep)
-def canon_path(nativepath: str) -> str:
+def canon_path(nativepath: str | os.PathLike[str]) -> str:
"""Return path in OS-independent form"""
- return nativepath.replace(path.sep, SEP)
+ return str(nativepath).replace(path.sep, SEP)
-def path_stabilize(filepath: str) -> str:
+def path_stabilize(filepath: str | os.PathLike[str]) -> str:
"Normalize path separator and unicode string"
new_path = canon_path(filepath)
return unicodedata.normalize('NFC', new_path)
@@ -71,9 +64,9 @@ def relative_uri(base: str, to: str) -> str:
return ('..' + SEP) * (len(b2) - 1) + SEP.join(t2)
-def ensuredir(path: str) -> None:
+def ensuredir(file: str | os.PathLike[str]) -> None:
"""Ensure that a path exists."""
- os.makedirs(path, exist_ok=True)
+ os.makedirs(file, exist_ok=True)
def mtimes_of_files(dirnames: list[str], suffix: str) -> Iterator[float]:
@@ -87,14 +80,14 @@ def mtimes_of_files(dirnames: list[str], suffix: str) -> Iterator[float]:
pass
-def copytimes(source: str, dest: str) -> None:
+def copytimes(source: str | os.PathLike[str], dest: str | os.PathLike[str]) -> None:
"""Copy a file's modification times."""
st = os.stat(source)
if hasattr(os, 'utime'):
os.utime(dest, (st.st_atime, st.st_mtime))
-def copyfile(source: str, dest: str) -> None:
+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"""
@@ -119,7 +112,8 @@ def make_filename_from_project(project: str) -> str:
return make_filename(project_suffix_re.sub('', project)).lower()
-def relpath(path: str, start: str | None = os.curdir) -> str:
+def relpath(path: str | os.PathLike[str],
+ start: str | os.PathLike[str] | None = os.curdir) -> str:
"""Return a relative filepath to *path* either from the current directory or
from an optional *start* directory.
@@ -129,26 +123,14 @@ def relpath(path: str, start: str | None = os.curdir) -> str:
try:
return os.path.relpath(path, start)
except ValueError:
- return path
+ return str(path)
safe_relpath = relpath # for compatibility
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
-def abspath(pathdir: str) -> str:
- if Path is not None and isinstance(pathdir, Path):
- return pathdir.abspath()
- else:
- pathdir = path.abspath(pathdir)
- if isinstance(pathdir, bytes):
- try:
- pathdir = pathdir.decode(fs_encoding)
- except UnicodeDecodeError as exc:
- raise UnicodeDecodeError('multibyte filename not supported on '
- 'this filesystem encoding '
- '(%r)' % fs_encoding) from exc
- return pathdir
+abspath = path.abspath
class _chdir:
diff --git a/sphinx/util/template.py b/sphinx/util/template.py
index 2bcfd28fc98..25004e448b2 100644
--- a/sphinx/util/template.py
+++ b/sphinx/util/template.py
@@ -5,7 +5,7 @@
import os
from functools import partial
from os import path
-from typing import Any, Callable
+from typing import TYPE_CHECKING, Any, Callable
from jinja2 import TemplateNotFound
from jinja2.environment import Environment
@@ -17,6 +17,9 @@
from sphinx.locale import get_translator
from sphinx.util import rst, texescape
+if TYPE_CHECKING:
+ from collections.abc import Sequence
+
class BaseRenderer:
def __init__(self, loader: BaseLoader | None = None) -> None:
@@ -32,8 +35,8 @@ def render_string(self, source: str, context: dict[str, Any]) -> str:
class FileRenderer(BaseRenderer):
- def __init__(self, search_path: str | list[str]) -> None:
- if isinstance(search_path, str):
+ def __init__(self, search_path: Sequence[str | os.PathLike[str]]) -> None:
+ if isinstance(search_path, (str, os.PathLike)):
search_path = [search_path]
else:
# filter "None" paths
@@ -50,7 +53,7 @@ def render_from_file(cls, filename: str, context: dict[str, Any]) -> str:
class SphinxRenderer(FileRenderer):
- def __init__(self, template_path: None | str | list[str] = None) -> None:
+ def __init__(self, template_path: Sequence[str | os.PathLike[str]] | None = None) -> None:
if template_path is None:
template_path = os.path.join(package_dir, 'templates')
super().__init__(template_path)
@@ -61,11 +64,10 @@ def render_from_file(cls, filename: str, context: dict[str, Any]) -> str:
class LaTeXRenderer(SphinxRenderer):
- def __init__(
- self, template_path: str | None = None, latex_engine: str | None = None,
- ) -> None:
+ def __init__(self, template_path: Sequence[str | os.PathLike[str]] | None = None,
+ latex_engine: str | None = None) -> None:
if template_path is None:
- template_path = os.path.join(package_dir, 'templates', 'latex')
+ template_path = [os.path.join(package_dir, 'templates', 'latex')]
super().__init__(template_path)
# use texescape as escape filter
@@ -85,9 +87,8 @@ def __init__(
class ReSTRenderer(SphinxRenderer):
- def __init__(
- self, template_path: None | str | list[str] = None, language: str | None = None,
- ) -> None:
+ def __init__(self, template_path: Sequence[str | os.PathLike[str]] | None = None,
+ language: str | None = None) -> None:
super().__init__(template_path)
# add language to environment
@@ -102,8 +103,9 @@ def __init__(
class SphinxTemplateLoader(BaseLoader):
"""A loader supporting template inheritance"""
- def __init__(self, confdir: str, templates_paths: list[str],
- system_templates_paths: list[str]) -> None:
+ def __init__(self, confdir: str | os.PathLike[str],
+ templates_paths: Sequence[str | os.PathLike[str]],
+ system_templates_paths: Sequence[str | os.PathLike[str]]) -> None:
self.loaders = []
self.sysloaders = []
diff --git a/tests/conftest.py b/tests/conftest.py
index 3934203eab3..f0cc23e71a8 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,13 +1,10 @@
-import os
-import shutil
+from pathlib import Path
import docutils
import pytest
import sphinx
import sphinx.locale
-from sphinx.testing import comparer
-from sphinx.testing.path import path
def _init_console(locale_dir=sphinx.locale._LOCALE_DIR, catalog='sphinx'):
@@ -30,32 +27,11 @@ def _init_console(locale_dir=sphinx.locale._LOCALE_DIR, catalog='sphinx'):
@pytest.fixture(scope='session')
def rootdir():
- return path(__file__).parent.abspath() / 'roots'
+ return Path(__file__).parent.absolute() / 'roots'
def pytest_report_header(config):
- header = ("libraries: Sphinx-%s, docutils-%s" %
- (sphinx.__display_version__, docutils.__version__))
+ header = f"libraries: Sphinx-{sphinx.__display_version__}, docutils-{docutils.__version__}"
if hasattr(config, '_tmp_path_factory'):
- header += "\nbase tempdir: %s" % config._tmp_path_factory.getbasetemp()
-
+ header += f"\nbase tmp_path: {config._tmp_path_factory.getbasetemp()}"
return header
-
-
-def pytest_assertrepr_compare(op, left, right):
- comparer.pytest_assertrepr_compare(op, left, right)
-
-
-def _initialize_test_directory(session):
- if 'SPHINX_TEST_TEMPDIR' in os.environ:
- tempdir = os.path.abspath(os.getenv('SPHINX_TEST_TEMPDIR'))
- print('Temporary files will be placed in %s.' % tempdir)
-
- if os.path.exists(tempdir):
- shutil.rmtree(tempdir)
-
- os.makedirs(tempdir)
-
-
-def pytest_sessionstart(session):
- _initialize_test_directory(session)
diff --git a/tests/test_application.py b/tests/test_application.py
index a7a4e7093c6..a0fe268fe46 100644
--- a/tests/test_application.py
+++ b/tests/test_application.py
@@ -11,7 +11,6 @@
import sphinx.application
from sphinx.errors import ExtensionError
-from sphinx.testing.path import path
from sphinx.testing.util import SphinxTestApp, strip_escseq
from sphinx.util import logging
@@ -24,13 +23,11 @@ def test_instantiation(tmp_path_factory, rootdir: str, monkeypatch):
if rootdir and not src_dir.exists():
shutil.copytree(Path(str(rootdir)) / 'test-root', src_dir)
- monkeypatch.setattr('sphinx.application.abspath', lambda x: x)
-
syspath = sys.path[:]
# When
app_ = SphinxTestApp(
- srcdir=path(src_dir),
+ srcdir=src_dir,
status=StringIO(),
warning=StringIO(),
)
diff --git a/tests/test_build.py b/tests/test_build.py
index f3a48a3bdfa..546798b0216 100644
--- a/tests/test_build.py
+++ b/tests/test_build.py
@@ -1,5 +1,7 @@
"""Test all builders."""
+import os
+import shutil
import sys
from unittest import mock
@@ -23,7 +25,7 @@ def nonascii_srcdir(request, rootdir, sphinx_test_tempdir):
basedir = sphinx_test_tempdir / request.node.originalname
srcdir = basedir / test_name
if not srcdir.exists():
- (rootdir / 'test-root').copytree(srcdir)
+ shutil.copytree(rootdir / 'test-root', srcdir)
# add a doc with a non-ASCII file name to the source dir
(srcdir / (test_name + '.txt')).write_text("""
@@ -54,11 +56,11 @@ def test_build_all(requests_head, make_app, nonascii_srcdir, buildername):
app.build()
-def test_root_doc_not_found(tempdir, make_app):
- (tempdir / 'conf.py').write_text('', encoding='utf8')
- assert tempdir.listdir() == ['conf.py']
+def test_root_doc_not_found(tmp_path, make_app):
+ (tmp_path / 'conf.py').write_text('', encoding='utf8')
+ assert os.listdir(tmp_path) == ['conf.py']
- app = make_app('dummy', srcdir=tempdir)
+ app = make_app('dummy', srcdir=tmp_path)
with pytest.raises(SphinxError):
app.builder.build_all() # no index.rst
diff --git a/tests/test_build_gettext.py b/tests/test_build_gettext.py
index dee9757b024..bce6bd2dbda 100644
--- a/tests/test_build_gettext.py
+++ b/tests/test_build_gettext.py
@@ -42,9 +42,9 @@ def test_build_gettext(app):
# Do messages end up in the correct location?
# top-level documents end up in a message catalog
- assert (app.outdir / 'extapi.pot').isfile()
+ assert (app.outdir / 'extapi.pot').is_file()
# directory items are grouped into sections
- assert (app.outdir / 'subdir.pot').isfile()
+ assert (app.outdir / 'subdir.pot').is_file()
# regression test for issue #960
catalog = (app.outdir / 'markup.pot').read_text(encoding='utf8')
@@ -54,7 +54,7 @@ def test_build_gettext(app):
@pytest.mark.sphinx('gettext', srcdir='root-gettext')
def test_msgfmt(app):
app.builder.build_all()
- (app.outdir / 'en' / 'LC_MESSAGES').makedirs()
+ (app.outdir / 'en' / 'LC_MESSAGES').mkdir(parents=True, exist_ok=True)
with chdir(app.outdir):
try:
args = ['msginit', '--no-translator', '-i', 'markup.pot', '--locale', 'en_US']
@@ -66,7 +66,7 @@ def test_msgfmt(app):
print(exc.stderr)
raise AssertionError('msginit exited with return code %s' % exc.returncode)
- assert (app.outdir / 'en_US.po').isfile(), 'msginit failed'
+ assert (app.outdir / 'en_US.po').is_file(), 'msginit failed'
try:
args = ['msgfmt', 'en_US.po',
'-o', os.path.join('en', 'LC_MESSAGES', 'test_root.mo')]
@@ -79,7 +79,7 @@ def test_msgfmt(app):
raise AssertionError('msgfmt exited with return code %s' % exc.returncode)
mo = app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo'
- assert mo.isfile(), 'msgfmt failed'
+ assert mo.is_file(), 'msgfmt failed'
_ = gettext.translation('test_root', app.outdir, languages=['en']).gettext
assert _("Testing various markup") == "Testing various markup"
@@ -164,7 +164,7 @@ def msgid_getter(msgid):
@pytest.mark.sphinx('gettext', testroot='intl', srcdir='gettext')
def test_gettext_template(app):
app.build()
- assert (app.outdir / 'sphinx.pot').isfile()
+ assert (app.outdir / 'sphinx.pot').is_file()
result = (app.outdir / 'sphinx.pot').read_text(encoding='utf8')
assert "Welcome" in result
@@ -174,7 +174,7 @@ def test_gettext_template(app):
@pytest.mark.sphinx('gettext', testroot='gettext-template')
def test_gettext_template_msgid_order_in_sphinxpot(app):
app.builder.build_all()
- assert (app.outdir / 'sphinx.pot').isfile()
+ assert (app.outdir / 'sphinx.pot').is_file()
result = (app.outdir / 'sphinx.pot').read_text(encoding='utf8')
assert re.search(
@@ -192,7 +192,7 @@ def test_gettext_template_msgid_order_in_sphinxpot(app):
def test_build_single_pot(app):
app.builder.build_all()
- assert (app.outdir / 'documentation.pot').isfile()
+ assert (app.outdir / 'documentation.pot').is_file()
result = (app.outdir / 'documentation.pot').read_text(encoding='utf8')
assert re.search(
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index 2604f3df920..9a6326c69f5 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -116,22 +116,22 @@ def test_html_warnings(app, warning):
app.build()
html_warnings = strip_escseq(re.sub(re.escape(os.sep) + '{1,2}', '/', warning.getvalue()))
html_warnings_exp = HTML_WARNINGS % {
- 'root': re.escape(app.srcdir.replace(os.sep, '/'))}
+ 'root': re.escape(app.srcdir.as_posix())}
assert re.match(html_warnings_exp + '$', html_warnings), \
"Warnings don't match:\n" + \
'--- Expected (regex):\n' + html_warnings_exp + \
'--- Got:\n' + html_warnings
-def test_html4_error(make_app, tempdir):
- (tempdir / 'conf.py').write_text('', encoding='utf-8')
+def test_html4_error(make_app, tmp_path):
+ (tmp_path / 'conf.py').write_text('', encoding='utf-8')
with pytest.raises(
ConfigError,
match=r'HTML 4 is no longer supported by Sphinx',
):
make_app(
buildername='html',
- srcdir=tempdir,
+ srcdir=tmp_path,
confoverrides={'html4_writer': True},
)
@@ -753,7 +753,7 @@ def test_numfig_without_numbered_toctree(app, cached_etree_parse, fname, expect)
index = re.sub(':numbered:.*', '', index)
(app.srcdir / 'index.rst').write_text(index, encoding='utf8')
- if not app.outdir.listdir():
+ if not os.listdir(app.outdir):
app.build()
check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
@@ -1371,7 +1371,7 @@ def test_html_remote_images(app, status, warning):
def test_html_encoded_image(app, status, warning):
app.builder.build_all()
- result = (app.outdir / 'index.html').read_text()
+ result = (app.outdir / 'index.html').read_text(encoding='utf8')
assert ('' in result)
assert (app.outdir / '_images/img_#1.png').exists()
@@ -1563,7 +1563,7 @@ def test_html_dark_pygments_style_default(app):
@pytest.mark.sphinx(testroot='basic', srcdir='validate_html_extra_path')
def test_validate_html_extra_path(app):
- (app.confdir / '_static').makedirs()
+ (app.confdir / '_static').mkdir(parents=True, exist_ok=True)
app.config.html_extra_path = [
'/path/to/not_found', # not found
'_static',
@@ -1576,7 +1576,7 @@ def test_validate_html_extra_path(app):
@pytest.mark.sphinx(testroot='basic', srcdir='validate_html_static_path')
def test_validate_html_static_path(app):
- (app.confdir / '_static').makedirs()
+ (app.confdir / '_static').mkdir(parents=True, exist_ok=True)
app.config.html_static_path = [
'/path/to/not_found', # not found
'_static',
@@ -1691,7 +1691,7 @@ def test_html_signaturereturn_icon(app):
@pytest.mark.sphinx('html', testroot='reST-code-role')
def test_html_code_role(app):
app.build()
- content = (app.outdir / 'index.html').read_text()
+ content = (app.outdir / 'index.html').read_text(encoding='utf8')
common_content = (
'def foo'
@@ -1716,7 +1716,7 @@ def test_html_code_role(app):
confoverrides={'option_emphasise_placeholders': True})
def test_option_emphasise_placeholders(app, status, warning):
app.build()
- content = (app.outdir / 'objects.html').read_text()
+ content = (app.outdir / 'objects.html').read_text(encoding='utf8')
assert 'TYPE' in content
assert '{TYPE}' not in content
assert ('WHERE'
@@ -1730,7 +1730,7 @@ def test_option_emphasise_placeholders(app, status, warning):
@pytest.mark.sphinx('html', testroot='root')
def test_option_emphasise_placeholders_default(app, status, warning):
app.build()
- content = (app.outdir / 'objects.html').read_text()
+ content = (app.outdir / 'objects.html').read_text(encoding='utf8')
assert '={TYPE}' in content
assert '={WHERE}-{COUNT}' in content
assert '{client_name}' in content
@@ -1742,7 +1742,7 @@ def test_option_emphasise_placeholders_default(app, status, warning):
@pytest.mark.sphinx('html', testroot='root')
def test_option_reference_with_value(app, status, warning):
app.build()
- content = (app.outdir / 'objects.html').read_text()
+ content = (app.outdir / 'objects.html').read_text(encoding='utf-8')
assert ('-mapi'
'' in html)
-def test_missing_reference_jsdomain(tempdir, app, status, warning):
- inv_file = tempdir / 'inventory'
+def test_missing_reference_jsdomain(tmp_path, app, status, warning):
+ inv_file = tmp_path / 'inventory'
inv_file.write_bytes(inventory_v2)
set_config(app, {
- 'https://docs.python.org/': inv_file,
+ 'https://docs.python.org/': str(inv_file),
})
# load the inventory and check if it's done correctly
@@ -290,11 +290,11 @@ def test_missing_reference_jsdomain(tempdir, app, status, warning):
assert rn.astext() == 'baz()'
-def test_missing_reference_disabled_domain(tempdir, app, status, warning):
- inv_file = tempdir / 'inventory'
+def test_missing_reference_disabled_domain(tmp_path, app, status, warning):
+ inv_file = tmp_path / 'inventory'
inv_file.write_bytes(inventory_v2)
set_config(app, {
- 'inv': ('https://docs.python.org/', inv_file),
+ 'inv': ('https://docs.python.org/', str(inv_file)),
})
# load the inventory and check if it's done correctly
@@ -353,11 +353,11 @@ def assert_(rn, expected):
@pytest.mark.xfail(os.name != 'posix', reason="Path separator mismatch issue")
-def test_inventory_not_having_version(tempdir, app, status, warning):
- inv_file = tempdir / 'inventory'
+def test_inventory_not_having_version(tmp_path, app, status, warning):
+ inv_file = tmp_path / 'inventory'
inv_file.write_bytes(inventory_v2_not_having_version)
set_config(app, {
- 'https://docs.python.org/': inv_file,
+ 'https://docs.python.org/': str(inv_file),
})
# load the inventory and check if it's done correctly
@@ -371,20 +371,20 @@ def test_inventory_not_having_version(tempdir, app, status, warning):
assert rn[0].astext() == 'Long Module desc'
-def test_load_mappings_warnings(tempdir, app, status, warning):
+def test_load_mappings_warnings(tmp_path, app, status, warning):
"""
load_mappings issues a warning if new-style mapping
identifiers are not string
"""
- inv_file = tempdir / 'inventory'
+ inv_file = tmp_path / 'inventory'
inv_file.write_bytes(inventory_v2)
set_config(app, {
- 'https://docs.python.org/': inv_file,
- 'py3k': ('https://docs.python.org/py3k/', inv_file),
- 'repoze.workflow': ('http://docs.repoze.org/workflow/', inv_file),
+ 'https://docs.python.org/': str(inv_file),
+ 'py3k': ('https://docs.python.org/py3k/', str(inv_file)),
+ 'repoze.workflow': ('http://docs.repoze.org/workflow/', str(inv_file)),
'django-taggit': ('http://django-taggit.readthedocs.org/en/latest/',
- inv_file),
- 12345: ('http://www.sphinx-doc.org/en/stable/', inv_file),
+ str(inv_file)),
+ 12345: ('http://www.sphinx-doc.org/en/stable/', str(inv_file)),
})
# load the inventory and check if it's done correctly
@@ -396,8 +396,8 @@ def test_load_mappings_warnings(tempdir, app, status, warning):
assert 'intersphinx identifier 12345 is not string. Ignored' in warnings[1]
-def test_load_mappings_fallback(tempdir, app, status, warning):
- inv_file = tempdir / 'inventory'
+def test_load_mappings_fallback(tmp_path, app, status, warning):
+ inv_file = tmp_path / 'inventory'
inv_file.write_bytes(inventory_v2)
set_config(app, {})
@@ -419,7 +419,7 @@ def test_load_mappings_fallback(tempdir, app, status, warning):
# add fallbacks to mapping
app.config.intersphinx_mapping = {
'fallback': ('https://docs.python.org/py3k/', ('/invalid/inventory/path',
- inv_file)),
+ str(inv_file))),
}
normalize_intersphinx_mapping(app, app.config)
load_mappings(app)
@@ -493,9 +493,9 @@ def test_inspect_main_noargs(capsys):
assert stderr == expected + "\n"
-def test_inspect_main_file(capsys, tempdir):
+def test_inspect_main_file(capsys, tmp_path):
"""inspect_main interface, with file argument"""
- inv_file = tempdir / 'inventory'
+ inv_file = tmp_path / 'inventory'
inv_file.write_bytes(inventory_v2)
inspect_main([str(inv_file)])
@@ -532,7 +532,7 @@ def test_intersphinx_role(app, warning):
inv_file = app.srcdir / 'inventory'
inv_file.write_bytes(inventory_v2)
app.config.intersphinx_mapping = {
- 'inv': ('http://example.org/', inv_file),
+ 'inv': ('http://example.org/', str(inv_file)),
}
app.config.intersphinx_cache_limit = 0
app.config.nitpicky = True
diff --git a/tests/test_intl.py b/tests/test_intl.py
index e451a664e27..9a47345879a 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -4,8 +4,11 @@
"""
import os
+import os.path
import re
+import shutil
import time
+from pathlib import Path
import pygments
import pytest
@@ -20,7 +23,6 @@
assert_re_search,
assert_startswith,
etree_parse,
- path,
strip_escseq,
)
from sphinx.util.nodes import NodeMatcher
@@ -35,28 +37,29 @@
def read_po(pathname):
- with pathname.open(encoding='utf-8') as f:
+ with open(pathname, encoding='utf-8') as f:
return pofile.read_po(f)
def write_mo(pathname, po):
- with pathname.open('wb') as f:
+ with open(pathname, 'wb') as f:
return mofile.write_mo(f, po)
@pytest.fixture(autouse=True)
def _setup_intl(app_params):
- srcdir = path(app_params.kwargs['srcdir'])
+ assert isinstance(app_params.kwargs['srcdir'], Path)
+ srcdir = app_params.kwargs['srcdir']
for dirpath, _dirs, files in os.walk(srcdir):
- dirpath = path(dirpath)
+ dirpath = Path(dirpath)
for f in [f for f in files if f.endswith('.po')]:
- po = dirpath / f
+ po = str(dirpath / f)
mo = srcdir / 'xx' / 'LC_MESSAGES' / (
os.path.relpath(po[:-3], srcdir) + '.mo')
if not mo.parent.exists():
- mo.parent.makedirs()
+ mo.parent.mkdir(parents=True, exist_ok=True)
- if not mo.exists() or mo.stat().st_mtime < po.stat().st_mtime:
+ if not mo.exists() or os.stat(mo).st_mtime < os.stat(po).st_mtime:
# compile .mo file only if needed
write_mo(mo, read_po(po))
@@ -697,13 +700,13 @@ def get_update_targets(app_):
# When rewriting the timestamp of mo file, the number of documents to be
# updated will be changed.
mtime = (app0.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').stat().st_mtime
- (app0.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').utime((mtime + 5, mtime + 5))
+ os.utime(app0.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo', (mtime + 5, mtime + 5))
update_targets = get_update_targets(app0)
assert update_targets[1] == {'bom'}, update_targets
# Because doctree for gettext builder can not be shared with other builders,
# erase doctreedir before gettext build.
- app0.doctreedir.rmtree()
+ shutil.rmtree(app0.doctreedir)
# phase2: build document with gettext builder.
# The mo file in the srcdir directory is retained.
@@ -715,7 +718,7 @@ def get_update_targets(app_):
assert update_targets[1] == set(), update_targets
# Even if the timestamp of the mo file is updated, the number of documents
# to be updated is 0. gettext builder does not rebuild because of mo update.
- (app0.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').utime((mtime + 10, mtime + 10))
+ os.utime(app0.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo', (mtime + 10, mtime + 10))
update_targets = get_update_targets(app)
assert update_targets[1] == set(), update_targets
@@ -867,7 +870,7 @@ def test_html_rebuild_mo(app):
assert len(updated) == 0
mtime = (app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').stat().st_mtime
- (app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').utime((mtime + 5, mtime + 5))
+ os.utime(app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo', (mtime + 5, mtime + 5))
app.env.find_files(app.config, app.builder)
_, updated, _ = app.env.get_outdated_files(config_changed=False)
assert len(updated) == 1
@@ -1401,7 +1404,7 @@ def getwarning(warnings):
})
def test_gettext_allow_fuzzy_translations(app):
locale_dir = app.srcdir / 'locales' / 'de' / 'LC_MESSAGES'
- locale_dir.makedirs()
+ locale_dir.mkdir(parents=True, exist_ok=True)
with (locale_dir / 'index.po').open('wb') as f:
catalog = Catalog()
catalog.add('features', 'FEATURES', flags=('fuzzy',))
@@ -1420,7 +1423,7 @@ def test_gettext_allow_fuzzy_translations(app):
})
def test_gettext_disallow_fuzzy_translations(app):
locale_dir = app.srcdir / 'locales' / 'de' / 'LC_MESSAGES'
- locale_dir.makedirs()
+ locale_dir.mkdir(parents=True, exist_ok=True)
with (locale_dir / 'index.po').open('wb') as f:
catalog = Catalog()
catalog.add('features', 'FEATURES', flags=('fuzzy',))
@@ -1439,7 +1442,7 @@ def test_customize_system_message(make_app, app_params, sphinx_test_tempdir):
# prepare message catalog (.po)
locale_dir = sphinx_test_tempdir / 'basic' / 'locales' / 'de' / 'LC_MESSAGES'
- locale_dir.makedirs()
+ locale_dir.mkdir(parents=True, exist_ok=True)
with (locale_dir / 'sphinx.po').open('wb') as f:
catalog = Catalog()
catalog.add('Quick search', 'QUICK SEARCH')
diff --git a/tests/test_project.py b/tests/test_project.py
index 9eba9316407..790865fc1cf 100644
--- a/tests/test_project.py
+++ b/tests/test_project.py
@@ -6,7 +6,7 @@
def test_project_discover(rootdir):
- project = Project(rootdir / 'test-root', {})
+ project = Project(str(rootdir / 'test-root'), {})
docnames = {'autodoc', 'bom', 'extapi', 'extensions', 'footnote', 'images',
'includes', 'index', 'lists', 'markup', 'math', 'objects',
@@ -48,7 +48,7 @@ def test_project_path2doc(app):
assert project.path2doc('index.foo.rst') == 'index.foo'
assert project.path2doc('index') is None
assert project.path2doc('path/to/index.rst') == 'path/to/index'
- assert project.path2doc(app.srcdir / 'to/index.rst') == 'to/index'
+ assert project.path2doc(str(app.srcdir / 'to/index.rst')) == 'to/index'
@pytest.mark.sphinx(srcdir='project_doc2path', testroot='basic')
@@ -56,17 +56,17 @@ def test_project_doc2path(app):
source_suffix = {'.rst': 'restructuredtext', '.txt': 'restructuredtext'}
project = Project(app.srcdir, source_suffix)
- assert project.doc2path('index') == (app.srcdir / 'index.rst')
+ assert project.doc2path('index') == str(app.srcdir / 'index.rst')
# first source_suffix is used for missing file
- assert project.doc2path('foo') == (app.srcdir / 'foo.rst')
+ assert project.doc2path('foo') == str(app.srcdir / 'foo.rst')
# matched source_suffix is used if exists
(app.srcdir / 'foo.txt').write_text('', encoding='utf8')
- assert project.doc2path('foo') == (app.srcdir / 'foo.txt')
+ assert project.doc2path('foo') == str(app.srcdir / 'foo.txt')
# absolute path
- assert project.doc2path('index', basedir=True) == (app.srcdir / 'index.rst')
+ assert project.doc2path('index', basedir=True) == str(app.srcdir / 'index.rst')
# relative path
assert project.doc2path('index', basedir=False) == 'index.rst'
diff --git a/tests/test_pycode.py b/tests/test_pycode.py
index 92a8a19e912..5739787fff2 100644
--- a/tests/test_pycode.py
+++ b/tests/test_pycode.py
@@ -40,7 +40,7 @@ def test_ModuleAnalyzer_for_module(rootdir):
assert analyzer.srcname in (SPHINX_MODULE_PATH,
os.path.abspath(SPHINX_MODULE_PATH))
- path = rootdir / 'test-pycode'
+ path = str(rootdir / 'test-pycode')
sys.path.insert(0, path)
try:
analyzer = ModuleAnalyzer.for_module('cp_1251_coded')
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
index bba97f5e3c4..6a9f5c70979 100644
--- a/tests/test_quickstart.py
+++ b/tests/test_quickstart.py
@@ -85,9 +85,9 @@ def test_do_prompt_with_nonascii():
assert result == '\u30c9\u30a4\u30c4'
-def test_quickstart_defaults(tempdir):
+def test_quickstart_defaults(tmp_path):
answers = {
- 'Root path': tempdir,
+ 'Root path': str(tmp_path),
'Project name': 'Sphinx Test',
'Author name': 'Georg Brandl',
'Project version': '0.1',
@@ -97,8 +97,8 @@ def test_quickstart_defaults(tempdir):
qs.ask_user(d)
qs.generate(d)
- conffile = tempdir / 'conf.py'
- assert conffile.isfile()
+ conffile = tmp_path / 'conf.py'
+ assert conffile.is_file()
ns = {}
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
assert ns['extensions'] == []
@@ -109,16 +109,16 @@ def test_quickstart_defaults(tempdir):
assert ns['release'] == '0.1'
assert ns['html_static_path'] == ['_static']
- assert (tempdir / '_static').isdir()
- assert (tempdir / '_templates').isdir()
- assert (tempdir / 'index.rst').isfile()
- assert (tempdir / 'Makefile').isfile()
- assert (tempdir / 'make.bat').isfile()
+ assert (tmp_path / '_static').is_dir()
+ assert (tmp_path / '_templates').is_dir()
+ assert (tmp_path / 'index.rst').is_file()
+ assert (tmp_path / 'Makefile').is_file()
+ assert (tmp_path / 'make.bat').is_file()
-def test_quickstart_all_answers(tempdir):
+def test_quickstart_all_answers(tmp_path):
answers = {
- 'Root path': tempdir,
+ 'Root path': str(tmp_path),
'Separate source and build': 'y',
'Name prefix for templates': '.',
'Project name': 'STASI™',
@@ -147,8 +147,8 @@ def test_quickstart_all_answers(tempdir):
qs.ask_user(d)
qs.generate(d)
- conffile = tempdir / 'source' / 'conf.py'
- assert conffile.isfile()
+ conffile = tmp_path / 'source' / 'conf.py'
+ assert conffile.is_file()
ns = {}
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
assert ns['extensions'] == [
@@ -165,15 +165,15 @@ def test_quickstart_all_answers(tempdir):
assert ns['todo_include_todos'] is True
assert ns['html_static_path'] == ['.static']
- assert (tempdir / 'build').isdir()
- assert (tempdir / 'source' / '.static').isdir()
- assert (tempdir / 'source' / '.templates').isdir()
- assert (tempdir / 'source' / 'contents.txt').isfile()
+ assert (tmp_path / 'build').is_dir()
+ assert (tmp_path / 'source' / '.static').is_dir()
+ assert (tmp_path / 'source' / '.templates').is_dir()
+ assert (tmp_path / 'source' / 'contents.txt').is_file()
-def test_generated_files_eol(tempdir):
+def test_generated_files_eol(tmp_path):
answers = {
- 'Root path': tempdir,
+ 'Root path': str(tmp_path),
'Project name': 'Sphinx Test',
'Author name': 'Georg Brandl',
'Project version': '0.1',
@@ -187,13 +187,13 @@ def assert_eol(filename, eol):
content = filename.read_bytes().decode()
assert all(l[-len(eol):] == eol for l in content.splitlines(keepends=True))
- assert_eol(tempdir / 'make.bat', '\r\n')
- assert_eol(tempdir / 'Makefile', '\n')
+ assert_eol(tmp_path / 'make.bat', '\r\n')
+ assert_eol(tmp_path / 'Makefile', '\n')
-def test_quickstart_and_build(tempdir):
+def test_quickstart_and_build(tmp_path):
answers = {
- 'Root path': tempdir,
+ 'Root path': str(tmp_path),
'Project name': 'Fullwidth characters: \u30c9\u30a4\u30c4',
'Author name': 'Georg Brandl',
'Project version': '0.1',
@@ -204,10 +204,10 @@ def test_quickstart_and_build(tempdir):
qs.generate(d)
app = application.Sphinx(
- tempdir, # srcdir
- tempdir, # confdir
- (tempdir / '_build' / 'html'), # outdir
- (tempdir / '_build' / '.doctree'), # doctreedir
+ tmp_path, # srcdir
+ tmp_path, # confdir
+ (tmp_path / '_build' / 'html'), # outdir
+ (tmp_path / '_build' / '.doctree'), # doctreedir
'html', # buildername
status=StringIO(),
warning=warnfile)
@@ -216,9 +216,9 @@ def test_quickstart_and_build(tempdir):
assert not warnings
-def test_default_filename(tempdir):
+def test_default_filename(tmp_path):
answers = {
- 'Root path': tempdir,
+ 'Root path': str(tmp_path),
'Project name': '\u30c9\u30a4\u30c4', # Fullwidth characters only
'Author name': 'Georg Brandl',
'Project version': '0.1',
@@ -228,25 +228,25 @@ def test_default_filename(tempdir):
qs.ask_user(d)
qs.generate(d)
- conffile = tempdir / 'conf.py'
- assert conffile.isfile()
+ conffile = tmp_path / 'conf.py'
+ assert conffile.is_file()
ns = {}
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
-def test_extensions(tempdir):
+def test_extensions(tmp_path):
qs.main(['-q', '-p', 'project_name', '-a', 'author',
- '--extensions', 'foo,bar,baz', tempdir])
+ '--extensions', 'foo,bar,baz', str(tmp_path)])
- conffile = tempdir / 'conf.py'
- assert conffile.isfile()
+ conffile = tmp_path / 'conf.py'
+ assert conffile.is_file()
ns = {}
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
assert ns['extensions'] == ['foo', 'bar', 'baz']
def test_exits_when_existing_confpy(monkeypatch):
- # The code detects existing conf.py with path.isfile()
+ # The code detects existing conf.py with path.is_file()
# so we mock it as True with pytest's monkeypatch
def mock_isfile(path):
return True
diff --git a/tests/test_theming.py b/tests/test_theming.py
index b7ccda95c98..7473cb371c5 100644
--- a/tests/test_theming.py
+++ b/tests/test_theming.py
@@ -27,9 +27,9 @@ def test_theme_api(app, status, warning):
# test Theme class API
assert set(app.registry.html_themes.keys()) == set(themes)
- assert app.registry.html_themes['test-theme'] == app.srcdir / 'test_theme' / 'test-theme'
- assert app.registry.html_themes['ziptheme'] == app.srcdir / 'ziptheme.zip'
- assert app.registry.html_themes['staticfiles'] == app.srcdir / 'test_theme' / 'staticfiles'
+ assert app.registry.html_themes['test-theme'] == str(app.srcdir / 'test_theme' / 'test-theme')
+ assert app.registry.html_themes['ziptheme'] == str(app.srcdir / 'ziptheme.zip')
+ assert app.registry.html_themes['staticfiles'] == str(app.srcdir / 'test_theme' / 'staticfiles')
# test Theme instance API
theme = app.builder.theme
diff --git a/tests/test_util.py b/tests/test_util.py
index bb4f10a8cf6..40a5515071c 100644
--- a/tests/test_util.py
+++ b/tests/test_util.py
@@ -33,10 +33,6 @@ def test_ensuredir():
ensuredir(path)
assert os.path.isdir(path)
- with tempfile.NamedTemporaryFile() as tmp:
- with pytest.raises(OSError):
- ensuredir(tmp.name)
-
def test_import_object():
module = import_object('sphinx')
diff --git a/tests/test_util_fileutil.py b/tests/test_util_fileutil.py
index 7ea12508c61..fea21309aac 100644
--- a/tests/test_util_fileutil.py
+++ b/tests/test_util_fileutil.py
@@ -15,42 +15,42 @@ def __init__(self):
self.init(builder)
-def test_copy_asset_file(tempdir):
+def test_copy_asset_file(tmp_path):
renderer = DummyTemplateLoader()
# copy normal file
- src = (tempdir / 'asset.txt')
+ src = (tmp_path / 'asset.txt')
src.write_text('# test data')
- dest = (tempdir / 'output.txt')
+ dest = (tmp_path / 'output.txt')
copy_asset_file(src, dest)
assert dest.exists()
assert src.read_text(encoding='utf8') == dest.read_text(encoding='utf8')
# copy template file
- src = (tempdir / 'asset.txt_t')
+ src = (tmp_path / 'asset.txt_t')
src.write_text('# {{var1}} data')
- dest = (tempdir / 'output.txt_t')
+ dest = (tmp_path / 'output.txt_t')
- copy_asset_file(src, dest, {'var1': 'template'}, renderer)
+ copy_asset_file(str(src), str(dest), {'var1': 'template'}, renderer)
assert not dest.exists()
- assert (tempdir / 'output.txt').exists()
- assert (tempdir / 'output.txt').read_text(encoding='utf8') == '# template data'
+ assert (tmp_path / 'output.txt').exists()
+ assert (tmp_path / 'output.txt').read_text(encoding='utf8') == '# template data'
# copy template file to subdir
- src = (tempdir / 'asset.txt_t')
+ src = (tmp_path / 'asset.txt_t')
src.write_text('# {{var1}} data')
- subdir1 = (tempdir / 'subdir')
- subdir1.makedirs()
+ subdir1 = (tmp_path / 'subdir')
+ subdir1.mkdir(parents=True, exist_ok=True)
copy_asset_file(src, subdir1, {'var1': 'template'}, renderer)
assert (subdir1 / 'asset.txt').exists()
assert (subdir1 / 'asset.txt').read_text(encoding='utf8') == '# template data'
# copy template file without context
- src = (tempdir / 'asset.txt_t')
- subdir2 = (tempdir / 'subdir2')
- subdir2.makedirs()
+ src = (tmp_path / 'asset.txt_t')
+ subdir2 = (tmp_path / 'subdir2')
+ subdir2.mkdir(parents=True, exist_ok=True)
copy_asset_file(src, subdir2)
assert not (subdir2 / 'asset.txt').exists()
@@ -58,28 +58,28 @@ def test_copy_asset_file(tempdir):
assert (subdir2 / 'asset.txt_t').read_text(encoding='utf8') == '# {{var1}} data'
-def test_copy_asset(tempdir):
+def test_copy_asset(tmp_path):
renderer = DummyTemplateLoader()
# prepare source files
- source = (tempdir / 'source')
- source.makedirs()
+ source = (tmp_path / 'source')
+ source.mkdir(parents=True, exist_ok=True)
(source / 'index.rst').write_text('index.rst', encoding='utf8')
(source / 'foo.rst_t').write_text('{{var1}}.rst', encoding='utf8')
- (source / '_static').makedirs()
+ (source / '_static').mkdir(parents=True, exist_ok=True)
(source / '_static' / 'basic.css').write_text('basic.css', encoding='utf8')
- (source / '_templates').makedirs()
+ (source / '_templates').mkdir(parents=True, exist_ok=True)
(source / '_templates' / 'layout.html').write_text('layout.html', encoding='utf8')
(source / '_templates' / 'sidebar.html_t').write_text('sidebar: {{var2}}', encoding='utf8')
# copy a single file
- assert not (tempdir / 'test1').exists()
- copy_asset(source / 'index.rst', tempdir / 'test1')
- assert (tempdir / 'test1').exists()
- assert (tempdir / 'test1/index.rst').exists()
+ 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()
# copy directories
- destdir = tempdir / 'test2'
+ destdir = tmp_path / 'test2'
copy_asset(source, destdir, context={'var1': 'bar', 'var2': 'baz'}, renderer=renderer)
assert (destdir / 'index.rst').exists()
assert (destdir / 'foo.rst').exists()
@@ -93,7 +93,7 @@ def test_copy_asset(tempdir):
def excluded(path):
return ('sidebar.html' in path or 'basic.css' in path)
- destdir = tempdir / 'test3'
+ destdir = tmp_path / 'test3'
copy_asset(source, destdir, excluded,
context={'var1': 'bar', 'var2': 'baz'}, renderer=renderer)
assert (destdir / 'index.rst').exists()
diff --git a/tests/test_util_i18n.py b/tests/test_util_i18n.py
index 8aae9402847..735ee678852 100644
--- a/tests/test_util_i18n.py
+++ b/tests/test_util_i18n.py
@@ -29,12 +29,12 @@ def test_catalog_info_for_sub_domain_file_and_path():
assert cat.mo_path == os.path.join('path', 'sub/domain.mo')
-def test_catalog_outdated(tempdir):
- (tempdir / 'test.po').write_text('#', encoding='utf8')
- cat = i18n.CatalogInfo(tempdir, 'test', 'utf-8')
+def test_catalog_outdated(tmp_path):
+ (tmp_path / 'test.po').write_text('#', encoding='utf8')
+ cat = i18n.CatalogInfo(tmp_path, 'test', 'utf-8')
assert cat.is_outdated() # if mo is not exist
- mo_file = (tempdir / 'test.mo')
+ mo_file = (tmp_path / 'test.mo')
mo_file.write_text('#', encoding='utf8')
assert not cat.is_outdated() # if mo is exist and newer than po
@@ -42,9 +42,9 @@ def test_catalog_outdated(tempdir):
assert cat.is_outdated() # if mo is exist and older than po
-def test_catalog_write_mo(tempdir):
- (tempdir / 'test.po').write_text('#', encoding='utf8')
- cat = i18n.CatalogInfo(tempdir, 'test', 'utf-8')
+def test_catalog_write_mo(tmp_path):
+ (tmp_path / 'test.po').write_text('#', encoding='utf8')
+ cat = i18n.CatalogInfo(tmp_path, 'test', 'utf-8')
cat.write_mo('en')
assert os.path.exists(cat.mo_path)
with open(cat.mo_path, 'rb') as f:
@@ -147,45 +147,45 @@ def test_get_filename_for_language(app):
'/subdir/en/foo.png')
-def test_CatalogRepository(tempdir):
- (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
- (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#', encoding='utf8')
- (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#', encoding='utf8')
- (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
- (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test3.po').write_text('#', encoding='utf8')
- (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#', encoding='utf8')
- (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / '.dotdir').makedirs()
- (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / '.dotdir' / 'test5.po').write_text('#', encoding='utf8')
- (tempdir / 'loc1' / 'yy' / 'LC_MESSAGES').makedirs()
- (tempdir / 'loc1' / 'yy' / 'LC_MESSAGES' / 'test6.po').write_text('#', encoding='utf8')
- (tempdir / 'loc2' / 'xx' / 'LC_MESSAGES').makedirs()
- (tempdir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#', encoding='utf8')
- (tempdir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test7.po').write_text('#', encoding='utf8')
+def test_CatalogRepository(tmp_path):
+ (tmp_path / 'loc1' / 'xx' / 'LC_MESSAGES').mkdir(parents=True, exist_ok=True)
+ (tmp_path / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#', encoding='utf8')
+ (tmp_path / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#', encoding='utf8')
+ (tmp_path / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').mkdir(parents=True, exist_ok=True)
+ (tmp_path / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test3.po').write_text('#', encoding='utf8')
+ (tmp_path / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#', encoding='utf8')
+ (tmp_path / 'loc1' / 'xx' / 'LC_MESSAGES' / '.dotdir').mkdir(parents=True, exist_ok=True)
+ (tmp_path / 'loc1' / 'xx' / 'LC_MESSAGES' / '.dotdir' / 'test5.po').write_text('#', encoding='utf8')
+ (tmp_path / 'loc1' / 'yy' / 'LC_MESSAGES').mkdir(parents=True, exist_ok=True)
+ (tmp_path / 'loc1' / 'yy' / 'LC_MESSAGES' / 'test6.po').write_text('#', encoding='utf8')
+ (tmp_path / 'loc2' / 'xx' / 'LC_MESSAGES').mkdir(parents=True, exist_ok=True)
+ (tmp_path / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#', encoding='utf8')
+ (tmp_path / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test7.po').write_text('#', encoding='utf8')
# for language xx
- repo = i18n.CatalogRepository(tempdir, ['loc1', 'loc2'], 'xx', 'utf-8')
- assert list(repo.locale_dirs) == [str(tempdir / 'loc1'),
- str(tempdir / 'loc2')]
+ repo = i18n.CatalogRepository(tmp_path, ['loc1', 'loc2'], 'xx', 'utf-8')
+ assert list(repo.locale_dirs) == [str(tmp_path / 'loc1'),
+ str(tmp_path / 'loc2')]
assert all(isinstance(c, i18n.CatalogInfo) for c in repo.catalogs)
assert sorted(c.domain for c in repo.catalogs) == ['sub/test3', 'sub/test4',
'test1', 'test1', 'test2', 'test7']
# for language yy
- repo = i18n.CatalogRepository(tempdir, ['loc1', 'loc2'], 'yy', 'utf-8')
+ repo = i18n.CatalogRepository(tmp_path, ['loc1', 'loc2'], 'yy', 'utf-8')
assert sorted(c.domain for c in repo.catalogs) == ['test6']
# unknown languages
- repo = i18n.CatalogRepository(tempdir, ['loc1', 'loc2'], 'zz', 'utf-8')
+ repo = i18n.CatalogRepository(tmp_path, ['loc1', 'loc2'], 'zz', 'utf-8')
assert sorted(c.domain for c in repo.catalogs) == []
# no languages
- repo = i18n.CatalogRepository(tempdir, ['loc1', 'loc2'], None, 'utf-8')
+ repo = i18n.CatalogRepository(tmp_path, ['loc1', 'loc2'], None, 'utf-8')
assert sorted(c.domain for c in repo.catalogs) == []
# unknown locale_dirs
- repo = i18n.CatalogRepository(tempdir, ['loc3'], None, 'utf-8')
+ repo = i18n.CatalogRepository(tmp_path, ['loc3'], None, 'utf-8')
assert sorted(c.domain for c in repo.catalogs) == []
# no locale_dirs
- repo = i18n.CatalogRepository(tempdir, [], None, 'utf-8')
+ repo = i18n.CatalogRepository(tmp_path, [], None, 'utf-8')
assert sorted(c.domain for c in repo.catalogs) == []
diff --git a/tests/test_util_inventory.py b/tests/test_util_inventory.py
index 2833d979e52..2c2076384af 100644
--- a/tests/test_util_inventory.py
+++ b/tests/test_util_inventory.py
@@ -1,5 +1,5 @@
"""Test inventory util functions."""
-
+import os
import posixpath
import zlib
from io import BytesIO
@@ -88,12 +88,12 @@ def test_read_inventory_v2_not_having_version():
def _write_appconfig(dir, language, prefix=None):
prefix = prefix or language
- (dir / prefix).makedirs()
+ os.makedirs(dir / prefix, exist_ok=True)
(dir / prefix / 'conf.py').write_text(f'language = "{language}"', encoding='utf8')
(dir / prefix / 'index.rst').write_text('index.rst', encoding='utf8')
- assert sorted((dir / prefix).listdir()) == ['conf.py', 'index.rst']
+ assert sorted(os.listdir(dir / prefix)) == ['conf.py', 'index.rst']
assert (dir / prefix / 'index.rst').exists()
- return (dir / prefix)
+ return dir / prefix
def _build_inventory(srcdir):
@@ -103,13 +103,13 @@ def _build_inventory(srcdir):
return (app.outdir / 'objects.inv')
-def test_inventory_localization(tempdir):
+def test_inventory_localization(tmp_path):
# Build an app using Estonian (EE) locale
- srcdir_et = _write_appconfig(tempdir, "et")
+ srcdir_et = _write_appconfig(tmp_path, "et")
inventory_et = _build_inventory(srcdir_et)
# Build the same app using English (US) locale
- srcdir_en = _write_appconfig(tempdir, "en")
+ srcdir_en = _write_appconfig(tmp_path, "en")
inventory_en = _build_inventory(srcdir_en)
# Ensure that the inventory contents differ
diff --git a/tests/test_versioning.py b/tests/test_versioning.py
index 80f1798f65d..ae159dfebac 100644
--- a/tests/test_versioning.py
+++ b/tests/test_versioning.py
@@ -1,6 +1,7 @@
"""Test the versioning implementation."""
import pickle
+import shutil
import pytest
@@ -15,7 +16,7 @@ def _setup_module(rootdir, sphinx_test_tempdir):
global app, original, original_uids
srcdir = sphinx_test_tempdir / 'test-versioning'
if not srcdir.exists():
- (rootdir / 'test-versioning').copytree(srcdir)
+ shutil.copytree(rootdir / 'test-versioning', srcdir)
app = SphinxTestApp(srcdir=srcdir)
app.builder.env.app = app
app.connect('doctree-resolved', on_doctree_resolved)