mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Allow configuration of trailing commas in multi-line signatures (#12975)
Stop outputting trailing commas for C and C++, as it is invalid syntax. Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com> Co-authored-by: Jakob Lykke Andersen <jakobandersen@users.noreply.github.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import pytest
|
||||
from sphinx._cli.util.errors import strip_escape_sequences
|
||||
from sphinx.builders.html import validate_html_extra_path, validate_html_static_path
|
||||
from sphinx.errors import ConfigError
|
||||
from sphinx.testing.util import etree_parse
|
||||
from sphinx.util.inventory import InventoryFile, _InventoryItem
|
||||
|
||||
from tests.test_builders.xpath_data import FIGURE_CAPTION
|
||||
@@ -657,3 +658,60 @@ def test_html_pep_695_one_type_per_line(app, cached_etree_parse):
|
||||
r'.//dt[@id="MyList"][1]',
|
||||
chk('class MyList[\nT,\n](list[T])'),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'html',
|
||||
testroot='domain-py-python_maximum_signature_line_length',
|
||||
confoverrides={
|
||||
'python_maximum_signature_line_length': 1,
|
||||
'python_trailing_comma_in_multi_line_signatures': False,
|
||||
},
|
||||
)
|
||||
def test_html_pep_695_trailing_comma_in_multi_line_signatures(app):
|
||||
app.build()
|
||||
fname = app.outdir / 'index.html'
|
||||
etree = etree_parse(fname)
|
||||
|
||||
class chk:
|
||||
def __init__(self, expect: str) -> None:
|
||||
self.expect = expect
|
||||
|
||||
def __call__(self, nodes):
|
||||
assert len(nodes) == 1, nodes
|
||||
objnode = ''.join(nodes[0].itertext()).replace('\n\n', '')
|
||||
objnode = objnode.rstrip(chr(182)) # remove '¶' symbol
|
||||
objnode = objnode.strip('\n') # remove surrounding new lines
|
||||
assert objnode == self.expect
|
||||
|
||||
# each signature has a dangling ',' at the end of its parameters lists
|
||||
check_xpath(
|
||||
etree,
|
||||
fname,
|
||||
r'.//dt[@id="generic_foo"][1]',
|
||||
chk('generic_foo[\nT\n]()'),
|
||||
)
|
||||
check_xpath(
|
||||
etree,
|
||||
fname,
|
||||
r'.//dt[@id="generic_bar"][1]',
|
||||
chk('generic_bar[\nT\n](\nx: list[T]\n)'),
|
||||
)
|
||||
check_xpath(
|
||||
etree,
|
||||
fname,
|
||||
r'.//dt[@id="generic_ret"][1]',
|
||||
chk('generic_ret[\nR\n]() → R'),
|
||||
)
|
||||
check_xpath(
|
||||
etree,
|
||||
fname,
|
||||
r'.//dt[@id="MyGenericClass"][1]',
|
||||
chk('class MyGenericClass[\nX\n]'),
|
||||
)
|
||||
check_xpath(
|
||||
etree,
|
||||
fname,
|
||||
r'.//dt[@id="MyList"][1]',
|
||||
chk('class MyList[\nT\n](list[T])'),
|
||||
)
|
||||
|
@@ -2214,7 +2214,6 @@ def test_one_parameter_per_line(app):
|
||||
app.build(force_all=True)
|
||||
result = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8')
|
||||
|
||||
# TODO: should these asserts check presence or absence of a final \sphinxparamcomma?
|
||||
# signature of 23 characters is too short to trigger one-param-per-line mark-up
|
||||
assert (
|
||||
'\\pysiglinewithargsret\n'
|
||||
@@ -2227,6 +2226,7 @@ def test_one_parameter_per_line(app):
|
||||
'{\\sphinxbfcode{\\sphinxupquote{foo}}}\n'
|
||||
'{\\sphinxoptional{\\sphinxparam{' in result
|
||||
)
|
||||
assert r'\sphinxparam{\DUrole{n}{f}}\sphinxparamcomma' in result
|
||||
|
||||
# generic_arg[T]
|
||||
assert (
|
||||
@@ -2283,6 +2283,22 @@ def test_one_parameter_per_line(app):
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'latex',
|
||||
testroot='domain-py-python_maximum_signature_line_length',
|
||||
confoverrides={
|
||||
'python_maximum_signature_line_length': 23,
|
||||
'python_trailing_comma_in_multi_line_signatures': False,
|
||||
},
|
||||
)
|
||||
def test_one_parameter_per_line_without_trailing_comma(app):
|
||||
app.build(force_all=True)
|
||||
result = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8')
|
||||
|
||||
assert r'\sphinxparam{\DUrole{n}{f}}\sphinxparamcomma' not in result
|
||||
assert r'\sphinxparam{\DUrole{n}{f}}}}' in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='markup-rubric')
|
||||
def test_latex_rubric(app):
|
||||
app.build()
|
||||
|
@@ -1374,7 +1374,7 @@ def test_domain_c_c_maximum_signature_line_length_in_html(app):
|
||||
<dd>\
|
||||
<span class="n"><span class="pre">str</span></span>\
|
||||
<span class="w"> </span>\
|
||||
<span class="n"><span class="pre">name</span></span>,\
|
||||
<span class="n"><span class="pre">name</span></span>\
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
@@ -1395,6 +1395,6 @@ def test_domain_c_c_maximum_signature_line_length_in_text(app):
|
||||
content = (app.outdir / 'index.txt').read_text(encoding='utf8')
|
||||
param_line_fmt = STDINDENT * ' ' + '{}\n'
|
||||
|
||||
expected_parameter_list_hello = '(\n{})'.format(param_line_fmt.format('str name,'))
|
||||
expected_parameter_list_hello = '(\n{})'.format(param_line_fmt.format('str name'))
|
||||
|
||||
assert expected_parameter_list_hello in content
|
||||
|
@@ -2426,7 +2426,7 @@ def test_domain_cpp_cpp_maximum_signature_line_length_in_html(app):
|
||||
<dd>\
|
||||
<span class="n"><span class="pre">str</span></span>\
|
||||
<span class="w"> </span>\
|
||||
<span class="n sig-param"><span class="pre">name</span></span>,\
|
||||
<span class="n sig-param"><span class="pre">name</span></span>\
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
@@ -2445,6 +2445,6 @@ def test_domain_cpp_cpp_maximum_signature_line_length_in_text(app):
|
||||
content = (app.outdir / 'index.txt').read_text(encoding='utf8')
|
||||
param_line_fmt = STDINDENT * ' ' + '{}\n'
|
||||
|
||||
expected_parameter_list_hello = '(\n{})'.format(param_line_fmt.format('str name,'))
|
||||
expected_parameter_list_hello = '(\n{})'.format(param_line_fmt.format('str name'))
|
||||
|
||||
assert expected_parameter_list_hello in content
|
||||
|
@@ -755,3 +755,121 @@ def test_domain_js_javascript_maximum_signature_line_length_in_text(app):
|
||||
expected_f,
|
||||
)
|
||||
assert expected_parameter_list_foo in content
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'html',
|
||||
testroot='domain-js-javascript_maximum_signature_line_length',
|
||||
confoverrides={'javascript_trailing_comma_in_multi_line_signatures': False},
|
||||
)
|
||||
def test_domain_js_javascript_trailing_comma_in_multi_line_signatures_in_html(app):
|
||||
app.build()
|
||||
content = (app.outdir / 'index.html').read_text(encoding='utf8')
|
||||
expected_parameter_list_hello = """\
|
||||
|
||||
<dl>
|
||||
<dd>\
|
||||
<em class="sig-param">\
|
||||
<span class="n"><span class="pre">name</span></span>\
|
||||
</em>\
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<span class="sig-paren">)</span>\
|
||||
<a class="headerlink" href="#hello" title="Link to this definition">¶</a>\
|
||||
</dt>\
|
||||
"""
|
||||
assert expected_parameter_list_hello in content
|
||||
|
||||
param_line_fmt = '<dd>{}</dd>\n'
|
||||
param_name_fmt = (
|
||||
'<em class="sig-param"><span class="n"><span class="pre">{}</span></span></em>'
|
||||
)
|
||||
optional_fmt = '<span class="optional">{}</span>'
|
||||
|
||||
expected_a = param_line_fmt.format(
|
||||
optional_fmt.format('[')
|
||||
+ param_name_fmt.format('a')
|
||||
+ ','
|
||||
+ optional_fmt.format('['),
|
||||
)
|
||||
assert expected_a in content
|
||||
|
||||
expected_b = param_line_fmt.format(
|
||||
param_name_fmt.format('b')
|
||||
+ ','
|
||||
+ optional_fmt.format(']')
|
||||
+ optional_fmt.format(']'),
|
||||
)
|
||||
assert expected_b in content
|
||||
|
||||
expected_c = param_line_fmt.format(param_name_fmt.format('c') + ',')
|
||||
assert expected_c in content
|
||||
|
||||
expected_d = param_line_fmt.format(
|
||||
param_name_fmt.format('d') + optional_fmt.format('[') + ','
|
||||
)
|
||||
assert expected_d in content
|
||||
|
||||
expected_e = param_line_fmt.format(param_name_fmt.format('e') + ',')
|
||||
assert expected_e in content
|
||||
|
||||
expected_f = param_line_fmt.format(
|
||||
param_name_fmt.format('f') + optional_fmt.format(']')
|
||||
)
|
||||
assert expected_f in content
|
||||
|
||||
expected_parameter_list_foo = """\
|
||||
|
||||
<dl>
|
||||
{}{}{}{}{}{}</dl>
|
||||
|
||||
<span class="sig-paren">)</span>\
|
||||
<a class="headerlink" href="#foo" title="Link to this definition">¶</a>\
|
||||
</dt>\
|
||||
""".format(expected_a, expected_b, expected_c, expected_d, expected_e, expected_f)
|
||||
assert expected_parameter_list_foo in content
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'text',
|
||||
testroot='domain-js-javascript_maximum_signature_line_length',
|
||||
freshenv=True,
|
||||
confoverrides={'javascript_trailing_comma_in_multi_line_signatures': False},
|
||||
)
|
||||
def test_domain_js_javascript_trailing_comma_in_multi_line_signatures_in_text(app):
|
||||
app.build()
|
||||
content = (app.outdir / 'index.txt').read_text(encoding='utf8')
|
||||
param_line_fmt = STDINDENT * ' ' + '{}\n'
|
||||
|
||||
expected_parameter_list_hello = '(\n{})'.format(param_line_fmt.format('name'))
|
||||
|
||||
assert expected_parameter_list_hello in content
|
||||
|
||||
expected_a = param_line_fmt.format('[a,[')
|
||||
assert expected_a in content
|
||||
|
||||
expected_b = param_line_fmt.format('b,]]')
|
||||
assert expected_b in content
|
||||
|
||||
expected_c = param_line_fmt.format('c,')
|
||||
assert expected_c in content
|
||||
|
||||
expected_d = param_line_fmt.format('d[,')
|
||||
assert expected_d in content
|
||||
|
||||
expected_e = param_line_fmt.format('e,')
|
||||
assert expected_e in content
|
||||
|
||||
expected_f = param_line_fmt.format('f]')
|
||||
assert expected_f in content
|
||||
|
||||
expected_parameter_list_foo = '(\n{}{}{}{}{}{})'.format(
|
||||
expected_a,
|
||||
expected_b,
|
||||
expected_c,
|
||||
expected_d,
|
||||
expected_e,
|
||||
expected_f,
|
||||
)
|
||||
assert expected_parameter_list_foo in content
|
||||
|
@@ -1073,6 +1073,133 @@ def test_domain_py_python_maximum_signature_line_length_in_text(app):
|
||||
assert expected_parameter_list_foo in content
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'html',
|
||||
testroot='domain-py-python_maximum_signature_line_length',
|
||||
confoverrides={'python_trailing_comma_in_multi_line_signatures': False},
|
||||
)
|
||||
def test_domain_py_python_trailing_comma_in_multi_line_signatures_in_html(app):
|
||||
app.build()
|
||||
content = (app.outdir / 'index.html').read_text(encoding='utf8')
|
||||
expected_parameter_list_hello = """\
|
||||
|
||||
<dl>
|
||||
<dd>\
|
||||
<em class="sig-param">\
|
||||
<span class="n"><span class="pre">name</span></span>\
|
||||
<span class="p"><span class="pre">:</span></span>\
|
||||
<span class="w"> </span>\
|
||||
<span class="n"><span class="pre">str</span></span>\
|
||||
</em>\
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<span class="sig-paren">)</span> \
|
||||
<span class="sig-return">\
|
||||
<span class="sig-return-icon">→</span> \
|
||||
<span class="sig-return-typehint"><span class="pre">str</span></span>\
|
||||
</span>\
|
||||
<a class="headerlink" href="#hello" title="Link to this definition">¶</a>\
|
||||
</dt>\
|
||||
"""
|
||||
assert expected_parameter_list_hello in content
|
||||
|
||||
param_line_fmt = '<dd>{}</dd>\n'
|
||||
param_name_fmt = (
|
||||
'<em class="sig-param"><span class="n"><span class="pre">{}</span></span></em>'
|
||||
)
|
||||
optional_fmt = '<span class="optional">{}</span>'
|
||||
|
||||
expected_a = param_line_fmt.format(
|
||||
optional_fmt.format('[')
|
||||
+ param_name_fmt.format('a')
|
||||
+ ','
|
||||
+ optional_fmt.format('['),
|
||||
)
|
||||
assert expected_a in content
|
||||
|
||||
expected_b = param_line_fmt.format(
|
||||
param_name_fmt.format('b')
|
||||
+ ','
|
||||
+ optional_fmt.format(']')
|
||||
+ optional_fmt.format(']'),
|
||||
)
|
||||
assert expected_b in content
|
||||
|
||||
expected_c = param_line_fmt.format(param_name_fmt.format('c') + ',')
|
||||
assert expected_c in content
|
||||
|
||||
expected_d = param_line_fmt.format(
|
||||
param_name_fmt.format('d') + optional_fmt.format('[') + ','
|
||||
)
|
||||
assert expected_d in content
|
||||
|
||||
expected_e = param_line_fmt.format(param_name_fmt.format('e') + ',')
|
||||
assert expected_e in content
|
||||
|
||||
expected_f = param_line_fmt.format(
|
||||
param_name_fmt.format('f') + optional_fmt.format(']')
|
||||
)
|
||||
assert expected_f in content
|
||||
|
||||
expected_parameter_list_foo = """\
|
||||
|
||||
<dl>
|
||||
{}{}{}{}{}{}</dl>
|
||||
|
||||
<span class="sig-paren">)</span>\
|
||||
<a class="headerlink" href="#foo" title="Link to this definition">¶</a>\
|
||||
</dt>\
|
||||
""".format(expected_a, expected_b, expected_c, expected_d, expected_e, expected_f)
|
||||
assert expected_parameter_list_foo in content
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'text',
|
||||
testroot='domain-py-python_maximum_signature_line_length',
|
||||
freshenv=True,
|
||||
confoverrides={'python_trailing_comma_in_multi_line_signatures': False},
|
||||
)
|
||||
def test_domain_py_python_trailing_comma_in_multi_line_signatures_in_text(app):
|
||||
app.build()
|
||||
content = (app.outdir / 'index.txt').read_text(encoding='utf8')
|
||||
param_line_fmt = STDINDENT * ' ' + '{}\n'
|
||||
|
||||
expected_parameter_list_hello = '(\n{}) -> str'.format(
|
||||
param_line_fmt.format('name: str')
|
||||
)
|
||||
|
||||
assert expected_parameter_list_hello in content
|
||||
|
||||
expected_a = param_line_fmt.format('[a,[')
|
||||
assert expected_a in content
|
||||
|
||||
expected_b = param_line_fmt.format('b,]]')
|
||||
assert expected_b in content
|
||||
|
||||
expected_c = param_line_fmt.format('c,')
|
||||
assert expected_c in content
|
||||
|
||||
expected_d = param_line_fmt.format('d[,')
|
||||
assert expected_d in content
|
||||
|
||||
expected_e = param_line_fmt.format('e,')
|
||||
assert expected_e in content
|
||||
|
||||
expected_f = param_line_fmt.format('f]')
|
||||
assert expected_f in content
|
||||
|
||||
expected_parameter_list_foo = '(\n{}{}{}{}{}{})'.format(
|
||||
expected_a,
|
||||
expected_b,
|
||||
expected_c,
|
||||
expected_d,
|
||||
expected_e,
|
||||
expected_f,
|
||||
)
|
||||
assert expected_parameter_list_foo in content
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='root')
|
||||
def test_module_content_line_number(app):
|
||||
text = '.. py:module:: foo\n\n Some link here: :ref:`abc`\n'
|
||||
|
Reference in New Issue
Block a user