Use pathlib in the tests (#13051)

This commit is contained in:
Adam Turner 2024-10-25 22:41:08 +01:00 committed by GitHub
parent 63a4175b53
commit 71c0fcfbc5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 59 additions and 65 deletions

View File

@ -13,9 +13,12 @@ from sphinx.directives import optional_int
from sphinx.locale import __ from sphinx.locale import __
from sphinx.util import logging from sphinx.util import logging
from sphinx.util._lines import parse_line_num_spec from sphinx.util._lines import parse_line_num_spec
from sphinx.util._pathlib import _StrPath
from sphinx.util.docutils import SphinxDirective from sphinx.util.docutils import SphinxDirective
if TYPE_CHECKING: if TYPE_CHECKING:
import os
from docutils.nodes import Element, Node from docutils.nodes import Element, Node
from sphinx.application import Sphinx from sphinx.application import Sphinx
@ -197,8 +200,10 @@ class LiteralIncludeReader:
('diff', 'end-at'), ('diff', 'end-at'),
] ]
def __init__(self, filename: str, options: dict[str, Any], config: Config) -> None: def __init__(
self.filename = filename self, filename: str | os.PathLike[str], options: dict[str, Any], config: Config
) -> None:
self.filename = _StrPath(filename)
self.options = options self.options = options
self.encoding = options.get('encoding', config.source_encoding) self.encoding = options.get('encoding', config.source_encoding)
self.lineno_start = self.options.get('lineno-start', 1) self.lineno_start = self.options.get('lineno-start', 1)
@ -212,8 +217,9 @@ class LiteralIncludeReader:
raise ValueError(msg) raise ValueError(msg)
def read_file( def read_file(
self, filename: str, location: tuple[str, int] | None = None self, filename: str | os.PathLike[str], location: tuple[str, int] | None = None
) -> list[str]: ) -> list[str]:
filename = _StrPath(filename)
try: try:
with open(filename, encoding=self.encoding, errors='strict') as f: with open(filename, encoding=self.encoding, errors='strict') as f:
text = f.read() text = f.read()
@ -222,11 +228,11 @@ class LiteralIncludeReader:
return text.splitlines(True) return text.splitlines(True)
except OSError as exc: except OSError as exc:
msg = __('Include file %r not found or reading it failed') % filename msg = __("Include file '%s' not found or reading it failed") % filename
raise OSError(msg) from exc raise OSError(msg) from exc
except UnicodeError as exc: except UnicodeError as exc:
msg = __( msg = __(
'Encoding %r used for reading included file %r seems to ' "Encoding %r used for reading included file '%s' seems to "
'be wrong, try giving an :encoding: option' 'be wrong, try giving an :encoding: option'
) % (self.encoding, filename) ) % (self.encoding, filename)
raise UnicodeError(msg) from exc raise UnicodeError(msg) from exc

View File

@ -2,13 +2,15 @@
from __future__ import annotations from __future__ import annotations
import os
import tokenize import tokenize
from importlib import import_module from importlib import import_module
from os import path from os import path
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any, Literal
from sphinx.errors import PycodeError from sphinx.errors import PycodeError
from sphinx.pycode.parser import Parser from sphinx.pycode.parser import Parser
from sphinx.util._pathlib import _StrPath
if TYPE_CHECKING: if TYPE_CHECKING:
from inspect import Signature from inspect import Signature
@ -23,7 +25,7 @@ class ModuleAnalyzer:
tags: dict[str, tuple[str, int, int]] tags: dict[str, tuple[str, int, int]]
# cache for analyzer objects -- caches both by module and file name # cache for analyzer objects -- caches both by module and file name
cache: dict[tuple[str, str], Any] = {} cache: dict[tuple[Literal['file', 'module'], str | _StrPath], Any] = {}
@staticmethod @staticmethod
def get_module_source(modname: str) -> tuple[str | None, str | None]: def get_module_source(modname: str) -> tuple[str | None, str | None]:
@ -81,8 +83,9 @@ class ModuleAnalyzer:
@classmethod @classmethod
def for_file( def for_file(
cls: type[ModuleAnalyzer], filename: str, modname: str cls: type[ModuleAnalyzer], filename: str | os.PathLike[str], modname: str
) -> ModuleAnalyzer: ) -> ModuleAnalyzer:
filename = _StrPath(filename)
if ('file', filename) in cls.cache: if ('file', filename) in cls.cache:
return cls.cache['file', filename] return cls.cache['file', filename]
try: try:
@ -114,9 +117,11 @@ class ModuleAnalyzer:
cls.cache['module', modname] = obj cls.cache['module', modname] = obj
return obj return obj
def __init__(self, source: str, modname: str, srcname: str) -> None: def __init__(
self, source: str, modname: str, srcname: str | os.PathLike[str]
) -> None:
self.modname = modname # name of the module self.modname = modname # name of the module
self.srcname = srcname # name of the source file self.srcname = str(srcname) # name of the source file
# cache the source code as well # cache the source code as well
self.code = source self.code = source

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os from pathlib import Path
import mod_resource import mod_resource
import mod_something import mod_something
@ -8,8 +8,6 @@ import mod_something
if __name__ == "__main__": if __name__ == "__main__":
print(f"Hello, world! -> something returns: {mod_something.something()}") print(f"Hello, world! -> something returns: {mod_something.something()}")
res_path = \ res_path = Path(mod_resource.__file__).parent / 'resource.txt'
os.path.join(os.path.dirname(mod_resource.__file__), 'resource.txt') text = res_path.read_text(encoding='utf-8')
with open(res_path, encoding='utf-8') as f:
text = f.read()
print(f"From mod_resource:resource.txt -> {text}") print(f"From mod_resource:resource.txt -> {text}")

