'),
+ ],
+ 'genindex.html': [
+ # index entries
+ (".//a/strong", "Main"),
+ (".//a/strong", "[1]"),
+ (".//a/strong", "Other"),
+ (".//a", "entry"),
+ (".//li/a", "double"),
+ ],
+ 'footnote.html': [
+ (".//a[@class='footnote-reference'][@href='#id7'][@id='id1']", r"\[1\]"),
+ (".//a[@class='footnote-reference'][@href='#id8'][@id='id2']", r"\[2\]"),
+ (".//a[@class='footnote-reference'][@href='#foo'][@id='id3']", r"\[3\]"),
+ (".//a[@class='reference internal'][@href='#bar'][@id='id4']", r"\[bar\]"),
+ (".//a[@class='footnote-reference'][@href='#id9'][@id='id5']", r"\[4\]"),
+ (".//a[@class='footnote-reference'][@href='#id10'][@id='id6']", r"\[5\]"),
+ (".//a[@class='fn-backref'][@href='#id1']", r"\[1\]"),
+ (".//a[@class='fn-backref'][@href='#id2']", r"\[2\]"),
+ (".//a[@class='fn-backref'][@href='#id3']", r"\[3\]"),
+ (".//a[@class='fn-backref'][@href='#id4']", r"\[bar\]"),
+ (".//a[@class='fn-backref'][@href='#id5']", r"\[4\]"),
+ (".//a[@class='fn-backref'][@href='#id6']", r"\[5\]"),
+ ],
+ 'otherext.html': [
+ (".//h1", "Generated section"),
+ (".//a[@href='_sources/otherext.foo.txt']", ''),
+ ]
+}))
+@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_html_output(app, cached_etree_parse, fname, expect):
+ app.build()
+ check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
+
+
+@pytest.mark.parametrize("fname,expect", flat_dict({
+ 'index.html': [
+ (".//li[@class='toctree-l3']/a", '1.1.1. Foo A1', True),
+ (".//li[@class='toctree-l3']/a", '1.2.1. Foo B1', True),
+ (".//li[@class='toctree-l3']/a", '2.1.1. Bar A1', False),
+ (".//li[@class='toctree-l3']/a", '2.2.1. Bar B1', False),
+ ],
+ 'foo.html': [
+ (".//h1", '1. Foo', True),
+ (".//h2", '1.1. Foo A', True),
+ (".//h3", '1.1.1. Foo A1', True),
+ (".//h2", '1.2. Foo B', True),
+ (".//h3", '1.2.1. Foo B1', True),
+ (".//div[@class='sphinxsidebarwrapper']//li/a", '1.1. Foo A', True),
+ (".//div[@class='sphinxsidebarwrapper']//li/a", '1.1.1. Foo A1', True),
+ (".//div[@class='sphinxsidebarwrapper']//li/a", '1.2. Foo B', True),
+ (".//div[@class='sphinxsidebarwrapper']//li/a", '1.2.1. Foo B1', True),
+ ],
+ 'bar.html': [
+ (".//h1", '2. Bar', True),
+ (".//h2", '2.1. Bar A', True),
+ (".//h2", '2.2. Bar B', True),
+ (".//h3", '2.2.1. Bar B1', True),
+ (".//div[@class='sphinxsidebarwrapper']//li/a", '2. Bar', True),
+ (".//div[@class='sphinxsidebarwrapper']//li/a", '2.1. Bar A', True),
+ (".//div[@class='sphinxsidebarwrapper']//li/a", '2.2. Bar B', True),
+ (".//div[@class='sphinxsidebarwrapper']//li/a", '2.2.1. Bar B1', False),
+ ],
+ 'baz.html': [
+ (".//h1", '2.1.1. Baz A', True),
+ ],
+}))
+@pytest.mark.sphinx('html', testroot='tocdepth')
+@pytest.mark.test_params(shared_result='test_build_html_tocdepth')
+def test_tocdepth(app, cached_etree_parse, fname, expect):
+ app.build()
# issue #1251
- app.builder.build_all()
-
- expects = {
- 'index.html': [
- (".//li[@class='toctree-l3']/a", '1.1.1. Foo A1', True),
- (".//li[@class='toctree-l3']/a", '1.2.1. Foo B1', True),
- (".//li[@class='toctree-l3']/a", '2.1.1. Bar A1', False),
- (".//li[@class='toctree-l3']/a", '2.2.1. Bar B1', False),
- ],
- 'foo.html': [
- (".//h1", '1. Foo', True),
- (".//h2", '1.1. Foo A', True),
- (".//h3", '1.1.1. Foo A1', True),
- (".//h2", '1.2. Foo B', True),
- (".//h3", '1.2.1. Foo B1', True),
- (".//div[@class='sphinxsidebarwrapper']//li/a", '1.1. Foo A', True),
- (".//div[@class='sphinxsidebarwrapper']//li/a", '1.1.1. Foo A1', True),
- (".//div[@class='sphinxsidebarwrapper']//li/a", '1.2. Foo B', True),
- (".//div[@class='sphinxsidebarwrapper']//li/a", '1.2.1. Foo B1', True),
- ],
- 'bar.html': [
- (".//h1", '2. Bar', True),
- (".//h2", '2.1. Bar A', True),
- (".//h2", '2.2. Bar B', True),
- (".//h3", '2.2.1. Bar B1', True),
- (".//div[@class='sphinxsidebarwrapper']//li/a", '2. Bar', True),
- (".//div[@class='sphinxsidebarwrapper']//li/a", '2.1. Bar A', True),
- (".//div[@class='sphinxsidebarwrapper']//li/a", '2.2. Bar B', True),
- (".//div[@class='sphinxsidebarwrapper']//li/a", '2.2.1. Bar B1', False),
- ],
- 'baz.html': [
- (".//h1", '2.1.1. Baz A', True),
- ],
- }
-
- for fname, paths in iteritems(expects):
- with (app.outdir / fname).open('rb') as fp:
- etree = HTML_PARSER.parse(fp)
-
- for xpath, check, be_found in paths:
- yield check_xpath, etree, fname, xpath, check, be_found
+ check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
-@gen_with_app(buildername='singlehtml', testroot='tocdepth')
-def test_tocdepth_singlehtml(app, status, warning):
- app.builder.build_all()
+@pytest.mark.parametrize("fname,expect", flat_dict({
+ 'index.html': [
+ (".//li[@class='toctree-l3']/a", '1.1.1. Foo A1', True),
+ (".//li[@class='toctree-l3']/a", '1.2.1. Foo B1', True),
+ (".//li[@class='toctree-l3']/a", '2.1.1. Bar A1', False),
+ (".//li[@class='toctree-l3']/a", '2.2.1. Bar B1', False),
- expects = {
- 'index.html': [
- (".//li[@class='toctree-l3']/a", '1.1.1. Foo A1', True),
- (".//li[@class='toctree-l3']/a", '1.2.1. Foo B1', True),
- (".//li[@class='toctree-l3']/a", '2.1.1. Bar A1', False),
- (".//li[@class='toctree-l3']/a", '2.2.1. Bar B1', False),
+ # index.rst
+ (".//h1", 'test-tocdepth', True),
- # index.rst
- (".//h1", 'test-tocdepth', True),
+ # foo.rst
+ (".//h2", '1. Foo', True),
+ (".//h3", '1.1. Foo A', True),
+ (".//h4", '1.1.1. Foo A1', True),
+ (".//h3", '1.2. Foo B', True),
+ (".//h4", '1.2.1. Foo B1', True),
- # foo.rst
- (".//h2", '1. Foo', True),
- (".//h3", '1.1. Foo A', True),
- (".//h4", '1.1.1. Foo A1', True),
- (".//h3", '1.2. Foo B', True),
- (".//h4", '1.2.1. Foo B1', True),
+ # bar.rst
+ (".//h2", '2. Bar', True),
+ (".//h3", '2.1. Bar A', True),
+ (".//h3", '2.2. Bar B', True),
+ (".//h4", '2.2.1. Bar B1', True),
- # bar.rst
- (".//h2", '2. Bar', True),
- (".//h3", '2.1. Bar A', True),
- (".//h3", '2.2. Bar B', True),
- (".//h4", '2.2.1. Bar B1', True),
-
- # baz.rst
- (".//h4", '2.1.1. Baz A', True),
- ],
- }
-
- for fname, paths in iteritems(expects):
- with (app.outdir / fname).open('rb') as fp:
- etree = HTML_PARSER.parse(fp)
-
- for xpath, check, be_found in paths:
- yield check_xpath, etree, fname, xpath, check, be_found
+ # baz.rst
+ (".//h4", '2.1.1. Baz A', True),
+ ],
+}))
+@pytest.mark.sphinx('singlehtml', testroot='tocdepth')
+@pytest.mark.test_params(shared_result='test_build_html_tocdepth')
+def test_tocdepth_singlehtml(app, cached_etree_parse, fname, expect):
+ app.build()
+ check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
-@gen_with_app(buildername='html', testroot='numfig')
-def test_numfig_disabled(app, status, warning):
- app.builder.build_all()
-
+@pytest.mark.sphinx('html', testroot='numfig')
+@pytest.mark.test_params(shared_result='test_build_html_numfig')
+def test_numfig_disabled_warn(app, warning):
+ app.build()
warnings = warning.getvalue()
assert 'index.rst:47: WARNING: numfig is disabled. :numref: is ignored.' in warnings
assert 'index.rst:55: WARNING: no number is assigned for section: index' not in warnings
assert 'index.rst:56: WARNING: invalid numfig_format: invalid' not in warnings
assert 'index.rst:57: WARNING: invalid numfig_format: Fig %s %s' not in warnings
- expects = {
- 'index.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", None, True),
- (".//table/caption/span[@class='caption-number']", None, True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", None, True),
- (".//li/code/span", '^fig1$', True),
- (".//li/code/span", '^Figure%s$', True),
- (".//li/code/span", '^table-1$', True),
- (".//li/code/span", '^Table:%s$', True),
- (".//li/code/span", '^CODE_1$', True),
- (".//li/code/span", '^Code-%s$', True),
- (".//li/code/span", '^foo$', True),
- (".//li/code/span", '^bar_a$', True),
- (".//li/code/span", '^Fig.{number}$', True),
- (".//li/code/span", '^Sect.{number}$', True),
- ],
- 'foo.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", None, True),
- (".//table/caption/span[@class='caption-number']", None, True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", None, True),
- ],
- 'bar.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", None, True),
- (".//table/caption/span[@class='caption-number']", None, True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", None, True),
- ],
- 'baz.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", None, True),
- (".//table/caption/span[@class='caption-number']", None, True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", None, True),
- ],
- }
- for fname, paths in iteritems(expects):
- with (app.outdir / fname).open('rb') as fp:
- etree = HTML_PARSER.parse(fp)
-
- for xpath, check, be_found in paths:
- yield check_xpath, etree, fname, xpath, check, be_found
+@pytest.mark.parametrize("fname,expect", flat_dict({
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", None, True),
+ (".//table/caption/span[@class='caption-number']", None, True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", None, True),
+ (".//li/code/span", '^fig1$', True),
+ (".//li/code/span", '^Figure%s$', True),
+ (".//li/code/span", '^table-1$', True),
+ (".//li/code/span", '^Table:%s$', True),
+ (".//li/code/span", '^CODE_1$', True),
+ (".//li/code/span", '^Code-%s$', True),
+ (".//li/code/span", '^foo$', True),
+ (".//li/code/span", '^bar_a$', True),
+ (".//li/code/span", '^Fig.{number}$', True),
+ (".//li/code/span", '^Sect.{number}$', True),
+ ],
+ 'foo.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", None, True),
+ (".//table/caption/span[@class='caption-number']", None, True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", None, True),
+ ],
+ 'bar.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", None, True),
+ (".//table/caption/span[@class='caption-number']", None, True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", None, True),
+ ],
+ 'baz.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", None, True),
+ (".//table/caption/span[@class='caption-number']", None, True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", None, True),
+ ],
+}))
+@pytest.mark.sphinx('html', testroot='numfig')
+@pytest.mark.test_params(shared_result='test_build_html_numfig')
+def test_numfig_disabled(app, cached_etree_parse, fname, expect):
+ app.build()
+ check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
-@gen_with_app(buildername='html', testroot='numfig', freshenv=True,
- confoverrides={'numfig': True})
-def test_numfig_without_numbered_toctree(app, status, warning):
+@pytest.mark.sphinx(
+ 'html', testroot='numfig',
+ srcdir='test_numfig_without_numbered_toctree_warn',
+ confoverrides={'numfig': True})
+def test_numfig_without_numbered_toctree_warn(app, warning):
+ app.build()
# remove :numbered: option
index = (app.srcdir / 'index.rst').text()
index = re.sub(':numbered:.*', '', index, re.MULTILINE)
@@ -573,519 +588,518 @@ def test_numfig_without_numbered_toctree(app, status, warning):
assert 'index.rst:56: WARNING: invalid numfig_format: invalid' in warnings
assert 'index.rst:57: WARNING: invalid numfig_format: Fig %s %s' in warnings
- expects = {
- 'index.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 9 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 10 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 9 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 10 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 9 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 10 $', True),
- (".//li/a/span", '^Fig. 9$', True),
- (".//li/a/span", '^Figure6$', True),
- (".//li/a/span", '^Table 9$', True),
- (".//li/a/span", '^Table:6$', True),
- (".//li/a/span", '^Listing 9$', True),
- (".//li/a/span", '^Code-6$', True),
- (".//li/code/span", '^foo$', True),
- (".//li/code/span", '^bar_a$', True),
- (".//li/a/span", '^Fig.9 should be Fig.1$', True),
- (".//li/code/span", '^Sect.{number}$', True),
- ],
- 'foo.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 3 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 4 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 3 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 4 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 3 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 4 $', True),
- ],
- 'bar.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 5 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 7 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 8 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 5 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 7 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 8 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 5 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 7 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 8 $', True),
- ],
- 'baz.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 6 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 6 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 6 $', True),
- ],
- }
- for fname, paths in iteritems(expects):
- with (app.outdir / fname).open('rb') as fp:
- etree = HTML_PARSER.parse(fp)
+@pytest.mark.parametrize("fname,expect", flat_dict({
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 9 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 10 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 9 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 10 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 9 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 10 $', True),
+ (".//li/a/span", '^Fig. 9$', True),
+ (".//li/a/span", '^Figure6$', True),
+ (".//li/a/span", '^Table 9$', True),
+ (".//li/a/span", '^Table:6$', True),
+ (".//li/a/span", '^Listing 9$', True),
+ (".//li/a/span", '^Code-6$', True),
+ (".//li/code/span", '^foo$', True),
+ (".//li/code/span", '^bar_a$', True),
+ (".//li/a/span", '^Fig.9 should be Fig.1$', True),
+ (".//li/code/span", '^Sect.{number}$', True),
+ ],
+ 'foo.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 4 $', True),
+ ],
+ 'bar.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 5 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 7 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 8 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 5 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 7 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 8 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 5 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 7 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 8 $', True),
+ ],
+ 'baz.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 6 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 6 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 6 $', True),
+ ],
+}))
+@pytest.mark.sphinx(
+ 'html', testroot='numfig',
+ srcdir='test_numfig_without_numbered_toctree',
+ confoverrides={'numfig': True})
+def test_numfig_without_numbered_toctree(app, cached_etree_parse, fname, expect):
+ # remove :numbered: option
+ index = (app.srcdir / 'index.rst').text()
+ index = re.sub(':numbered:.*', '', index, re.MULTILINE)
+ (app.srcdir / 'index.rst').write_text(index, encoding='utf-8')
- for xpath, check, be_found in paths:
- yield check_xpath, etree, fname, xpath, check, be_found
+ if not app.outdir.listdir():
+ app.build()
+ check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
-@gen_with_app(buildername='html', testroot='numfig',
- confoverrides={'numfig': True})
-def test_numfig_with_numbered_toctree(app, status, warning):
- app.builder.build_all()
-
+@pytest.mark.sphinx('html', testroot='numfig', confoverrides={'numfig': True})
+@pytest.mark.test_params(shared_result='test_build_html_numfig_on')
+def test_numfig_with_numbered_toctree_warn(app, warning):
+ app.build()
warnings = warning.getvalue()
assert 'index.rst:47: WARNING: numfig is disabled. :numref: is ignored.' not in warnings
assert 'index.rst:55: WARNING: no number is assigned for section: index' in warnings
assert 'index.rst:56: WARNING: invalid numfig_format: invalid' in warnings
assert 'index.rst:57: WARNING: invalid numfig_format: Fig %s %s' in warnings
- expects = {
- 'index.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2 $', True),
- (".//li/a/span", '^Fig. 1$', True),
- (".//li/a/span", '^Figure2.2$', True),
- (".//li/a/span", '^Table 1$', True),
- (".//li/a/span", '^Table:2.2$', True),
- (".//li/a/span", '^Listing 1$', True),
- (".//li/a/span", '^Code-2.2$', True),
- (".//li/a/span", '^Section.1$', True),
- (".//li/a/span", '^Section.2.1$', True),
- (".//li/a/span", '^Fig.1 should be Fig.1$', True),
- (".//li/a/span", '^Sect.1 Foo$', True),
- ],
- 'foo.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.2 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.3 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.4 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.3 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.4 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.3 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.4 $', True),
- ],
- 'bar.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.3 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.4 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.3 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.4 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.3 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.4 $', True),
- ],
- 'baz.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.2 $', True),
- ],
- }
- for fname, paths in iteritems(expects):
- with (app.outdir / fname).open('rb') as fp:
- etree = HTML_PARSER.parse(fp)
-
- for xpath, check, be_found in paths:
- yield check_xpath, etree, fname, xpath, check, be_found
+@pytest.mark.parametrize("fname,expect", flat_dict({
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2 $', True),
+ (".//li/a/span", '^Fig. 1$', True),
+ (".//li/a/span", '^Figure2.2$', True),
+ (".//li/a/span", '^Table 1$', True),
+ (".//li/a/span", '^Table:2.2$', True),
+ (".//li/a/span", '^Listing 1$', True),
+ (".//li/a/span", '^Code-2.2$', True),
+ (".//li/a/span", '^Section.1$', True),
+ (".//li/a/span", '^Section.2.1$', True),
+ (".//li/a/span", '^Fig.1 should be Fig.1$', True),
+ (".//li/a/span", '^Sect.1 Foo$', True),
+ ],
+ 'foo.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.2 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.4 $', True),
+ ],
+ 'bar.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.4 $', True),
+ ],
+ 'baz.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.2 $', True),
+ ],
+}))
+@pytest.mark.sphinx('html', testroot='numfig', confoverrides={'numfig': True})
+@pytest.mark.test_params(shared_result='test_build_html_numfig_on')
+def test_numfig_with_numbered_toctree(app, cached_etree_parse, fname, expect):
+ app.build()
+ check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
-@gen_with_app(buildername='html', testroot='numfig',
- confoverrides={'numfig': True,
- 'numfig_format': {'figure': 'Figure:%s',
- 'table': 'Tab_%s',
- 'code-block': 'Code-%s',
- 'section': 'SECTION-%s'}})
-def test_numfig_with_prefix(app, status, warning):
- app.builder.build_all()
-
+@pytest.mark.sphinx('html', testroot='numfig', confoverrides={
+ 'numfig': True,
+ 'numfig_format': {'figure': 'Figure:%s',
+ 'table': 'Tab_%s',
+ 'code-block': 'Code-%s',
+ 'section': 'SECTION-%s'}})
+@pytest.mark.test_params(shared_result='test_build_html_numfig_format_warn')
+def test_numfig_with_prefix_warn(app, warning):
+ app.build()
warnings = warning.getvalue()
assert 'index.rst:47: WARNING: numfig is disabled. :numref: is ignored.' not in warnings
assert 'index.rst:55: WARNING: no number is assigned for section: index' in warnings
assert 'index.rst:56: WARNING: invalid numfig_format: invalid' in warnings
assert 'index.rst:57: WARNING: invalid numfig_format: Fig %s %s' in warnings
- expects = {
- 'index.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Figure:1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Figure:2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Tab_1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Tab_2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Code-1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Code-2 $', True),
- (".//li/a/span", '^Figure:1$', True),
- (".//li/a/span", '^Figure2.2$', True),
- (".//li/a/span", '^Tab_1$', True),
- (".//li/a/span", '^Table:2.2$', True),
- (".//li/a/span", '^Code-1$', True),
- (".//li/a/span", '^Code-2.2$', True),
- (".//li/a/span", '^SECTION-1$', True),
- (".//li/a/span", '^SECTION-2.1$', True),
- (".//li/a/span", '^Fig.1 should be Fig.1$', True),
- (".//li/a/span", '^Sect.1 Foo$', True),
- ],
- 'foo.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Figure:1.1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Figure:1.2 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Figure:1.3 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Figure:1.4 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Tab_1.1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Tab_1.2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Tab_1.3 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Tab_1.4 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Code-1.1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Code-1.2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Code-1.3 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Code-1.4 $', True),
- ],
- 'bar.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Figure:2.1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Figure:2.3 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Figure:2.4 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Tab_2.1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Tab_2.3 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Tab_2.4 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Code-2.1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Code-2.3 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Code-2.4 $', True),
- ],
- 'baz.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Figure:2.2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Tab_2.2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Code-2.2 $', True),
- ],
- }
- for fname, paths in iteritems(expects):
- with (app.outdir / fname).open('rb') as fp:
- etree = HTML_PARSER.parse(fp)
-
- for xpath, check, be_found in paths:
- yield check_xpath, etree, fname, xpath, check, be_found
+@pytest.mark.parametrize("fname,expect", flat_dict({
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-2 $', True),
+ (".//li/a/span", '^Figure:1$', True),
+ (".//li/a/span", '^Figure2.2$', True),
+ (".//li/a/span", '^Tab_1$', True),
+ (".//li/a/span", '^Table:2.2$', True),
+ (".//li/a/span", '^Code-1$', True),
+ (".//li/a/span", '^Code-2.2$', True),
+ (".//li/a/span", '^SECTION-1$', True),
+ (".//li/a/span", '^SECTION-2.1$', True),
+ (".//li/a/span", '^Fig.1 should be Fig.1$', True),
+ (".//li/a/span", '^Sect.1 Foo$', True),
+ ],
+ 'foo.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:1.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:1.2 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:1.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:1.4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_1.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_1.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_1.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_1.4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-1.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-1.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-1.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-1.4 $', True),
+ ],
+ 'bar.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:2.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:2.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:2.4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_2.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_2.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_2.4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-2.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-2.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-2.4 $', True),
+ ],
+ 'baz.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:2.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_2.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-2.2 $', True),
+ ],
+}))
+@pytest.mark.sphinx('html', testroot='numfig', confoverrides={
+ 'numfig': True,
+ 'numfig_format': {'figure': 'Figure:%s',
+ 'table': 'Tab_%s',
+ 'code-block': 'Code-%s',
+ 'section': 'SECTION-%s'}})
+@pytest.mark.test_params(shared_result='test_build_html_numfig_format_warn')
+def test_numfig_with_prefix(app, cached_etree_parse, fname, expect):
+ app.build()
+ check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
-@gen_with_app(buildername='html', testroot='numfig',
- confoverrides={'numfig': True, 'numfig_secnum_depth': 2})
-def test_numfig_with_secnum_depth(app, status, warning):
- app.builder.build_all()
-
+@pytest.mark.sphinx('html', testroot='numfig', confoverrides={
+ 'numfig': True, 'numfig_secnum_depth': 2})
+@pytest.mark.test_params(shared_result='test_build_html_numfig_depth_2')
+def test_numfig_with_secnum_depth_warn(app, warning):
+ app.build()
warnings = warning.getvalue()
assert 'index.rst:47: WARNING: numfig is disabled. :numref: is ignored.' not in warnings
assert 'index.rst:55: WARNING: no number is assigned for section: index' in warnings
assert 'index.rst:56: WARNING: invalid numfig_format: invalid' in warnings
assert 'index.rst:57: WARNING: invalid numfig_format: Fig %s %s' in warnings
- expects = {
- 'index.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2 $', True),
- (".//li/a/span", '^Fig. 1$', True),
- (".//li/a/span", '^Figure2.1.2$', True),
- (".//li/a/span", '^Table 1$', True),
- (".//li/a/span", '^Table:2.1.2$', True),
- (".//li/a/span", '^Listing 1$', True),
- (".//li/a/span", '^Code-2.1.2$', True),
- (".//li/a/span", '^Section.1$', True),
- (".//li/a/span", '^Section.2.1$', True),
- (".//li/a/span", '^Fig.1 should be Fig.1$', True),
- (".//li/a/span", '^Sect.1 Foo$', True),
- ],
- 'foo.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.1.1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.1.2 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.2.1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.1.1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.1.2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.2.1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.1.1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.1.2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.2.1 $', True),
- ],
- 'bar.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.1.1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.1.3 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.2.1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.1.1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.1.3 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.2.1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.1.1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.1.3 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.2.1 $', True),
- ],
- 'baz.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.1.2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.1.2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.1.2 $', True),
- ],
- }
- for fname, paths in iteritems(expects):
- with (app.outdir / fname).open('rb') as fp:
- etree = HTML_PARSER.parse(fp)
-
- for xpath, check, be_found in paths:
- yield check_xpath, etree, fname, xpath, check, be_found
+@pytest.mark.parametrize("fname,expect", flat_dict({
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2 $', True),
+ (".//li/a/span", '^Fig. 1$', True),
+ (".//li/a/span", '^Figure2.1.2$', True),
+ (".//li/a/span", '^Table 1$', True),
+ (".//li/a/span", '^Table:2.1.2$', True),
+ (".//li/a/span", '^Listing 1$', True),
+ (".//li/a/span", '^Code-2.1.2$', True),
+ (".//li/a/span", '^Section.1$', True),
+ (".//li/a/span", '^Section.2.1$', True),
+ (".//li/a/span", '^Fig.1 should be Fig.1$', True),
+ (".//li/a/span", '^Sect.1 Foo$', True),
+ ],
+ 'foo.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.1.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.1.2 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.2.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.1.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.1.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.2.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.1.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.1.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.2.1 $', True),
+ ],
+ 'bar.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.1.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.1.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.2.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.1.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.1.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.2.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.1.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.1.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.2.1 $', True),
+ ],
+ 'baz.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.1.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.1.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.1.2 $', True),
+ ],
+}))
+@pytest.mark.sphinx('html', testroot='numfig', confoverrides={
+ 'numfig': True, 'numfig_secnum_depth': 2})
+@pytest.mark.test_params(shared_result='test_build_html_numfig_depth_2')
+def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
+ app.build()
+ check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
-@gen_with_app(buildername='singlehtml', testroot='numfig',
- confoverrides={'numfig': True})
-def test_numfig_with_singlehtml(app, status, warning):
- app.builder.build_all()
-
- expects = {
- 'index.html': [
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2 $', True),
- (".//li/a/span", '^Fig. 1$', True),
- (".//li/a/span", '^Figure2.2$', True),
- (".//li/a/span", '^Table 1$', True),
- (".//li/a/span", '^Table:2.2$', True),
- (".//li/a/span", '^Listing 1$', True),
- (".//li/a/span", '^Code-2.2$', True),
- (".//li/a/span", '^Section.1$', True),
- (".//li/a/span", '^Section.2.1$', True),
- (".//li/a/span", '^Fig.1 should be Fig.1$', True),
- (".//li/a/span", '^Sect.1 Foo$', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.2 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.3 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 1.4 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.3 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 1.4 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.3 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 1.4 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.1 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.3 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.4 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.1 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.3 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.4 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.1 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.3 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.4 $', True),
- (".//div[@class='figure']/p[@class='caption']/"
- "span[@class='caption-number']", '^Fig. 2.2 $', True),
- (".//table/caption/span[@class='caption-number']",
- '^Table 2.2 $', True),
- (".//div[@class='code-block-caption']/"
- "span[@class='caption-number']", '^Listing 2.2 $', True),
- ],
- }
-
- for fname, paths in iteritems(expects):
- with (app.outdir / fname).open('rb') as fp:
- etree = HTML_PARSER.parse(fp)
-
- for xpath, check, be_found in paths:
- yield check_xpath, etree, fname, xpath, check, be_found
+@pytest.mark.parametrize("fname,expect", flat_dict({
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2 $', True),
+ (".//li/a/span", '^Fig. 1$', True),
+ (".//li/a/span", '^Figure2.2$', True),
+ (".//li/a/span", '^Table 1$', True),
+ (".//li/a/span", '^Table:2.2$', True),
+ (".//li/a/span", '^Listing 1$', True),
+ (".//li/a/span", '^Code-2.2$', True),
+ (".//li/a/span", '^Section.1$', True),
+ (".//li/a/span", '^Section.2.1$', True),
+ (".//li/a/span", '^Fig.1 should be Fig.1$', True),
+ (".//li/a/span", '^Sect.1 Foo$', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.2 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.4 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.4 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.2 $', True),
+ ],
+}))
+@pytest.mark.sphinx('singlehtml', testroot='numfig', confoverrides={
+ 'numfig': True})
+@pytest.mark.test_params(shared_result='test_build_html_numfig_on')
+def test_numfig_with_singlehtml(app, cached_etree_parse, fname, expect):
+ app.build()
+ check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
-@gen_with_app(buildername='html', testroot='add_enumerable_node')
-def test_enumerable_node(app, status, warning):
- app.builder.build_all()
-
- expects = {
- 'index.html': [
- (".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']",
- "Fig. 1", True),
- (".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']",
- "Fig. 2", True),
- (".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']",
- "Fig. 3", True),
- (".//div//span[@class='caption-number']", "No.1 ", True),
- (".//div//span[@class='caption-number']", "No.2 ", True),
- (".//li/a/span", 'Fig. 1', True),
- (".//li/a/span", 'Fig. 2', True),
- (".//li/a/span", 'Fig. 3', True),
- (".//li/a/span", 'No.1', True),
- (".//li/a/span", 'No.2', True),
- ],
- }
-
- for fname, paths in iteritems(expects):
- with (app.outdir / fname).open('rb') as fp:
- etree = HTML_PARSER.parse(fp)
-
- for xpath, check, be_found in paths:
- yield check_xpath, etree, fname, xpath, check, be_found
+@pytest.mark.parametrize("fname,expect", flat_dict({
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']",
+ "Fig. 1", True),
+ (".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']",
+ "Fig. 2", True),
+ (".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']",
+ "Fig. 3", True),
+ (".//div//span[@class='caption-number']", "No.1 ", True),
+ (".//div//span[@class='caption-number']", "No.2 ", True),
+ (".//li/a/span", 'Fig. 1', True),
+ (".//li/a/span", 'Fig. 2', True),
+ (".//li/a/span", 'Fig. 3', True),
+ (".//li/a/span", 'No.1', True),
+ (".//li/a/span", 'No.2', True),
+ ],
+}))
+@pytest.mark.sphinx(
+ 'html', testroot='add_enumerable_node',
+ srcdir='test_enumerable_node',
+)
+def test_enumerable_node(app, cached_etree_parse, fname, expect):
+ app.build()
+ check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
-@with_app(buildername='html', testroot='html_assets')
-def test_html_assets(app, status, warning):
+@pytest.mark.sphinx('html', testroot='html_assets')
+def test_html_assets(app):
app.builder.build_all()
# html_static_path
@@ -1112,8 +1126,8 @@ def test_html_assets(app, status, warning):
assert not (app.outdir / 'subdir' / '.htpasswd').exists()
-@with_app(buildername='html', confoverrides={'html_sourcelink_suffix': ''})
-def test_html_sourcelink_suffix(app, status, warning):
+@pytest.mark.sphinx('html', confoverrides={'html_sourcelink_suffix': ''})
+def test_html_sourcelink_suffix(app):
app.builder.build_all()
content_otherext = (app.outdir / 'otherext.html').text()
content_images = (app.outdir / 'images.html').text()
diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py
index dfcadc6a1..027df463a 100644
--- a/tests/test_build_latex.py
+++ b/tests/test_build_latex.py
@@ -12,17 +12,17 @@ from __future__ import print_function
import os
import re
-from functools import wraps
from itertools import product
from subprocess import Popen, PIPE
from six import PY3
+import pytest
from sphinx.errors import SphinxError
from sphinx.util.osutil import cd, ensuredir
from sphinx.writers.latex import LaTeXTranslator
-from util import SkipTest, remove_unicode_literals, with_app, strip_escseq, skip_if
+from util import SkipTest, remove_unicode_literals, strip_escseq, skip_if
from test_build_html import ENV_WARNINGS
@@ -90,14 +90,13 @@ def skip_if_stylefiles_notfound(testfunc):
return testfunc
-def test_latex():
- for engine, docclass in product(LATEX_ENGINES, DOCCLASSES):
- yield build_latex_doc, engine, docclass
-
-
@skip_if_stylefiles_notfound
-@with_app(buildername='latex')
-def build_latex_doc(app, status, warning, engine, docclass):
+@pytest.mark.parametrize(
+ "engine,docclass",
+ product(LATEX_ENGINES, DOCCLASSES),
+)
+@pytest.mark.sphinx('latex')
+def test_build_latex_doc(app, status, warning, engine, docclass):
app.config.latex_engine = engine
app.config.latex_documents[0] = app.config.latex_documents[0][:4] + (docclass,)
@@ -110,7 +109,7 @@ def build_latex_doc(app, status, warning, engine, docclass):
compile_latex_document(app)
-@with_app(buildername='latex')
+@pytest.mark.sphinx('latex')
def test_writer(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
@@ -138,7 +137,7 @@ def test_writer(app, status, warning):
'\\end{wrapfigure}' in result)
-@with_app(buildername='latex', testroot='warnings', freshenv=True)
+@pytest.mark.sphinx('latex', testroot='warnings', freshenv=True)
def test_latex_warnings(app, status, warning):
app.builder.build_all()
@@ -151,7 +150,7 @@ def test_latex_warnings(app, status, warning):
'--- Got:\n' + warnings
-@with_app(buildername='latex', testroot='basic')
+@pytest.mark.sphinx('latex', testroot='basic')
def test_latex_title(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
@@ -161,7 +160,7 @@ def test_latex_title(app, status, warning):
assert '\\title{The basic Sphinx documentation for testing}' in result
-@with_app(buildername='latex', testroot='latex-title')
+@pytest.mark.sphinx('latex', testroot='latex-title')
def test_latex_title_after_admonitions(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
@@ -171,7 +170,7 @@ def test_latex_title_after_admonitions(app, status, warning):
assert '\\title{test-latex-title}' in result
-@with_app(buildername='latex', testroot='numfig',
+@pytest.mark.sphinx('latex', testroot='numfig',
confoverrides={'numfig': True})
def test_numref(app, status, warning):
app.builder.build_all()
@@ -204,12 +203,13 @@ def test_numref(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
-@with_app(buildername='latex', testroot='numfig',
- confoverrides={'numfig': True,
- 'numfig_format': {'figure': 'Figure:%s',
- 'table': 'Tab_%s',
- 'code-block': 'Code-%s',
- 'section': 'SECTION-%s'}})
+@pytest.mark.sphinx(
+ 'latex', testroot='numfig',
+ confoverrides={'numfig': True,
+ 'numfig_format': {'figure': 'Figure:%s',
+ 'table': 'Tab_%s',
+ 'code-block': 'Code-%s',
+ 'section': 'SECTION-%s'}})
def test_numref_with_prefix1(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -247,12 +247,13 @@ def test_numref_with_prefix1(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
-@with_app(buildername='latex', testroot='numfig',
- confoverrides={'numfig': True,
- 'numfig_format': {'figure': 'Figure:%s.',
- 'table': 'Tab_%s:',
- 'code-block': 'Code-%s | ',
- 'section': 'SECTION_%s_'}})
+@pytest.mark.sphinx(
+ 'latex', testroot='numfig',
+ confoverrides={'numfig': True,
+ 'numfig_format': {'figure': 'Figure:%s.',
+ 'table': 'Tab_%s:',
+ 'code-block': 'Code-%s | ',
+ 'section': 'SECTION_%s_'}})
def test_numref_with_prefix2(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -286,8 +287,9 @@ def test_numref_with_prefix2(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
-@with_app(buildername='latex', testroot='numfig',
- confoverrides={'numfig': True, 'language': 'ja'})
+@pytest.mark.sphinx(
+ 'latex', testroot='numfig',
+ confoverrides={'numfig': True, 'language': 'ja'})
def test_numref_with_language_ja(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -319,7 +321,7 @@ def test_numref_with_language_ja(app, status, warning):
'\\nameref{\\detokenize{foo:foo}}}') in result
-@with_app(buildername='latex')
+@pytest.mark.sphinx('latex')
def test_latex_add_latex_package(app, status, warning):
app.add_latex_package('foo')
app.add_latex_package('bar', 'baz')
@@ -329,7 +331,7 @@ def test_latex_add_latex_package(app, status, warning):
assert '\\usepackage[baz]{bar}' in result
-@with_app(buildername='latex', testroot='latex-babel')
+@pytest.mark.sphinx('latex', testroot='latex-babel')
def test_babel_with_no_language_settings(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -348,8 +350,9 @@ def test_babel_with_no_language_settings(app, status, warning):
assert '\\shorthandoff' not in result
-@with_app(buildername='latex', testroot='latex-babel',
- confoverrides={'language': 'de'})
+@pytest.mark.sphinx(
+ 'latex', testroot='latex-babel',
+ confoverrides={'language': 'de'})
def test_babel_with_language_de(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -368,8 +371,9 @@ def test_babel_with_language_de(app, status, warning):
assert '\\shorthandoff{"}' in result
-@with_app(buildername='latex', testroot='latex-babel',
- confoverrides={'language': 'ru'})
+@pytest.mark.sphinx(
+ 'latex', testroot='latex-babel',
+ confoverrides={'language': 'ru'})
def test_babel_with_language_ru(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -389,8 +393,9 @@ def test_babel_with_language_ru(app, status, warning):
assert '\\shorthandoff' not in result
-@with_app(buildername='latex', testroot='latex-babel',
- confoverrides={'language': 'tr'})
+@pytest.mark.sphinx(
+ 'latex', testroot='latex-babel',
+ confoverrides={'language': 'tr'})
def test_babel_with_language_tr(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -409,8 +414,9 @@ def test_babel_with_language_tr(app, status, warning):
assert '\\shorthandoff{=}' in result
-@with_app(buildername='latex', testroot='latex-babel',
- confoverrides={'language': 'ja'})
+@pytest.mark.sphinx(
+ 'latex', testroot='latex-babel',
+ confoverrides={'language': 'ja'})
def test_babel_with_language_ja(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -428,8 +434,9 @@ def test_babel_with_language_ja(app, status, warning):
assert '\\shorthandoff' not in result
-@with_app(buildername='latex', testroot='latex-babel',
- confoverrides={'language': 'unknown'})
+@pytest.mark.sphinx(
+ 'latex', testroot='latex-babel',
+ confoverrides={'language': 'unknown'})
def test_babel_with_unknown_language(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -450,7 +457,7 @@ def test_babel_with_unknown_language(app, status, warning):
assert "WARNING: no Babel option known for language 'unknown'" in warning.getvalue()
-@with_app(buildername='latex')
+@pytest.mark.sphinx('latex')
def test_footnote(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
@@ -480,7 +487,7 @@ def test_footnote(app, status, warning):
'footnotes in table\n%\n\\end{footnotetext}') in result
-@with_app(buildername='latex', testroot='footnotes')
+@pytest.mark.sphinx('latex', testroot='footnotes')
def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -517,8 +524,9 @@ def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning):
assert '\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]' in result
-@with_app(buildername='latex', testroot='footnotes',
- confoverrides={'latex_show_urls': 'inline'})
+@pytest.mark.sphinx(
+ 'latex', testroot='footnotes',
+ confoverrides={'latex_show_urls': 'inline'})
def test_latex_show_urls_is_inline(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -560,8 +568,9 @@ def test_latex_show_urls_is_inline(app, status, warning):
'{sphinx-dev@googlegroups.com}') in result
-@with_app(buildername='latex', testroot='footnotes',
- confoverrides={'latex_show_urls': 'footnote'})
+@pytest.mark.sphinx(
+ 'latex', testroot='footnotes',
+ confoverrides={'latex_show_urls': 'footnote'})
def test_latex_show_urls_is_footnote(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -611,8 +620,9 @@ def test_latex_show_urls_is_footnote(app, status, warning):
'{sphinx-dev@googlegroups.com}\n') in result
-@with_app(buildername='latex', testroot='footnotes',
- confoverrides={'latex_show_urls': 'no'})
+@pytest.mark.sphinx(
+ 'latex', testroot='footnotes',
+ confoverrides={'latex_show_urls': 'no'})
def test_latex_show_urls_is_no(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -652,7 +662,7 @@ def test_latex_show_urls_is_no(app, status, warning):
'{sphinx-dev@googlegroups.com}\n') in result
-@with_app(buildername='latex', testroot='image-in-section')
+@pytest.mark.sphinx('latex', testroot='image-in-section')
def test_image_in_section(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -668,7 +678,7 @@ def test_image_in_section(app, status, warning):
assert ('\\chapter{Another section}' in result)
-@with_app(buildername='latex', confoverrides={'latex_logo': 'notfound.jpg'})
+@pytest.mark.sphinx('latex', confoverrides={'latex_logo': 'notfound.jpg'})
def test_latex_logo_if_not_found(app, status, warning):
try:
app.builder.build_all()
@@ -677,7 +687,7 @@ def test_latex_logo_if_not_found(app, status, warning):
assert isinstance(exc, SphinxError)
-@with_app(buildername='latex', testroot='toctree-maxdepth',
+@pytest.mark.sphinx('latex', testroot='toctree-maxdepth',
confoverrides={'latex_documents': [
('index', 'SphinxTests.tex', 'Sphinx Tests Documentation',
'Georg Brandl', 'manual'),
@@ -692,11 +702,12 @@ def test_toctree_maxdepth_manual(app, status, warning):
assert '\\setcounter{secnumdepth}' not in result
-@with_app(buildername='latex', testroot='toctree-maxdepth',
- confoverrides={'latex_documents': [
- ('index', 'SphinxTests.tex', 'Sphinx Tests Documentation',
- 'Georg Brandl', 'howto'),
- ]})
+@pytest.mark.sphinx(
+ 'latex', testroot='toctree-maxdepth',
+ confoverrides={'latex_documents': [
+ ('index', 'SphinxTests.tex', 'Sphinx Tests Documentation',
+ 'Georg Brandl', 'howto'),
+ ]})
def test_toctree_maxdepth_howto(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
@@ -707,8 +718,9 @@ def test_toctree_maxdepth_howto(app, status, warning):
assert '\\setcounter{secnumdepth}' not in result
-@with_app(buildername='latex', testroot='toctree-maxdepth',
- confoverrides={'master_doc': 'foo'})
+@pytest.mark.sphinx(
+ 'latex', testroot='toctree-maxdepth',
+ confoverrides={'master_doc': 'foo'})
def test_toctree_not_found(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -719,8 +731,9 @@ def test_toctree_not_found(app, status, warning):
assert '\\setcounter{secnumdepth}' not in result
-@with_app(buildername='latex', testroot='toctree-maxdepth',
- confoverrides={'master_doc': 'bar'})
+@pytest.mark.sphinx(
+ 'latex', testroot='toctree-maxdepth',
+ confoverrides={'master_doc': 'bar'})
def test_toctree_without_maxdepth(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -731,8 +744,9 @@ def test_toctree_without_maxdepth(app, status, warning):
assert '\\setcounter{secnumdepth}' not in result
-@with_app(buildername='latex', testroot='toctree-maxdepth',
- confoverrides={'master_doc': 'qux'})
+@pytest.mark.sphinx(
+ 'latex', testroot='toctree-maxdepth',
+ confoverrides={'master_doc': 'qux'})
def test_toctree_with_deeper_maxdepth(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -743,8 +757,9 @@ def test_toctree_with_deeper_maxdepth(app, status, warning):
assert '\\setcounter{secnumdepth}{3}' in result
-@with_app(buildername='latex', testroot='toctree-maxdepth',
- confoverrides={'latex_toplevel_sectioning': None})
+@pytest.mark.sphinx(
+ 'latex', testroot='toctree-maxdepth',
+ confoverrides={'latex_toplevel_sectioning': None})
def test_latex_toplevel_sectioning_is_None(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -754,8 +769,9 @@ def test_latex_toplevel_sectioning_is_None(app, status, warning):
assert '\\chapter{Foo}' in result
-@with_app(buildername='latex', testroot='toctree-maxdepth',
- confoverrides={'latex_toplevel_sectioning': 'part'})
+@pytest.mark.sphinx(
+ 'latex', testroot='toctree-maxdepth',
+ confoverrides={'latex_toplevel_sectioning': 'part'})
def test_latex_toplevel_sectioning_is_part(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -765,8 +781,9 @@ def test_latex_toplevel_sectioning_is_part(app, status, warning):
assert '\\part{Foo}' in result
-@with_app(buildername='latex', testroot='toctree-maxdepth',
- confoverrides={'latex_toplevel_sectioning': 'chapter'})
+@pytest.mark.sphinx(
+ 'latex', testroot='toctree-maxdepth',
+ confoverrides={'latex_toplevel_sectioning': 'chapter'})
def test_latex_toplevel_sectioning_is_chapter(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -776,8 +793,9 @@ def test_latex_toplevel_sectioning_is_chapter(app, status, warning):
assert '\\chapter{Foo}' in result
-@with_app(buildername='latex', testroot='toctree-maxdepth',
- confoverrides={'latex_toplevel_sectioning': 'section'})
+@pytest.mark.sphinx(
+ 'latex', testroot='toctree-maxdepth',
+ confoverrides={'latex_toplevel_sectioning': 'section'})
def test_latex_toplevel_sectioning_is_section(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
@@ -787,7 +805,7 @@ def test_latex_toplevel_sectioning_is_section(app, status, warning):
assert '\\section{Foo}' in result
@skip_if_stylefiles_notfound
-@with_app(buildername='latex', testroot='maxlistdepth')
+@pytest.mark.sphinx('latex', testroot='maxlistdepth')
def test_maxlistdepth_at_ten(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
diff --git a/tests/test_build_linkcheck.py b/tests/test_build_linkcheck.py
index 1d75135af..f776f772a 100644
--- a/tests/test_build_linkcheck.py
+++ b/tests/test_build_linkcheck.py
@@ -10,10 +10,10 @@
"""
from __future__ import print_function
-from util import with_app
+import pytest
-@with_app('linkcheck', testroot='linkcheck', freshenv=True)
+@pytest.mark.sphinx('linkcheck', testroot='linkcheck', freshenv=True)
def test_defaults(app, status, warning):
app.builder.build_all()
@@ -26,8 +26,9 @@ def test_defaults(app, status, warning):
assert len(content.splitlines()) == 1
-@with_app('linkcheck', testroot='linkcheck', freshenv=True,
- confoverrides={'linkcheck_anchors_ignore': ["^!", "^top$"]})
+@pytest.mark.sphinx(
+ 'linkcheck', testroot='linkcheck', freshenv=True,
+ confoverrides={'linkcheck_anchors_ignore': ["^!", "^top$"]})
def test_anchors_ignored(app, status, warning):
app.builder.build_all()
diff --git a/tests/test_build_manpage.py b/tests/test_build_manpage.py
index 8da2eaadd..b91a4fd29 100644
--- a/tests/test_build_manpage.py
+++ b/tests/test_build_manpage.py
@@ -10,10 +10,10 @@
"""
from __future__ import print_function
-from util import with_app
+import pytest
-@with_app(buildername='man')
+@pytest.mark.sphinx('man')
def test_all(app, status, warning):
app.builder.build_all()
assert (app.outdir / 'SphinxTests.1').exists()
diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py
index 06da311df..bd7bd6270 100644
--- a/tests/test_build_texinfo.py
+++ b/tests/test_build_texinfo.py
@@ -15,10 +15,11 @@ import re
from subprocess import Popen, PIPE
from six import PY3
+import pytest
from sphinx.writers.texinfo import TexinfoTranslator
-from util import SkipTest, remove_unicode_literals, with_app, strip_escseq
+from util import SkipTest, remove_unicode_literals, strip_escseq
from test_build_html import ENV_WARNINGS
@@ -33,7 +34,7 @@ if PY3:
TEXINFO_WARNINGS = remove_unicode_literals(TEXINFO_WARNINGS)
-@with_app(buildername='texinfo', testroot='warnings', freshenv=True)
+@pytest.mark.sphinx('texinfo', testroot='warnings', freshenv=True)
def test_texinfo_warnings(app, status, warning):
app.builder.build_all()
warnings = strip_escseq(warning.getvalue().replace(os.sep, '/'))
@@ -45,7 +46,7 @@ def test_texinfo_warnings(app, status, warning):
'--- Got:\n' + warnings
-@with_app(buildername='texinfo')
+@pytest.mark.sphinx('texinfo')
def test_texinfo(app, status, warning):
TexinfoTranslator.ignore_missing_images = True
app.builder.build_all()
diff --git a/tests/test_catalogs.py b/tests/test_catalogs.py
index ca6608490..7e395274c 100644
--- a/tests/test_catalogs.py
+++ b/tests/test_catalogs.py
@@ -10,15 +10,16 @@
"""
import shutil
-from nose.tools import with_setup
+import pytest
-from util import with_app, find_files, rootdir, tempdir
+from util import find_files, rootdir, tempdir
root = tempdir / 'test-intl'
build_dir = root / '_build'
locale_dir = build_dir / 'locale'
+@pytest.fixture
def setup_test():
# delete remnants left over after failed build
root.rmtree(True)
@@ -30,14 +31,15 @@ def setup_test():
copy_po.parent.makedirs()
shutil.copy(root / po, copy_po)
+ yield
-def teardown_test():
build_dir.rmtree(True)
-@with_setup(setup_test, teardown_test)
-@with_app(buildername='html', testroot='intl',
- confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
+@pytest.mark.usefixtures('setup_test')
+@pytest.mark.sphinx(
+ 'html', testroot='intl',
+ confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
def test_compile_all_catalogs(app, status, warning):
app.builder.compile_all_catalogs()
@@ -51,9 +53,10 @@ def test_compile_all_catalogs(app, status, warning):
assert actual == expect
-@with_setup(setup_test, teardown_test)
-@with_app(buildername='html', testroot='intl',
- confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
+@pytest.mark.usefixtures('setup_test')
+@pytest.mark.sphinx(
+ 'html', testroot='intl',
+ confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
def test_compile_specific_catalogs(app, status, warning):
catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
@@ -66,9 +69,10 @@ def test_compile_specific_catalogs(app, status, warning):
assert actual == set(['admonitions.mo'])
-@with_setup(setup_test, teardown_test)
-@with_app(buildername='html', testroot='intl',
- confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
+@pytest.mark.usefixtures('setup_test')
+@pytest.mark.sphinx(
+ 'html', testroot='intl',
+ confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
def test_compile_update_catalogs(app, status, warning):
app.builder.compile_update_catalogs()
diff --git a/tests/test_config.py b/tests/test_config.py
index 1b3c94957..4bf4d6c11 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -10,19 +10,19 @@
:license: BSD, see LICENSE for details.
"""
from six import PY3, iteritems
+import pytest
import mock
-from util import TestApp, with_app, gen_with_app, with_tempdir, \
- raises, raises_msg, assert_in, assert_not_in
-
import sphinx
from sphinx.config import Config
from sphinx.errors import ExtensionError, ConfigError, VersionRequirementError
-@with_app(confoverrides={'master_doc': 'master', 'nonexisting_value': 'True',
- 'latex_elements.docclass': 'scrartcl',
- 'modindex_common_prefix': 'path1,path2'})
+@pytest.mark.sphinx(confoverrides={
+ 'master_doc': 'master',
+ 'nonexisting_value': 'True',
+ 'latex_elements.docclass': 'scrartcl',
+ 'modindex_common_prefix': 'path1,path2'})
def test_core_config(app, status, warning):
cfg = app.config
@@ -55,11 +55,14 @@ def test_core_config(app, status, warning):
assert 'nonexisting_value' not in cfg
# invalid values
- raises(AttributeError, getattr, cfg, '_value')
- raises(AttributeError, getattr, cfg, 'nonexisting_value')
+ with pytest.raises(AttributeError):
+ getattr(cfg, '_value')
+ with pytest.raises(AttributeError):
+ getattr(cfg, 'nonexisting_value')
# non-value attributes are deleted from the namespace
- raises(AttributeError, getattr, cfg, 'sys')
+ with pytest.raises(AttributeError):
+ getattr(cfg, 'sys')
# setting attributes
cfg.project = 'Foo'
@@ -70,7 +73,6 @@ def test_core_config(app, status, warning):
assert cfg['project'] == cfg.project == 'Sphinx Tests'
-@with_app()
def test_extension_values(app, status, warning):
cfg = app.config
@@ -80,23 +82,26 @@ def test_extension_values(app, status, warning):
assert cfg.value_from_conf_py == 84
# no duplicate values allowed
- raises_msg(ExtensionError, 'already present', app.add_config_value,
- 'html_title', 'x', True)
- raises_msg(ExtensionError, 'already present', app.add_config_value,
- 'value_from_ext', 'x', True)
+ with pytest.raises(ExtensionError) as excinfo:
+ app.add_config_value('html_title', 'x', True)
+ assert 'already present' in str(excinfo.value)
+ with pytest.raises(ExtensionError) as excinfo:
+ app.add_config_value('value_from_ext', 'x', True)
+ assert 'already present' in str(excinfo.value)
-@with_tempdir
-def test_errors_warnings(dir):
+def test_errors_warnings(tempdir):
# test the error for syntax errors in the config file
- (dir / 'conf.py').write_text(u'project = \n', encoding='ascii')
- raises_msg(ConfigError, 'conf.py', Config, dir, 'conf.py', {}, None)
+ (tempdir / 'conf.py').write_text(u'project = \n', encoding='ascii')
+ with pytest.raises(ConfigError) as excinfo:
+ Config(tempdir, 'conf.py', {}, None)
+ assert 'conf.py' in str(excinfo.value)
# test the automatic conversion of 2.x only code in configs
- (dir / 'conf.py').write_text(
+ (tempdir / 'conf.py').write_text(
u'# -*- coding: utf-8\n\nproject = u"Jägermeister"\n',
encoding='utf-8')
- cfg = Config(dir, 'conf.py', {}, None)
+ cfg = Config(tempdir, 'conf.py', {}, None)
cfg.init_values(lambda warning: 1/0)
assert cfg.project == u'Jägermeister'
@@ -105,9 +110,9 @@ def test_errors_warnings(dir):
# skip the test there
if PY3:
return
- (dir / 'conf.py').write_text(
+ (tempdir / 'conf.py').write_text(
u'# -*- coding: latin-1\nproject = "fooä"\n', encoding='latin-1')
- cfg = Config(dir, 'conf.py', {}, None)
+ cfg = Config(tempdir, 'conf.py', {}, None)
warned = [False]
def warn(msg):
@@ -117,62 +122,64 @@ def test_errors_warnings(dir):
assert warned[0]
-@with_tempdir
-def test_errors_if_setup_is_not_callable(dir):
+def test_errors_if_setup_is_not_callable(tempdir, make_app):
# test the error to call setup() in the config file
- (dir / 'conf.py').write_text(u'setup = 1')
- raises_msg(ConfigError, 'callable', TestApp, srcdir=dir)
+ (tempdir / 'conf.py').write_text(u'setup = 1')
+ with pytest.raises(ConfigError) as excinfo:
+ make_app(srcdir=tempdir)
+ assert 'callable' in str(excinfo.value)
@mock.patch.object(sphinx, '__display_version__', '1.3.4')
-def test_needs_sphinx():
+def test_needs_sphinx(make_app):
# micro version
- app = TestApp(confoverrides={'needs_sphinx': '1.3.3'}) # OK: less
+ app = make_app(confoverrides={'needs_sphinx': '1.3.3'}) # OK: less
app.cleanup()
- app = TestApp(confoverrides={'needs_sphinx': '1.3.4'}) # OK: equals
+ app = make_app(confoverrides={'needs_sphinx': '1.3.4'}) # OK: equals
app.cleanup()
- raises(VersionRequirementError, TestApp,
- confoverrides={'needs_sphinx': '1.3.5'}) # NG: greater
+ with pytest.raises(VersionRequirementError):
+ make_app(confoverrides={'needs_sphinx': '1.3.5'}) # NG: greater
# minor version
- app = TestApp(confoverrides={'needs_sphinx': '1.2'}) # OK: less
+ app = make_app(confoverrides={'needs_sphinx': '1.2'}) # OK: less
app.cleanup()
- app = TestApp(confoverrides={'needs_sphinx': '1.3'}) # OK: equals
+ app = make_app(confoverrides={'needs_sphinx': '1.3'}) # OK: equals
app.cleanup()
- raises(VersionRequirementError, TestApp,
- confoverrides={'needs_sphinx': '1.4'}) # NG: greater
+ with pytest.raises(VersionRequirementError):
+ make_app(confoverrides={'needs_sphinx': '1.4'}) # NG: greater
# major version
- app = TestApp(confoverrides={'needs_sphinx': '0'}) # OK: less
+ app = make_app(confoverrides={'needs_sphinx': '0'}) # OK: less
app.cleanup()
- app = TestApp(confoverrides={'needs_sphinx': '1'}) # OK: equals
+ app = make_app(confoverrides={'needs_sphinx': '1'}) # OK: equals
app.cleanup()
- raises(VersionRequirementError, TestApp,
- confoverrides={'needs_sphinx': '2'}) # NG: greater
+ with pytest.raises(VersionRequirementError):
+ make_app(confoverrides={'needs_sphinx': '2'}) # NG: greater
-@with_tempdir
-def test_config_eol(tmpdir):
+def test_config_eol(tempdir):
# test config file's eol patterns: LF, CRLF
- configfile = tmpdir / 'conf.py'
+ configfile = tempdir / 'conf.py'
for eol in (b'\n', b'\r\n'):
configfile.write_bytes(b'project = "spam"' + eol)
- cfg = Config(tmpdir, 'conf.py', {}, None)
+ cfg = Config(tempdir, 'conf.py', {}, None)
cfg.init_values(lambda warning: 1/0)
assert cfg.project == u'spam'
-@with_app(confoverrides={'master_doc': 123,
+@pytest.mark.sphinx(confoverrides={'master_doc': 123,
'language': 'foo',
'primary_domain': None})
def test_builtin_conf(app, status, warning):
warnings = warning.getvalue()
- assert_in('master_doc', warnings,
- 'override on builtin "master_doc" should raise a type warning')
- assert_not_in('language', warnings, 'explicitly permitted '
- 'override on builtin "language" should NOT raise a type warning')
- assert_not_in('primary_domain', warnings, 'override to None on builtin '
- '"primary_domain" should NOT raise a type warning')
+ assert 'master_doc' in warnings, (
+ 'override on builtin "master_doc" should raise a type warning')
+ assert 'language' not in warnings, (
+ 'explicitly permitted override on builtin "language" should NOT raise '
+ 'a type warning')
+ assert 'primary_domain' not in warnings, (
+ 'override to None on builtin "primary_domain" should NOT raise a type '
+ 'warning')
# See roots/test-config/conf.py.
@@ -187,7 +194,7 @@ TYPECHECK_WARNINGS = {
'value8': False,
'value9': False,
'value10': False,
- 'value11': True,
+ 'value11': False if PY3 else True,
'value12': False,
'value13': False,
'value14': False,
@@ -196,25 +203,27 @@ TYPECHECK_WARNINGS = {
}
-@gen_with_app(testroot='config')
-def test_gen_check_types(app, status, warning):
- if PY3:
- TYPECHECK_WARNINGS['value11'] = False
-
- for key, should in iteritems(TYPECHECK_WARNINGS):
- yield assert_in if should else assert_not_in, key, warning.getvalue(), (
- 'override on "%s" should%s raise a type warning' %
- (key, '' if should else ' NOT')
+@pytest.mark.parametrize("key,should", iteritems(TYPECHECK_WARNINGS))
+@pytest.mark.sphinx(testroot='config')
+def test_check_types(warning, key, should):
+ warn = warning.getvalue()
+ if should:
+ assert key in warn, (
+ 'override on "%s" should raise a type warning' % key
+ )
+ else:
+ assert key not in warn, (
+ 'override on "%s" should NOT raise a type warning' % key
)
-@with_app(testroot='config')
+@pytest.mark.sphinx(testroot='config')
def test_check_enum(app, status, warning):
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
not in warning.getvalue()
-@with_app(testroot='config', confoverrides={'value17': 'invalid'})
+@pytest.mark.sphinx(testroot='config', confoverrides={'value17': 'invalid'})
def test_check_enum_failed(app, status, warning):
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
"but `invalid` is given." in warning.getvalue()
diff --git a/tests/test_correct_year.py b/tests/test_correct_year.py
index 2c2f0d812..574adb6f0 100644
--- a/tests/test_correct_year.py
+++ b/tests/test_correct_year.py
@@ -8,42 +8,30 @@
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-import os
-
-from util import TestApp
+import pytest
-def test_correct_year():
- try:
- # save current value of SOURCE_DATE_EPOCH
- sde = os.environ.pop('SOURCE_DATE_EPOCH', None)
-
+@pytest.fixture(
+ params=[
# test with SOURCE_DATE_EPOCH unset: no modification
- app = TestApp(buildername='html', testroot='correct-year')
- app.builder.build_all()
- content = (app.outdir / 'contents.html').text()
- app.cleanup()
- assert '2006-2009' in content
+ (None, '2006-2009'),
+ # test with SOURCE_DATE_EPOCH set: copyright year should be updated
+ ('1293840000', '2006-2011'),
+ ('1293839999', '2006-2010'),
+ ],
- # test with SOURCE_DATE_EPOCH set: copyright year should be
- # updated
- os.environ['SOURCE_DATE_EPOCH'] = "1293840000"
- app = TestApp(buildername='html', testroot='correct-year')
- app.builder.build_all()
- content = (app.outdir / 'contents.html').text()
- app.cleanup()
- assert '2006-2011' in content
+)
+def expect_date(request, monkeypatch):
+ sde, expect = request.param
+ if sde:
+ monkeypatch.setenv('SOURCE_DATE_EPOCH', sde)
+ else:
+ monkeypatch.delenv('SOURCE_DATE_EPOCH', raising=False)
+ yield expect
- os.environ['SOURCE_DATE_EPOCH'] = "1293839999"
- app = TestApp(buildername='html', testroot='correct-year')
- app.builder.build_all()
- content = (app.outdir / 'contents.html').text()
- app.cleanup()
- assert '2006-2010' in content
- finally:
- # Restores SOURCE_DATE_EPOCH
- if sde is None:
- os.environ.pop('SOURCE_DATE_EPOCH', None)
- else:
- os.environ['SOURCE_DATE_EPOCH'] = sde
+@pytest.mark.sphinx('html', testroot='correct-year')
+def test_correct_year(expect_date, app):
+ app.build()
+ content = (app.outdir / 'contents.html').text()
+ assert expect_date in content
diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py
index cb6221355..f168eafbe 100644
--- a/tests/test_directive_code.py
+++ b/tests/test_directive_code.py
@@ -9,10 +9,12 @@
:license: BSD, see LICENSE for details.
"""
-from util import with_app, etree_parse
+import pytest
+
+from util import etree_parse
-@with_app('xml', testroot='directive-code')
+@pytest.mark.sphinx('xml', testroot='directive-code')
def test_code_block(app, status, warning):
app.builder.build('index')
et = etree_parse(app.outdir / 'index.xml')
@@ -28,7 +30,7 @@ def test_code_block(app, status, warning):
assert actual == expect
-@with_app('xml', testroot='directive-code')
+@pytest.mark.sphinx('xml', testroot='directive-code')
def test_code_block_dedent(app, status, warning):
app.builder.build(['dedent_code'])
et = etree_parse(app.outdir / 'dedent_code.xml')
@@ -47,7 +49,7 @@ def test_code_block_dedent(app, status, warning):
assert blocks[5].text == '\n\n' # dedent: 1000
-@with_app('html', testroot='directive-code')
+@pytest.mark.sphinx('html', testroot='directive-code')
def test_code_block_caption_html(app, status, warning):
app.builder.build(['caption'])
html = (app.outdir / 'caption.html').text(encoding='utf-8')
@@ -59,7 +61,7 @@ def test_code_block_caption_html(app, status, warning):
assert caption in html
-@with_app('latex', testroot='directive-code')
+@pytest.mark.sphinx('latex', testroot='directive-code')
def test_code_block_caption_latex(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
@@ -72,7 +74,7 @@ def test_code_block_caption_latex(app, status, warning):
assert link in latex
-@with_app('latex', testroot='directive-code')
+@pytest.mark.sphinx('latex', testroot='directive-code')
def test_code_block_namedlink_latex(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
@@ -89,7 +91,7 @@ def test_code_block_namedlink_latex(app, status, warning):
assert link2 in latex
-@with_app('xml', testroot='directive-code')
+@pytest.mark.sphinx('xml', testroot='directive-code')
def test_literal_include(app, status, warning):
app.builder.build(['index'])
et = etree_parse(app.outdir / 'index.xml')
@@ -101,7 +103,7 @@ def test_literal_include(app, status, warning):
assert actual == literal_src
-@with_app('xml', testroot='directive-code')
+@pytest.mark.sphinx('xml', testroot='directive-code')
def test_literal_include_dedent(app, status, warning):
literal_src = (app.srcdir / 'literal.inc').text(encoding='utf-8')
literal_lines = [l[4:] for l in literal_src.split('\n')[9:11]]
@@ -119,7 +121,7 @@ def test_literal_include_dedent(app, status, warning):
assert blocks[5].text == '\n\n' # dedent: 1000
-@with_app('xml', testroot='directive-code')
+@pytest.mark.sphinx('xml', testroot='directive-code')
def test_literal_include_block_start_with_comment_or_brank(app, status, warning):
app.builder.build(['python'])
et = etree_parse(app.outdir / 'python.xml')
@@ -143,7 +145,7 @@ def test_literal_include_block_start_with_comment_or_brank(app, status, warning)
assert actual == expect
-@with_app('html', testroot='directive-code')
+@pytest.mark.sphinx('html', testroot='directive-code')
def test_literal_include_linenos(app, status, warning):
app.builder.build(['linenos'])
html = (app.outdir / 'linenos.html').text(encoding='utf-8')
@@ -166,7 +168,7 @@ def test_literal_include_linenos(app, status, warning):
assert linenos in html
-@with_app('html', testroot='directive-code')
+@pytest.mark.sphinx('html', testroot='directive-code')
def test_literal_include_lineno_start(app, status, warning):
app.builder.build(['lineno_start'])
html = (app.outdir / 'lineno_start.html').text(encoding='utf-8')
@@ -189,7 +191,7 @@ def test_literal_include_lineno_start(app, status, warning):
assert linenos in html
-@with_app('html', testroot='directive-code')
+@pytest.mark.sphinx('html', testroot='directive-code')
def test_literal_include_lineno_match(app, status, warning):
app.builder.build(['lineno_match'])
html = (app.outdir / 'lineno_match.html').text(encoding='utf-8')
@@ -229,7 +231,7 @@ def test_literal_include_lineno_match(app, status, warning):
assert start_at_end_at in html
-@with_app('latex', testroot='directive-code')
+@pytest.mark.sphinx('latex', testroot='directive-code')
def test_literalinclude_file_whole_of_emptyline(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8').replace('\r\n', '\n')
@@ -243,7 +245,7 @@ def test_literalinclude_file_whole_of_emptyline(app, status, warning):
assert includes in latex
-@with_app('html', testroot='directive-code')
+@pytest.mark.sphinx('html', testroot='directive-code')
def test_literalinclude_caption_html(app, status, warning):
app.builder.build('index')
html = (app.outdir / 'caption.html').text(encoding='utf-8')
@@ -255,7 +257,7 @@ def test_literalinclude_caption_html(app, status, warning):
assert caption in html
-@with_app('latex', testroot='directive-code')
+@pytest.mark.sphinx('latex', testroot='directive-code')
def test_literalinclude_caption_latex(app, status, warning):
app.builder.build('index')
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
@@ -268,7 +270,7 @@ def test_literalinclude_caption_latex(app, status, warning):
assert link in latex
-@with_app('latex', testroot='directive-code')
+@pytest.mark.sphinx('latex', testroot='directive-code')
def test_literalinclude_namedlink_latex(app, status, warning):
app.builder.build('index')
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
@@ -285,7 +287,7 @@ def test_literalinclude_namedlink_latex(app, status, warning):
assert link2 in latex
-@with_app('xml', testroot='directive-code')
+@pytest.mark.sphinx('xml', testroot='directive-code')
def test_literalinclude_classes(app, status, warning):
app.builder.build(['classes'])
et = etree_parse(app.outdir / 'classes.xml')
diff --git a/tests/test_directive_only.py b/tests/test_directive_only.py
index def064c5a..30b569a12 100644
--- a/tests/test_directive_only.py
+++ b/tests/test_directive_only.py
@@ -13,11 +13,10 @@ import re
from docutils import nodes
from sphinx.util.nodes import process_only_nodes
-
-from util import with_app
+import pytest
-@with_app('text', testroot='directive-only')
+@pytest.mark.sphinx('text', testroot='directive-only')
def test_sectioning(app, status, warning):
def getsects(section):
diff --git a/tests/test_docutilsconf.py b/tests/test_docutilsconf.py
index ebd0782bd..89ec63107 100644
--- a/tests/test_docutilsconf.py
+++ b/tests/test_docutilsconf.py
@@ -11,14 +11,15 @@
import re
-from util import with_app, path, SkipTest
+import pytest
+from util import path, SkipTest
def regex_count(expr, result):
return len(re.findall(expr, result))
-@with_app('html', testroot='docutilsconf', freshenv=True, docutilsconf='')
+@pytest.mark.sphinx('html', testroot='docutilsconf', freshenv=True, docutilsconf='')
def test_html_with_default_docutilsconf(app, status, warning):
app.builder.build(['contents'])
result = (app.outdir / 'contents.html').text(encoding='utf-8')
@@ -29,7 +30,7 @@ def test_html_with_default_docutilsconf(app, status, warning):
assert regex_count(r'| ', result) == 1
-@with_app('html', testroot='docutilsconf', freshenv=True, docutilsconf=(
+@pytest.mark.sphinx('html', testroot='docutilsconf', freshenv=True, docutilsconf=(
'\n[html4css1 writer]'
'\noption-limit:1'
'\nfield-name-limit:1'
@@ -45,31 +46,31 @@ def test_html_with_docutilsconf(app, status, warning):
assert regex_count(r' | ', result) == 2
-@with_app('html', testroot='docutilsconf')
+@pytest.mark.sphinx('html', testroot='docutilsconf')
def test_html(app, status, warning):
app.builder.build(['contents'])
assert warning.getvalue() == ''
-@with_app('latex', testroot='docutilsconf')
+@pytest.mark.sphinx('latex', testroot='docutilsconf')
def test_latex(app, status, warning):
app.builder.build(['contents'])
assert warning.getvalue() == ''
-@with_app('man', testroot='docutilsconf')
+@pytest.mark.sphinx('man', testroot='docutilsconf')
def test_man(app, status, warning):
app.builder.build(['contents'])
assert warning.getvalue() == ''
-@with_app('texinfo', testroot='docutilsconf')
+@pytest.mark.sphinx('texinfo', testroot='docutilsconf')
def test_texinfo(app, status, warning):
app.builder.build(['contents'])
-@with_app('html', testroot='docutilsconf',
- docutilsconf='[general]\nsource_link=true\n')
+@pytest.mark.sphinx('html', testroot='docutilsconf',
+ docutilsconf='[general]\nsource_link=true\n')
def test_docutils_source_link_with_nonascii_file(app, status, warning):
srcdir = path(app.srcdir)
mb_name = u'\u65e5\u672c\u8a9e'
diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py
index 4a505119d..58e6093ba 100644
--- a/tests/test_domain_cpp.py
+++ b/tests/test_domain_cpp.py
@@ -12,8 +12,7 @@
import re
from six import text_type
-
-from util import raises, with_app
+import pytest
from sphinx import addnodes
from sphinx.domains.cpp import DefinitionParser, DefinitionError, NoOldIdError
@@ -150,9 +149,10 @@ def test_concept_definitions():
None, 'I0EN1A1B7ConceptE')
check('concept', 'template Foo()',
None, 'I00DpE3Foo')
- raises(DefinitionError, parse, 'concept', 'Foo')
- raises(DefinitionError, parse, 'concept',
- 'template template Foo')
+ with pytest.raises(DefinitionError):
+ parse('concept', 'Foo')
+ with pytest.raises(DefinitionError):
+ parse('concept', 'template template Foo')
def test_member_definitions():
@@ -259,9 +259,12 @@ def test_function_definitions():
'int foo(Foo f = Foo(double(), std::make_pair(int(2), double(3.4))))',
"foo__Foo", "3foo3Foo")
check('function', 'int foo(A a = x(a))', "foo__A", "3foo1A")
- raises(DefinitionError, parse, 'function', 'int foo(B b=x(a)')
- raises(DefinitionError, parse, 'function', 'int foo)C c=x(a))')
- raises(DefinitionError, parse, 'function', 'int foo(D d=x(a')
+ with pytest.raises(DefinitionError):
+ parse('function', 'int foo(B b=x(a)')
+ with pytest.raises(DefinitionError):
+ parse('function', 'int foo)C c=x(a))')
+ with pytest.raises(DefinitionError):
+ parse('function', 'int foo(D d=x(a')
check('function', 'int foo(const A&... a)', "foo__ACRDp", "3fooDpRK1A")
check('function', 'virtual void f()', "f", "1fv")
# test for ::nestedName, from issue 1738
@@ -382,8 +385,10 @@ def test_templates():
check('function', "template<> void A()", None, "IE1Av")
check('member', "template<> A a", None, "IE1a")
check('type', "template<> a = A", None, "IE1a")
- raises(DefinitionError, parse, 'enum', "template<> A")
- raises(DefinitionError, parse, 'enumerator', "template<> A")
+ with pytest.raises(DefinitionError):
+ parse('enum', "template<> A")
+ with pytest.raises(DefinitionError):
+ parse('enumerator', "template<> A")
# then all the real tests
check('class', "template A", None, "I00E1A")
check('type', "template<> a", None, "IE1a")
@@ -419,8 +424,10 @@ def test_templates():
"RK18c_string_view_baseIK4Char6TraitsE")
# template introductions
- raises(DefinitionError, parse, 'enum', 'abc::ns::foo{id_0, id_1, id_2} A')
- raises(DefinitionError, parse, 'enumerator', 'abc::ns::foo{id_0, id_1, id_2} A')
+ with pytest.raises(DefinitionError):
+ parse('enum', 'abc::ns::foo{id_0, id_1, id_2} A')
+ with pytest.raises(DefinitionError):
+ parse('enumerator', 'abc::ns::foo{id_0, id_1, id_2} A')
check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar',
None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE')
check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar',
@@ -469,12 +476,18 @@ def test_attributes():
check('member', 'paren_attr(a) int f', 'f__i', '1f')
check('member', 'paren_attr("") int f', 'f__i', '1f')
check('member', 'paren_attr(()[{}][]{}) int f', 'f__i', '1f')
- raises(DefinitionError, parse, 'member', 'paren_attr(() int f')
- raises(DefinitionError, parse, 'member', 'paren_attr([) int f')
- raises(DefinitionError, parse, 'member', 'paren_attr({) int f')
- raises(DefinitionError, parse, 'member', 'paren_attr([)]) int f')
- raises(DefinitionError, parse, 'member', 'paren_attr((])) int f')
- raises(DefinitionError, parse, 'member', 'paren_attr({]}) int f')
+ with pytest.raises(DefinitionError):
+ parse('member', 'paren_attr(() int f')
+ with pytest.raises(DefinitionError):
+ parse('member', 'paren_attr([) int f')
+ with pytest.raises(DefinitionError):
+ parse('member', 'paren_attr({) int f')
+ with pytest.raises(DefinitionError):
+ parse('member', 'paren_attr([)]) int f')
+ with pytest.raises(DefinitionError):
+ parse('member', 'paren_attr((])) int f')
+ with pytest.raises(DefinitionError):
+ parse('member', 'paren_attr({]}) int f')
# position: decl specs
check('function', 'static inline __attribute__(()) void f()',
@@ -490,7 +503,7 @@ def test_attributes():
# raise DefinitionError("")
-@with_app(testroot='domain-cpp', confoverrides={'add_function_parentheses': True})
+@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={'add_function_parentheses': True})
def test_build_domain_cpp_with_add_function_parentheses_is_True(app, status, warning):
app.builder.build_all()
@@ -527,7 +540,8 @@ def test_build_domain_cpp_with_add_function_parentheses_is_True(app, status, war
check(s, t, f)
-@with_app(testroot='domain-cpp', confoverrides={'add_function_parentheses': False})
+@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={
+ 'add_function_parentheses': False})
def test_build_domain_cpp_with_add_function_parentheses_is_False(app, status, warning):
app.builder.build_all()
diff --git a/tests/test_environment.py b/tests/test_environment.py
index f65a6f3f0..476b66923 100644
--- a/tests/test_environment.py
+++ b/tests/test_environment.py
@@ -9,9 +9,7 @@
:license: BSD, see LICENSE for details.
"""
-from six import PY3
-
-from util import TestApp, remove_unicode_literals, path
+from util import SphinxTestApp, path
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.builders.latex import LaTeXBuilder
@@ -22,7 +20,7 @@ warnings = []
def setup_module():
global app, env
- app = TestApp(srcdir='root-envtest')
+ app = SphinxTestApp(srcdir='root-envtest')
env = app.env
env.set_warnfunc(lambda *args, **kwargs: warnings.append(args))
@@ -54,7 +52,6 @@ def test_images():
'http://www.python.org/logo.png')
tree = env.get_doctree('images')
- app._warning.reset()
htmlbuilder = StandaloneHTMLBuilder(app)
htmlbuilder.imgpath = 'dummy'
htmlbuilder.post_process_images(tree)
@@ -64,7 +61,6 @@ def test_images():
assert set(htmlbuilder.images.values()) == \
set(['img.png', 'img1.png', 'simg.png', 'svgimg.svg', 'img.foo.png'])
- app._warning.reset()
latexbuilder = LaTeXBuilder(app)
latexbuilder.post_process_images(tree)
assert set(latexbuilder.images.keys()) == \
diff --git a/tests/test_environment_toctree.py b/tests/test_environment_toctree.py
index 20188c16a..595f922ae 100644
--- a/tests/test_environment_toctree.py
+++ b/tests/test_environment_toctree.py
@@ -14,24 +14,15 @@ from docutils.nodes import bullet_list, list_item, caption, comment, reference
from sphinx import addnodes
from sphinx.addnodes import compact_paragraph, only
from sphinx.builders.html import StandaloneHTMLBuilder
+import pytest
-from util import with_app, gen_with_app, assert_node
+from util import assert_node
-@gen_with_app('xml', testroot='toctree')
-def test_basic(app, status, warning):
+@pytest.mark.sphinx('xml', testroot='toctree')
+@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
+def test_process_doc(app):
app.build()
- yield _test_process_doc, app
- yield _test_get_toc_for, app
- yield _test_get_toc_for_only, app
- yield _test_get_toc_for_tocdepth, app
- yield _test_get_toctree_for, app
- yield _test_get_toctree_for_collapse, app
- yield _test_get_toctree_for_maxdepth, app
- yield _test_get_toctree_for_includehidden, app
-
-
-def _test_process_doc(app):
# tocs
toctree = app.env.tocs['index']
assert_node(toctree,
@@ -97,8 +88,8 @@ def _test_process_doc(app):
assert 'qux' not in app.env.toctree_includes
-@with_app('dummy', testroot='toctree-glob')
-def test_glob(app, status, warning):
+@pytest.mark.sphinx('dummy', testroot='toctree-glob')
+def test_glob(app):
includefiles = ['foo', 'bar/index', 'bar/bar_1', 'bar/bar_2',
'bar/bar_3', 'baz', 'qux/index']
@@ -143,7 +134,10 @@ def test_glob(app, status, warning):
assert app.env.numbered_toctrees == set()
-def _test_get_toc_for(app):
+@pytest.mark.sphinx('xml', testroot='toctree')
+@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
+def test_get_toc_for(app):
+ app.build()
toctree = app.env.get_toc_for('index', app.builder)
assert_node(toctree,
@@ -166,7 +160,10 @@ def _test_get_toc_for(app):
[compact_paragraph, reference, "Indices and tables"])
-def _test_get_toc_for_only(app):
+@pytest.mark.sphinx('xml', testroot='toctree')
+@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
+def test_get_toc_for_only(app):
+ app.build()
builder = StandaloneHTMLBuilder(app)
toctree = app.env.get_toc_for('index', builder)
@@ -193,7 +190,10 @@ def _test_get_toc_for_only(app):
[compact_paragraph, reference, "Indices and tables"])
-def _test_get_toc_for_tocdepth(app):
+@pytest.mark.sphinx('xml', testroot='toctree')
+@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
+def test_get_toc_for_tocdepth(app):
+ app.build()
toctree = app.env.get_toc_for('tocdepth', app.builder)
assert_node(toctree,
@@ -205,7 +205,10 @@ def _test_get_toc_for_tocdepth(app):
[bullet_list, list_item, compact_paragraph, reference, "level 2"])
-def _test_get_toctree_for(app):
+@pytest.mark.sphinx('xml', testroot='toctree')
+@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
+def test_get_toctree_for(app):
+ app.build()
toctree = app.env.get_toctree_for('index', app.builder, collapse=False)
assert_node(toctree,
[compact_paragraph, ([caption, "Table of Contents"],
@@ -239,7 +242,10 @@ def _test_get_toctree_for(app):
assert_node(toctree[3][1][0][0], reference, refuri="http://python.org/")
-def _test_get_toctree_for_collapse(app):
+@pytest.mark.sphinx('xml', testroot='toctree')
+@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
+def test_get_toctree_for_collapse(app):
+ app.build()
toctree = app.env.get_toctree_for('index', app.builder, collapse=True)
assert_node(toctree,
[compact_paragraph, ([caption, "Table of Contents"],
@@ -264,7 +270,10 @@ def _test_get_toctree_for_collapse(app):
assert_node(toctree[3][1][0][0], reference, refuri="http://python.org/")
-def _test_get_toctree_for_maxdepth(app):
+@pytest.mark.sphinx('xml', testroot='toctree')
+@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
+def test_get_toctree_for_maxdepth(app):
+ app.build()
toctree = app.env.get_toctree_for('index', app.builder, collapse=False, maxdepth=3)
assert_node(toctree,
[compact_paragraph, ([caption, "Table of Contents"],
@@ -303,7 +312,10 @@ def _test_get_toctree_for_maxdepth(app):
assert_node(toctree[3][1][0][0], reference, refuri="http://python.org/")
-def _test_get_toctree_for_includehidden(app):
+@pytest.mark.sphinx('xml', testroot='toctree')
+@pytest.mark.test_params(shared_result='test_environment_toctree_basic')
+def test_get_toctree_for_includehidden(app):
+ app.build()
toctree = app.env.get_toctree_for('index', app.builder, collapse=False,
includehidden=False)
assert_node(toctree,
diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py
index dad7521af..873fc23c9 100644
--- a/tests/test_ext_autodoc.py
+++ b/tests/test_ext_autodoc.py
@@ -10,12 +10,11 @@
"""
import pickle
-from docutils import nodes
+import pytest
from sphinx import addnodes
-from util import with_app
-@with_app(buildername='dummy', testroot='ext-autodoc')
+@pytest.mark.sphinx('dummy', testroot='ext-autodoc')
def test_autodoc(app, status, warning):
app.builder.build_all()
diff --git a/tests/test_ext_autosectionlabel.py b/tests/test_ext_autosectionlabel.py
index ff7cd6776..71d19e800 100644
--- a/tests/test_ext_autosectionlabel.py
+++ b/tests/test_ext_autosectionlabel.py
@@ -11,10 +11,10 @@
import re
-from util import with_app
+import pytest
-@with_app('html', testroot='ext-autosectionlabel')
+@pytest.mark.sphinx('html', testroot='ext-autosectionlabel')
def test_autosectionlabel_html(app, status, warning):
app.builder.build_all()
diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py
index f8a8a3900..84c73d632 100644
--- a/tests/test_ext_autosummary.py
+++ b/tests/test_ext_autosummary.py
@@ -13,7 +13,7 @@ from six import iteritems, StringIO
from sphinx.ext.autosummary import mangle_signature
-from util import with_app
+import pytest
html_warnfile = StringIO()
@@ -54,7 +54,7 @@ def test_mangle_signature():
assert res == outp, (u"'%s' -> '%s' != '%s'" % (inp, res, outp))
-@with_app(buildername='dummy', **default_kw)
+@pytest.mark.sphinx('dummy', **default_kw)
def test_get_items_summary(app, status, warning):
# monkey-patch Autosummary.get_items so we can easily get access to it's
# results..
diff --git a/tests/test_ext_coverage.py b/tests/test_ext_coverage.py
index ddf8efe51..4ae18b66e 100644
--- a/tests/test_ext_coverage.py
+++ b/tests/test_ext_coverage.py
@@ -11,10 +11,10 @@
import pickle
-from util import with_app
+import pytest
-@with_app(buildername='coverage')
+@pytest.mark.sphinx('coverage')
def test_build(app, status, warning):
app.builder.build_all()
diff --git a/tests/test_ext_doctest.py b/tests/test_ext_doctest.py
index d2a2d90ce..6b17f2ed7 100644
--- a/tests/test_ext_doctest.py
+++ b/tests/test_ext_doctest.py
@@ -8,13 +8,12 @@
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-
-from util import with_app
+import pytest
cleanup_called = 0
-@with_app(buildername='doctest', testroot='doctest')
+@pytest.mark.sphinx('doctest', testroot='doctest')
def test_build(app, status, warning):
global cleanup_called
cleanup_called = 0
diff --git a/tests/test_ext_githubpages.py b/tests/test_ext_githubpages.py
index f74ed5315..2eff6be78 100644
--- a/tests/test_ext_githubpages.py
+++ b/tests/test_ext_githubpages.py
@@ -9,10 +9,10 @@
:license: BSD, see LICENSE for details.
"""
-from util import with_app
+import pytest
-@with_app('html', testroot='ext-githubpages')
+@pytest.mark.sphinx('html', testroot='ext-githubpages')
def test_githubpages(app, status, warning):
app.builder.build_all()
assert (app.outdir / '.nojekyll').exists()
diff --git a/tests/test_ext_graphviz.py b/tests/test_ext_graphviz.py
index 7d464343f..45850f3ce 100644
--- a/tests/test_ext_graphviz.py
+++ b/tests/test_ext_graphviz.py
@@ -10,37 +10,12 @@
"""
import re
-import subprocess
-from functools import wraps
-from util import with_app, SkipTest
+import pytest
-def skip_if_graphviz_not_found(fn):
- @wraps(fn)
- def decorator(app, *args, **kwargs):
- found = False
- graphviz_dot = getattr(app.config, 'graphviz_dot', '')
- try:
- if graphviz_dot:
- dot = subprocess.Popen([graphviz_dot, '-V'],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE) # show version
- dot.communicate()
- found = True
- except OSError: # No such file or directory
- pass
-
- if not found:
- raise SkipTest('graphviz "dot" is not available')
-
- return fn(app, *args, **kwargs)
-
- return decorator
-
-
-@with_app('html', testroot='ext-graphviz')
-@skip_if_graphviz_not_found
+@pytest.mark.sphinx('html', testroot='ext-graphviz')
+@pytest.mark.usefixtures('if_graphviz_found')
def test_graphviz_html(app, status, warning):
app.builder.build_all()
@@ -60,8 +35,8 @@ def test_graphviz_html(app, status, warning):
assert re.search(html, content, re.S)
-@with_app('latex', testroot='ext-graphviz')
-@skip_if_graphviz_not_found
+@pytest.mark.sphinx('latex', testroot='ext-graphviz')
+@pytest.mark.usefixtures('if_graphviz_found')
def test_graphviz_latex(app, status, warning):
app.builder.build_all()
@@ -80,8 +55,8 @@ def test_graphviz_latex(app, status, warning):
assert re.search(macro, content, re.S)
-@with_app('html', testroot='ext-graphviz', confoverrides={'language': 'xx'})
-@skip_if_graphviz_not_found
+@pytest.mark.sphinx('html', testroot='ext-graphviz', confoverrides={'language': 'xx'})
+@pytest.mark.usefixtures('if_graphviz_found')
def test_graphviz_i18n(app, status, warning):
app.builder.build_all()
diff --git a/tests/test_ext_ifconfig.py b/tests/test_ext_ifconfig.py
index 835ab0938..1ed7c78d2 100644
--- a/tests/test_ext_ifconfig.py
+++ b/tests/test_ext_ifconfig.py
@@ -9,10 +9,10 @@
:license: BSD, see LICENSE for details.
"""
-from util import with_app
+import pytest
-@with_app(buildername='text', testroot='ext-ifconfig')
+@pytest.mark.sphinx('text', testroot='ext-ifconfig')
def test_ifconfig(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'index.txt').text()
diff --git a/tests/test_ext_inheritance_diagram.py b/tests/test_ext_inheritance_diagram.py
index 0171cafe6..3ce4b23a5 100644
--- a/tests/test_ext_inheritance_diagram.py
+++ b/tests/test_ext_inheritance_diagram.py
@@ -11,13 +11,13 @@
import re
import sys
-from util import with_app, rootdir, raises
-from test_ext_graphviz import skip_if_graphviz_not_found
+from util import rootdir
from sphinx.ext.inheritance_diagram import InheritanceException, import_classes
+import pytest
-@with_app('html', testroot='ext-inheritance_diagram')
-@skip_if_graphviz_not_found
+@pytest.mark.sphinx('html', testroot='ext-inheritance_diagram')
+@pytest.mark.usefixtures('if_graphviz_found')
def test_inheritance_diagram_html(app, status, warning):
app.builder.build_all()
@@ -31,8 +31,8 @@ def test_inheritance_diagram_html(app, status, warning):
assert re.search(pattern, content, re.M)
-@with_app('latex', testroot='ext-inheritance_diagram')
-@skip_if_graphviz_not_found
+@pytest.mark.sphinx('latex', testroot='ext-inheritance_diagram')
+@pytest.mark.usefixtures('if_graphviz_found')
def test_inheritance_diagram_latex(app, status, warning):
app.builder.build_all()
@@ -53,8 +53,10 @@ def test_import_classes():
from example.sphinx import DummyClass
# got exception for unknown class or module
- raises(InheritanceException, import_classes, 'unknown', None)
- raises(InheritanceException, import_classes, 'unknown.Unknown', None)
+ with pytest.raises(InheritanceException):
+ import_classes('unknown', None)
+ with pytest.raises(InheritanceException):
+ import_classes('unknown.Unknown', None)
# a module having no classes
classes = import_classes('sphinx', None)
@@ -80,7 +82,8 @@ def test_import_classes():
assert classes == [CatalogInfo]
# got exception for functions
- raises(InheritanceException, import_classes, 'encode_uri', 'sphinx.util')
+ with pytest.raises(InheritanceException):
+ import_classes('encode_uri', 'sphinx.util')
# import submodule on current module (refs: #3164)
classes = import_classes('sphinx', 'example')
diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py
index e1995e3d3..a913102b1 100644
--- a/tests/test_ext_intersphinx.py
+++ b/tests/test_ext_intersphinx.py
@@ -23,8 +23,6 @@ from sphinx.ext.intersphinx import read_inventory, \
load_mappings, missing_reference, _strip_basic_auth, _read_from_url, \
_get_safe_url, fetch_inventory, INVENTORY_FILENAME
-from util import with_app, with_tempdir
-
inventory_v1 = '''\
# Sphinx inventory version 1
@@ -82,10 +80,9 @@ def test_read_inventory_v2():
'/util/glossary.html#term-a-term-including-colon'
-@with_app()
@mock.patch('sphinx.ext.intersphinx.read_inventory')
@mock.patch('sphinx.ext.intersphinx._read_from_url')
-def test_fetch_inventory_redirection(app, status, warning, _read_from_url, read_inventory):
+def test_fetch_inventory_redirection(_read_from_url, read_inventory, app, status, warning):
intersphinx_setup(app)
_read_from_url().readline.return_value = '# Sphinx inventory version 2'.encode('utf-8')
@@ -127,8 +124,6 @@ def test_fetch_inventory_redirection(app, status, warning, _read_from_url, read_
assert read_inventory.call_args[0][1] == 'http://hostname/'
-@with_app()
-@with_tempdir
def test_missing_reference(tempdir, app, status, warning):
inv_file = tempdir / 'inventory'
inv_file.write_bytes(inventory_v2)
@@ -218,8 +213,6 @@ def test_missing_reference(tempdir, app, status, warning):
assert rn['refuri'] == '../../../../py3k/foo.html#module-module1'
-@with_app()
-@with_tempdir
def test_load_mappings_warnings(tempdir, app, status, warning):
"""
load_mappings issues a warning if new-style mapping
diff --git a/tests/test_ext_math.py b/tests/test_ext_math.py
index 0c7d44e8e..0e02c924f 100644
--- a/tests/test_ext_math.py
+++ b/tests/test_ext_math.py
@@ -11,11 +11,13 @@
import re
-from util import with_app, SkipTest
+import pytest
+from util import SkipTest
-@with_app(buildername='html', testroot='ext-math',
- confoverrides = {'extensions': ['sphinx.ext.jsmath'], 'jsmath_path': 'dummy.js'})
+@pytest.mark.sphinx(
+ 'html', testroot='ext-math',
+ confoverrides = {'extensions': ['sphinx.ext.jsmath'], 'jsmath_path': 'dummy.js'})
def test_jsmath(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'math.html').text()
@@ -33,7 +35,7 @@ def test_jsmath(app, status, warning):
assert ' \na + 1 < b ' in content
-@with_app('html', testroot='ext-math-simple',
+@pytest.mark.sphinx('html', testroot='ext-math-simple',
confoverrides = {'extensions': ['sphinx.ext.imgmath']})
def test_imgmath_png(app, status, warning):
app.builder.build_all()
@@ -48,7 +50,7 @@ def test_imgmath_png(app, status, warning):
assert re.search(html, content, re.S)
-@with_app('html', testroot='ext-math-simple',
+@pytest.mark.sphinx('html', testroot='ext-math-simple',
confoverrides={'extensions': ['sphinx.ext.imgmath'],
'imgmath_image_format': 'svg'})
def test_imgmath_svg(app, status, warning):
@@ -64,7 +66,7 @@ def test_imgmath_svg(app, status, warning):
assert re.search(html, content, re.S)
-@with_app('html', testroot='ext-math',
+@pytest.mark.sphinx('html', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_mathjax_align(app, status, warning):
app.builder.build_all()
@@ -76,7 +78,7 @@ def test_mathjax_align(app, status, warning):
assert re.search(html, content, re.S)
-@with_app('html', testroot='ext-math',
+@pytest.mark.sphinx('html', testroot='ext-math',
confoverrides={'math_number_all': True,
'extensions': ['sphinx.ext.mathjax']})
def test_math_number_all_mathjax(app, status, warning):
@@ -88,7 +90,7 @@ def test_math_number_all_mathjax(app, status, warning):
assert re.search(html, content, re.S)
-@with_app('latex', testroot='ext-math',
+@pytest.mark.sphinx('latex', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_math_number_all_latex(app, status, warning):
app.builder.build_all()
diff --git a/tests/test_ext_todo.py b/tests/test_ext_todo.py
index 269a8a2be..cbea9b74c 100644
--- a/tests/test_ext_todo.py
+++ b/tests/test_ext_todo.py
@@ -10,10 +10,11 @@
"""
import re
-from util import with_app
+
+import pytest
-@with_app('html', testroot='ext-todo', freshenv=True,
+@pytest.mark.sphinx('html', testroot='ext-todo', freshenv=True,
confoverrides={'todo_include_todos': True, 'todo_emit_warnings': True})
def test_todo(app, status, warning):
todos = []
@@ -49,7 +50,7 @@ def test_todo(app, status, warning):
assert set(todo[1].astext() for todo in todos) == set(['todo in foo', 'todo in bar'])
-@with_app('html', testroot='ext-todo', freshenv=True,
+@pytest.mark.sphinx('html', testroot='ext-todo', freshenv=True,
confoverrides={'todo_include_todos': False, 'todo_emit_warnings': True})
def test_todo_not_included(app, status, warning):
todos = []
diff --git a/tests/test_ext_viewcode.py b/tests/test_ext_viewcode.py
index 93e681a5d..e4763119a 100644
--- a/tests/test_ext_viewcode.py
+++ b/tests/test_ext_viewcode.py
@@ -11,10 +11,10 @@
import re
-from util import with_app
+import pytest
-@with_app(testroot='ext-viewcode')
+@pytest.mark.sphinx(testroot='ext-viewcode')
def test_viewcode(app, status, warning):
app.builder.build_all()
@@ -32,7 +32,7 @@ def test_viewcode(app, status, warning):
assert result.count('href="_modules/spam/mod2.html#Class2"') == 2
-@with_app(testroot='ext-viewcode', tags=['test_linkcode'])
+@pytest.mark.sphinx(testroot='ext-viewcode', tags=['test_linkcode'])
def test_linkcode(app, status, warning):
app.builder.build(['objects'])
diff --git a/tests/test_highlighting.py b/tests/test_highlighting.py
index 328abdf31..44a1cb3c1 100644
--- a/tests/test_highlighting.py
+++ b/tests/test_highlighting.py
@@ -16,8 +16,6 @@ from pygments.formatters.html import HtmlFormatter
from sphinx.highlighting import PygmentsBridge
-from util import with_app
-
class MyLexer(RegexLexer):
name = 'testlexer'
@@ -41,7 +39,6 @@ class ComplainOnUnhighlighted(PygmentsBridge):
raise AssertionError("should highlight %r" % source)
-@with_app()
def test_add_lexer(app, status, warning):
app.add_lexer('test', MyLexer())
diff --git a/tests/test_intl.py b/tests/test_intl.py
index 21d6f763b..e7bb130ff 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -15,31 +15,22 @@ import os
import re
import pickle
from docutils import nodes
-from subprocess import Popen, PIPE
-from babel.messages import pofile
-from nose.tools import assert_equal
+from babel.messages import pofile, mofile
from six import string_types
+import pytest
-from util import tempdir, rootdir, path, gen_with_app, with_app, SkipTest, \
- assert_re_search, assert_not_re_search, assert_in, assert_not_in, \
- assert_startswith, assert_node, repr_as, etree_parse
+from util import tempdir, rootdir, path, assert_re_search, \
+ assert_not_re_search, assert_startswith, assert_node, etree_parse
-root = tempdir / 'test-intl'
-
-
-def gen_with_intl_app(builder, confoverrides={}, *args, **kw):
- default_kw = {
- 'testroot': 'intl',
- 'confoverrides': {
- 'language': 'xx', 'locale_dirs': ['.'],
- 'gettext_compact': False,
- },
- }
- default_kw.update(kw)
- default_kw['confoverrides'].update(confoverrides)
- return gen_with_app(builder, *args, **default_kw)
+sphinx_intl = pytest.mark.sphinx(
+ testroot='intl',
+ confoverrides={
+ 'language': 'xx', 'locale_dirs': ['.'],
+ 'gettext_compact': False,
+ },
+)
def read_po(pathname):
@@ -47,32 +38,41 @@ def read_po(pathname):
return pofile.read_po(f)
-def setup_module():
- if not root.exists():
- (rootdir / 'roots' / 'test-intl').copytree(root)
- # Delete remnants left over after failed build
- # Compile all required catalogs into binary format (*.mo).
- for dirpath, dirs, files in os.walk(root):
- dirpath = path(dirpath)
- for f in [f for f in files if f.endswith('.po')]:
- po = dirpath / f
- mo = root / 'xx' / 'LC_MESSAGES' / (
- os.path.relpath(po[:-3], root) + '.mo')
- if not mo.parent.exists():
- mo.parent.makedirs()
- try:
- p = Popen(['msgfmt', po, '-o', mo],
- stdout=PIPE, stderr=PIPE)
- except OSError:
- raise SkipTest # most likely msgfmt was not found
- else:
- stdout, stderr = p.communicate()
- if p.returncode != 0:
- print(stdout)
- print(stderr)
- assert False, \
- 'msgfmt exited with return code %s' % p.returncode
- assert mo.isfile(), 'msgfmt failed'
+def write_mo(pathname, po):
+ with pathname.open('wb') as f:
+ return mofile.write_mo(f, po)
+
+
+@pytest.fixture
+def build_mo():
+ def builder(srcdir):
+ """
+ :param str srcdir: app.srcdir
+ """
+ srcdir = path(srcdir)
+ for dirpath, dirs, files in os.walk(srcdir):
+ dirpath = path(dirpath)
+ for f in [f for f in files if f.endswith('.po')]:
+ po = dirpath / f
+ mo = srcdir / 'xx' / 'LC_MESSAGES' / (
+ os.path.relpath(po[:-3], srcdir) + '.mo')
+ if not mo.parent.exists():
+ mo.parent.makedirs()
+
+ write_mo(mo, read_po(po))
+ return builder
+
+
+@pytest.fixture(autouse=True)
+def setup_intl(app_params, build_mo):
+ build_mo(app_params.kwargs['srcdir'])
+
+
+@pytest.fixture(autouse=True)
+def _info(app):
+ yield
+ print('# language:', app.config.language)
+ print('# locale_dirs:', app.config.locale_dirs)
def elem_gettexts(elem):
@@ -110,46 +110,72 @@ def assert_elem(elem, texts=None, refs=None, names=None):
def assert_count(expected_expr, result, count):
find_pair = (expected_expr, result)
- return assert_equal, len(re.findall(*find_pair)), count, find_pair
+ assert len(re.findall(*find_pair)) == count, find_pair
-@gen_with_intl_app('text', freshenv=True)
-def test_text_builder(app, status, warning):
- app.builder.build_all()
-
- # --- toctree
-
+@sphinx_intl
+@pytest.mark.sphinx('text')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_text_toctree(app):
+ app.build()
result = (app.outdir / 'contents.txt').text(encoding='utf-8')
- yield assert_startswith, result, u"CONTENTS\n********\n\nTABLE OF CONTENTS\n"
+ assert_startswith(result, u"CONTENTS\n********\n\nTABLE OF CONTENTS\n")
- # --- warnings in translation
+@sphinx_intl
+@pytest.mark.sphinx('text')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_text_emit_warnings(app, warning):
+ app.build()
+ # test warnings in translation
warnings = getwarning(warning)
warning_expr = u'.*/warnings.txt:4: ' \
u'WARNING: Inline literal start-string without end-string.\n'
- yield assert_re_search, warning_expr, warnings
+ assert_re_search(warning_expr, warnings)
+
+@sphinx_intl
+@pytest.mark.sphinx('text')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_text_warning_node(app):
+ app.build()
+ # test warnings in translation
result = (app.outdir / 'warnings.txt').text(encoding='utf-8')
expect = (u"I18N WITH REST WARNINGS"
u"\n***********************\n"
u"\nLINE OF >>``<reference')
- yield assert_equal, len(re.findall(expected_expr, result)), 2
+ assert len(re.findall(expected_expr, result)) == 2
expected_expr = ('reference')
- yield assert_equal, len(re.findall(expected_expr, result)), 0
+ assert len(re.findall(expected_expr, result)) == 0
expected_expr = ('I18N WITH '
'REFS INCONSISTENCY')
- yield assert_equal, len(re.findall(expected_expr, result)), 1
+ assert len(re.findall(expected_expr, result)) == 1
+
+@sphinx_intl
+@pytest.mark.sphinx('html')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_html_index_entries(app):
+ app.build()
# --- index entries: regression test for #976
-
result = (app.outdir / 'genindex.html').text(encoding='utf-8')
def wrap(tag, keyword):
@@ -440,10 +581,15 @@ def test_html_builder(app, status, warning):
wrap('a', 'BUILTIN'),
]
for expr in expected_exprs:
- yield assert_re_search, expr, result, re.M
+ assert_re_search(expr, result, re.M)
+
+@sphinx_intl
+@pytest.mark.sphinx('html')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_html_versionchanges(app):
+ app.build()
# --- versionchanges
-
result = (app.outdir / 'versionchange.html').text(encoding='utf-8')
def get_content(result, name):
@@ -459,88 +605,108 @@ def test_html_builder(app, status, warning):
u"""THIS IS THE FIRST PARAGRAPH OF DEPRECATED.\n"""
u"""THIS IS THE SECOND PARAGRAPH OF DEPRECATED. \n""")
matched_content = get_content(result, "deprecated")
- yield assert_equal, expect1, matched_content
+ assert expect1 == matched_content
expect2 = (
u"""New in version 1.0: """
u"""THIS IS THE FIRST PARAGRAPH OF VERSIONADDED. \n""")
matched_content = get_content(result, "versionadded")
- yield assert_equal, expect2, matched_content
+ assert expect2 == matched_content
expect3 = (
u"""Changed in version 1.0: """
u"""THIS IS THE FIRST PARAGRAPH OF VERSIONCHANGED. \n""")
matched_content = get_content(result, "versionchanged")
- yield assert_equal, expect3, matched_content
+ assert expect3 == matched_content
+
+@sphinx_intl
+@pytest.mark.sphinx('html')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_html_docfields(app):
+ app.build()
# --- docfields
-
# expect no error by build
(app.outdir / 'docfields.html').text(encoding='utf-8')
+
+@sphinx_intl
+@pytest.mark.sphinx('html')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_html_template(app):
+ app.build()
# --- gettext template
-
result = (app.outdir / 'index.html').text(encoding='utf-8')
- yield assert_in, "WELCOME", result
- yield assert_in, "SPHINX 2013.120", result
+ assert "WELCOME" in result
+ assert "SPHINX 2013.120" in result
+
+@sphinx_intl
+@pytest.mark.sphinx('html')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_html_rebuild_mo(app):
+ app.build()
# --- rebuild by .mo mtime
-
app.builder.build_update()
updated = app.env.update(app.config, app.srcdir, app.doctreedir, app)
- yield assert_equal, len(updated), 0
+ assert len(updated) == 0
(app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').utime(None)
updated = app.env.update(app.config, app.srcdir, app.doctreedir, app)
- yield assert_equal, len(updated), 1
+ assert len(updated) == 1
-@gen_with_intl_app('xml', freshenv=True)
-def test_xml_builder(app, status, warning):
- app.builder.build_all()
-
+@sphinx_intl
+@pytest.mark.sphinx('xml')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_xml_footnotes(app, warning):
+ app.build()
# --- footnotes: regression test for fix #955, #1176
-
et = etree_parse(app.outdir / 'footnote.xml')
secs = et.findall('section')
para0 = secs[0].findall('paragraph')
- yield (assert_elem,
- para0[0],
- ['I18N WITH FOOTNOTE', 'INCLUDE THIS CONTENTS',
- '2', '[ref]', '1', '100', '.'],
- ['i18n-with-footnote', 'ref'])
+ assert_elem(
+ para0[0],
+ ['I18N WITH FOOTNOTE', 'INCLUDE THIS CONTENTS',
+ '2', '[ref]', '1', '100', '.'],
+ ['i18n-with-footnote', 'ref'])
footnote0 = secs[0].findall('footnote')
- yield (assert_elem,
- footnote0[0],
- ['1', 'THIS IS A AUTO NUMBERED FOOTNOTE.'],
- None,
- ['1'])
- yield (assert_elem,
- footnote0[1],
- ['100', 'THIS IS A NUMBERED FOOTNOTE.'],
- None,
- ['100'])
- yield (assert_elem,
- footnote0[2],
- ['2', 'THIS IS A AUTO NUMBERED NAMED FOOTNOTE.'],
- None,
- ['named'])
+ assert_elem(
+ footnote0[0],
+ ['1', 'THIS IS A AUTO NUMBERED FOOTNOTE.'],
+ None,
+ ['1'])
+ assert_elem(
+ footnote0[1],
+ ['100', 'THIS IS A NUMBERED FOOTNOTE.'],
+ None,
+ ['100'])
+ assert_elem(
+ footnote0[2],
+ ['2', 'THIS IS A AUTO NUMBERED NAMED FOOTNOTE.'],
+ None,
+ ['named'])
citation0 = secs[0].findall('citation')
- yield (assert_elem,
- citation0[0],
- ['ref', 'THIS IS A NAMED FOOTNOTE.'],
- None,
- ['ref'])
+ assert_elem(
+ citation0[0],
+ ['ref', 'THIS IS A NAMED FOOTNOTE.'],
+ None,
+ ['ref'])
warnings = getwarning(warning)
warning_expr = u'.*/footnote.xml:\\d*: SEVERE: Duplicate ID: ".*".\n'
- yield assert_not_re_search, warning_expr, warnings
+ assert_not_re_search(warning_expr, warnings)
+
+@sphinx_intl
+@pytest.mark.sphinx('xml')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_xml_footnote_backlinks(app):
+ app.build()
# --- footnote backlinks: i18n test for #1058
-
et = etree_parse(app.outdir / 'footnote.xml')
secs = et.findall('section')
@@ -553,207 +719,234 @@ def test_xml_builder(app, status, warning):
for footnote in footnote0:
ids = footnote.attrib.get('ids')
backrefs = footnote.attrib.get('backrefs')
- yield assert_equal, refid2id[ids], backrefs
+ assert refid2id[ids] == backrefs
+
+@sphinx_intl
+@pytest.mark.sphinx('xml')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_xml_refs_in_python_domain(app):
+ app.build()
# --- refs in the Python domain
-
et = etree_parse(app.outdir / 'refs_python_domain.xml')
secs = et.findall('section')
# regression test for fix #1363
para0 = secs[0].findall('paragraph')
- yield (assert_elem,
- para0[0],
- ['SEE THIS DECORATOR:', 'sensitive_variables()', '.'],
- ['sensitive.sensitive_variables'])
+ assert_elem(
+ para0[0],
+ ['SEE THIS DECORATOR:', 'sensitive_variables()', '.'],
+ ['sensitive.sensitive_variables'])
+
+@sphinx_intl
+@pytest.mark.sphinx('xml')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_xml_keep_external_links(app):
+ app.build()
# --- keep external links: regression test for #1044
-
et = etree_parse(app.outdir / 'external_links.xml')
secs = et.findall('section')
para0 = secs[0].findall('paragraph')
# external link check
- yield (assert_elem,
- para0[0],
- ['EXTERNAL LINK TO', 'Python', '.'],
- ['http://python.org/index.html'])
+ assert_elem(
+ para0[0],
+ ['EXTERNAL LINK TO', 'Python', '.'],
+ ['http://python.org/index.html'])
# internal link check
- yield (assert_elem,
- para0[1],
- ['EXTERNAL LINKS', 'IS INTERNAL LINK.'],
- ['i18n-with-external-links'])
+ assert_elem(
+ para0[1],
+ ['EXTERNAL LINKS', 'IS INTERNAL LINK.'],
+ ['i18n-with-external-links'])
# inline link check
- yield (assert_elem,
- para0[2],
- ['INLINE LINK BY', 'THE SPHINX SITE', '.'],
- ['http://sphinx-doc.org'])
+ assert_elem(
+ para0[2],
+ ['INLINE LINK BY', 'THE SPHINX SITE', '.'],
+ ['http://sphinx-doc.org'])
# unnamed link check
- yield (assert_elem,
- para0[3],
- ['UNNAMED', 'LINK', '.'],
- ['http://google.com'])
+ assert_elem(
+ para0[3],
+ ['UNNAMED', 'LINK', '.'],
+ ['http://google.com'])
# link target swapped translation
para1 = secs[1].findall('paragraph')
- yield (assert_elem,
- para1[0],
- ['LINK TO', 'external2', 'AND', 'external1', '.'],
- ['http://example.com/external2',
- 'http://example.com/external1'])
- yield (assert_elem,
+ assert_elem(
+ para1[0],
+ ['LINK TO', 'external2', 'AND', 'external1', '.'],
+ ['http://example.com/external2',
+ 'http://example.com/external1'])
+ assert_elem(
para1[1],
['LINK TO', 'THE PYTHON SITE', 'AND', 'THE SPHINX SITE', '.'],
['http://python.org', 'http://sphinx-doc.org'])
# multiple references in the same line
para2 = secs[2].findall('paragraph')
- yield (assert_elem,
- para2[0],
- ['LINK TO', 'EXTERNAL LINKS', ',', 'Python', ',',
- 'THE SPHINX SITE', ',', 'UNNAMED', 'AND',
- 'THE PYTHON SITE', '.'],
- ['i18n-with-external-links', 'http://python.org/index.html',
- 'http://sphinx-doc.org', 'http://google.com',
- 'http://python.org'])
+ assert_elem(
+ para2[0],
+ ['LINK TO', 'EXTERNAL LINKS', ',', 'Python', ',',
+ 'THE SPHINX SITE', ',', 'UNNAMED', 'AND',
+ 'THE PYTHON SITE', '.'],
+ ['i18n-with-external-links', 'http://python.org/index.html',
+ 'http://sphinx-doc.org', 'http://google.com',
+ 'http://python.org'])
+
+@sphinx_intl
+@pytest.mark.sphinx('xml')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_xml_role_xref(app):
+ app.build()
# --- role xref: regression test for #1090, #1193
-
et = etree_parse(app.outdir / 'role_xref.xml')
sec1, sec2 = et.findall('section')
para1, = sec1.findall('paragraph')
- yield (assert_elem,
- para1,
- ['LINK TO', "I18N ROCK'N ROLE XREF", ',', 'CONTENTS', ',',
- 'SOME NEW TERM', '.'],
- ['i18n-role-xref', 'contents',
- 'glossary_terms#term-some-term'])
+ assert_elem(
+ para1,
+ ['LINK TO', "I18N ROCK'N ROLE XREF", ',', 'CONTENTS', ',',
+ 'SOME NEW TERM', '.'],
+ ['i18n-role-xref', 'contents',
+ 'glossary_terms#term-some-term'])
para2 = sec2.findall('paragraph')
- yield (assert_elem,
- para2[0],
- ['LINK TO', 'SOME OTHER NEW TERM', 'AND', 'SOME NEW TERM', '.'],
- ['glossary_terms#term-some-other-term',
- 'glossary_terms#term-some-term'])
- yield(assert_elem,
- para2[1],
- ['LINK TO', 'SAME TYPE LINKS', 'AND',
- "I18N ROCK'N ROLE XREF", '.'],
- ['same-type-links', 'i18n-role-xref'])
- yield (assert_elem,
- para2[2],
- ['LINK TO', 'I18N WITH GLOSSARY TERMS', 'AND', 'CONTENTS', '.'],
- ['glossary_terms', 'contents'])
- yield (assert_elem,
- para2[3],
- ['LINK TO', '--module', 'AND', '-m', '.'],
- ['cmdoption-module', 'cmdoption-m'])
- yield (assert_elem,
- para2[4],
- ['LINK TO', 'env2', 'AND', 'env1', '.'],
- ['envvar-env2', 'envvar-env1'])
- yield (assert_elem,
- para2[5],
- ['LINK TO', 'token2', 'AND', 'token1', '.'],
- []) # TODO: how do I link token role to productionlist?
- yield (assert_elem,
- para2[6],
- ['LINK TO', 'same-type-links', 'AND', "i18n-role-xref", '.'],
- ['same-type-links', 'i18n-role-xref'])
+ assert_elem(
+ para2[0],
+ ['LINK TO', 'SOME OTHER NEW TERM', 'AND', 'SOME NEW TERM', '.'],
+ ['glossary_terms#term-some-other-term',
+ 'glossary_terms#term-some-term'])
+ assert_elem(
+ para2[1],
+ ['LINK TO', 'SAME TYPE LINKS', 'AND',
+ "I18N ROCK'N ROLE XREF", '.'],
+ ['same-type-links', 'i18n-role-xref'])
+ assert_elem(
+ para2[2],
+ ['LINK TO', 'I18N WITH GLOSSARY TERMS', 'AND', 'CONTENTS', '.'],
+ ['glossary_terms', 'contents'])
+ assert_elem(
+ para2[3],
+ ['LINK TO', '--module', 'AND', '-m', '.'],
+ ['cmdoption-module', 'cmdoption-m'])
+ assert_elem(
+ para2[4],
+ ['LINK TO', 'env2', 'AND', 'env1', '.'],
+ ['envvar-env2', 'envvar-env1'])
+ assert_elem(
+ para2[5],
+ ['LINK TO', 'token2', 'AND', 'token1', '.'],
+ []) # TODO: how do I link token role to productionlist?
+ assert_elem(
+ para2[6],
+ ['LINK TO', 'same-type-links', 'AND', "i18n-role-xref", '.'],
+ ['same-type-links', 'i18n-role-xref'])
+
+@sphinx_intl
+@pytest.mark.sphinx('xml')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_xml_warnings(app, warning):
+ app.build()
# warnings
warnings = getwarning(warning)
- yield assert_not_in, 'term not in glossary', warnings
- yield assert_not_in, 'undefined label', warnings
- yield assert_not_in, 'unknown document', warnings
+ assert 'term not in glossary' not in warnings
+ assert 'undefined label' not in warnings
+ assert 'unknown document' not in warnings
+
+@sphinx_intl
+@pytest.mark.sphinx('xml')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_xml_label_targets(app):
+ app.build()
# --- label targets: regression test for #1193, #1265
-
et = etree_parse(app.outdir / 'label_target.xml')
secs = et.findall('section')
para0 = secs[0].findall('paragraph')
- yield (assert_elem,
- para0[0],
- ['X SECTION AND LABEL', 'POINT TO', 'implicit-target', 'AND',
- 'X SECTION AND LABEL', 'POINT TO', 'section-and-label', '.'],
- ['implicit-target', 'section-and-label'])
+ assert_elem(
+ para0[0],
+ ['X SECTION AND LABEL', 'POINT TO', 'implicit-target', 'AND',
+ 'X SECTION AND LABEL', 'POINT TO', 'section-and-label', '.'],
+ ['implicit-target', 'section-and-label'])
para1 = secs[1].findall('paragraph')
- yield (assert_elem,
- para1[0],
- ['X EXPLICIT-TARGET', 'POINT TO', 'explicit-target', 'AND',
- 'X EXPLICIT-TARGET', 'POINT TO DUPLICATED ID LIKE', 'id1',
- '.'],
- ['explicit-target', 'id1'])
+ assert_elem(
+ para1[0],
+ ['X EXPLICIT-TARGET', 'POINT TO', 'explicit-target', 'AND',
+ 'X EXPLICIT-TARGET', 'POINT TO DUPLICATED ID LIKE', 'id1',
+ '.'],
+ ['explicit-target', 'id1'])
para2 = secs[2].findall('paragraph')
- yield (assert_elem,
- para2[0],
- ['X IMPLICIT SECTION NAME', 'POINT TO',
- 'implicit-section-name', '.'],
- ['implicit-section-name'])
+ assert_elem(
+ para2[0],
+ ['X IMPLICIT SECTION NAME', 'POINT TO',
+ 'implicit-section-name', '.'],
+ ['implicit-section-name'])
sec2 = secs[2].findall('section')
para2_0 = sec2[0].findall('paragraph')
- yield (assert_elem,
- para2_0[0],
- ['`X DUPLICATED SUB SECTION`_', 'IS BROKEN LINK.'],
- [])
+ assert_elem(
+ para2_0[0],
+ ['`X DUPLICATED SUB SECTION`_', 'IS BROKEN LINK.'],
+ [])
para3 = secs[3].findall('paragraph')
- yield (assert_elem,
- para3[0],
- ['X', 'bridge label',
- 'IS NOT TRANSLATABLE BUT LINKED TO TRANSLATED ' +
- 'SECTION TITLE.'],
- ['label-bridged-target-section'])
- yield (assert_elem,
- para3[1],
- ['X', 'bridge label', 'POINT TO',
- 'LABEL BRIDGED TARGET SECTION', 'AND', 'bridge label2',
- 'POINT TO', 'SECTION AND LABEL', '. THE SECOND APPEARED',
- 'bridge label2', 'POINT TO CORRECT TARGET.'],
- ['label-bridged-target-section',
- 'section-and-label',
- 'section-and-label'])
+ assert_elem(
+ para3[0],
+ ['X', 'bridge label',
+ 'IS NOT TRANSLATABLE BUT LINKED TO TRANSLATED ' +
+ 'SECTION TITLE.'],
+ ['label-bridged-target-section'])
+ assert_elem(
+ para3[1],
+ ['X', 'bridge label', 'POINT TO',
+ 'LABEL BRIDGED TARGET SECTION', 'AND', 'bridge label2',
+ 'POINT TO', 'SECTION AND LABEL', '. THE SECOND APPEARED',
+ 'bridge label2', 'POINT TO CORRECT TARGET.'],
+ ['label-bridged-target-section',
+ 'section-and-label',
+ 'section-and-label'])
-@gen_with_intl_app('html', freshenv=True)
-def test_additional_targets_should_not_be_translated(app, status, warning):
- app.builder.build_all()
-
+@sphinx_intl
+@pytest.mark.sphinx('html')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_additional_targets_should_not_be_translated(app):
+ app.build()
# [literalblock.txt]
result = (app.outdir / 'literalblock.html').text(encoding='utf-8')
# title should be translated
expected_expr = 'CODE-BLOCKS'
- yield assert_count(expected_expr, result, 2)
+ assert_count(expected_expr, result, 2)
# ruby code block should not be translated but be highlighted
expected_expr = """'result'"""
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# C code block without lang should not be translated and *ruby* highlighted
expected_expr = """#include <stdlib.h>"""
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# C code block with lang should not be translated but be *C* highlighted
expected_expr = ("""#include """
"""<stdio.h>""")
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# doctest block should not be translated but be highlighted
expected_expr = (
""">>> """
"""import sys """
"""# sys importing""")
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# [raw.txt]
@@ -761,7 +954,7 @@ def test_additional_targets_should_not_be_translated(app, status, warning):
# raw block should not be translated
expected_expr = """"""
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# [figure.txt]
@@ -769,52 +962,57 @@ def test_additional_targets_should_not_be_translated(app, status, warning):
# alt and src for image block should not be translated
expected_expr = """ """
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# alt and src for figure block should not be translated
expected_expr = """ """
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
-@gen_with_intl_app('html', freshenv=True,
- confoverrides={
- 'gettext_additional_targets': [
- 'index',
- 'literal-block',
- 'doctest-block',
- 'raw',
- 'image',
- ],
- })
-def test_additional_targets_should_be_translated(app, status, warning):
- app.builder.build_all()
-
+@sphinx_intl
+@pytest.mark.sphinx(
+ 'html',
+ srcdir='test_additional_targets_should_be_translated',
+ confoverrides={
+ 'language': 'xx', 'locale_dirs': ['.'],
+ 'gettext_compact': False,
+ 'gettext_additional_targets': [
+ 'index',
+ 'literal-block',
+ 'doctest-block',
+ 'raw',
+ 'image',
+ ],
+ }
+)
+def test_additional_targets_should_be_translated(app):
+ app.build()
# [literalblock.txt]
result = (app.outdir / 'literalblock.html').text(encoding='utf-8')
# title should be translated
expected_expr = 'CODE-BLOCKS'
- yield assert_count(expected_expr, result, 2)
+ assert_count(expected_expr, result, 2)
# ruby code block should be translated and be highlighted
expected_expr = """'RESULT'"""
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# C code block without lang should be translated and *ruby* highlighted
expected_expr = """#include <STDLIB.H>"""
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# C code block with lang should be translated and be *C* highlighted
expected_expr = ("""#include """
"""<STDIO.H>""")
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# doctest block should not be translated but be highlighted
expected_expr = (
""">>> """
"""import sys """
"""# SYS IMPORTING""")
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# [raw.txt]
@@ -822,7 +1020,7 @@ def test_additional_targets_should_be_translated(app, status, warning):
# raw block should be translated
expected_expr = """"""
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# [figure.txt]
@@ -830,26 +1028,31 @@ def test_additional_targets_should_be_translated(app, status, warning):
# alt and src for image block should be translated
expected_expr = """ """
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
# alt and src for figure block should be translated
expected_expr = """ """
- yield assert_count(expected_expr, result, 1)
+ assert_count(expected_expr, result, 1)
-@gen_with_intl_app('text', freshenv=True)
-def test_references(app, status, warning):
+@sphinx_intl
+@pytest.mark.sphinx('text')
+@pytest.mark.test_params(shared_result='test_intl_basic')
+def test_text_references(app, warning):
app.builder.build_specific([app.srcdir / 'refs.txt'])
warnings = warning.getvalue().replace(os.sep, '/')
warning_expr = u'refs.txt:\\d+: ERROR: Unknown target name:'
- yield assert_count(warning_expr, warnings, 0)
+ assert_count(warning_expr, warnings, 0)
-@with_app(buildername='dummy', testroot='image-glob', confoverrides={'language': 'xx'})
-def test_image_glob_intl(app, status, warning):
- app.builder.build_all()
-
+@pytest.mark.sphinx(
+ 'dummy', testroot='image-glob',
+ srcdir='test_intl_image_glob',
+ confoverrides={'language': 'xx'}
+)
+def test_image_glob_intl(app):
+ app.build()
# index.rst
doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())
@@ -887,12 +1090,16 @@ def test_image_glob_intl(app, status, warning):
'image/svg+xml': 'subdir/svgimg.xx.svg'})
-@with_app(buildername='dummy', testroot='image-glob',
- confoverrides={'language': 'xx',
- 'figure_language_filename': u'{root}{ext}.{language}'})
-def test_image_glob_intl_using_figure_language_filename(app, status, warning):
- app.builder.build_all()
-
+@pytest.mark.sphinx(
+ 'dummy', testroot='image-glob',
+ srcdir='test_intl_image_glob',
+ confoverrides={
+ 'language': 'xx',
+ 'figure_language_filename': u'{root}{ext}.{language}',
+ }
+)
+def test_image_glob_intl_using_figure_language_filename(app):
+ app.build()
# index.rst
doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())
@@ -931,4 +1138,4 @@ def test_image_glob_intl_using_figure_language_filename(app, status, warning):
def getwarning(warnings):
- return repr_as(warnings.getvalue().replace(os.sep, '/'), '')
+ return warnings.getvalue().replace(os.sep, '/')
diff --git a/tests/test_markup.py b/tests/test_markup.py
index ec203447f..3e190a4d6 100644
--- a/tests/test_markup.py
+++ b/tests/test_markup.py
@@ -13,39 +13,46 @@ import re
import pickle
from docutils import frontend, utils, nodes
-from docutils.parsers import rst
+from docutils.parsers.rst import Parser as RstParser
from sphinx import addnodes
from sphinx.util import texescape
from sphinx.util.docutils import sphinx_domains
from sphinx.writers.html import HTMLWriter, SmartyPantsHTMLTranslator
from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
+import pytest
-from util import TestApp, with_app, assert_node
+from util import assert_node
-app = settings = parser = domain_context = None
-
-
-def setup_module():
- global app, settings, parser, domain_context
+@pytest.fixture
+def settings(app):
texescape.init() # otherwise done by the latex builder
- app = TestApp()
optparser = frontend.OptionParser(
- components=(rst.Parser, HTMLWriter, LaTeXWriter))
+ components=(RstParser, HTMLWriter, LaTeXWriter))
settings = optparser.get_default_values()
settings.env = app.builder.env
settings.env.temp_data['docname'] = 'dummy'
- parser = rst.Parser()
domain_context = sphinx_domains(settings.env)
domain_context.enable()
-
-
-def teardown_module():
- app.cleanup()
+ yield settings
domain_context.disable()
+@pytest.fixture
+def parse(settings):
+ def parse_(rst):
+ document = utils.new_document(b'test data', settings)
+ document['file'] = 'dummy'
+ parser = RstParser()
+ parser.parse(rst, document)
+ for msg in document.traverse(nodes.system_message):
+ if msg['level'] == 1:
+ msg.replace_self([])
+ return document
+ return parse_
+
+
# since we're not resolving the markup afterwards, these nodes may remain
class ForgivingTranslator:
def visit_pending_xref(self, node):
@@ -63,96 +70,161 @@ class ForgivingLaTeXTranslator(LaTeXTranslator, ForgivingTranslator):
pass
-def verify_re(rst, html_expected, latex_expected):
- document = utils.new_document(b'test data', settings)
- document['file'] = 'dummy'
- parser.parse(rst, document)
- for msg in document.traverse(nodes.system_message):
- if msg['level'] == 1:
- msg.replace_self([])
-
- if html_expected:
+@pytest.fixture
+def verify_re_html(app, parse):
+ def verify(rst, html_expected):
+ document = parse(rst)
html_translator = ForgivingHTMLTranslator(app.builder, document)
document.walkabout(html_translator)
html_translated = ''.join(html_translator.fragment).strip()
assert re.match(html_expected, html_translated), 'from ' + rst
+ return verify
- if latex_expected:
+
+@pytest.fixture
+def verify_re_latex(app, parse):
+ def verify(rst, latex_expected):
+ document = parse(rst)
latex_translator = ForgivingLaTeXTranslator(document, app.builder)
latex_translator.first_document = -1 # don't write \begin{document}
document.walkabout(latex_translator)
latex_translated = ''.join(latex_translator.body).strip()
assert re.match(latex_expected, latex_translated), 'from ' + repr(rst)
+ return verify
-def verify(rst, html_expected, latex_expected):
- if html_expected:
- html_expected = re.escape(html_expected) + '$'
- if latex_expected:
- latex_expected = re.escape(latex_expected) + '$'
- verify_re(rst, html_expected, latex_expected)
+@pytest.fixture
+def verify_re(verify_re_html, verify_re_latex):
+ def verify_re_(rst, html_expected, latex_expected):
+ if html_expected:
+ return verify_re_html(rst, html_expected)
+ if latex_expected:
+ return verify_re_latex(rst, latex_expected)
+ return verify_re_
-def test_inline():
- # correct interpretation of code with whitespace
- _html = (''
- 'code sample ')
- yield verify_re, '``code sample``', _html, r'\\sphinxcode{code sample}'
- yield verify_re, ':samp:`code sample`', _html, r'\\sphinxcode{code sample}'
-
- # interpolation of braces in samp and file roles (HTML only)
- yield (verify, ':samp:`a{b}c`',
- 'a'
- 'b'
- 'c ',
- '\\sphinxcode{a\\sphinxstyleemphasis{b}c}')
-
- # interpolation of arrows in menuselection
- yield (verify, ':menuselection:`a --> b`',
- u'',
- '\\sphinxmenuselection{a \\(\\rightarrow\\) b}')
-
- # interpolation of ampersands in guilabel/menuselection
- yield (verify, ':guilabel:`&Foo -&&- &Bar`',
- u'Foo '
- '-&- Bar ',
- r'\sphinxmenuselection{\sphinxaccelerator{F}oo -\&- \sphinxaccelerator{B}ar}')
-
- # non-interpolation of dashes in option role
- yield (verify_re, ':option:`--with-option`',
- ''
- '--with-option $',
- r'\\sphinxcode{-{-}with-option}$')
-
- # verify smarty-pants quotes
- yield verify, '"John"', '“John” ', "``John''"
- # ... but not in literal text
- yield (verify, '``"John"``',
- ''
- '"John" ',
- '\\sphinxcode{"John"}')
-
- # verify classes for inline roles
- yield (verify, ':manpage:`mp(1)`',
- 'mp(1) ',
- '\\sphinxstyleliteralemphasis{mp(1)}')
+@pytest.fixture
+def verify(verify_re_html, verify_re_latex):
+ def verify_(rst, html_expected, latex_expected):
+ if html_expected:
+ return verify_re_html(rst, re.escape(html_expected) + '$')
+ if latex_expected:
+ return verify_re_latex(rst, re.escape(latex_expected) + '$')
+ return verify_
-def test_latex_escaping():
- # correct escaping in normal mode
- yield (verify, u'Γ\\\\∞$', None,
- r'\(\Gamma\)\textbackslash{}\(\infty\)\$')
- # in verbatim code fragments
- yield (verify, u'::\n\n @Γ\\∞${}', None,
- u'\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]\n'
- u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n'
- u'\\end{sphinxVerbatim}')
- # in URIs
- yield (verify_re, u'`test `_', None,
- r'\\href{http://example.com/~me/}{test}.*')
+@pytest.fixture
+def get_verifier(verify, verify_re):
+ v = {
+ 'verify': verify,
+ 'verify_re': verify_re,
+ }
+ def get(name):
+ return v[name]
+ return get
-@with_app(buildername='dummy', testroot='prolog')
+@pytest.mark.parametrize('type,rst,html_expected,latex_expected', [
+ (
+ # correct interpretation of code with whitespace
+ 'verify_re',
+ '``code sample``',
+ (''
+ 'code sample '),
+ r'\\sphinxcode{code sample}',
+ ),
+ (
+ # correct interpretation of code with whitespace
+ 'verify_re',
+ ':samp:`code sample`',
+ (''
+ 'code sample '),
+ r'\\sphinxcode{code sample}',
+ ),
+ (
+ # interpolation of braces in samp and file roles (HTML only)
+ 'verify',
+ ':samp:`a{b}c`',
+ ('a'
+ 'b'
+ 'c '),
+ '\\sphinxcode{a\\sphinxstyleemphasis{b}c}',
+ ),
+ (
+ # interpolation of arrows in menuselection
+ 'verify',
+ ':menuselection:`a --> b`',
+ (u''),
+ '\\sphinxmenuselection{a \\(\\rightarrow\\) b}',
+ ),
+ (
+ # interpolation of ampersands in guilabel/menuselection
+ 'verify',
+ ':guilabel:`&Foo -&&- &Bar`',
+ (u'Foo '
+ '-&- Bar '),
+ r'\sphinxmenuselection{\sphinxaccelerator{F}oo -\&- \sphinxaccelerator{B}ar}',
+ ),
+ (
+ # non-interpolation of dashes in option role
+ 'verify_re',
+ ':option:`--with-option`',
+ (''
+ '--with-option $'),
+ r'\\sphinxcode{-{-}with-option}$',
+ ),
+ (
+ # verify smarty-pants quotes
+ 'verify',
+ '"John"',
+ '“John” ',
+ "``John''",
+ ),
+ (
+ # ... but not in literal text
+ 'verify',
+ '``"John"``',
+ (''
+ '"John" '),
+ '\\sphinxcode{"John"}',
+ ),
+ (
+ # verify classes for inline roles
+ 'verify',
+ ':manpage:`mp(1)`',
+ 'mp(1) ',
+ '\\sphinxstyleliteralemphasis{mp(1)}',
+ ),
+ (
+ # correct escaping in normal mode
+ 'verify',
+ u'Γ\\\\∞$',
+ None,
+ r'\(\Gamma\)\textbackslash{}\(\infty\)\$',
+ ),
+ (
+ # in verbatim code fragments
+ 'verify',
+ u'::\n\n @Γ\\∞${}',
+ None,
+ (u'\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]\n'
+ u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n'
+ u'\\end{sphinxVerbatim}'),
+ ),
+ (
+ # in URIs
+ 'verify_re',
+ u'`test `_',
+ None,
+ r'\\href{http://example.com/~me/}{test}.*',
+ ),
+])
+def test_inline(get_verifier, type, rst, html_expected, latex_expected):
+ verifier = get_verifier(type)
+ verifier(rst, html_expected, latex_expected)
+
+
+@pytest.mark.sphinx('dummy', testroot='prolog')
def test_rst_prolog(app, status, warning):
app.builder.build_all()
rst = pickle.loads((app.doctreedir / 'restructuredtext.doctree').bytes())
@@ -176,7 +248,7 @@ def test_rst_prolog(app, status, warning):
assert not md.rawsource.endswith('*Good-bye world*.\n')
-@with_app(buildername='dummy', testroot='keep_warnings')
+@pytest.mark.sphinx('dummy', testroot='keep_warnings')
def test_keep_warnings_is_True(app, status, warning):
app.builder.build_all()
doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())
@@ -185,7 +257,7 @@ def test_keep_warnings_is_True(app, status, warning):
assert_node(doctree[0][1], nodes.system_message)
-@with_app(buildername='dummy', testroot='keep_warnings',
+@pytest.mark.sphinx('dummy', testroot='keep_warnings',
confoverrides={'keep_warnings': False})
def test_keep_warnings_is_False(app, status, warning):
app.builder.build_all()
@@ -194,7 +266,7 @@ def test_keep_warnings_is_False(app, status, warning):
assert len(doctree[0]) == 1
-@with_app(buildername='dummy', testroot='refonly_bullet_list')
+@pytest.mark.sphinx('dummy', testroot='refonly_bullet_list')
def test_compact_refonly_bullet_list(app, status, warning):
app.builder.build_all()
doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
index 14ab51ccd..868b05139 100644
--- a/tests/test_metadata.py
+++ b/tests/test_metadata.py
@@ -12,12 +12,10 @@
# adapted from an example of bibliographic metadata at
# http://docutils.sourceforge.net/docs/user/rst/demo.txt
-from util import with_app
-
-from nose.tools import assert_equal
+import pytest
-@with_app('pseudoxml')
+@pytest.mark.sphinx('pseudoxml')
def test_docinfo(app, status, warning):
"""
Inspect the 'docinfo' metadata stored in the first node of the document.
@@ -53,8 +51,4 @@ def test_docinfo(app, status, warning):
'orphan': u'',
'nocomments': u'',
}
- # I like this way of comparing dicts - easier to see the error.
- for key in exampledocinfo:
- yield assert_equal, exampledocinfo.get(key), expecteddocinfo.get(key)
- # but then we still have to check for missing keys
- yield assert_equal, set(expecteddocinfo.keys()), set(exampledocinfo.keys())
+ assert exampledocinfo == expecteddocinfo
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
index 7a77ce225..eb1d32409 100644
--- a/tests/test_quickstart.py
+++ b/tests/test_quickstart.py
@@ -14,8 +14,9 @@ import time
from six import PY2, text_type, StringIO
from six.moves import input
+import pytest
-from util import raises, with_tempdir, SkipTest
+from util import SkipTest
from sphinx import application
from sphinx import quickstart as qs
@@ -107,7 +108,8 @@ def test_do_prompt():
assert d['k4'] is True
qs.do_prompt(d, 'k5', 'Q5', validator=qs.boolean)
assert d['k5'] is False
- raises(AssertionError, qs.do_prompt, d, 'k6', 'Q6', validator=qs.boolean)
+ with pytest.raises(AssertionError):
+ qs.do_prompt(d, 'k6', 'Q6', validator=qs.boolean)
def test_do_prompt_with_nonascii():
@@ -125,7 +127,6 @@ def test_do_prompt_with_nonascii():
assert d['k1'] == u'\u30c9\u30a4\u30c4'
-@with_tempdir
def test_quickstart_defaults(tempdir):
answers = {
'Root path': tempdir,
@@ -163,7 +164,6 @@ def test_quickstart_defaults(tempdir):
assert (tempdir / 'make.bat').isfile()
-@with_tempdir
def test_quickstart_all_answers(tempdir):
answers = {
'Root path': tempdir,
@@ -231,7 +231,6 @@ def test_quickstart_all_answers(tempdir):
assert (tempdir / 'source' / 'contents.txt').isfile()
-@with_tempdir
def test_generated_files_eol(tempdir):
answers = {
'Root path': tempdir,
@@ -252,7 +251,6 @@ def test_generated_files_eol(tempdir):
assert_eol(tempdir / 'Makefile', '\n')
-@with_tempdir
def test_quickstart_and_build(tempdir):
answers = {
'Root path': tempdir,
@@ -278,7 +276,6 @@ def test_quickstart_and_build(tempdir):
assert not warnings
-@with_tempdir
def test_default_filename(tempdir):
answers = {
'Root path': tempdir,
@@ -300,7 +297,6 @@ def test_default_filename(tempdir):
assert ns['texinfo_documents'][0][1] == 'sphinx'
-@with_tempdir
def test_extensions(tempdir):
qs.main(['sphinx-quickstart', '-q',
'-p', 'project_name', '-a', 'author',
diff --git a/tests/test_search.py b/tests/test_search.py
index fb7d47d6f..143a3db2b 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -15,8 +15,7 @@ from docutils.parsers import rst
from sphinx.search import IndexBuilder
from sphinx.util import jsdump
-
-from util import with_app
+import pytest
settings = parser = None
@@ -58,7 +57,7 @@ def test_wordcollector():
assert 'fermion' in ix._mapping
-@with_app(testroot='ext-viewcode')
+@pytest.mark.sphinx(testroot='ext-viewcode')
def test_objects_are_escaped(app, status, warning):
app.builder.build_all()
searchindex = (app.outdir / 'searchindex.js').text()
@@ -68,7 +67,7 @@ def test_objects_are_escaped(app, status, warning):
assert 'n::Array<T, d>' in index.get('objects').get('') # n::Array is escaped
-@with_app(testroot='search')
+@pytest.mark.sphinx(testroot='search')
def test_meta_keys_are_handled_for_language_en(app, status, warning):
app.builder.build_all()
searchindex = jsload(app.outdir / 'searchindex.js')
@@ -81,7 +80,7 @@ def test_meta_keys_are_handled_for_language_en(app, status, warning):
assert not is_registered_term(searchindex, 'onlytoogerman')
-@with_app(testroot='search', confoverrides={'html_search_language': 'de'})
+@pytest.mark.sphinx(testroot='search', confoverrides={'html_search_language': 'de'})
def test_meta_keys_are_handled_for_language_de(app, status, warning):
app.builder.build_all()
searchindex = jsload(app.outdir / 'searchindex.js')
@@ -94,14 +93,14 @@ def test_meta_keys_are_handled_for_language_de(app, status, warning):
assert is_registered_term(searchindex, 'onlytoogerman')
-@with_app(testroot='search')
+@pytest.mark.sphinx(testroot='search')
def test_stemmer_does_not_remove_short_words(app, status, warning):
app.builder.build_all()
searchindex = (app.outdir / 'searchindex.js').text()
assert 'zfs' in searchindex
-@with_app(testroot='search')
+@pytest.mark.sphinx(testroot='search')
def test_stemmer(app, status, warning):
searchindex = jsload(app.outdir / 'searchindex.js')
print(searchindex)
@@ -109,7 +108,7 @@ def test_stemmer(app, status, warning):
assert is_registered_term(searchindex, 'intern')
-@with_app(testroot='search')
+@pytest.mark.sphinx(testroot='search')
def test_term_in_heading_and_section(app, status, warning):
searchindex = (app.outdir / 'searchindex.js').text()
# if search term is in the title of one doc and in the text of another
@@ -119,7 +118,7 @@ def test_term_in_heading_and_section(app, status, warning):
assert 'textinhead:0' in searchindex
-@with_app(testroot='search')
+@pytest.mark.sphinx(testroot='search')
def test_term_in_raw_directive(app, status, warning):
searchindex = jsload(app.outdir / 'searchindex.js')
assert not is_registered_term(searchindex, 'raw')
diff --git a/tests/test_setup_command.py b/tests/test_setup_command.py
index c92f6220f..67f46e1a8 100644
--- a/tests/test_setup_command.py
+++ b/tests/test_setup_command.py
@@ -12,12 +12,13 @@
import os
import sys
import subprocess
-from functools import wraps
-import tempfile
+from collections import namedtuple
import sphinx
-from util import rootdir, tempdir, SkipTest
-from path import path
+import pytest
+
+from sphinx.util.osutil import cd
+from util import rootdir, tempdir
from textwrap import dedent
root = tempdir / 'test-setup'
@@ -28,57 +29,52 @@ def setup_module():
(rootdir / 'roots' / 'test-setup').copytree(root)
-def with_setup_command(root, *args, **kwds):
+@pytest.fixture
+def setup_command(request, tempdir):
"""
Run `setup.py build_sphinx` with args and kwargs,
pass it to the test and clean up properly.
"""
- def generator(func):
- @wraps(func)
- def deco(*args2, **kwargs2):
- tempdir = path(tempfile.mkdtemp())
- pkgrootdir = (tempdir / 'root')
- root.copytree(pkgrootdir)
- cwd = os.getcwd()
- os.chdir(pkgrootdir)
- pythonpath = os.path.dirname(os.path.dirname(sphinx.__file__))
- if os.getenv('PYTHONPATH'):
- pythonpath = os.getenv('PYTHONPATH') + os.pathsep + pythonpath
- command = [sys.executable, 'setup.py', 'build_sphinx']
- command.extend(args)
- try:
- proc = subprocess.Popen(
- command,
- env=dict(os.environ, PYTHONPATH=pythonpath),
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- func(pkgrootdir, proc)
- finally:
- tempdir.rmtree(ignore_errors=True)
- os.chdir(cwd)
- return deco
- return generator
+ marker = request.node.get_marker('setup_command')
+ args = marker.args if marker else []
+
+ pkgrootdir = tempdir / 'root'
+ root.copytree(pkgrootdir)
+
+ with cd(pkgrootdir):
+ pythonpath = os.path.dirname(os.path.dirname(sphinx.__file__))
+ if os.getenv('PYTHONPATH'):
+ pythonpath = os.getenv('PYTHONPATH') + os.pathsep + pythonpath
+ command = [sys.executable, 'setup.py', 'build_sphinx']
+ command.extend(args)
+
+ proc = subprocess.Popen(
+ command,
+ env=dict(os.environ, PYTHONPATH=pythonpath),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ yield namedtuple('setup', 'pkgroot,proc')(pkgrootdir, proc)
-@with_setup_command(root)
-def test_build_sphinx(pkgroot, proc):
+def test_build_sphinx(setup_command):
+ proc = setup_command.proc
out, err = proc.communicate()
print(out)
print(err)
assert proc.returncode == 0
-@with_setup_command(root)
-def test_build_sphinx_with_nonascii_path(pkgroot, proc):
+@pytest.fixture
+def nonascii_srcdir(request, setup_command):
mb_name = u'\u65e5\u672c\u8a9e'
- srcdir = (pkgroot / 'doc')
+ srcdir = (setup_command.pkgroot / 'doc')
try:
(srcdir / mb_name).makedirs()
except UnicodeEncodeError:
from path import FILESYSTEMENCODING
- raise SkipTest(
+ pytest.skip(
'non-ASCII filename not supported on this filesystem encoding: '
- '%s', FILESYSTEMENCODING)
+ '%s' % FILESYSTEMENCODING)
(srcdir / mb_name / (mb_name + '.txt')).write_text(dedent("""
multi byte file name page
@@ -91,41 +87,47 @@ def test_build_sphinx_with_nonascii_path(pkgroot, proc):
%(mb_name)s/%(mb_name)s
""" % locals())
- ).encode('utf-8'))
+ ).encode('utf-8'))
+
+@pytest.mark.usefixtures('nonascii_srcdir')
+def test_build_sphinx_with_nonascii_path(setup_command):
+ proc = setup_command.proc
out, err = proc.communicate()
print(out)
print(err)
assert proc.returncode == 0
-@with_setup_command(root, '-b', 'linkcheck')
-def test_build_sphinx_return_nonzero_status(pkgroot, proc):
- srcdir = (pkgroot / 'doc')
+@pytest.mark.setup_command('-b', 'linkcheck')
+def test_build_sphinx_return_nonzero_status(setup_command):
+ srcdir = (setup_command.pkgroot / 'doc')
(srcdir / 'contents.txt').write_text(
'http://localhost.unexistentdomain/index.html')
+ proc = setup_command.proc
out, err = proc.communicate()
print(out)
print(err)
assert proc.returncode != 0, 'expect non-zero status for setup.py'
-@with_setup_command(root)
-def test_build_sphinx_warning_return_zero_status(pkgroot, proc):
- srcdir = (pkgroot / 'doc')
+def test_build_sphinx_warning_return_zero_status(setup_command):
+ srcdir = (setup_command.pkgroot / 'doc')
(srcdir / 'contents.txt').write_text(
'See :ref:`unexisting-reference-label`')
+ proc = setup_command.proc
out, err = proc.communicate()
print(out)
print(err)
assert proc.returncode == 0
-@with_setup_command(root, '--warning-is-error')
-def test_build_sphinx_warning_is_error_return_nonzero_status(pkgroot, proc):
- srcdir = (pkgroot / 'doc')
+@pytest.mark.setup_command('--warning-is-error')
+def test_build_sphinx_warning_is_error_return_nonzero_status(setup_command):
+ srcdir = (setup_command.pkgroot / 'doc')
(srcdir / 'contents.txt').write_text(
'See :ref:`unexisting-reference-label`')
+ proc = setup_command.proc
out, err = proc.communicate()
print(out)
print(err)
diff --git a/tests/test_templating.py b/tests/test_templating.py
index 3cfb69ba2..aaca9d6bf 100644
--- a/tests/test_templating.py
+++ b/tests/test_templating.py
@@ -9,10 +9,10 @@
:license: BSD, see LICENSE for details.
"""
-from util import with_app
+import pytest
-@with_app('html', testroot='templating')
+@pytest.mark.sphinx('html', testroot='templating')
def test_layout_overloading(app, status, warning):
app.builder.build_update()
@@ -21,7 +21,7 @@ def test_layout_overloading(app, status, warning):
assert '' in result
-@with_app('html', testroot='templating')
+@pytest.mark.sphinx('html', testroot='templating')
def test_autosummary_class_template_overloading(app, status, warning):
app.builder.build_update()
diff --git a/tests/test_theming.py b/tests/test_theming.py
index b62cbcd72..ce207a519 100644
--- a/tests/test_theming.py
+++ b/tests/test_theming.py
@@ -13,14 +13,16 @@ import os
import zipfile
import mock
+import pytest
from sphinx.theming import Theme, ThemeError
-from util import with_app, raises, path
+from util import with_app, path
-@with_app(confoverrides={'html_theme': 'ziptheme',
- 'html_theme_options.testopt': 'foo'})
+@pytest.mark.sphinx(
+ confoverrides={'html_theme': 'ziptheme',
+ 'html_theme_options.testopt': 'foo'})
def test_theme_api(app, status, warning):
cfg = app.config
@@ -46,10 +48,12 @@ def test_theme_api(app, status, warning):
assert theme.get_confstr('options', 'nosidebar') == 'false'
# nonexisting setting
assert theme.get_confstr('theme', 'foobar', 'def') == 'def'
- raises(ThemeError, theme.get_confstr, 'theme', 'foobar')
+ with pytest.raises(ThemeError):
+ theme.get_confstr('theme', 'foobar')
# options API
- raises(ThemeError, theme.get_options, {'nonexisting': 'foo'})
+ with pytest.raises(ThemeError):
+ theme.get_options({'nonexisting': 'foo'})
options = theme.get_options(cfg.html_theme_options)
assert options['testopt'] == 'foo'
assert options['nosidebar'] == 'false'
@@ -59,7 +63,7 @@ def test_theme_api(app, status, warning):
assert not os.path.exists(themedir)
-@with_app(testroot='tocdepth') # a minimal root
+@pytest.mark.sphinx(testroot='tocdepth') # a minimal root
def test_js_source(app, status, warning):
# Now sphinx provides non-minified JS files for jquery.js and underscore.js
# to clarify the source of the minified files. see also #1434.
@@ -83,7 +87,8 @@ def test_js_source(app, status, warning):
assert 'Underscore.js {v}'.format(v=v) in underscore_src, msg
-def test_double_inheriting_theme():
+@pytest.mark.sphinx(testroot='double-inheriting-theme')
+def test_double_inheriting_theme(make_app, app_params):
from sphinx.theming import load_theme_plugins # load original before patching
def load_themes():
@@ -92,8 +97,6 @@ def test_double_inheriting_theme():
for t in load_theme_plugins():
yield t
- @mock.patch('sphinx.theming.load_theme_plugins', side_effect=load_themes)
- @with_app(testroot='double-inheriting-theme')
- def test_double_inheriting_theme_(app, status, warning, m_):
- pass
- yield test_double_inheriting_theme_
+ with mock.patch('sphinx.theming.load_theme_plugins', side_effect=load_themes):
+ args, kwargs = app_params
+ make_app(*args, **kwargs)
diff --git a/tests/test_toctree.py b/tests/test_toctree.py
index 64cb8cfd6..441479882 100644
--- a/tests/test_toctree.py
+++ b/tests/test_toctree.py
@@ -8,11 +8,9 @@
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+import pytest
-from util import with_app
-
-
-@with_app(testroot='toctree-glob')
+@pytest.mark.sphinx(testroot='toctree-glob')
def test_relations(app, status, warning):
app.builder.build_all()
assert app.builder.relations['index'] == [None, None, 'foo']
diff --git a/tests/test_util_fileutil.py b/tests/test_util_fileutil.py
index 5810dd2a8..121b0d69f 100644
--- a/tests/test_util_fileutil.py
+++ b/tests/test_util_fileutil.py
@@ -12,7 +12,6 @@ from sphinx.util.fileutil import copy_asset, copy_asset_file
from sphinx.jinja2glue import BuiltinTemplateLoader
import mock
-from util import with_tempdir
class DummyTemplateLoader(BuiltinTemplateLoader):
@@ -24,33 +23,32 @@ class DummyTemplateLoader(BuiltinTemplateLoader):
self.init(builder)
-@with_tempdir
-def test_copy_asset_file(tmpdir):
+def test_copy_asset_file(tempdir):
renderer = DummyTemplateLoader()
# copy normal file
- src = (tmpdir / 'asset.txt')
+ src = (tempdir / 'asset.txt')
src.write_text('# test data')
- dest = (tmpdir / 'output.txt')
+ dest = (tempdir / 'output.txt')
copy_asset_file(src, dest)
assert dest.exists()
assert src.text() == dest.text()
# copy template file
- src = (tmpdir / 'asset.txt_t')
+ src = (tempdir / 'asset.txt_t')
src.write_text('# {{var1}} data')
- dest = (tmpdir / 'output.txt_t')
+ dest = (tempdir / 'output.txt_t')
copy_asset_file(src, dest, {'var1': 'template'}, renderer)
assert not dest.exists()
- assert (tmpdir / 'output.txt').exists()
- assert (tmpdir / 'output.txt').text() == '# template data'
+ assert (tempdir / 'output.txt').exists()
+ assert (tempdir / 'output.txt').text() == '# template data'
# copy template file to subdir
- src = (tmpdir / 'asset.txt_t')
+ src = (tempdir / 'asset.txt_t')
src.write_text('# {{var1}} data')
- subdir1 = (tmpdir / 'subdir')
+ subdir1 = (tempdir / 'subdir')
subdir1.makedirs()
copy_asset_file(src, subdir1, {'var1': 'template'}, renderer)
@@ -58,8 +56,8 @@ def test_copy_asset_file(tmpdir):
assert (subdir1 / 'asset.txt').text() == '# template data'
# copy template file without context
- src = (tmpdir / 'asset.txt_t')
- subdir2 = (tmpdir / 'subdir2')
+ src = (tempdir / 'asset.txt_t')
+ subdir2 = (tempdir / 'subdir2')
subdir2.makedirs()
copy_asset_file(src, subdir2)
@@ -68,12 +66,11 @@ def test_copy_asset_file(tmpdir):
assert (subdir2 / 'asset.txt_t').text() == '# {{var1}} data'
-@with_tempdir
-def test_copy_asset(tmpdir):
+def test_copy_asset(tempdir):
renderer = DummyTemplateLoader()
# prepare source files
- source = (tmpdir / 'source')
+ source = (tempdir / 'source')
source.makedirs()
(source / 'index.rst').write_text('index.rst')
(source / 'foo.rst_t').write_text('{{var1}}.rst')
@@ -84,13 +81,13 @@ def test_copy_asset(tmpdir):
(source / '_templates' / 'sidebar.html_t').write_text('sidebar: {{var2}}')
# copy a single file
- assert not (tmpdir / 'test1').exists()
- copy_asset(source / 'index.rst', tmpdir / 'test1')
- assert (tmpdir / 'test1').exists()
- assert (tmpdir / 'test1/index.rst').exists()
+ assert not (tempdir / 'test1').exists()
+ copy_asset(source / 'index.rst', tempdir / 'test1')
+ assert (tempdir / 'test1').exists()
+ assert (tempdir / 'test1/index.rst').exists()
# copy directories
- destdir = tmpdir / 'test2'
+ destdir = tempdir / 'test2'
copy_asset(source, destdir, context=dict(var1='bar', var2='baz'), renderer=renderer)
assert (destdir / 'index.rst').exists()
assert (destdir / 'foo.rst').exists()
@@ -104,7 +101,7 @@ def test_copy_asset(tmpdir):
def excluded(path):
return ('sidebar.html' in path or 'basic.css' in path)
- destdir = tmpdir / 'test3'
+ destdir = tempdir / 'test3'
copy_asset(source, destdir, excluded,
context=dict(var1='bar', var2='baz'), renderer=renderer)
assert (destdir / 'index.rst').exists()
diff --git a/tests/test_util_i18n.py b/tests/test_util_i18n.py
index 849796a8f..74313c5f5 100644
--- a/tests/test_util_i18n.py
+++ b/tests/test_util_i18n.py
@@ -12,38 +12,35 @@ from __future__ import print_function
import os
import datetime
-from os import path
+import pytest
from babel.messages.mofile import read_mo
from sphinx.util import i18n
from sphinx.errors import SphinxError
-from util import TestApp, with_tempdir, raises
-
def test_catalog_info_for_file_and_path():
cat = i18n.CatalogInfo('path', 'domain', 'utf-8')
assert cat.po_file == 'domain.po'
assert cat.mo_file == 'domain.mo'
- assert cat.po_path == path.join('path', 'domain.po')
- assert cat.mo_path == path.join('path', 'domain.mo')
+ assert cat.po_path == os.path.join('path', 'domain.po')
+ assert cat.mo_path == os.path.join('path', 'domain.mo')
def test_catalog_info_for_sub_domain_file_and_path():
cat = i18n.CatalogInfo('path', 'sub/domain', 'utf-8')
assert cat.po_file == 'sub/domain.po'
assert cat.mo_file == 'sub/domain.mo'
- assert cat.po_path == path.join('path', 'sub/domain.po')
- assert cat.mo_path == path.join('path', 'sub/domain.mo')
+ assert cat.po_path == os.path.join('path', 'sub/domain.po')
+ assert cat.mo_path == os.path.join('path', 'sub/domain.mo')
-@with_tempdir
-def test_catalog_outdated(dir):
- (dir / 'test.po').write_text('#')
- cat = i18n.CatalogInfo(dir, 'test', 'utf-8')
+def test_catalog_outdated(tempdir):
+ (tempdir / 'test.po').write_text('#')
+ cat = i18n.CatalogInfo(tempdir, 'test', 'utf-8')
assert cat.is_outdated() # if mo is not exist
- mo_file = (dir / 'test.mo')
+ mo_file = (tempdir / 'test.mo')
mo_file.write_text('#')
assert not cat.is_outdated() # if mo is exist and newer than po
@@ -51,31 +48,29 @@ def test_catalog_outdated(dir):
assert cat.is_outdated() # if mo is exist and older than po
-@with_tempdir
-def test_catalog_write_mo(dir):
- (dir / 'test.po').write_text('#')
- cat = i18n.CatalogInfo(dir, 'test', 'utf-8')
- cat.write_mo('en')
- assert path.exists(cat.mo_path)
+def test_catalog_write_mo(tempdir):
+ (tempdir / 'test.po').write_text('#')
+ cat = i18n.CatalogInfo(tempdir, 'test', 'utf-8')
+ cat.write_mo('en', lambda *a, **kw: None)
+ assert os.path.exists(cat.mo_path)
with open(cat.mo_path, 'rb') as f:
assert read_mo(f) is not None
-@with_tempdir
-def test_get_catalogs_for_xx(dir):
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
- (dir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
- (dir / 'loc1' / 'en' / 'LC_MESSAGES' / 'test6.po').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_ALL').makedirs()
- (dir / 'loc1' / 'xx' / 'LC_ALL' / 'test7.po').write_text('#')
+def test_get_catalogs_for_xx(tempdir):
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
+ (tempdir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
+ (tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / 'test6.po').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_ALL').makedirs()
+ (tempdir / 'loc1' / 'xx' / 'LC_ALL' / 'test7.po').write_text('#')
- catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', force_all=False)
+ catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', force_all=False)
domains = set(c.domain for c in catalogs)
assert domains == set([
'test1',
@@ -85,24 +80,22 @@ def test_get_catalogs_for_xx(dir):
])
-@with_tempdir
-def test_get_catalogs_for_en(dir):
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'xx_dom.po').write_text('#')
- (dir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
- (dir / 'loc1' / 'en' / 'LC_MESSAGES' / 'en_dom.po').write_text('#')
+def test_get_catalogs_for_en(tempdir):
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'xx_dom.po').write_text('#')
+ (tempdir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
+ (tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / 'en_dom.po').write_text('#')
- catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'en', force_all=False)
+ catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'en', force_all=False)
domains = set(c.domain for c in catalogs)
assert domains == set(['en_dom'])
-@with_tempdir
-def test_get_catalogs_with_non_existent_locale(dir):
- catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx')
+def test_get_catalogs_with_non_existent_locale(tempdir):
+ catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx')
assert not catalogs
- catalogs = i18n.find_catalog_source_files([dir / 'loc1'], None)
+ catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], None)
assert not catalogs
@@ -111,25 +104,24 @@ def test_get_catalogs_with_non_existent_locale_dirs():
assert not catalogs
-@with_tempdir
-def test_get_catalogs_for_xx_without_outdated(dir):
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.mo').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.mo').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.mo').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.mo').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.mo').write_text('#')
+def test_get_catalogs_for_xx_without_outdated(tempdir):
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.mo').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.mo').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.mo').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.mo').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.mo').write_text('#')
- catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', force_all=False)
+ catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', force_all=False)
assert not catalogs
- catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', force_all=True)
+ catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', force_all=True)
domains = set(c.domain for c in catalogs)
assert domains == set([
'test1',
@@ -139,29 +131,27 @@ def test_get_catalogs_for_xx_without_outdated(dir):
])
-@with_tempdir
-def test_get_catalogs_from_multiple_locale_dirs(dir):
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
- (dir / 'loc2' / 'xx' / 'LC_MESSAGES').makedirs()
- (dir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
- (dir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
+def test_get_catalogs_from_multiple_locale_dirs(tempdir):
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
+ (tempdir / 'loc2' / 'xx' / 'LC_MESSAGES').makedirs()
+ (tempdir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
+ (tempdir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
- catalogs = i18n.find_catalog_source_files([dir / 'loc1', dir / 'loc2'], 'xx')
+ catalogs = i18n.find_catalog_source_files([tempdir / 'loc1', tempdir / 'loc2'], 'xx')
domains = sorted(c.domain for c in catalogs)
assert domains == ['test1', 'test1', 'test2']
-@with_tempdir
-def test_get_catalogs_with_compact(dir):
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test3.po').write_text('#')
- (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
+def test_get_catalogs_with_compact(tempdir):
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test3.po').write_text('#')
+ (tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
- catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', gettext_compact=True)
+ catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', gettext_compact=True)
domains = set(c.domain for c in catalogs)
assert domains == set(['test1', 'test2', 'sub'])
@@ -214,9 +204,7 @@ def test_format_date():
assert i18n.format_date(format, date=date) == 'Feb 7, 2016'
-def test_get_filename_for_language():
- app = TestApp()
-
+def test_get_filename_for_language(app):
# language is None
app.env.config.language = None
assert app.env.config.language is None
@@ -269,4 +257,5 @@ def test_get_filename_for_language():
# invalid figure_language_filename
app.env.config.figure_language_filename = '{root}.{invalid}{ext}'
- raises(SphinxError, i18n.get_image_filename_for_language, 'foo.png', app.env)
+ with pytest.raises(SphinxError):
+ i18n.get_image_filename_for_language('foo.png', app.env)
diff --git a/tests/test_util_nodes.py b/tests/test_util_nodes.py
index ac8c3645d..7aded8a4b 100644
--- a/tests/test_util_nodes.py
+++ b/tests/test_util_nodes.py
@@ -17,6 +17,7 @@ from docutils import frontend
from sphinx.util.nodes import extract_messages, clean_astext
from sphinx.transforms import ApplySourceWorkaround
+import pytest
def _transform(doctree):
@@ -49,84 +50,63 @@ def assert_node_count(messages, node_type, expect_count):
% (node_type, node_list, count, expect_count))
-def test_extract_messages():
- text = dedent(
- """
- .. admonition:: admonition title
+@pytest.mark.parametrize(
+ 'rst,node_cls,count',
+ [
+ (
+ """
+ .. admonition:: admonition title
- admonition body
- """
- )
- yield (
- assert_node_count,
- extract_messages(_get_doctree(text)),
- nodes.title, 1,
- )
+ admonition body
+ """,
+ nodes.title, 1
+ ),
+ (
+ """
+ .. figure:: foo.jpg
- text = dedent(
- """
- .. figure:: foo.jpg
+ this is title
+ """,
+ nodes.caption, 1,
+ ),
+ (
+ """
+ .. rubric:: spam
+ """,
+ nodes.rubric, 1,
+ ),
+ (
+ """
+ | spam
+ | egg
+ """,
+ nodes.line, 2,
+ ),
+ (
+ """
+ section
+ =======
- this is title
- """
- )
- yield (
- assert_node_count,
- extract_messages(_get_doctree(text)),
- nodes.caption, 1,
- )
+ +----------------+
+ | | **Title 1** |
+ | | Message 1 |
+ +----------------+
+ """,
+ nodes.line, 2,
+ ),
+ (
+ """
+ * | **Title 1**
+ | Message 1
+ """,
+ nodes.line, 2,
- text = dedent(
- """
- .. rubric:: spam
- """
- )
- yield (
- assert_node_count,
- extract_messages(_get_doctree(text)),
- nodes.rubric, 1,
- )
-
- text = dedent(
- """
- | spam
- | egg
- """
- )
- yield (
- assert_node_count,
- extract_messages(_get_doctree(text)),
- nodes.line, 2,
- )
-
- text = dedent(
- """
- section
- =======
-
- +----------------+
- | | **Title 1** |
- | | Message 1 |
- +----------------+
- """
- )
- yield (
- assert_node_count,
- extract_messages(_get_doctree(text)),
- nodes.line, 2,
- )
-
- text = dedent(
- """
- * | **Title 1**
- | Message 1
- """
- )
- yield (
- assert_node_count,
- extract_messages(_get_doctree(text)),
- nodes.line, 2,
- )
+ ),
+ ]
+)
+def test_extract_messages(rst, node_cls, count):
+ msg = extract_messages(_get_doctree(dedent(rst)))
+ assert_node_count(msg, node_cls, count)
def test_extract_messages_without_rawsource():
diff --git a/tests/test_versioning.py b/tests/test_versioning.py
index f5b5057d7..4b9ebefcb 100644
--- a/tests/test_versioning.py
+++ b/tests/test_versioning.py
@@ -16,7 +16,7 @@ from docutils.parsers.rst.directives.html import MetaBody
from sphinx import addnodes
from sphinx.versioning import add_uids, merge_doctrees, get_ratio
-from util import TestApp
+from util import SphinxTestApp
app = original = original_uids = None
@@ -24,7 +24,7 @@ app = original = original_uids = None
def setup_module():
global app, original, original_uids
- app = TestApp(testroot='versioning')
+ app = SphinxTestApp(testroot='versioning')
app.builder.env.app = app
app.connect('doctree-resolved', on_doctree_resolved)
app.build()
diff --git a/tests/test_websupport.py b/tests/test_websupport.py
index bb41ae1ab..bded050d3 100644
--- a/tests/test_websupport.py
+++ b/tests/test_websupport.py
@@ -9,10 +9,6 @@
:license: BSD, see LICENSE for details.
"""
-from functools import wraps
-
-from six import StringIO
-
from sphinx.websupport import WebSupport
from sphinx.websupport.errors import DocumentNotFoundError, \
CommentNotAllowedError, UserNotAuthorizedError
@@ -26,26 +22,28 @@ try:
except ImportError:
sqlalchemy_missing = True
-from util import rootdir, tempdir, raises, skip_if
+import pytest
+from util import rootdir, tempdir
-default_settings = {'builddir': tempdir / 'websupport',
- 'status': StringIO(),
- 'warning': StringIO()}
+@pytest.fixture
+def support(request):
+ settings = {
+ 'srcdir': rootdir / 'root',
+ # to use same directory for 'builddir' in each 'support' fixture, using
+ # 'tempdir' (static) value instead of 'tempdir' fixture value.
+ # each test expect result of db value at previous test case.
+ 'builddir': tempdir / 'websupport'
+ }
+ marker = request.node.get_marker('support')
+ if marker:
+ settings.update(marker.kwargs)
+
+ support = WebSupport(**settings)
+ yield support
-def with_support(*args, **kwargs):
- """Make a WebSupport object and pass it the test."""
- settings = default_settings.copy()
- settings.update(kwargs)
-
- def generator(func):
- @wraps(func)
- def new_func(*args2, **kwargs2):
- support = WebSupport(**settings)
- func(support, *args2, **kwargs2)
- return new_func
- return generator
+with_support = pytest.mark.support
class NullStorage(StorageBackend):
@@ -55,26 +53,28 @@ class NullStorage(StorageBackend):
@with_support(storage=NullStorage())
def test_no_srcdir(support):
# make sure the correct exception is raised if srcdir is not given.
- raises(RuntimeError, support.build)
+ with pytest.raises(RuntimeError):
+ support.build()
-@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
-@with_support(srcdir=rootdir / 'root')
+@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
+@with_support()
def test_build(support):
support.build()
-@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support()
def test_get_document(support):
- raises(DocumentNotFoundError, support.get_document, 'nonexisting')
+ with pytest.raises(DocumentNotFoundError):
+ support.get_document('nonexisting')
contents = support.get_document('contents')
assert contents['title'] and contents['body'] \
and contents['sidebar'] and contents['relbar']
-@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support()
def test_comments(support):
session = Session()
@@ -92,8 +92,8 @@ def test_comments(support):
# Make sure that comments can't be added to a comment where
# displayed == False, since it could break the algorithm that
# converts a nodes comments to a tree.
- raises(CommentNotAllowedError, support.add_comment, 'Not allowed',
- parent_id=str(hidden_comment['id']))
+ with pytest.raises(CommentNotAllowedError):
+ support.add_comment('Not allowed', parent_id=str(hidden_comment['id']))
# Add a displayed and not displayed child to the displayed comment.
support.add_comment('Child test comment', parent_id=str(comment['id']),
username='user_one')
@@ -123,7 +123,113 @@ def test_comments(support):
assert children[0]['text'] == 'Child test comment \n'
-@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
+@with_support()
+def test_user_delete_comments(support):
+ def get_comment():
+ session = Session()
+ node = session.query(Node).first()
+ session.close()
+ return support.get_data(node.id)['comments'][0]
+
+ comment = get_comment()
+ assert comment['username'] == 'user_one'
+ # Make sure other normal users can't delete someone elses comments.
+ with pytest.raises(UserNotAuthorizedError):
+ support.delete_comment(comment['id'], username='user_two')
+ # Now delete the comment using the correct username.
+ support.delete_comment(comment['id'], username='user_one')
+ comment = get_comment()
+ assert comment['username'] == '[deleted]'
+ assert comment['text'] == '[deleted]'
+
+
+called = False
+
+
+def moderation_callback(comment):
+ global called
+ called = True
+
+
+@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
+@with_support(moderation_callback=moderation_callback)
+def test_moderation(support):
+ session = Session()
+ nodes = session.query(Node).all()
+ node = nodes[7]
+ session.close()
+ accepted = support.add_comment('Accepted Comment', node_id=node.id,
+ displayed=False)
+ deleted = support.add_comment('Comment to delete', node_id=node.id,
+ displayed=False)
+ # Make sure the moderation_callback is called.
+ assert called
+ # Make sure the user must be a moderator.
+ with pytest.raises(UserNotAuthorizedError):
+ support.accept_comment(accepted['id'])
+ with pytest.raises(UserNotAuthorizedError):
+ support.delete_comment(deleted['id'])
+ support.accept_comment(accepted['id'], moderator=True)
+ support.delete_comment(deleted['id'], moderator=True)
+ comments = support.get_data(node.id)['comments']
+ assert len(comments) == 1
+ comments = support.get_data(node.id, moderator=True)['comments']
+ assert len(comments) == 1
+
+
+@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
+@with_support()
+def test_moderator_delete_comments(support):
+ def get_comment():
+ session = Session()
+ node = session.query(Node).first()
+ session.close()
+ return support.get_data(node.id, moderator=True)['comments'][1]
+
+ comment = get_comment()
+ support.delete_comment(comment['id'], username='user_two',
+ moderator=True)
+ with pytest.raises(IndexError):
+ get_comment()
+
+
+@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
+@with_support()
+def test_update_username(support):
+ support.update_username('user_two', 'new_user_two')
+ session = Session()
+ comments = session.query(Comment).\
+ filter(Comment.username == 'user_two').all()
+ assert len(comments) == 0
+ votes = session.query(CommentVote).\
+ filter(CommentVote.username == 'user_two').all()
+ assert len(votes) == 0
+ comments = session.query(Comment).\
+ filter(Comment.username == 'new_user_two').all()
+ assert len(comments) == 1
+ votes = session.query(CommentVote).\
+ filter(CommentVote.username == 'new_user_two').all()
+ assert len(votes) == 0
+
+
+@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
+@with_support()
+def test_proposals(support):
+ session = Session()
+ node = session.query(Node).first()
+
+ data = support.get_data(node.id)
+
+ source = data['source']
+ proposal = source[:5] + source[10:15] + 'asdf' + source[15:]
+
+ support.add_comment('Proposal comment',
+ node_id=node.id,
+ proposal=proposal)
+
+
+@pytest.mark.skipif(sqlalchemy_missing, reason='needs sqlalchemy')
@with_support()
def test_voting(support):
session = Session()
@@ -147,8 +253,10 @@ def test_voting(support):
check_rating(2)
# Make sure a vote with value > 1 or < -1 can't be cast.
- raises(ValueError, support.process_vote, comment['id'], 'user_one', '2')
- raises(ValueError, support.process_vote, comment['id'], 'user_one', '-2')
+ with pytest.raises(ValueError):
+ support.process_vote(comment['id'], 'user_one', '2')
+ with pytest.raises(ValueError):
+ support.process_vote(comment['id'], 'user_one', '-2')
# Make sure past voting data is associated with comments when they are
# fetched.
@@ -157,109 +265,6 @@ def test_voting(support):
assert comment['vote'] == 1, '%s != 1' % comment['vote']
-@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
-@with_support()
-def test_proposals(support):
- session = Session()
- node = session.query(Node).first()
-
- data = support.get_data(node.id)
-
- source = data['source']
- proposal = source[:5] + source[10:15] + 'asdf' + source[15:]
-
- support.add_comment('Proposal comment',
- node_id=node.id,
- proposal=proposal)
-
-
-@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
-@with_support()
-def test_user_delete_comments(support):
- def get_comment():
- session = Session()
- node = session.query(Node).first()
- session.close()
- return support.get_data(node.id)['comments'][0]
-
- comment = get_comment()
- assert comment['username'] == 'user_one'
- # Make sure other normal users can't delete someone elses comments.
- raises(UserNotAuthorizedError, support.delete_comment,
- comment['id'], username='user_two')
- # Now delete the comment using the correct username.
- support.delete_comment(comment['id'], username='user_one')
- comment = get_comment()
- assert comment['username'] == '[deleted]'
- assert comment['text'] == '[deleted]'
-
-
-@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
-@with_support()
-def test_moderator_delete_comments(support):
- def get_comment():
- session = Session()
- node = session.query(Node).first()
- session.close()
- return support.get_data(node.id, moderator=True)['comments'][1]
-
- comment = get_comment()
- support.delete_comment(comment['id'], username='user_two',
- moderator=True)
- raises(IndexError, get_comment)
-
-
-@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
-@with_support()
-def test_update_username(support):
- support.update_username('user_two', 'new_user_two')
- session = Session()
- comments = session.query(Comment).\
- filter(Comment.username == 'user_two').all()
- assert len(comments) == 0
- votes = session.query(CommentVote).\
- filter(CommentVote.username == 'user_two').all()
- assert len(votes) == 0
- comments = session.query(Comment).\
- filter(Comment.username == 'new_user_two').all()
- assert len(comments) == 1
- votes = session.query(CommentVote).\
- filter(CommentVote.username == 'new_user_two').all()
- assert len(votes) == 0
-
-
-called = False
-
-
-def moderation_callback(comment):
- global called
- called = True
-
-
-@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
-@with_support(moderation_callback=moderation_callback)
-def test_moderation(support):
- session = Session()
- nodes = session.query(Node).all()
- node = nodes[7]
- session.close()
- accepted = support.add_comment('Accepted Comment', node_id=node.id,
- displayed=False)
- deleted = support.add_comment('Comment to delete', node_id=node.id,
- displayed=False)
- # Make sure the moderation_callback is called.
- assert called
- # Make sure the user must be a moderator.
- raises(UserNotAuthorizedError, support.accept_comment, accepted['id'])
- raises(UserNotAuthorizedError, support.delete_comment, deleted['id'])
- support.accept_comment(accepted['id'], moderator=True)
- support.delete_comment(deleted['id'], moderator=True)
- comments = support.get_data(node.id)['comments']
- assert len(comments) == 1
- comments = support.get_data(node.id, moderator=True)['comments']
- assert len(comments) == 1
-
-
def test_differ():
source = 'Lorem ipsum dolor sit amet,\nconsectetur adipisicing elit,\n' \
'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'
diff --git a/tests/test_writer_latex.py b/tests/test_writer_latex.py
index 72eb7ed2a..33803299b 100644
--- a/tests/test_writer_latex.py
+++ b/tests/test_writer_latex.py
@@ -11,7 +11,7 @@
from __future__ import print_function
from sphinx.writers.latex import rstdim_to_latexdim
-from util import raises
+import pytest
def test_rstdim_to_latexdim():
@@ -32,5 +32,6 @@ def test_rstdim_to_latexdim():
assert rstdim_to_latexdim('.5em') == '.5em'
# unknown values (it might be generated by 3rd party extension)
- raises(ValueError, rstdim_to_latexdim, 'unknown')
+ with pytest.raises(ValueError):
+ rstdim_to_latexdim('unknown')
assert rstdim_to_latexdim('160.0unknown') == '160.0unknown'
diff --git a/tests/util.py b/tests/util.py
index 13366a1da..a756b6006 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -10,14 +10,13 @@
import os
import re
import sys
-import tempfile
import warnings
from functools import wraps
from xml.etree import ElementTree
-from six import StringIO, string_types
+from six import string_types
-from nose import tools, SkipTest
+import pytest
from docutils import nodes
from docutils.parsers.rst import directives, roles
@@ -27,16 +26,17 @@ from sphinx.builders.latex import LaTeXBuilder
from sphinx.theming import Theme
from sphinx.ext.autodoc import AutoDirective
from sphinx.pycode import ModuleAnalyzer
+from sphinx.deprecation import RemovedInSphinx17Warning
-from path import path, repr_as # NOQA
+from path import path
__all__ = [
- 'rootdir', 'tempdir', 'raises', 'raises_msg',
- 'skip_if', 'skip_unless', 'skip_unless_importable', 'Struct',
- 'ListOutput', 'TestApp', 'with_app', 'gen_with_app',
- 'path', 'with_tempdir',
- 'sprint', 'remove_unicode_literals',
+ 'rootdir', 'tempdir',
+ 'skip_unless_importable', 'Struct',
+ 'SphinxTestApp',
+ 'path',
+ 'remove_unicode_literals',
]
@@ -44,36 +44,6 @@ rootdir = path(os.path.dirname(__file__) or '.').abspath()
tempdir = path(os.environ['SPHINX_TEST_TEMPDIR']).abspath()
-def _excstr(exc):
- if type(exc) is tuple:
- return str(tuple(map(_excstr, exc)))
- return exc.__name__
-
-
-def raises(exc, func, *args, **kwds):
- """Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*."""
- try:
- func(*args, **kwds)
- except exc:
- pass
- else:
- raise AssertionError('%s did not raise %s' %
- (func.__name__, _excstr(exc)))
-
-
-def raises_msg(exc, msg, func, *args, **kwds):
- """Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*,
- and check if the message contains *msg*.
- """
- try:
- func(*args, **kwds)
- except exc as err:
- assert msg in str(err), "\"%s\" not in \"%s\"" % (msg, err)
- else:
- raise AssertionError('%s did not raise %s' %
- (func.__name__, _excstr(exc)))
-
-
def assert_re_search(regex, text, flags=0):
if not re.search(regex, text, flags):
assert False, '%r did not match %r' % (regex, text)
@@ -118,43 +88,14 @@ def assert_node(node, cls=None, xpath="", **kwargs):
'The node%s[%s] is not %r: %r' % (xpath, key, value, node[key])
-try:
- from nose.tools import assert_in, assert_not_in
-except ImportError:
- def assert_in(x, thing, msg=''):
- if x not in thing:
- assert False, msg or '%r is not in %r' % (x, thing)
-
- def assert_not_in(x, thing, msg=''):
- if x in thing:
- assert False, msg or '%r is in %r' % (x, thing)
-
-
-def skip_if(condition, msg=None):
- """Decorator to skip test if condition is true."""
- def deco(test):
- @tools.make_decorator(test)
- def skipper(*args, **kwds):
- if condition:
- raise SkipTest(msg or 'conditional skip')
- return test(*args, **kwds)
- return skipper
- return deco
-
-
-def skip_unless(condition, msg=None):
- """Decorator to skip test if condition is false."""
- return skip_if(not condition, msg)
-
-
def skip_unless_importable(module, msg=None):
"""Decorator to skip test if module is not importable."""
try:
__import__(module)
except ImportError:
- return skip_if(True, msg)
+ return pytest.mark.skipif(True, reason=(msg or 'conditional skip'))
else:
- return skip_if(False, msg)
+ return pytest.mark.skipif(False, reason=(msg or 'conditional skip'))
def etree_parse(path):
@@ -168,22 +109,7 @@ class Struct(object):
self.__dict__.update(kwds)
-class ListOutput(object):
- """
- File-like object that collects written text in a list.
- """
- def __init__(self, name):
- self.name = name
- self.content = []
-
- def reset(self):
- del self.content[:]
-
- def write(self, text):
- self.content.append(text)
-
-
-class TestApp(application.Sphinx):
+class SphinxTestApp(application.Sphinx):
"""
A subclass of :class:`Sphinx` that runs on the test root, with some
better default values for the initialization parameters.
@@ -222,10 +148,6 @@ class TestApp(application.Sphinx):
doctreedir.makedirs()
if confoverrides is None:
confoverrides = {}
- if status is None:
- status = StringIO()
- if warning is None:
- warning = ListOutput('stderr')
# if warningiserror is None:
warningiserror = False
@@ -263,59 +185,6 @@ class TestApp(application.Sphinx):
return '<%s buildername=%r>' % (self.__class__.__name__, self.builder.name)
-def with_app(*args, **kwargs):
- """
- Make a TestApp with args and kwargs, pass it to the test and clean up
- properly.
- """
- def generator(func):
- @wraps(func)
- def deco(*args2, **kwargs2):
- status, warning = StringIO(), StringIO()
- kwargs['status'] = status
- kwargs['warning'] = warning
- app = TestApp(*args, **kwargs)
- try:
- func(app, status, warning, *args2, **kwargs2)
- finally:
- app.cleanup()
- return deco
- return generator
-
-
-def gen_with_app(*args, **kwargs):
- """
- Decorate a test generator to pass a TestApp as the first argument to the
- test generator when it's executed.
- """
- def generator(func):
- @wraps(func)
- def deco(*args2, **kwargs2):
- status, warning = StringIO(), StringIO()
- kwargs['status'] = status
- kwargs['warning'] = warning
- app = TestApp(*args, **kwargs)
- try:
- for item in func(app, status, warning, *args2, **kwargs2):
- yield item
- finally:
- app.cleanup()
- return deco
- return generator
-
-
-def with_tempdir(func):
- def new_func(*args, **kwds):
- new_tempdir = path(tempfile.mkdtemp(dir=tempdir))
- func(new_tempdir, *args, **kwds)
- new_func.__name__ = func.__name__
- return new_func
-
-
-def sprint(*args):
- sys.stderr.write(' '.join(map(str, args)) + '\n')
-
-
_unicode_literals_re = re.compile(r'u(".*?")|u(\'.*?\')')
@@ -333,3 +202,162 @@ def find_files(root, suffix=None):
def strip_escseq(text):
return re.sub('\x1b.*?m', '', text)
+
+
+# #############################################
+# DEPRECATED implementations
+
+from six import StringIO
+
+
+def gen_with_app(*args, **kwargs):
+ """
+ **DEPRECATED**: use pytest.mark.parametrize instead.
+
+ Decorate a test generator to pass a SphinxTestApp as the first argument to
+ the test generator when it's executed.
+ """
+ def generator(func):
+ @wraps(func)
+ def deco(*args2, **kwargs2):
+ status, warning = StringIO(), StringIO()
+ kwargs['status'] = status
+ kwargs['warning'] = warning
+ app = SphinxTestApp(*args, **kwargs)
+ try:
+ for item in func(app, status, warning, *args2, **kwargs2):
+ yield item
+ finally:
+ app.cleanup()
+ return deco
+ return generator
+
+
+def skip_if(condition, msg=None):
+ """
+ **DEPRECATED**: use pytest.mark.skipif instead.
+
+ Decorator to skip test if condition is true.
+ """
+ return pytest.mark.skipif(condition, reason=(msg or 'conditional skip'))
+
+
+def skip_unless(condition, msg=None):
+ """
+ **DEPRECATED**: use pytest.mark.skipif instead.
+
+ Decorator to skip test if condition is false.
+ """
+ return pytest.mark.skipif(not condition, reason=(msg or 'conditional skip'))
+
+
+def with_tempdir(func):
+ """
+ **DEPRECATED**: use tempdir fixture instead.
+ """
+ return func
+
+
+def raises(exc, func, *args, **kwds):
+ """
+ **DEPRECATED**: use pytest.raises instead.
+
+ Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*.
+ """
+ with pytest.raises(exc):
+ func(*args, **kwds)
+
+
+def raises_msg(exc, msg, func, *args, **kwds):
+ """
+ **DEPRECATED**: use pytest.raises instead.
+
+ Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*,
+ and check if the message contains *msg*.
+ """
+ with pytest.raises(exc) as excinfo:
+ func(*args, **kwds)
+ assert msg in str(excinfo.value)
+
+
+def assert_true(v1, msg=''):
+ """
+ **DEPRECATED**: use assert instead.
+ """
+ assert v1, msg
+
+
+def assert_equal(v1, v2, msg=''):
+ """
+ **DEPRECATED**: use assert instead.
+ """
+ assert v1 == v2, msg
+
+
+def assert_in(x, thing, msg=''):
+ """
+ **DEPRECATED**: use assert instead.
+ """
+ if x not in thing:
+ assert False, msg or '%r is not in %r' % (x, thing)
+
+
+def assert_not_in(x, thing, msg=''):
+ """
+ **DEPRECATED**: use assert instead.
+ """
+ if x in thing:
+ assert False, msg or '%r is in %r' % (x, thing)
+
+
+class ListOutput(object):
+ """
+ File-like object that collects written text in a list.
+ """
+ def __init__(self, name):
+ self.name = name
+ self.content = []
+
+ def reset(self):
+ del self.content[:]
+
+ def write(self, text):
+ self.content.append(text)
+
+
+# **DEPRECATED**: use pytest.skip instead.
+SkipTest = pytest.skip.Exception
+
+
+class _DeprecationWrapper(object):
+ def __init__(self, mod, deprecated):
+ self._mod = mod
+ self._deprecated = deprecated
+
+ def __getattr__(self, attr):
+ if attr in self._deprecated:
+ obj, instead = self._deprecated[attr]
+ warnings.warn("tests/util.py::%s is deprecated and will be "
+ "removed in Sphinx 1.7, please use %s instead."
+ % (attr, instead),
+ RemovedInSphinx17Warning, stacklevel=2)
+ return obj
+ return getattr(self._mod, attr)
+
+
+sys.modules[__name__] = _DeprecationWrapper(sys.modules[__name__], dict( # type: ignore
+ with_app=(pytest.mark.sphinx, 'pytest.mark.sphinx'),
+ TestApp=(SphinxTestApp, 'SphinxTestApp'),
+ gen_with_app=(gen_with_app, 'pytest.mark.parametrize'),
+ skip_if=(skip_if, 'pytest.skipif'),
+ skip_unless=(skip_unless, 'pytest.skipif'),
+ with_tempdir=(with_tempdir, 'tmpdir pytest fixture'),
+ raises=(raises, 'pytest.raises'),
+ raises_msg=(raises_msg, 'pytest.raises'),
+ assert_true=(assert_true, 'assert'),
+ assert_equal=(assert_equal, 'assert'),
+ assert_in=(assert_in, 'assert'),
+ assert_not_in=(assert_not_in, 'assert'),
+ ListOutput=(ListOutput, 'StringIO'),
+ SkipTest=(SkipTest, 'pytest.skip'),
+))
diff --git a/tox.ini b/tox.ini
index 09241c1d8..b3f084a4d 100644
--- a/tox.ini
+++ b/tox.ini
@@ -4,7 +4,7 @@ envlist=flake8,py27,py34,py35,py36,pypy,du13,du12,du11
[testenv]
deps=
six
- nose
+ pytest
sqlalchemy
whoosh
html5lib
@@ -15,7 +15,7 @@ setenv =
SPHINX_TEST_TEMPDIR = {envdir}/testbuild
PYTHONDONTWRITEBYTECODE = true
commands=
- {envpython} -Wall tests/run.py --ignore-files=test_autodoc_py35 -m '^[tT]est' {posargs}
+ {envpython} -Wall tests/run.py --ignore tests/py35 {posargs}
sphinx-build -q -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html
[testenv:pypy]
@@ -48,5 +48,5 @@ deps=
[testenv:py35]
commands=
- {envpython} -Wall tests/run.py -m '^[tT]est' {posargs}
+ {envpython} -Wall tests/run.py {posargs}
sphinx-build -q -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html
diff --git a/utils/check_sources.py b/utils/check_sources.py
index 18d444057..066ed8881 100755
--- a/utils/check_sources.py
+++ b/utils/check_sources.py
@@ -34,7 +34,7 @@ def checker(*suffixes, **kwds):
# this one is a byte regex since it is applied before decoding
-coding_re = re.compile(br'coding[:=]\s*([-\w.]+)')
+coding_re = re.compile(br'coding[:=]\s*([-\w.]+)')
uni_coding_re = re.compile(r'^#.*coding[:=]\s*([-\w.]+).*')
name_mail_re = r'[\w ]+(<.*?>)?'
@@ -44,8 +44,8 @@ copyright_re = re.compile(r'^ :copyright: Copyright 200\d(-20\d\d)? '
license_re = re.compile(r" :license: (.*?).\n")
copyright_2_re = re.compile(r'^ %s(, %s)*[,.]$' %
(name_mail_re, name_mail_re))
-not_ix_re = re.compile(r'\bnot\s+\S+?\s+i[sn]\s\S+')
-is_const_re = re.compile(r'if.*?==\s+(None|False|True)\b')
+not_ix_re = re.compile(r'\bnot\s+\S+?\s+i[sn]\s\S+')
+is_const_re = re.compile(r'if.*?==\s+(None|False|True)\b')
misspellings = ["developement", "adress", # ALLOW-MISSPELLING
"verificate", "informations"] # ALLOW-MISSPELLING
@@ -63,7 +63,7 @@ def decode_source(fn, lines):
decoded_lines.append(line.decode(encoding))
except UnicodeDecodeError as err:
raise UnicodeError("%s:%d: not decodable: %s\n Line: %r" %
- (fn, lno+1, err, line))
+ (fn, lno + 1, err, line))
except LookupError as err:
raise LookupError("unknown encoding: %s" % encoding)
return decoded_lines
@@ -82,14 +82,14 @@ def check_syntax(fn, lines):
def check_style(fn, lines):
for lno, line in enumerate(lines):
if len(line.rstrip('\n')) > 95:
- yield lno+1, "line too long"
+ yield lno + 1, "line too long"
if line.strip().startswith('#'):
continue
# m = not_ix_re.search(line)
# if m:
# yield lno+1, '"' + m.group() + '"'
if is_const_re.search(line):
- yield lno+1, 'using == None/True/False'
+ yield lno + 1, 'using == None/True/False'
@checker('.py', only_pkg=True)
@@ -116,11 +116,11 @@ def check_fileheader(fn, lines):
if l == '"""\n':
# end of docstring
if lno <= 4:
- yield lno+c, "missing module name in docstring"
+ yield lno + c, "missing module name in docstring"
break
if l != '\n' and l[:4] != ' ' and docopen:
- yield lno+c, "missing correct docstring indentation"
+ yield lno + c, "missing correct docstring indentation"
if lno == 2:
# if not in package, don't check the module name
@@ -145,10 +145,10 @@ def check_fileheader(fn, lines):
yield 0, "no correct license info"
ci = -3
- copyright = llist[ci:ci+1]
+ copyright = llist[ci:ci + 1]
while copyright and copyright_2_re.match(copyright[0]):
ci -= 1
- copyright = llist[ci:ci+1]
+ copyright = llist[ci:ci + 1]
if not copyright or not copyright_re.match(copyright[0]):
yield 0, "no correct copyright info"
@@ -157,12 +157,12 @@ def check_fileheader(fn, lines):
def check_whitespace_and_spelling(fn, lines):
for lno, line in enumerate(lines):
if '\t' in line:
- yield lno+1, "OMG TABS!!!1 "
+ yield lno + 1, "OMG TABS!!!1 "
if line[:-1].rstrip(' \t') != line[:-1]:
- yield lno+1, "trailing whitespace"
+ yield lno + 1, "trailing whitespace"
for word in misspellings:
if word in line and 'ALLOW-MISSPELLING' not in line:
- yield lno+1, '"%s" used' % word
+ yield lno + 1, '"%s" used' % word
bad_tags = ['', '', '', '', '= (3, 0):
else:
tokens = tokenize.tokenize
-verbose = 0
-recurse = 0
-dryrun = 0
+verbose = 0
+recurse = 0
+dryrun = 0
makebackup = True
@@ -160,7 +160,7 @@ def _rstrip(line, JUNK='\n \t'):
"""
i = len(line)
- while i > 0 and line[i-1] in JUNK:
+ while i > 0 and line[i - 1] in JUNK:
i -= 1
return line[:i]
@@ -204,9 +204,9 @@ class Reindenter:
# we see a line with *something* on it.
i = stats[0][0]
after.extend(lines[1:i])
- for i in range(len(stats)-1):
+ for i in range(len(stats) - 1):
thisstmt, thislevel = stats[i]
- nextstmt = stats[i+1][0]
+ nextstmt = stats[i + 1][0]
have = getlspace(lines[thisstmt])
want = thislevel * 4
if want < 0:
@@ -218,7 +218,7 @@ class Reindenter:
want = have2want.get(have, -1)
if want < 0:
# Then it probably belongs to the next real stmt.
- for j in range(i+1, len(stats)-1):
+ for j in range(i + 1, len(stats) - 1):
jline, jlevel = stats[j]
if jlevel >= 0:
if have == getlspace(lines[jline]):
@@ -228,10 +228,10 @@ class Reindenter:
# comment like this one,
# in which case we should shift it like its base
# line got shifted.
- for j in range(i-1, -1, -1):
+ for j in range(i - 1, -1, -1):
jline, jlevel = stats[j]
if jlevel >= 0:
- want = (have + getlspace(after[jline-1]) -
+ want = (have + getlspace(after[jline - 1]) -
getlspace(lines[jline]))
break
if want < 0:
|