mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Use pathlib in the tests (#13051)
This commit is contained in:
parent
63a4175b53
commit
71c0fcfbc5
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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}")
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
def get_path():
|
|
||||||
return os.path.dirname(os.path.abspath(__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:
|
||||||
|
@ -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:
|
||||||
|
@ -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,
|
||||||
|
@ -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'
|
||||||
|
@ -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()
|
||||||
|
@ -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')
|
||||||
|
@ -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')
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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'))
|
||||||
|
@ -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)': '',
|
||||||
|
@ -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()
|
||||||
|
@ -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})
|
||||||
|
Loading…
Reference in New Issue
Block a user