View File

@ -1,5 +0,0 @@
import os
def get_path():
return os.path.dirname(os.path.abspath(__file__))

View File

@ -450,8 +450,8 @@ def test_run_epubcheck(app):
if not runnable(['java', '-version']): if not runnable(['java', '-version']):
pytest.skip('Unable to run Java; skipping test') pytest.skip('Unable to run Java; skipping test')
epubcheck = os.environ.get('EPUBCHECK_PATH', '/usr/share/java/epubcheck.jar') epubcheck = Path(os.environ.get('EPUBCHECK_PATH', '/usr/share/java/epubcheck.jar'))
if not os.path.exists(epubcheck): if not epubcheck.exists():
pytest.skip('Could not find epubcheck; skipping test') pytest.skip('Could not find epubcheck; skipping test')
try: try:

View File

@ -1,10 +1,10 @@
"""Test the build process with gettext builder with the test root.""" """Test the build process with gettext builder with the test root."""
import gettext import gettext
import os
import re import re
import subprocess import subprocess
from contextlib import chdir from contextlib import chdir
from pathlib import Path
from subprocess import CalledProcessError from subprocess import CalledProcessError
import pytest import pytest
@ -94,7 +94,7 @@ def test_msgfmt(app):
'msgfmt', 'msgfmt',
'en_US.po', 'en_US.po',
'-o', '-o',
os.path.join('en', 'LC_MESSAGES', 'test_root.mo'), Path('en', 'LC_MESSAGES', 'test_root.mo'),
] ]
subprocess.run(args, capture_output=True, check=True) subprocess.run(args, capture_output=True, check=True)
except OSError: except OSError:

View File

