diff options
Diffstat (limited to '')
-rw-r--r-- | tests/test_builders/test_build.py | 2 | ||||
-rw-r--r-- | tests/test_builders/test_build_dirhtml.py | 8 | ||||
-rw-r--r-- | tests/test_builders/test_build_epub.py | 11 | ||||
-rw-r--r-- | tests/test_builders/test_build_gettext.py | 51 | ||||
-rw-r--r-- | tests/test_builders/test_build_html.py | 77 | ||||
-rw-r--r-- | tests/test_builders/test_build_html_5_output.py | 33 | ||||
-rw-r--r-- | tests/test_builders/test_build_html_assets.py | 2 | ||||
-rw-r--r-- | tests/test_builders/test_build_html_download.py | 1 | ||||
-rw-r--r-- | tests/test_builders/test_build_html_image.py | 5 | ||||
-rw-r--r-- | tests/test_builders/test_build_latex.py | 166 | ||||
-rw-r--r-- | tests/test_builders/test_build_linkcheck.py | 235 | ||||
-rw-r--r-- | tests/test_builders/test_build_manpage.py | 10 | ||||
-rw-r--r-- | tests/test_builders/test_build_texinfo.py | 10 |
13 files changed, 438 insertions, 173 deletions
diff --git a/tests/test_builders/test_build.py b/tests/test_builders/test_build.py index 3f6d12c..0e649f7 100644 --- a/tests/test_builders/test_build.py +++ b/tests/test_builders/test_build.py @@ -21,7 +21,7 @@ def request_session_head(url, **kwargs): return response -@pytest.fixture() +@pytest.fixture def nonascii_srcdir(request, rootdir, sphinx_test_tempdir): # Build in a non-ASCII source dir test_name = '\u65e5\u672c\u8a9e' diff --git a/tests/test_builders/test_build_dirhtml.py b/tests/test_builders/test_build_dirhtml.py index dc5ab86..93609e3 100644 --- a/tests/test_builders/test_build_dirhtml.py +++ b/tests/test_builders/test_build_dirhtml.py @@ -28,13 +28,13 @@ def test_dirhtml(app, status, warning): invdata = InventoryFile.load(f, 'path/to', posixpath.join) assert 'index' in invdata.get('std:doc') - assert invdata['std:doc']['index'] == ('Python', '', 'path/to/', '-') + assert invdata['std:doc']['index'] == ('Project name not set', '', 'path/to/', '-') assert 'foo/index' in invdata.get('std:doc') - assert invdata['std:doc']['foo/index'] == ('Python', '', 'path/to/foo/', '-') + assert invdata['std:doc']['foo/index'] == ('Project name not set', '', 'path/to/foo/', '-') assert 'index' in invdata.get('std:label') - assert invdata['std:label']['index'] == ('Python', '', 'path/to/#index', '-') + assert invdata['std:label']['index'] == ('Project name not set', '', 'path/to/#index', '-') assert 'foo' in invdata.get('std:label') - assert invdata['std:label']['foo'] == ('Python', '', 'path/to/foo/#foo', 'foo/index') + assert invdata['std:label']['foo'] == ('Project name not set', '', 'path/to/foo/#foo', 'foo/index') diff --git a/tests/test_builders/test_build_epub.py b/tests/test_builders/test_build_epub.py index 6829f22..691ffcc 100644 --- a/tests/test_builders/test_build_epub.py +++ b/tests/test_builders/test_build_epub.py @@ -67,7 +67,7 @@ def test_build_epub(app): # toc.ncx toc = EPUBElementTree.fromstring((app.outdir / 'toc.ncx').read_text(encoding='utf8')) - assert toc.find("./ncx:docTitle/ncx:text").text == 'Python' + assert toc.find("./ncx:docTitle/ncx:text").text == 'Project name not set' # toc.ncx / head meta = list(toc.find("./ncx:head")) @@ -91,11 +91,11 @@ def test_build_epub(app): # content.opf / metadata metadata = opf.find("./idpf:metadata") assert metadata.find("./dc:language").text == 'en' - assert metadata.find("./dc:title").text == 'Python' + assert metadata.find("./dc:title").text == 'Project name not set' assert metadata.find("./dc:description").text == 'unknown' - assert metadata.find("./dc:creator").text == 'unknown' + assert metadata.find("./dc:creator").text == 'Author name not set' assert metadata.find("./dc:contributor").text == 'unknown' - assert metadata.find("./dc:publisher").text == 'unknown' + assert metadata.find("./dc:publisher").text == 'Author name not set' assert metadata.find("./dc:rights").text is None assert metadata.find("./idpf:meta[@property='ibooks:version']").text is None assert metadata.find("./idpf:meta[@property='ibooks:specified-fonts']").text == 'true' @@ -171,7 +171,7 @@ def test_nested_toc(app): # toc.ncx toc = EPUBElementTree.fromstring((app.outdir / 'toc.ncx').read_bytes()) - assert toc.find("./ncx:docTitle/ncx:text").text == 'Python' + assert toc.find("./ncx:docTitle/ncx:text").text == 'Project name not set' # toc.ncx / navPoint def navinfo(elem): @@ -409,6 +409,7 @@ def test_copy_images(app, status, warning): images = {image.name for image in images_dir.rglob('*')} images.discard('python-logo.png') assert images == { + # 'ba30773957c3fe046897111afd65a80b81cad089.png', # epub: image from data:image/png URI in source 'img.png', 'rimg.png', 'rimg1.png', diff --git a/tests/test_builders/test_build_gettext.py b/tests/test_builders/test_build_gettext.py index ddc6d30..dc8f4c9 100644 --- a/tests/test_builders/test_build_gettext.py +++ b/tests/test_builders/test_build_gettext.py @@ -16,13 +16,12 @@ if sys.version_info[:2] >= (3, 11): else: from sphinx.util.osutil import _chdir as chdir -_MSGID_PATTERN = re.compile(r'msgid "(.*)"') +_MSGID_PATTERN = re.compile(r'msgid "((?:\n|.)*?)"\nmsgstr', re.MULTILINE) -def msgid_getter(msgid): - if m := _MSGID_PATTERN.search(msgid): - return m[1] - return None +def get_msgids(pot): + matches = _MSGID_PATTERN.findall(pot) + return [m.replace('"\n"', '') for m in matches[1:]] def test_Catalog_duplicated_message(): @@ -105,7 +104,7 @@ def test_gettext_index_entries(app): app.build(filenames=[app.srcdir / 'index_entries.txt']) pot = (app.outdir / 'index_entries.pot').read_text(encoding='utf8') - msg_ids = list(filter(None, map(msgid_getter, pot.splitlines()))) + msg_ids = get_msgids(pot) assert msg_ids == [ "i18n with index entries", @@ -134,7 +133,7 @@ def test_gettext_disable_index_entries(app): app.build(filenames=[app.srcdir / 'index_entries.txt']) pot = (app.outdir / 'index_entries.pot').read_text(encoding='utf8') - msg_ids = list(filter(None, map(msgid_getter, pot.splitlines()))) + msg_ids = get_msgids(pot) assert msg_ids == [ "i18n with index entries", @@ -200,7 +199,7 @@ def test_gettext_prolog_epilog_substitution(app): assert (app.outdir / 'prolog_epilog_substitution.pot').is_file() pot = (app.outdir / 'prolog_epilog_substitution.pot').read_text(encoding='utf8') - msg_ids = list(filter(None, map(msgid_getter, pot.splitlines()))) + msg_ids = get_msgids(pot) assert msg_ids == [ "i18n with prologue and epilogue substitutions", @@ -227,9 +226,43 @@ def test_gettext_prolog_epilog_substitution_excluded(app): assert (app.outdir / 'prolog_epilog_substitution_excluded.pot').is_file() pot = (app.outdir / 'prolog_epilog_substitution_excluded.pot').read_text(encoding='utf8') - msg_ids = list(filter(None, map(msgid_getter, pot.splitlines()))) + msg_ids = get_msgids(pot) assert msg_ids == [ "i18n without prologue and epilogue substitutions", "This is content that does not include prologue and epilogue substitutions.", ] + + +@pytest.mark.sphinx( + 'gettext', srcdir='gettext', + confoverrides={'gettext_compact': False, + 'gettext_additional_targets': ['literal-block', 'doctest-block']}) +def test_gettext_literalblock_additional(app): + app.build(force_all=True) + + assert (app.outdir / 'literalblock.pot').is_file() + pot = (app.outdir / 'literalblock.pot').read_text(encoding='utf8') + msg_ids = get_msgids(pot) + + assert msg_ids == [ + 'i18n with literal block', + 'Correct literal block::', + 'this is\\nliteral block', + 'Missing literal block::', + "That's all.", + 'included raw.txt', + '===\\nRaw\\n===\\n\\n.. raw:: html\\n\\n <iframe src=\\"https://sphinx-doc.org\\"></iframe>\\n\\n', + 'code blocks', + "def main\\n 'result'\\nend", + '#include <stdlib.h>\\nint main(int argc, char** argv)\\n{\\n return 0;\\n}', + 'example of C language', + '#include <stdio.h>\\nint main(int argc, char** argv)\\n{\\n return 0;\\n}', + 'literal-block\\nin list', + 'test_code_for_noqa()\\ncontinued()', + 'doctest blocks', + '>>> import sys # sys importing\\n>>> def main(): # define main ' + "function\\n... sys.stdout.write('hello') # call write method of " + "stdout object\\n>>>\\n>>> if __name__ == '__main__': # if run this py " + 'file as python script\\n... main() # call main', + ] diff --git a/tests/test_builders/test_build_html.py b/tests/test_builders/test_build_html.py index 1fa3ba4..8db0790 100644 --- a/tests/test_builders/test_build_html.py +++ b/tests/test_builders/test_build_html.py @@ -1,5 +1,6 @@ """Test the HTML builder and check output against XPath.""" +import contextlib import os import posixpath import re @@ -8,7 +9,7 @@ import pytest from sphinx.builders.html import validate_html_extra_path, validate_html_static_path from sphinx.deprecation import RemovedInSphinx80Warning -from sphinx.errors import ConfigError +from sphinx.errors import ConfigError, ThemeError from sphinx.util.console import strip_colors from sphinx.util.inventory import InventoryFile @@ -16,6 +17,31 @@ from tests.test_builders.xpath_data import FIGURE_CAPTION from tests.test_builders.xpath_util import check_xpath +def test_html_sidebars_error(make_app, tmp_path): + (tmp_path / 'conf.py').touch() + (tmp_path / 'index.rst').touch() + app = make_app( + buildername='html', + srcdir=tmp_path, + confoverrides={'html_sidebars': {'index': 'searchbox.html'}}, + ) + + # Test that the error is logged + warnings = app.warning.getvalue() + assert ("ERROR: Values in 'html_sidebars' must be a list of strings. " + "At least one pattern has a string value: 'index'. " + "Change to `html_sidebars = {'index': ['searchbox.html']}`.") in warnings + + # But that the value is unchanged. + # (Remove this bit of the test in Sphinx 8) + def _html_context_hook(app, pagename, templatename, context, doctree): + assert context["sidebars"] == 'searchbox.html' + app.connect('html-page-context', _html_context_hook) + with contextlib.suppress(ThemeError): + # ignore template rendering issues (ThemeError). + app.build() + + def test_html4_error(make_app, tmp_path): (tmp_path / 'conf.py').write_text('', encoding='utf-8') with pytest.raises( @@ -131,24 +157,24 @@ def test_html_inventory(app): 'py-modindex', 'genindex', 'search'} - assert invdata['std:label']['modindex'] == ('Python', + assert invdata['std:label']['modindex'] == ('Project name not set', '', 'https://www.google.com/py-modindex.html', 'Module Index') - assert invdata['std:label']['py-modindex'] == ('Python', + assert invdata['std:label']['py-modindex'] == ('Project name not set', '', 'https://www.google.com/py-modindex.html', 'Python Module Index') - assert invdata['std:label']['genindex'] == ('Python', + assert invdata['std:label']['genindex'] == ('Project name not set', '', 'https://www.google.com/genindex.html', 'Index') - assert invdata['std:label']['search'] == ('Python', + assert invdata['std:label']['search'] == ('Project name not set', '', 'https://www.google.com/search.html', 'Search Page') assert set(invdata['std:doc'].keys()) == {'index'} - assert invdata['std:doc']['index'] == ('Python', + assert invdata['std:doc']['index'] == ('Project name not set', '', 'https://www.google.com/index.html', 'The basic Sphinx documentation for testing') @@ -222,8 +248,8 @@ def test_html_sidebar(app, status, warning): app.build(force_all=True) result = (app.outdir / 'index.html').read_text(encoding='utf8') assert ('<div class="sphinxsidebar" role="navigation" ' - 'aria-label="main navigation">' in result) - assert '<h1 class="logo"><a href="#">Python</a></h1>' in result + 'aria-label="Main">' in result) + assert '<h1 class="logo"><a href="#">Project name not set</a></h1>' in result assert '<h3>Navigation</h3>' in result assert '<h3>Related Topics</h3>' in result assert '<h3 id="searchlabel">Quick search</h3>' in result @@ -237,7 +263,7 @@ def test_html_sidebar(app, status, warning): app.build(force_all=True) result = (app.outdir / 'index.html').read_text(encoding='utf8') assert ('<div class="sphinxsidebar" role="navigation" ' - 'aria-label="main navigation">' in result) + 'aria-label="Main">' in result) assert '<h1 class="logo"><a href="#">Python</a></h1>' not in result assert '<h3>Navigation</h3>' not in result assert '<h3>Related Topics</h3>' in result @@ -251,7 +277,7 @@ def test_html_sidebar(app, status, warning): app.build(force_all=True) result = (app.outdir / 'index.html').read_text(encoding='utf8') assert ('<div class="sphinxsidebar" role="navigation" ' - 'aria-label="main navigation">' not in result) + 'aria-label="Main">' not in result) assert '<h1 class="logo"><a href="#">Python</a></h1>' not in result assert '<h3>Navigation</h3>' not in result assert '<h3>Related Topics</h3>' not in result @@ -376,3 +402,34 @@ def test_html_remove_sources_before_write_gh_issue_10786(app, warning): file = os.fsdecode(target) assert f'WARNING: cannot copy image file {file!r}: {file!s} does not exist' == ws[-1] + + +@pytest.mark.sphinx('html', testroot='domain-py-python_maximum_signature_line_length', + confoverrides={'python_maximum_signature_line_length': 1}) +def test_html_pep_695_one_type_per_line(app, cached_etree_parse): + app.build() + fname = app.outdir / 'index.html' + etree = cached_etree_parse(fname) + + class chk: + def __init__(self, expect): + self.expect = expect + + def __call__(self, nodes): + assert len(nodes) == 1, nodes + objnode = ''.join(nodes[0].itertext()).replace('\n\n', '') + objnode = objnode.rstrip(chr(182)) # remove '¶' symbol + objnode = objnode.strip('\n') # remove surrounding new lines + assert objnode == self.expect + + # each signature has a dangling ',' at the end of its parameters lists + check_xpath(etree, fname, r'.//dt[@id="generic_foo"][1]', + chk('generic_foo[\nT,\n]()')) + check_xpath(etree, fname, r'.//dt[@id="generic_bar"][1]', + chk('generic_bar[\nT,\n](\nx: list[T],\n)')) + check_xpath(etree, fname, r'.//dt[@id="generic_ret"][1]', + chk('generic_ret[\nR,\n]() → R')) + check_xpath(etree, fname, r'.//dt[@id="MyGenericClass"][1]', + chk('class MyGenericClass[\nX,\n]')) + check_xpath(etree, fname, r'.//dt[@id="MyList"][1]', + chk('class MyList[\nT,\n](list[T])')) diff --git a/tests/test_builders/test_build_html_5_output.py b/tests/test_builders/test_build_html_5_output.py index ece6f49..388c324 100644 --- a/tests/test_builders/test_build_html_5_output.py +++ b/tests/test_builders/test_build_html_5_output.py @@ -3,6 +3,7 @@ import re import pytest +from docutils import nodes from tests.test_builders.xpath_util import check_xpath @@ -25,6 +26,9 @@ def tail_check(check): ('images.html', ".//img[@src='_images/simg.png']", ''), ('images.html', ".//img[@src='_images/svgimg.svg']", ''), ('images.html', ".//a[@href='_sources/images.txt']", ''), + # Check svg options + ('images.html', ".//img[@src='_images/svgimg.svg'][@style='width: 2cm;']", ''), + ('images.html', ".//img[@src='_images/svgimg.svg'][@style='height: 2cm;']", ''), ('subdir/images.html', ".//img[@src='../_images/img1.png']", ''), ('subdir/images.html', ".//img[@src='../_images/rimg.png']", ''), @@ -255,6 +259,8 @@ def tail_check(check): ('extensions.html', ".//a[@href='https://python.org/dev/']", "https://python.org/dev/"), ('extensions.html', ".//a[@href='https://bugs.python.org/issue1000']", "issue 1000"), ('extensions.html', ".//a[@href='https://bugs.python.org/issue1042']", "explicit caption"), + ('extensions.html', ".//a[@class='extlink-pyurl reference external']", "https://python.org/dev/"), + ('extensions.html', ".//a[@class='extlink-issue reference external']", "issue 1000"), # index entries ('genindex.html', ".//a/strong", "Main"), @@ -270,7 +276,32 @@ def tail_check(check): ]) @pytest.mark.sphinx('html', tags=['testtag'], confoverrides={'html_context.hckey_co': 'hcval_co'}) -@pytest.mark.test_params(shared_result='test_build_html_output') def test_html5_output(app, cached_etree_parse, fname, path, check): app.build() check_xpath(cached_etree_parse(app.outdir / fname), fname, path, check) + + +@pytest.mark.sphinx('html', testroot='markup-rubric') +def test_html5_rubric(app): + def insert_invalid_rubric_heading_level(app, doctree, docname): + if docname != 'index': + return + new_node = nodes.rubric('', 'INSERTED RUBRIC') + new_node['heading-level'] = 7 + doctree[0].append(new_node) + + app.connect('doctree-resolved', insert_invalid_rubric_heading_level) + app.build() + + warnings = app.warning.getvalue() + content = (app.outdir / 'index.html').read_text(encoding='utf8') + assert '<p class="rubric">This is a rubric</p>' in content + assert '<h2 class="myclass rubric">A rubric with a heading level 2</h2>' in content + + # directive warning + assert '"7" unknown' in warnings + + # html writer warning + assert 'WARNING: unsupported rubric heading level: 7' in warnings + assert '</h7>' not in content + assert '<p class="rubric">INSERTED RUBRIC</p>' in content diff --git a/tests/test_builders/test_build_html_assets.py b/tests/test_builders/test_build_html_assets.py index fc7a987..e2c7c75 100644 --- a/tests/test_builders/test_build_html_assets.py +++ b/tests/test_builders/test_build_html_assets.py @@ -34,7 +34,7 @@ def test_html_assets(app): # html_extra_path assert (app.outdir / '.htaccess').exists() assert not (app.outdir / '.htpasswd').exists() - assert (app.outdir / 'API.html_t').exists() + assert (app.outdir / 'API.html.jinja').exists() assert (app.outdir / 'css/style.css').exists() assert (app.outdir / 'rimg.png').exists() assert not (app.outdir / '_build' / 'index.html').exists() diff --git a/tests/test_builders/test_build_html_download.py b/tests/test_builders/test_build_html_download.py index 1201c66..14332d8 100644 --- a/tests/test_builders/test_build_html_download.py +++ b/tests/test_builders/test_build_html_download.py @@ -5,7 +5,6 @@ import pytest @pytest.mark.sphinx('html') -@pytest.mark.test_params(shared_result='test_build_html_output') def test_html_download(app): app.build() diff --git a/tests/test_builders/test_build_html_image.py b/tests/test_builders/test_build_html_image.py index 08ed618..860beb6 100644 --- a/tests/test_builders/test_build_html_image.py +++ b/tests/test_builders/test_build_html_image.py @@ -29,7 +29,7 @@ def test_html_remote_logo(app, status, warning): app.build(force_all=True) result = (app.outdir / 'index.html').read_text(encoding='utf8') - assert ('<img class="logo" src="https://www.python.org/static/img/python-logo.png" alt="Logo"/>' in result) + assert ('<img class="logo" src="https://www.python.org/static/img/python-logo.png" alt="Logo of Project name not set"/>' in result) assert ('<link rel="icon" href="https://www.python.org/static/favicon.ico"/>' in result) assert not (app.outdir / 'python-logo.png').exists() @@ -39,7 +39,7 @@ def test_html_local_logo(app, status, warning): app.build(force_all=True) result = (app.outdir / 'index.html').read_text(encoding='utf8') - assert ('<img class="logo" src="_static/img.png" alt="Logo"/>' in result) + assert ('<img class="logo" src="_static/img.png" alt="Logo of Project name not set"/>' in result) assert (app.outdir / '_static/img.png').exists() @@ -72,6 +72,7 @@ def test_copy_images(app, status, warning): images_dir = Path(app.outdir) / '_images' images = {image.name for image in images_dir.rglob('*')} assert images == { + # 'ba30773957c3fe046897111afd65a80b81cad089.png', # html: image from data:image/png URI in source 'img.png', 'rimg.png', 'rimg1.png', diff --git a/tests/test_builders/test_build_latex.py b/tests/test_builders/test_build_latex.py index 0776c74..56505b4 100644 --- a/tests/test_builders/test_build_latex.py +++ b/tests/test_builders/test_build_latex.py @@ -41,7 +41,7 @@ def kpsetest(*filenames): # compile latex document with app.config.latex_engine -def compile_latex_document(app, filename='python.tex', docclass='manual'): +def compile_latex_document(app, filename='projectnamenotset.tex', docclass='manual'): # now, try to run latex over it try: with chdir(app.outdir): @@ -158,21 +158,21 @@ def test_writer(app, status, warning): assert ('\\begin{wrapfigure}{r}{0pt}\n\\centering\n' '\\noindent\\sphinxincludegraphics{{rimg}.png}\n' - '\\caption{figure with align option}\\label{\\detokenize{markup:id9}}' + '\\caption{figure with align option}\\label{\\detokenize{markup:id10}}' '\\end{wrapfigure}\n\n' '\\mbox{}\\par\\vskip-\\dimexpr\\baselineskip+\\parskip\\relax' in result) assert ('\\begin{wrapfigure}{r}{0.500\\linewidth}\n\\centering\n' '\\noindent\\sphinxincludegraphics{{rimg}.png}\n' '\\caption{figure with align \\& figwidth option}' - '\\label{\\detokenize{markup:id10}}' + '\\label{\\detokenize{markup:id11}}' '\\end{wrapfigure}\n\n' '\\mbox{}\\par\\vskip-\\dimexpr\\baselineskip+\\parskip\\relax' in result) assert ('\\begin{wrapfigure}{r}{3cm}\n\\centering\n' '\\noindent\\sphinxincludegraphics[width=3cm]{{rimg}.png}\n' '\\caption{figure with align \\& width option}' - '\\label{\\detokenize{markup:id11}}' + '\\label{\\detokenize{markup:id12}}' '\\end{wrapfigure}\n\n' '\\mbox{}\\par\\vskip-\\dimexpr\\baselineskip+\\parskip\\relax' in result) @@ -255,7 +255,7 @@ def test_latex_basic_howto_ja(app, status, warning): @pytest.mark.sphinx('latex', testroot='latex-theme') def test_latex_theme(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(result) assert r'\def\sphinxdocclass{book}' in result assert r'\documentclass[a4paper,12pt,english]{sphinxbook}' in result @@ -266,7 +266,7 @@ def test_latex_theme(app, status, warning): 'pointsize': '9pt'}}) def test_latex_theme_papersize(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(result) assert r'\def\sphinxdocclass{book}' in result assert r'\documentclass[b5paper,9pt,english]{sphinxbook}' in result @@ -277,7 +277,7 @@ def test_latex_theme_papersize(app, status, warning): 'pointsize': '9pt'}}) def test_latex_theme_options(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(result) assert r'\def\sphinxdocclass{book}' in result assert r'\documentclass[b5paper,9pt,english]{sphinxbook}' in result @@ -330,7 +330,7 @@ def test_latex_release(app, status, warning): confoverrides={'numfig': True}) def test_numref(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -372,7 +372,7 @@ def test_numref(app, status, warning): 'section': 'SECTION-%s'}}) def test_numref_with_prefix1(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -420,7 +420,7 @@ def test_numref_with_prefix1(app, status, warning): 'section': 'SECTION_%s_'}}) def test_numref_with_prefix2(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -460,7 +460,7 @@ def test_numref_with_prefix2(app, status, warning): confoverrides={'numfig': True, 'language': 'ja'}) def test_numref_with_language_ja(app, status, warning): app.build() - result = (app.outdir / 'python.tex').read_text(encoding='utf8') + result = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') print(result) print(status.getvalue()) print(warning.getvalue()) @@ -556,7 +556,7 @@ def test_latex_add_latex_package(app, status, warning): @pytest.mark.sphinx('latex', testroot='latex-babel') def test_babel_with_no_language_settings(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -581,7 +581,7 @@ def test_babel_with_no_language_settings(app, status, warning): confoverrides={'language': 'de'}) def test_babel_with_language_de(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -606,7 +606,7 @@ def test_babel_with_language_de(app, status, warning): confoverrides={'language': 'ru'}) def test_babel_with_language_ru(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -631,7 +631,7 @@ def test_babel_with_language_ru(app, status, warning): confoverrides={'language': 'tr'}) def test_babel_with_language_tr(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -656,7 +656,7 @@ def test_babel_with_language_tr(app, status, warning): confoverrides={'language': 'ja'}) def test_babel_with_language_ja(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -680,7 +680,7 @@ def test_babel_with_language_ja(app, status, warning): confoverrides={'language': 'unknown'}) def test_babel_with_unknown_language(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -707,7 +707,7 @@ def test_babel_with_unknown_language(app, status, warning): confoverrides={'language': 'de', 'latex_engine': 'lualatex'}) def test_polyglossia_with_language_de(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -733,7 +733,7 @@ def test_polyglossia_with_language_de(app, status, warning): confoverrides={'language': 'de-1901', 'latex_engine': 'lualatex'}) def test_polyglossia_with_language_de_1901(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -786,7 +786,7 @@ def test_footnote(app, status, warning): @pytest.mark.sphinx('latex', testroot='footnotes') def test_reference_in_caption_and_codeblock_in_footnote(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -826,7 +826,7 @@ def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning): @pytest.mark.sphinx('latex', testroot='footnotes') def test_footnote_referred_multiple_times(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -848,7 +848,7 @@ def test_footnote_referred_multiple_times(app, status, warning): confoverrides={'latex_show_urls': 'inline'}) def test_latex_show_urls_is_inline(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -905,7 +905,7 @@ def test_latex_show_urls_is_inline(app, status, warning): confoverrides={'latex_show_urls': 'footnote'}) def test_latex_show_urls_is_footnote(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -967,7 +967,7 @@ def test_latex_show_urls_is_footnote(app, status, warning): confoverrides={'latex_show_urls': 'no'}) def test_latex_show_urls_is_no(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1022,7 +1022,7 @@ def test_latex_show_urls_footnote_and_substitutions(app, status, warning): @pytest.mark.sphinx('latex', testroot='image-in-section') def test_image_in_section(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1045,7 +1045,7 @@ def test_latex_logo_if_not_found(app, status, warning): @pytest.mark.sphinx('latex', testroot='toctree-maxdepth') def test_toctree_maxdepth_manual(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1057,12 +1057,12 @@ def test_toctree_maxdepth_manual(app, status, warning): @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', confoverrides={'latex_documents': [ - ('index', 'python.tex', 'Sphinx Tests Documentation', + ('index', 'projectnamenotset.tex', 'Sphinx Tests Documentation', 'Georg Brandl', 'howto'), ]}) def test_toctree_maxdepth_howto(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1076,7 +1076,7 @@ def test_toctree_maxdepth_howto(app, status, warning): confoverrides={'root_doc': 'foo'}) def test_toctree_not_found(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1090,7 +1090,7 @@ def test_toctree_not_found(app, status, warning): confoverrides={'root_doc': 'bar'}) def test_toctree_without_maxdepth(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1103,7 +1103,7 @@ def test_toctree_without_maxdepth(app, status, warning): confoverrides={'root_doc': 'qux'}) def test_toctree_with_deeper_maxdepth(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1116,7 +1116,7 @@ def test_toctree_with_deeper_maxdepth(app, status, warning): confoverrides={'latex_toplevel_sectioning': None}) def test_latex_toplevel_sectioning_is_None(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1128,7 +1128,7 @@ def test_latex_toplevel_sectioning_is_None(app, status, warning): confoverrides={'latex_toplevel_sectioning': 'part'}) def test_latex_toplevel_sectioning_is_part(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1141,12 +1141,12 @@ def test_latex_toplevel_sectioning_is_part(app, status, warning): 'latex', testroot='toctree-maxdepth', confoverrides={'latex_toplevel_sectioning': 'part', 'latex_documents': [ - ('index', 'python.tex', 'Sphinx Tests Documentation', + ('index', 'projectnamenotset.tex', 'Sphinx Tests Documentation', 'Georg Brandl', 'howto'), ]}) def test_latex_toplevel_sectioning_is_part_with_howto(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1160,7 +1160,7 @@ def test_latex_toplevel_sectioning_is_part_with_howto(app, status, warning): confoverrides={'latex_toplevel_sectioning': 'chapter'}) def test_latex_toplevel_sectioning_is_chapter(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1171,12 +1171,12 @@ def test_latex_toplevel_sectioning_is_chapter(app, status, warning): 'latex', testroot='toctree-maxdepth', confoverrides={'latex_toplevel_sectioning': 'chapter', 'latex_documents': [ - ('index', 'python.tex', 'Sphinx Tests Documentation', + ('index', 'projectnamenotset.tex', 'Sphinx Tests Documentation', 'Georg Brandl', 'howto'), ]}) def test_latex_toplevel_sectioning_is_chapter_with_howto(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1188,7 +1188,7 @@ def test_latex_toplevel_sectioning_is_chapter_with_howto(app, status, warning): confoverrides={'latex_toplevel_sectioning': 'section'}) def test_latex_toplevel_sectioning_is_section(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(result) print(status.getvalue()) print(warning.getvalue()) @@ -1199,11 +1199,11 @@ def test_latex_toplevel_sectioning_is_section(app, status, warning): @pytest.mark.sphinx('latex', testroot='maxlistdepth') def test_maxlistdepth_at_ten(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(result) print(status.getvalue()) print(warning.getvalue()) - compile_latex_document(app, 'python.tex') + compile_latex_document(app, 'projectnamenotset.tex') @pytest.mark.sphinx('latex', testroot='latex-table', @@ -1211,7 +1211,7 @@ def test_maxlistdepth_at_ten(app, status, warning): @pytest.mark.test_params(shared_result='latex-table') def test_latex_table_tabulars(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') tables = {} for chap in re.split(r'\\(?:section|chapter){', result)[1:]: sectname, content = chap.split('}', 1) @@ -1282,7 +1282,7 @@ def test_latex_table_tabulars(app, status, warning): @pytest.mark.test_params(shared_result='latex-table') def test_latex_table_longtable(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') tables = {} for chap in re.split(r'\\(?:section|chapter){', result)[1:]: sectname, content = chap.split('}', 1) @@ -1343,7 +1343,7 @@ def test_latex_table_longtable(app, status, warning): @pytest.mark.test_params(shared_result='latex-table') def test_latex_table_complex_tables(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') tables = {} for chap in re.split(r'\\(?:section|renewcommand){', result)[1:]: sectname, content = chap.split('}', 1) @@ -1373,7 +1373,7 @@ def test_latex_table_complex_tables(app, status, warning): @pytest.mark.sphinx('latex', testroot='latex-table') def test_latex_table_with_booktabs_and_colorrows(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') assert r'\PassOptionsToPackage{booktabs}{sphinx}' in result assert r'\PassOptionsToPackage{colorrows}{sphinx}' in result # tabularcolumns @@ -1389,15 +1389,16 @@ def test_latex_table_with_booktabs_and_colorrows(app, status, warning): confoverrides={'templates_path': ['_mytemplates/latex']}) def test_latex_table_custom_template_caseA(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') assert 'SALUT LES COPAINS' in result + assert 'AU REVOIR, KANIGGETS' in result @pytest.mark.sphinx('latex', testroot='latex-table', confoverrides={'templates_path': ['_mytemplates']}) def test_latex_table_custom_template_caseB(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') assert 'SALUT LES COPAINS' not in result @@ -1405,14 +1406,14 @@ def test_latex_table_custom_template_caseB(app, status, warning): @pytest.mark.test_params(shared_result='latex-table') def test_latex_table_custom_template_caseC(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') assert 'SALUT LES COPAINS' not in result @pytest.mark.sphinx('latex', testroot='directives-raw') def test_latex_raw_directive(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') # standard case assert 'standalone raw directive (HTML)' not in result @@ -1429,7 +1430,7 @@ def test_latex_images(app, status, warning): with http_server(RemoteImageHandler, port=7777): app.build(force_all=True) - result = (app.outdir / 'python.tex').read_text(encoding='utf8') + result = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') # images are copied assert '\\sphinxincludegraphics{{sphinx}.png}' in result @@ -1453,7 +1454,7 @@ def test_latex_images(app, status, warning): def test_latex_index(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') assert ('A \\index{famous@\\spxentry{famous}}famous ' '\\index{equation@\\spxentry{equation}}equation:\n' in result) assert ('\n\\index{Einstein@\\spxentry{Einstein}}' @@ -1467,7 +1468,7 @@ def test_latex_index(app, status, warning): def test_latex_equations(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') expected = (app.srcdir / 'expects' / 'latex-equations.tex').read_text(encoding='utf8').strip() assert expected in result @@ -1477,7 +1478,7 @@ def test_latex_equations(app, status, warning): def test_latex_image_in_parsed_literal(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') assert ('{\\sphinxunactivateextrasandspace \\raisebox{-0.5\\height}' '{\\sphinxincludegraphics[height=2.00000cm]{{pic}.png}}' '}AFTER') in result @@ -1487,7 +1488,7 @@ def test_latex_image_in_parsed_literal(app, status, warning): def test_latex_nested_enumerated_list(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') assert ('\\sphinxsetlistlabels{\\arabic}{enumi}{enumii}{}{.}%\n' '\\setcounter{enumi}{4}\n' in result) assert ('\\sphinxsetlistlabels{\\alph}{enumii}{enumiii}{}{.}%\n' @@ -1504,7 +1505,7 @@ def test_latex_nested_enumerated_list(app, status, warning): def test_latex_thebibliography(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(result) assert ('\\begin{sphinxthebibliography}{AuthorYe}\n' '\\bibitem[AuthorYear]{index:authoryear}\n\\sphinxAtStartPar\n' @@ -1517,7 +1518,7 @@ def test_latex_thebibliography(app, status, warning): def test_latex_glossary(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') assert (r'\sphinxlineitem{ähnlich\index{ähnlich@\spxentry{ähnlich}|spxpagem}' r'\phantomsection' r'\label{\detokenize{index:term-ahnlich}}}' in result) @@ -1541,7 +1542,7 @@ def test_latex_glossary(app, status, warning): def test_latex_labels(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') # figures assert (r'\caption{labeled figure}' @@ -1589,8 +1590,10 @@ def test_latex_labels(app, status, warning): @pytest.mark.sphinx('latex', testroot='latex-figure-in-admonition') def test_latex_figure_in_admonition(app, status, warning): app.build(force_all=True) - result = (app.outdir / 'python.tex').read_text(encoding='utf8') - assert r'\begin{figure}[H]' in result + result = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') + assert 'tabulary' not in result + for type in ('caution', 'note', 'seealso', 'todo'): + assert f'{type} directive.\n\n\\begin{{figure}}[H]' in result def test_default_latex_documents(): @@ -1619,7 +1622,7 @@ def test_includegraphics_oversized(app, status, warning): @pytest.mark.sphinx('latex', testroot='index_on_title') def test_index_on_title(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') assert ('\\chapter{Test for index in top level title}\n' '\\label{\\detokenize{contents:test-for-index-in-top-level-title}}' '\\index{index@\\spxentry{index}}\n' @@ -1630,7 +1633,7 @@ def test_index_on_title(app, status, warning): confoverrides={'latex_engine': 'pdflatex'}) def test_texescape_for_non_unicode_supported_engine(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(result) assert 'script small e: e' in result assert 'double struck italic small i: i' in result @@ -1642,7 +1645,7 @@ def test_texescape_for_non_unicode_supported_engine(app, status, warning): confoverrides={'latex_engine': 'xelatex'}) def test_texescape_for_unicode_supported_engine(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(result) assert 'script small e: e' in result assert 'double struck italic small i: i' in result @@ -1667,7 +1670,7 @@ def test_latex_nested_tables(app, status, warning): @pytest.mark.sphinx('latex', testroot='latex-container') def test_latex_container(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') assert r'\begin{sphinxuseclass}{classname}' in result assert r'\end{sphinxuseclass}' in result @@ -1675,7 +1678,7 @@ def test_latex_container(app, status, warning): @pytest.mark.sphinx('latex', testroot='reST-code-role') def test_latex_code_role(app): app.build() - content = (app.outdir / 'python.tex').read_text(encoding='utf8') + content = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') common_content = ( r'\PYG{k}{def} ' @@ -1710,6 +1713,7 @@ def test_copy_images(app, status, warning): } images.discard('sphinx.png') assert images == { + 'ba30773957c3fe046897111afd65a80b81cad089.png', # latex: image from data:image/png URI in source 'img.pdf', 'rimg.png', 'testimäge.png', @@ -1719,7 +1723,7 @@ def test_copy_images(app, status, warning): @pytest.mark.sphinx('latex', testroot='latex-labels-before-module') def test_duplicated_labels_before_module(app, status, warning): app.build() - content: str = (app.outdir / 'python.tex').read_text(encoding='utf8') + content: str = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') def count_label(name): text = r'\phantomsection\label{\detokenize{%s}}' % name @@ -1750,10 +1754,40 @@ def test_duplicated_labels_before_module(app, status, warning): confoverrides={'python_maximum_signature_line_length': 23}) def test_one_parameter_per_line(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') # TODO: should these asserts check presence or absence of a final \sphinxparamcomma? # signature of 23 characters is too short to trigger one-param-per-line mark-up assert ('\\pysiglinewithargsret{\\sphinxbfcode{\\sphinxupquote{hello}}}' in result) assert ('\\pysigwithonelineperarg{\\sphinxbfcode{\\sphinxupquote{foo}}}' in result) + + # generic_arg[T] + assert ('\\pysiglinewithargsretwithtypelist{\\sphinxbfcode{\\sphinxupquote{generic\\_arg}}}' + '{\\sphinxtypeparam{\\DUrole{n}{T}}}{}{}' in result) + + # generic_foo[T]() + assert ('\\pysiglinewithargsretwithtypelist{\\sphinxbfcode{\\sphinxupquote{generic\\_foo}}}' in result) + + # generic_bar[T](x: list[T]) + assert ('\\pysigwithonelineperargwithtypelist{\\sphinxbfcode{\\sphinxupquote{generic\\_bar}}}' in result) + + # generic_ret[R]() -> R + assert ('\\pysiglinewithargsretwithtypelist{\\sphinxbfcode{\\sphinxupquote{generic\\_ret}}}' + '{\\sphinxtypeparam{\\DUrole{n}{R}}}{}{{ $\\rightarrow$ R}}' in result) + + # MyGenericClass[X] + assert ('\\pysiglinewithargsretwithtypelist{\\sphinxbfcode{\\sphinxupquote{class\\DUrole{w}{ ' + '}}}\\sphinxbfcode{\\sphinxupquote{MyGenericClass}}}' in result) + + # MyList[T](list[T]) + assert ('\\pysiglinewithargsretwithtypelist{\\sphinxbfcode{\\sphinxupquote{class\\DUrole{w}{ ' + '}}}\\sphinxbfcode{\\sphinxupquote{MyList}}}' in result) + + +@pytest.mark.sphinx('latex', testroot='markup-rubric') +def test_latex_rubric(app): + app.build() + content = (app.outdir / 'test.tex').read_text(encoding='utf8') + assert r'\subsubsection*{This is a rubric}' in content + assert r'\subsection*{A rubric with a heading level 2}' in content diff --git a/tests/test_builders/test_build_linkcheck.py b/tests/test_builders/test_build_linkcheck.py index c8d8515..0787661 100644 --- a/tests/test_builders/test_build_linkcheck.py +++ b/tests/test_builders/test_build_linkcheck.py @@ -11,6 +11,7 @@ import wsgiref.handlers from base64 import b64encode from http.server import BaseHTTPRequestHandler from queue import Queue +from typing import TYPE_CHECKING from unittest import mock import docutils @@ -20,6 +21,7 @@ from urllib3.poolmanager import PoolManager import sphinx.util.http_date from sphinx.builders.linkcheck import ( CheckRequest, + CheckResult, Hyperlink, HyperlinkAvailabilityCheckWorker, RateLimit, @@ -33,6 +35,12 @@ from tests.utils import CERT_FILE, serve_application ts_re = re.compile(r".*\[(?P<ts>.*)\].*") +if TYPE_CHECKING: + from collections.abc import Callable, Iterable + from io import StringIO + + from sphinx.application import Sphinx + class DefaultsHandler(BaseHTTPRequestHandler): protocol_version = "HTTP/1.1" @@ -101,7 +109,7 @@ class ConnectionMeasurement: @pytest.mark.sphinx('linkcheck', testroot='linkcheck', freshenv=True) -def test_defaults(app): +def test_defaults(app: Sphinx) -> None: with serve_application(app, DefaultsHandler) as address: with ConnectionMeasurement() as m: app.build() @@ -146,7 +154,7 @@ def test_defaults(app): 'info': '', } - def _missing_resource(filename: str, lineno: int): + def _missing_resource(filename: str, lineno: int) -> dict[str, str | int]: return { 'filename': 'links.rst', 'lineno': lineno, @@ -178,7 +186,7 @@ def test_defaults(app): @pytest.mark.sphinx( 'linkcheck', testroot='linkcheck', freshenv=True, confoverrides={'linkcheck_anchors': False}) -def test_check_link_response_only(app): +def test_check_link_response_only(app: Sphinx) -> None: with serve_application(app, DefaultsHandler) as address: app.build() @@ -192,7 +200,7 @@ def test_check_link_response_only(app): @pytest.mark.sphinx('linkcheck', testroot='linkcheck-too-many-retries', freshenv=True) -def test_too_many_retries(app): +def test_too_many_retries(app: Sphinx) -> None: with serve_application(app, DefaultsHandler) as address: app.build() @@ -221,7 +229,7 @@ def test_too_many_retries(app): @pytest.mark.sphinx('linkcheck', testroot='linkcheck-raw-node', freshenv=True) -def test_raw_node(app): +def test_raw_node(app: Sphinx) -> None: with serve_application(app, OKHandler) as address: # write an index file that contains a link back to this webserver's root # URL. docutils will replace the raw node with the contents retrieved.. @@ -254,7 +262,7 @@ def test_raw_node(app): @pytest.mark.sphinx( 'linkcheck', testroot='linkcheck-anchors-ignore', freshenv=True, confoverrides={'linkcheck_anchors_ignore': ["^!", "^top$"]}) -def test_anchors_ignored(app): +def test_anchors_ignored(app: Sphinx) -> None: with serve_application(app, OKHandler): app.build() @@ -266,6 +274,43 @@ def test_anchors_ignored(app): class AnchorsIgnoreForUrlHandler(BaseHTTPRequestHandler): + protocol_version = 'HTTP/1.1' + + def _chunk_content(self, content: str, *, max_chunk_size: int) -> Iterable[bytes]: + + def _encode_chunk(chunk: bytes) -> Iterable[bytes]: + """Encode a bytestring into a format suitable for HTTP chunked-transfer. + + https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding + """ + yield f'{len(chunk):X}'.encode('ascii') + yield b'\r\n' + yield chunk + yield b'\r\n' + + buffer = b'' + for char in content: + buffer += char.encode('utf-8') + if len(buffer) >= max_chunk_size: + chunk, buffer = buffer[:max_chunk_size], buffer[max_chunk_size:] + yield from _encode_chunk(chunk) + + # Flush remaining bytes, if any + if buffer: + yield from _encode_chunk(buffer) + + # Emit a final empty chunk to close the stream + yield from _encode_chunk(b'') + + def _send_chunked(self, content: str) -> bool: + for chunk in self._chunk_content(content, max_chunk_size=20): + try: + self.wfile.write(chunk) + except (BrokenPipeError, ConnectionResetError) as e: + self.log_message(str(e)) + return False + return True + def do_HEAD(self): if self.path in {'/valid', '/ignored'}: self.send_response(200, "OK") @@ -274,17 +319,24 @@ class AnchorsIgnoreForUrlHandler(BaseHTTPRequestHandler): self.end_headers() def do_GET(self): - self.do_HEAD() if self.path == '/valid': - self.wfile.write(b"<h1 id='valid-anchor'>valid anchor</h1>\n") + self.send_response(200, 'OK') + content = "<h1 id='valid-anchor'>valid anchor</h1>\n" elif self.path == '/ignored': - self.wfile.write(b"no anchor but page exists\n") + self.send_response(200, 'OK') + content = 'no anchor but page exists\n' + else: + self.send_response(404, 'Not Found') + content = 'not found\n' + self.send_header('Transfer-Encoding', 'chunked') + self.end_headers() + self._send_chunked(content) @pytest.mark.sphinx('linkcheck', testroot='linkcheck-anchors-ignore-for-url', freshenv=True) -def test_anchors_ignored_for_url(app): +def test_anchors_ignored_for_url(app: Sphinx) -> None: with serve_application(app, AnchorsIgnoreForUrlHandler) as address: - app.config.linkcheck_anchors_ignore_for_url = [ # type: ignore[attr-defined] + app.config.linkcheck_anchors_ignore_for_url = [ f'http://{address}/ignored', # existing page f'http://{address}/invalid', # unknown page ] @@ -295,7 +347,7 @@ def test_anchors_ignored_for_url(app): attrs = ('filename', 'lineno', 'status', 'code', 'uri', 'info') data = [json.loads(x) for x in content.splitlines()] - assert len(data) == 7 + assert len(data) == 8 assert all(all(attr in row for attr in attrs) for row in data) # rows may be unsorted due to network latency or @@ -304,6 +356,7 @@ def test_anchors_ignored_for_url(app): assert rows[f'http://{address}/valid']['status'] == 'working' assert rows[f'http://{address}/valid#valid-anchor']['status'] == 'working' + assert rows[f'http://{address}/valid#py:module::urllib.parse']['status'] == 'broken' assert rows[f'http://{address}/valid#invalid-anchor'] == { 'status': 'broken', 'info': "Anchor 'invalid-anchor' not found", @@ -323,7 +376,7 @@ def test_anchors_ignored_for_url(app): @pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-anchor', freshenv=True) -def test_raises_for_invalid_status(app): +def test_raises_for_invalid_status(app: Sphinx) -> None: class InternalServerErrorHandler(BaseHTTPRequestHandler): protocol_version = "HTTP/1.1" @@ -340,6 +393,50 @@ def test_raises_for_invalid_status(app): ) +@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-anchor', freshenv=True) +def test_incomplete_html_anchor(app): + class IncompleteHTMLDocumentHandler(BaseHTTPRequestHandler): + protocol_version = 'HTTP/1.1' + + def do_GET(self): + content = b'this is <div id="anchor">not</div> a valid HTML document' + self.send_response(200, 'OK') + self.send_header('Content-Length', str(len(content))) + self.end_headers() + self.wfile.write(content) + + with serve_application(app, IncompleteHTMLDocumentHandler): + app.build() + + content = (app.outdir / 'output.json').read_text(encoding='utf8') + assert len(content.splitlines()) == 1 + + row = json.loads(content) + assert row['status'] == 'working' + + +@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-anchor', freshenv=True) +def test_decoding_error_anchor_ignored(app): + class NonASCIIHandler(BaseHTTPRequestHandler): + protocol_version = 'HTTP/1.1' + + def do_GET(self): + content = b'\x80\x00\x80\x00' # non-ASCII byte-string + self.send_response(200, 'OK') + self.send_header('Content-Length', str(len(content))) + self.end_headers() + self.wfile.write(content) + + with serve_application(app, NonASCIIHandler): + app.build() + + content = (app.outdir / 'output.json').read_text(encoding='utf8') + assert len(content.splitlines()) == 1 + + row = json.loads(content) + assert row['status'] == 'ignored' + + def custom_handler(valid_credentials=(), success_criteria=lambda _: True): """ Returns an HTTP request handler that authenticates the client and then determines @@ -352,25 +449,27 @@ def custom_handler(valid_credentials=(), success_criteria=lambda _: True): expected_token = b64encode(":".join(valid_credentials).encode()).decode("utf-8") del valid_credentials + def authenticated( + method: Callable[[CustomHandler], None] + ) -> Callable[[CustomHandler], None]: + def method_if_authenticated(self): + if expected_token is None: + return method(self) + elif not self.headers["Authorization"]: + self.send_response(401, "Unauthorized") + self.end_headers() + elif self.headers["Authorization"] == f"Basic {expected_token}": + return method(self) + else: + self.send_response(403, "Forbidden") + self.send_header("Content-Length", "0") + self.end_headers() + + return method_if_authenticated + class CustomHandler(BaseHTTPRequestHandler): protocol_version = "HTTP/1.1" - def authenticated(method): - def method_if_authenticated(self): - if expected_token is None: - return method(self) - elif not self.headers["Authorization"]: - self.send_response(401, "Unauthorized") - self.end_headers() - elif self.headers["Authorization"] == f"Basic {expected_token}": - return method(self) - else: - self.send_response(403, "Forbidden") - self.send_header("Content-Length", "0") - self.end_headers() - - return method_if_authenticated - @authenticated def do_HEAD(self): self.do_GET() @@ -389,9 +488,9 @@ def custom_handler(valid_credentials=(), success_criteria=lambda _: True): @pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver', freshenv=True) -def test_auth_header_uses_first_match(app): +def test_auth_header_uses_first_match(app: Sphinx) -> None: with serve_application(app, custom_handler(valid_credentials=("user1", "password"))) as address: - app.config.linkcheck_auth = [ # type: ignore[attr-defined] + app.config.linkcheck_auth = [ (r'^$', ('no', 'match')), (fr'^http://{re.escape(address)}/$', ('user1', 'password')), (r'.*local.*', ('user2', 'hunter2')), @@ -408,7 +507,7 @@ def test_auth_header_uses_first_match(app): @pytest.mark.sphinx( 'linkcheck', testroot='linkcheck-localserver', freshenv=True, confoverrides={'linkcheck_allow_unauthorized': False}) -def test_unauthorized_broken(app): +def test_unauthorized_broken(app: Sphinx) -> None: with serve_application(app, custom_handler(valid_credentials=("user1", "password"))): app.build() @@ -422,7 +521,7 @@ def test_unauthorized_broken(app): @pytest.mark.sphinx( 'linkcheck', testroot='linkcheck-localserver', freshenv=True, confoverrides={'linkcheck_auth': [(r'^$', ('user1', 'password'))]}) -def test_auth_header_no_match(app): +def test_auth_header_no_match(app: Sphinx) -> None: with ( serve_application(app, custom_handler(valid_credentials=("user1", "password"))), pytest.warns(RemovedInSphinx80Warning, match='linkcheck builder encountered an HTTP 401'), @@ -438,14 +537,14 @@ def test_auth_header_no_match(app): @pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver', freshenv=True) -def test_linkcheck_request_headers(app): +def test_linkcheck_request_headers(app: Sphinx) -> None: def check_headers(self): if "X-Secret" in self.headers: return False return self.headers["Accept"] == "text/html" with serve_application(app, custom_handler(success_criteria=check_headers)) as address: - app.config.linkcheck_request_headers = { # type: ignore[attr-defined] + app.config.linkcheck_request_headers = { f"http://{address}/": {"Accept": "text/html"}, "*": {"X-Secret": "open sesami"}, } @@ -458,14 +557,14 @@ def test_linkcheck_request_headers(app): @pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver', freshenv=True) -def test_linkcheck_request_headers_no_slash(app): +def test_linkcheck_request_headers_no_slash(app: Sphinx) -> None: def check_headers(self): if "X-Secret" in self.headers: return False return self.headers["Accept"] == "application/json" with serve_application(app, custom_handler(success_criteria=check_headers)) as address: - app.config.linkcheck_request_headers = { # type: ignore[attr-defined] + app.config.linkcheck_request_headers = { f"http://{address}": {"Accept": "application/json"}, "*": {"X-Secret": "open sesami"}, } @@ -483,7 +582,7 @@ def test_linkcheck_request_headers_no_slash(app): "http://do.not.match.org": {"Accept": "application/json"}, "*": {"X-Secret": "open sesami"}, }}) -def test_linkcheck_request_headers_default(app): +def test_linkcheck_request_headers_default(app: Sphinx) -> None: def check_headers(self): if self.headers["X-Secret"] != "open sesami": return False @@ -566,9 +665,9 @@ def test_follows_redirects_on_GET(app, capsys, warning): @pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-warn-redirects') -def test_linkcheck_allowed_redirects(app, warning): +def test_linkcheck_allowed_redirects(app: Sphinx, warning: StringIO) -> None: with serve_application(app, make_redirect_handler(support_head=False)) as address: - app.config.linkcheck_allowed_redirects = {f'http://{address}/.*1': '.*'} # type: ignore[attr-defined] + app.config.linkcheck_allowed_redirects = {f'http://{address}/.*1': '.*'} compile_linkcheck_allowed_redirects(app, app.config) app.build() @@ -626,7 +725,7 @@ def test_invalid_ssl(get_request, app): @pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-https', freshenv=True) -def test_connect_to_selfsigned_fails(app): +def test_connect_to_selfsigned_fails(app: Sphinx) -> None: with serve_application(app, OKHandler, tls_enabled=True) as address: app.build() @@ -639,9 +738,9 @@ def test_connect_to_selfsigned_fails(app): assert "[SSL: CERTIFICATE_VERIFY_FAILED]" in content["info"] -@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-https', freshenv=True) -def test_connect_to_selfsigned_with_tls_verify_false(app): - app.config.tls_verify = False +@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-https', freshenv=True, + confoverrides={'tls_verify': False}) +def test_connect_to_selfsigned_with_tls_verify_false(app: Sphinx) -> None: with serve_application(app, OKHandler, tls_enabled=True) as address: app.build() @@ -657,9 +756,9 @@ def test_connect_to_selfsigned_with_tls_verify_false(app): } -@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-https', freshenv=True) -def test_connect_to_selfsigned_with_tls_cacerts(app): - app.config.tls_cacerts = CERT_FILE +@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-https', freshenv=True, + confoverrides={'tls_cacerts': CERT_FILE}) +def test_connect_to_selfsigned_with_tls_cacerts(app: Sphinx) -> None: with serve_application(app, OKHandler, tls_enabled=True) as address: app.build() @@ -693,9 +792,9 @@ def test_connect_to_selfsigned_with_requests_env_var(monkeypatch, app): } -@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-https', freshenv=True) -def test_connect_to_selfsigned_nonexistent_cert_file(app): - app.config.tls_cacerts = "does/not/exist" +@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-https', freshenv=True, + confoverrides={'tls_cacerts': "does/not/exist"}) +def test_connect_to_selfsigned_nonexistent_cert_file(app: Sphinx) -> None: with serve_application(app, OKHandler, tls_enabled=True) as address: app.build() @@ -863,7 +962,7 @@ def test_too_many_requests_retry_after_without_header(app, capsys): 'linkcheck_timeout': 0.01, } ) -def test_requests_timeout(app): +def test_requests_timeout(app: Sphinx) -> None: class DelayedResponseHandler(BaseHTTPRequestHandler): protocol_version = "HTTP/1.1" @@ -882,9 +981,9 @@ def test_requests_timeout(app): assert content["status"] == "timeout" -@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver', freshenv=True) -def test_too_many_requests_user_timeout(app): - app.config.linkcheck_rate_limit_timeout = 0.0 +@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver', freshenv=True, + confoverrides={'linkcheck_rate_limit_timeout': 0.0}) +def test_too_many_requests_user_timeout(app: Sphinx) -> None: with serve_application(app, make_retry_after_handler([(429, None)])) as address: app.build() content = (app.outdir / 'output.json').read_text(encoding='utf8') @@ -903,21 +1002,21 @@ class FakeResponse: url = "http://localhost/" -def test_limit_rate_default_sleep(app): +def test_limit_rate_default_sleep(app: Sphinx) -> None: worker = HyperlinkAvailabilityCheckWorker(app.config, Queue(), Queue(), {}) with mock.patch('time.time', return_value=0.0): next_check = worker.limit_rate(FakeResponse.url, FakeResponse.headers.get("Retry-After")) assert next_check == 60.0 -def test_limit_rate_user_max_delay(app): - app.config.linkcheck_rate_limit_timeout = 0.0 +@pytest.mark.sphinx(confoverrides={'linkcheck_rate_limit_timeout': 0.0}) +def test_limit_rate_user_max_delay(app: Sphinx) -> None: worker = HyperlinkAvailabilityCheckWorker(app.config, Queue(), Queue(), {}) next_check = worker.limit_rate(FakeResponse.url, FakeResponse.headers.get("Retry-After")) assert next_check is None -def test_limit_rate_doubles_previous_wait_time(app): +def test_limit_rate_doubles_previous_wait_time(app: Sphinx) -> None: rate_limits = {"localhost": RateLimit(60.0, 0.0)} worker = HyperlinkAvailabilityCheckWorker(app.config, Queue(), Queue(), rate_limits) with mock.patch('time.time', return_value=0.0): @@ -925,21 +1024,23 @@ def test_limit_rate_doubles_previous_wait_time(app): assert next_check == 120.0 -def test_limit_rate_clips_wait_time_to_max_time(app): - app.config.linkcheck_rate_limit_timeout = 90.0 +@pytest.mark.sphinx(confoverrides={'linkcheck_rate_limit_timeout': 90}) +def test_limit_rate_clips_wait_time_to_max_time(app: Sphinx, warning: StringIO) -> None: rate_limits = {"localhost": RateLimit(60.0, 0.0)} worker = HyperlinkAvailabilityCheckWorker(app.config, Queue(), Queue(), rate_limits) with mock.patch('time.time', return_value=0.0): next_check = worker.limit_rate(FakeResponse.url, FakeResponse.headers.get("Retry-After")) assert next_check == 90.0 + assert warning.getvalue() == '' -def test_limit_rate_bails_out_after_waiting_max_time(app): - app.config.linkcheck_rate_limit_timeout = 90.0 +@pytest.mark.sphinx(confoverrides={'linkcheck_rate_limit_timeout': 90.0}) +def test_limit_rate_bails_out_after_waiting_max_time(app: Sphinx, warning: StringIO) -> None: rate_limits = {"localhost": RateLimit(90.0, 0.0)} worker = HyperlinkAvailabilityCheckWorker(app.config, Queue(), Queue(), rate_limits) next_check = worker.limit_rate(FakeResponse.url, FakeResponse.headers.get("Retry-After")) assert next_check is None + assert warning.getvalue() == '' @mock.patch('sphinx.util.requests.requests.Session.get_adapter') @@ -957,11 +1058,13 @@ def test_connection_contention(get_adapter, app, capsys): # Place a workload into the linkcheck queue link_count = 10 - rqueue, wqueue = Queue(), Queue() + wqueue: Queue[CheckRequest] = Queue() + rqueue: Queue[CheckResult] = Queue() for _ in range(link_count): wqueue.put(CheckRequest(0, Hyperlink(f"http://{address}", "test", "test.rst", 1))) - begin, checked = time.time(), [] + begin = time.time() + checked: list[CheckResult] = [] threads = [ HyperlinkAvailabilityCheckWorker( config=app.config, @@ -997,7 +1100,7 @@ class ConnectionResetHandler(BaseHTTPRequestHandler): @pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver', freshenv=True) -def test_get_after_head_raises_connection_error(app): +def test_get_after_head_raises_connection_error(app: Sphinx) -> None: with serve_application(app, ConnectionResetHandler) as address: app.build() content = (app.outdir / 'output.txt').read_text(encoding='utf8') @@ -1014,7 +1117,7 @@ def test_get_after_head_raises_connection_error(app): @pytest.mark.sphinx('linkcheck', testroot='linkcheck-documents_exclude', freshenv=True) -def test_linkcheck_exclude_documents(app): +def test_linkcheck_exclude_documents(app: Sphinx) -> None: with serve_application(app, DefaultsHandler): app.build() diff --git a/tests/test_builders/test_build_manpage.py b/tests/test_builders/test_build_manpage.py index 7172281..31d75d6 100644 --- a/tests/test_builders/test_build_manpage.py +++ b/tests/test_builders/test_build_manpage.py @@ -7,6 +7,8 @@ from sphinx.builders.manpage import default_man_pages from sphinx.config import Config +@pytest.mark.xfail(docutils.__version_info__[:2] > (0, 21), + reason='Docutils has removed the reference key in master') @pytest.mark.sphinx('man') def test_all(app, status, warning): app.build(force_all=True) @@ -44,13 +46,15 @@ def test_man_pages_empty_description(app, status, warning): confoverrides={'man_make_section_directory': True}) def test_man_make_section_directory(app, status, warning): app.build() - assert (app.outdir / 'man1' / 'python.1').exists() + assert (app.outdir / 'man1' / 'projectnamenotset.1').exists() +@pytest.mark.xfail(docutils.__version_info__[:2] > (0, 21), + reason='Docutils has removed the reference key in master') @pytest.mark.sphinx('man', testroot='directive-code') def test_captioned_code_block(app, status, warning): app.build(force_all=True) - content = (app.outdir / 'python.1').read_text(encoding='utf8') + content = (app.outdir / 'projectnamenotset.1').read_text(encoding='utf8') if docutils.__version_info__[:2] < (0, 21): expected = """\ @@ -100,5 +104,5 @@ def test_default_man_pages(): @pytest.mark.sphinx('man', testroot='markup-rubric') def test_rubric(app, status, warning): app.build() - content = (app.outdir / 'python.1').read_text(encoding='utf8') + content = (app.outdir / 'projectnamenotset.1').read_text(encoding='utf8') assert 'This is a rubric\n' in content diff --git a/tests/test_builders/test_build_texinfo.py b/tests/test_builders/test_build_texinfo.py index f9effb2..6abbc96 100644 --- a/tests/test_builders/test_build_texinfo.py +++ b/tests/test_builders/test_build_texinfo.py @@ -40,16 +40,17 @@ def test_texinfo(app, status, warning): def test_texinfo_rubric(app, status, warning): app.build() - output = (app.outdir / 'python.texi').read_text(encoding='utf8') + output = (app.outdir / 'projectnamenotset.texi').read_text(encoding='utf8') assert '@heading This is a rubric' in output assert '@heading This is a multiline rubric' in output + assert '@heading A rubric with a heading level' in output @pytest.mark.sphinx('texinfo', testroot='markup-citation') def test_texinfo_citation(app, status, warning): app.build(force_all=True) - output = (app.outdir / 'python.texi').read_text(encoding='utf8') + output = (app.outdir / 'projectnamenotset.texi').read_text(encoding='utf8') assert 'This is a citation ref; @ref{1,,[CITE1]} and @ref{2,,[CITE2]}.' in output assert ('@anchor{index cite1}@anchor{1}@w{(CITE1)} \n' 'This is a citation\n') in output @@ -87,7 +88,7 @@ def test_texinfo_escape_id(app, status, warning): def test_texinfo_footnote(app, status, warning): app.build(force_all=True) - output = (app.outdir / 'python.texi').read_text(encoding='utf8') + output = (app.outdir / 'projectnamenotset.texi').read_text(encoding='utf8') assert 'First footnote: @footnote{\nFirst\n}' in output @@ -120,10 +121,11 @@ def test_texinfo_samp_with_variable(app, status, warning): def test_copy_images(app, status, warning): app.build() - images_dir = Path(app.outdir) / 'python-figures' + images_dir = Path(app.outdir) / 'projectnamenotset-figures' images = {image.name for image in images_dir.rglob('*')} images.discard('python-logo.png') assert images == { + 'ba30773957c3fe046897111afd65a80b81cad089.png', # texinfo: image from data:image/png URI in source 'img.png', 'rimg.png', 'testimäge.png', |