diff options
Diffstat (limited to 'tests/test_extensions')
-rw-r--r-- | tests/test_extensions/test_ext_apidoc.py | 25 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_autodoc.py | 54 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_autodoc_automodule.py | 16 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_autodoc_configs.py | 31 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_autosummary.py | 38 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_autosummary_imports.py | 49 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_coverage.py | 40 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_graphviz.py | 2 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_imgconverter.py | 4 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_imgmockconverter.py | 2 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_inheritance_diagram.py | 2 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_intersphinx.py | 33 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_math.py | 22 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_todo.py | 2 | ||||
-rw-r--r-- | tests/test_extensions/test_ext_viewcode.py | 4 |
15 files changed, 272 insertions, 52 deletions
diff --git a/tests/test_extensions/test_ext_apidoc.py b/tests/test_extensions/test_ext_apidoc.py index c3c979f..13c43df 100644 --- a/tests/test_extensions/test_ext_apidoc.py +++ b/tests/test_extensions/test_ext_apidoc.py @@ -2,6 +2,7 @@ import os.path from collections import namedtuple +from pathlib import Path import pytest @@ -9,7 +10,7 @@ import sphinx.ext.apidoc from sphinx.ext.apidoc import main as apidoc_main -@pytest.fixture() +@pytest.fixture def apidoc(rootdir, tmp_path, apidoc_params): _, kwargs = apidoc_params coderoot = rootdir / kwargs.get('coderoot', 'test-root') @@ -20,7 +21,7 @@ def apidoc(rootdir, tmp_path, apidoc_params): return namedtuple('apidoc', 'coderoot,outdir')(coderoot, outdir) -@pytest.fixture() +@pytest.fixture def apidoc_params(request): pargs = {} kwargs = {} @@ -661,3 +662,23 @@ def test_no_duplicates(rootdir, tmp_path): finally: sphinx.ext.apidoc.PY_SUFFIXES = original_suffixes + + +def test_remove_old_files(tmp_path: Path): + """Test that old files are removed when using the -r option. + + Also ensure that pre-existing files are not re-written, if unchanged. + This is required to avoid unnecessary rebuilds. + """ + module_dir = tmp_path / 'module' + module_dir.mkdir() + (module_dir / 'example.py').write_text('', encoding='utf8') + gen_dir = tmp_path / 'gen' + gen_dir.mkdir() + (gen_dir / 'other.rst').write_text('', encoding='utf8') + apidoc_main(['-o', str(gen_dir), str(module_dir)]) + assert set(gen_dir.iterdir()) == {gen_dir / 'modules.rst', gen_dir / 'example.rst', gen_dir / 'other.rst'} + example_mtime = (gen_dir / 'example.rst').stat().st_mtime + apidoc_main(['--remove-old', '-o', str(gen_dir), str(module_dir)]) + assert set(gen_dir.iterdir()) == {gen_dir / 'modules.rst', gen_dir / 'example.rst'} + assert (gen_dir / 'example.rst').stat().st_mtime == example_mtime diff --git a/tests/test_extensions/test_ext_autodoc.py b/tests/test_extensions/test_ext_autodoc.py index 54f81f2..e10850b 100644 --- a/tests/test_extensions/test_ext_autodoc.py +++ b/tests/test_extensions/test_ext_autodoc.py @@ -429,7 +429,7 @@ def _assert_getter_works(app, directive, objtype, name, attrs=(), **kw): hooked_members = {s[1] for s in getattr_spy} documented_members = {s[1] for s in processed_signatures} for attr in attrs: - fullname = '.'.join((name, attr)) + fullname = f'{name}.{attr}' assert attr in hooked_members assert fullname not in documented_members, f'{fullname!r} not intercepted' @@ -838,7 +838,7 @@ def test_autodoc_special_members(app): "special-members": None, } if sys.version_info >= (3, 13, 0, 'alpha', 5): - options["exclude-members"] = "__static_attributes__" + options["exclude-members"] = "__static_attributes__,__firstlineno__" actual = do_autodoc(app, 'class', 'target.Class', options) assert list(filter(lambda l: '::' in l, actual)) == [ '.. py:class:: Class(arg)', @@ -1479,7 +1479,7 @@ class _EnumFormatter: return self.entry(name, doc, role='attribute', indent=indent, **rst_options) -@pytest.fixture() +@pytest.fixture def autodoc_enum_options() -> dict[str, object]: """Default autodoc options to use when testing enum's documentation.""" return {"members": None, "undoc-members": None} @@ -2321,18 +2321,62 @@ def test_autodoc_TypeVar(app): @pytest.mark.sphinx('html', testroot='ext-autodoc') def test_autodoc_Annotated(app): - options = {"members": None} + options = {'members': None, 'member-order': 'bysource'} actual = do_autodoc(app, 'module', 'target.annotated', options) assert list(actual) == [ '', '.. py:module:: target.annotated', '', '', - '.. py:function:: hello(name: str) -> None', + '.. py:class:: FuncValidator(func: function)', + ' :module: target.annotated', + '', + '', + '.. py:class:: MaxLen(max_length: int, whitelisted_words: list[str])', + ' :module: target.annotated', + '', + '', + '.. py:data:: ValidatedString', + ' :module: target.annotated', + '', + ' Type alias for a validated string.', + '', + ' alias of :py:class:`~typing.Annotated`\\ [:py:class:`str`, ' + ':py:class:`~target.annotated.FuncValidator`\\ (func=\\ :py:class:`~target.annotated.validate`)]', + '', + '', + ".. py:function:: hello(name: ~typing.Annotated[str, 'attribute']) -> None", + ' :module: target.annotated', + '', + ' docstring', + '', + '', + '.. py:class:: AnnotatedAttributes()', ' :module: target.annotated', '', ' docstring', '', + '', + ' .. py:attribute:: AnnotatedAttributes.name', + ' :module: target.annotated', + " :type: ~typing.Annotated[str, 'attribute']", + '', + ' Docstring about the ``name`` attribute.', + '', + '', + ' .. py:attribute:: AnnotatedAttributes.max_len', + ' :module: target.annotated', + " :type: list[~typing.Annotated[str, ~target.annotated.MaxLen(max_length=10, whitelisted_words=['word_one', 'word_two'])]]", + '', + ' Docstring about the ``max_len`` attribute.', + '', + '', + ' .. py:attribute:: AnnotatedAttributes.validated', + ' :module: target.annotated', + ' :type: ~typing.Annotated[str, ~target.annotated.FuncValidator(func=~target.annotated.validate)]', + '', + ' Docstring about the ``validated`` attribute.', + '', ] diff --git a/tests/test_extensions/test_ext_autodoc_automodule.py b/tests/test_extensions/test_ext_autodoc_automodule.py index 92565ae..c6ced7e 100644 --- a/tests/test_extensions/test_ext_autodoc_automodule.py +++ b/tests/test_extensions/test_ext_autodoc_automodule.py @@ -4,7 +4,9 @@ This tests mainly the Documenters; the auto directives are tested in a test source file translated by test_build. """ +import inspect import sys +import typing import pytest @@ -185,8 +187,22 @@ def test_automodule_inherited_members(app): 'sphinx.missing_module4']}) @pytest.mark.usefixtures("rollback_sysmodules") def test_subclass_of_mocked_object(app): + from sphinx.ext.autodoc.mock import _MockObject sys.modules.pop('target', None) # unload target module to clear the module cache options = {'members': None} actual = do_autodoc(app, 'module', 'target.need_mocks', options) + # ``typing.Any`` is not available at runtime on ``_MockObject.__new__`` + assert '.. py:class:: Inherited(*args: Any, **kwargs: Any)' in actual + + # make ``typing.Any`` available at runtime on ``_MockObject.__new__`` + sig = inspect.signature(_MockObject.__new__) + parameters = sig.parameters.copy() + for name in ('args', 'kwargs'): + parameters[name] = parameters[name].replace(annotation=typing.Any) + sig = sig.replace(parameters=tuple(parameters.values())) + _MockObject.__new__.__signature__ = sig # type: ignore[attr-defined] + + options = {'members': None} + actual = do_autodoc(app, 'module', 'target.need_mocks', options) assert '.. py:class:: Inherited(*args: ~typing.Any, **kwargs: ~typing.Any)' in actual diff --git a/tests/test_extensions/test_ext_autodoc_configs.py b/tests/test_extensions/test_ext_autodoc_configs.py index 6c2af5a..1262b15 100644 --- a/tests/test_extensions/test_ext_autodoc_configs.py +++ b/tests/test_extensions/test_ext_autodoc_configs.py @@ -679,6 +679,10 @@ def test_autodoc_typehints_signature(app): type_o = "~typing.Any | None" else: type_o = "~typing.Any" + if sys.version_info[:2] >= (3, 13): + type_ppp = "pathlib._local.PurePosixPath" + else: + type_ppp = "pathlib.PurePosixPath" options = {"members": None, "undoc-members": None} @@ -703,7 +707,7 @@ def test_autodoc_typehints_signature(app): '', '.. py:data:: CONST3', ' :module: target.typehints', - ' :type: ~pathlib.PurePosixPath', + f' :type: ~{type_ppp}', " :value: PurePosixPath('/a/b/c')", '', ' docstring', @@ -726,7 +730,7 @@ def test_autodoc_typehints_signature(app): '', ' .. py:attribute:: Math.CONST3', ' :module: target.typehints', - ' :type: ~pathlib.PurePosixPath', + f' :type: ~{type_ppp}', " :value: PurePosixPath('/a/b/c')", '', '', @@ -748,7 +752,7 @@ def test_autodoc_typehints_signature(app): '', ' .. py:property:: Math.path', ' :module: target.typehints', - ' :type: ~pathlib.PurePosixPath', + f' :type: ~{type_ppp}', '', '', ' .. py:property:: Math.prop', @@ -773,7 +777,7 @@ def test_autodoc_typehints_signature(app): '', ' docstring', '', - " alias of TypeVar('T', bound=\\ :py:class:`~pathlib.PurePosixPath`)", + f" alias of TypeVar('T', bound=\\ :py:class:`~{type_ppp}`)", '', '', '.. py:function:: complex_func(arg1: str, arg2: List[int], arg3: Tuple[int, ' @@ -802,6 +806,10 @@ def test_autodoc_typehints_signature(app): @pytest.mark.sphinx('html', testroot='ext-autodoc', confoverrides={'autodoc_typehints': "none"}) def test_autodoc_typehints_none(app): + if sys.version_info[:2] >= (3, 13): + type_ppp = "pathlib._local.PurePosixPath" + else: + type_ppp = "pathlib.PurePosixPath" options = {"members": None, "undoc-members": None} actual = do_autodoc(app, 'module', 'target.typehints', options) @@ -887,7 +895,7 @@ def test_autodoc_typehints_none(app): '', ' docstring', '', - " alias of TypeVar('T', bound=\\ :py:class:`~pathlib.PurePosixPath`)", + f" alias of TypeVar('T', bound=\\ :py:class:`~{type_ppp}`)", '', '', '.. py:function:: complex_func(arg1, arg2, arg3=None, *args, **kwargs)', @@ -1417,7 +1425,10 @@ def test_autodoc_typehints_format_fully_qualified(app): type_o = "typing.Any | None" else: type_o = "typing.Any" - + if sys.version_info[:2] >= (3, 13): + type_ppp = "pathlib._local.PurePosixPath" + else: + type_ppp = "pathlib.PurePosixPath" options = {"members": None, "undoc-members": None} actual = do_autodoc(app, 'module', 'target.typehints', options) @@ -1441,7 +1452,7 @@ def test_autodoc_typehints_format_fully_qualified(app): '', '.. py:data:: CONST3', ' :module: target.typehints', - ' :type: pathlib.PurePosixPath', + f' :type: {type_ppp}', " :value: PurePosixPath('/a/b/c')", '', ' docstring', @@ -1464,7 +1475,7 @@ def test_autodoc_typehints_format_fully_qualified(app): '', ' .. py:attribute:: Math.CONST3', ' :module: target.typehints', - ' :type: pathlib.PurePosixPath', + f' :type: {type_ppp}', " :value: PurePosixPath('/a/b/c')", '', '', @@ -1486,7 +1497,7 @@ def test_autodoc_typehints_format_fully_qualified(app): '', ' .. py:property:: Math.path', ' :module: target.typehints', - ' :type: pathlib.PurePosixPath', + f' :type: {type_ppp}', '', '', ' .. py:property:: Math.prop', @@ -1511,7 +1522,7 @@ def test_autodoc_typehints_format_fully_qualified(app): '', ' docstring', '', - " alias of TypeVar('T', bound=\\ :py:class:`pathlib.PurePosixPath`)", + f" alias of TypeVar('T', bound=\\ :py:class:`{type_ppp}`)", '', '', '.. py:function:: complex_func(arg1: str, arg2: List[int], arg3: Tuple[int, ' diff --git a/tests/test_extensions/test_ext_autosummary.py b/tests/test_extensions/test_ext_autosummary.py index d761978..e3f034c 100644 --- a/tests/test_extensions/test_ext_autosummary.py +++ b/tests/test_extensions/test_ext_autosummary.py @@ -506,12 +506,20 @@ def test_autosummary_recursive(app, status, warning): # Check content of recursively generated stub-files content = (app.srcdir / 'generated' / 'package.rst').read_text(encoding='utf8') - assert 'package.module' in content - assert 'package.package' in content - assert 'package.module_importfail' in content + assert 'module' in content + assert 'package' in content + assert 'module_importfail' in content + # we no longer generate fully-qualified module names. + assert 'package.module' not in content + assert 'package.package' not in content + assert 'package.module_importfail' not in content content = (app.srcdir / 'generated' / 'package.package.rst').read_text(encoding='utf8') - assert 'package.package.module' in content + assert 'module' in content + assert 'package.package.module' not in content + + warnings = app.warning.getvalue() + assert 'Summarised items should not include the current module.' not in warnings @pytest.mark.sphinx('dummy', testroot='ext-autosummary-recursive', @@ -545,7 +553,7 @@ def test_autosummary_filename_map(app, status, warning): @pytest.mark.sphinx('latex', **default_kw) def test_autosummary_latex_table_colspec(app, status, warning): app.build(force_all=True) - result = (app.outdir / 'python.tex').read_text(encoding='utf8') + result = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') print(status.getvalue()) print(warning.getvalue()) assert r'\begin{longtable}{\X{1}{2}\X{1}{2}}' in result @@ -599,11 +607,11 @@ def test_autosummary_imported_members(app, status, warning): assert (' .. autosummary::\n' ' \n' ' Bar\n' - ' \n' in module) + ' ' in module) assert (' .. autosummary::\n' ' \n' ' foo\n' - ' \n' in module) + ' ' in module) finally: sys.modules.pop('autosummary_dummy_package', None) @@ -627,7 +635,7 @@ def test_autosummary_module_all(app, status, warning): assert ('.. autosummary::\n' ' :toctree:\n' ' :recursive:\n\n' - ' autosummary_dummy_package_all.extra_dummy_module\n\n' in module) + ' extra_dummy_module\n' in module) finally: sys.modules.pop('autosummary_dummy_package_all', None) @@ -684,3 +692,17 @@ def test_autogen(rootdir, tmp_path): args = ['-o', str(tmp_path), '-t', '.', 'autosummary_templating.txt'] autogen_main(args) assert (tmp_path / 'sphinx.application.TemplateBridge.rst').exists() + + +def test_autogen_remove_old(rootdir, tmp_path): + """Test the ``--remove-old`` option.""" + tmp_path.joinpath('other.rst').write_text('old content') + with chdir(rootdir / 'test-templating'): + args = ['-o', str(tmp_path), '-t', '.', 'autosummary_templating.txt'] + autogen_main(args) + assert set(tmp_path.iterdir()) == { + tmp_path / 'sphinx.application.TemplateBridge.rst', + tmp_path / 'other.rst' + } + autogen_main([*args, '--remove-old']) + assert set(tmp_path.iterdir()) == {tmp_path / 'sphinx.application.TemplateBridge.rst'} diff --git a/tests/test_extensions/test_ext_autosummary_imports.py b/tests/test_extensions/test_ext_autosummary_imports.py new file mode 100644 index 0000000..7420c99 --- /dev/null +++ b/tests/test_extensions/test_ext_autosummary_imports.py @@ -0,0 +1,49 @@ +"""Test autosummary for import cycles.""" + +import pytest +from docutils import nodes + +from sphinx import addnodes +from sphinx.ext.autosummary import autosummary_table +from sphinx.testing.util import assert_node + + +@pytest.mark.sphinx('dummy', testroot='ext-autosummary-import_cycle') +@pytest.mark.usefixtures("rollback_sysmodules") +def test_autosummary_import_cycle(app, warning): + app.build() + + doctree = app.env.get_doctree('index') + app.env.apply_post_transforms(doctree, 'index') + + assert len(list(doctree.findall(nodes.reference))) == 1 + + assert_node(doctree, + (addnodes.index, # [0] + nodes.target, # [1] + nodes.paragraph, # [2] + addnodes.tabular_col_spec, # [3] + [autosummary_table, nodes.table, nodes.tgroup, (nodes.colspec, # [4][0][0][0] + nodes.colspec, # [4][0][0][1] + [nodes.tbody, nodes.row])], # [4][0][0][2][1] + addnodes.index, # [5] + addnodes.desc)) # [6] + assert_node(doctree[4][0][0][2][0], + ([nodes.entry, nodes.paragraph, (nodes.reference, nodes.Text)], nodes.entry)) + assert_node(doctree[4][0][0][2][0][0][0][0], nodes.reference, + refid='spam.eggs.Ham', reftitle='spam.eggs.Ham') + + expected = ( + "Summarised items should not include the current module. " + "Replace 'spam.eggs.Ham' with 'Ham'." + ) + assert expected in app.warning.getvalue() + + +@pytest.mark.sphinx('dummy', testroot='ext-autosummary-module_prefix') +@pytest.mark.usefixtures("rollback_sysmodules") +def test_autosummary_generate_prefixes(app, warning): + app.build() + warnings = app.warning.getvalue() + assert 'Summarised items should not include the current module.' not in warnings + assert warnings == '' diff --git a/tests/test_extensions/test_ext_coverage.py b/tests/test_extensions/test_ext_coverage.py index c9e9ba9..ed7b5ad 100644 --- a/tests/test_extensions/test_ext_coverage.py +++ b/tests/test_extensions/test_ext_coverage.py @@ -10,8 +10,10 @@ def test_build(app, status, warning): app.build(force_all=True) py_undoc = (app.outdir / 'python.txt').read_text(encoding='utf8') - assert py_undoc.startswith('Undocumented Python objects\n' - '===========================\n') + assert py_undoc.startswith( + 'Undocumented Python objects\n' + '===========================\n', + ) assert 'autodoc_target\n--------------\n' in py_undoc assert ' * Class -- missing methods:\n' in py_undoc assert ' * raises\n' in py_undoc @@ -23,8 +25,10 @@ def test_build(app, status, warning): assert "undocumented py" not in status.getvalue() c_undoc = (app.outdir / 'c.txt').read_text(encoding='utf8') - assert c_undoc.startswith('Undocumented C API elements\n' - '===========================\n') + assert c_undoc.startswith( + 'Undocumented C API elements\n' + '===========================\n', + ) assert 'api.h' in c_undoc assert ' * Py_SphinxTest' in c_undoc @@ -54,16 +58,26 @@ Undocumented Python objects Statistics ---------- -+----------------------+----------+--------------+ -| Module | Coverage | Undocumented | -+======================+==========+==============+ -| coverage_not_ignored | 0.00% | 2 | -+----------------------+----------+--------------+ -| TOTAL | 0.00% | 2 | -+----------------------+----------+--------------+ ++---------------------------+----------+--------------+ +| Module | Coverage | Undocumented | ++===========================+==========+==============+ +| grog | 100.00% | 0 | ++---------------------------+----------+--------------+ +| grog.coverage_missing | 100.00% | 0 | ++---------------------------+----------+--------------+ +| grog.coverage_not_ignored | 0.00% | 2 | ++---------------------------+----------+--------------+ +| TOTAL | 0.00% | 2 | ++---------------------------+----------+--------------+ + +grog.coverage_missing +--------------------- -coverage_not_ignored --------------------- +Classes: + * Missing + +grog.coverage_not_ignored +------------------------- Classes: * Documented -- missing methods: diff --git a/tests/test_extensions/test_ext_graphviz.py b/tests/test_extensions/test_ext_graphviz.py index 866a92a..cd1fd92 100644 --- a/tests/test_extensions/test_ext_graphviz.py +++ b/tests/test_extensions/test_ext_graphviz.py @@ -105,7 +105,7 @@ def test_graphviz_svg_html(app, status, warning): def test_graphviz_latex(app, status, warning): app.build(force_all=True) - content = (app.outdir / 'python.tex').read_text(encoding='utf8') + content = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') macro = ('\\\\begin{figure}\\[htbp\\]\n\\\\centering\n\\\\capstart\n\n' '\\\\sphinxincludegraphics\\[\\]{graphviz-\\w+.pdf}\n' '\\\\caption{caption of graph}\\\\label{.*}\\\\end{figure}') diff --git a/tests/test_extensions/test_ext_imgconverter.py b/tests/test_extensions/test_ext_imgconverter.py index c1d2061..fee6593 100644 --- a/tests/test_extensions/test_ext_imgconverter.py +++ b/tests/test_extensions/test_ext_imgconverter.py @@ -5,7 +5,7 @@ import subprocess import pytest -@pytest.fixture() +@pytest.fixture def _if_converter_found(app): image_converter = getattr(app.config, 'image_converter', '') try: @@ -24,7 +24,7 @@ def _if_converter_found(app): def test_ext_imgconverter(app, status, warning): app.build(force_all=True) - content = (app.outdir / 'python.tex').read_text(encoding='utf8') + content = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') # supported image (not converted) assert '\\sphinxincludegraphics{{img}.pdf}' in content diff --git a/tests/test_extensions/test_ext_imgmockconverter.py b/tests/test_extensions/test_ext_imgmockconverter.py index 4c3c64e..c155274 100644 --- a/tests/test_extensions/test_ext_imgmockconverter.py +++ b/tests/test_extensions/test_ext_imgmockconverter.py @@ -7,7 +7,7 @@ import pytest def test_ext_imgmockconverter(app, status, warning): app.build(force_all=True) - content = (app.outdir / 'python.tex').read_text(encoding='utf8') + content = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') # check identical basenames give distinct files assert '\\sphinxincludegraphics{{svgimg}.pdf}' in content diff --git a/tests/test_extensions/test_ext_inheritance_diagram.py b/tests/test_extensions/test_ext_inheritance_diagram.py index c13ccea..45a5ff0 100644 --- a/tests/test_extensions/test_ext_inheritance_diagram.py +++ b/tests/test_extensions/test_ext_inheritance_diagram.py @@ -251,7 +251,7 @@ def test_inheritance_diagram_svg_html(tmp_path, app): def test_inheritance_diagram_latex(app, status, warning): app.build(force_all=True) - content = (app.outdir / 'python.tex').read_text(encoding='utf8') + content = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') pattern = ('\\\\begin{figure}\\[htbp]\n\\\\centering\n\\\\capstart\n\n' '\\\\sphinxincludegraphics\\[\\]{inheritance-\\w+.pdf}\n' diff --git a/tests/test_extensions/test_ext_intersphinx.py b/tests/test_extensions/test_ext_intersphinx.py index ef5a9b1..d475c60 100644 --- a/tests/test_extensions/test_ext_intersphinx.py +++ b/tests/test_extensions/test_ext_intersphinx.py @@ -7,10 +7,8 @@ import pytest from docutils import nodes from sphinx import addnodes +from sphinx.builders.html import INVENTORY_FILENAME from sphinx.ext.intersphinx import ( - INVENTORY_FILENAME, - _get_safe_url, - _strip_basic_auth, fetch_inventory, inspect_main, load_mappings, @@ -18,9 +16,14 @@ from sphinx.ext.intersphinx import ( normalize_intersphinx_mapping, ) from sphinx.ext.intersphinx import setup as intersphinx_setup +from sphinx.ext.intersphinx._load import _get_safe_url, _strip_basic_auth from sphinx.util.console import strip_colors -from tests.test_util.intersphinx_data import INVENTORY_V2, INVENTORY_V2_NO_VERSION +from tests.test_util.intersphinx_data import ( + INVENTORY_V2, + INVENTORY_V2_AMBIGUOUS_TERMS, + INVENTORY_V2_NO_VERSION, +) from tests.utils import http_server @@ -46,8 +49,8 @@ def set_config(app, mapping): app.config.intersphinx_disabled_reftypes = [] -@mock.patch('sphinx.ext.intersphinx.InventoryFile') -@mock.patch('sphinx.ext.intersphinx._read_from_url') +@mock.patch('sphinx.ext.intersphinx._load.InventoryFile') +@mock.patch('sphinx.ext.intersphinx._load._read_from_url') def test_fetch_inventory_redirection(_read_from_url, InventoryFile, app, status, warning): # NoQA: PT019 intersphinx_setup(app) _read_from_url().readline.return_value = b'# Sphinx inventory version 2' @@ -248,6 +251,24 @@ def test_missing_reference_stddomain(tmp_path, app, status, warning): assert rn.astext() == 'The Julia Domain' +def test_ambiguous_reference_warning(tmp_path, app, warning): + inv_file = tmp_path / 'inventory' + inv_file.write_bytes(INVENTORY_V2_AMBIGUOUS_TERMS) + set_config(app, { + 'cmd': ('https://docs.python.org/', str(inv_file)), + }) + + # load the inventory + normalize_intersphinx_mapping(app, app.config) + load_mappings(app) + + # term reference (case insensitive) + node, contnode = fake_node('std', 'term', 'A TERM', 'A TERM') + missing_reference(app, app.env, node, contnode) + + assert 'multiple matches found for std:term:A TERM' in warning.getvalue() + + @pytest.mark.sphinx('html', testroot='ext-intersphinx-cppdomain') def test_missing_reference_cppdomain(tmp_path, app, status, warning): inv_file = tmp_path / 'inventory' diff --git a/tests/test_extensions/test_ext_math.py b/tests/test_extensions/test_ext_math.py index b673f83..80a5ae7 100644 --- a/tests/test_extensions/test_ext_math.py +++ b/tests/test_extensions/test_ext_math.py @@ -127,7 +127,7 @@ def test_math_number_all_mathjax(app, status, warning): def test_math_number_all_latex(app, status, warning): app.build() - content = (app.outdir / 'python.tex').read_text(encoding='utf8') + content = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') macro = (r'\\begin{equation\*}\s*' r'\\begin{split}a\^2\+b\^2=c\^2\\end{split}\s*' r'\\end{equation\*}') @@ -170,7 +170,7 @@ def test_math_eqref_format_html(app, status, warning): def test_math_eqref_format_latex(app, status, warning): app.build(force_all=True) - content = (app.outdir / 'python.tex').read_text(encoding='utf8') + content = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') macro = (r'Referencing equation Eq.\\ref{equation:math:foo} and ' r'Eq.\\ref{equation:math:foo}.') assert re.search(macro, content, re.DOTALL) @@ -194,6 +194,24 @@ def test_mathjax_numfig_html(app, status, warning): @pytest.mark.sphinx('html', testroot='ext-math', + confoverrides={'extensions': ['sphinx.ext.mathjax'], + 'numfig': True, + 'math_numfig': True, + 'math_numsep': '-'}) +def test_mathjax_numsep_html(app, status, warning): + app.build(force_all=True) + + content = (app.outdir / 'math.html').read_text(encoding='utf8') + html = ('<div class="math notranslate nohighlight" id="equation-math-0">\n' + '<span class="eqno">(1-2)') + assert html in content + html = ('<p>Referencing equation <a class="reference internal" ' + 'href="#equation-foo">(1-1)</a> and ' + '<a class="reference internal" href="#equation-foo">(1-1)</a>.</p>') + assert html in content + + +@pytest.mark.sphinx('html', testroot='ext-math', confoverrides={'extensions': ['sphinx.ext.imgmath'], 'numfig': True, 'numfig_secnum_depth': 0, diff --git a/tests/test_extensions/test_ext_todo.py b/tests/test_extensions/test_ext_todo.py index 1903f9f..5acfcac 100644 --- a/tests/test_extensions/test_ext_todo.py +++ b/tests/test_extensions/test_ext_todo.py @@ -89,7 +89,7 @@ def test_todo_valid_link(app, status, warning): # Ensure the LaTeX output is built. app.build(force_all=True) - content = (app.outdir / 'python.tex').read_text(encoding='utf8') + content = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') # Look for the link to foo. Note that there are two of them because the # source document uses todolist twice. We could equally well look for links diff --git a/tests/test_extensions/test_ext_viewcode.py b/tests/test_extensions/test_ext_viewcode.py index b2c6fc0..800904a 100644 --- a/tests/test_extensions/test_ext_viewcode.py +++ b/tests/test_extensions/test_ext_viewcode.py @@ -42,6 +42,7 @@ def check_viewcode_output(app, warning): @pytest.mark.sphinx(testroot='ext-viewcode', freshenv=True, confoverrides={"viewcode_line_numbers": True}) +@pytest.mark.usefixtures("rollback_sysmodules") def test_viewcode_linenos(app, warning): shutil.rmtree(app.outdir / '_modules', ignore_errors=True) app.build(force_all=True) @@ -52,6 +53,7 @@ def test_viewcode_linenos(app, warning): @pytest.mark.sphinx(testroot='ext-viewcode', freshenv=True, confoverrides={"viewcode_line_numbers": False}) +@pytest.mark.usefixtures("rollback_sysmodules") def test_viewcode(app, warning): shutil.rmtree(app.outdir / '_modules', ignore_errors=True) app.build(force_all=True) @@ -61,6 +63,7 @@ def test_viewcode(app, warning): @pytest.mark.sphinx('epub', testroot='ext-viewcode') +@pytest.mark.usefixtures("rollback_sysmodules") def test_viewcode_epub_default(app, status, warning): shutil.rmtree(app.outdir) app.build(force_all=True) @@ -73,6 +76,7 @@ def test_viewcode_epub_default(app, status, warning): @pytest.mark.sphinx('epub', testroot='ext-viewcode', confoverrides={'viewcode_enable_epub': True}) +@pytest.mark.usefixtures("rollback_sysmodules") def test_viewcode_epub_enabled(app, status, warning): app.build(force_all=True) |