@ -1,7 +1,7 @@
from __future__ import annotations from __future__ import annotations
import os.path
import sys import sys
from pathlib import Path
from typing import Any from typing import Any
import pytest import pytest
@ -52,8 +52,8 @@ EXPECTED_BUILD_MAIN = {
EXPECTED_MAKE_MODE = { EXPECTED_MAKE_MODE = {
'builder': 'html', 'builder': 'html',
'sourcedir': 'source_dir', 'sourcedir': 'source_dir',
'outputdir': os.path.join('build_dir', 'html'), 'outputdir': str(Path('build_dir', 'html')),
'doctreedir': os.path.join('build_dir', 'doctrees'), 'doctreedir': str(Path('build_dir', 'doctrees')),
'filenames': ['filename1', 'filename2'], 'filenames': ['filename1', 'filename2'],
'freshenv': True, 'freshenv': True,
'noconfig': True, 'noconfig': True,

View File

@ -1,7 +1,5 @@
"""Test the code-block directive.""" """Test the code-block directive."""
import os.path
import pytest import pytest
from docutils import nodes from docutils import nodes
@ -257,12 +255,13 @@ def test_LiteralIncludeReader_tabwidth_dedent(testroot):
def test_LiteralIncludeReader_diff(testroot, literal_inc_path): def test_LiteralIncludeReader_diff(testroot, literal_inc_path):
options = {'diff': testroot / 'literal-diff.inc'} literal_diff_path = testroot / 'literal-diff.inc'
options = {'diff': literal_diff_path}
reader = LiteralIncludeReader(literal_inc_path, options, DUMMY_CONFIG) reader = LiteralIncludeReader(literal_inc_path, options, DUMMY_CONFIG)
content, lines = reader.read() content, lines = reader.read()
assert content == ( assert content == (
'--- ' + os.path.join(testroot, 'literal-diff.inc') + '\n' f'--- {literal_diff_path}\n'
'+++ ' + os.path.join(testroot, 'literal.inc') + '\n' f'+++ {literal_inc_path}\n'
'@@ -6,8 +6,8 @@\n' '@@ -6,8 +6,8 @@\n'
' pass\n' ' pass\n'
' \n' ' \n'

View File

@ -1,6 +1,5 @@
"""Test the BuildEnvironment class.""" """Test the BuildEnvironment class."""
import os
import shutil import shutil
from pathlib import Path from pathlib import Path
@ -41,8 +40,8 @@ def test_config_status(make_app, app_params):
# incremental build (config entry changed) # incremental build (config entry changed)
app3 = make_app(*args, confoverrides={'root_doc': 'indexx'}, **kwargs) app3 = make_app(*args, confoverrides={'root_doc': 'indexx'}, **kwargs)
fname = os.path.join(app3.srcdir, 'index.rst') fname = app3.srcdir / 'index.rst'
assert os.path.isfile(fname) assert fname.is_file()
shutil.move(fname, fname[:-4] + 'x.rst') shutil.move(fname, fname[:-4] + 'x.rst')
assert app3.env.config_status == CONFIG_CHANGED assert app3.env.config_status == CONFIG_CHANGED
app3.build() app3.build()

View File

@ -1,6 +1,5 @@
"""Test the sphinx.apidoc module.""" """Test the sphinx.apidoc module."""
import os.path
from collections import namedtuple from collections import namedtuple
from pathlib import Path from pathlib import Path
@ -732,7 +731,7 @@ def test_no_duplicates(rootdir, tmp_path):
apidoc_main(['-o', str(outdir), '-T', str(package), '--implicit-namespaces']) apidoc_main(['-o', str(outdir), '-T', str(package), '--implicit-namespaces'])
# Ensure the module has been documented # Ensure the module has been documented
assert os.path.isfile(outdir / 'fish_licence.rst') assert (outdir / 'fish_licence.rst').is_file()
# Ensure the submodule only appears once # Ensure the submodule only appears once
text = (outdir / 'fish_licence.rst').read_text(encoding='utf-8') text = (outdir / 'fish_licence.rst').read_text(encoding='utf-8')

View File

@ -2,7 +2,9 @@
import platform import platform
import sys import sys
from collections.abc import Iterator
from contextlib import contextmanager from contextlib import contextmanager
from pathlib import Path
import pytest import pytest
@ -19,7 +21,7 @@ IS_PYPY = platform.python_implementation() == 'PyPy'
@contextmanager @contextmanager
def overwrite_file(path, content): def overwrite_file(path: Path, content: str) -> Iterator[None]:
current_content = path.read_bytes() if path.exists() else None current_content = path.read_bytes() if path.exists() else None
try: try:
path.write_text(content, encoding='utf-8') path.write_text(content, encoding='utf-8')

View File

@ -1,9 +1,9 @@
"""Test sphinx.ext.inheritance_diagram extension.""" """Test sphinx.ext.inheritance_diagram extension."""
import os
import re import re
import sys import sys
import zlib import zlib
from pathlib import Path
import pytest import pytest
@ -26,7 +26,7 @@ def test_inheritance_diagram(app):
def new_run(self): def new_run(self):
result = orig_run(self) result = orig_run(self)
node = result[0] node = result[0]
source = os.path.basename(node.document.current_source).replace('.rst', '') source = Path(node.document.current_source).stem
graphs[source] = node['graph'] graphs[source] = node['graph']
return result return result

View File

@ -4,7 +4,6 @@ Runs the text builder in the test root.
""" """
import os import os
import os.path
import re import re
import shutil import shutil
import time import time

View File

@ -1,7 +1,7 @@
"""Test pycode.""" """Test pycode."""
import os
import sys import sys
from pathlib import Path
import pytest import pytest
@ -9,7 +9,7 @@ import sphinx
from sphinx.errors import PycodeError from sphinx.errors import PycodeError
from sphinx.pycode import ModuleAnalyzer from sphinx.pycode import ModuleAnalyzer
SPHINX_MODULE_PATH = os.path.splitext(sphinx.__file__)[0] + '.py' SPHINX_MODULE_PATH = Path(sphinx.__file__).resolve().with_suffix('.py')
def test_ModuleAnalyzer_get_module_source(): def test_ModuleAnalyzer_get_module_source():
@ -40,7 +40,7 @@ def test_ModuleAnalyzer_for_file():
def test_ModuleAnalyzer_for_module(rootdir): def test_ModuleAnalyzer_for_module(rootdir):
analyzer = ModuleAnalyzer.for_module('sphinx') analyzer = ModuleAnalyzer.for_module('sphinx')
assert analyzer.modname == 'sphinx' assert analyzer.modname == 'sphinx'
assert analyzer.srcname in {SPHINX_MODULE_PATH, os.path.abspath(SPHINX_MODULE_PATH)} assert analyzer.srcname == str(SPHINX_MODULE_PATH)
saved_path = sys.path.copy() saved_path = sys.path.copy()
sys.path.insert(0, str(rootdir / 'test-pycode')) sys.path.insert(0, str(rootdir / 'test-pycode'))

View File

@ -3,7 +3,6 @@
import time import time
from collections.abc import Callable from collections.abc import Callable
from io import StringIO from io import StringIO
from os import path
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
@ -260,10 +259,7 @@ def test_extensions(tmp_path):
def test_exits_when_existing_confpy(monkeypatch): def test_exits_when_existing_confpy(monkeypatch):
# The code detects existing conf.py with path.is_file() # The code detects existing conf.py with path.is_file()
# so we mock it as True with pytest's monkeypatch # so we mock it as True with pytest's monkeypatch
def mock_isfile(path): monkeypatch.setattr('os.path.isfile', lambda path: True)
return True
monkeypatch.setattr(path, 'isfile', mock_isfile)
qs.term_input = mock_input({ qs.term_input = mock_input({
'Please enter a new root path (or just Enter to exit)': '', 'Please enter a new root path (or just Enter to exit)': '',

View File

@ -1,16 +1,12 @@
"""Tests util functions.""" """Tests util functions."""
import os
import tempfile
from sphinx.util.osutil import ensuredir from sphinx.util.osutil import ensuredir
def test_ensuredir(): def test_ensuredir(tmp_path):
with tempfile.TemporaryDirectory() as tmp_path: # Does not raise an exception for an existing directory.
# Does not raise an exception for an existing directory. ensuredir(tmp_path)
ensuredir(tmp_path)
path = os.path.join(tmp_path, 'a', 'b', 'c') path = tmp_path / 'a' / 'b' / 'c'
ensuredir(path) ensuredir(path)
assert os.path.isdir(path) assert path.is_dir()

View File

@ -2,12 +2,12 @@
import codecs import codecs
import os import os
import os.path from pathlib import Path
import pytest import pytest
from docutils import nodes from docutils import nodes
from sphinx.util import logging, osutil from sphinx.util import logging
from sphinx.util.console import colorize, strip_colors from sphinx.util.console import colorize, strip_colors
from sphinx.util.logging import is_suppressed_warning, prefixed_warnings from sphinx.util.logging import is_suppressed_warning, prefixed_warnings
from sphinx.util.parallel import ParallelTasks from sphinx.util.parallel import ParallelTasks
@ -360,15 +360,15 @@ def test_get_node_location_abspath():
# Ensure that node locations are reported as an absolute path, # Ensure that node locations are reported as an absolute path,
# even if the source attribute is a relative path. # even if the source attribute is a relative path.
relative_filename = os.path.join('relative', 'path.txt') relative_filename = Path('relative', 'path.txt')
absolute_filename = osutil.abspath(relative_filename) absolute_filename = relative_filename.resolve()
n = nodes.Node() n = nodes.Node()
n.source = relative_filename n.source = str(relative_filename)
location = logging.get_node_location(n) location = logging.get_node_location(n)
assert location == absolute_filename + ':' assert location == f'{absolute_filename}:'
@pytest.mark.sphinx('html', testroot='root', confoverrides={'show_warning_types': True}) @pytest.mark.sphinx('html', testroot='root', confoverrides={'show_warning_types': True})