Skip to content

Commit c45bdf5

Browse files
committed
ENH: enable multiline signatures when too long.
1 parent cd3f2e4 commit c45bdf5

File tree

4 files changed

+35
-5
lines changed

4 files changed

+35
-5
lines changed

sphinx/addnodes.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ class desc_content(nodes.General, nodes.Element):
181181
"""
182182

183183

184+
class desc_compact_content(nodes.General, nodes.Element):
185+
"""Node for compact object description content.
186+
187+
Must be the last child node in a :py:class:`desc` node.
188+
"""
189+
190+
184191
class desc_inline(_desc_classes_injector, nodes.Inline, nodes.TextElement):
185192
"""Node for a signature fragment in inline text.
186193

sphinx/domains/python.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,21 +225,22 @@ def unparse(node: ast.AST) -> List[Node]:
225225

226226

227227
def _parse_arglist(
228-
arglist: str, env: Optional[BuildEnvironment] = None
228+
arglist: str, env: Optional[BuildEnvironment] = None, multiline=False
229229
) -> addnodes.desc_parameterlist:
230230
"""Parse a list of arguments using AST parser"""
231231
params = addnodes.desc_parameterlist(arglist)
232232
sig = signature_from_str('(%s)' % arglist)
233233
last_kind = None
234234
for param in sig.parameters.values():
235+
param_node = addnodes.desc_compact_content() if multiline else params
235236
if param.kind != param.POSITIONAL_ONLY and last_kind == param.POSITIONAL_ONLY:
236237
# PEP-570: Separator for Positional Only Parameter: /
237-
params += addnodes.desc_parameter('', '', addnodes.desc_sig_operator('', '/'))
238+
param_node += addnodes.desc_parameter('', '', addnodes.desc_sig_operator('', '/'))
238239
if param.kind == param.KEYWORD_ONLY and last_kind in (param.POSITIONAL_OR_KEYWORD,
239240
param.POSITIONAL_ONLY,
240241
None):
241242
# PEP-3102: Separator for Keyword Only Parameter: *
242-
params += addnodes.desc_parameter('', '', addnodes.desc_sig_operator('', '*'))
243+
param_node += addnodes.desc_parameter('', '', addnodes.desc_sig_operator('', '*'))
243244

244245
node = addnodes.desc_parameter()
245246
if param.kind == param.VAR_POSITIONAL:
@@ -266,7 +267,9 @@ def _parse_arglist(
266267
node += nodes.inline('', param.default, classes=['default_value'],
267268
support_smartquotes=False)
268269

269-
params += node
270+
param_node += node
271+
if multiline:
272+
params += param_node
270273
last_kind = param.kind
271274

272275
if last_kind == Parameter.POSITIONAL_ONLY:
@@ -412,6 +415,7 @@ class PyObject(ObjectDescription[Tuple[str, str]]):
412415
'noindex': directives.flag,
413416
'noindexentry': directives.flag,
414417
'nocontentsentry': directives.flag,
418+
'singlelinesig': directives.flag,
415419
'module': directives.unchanged,
416420
'canonical': directives.unchanged,
417421
'annotation': directives.unchanged,
@@ -493,6 +497,13 @@ def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]
493497
signode['module'] = modname
494498
signode['class'] = classname
495499
signode['fullname'] = fullname
500+
max_len = self.env.config.python_maximum_signature_line_length
501+
multiline = (
502+
max_len >= 0
503+
and 'singlelinesig' not in self.options
504+
and len(sig) > max_len
505+
)
506+
signode['is_multiline'] = multiline
496507

497508
sig_prefix = self.get_signature_prefix(sig)
498509
if sig_prefix:
@@ -513,7 +524,7 @@ def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]
513524
signode += addnodes.desc_name(name, name)
514525
if arglist:
515526
try:
516-
signode += _parse_arglist(arglist, self.env)
527+
signode += _parse_arglist(arglist, self.env, multiline=multiline)
517528
except SyntaxError:
518529
# fallback to parse arglist original parser.
519530
# it supports to represent optional arguments (ex. "func(foo [, bar])")
@@ -1470,6 +1481,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
14701481

14711482
app.add_domain(PythonDomain)
14721483
app.add_config_value('python_use_unqualified_type_names', False, 'env')
1484+
app.add_config_value('python_maximum_signature_line_length', -1, 'env')
14731485
app.connect('object-description-transform', filter_meta_fields)
14741486
app.connect('missing-reference', builtin_resolver, priority=900)
14751487

sphinx/themes/basic/static/basic.css_t

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,11 @@ dd {
670670
margin-left: 30px;
671671
}
672672

673+
dd.compact {
674+
margin-top: 0px;
675+
margin-bottom: 0px;
676+
}
677+
673678
dl > dd:last-child,
674679
dl > dd:last-child > :last-child {
675680
margin-bottom: 0;

sphinx/writers/html5.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ def visit_desc_content(self, node: Element) -> None:
112112
def depart_desc_content(self, node: Element) -> None:
113113
self.body.append('</dd>')
114114

115+
def visit_desc_compact_content(self, node: Element) -> None:
116+
self.body.append(self.starttag(node, 'dd', '', classes=['compact']))
117+
118+
def depart_desc_compact_content(self, node: Element) -> None:
119+
self.body.append('</dd>')
120+
115121
def visit_desc_inline(self, node: Element) -> None:
116122
self.body.append(self.starttag(node, 'span', ''))
117123

0 commit comments

Comments
 (0)