Skip to content

Commit

Permalink
py domain: Allow to make a style for arguments of functions and metho…
Browse files Browse the repository at this point in the history
…ds (refs: sphinx-doc#6417)
  • Loading branch information
tk0miya committed Feb 22, 2020
1 parent c4d7f4d commit 19feb1b
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 33 deletions.
3 changes: 3 additions & 0 deletions CHANGES
Expand Up @@ -19,6 +19,8 @@ Incompatible changes
when ``:inherited-members:`` and ``:special-members:`` are given.
* #6830: py domain: ``meta`` fields in info-field-list becomes reserved. They
are not displayed on output document now
* #6417: py domain: doctree of desc_parameterlist has been changed. The
argument names, annotations and default values are wrapped with inline node
* The structure of ``sphinx.events.EventManager.listeners`` has changed
* Due to the scoping changes for :rst:dir:`productionlist` some uses of
:rst:role:`token` must be modified to include the scope which was previously
Expand All @@ -44,6 +46,7 @@ Features added
* #6558: glossary: emit a warning for duplicated glossary entry
* #6558: std domain: emit a warning for duplicated generic objects
* #6830: py domain: Add new event: :event:`object-description-transform`
* #6417: py domain: Allow to make a style for arguments of functions and methods
* Support priority of event handlers. For more detail, see
:py:meth:`.Sphinx.connect()`
* #3077: Implement the scoping for :rst:dir:`productionlist` as indicated
Expand Down
22 changes: 13 additions & 9 deletions sphinx/domains/python.py
Expand Up @@ -72,35 +72,39 @@ def _parse_arglist(arglist: str) -> addnodes.desc_parameterlist:
for param in sig.parameters.values():
if param.kind != param.POSITIONAL_ONLY and last_kind == param.POSITIONAL_ONLY:
# PEP-570: Separator for Positional Only Parameter: /
params += nodes.Text('/')
params += nodes.inline('', '/', classes=['operator'])
if param.kind == param.KEYWORD_ONLY and last_kind in (param.POSITIONAL_OR_KEYWORD,
param.POSITIONAL_ONLY,
None):
# PEP-3102: Separator for Keyword Only Parameter: *
params += nodes.Text('*')
params += nodes.inline('', '*', classes=['operator'])

node = addnodes.desc_parameter()
if param.kind == param.VAR_POSITIONAL:
node += nodes.Text('*' + param.name)
node += nodes.inline('', '*', classes=['operator'])
node += nodes.inline('', param.name, classes=['name'])
elif param.kind == param.VAR_KEYWORD:
node += nodes.Text('**' + param.name)
node += nodes.inline('', '**', classes=['operator'])
node += nodes.inline('', param.name, classes=['name'])
else:
node += nodes.Text(param.name)
node += nodes.inline('', param.name, classes=['name'])

if param.annotation is not param.empty:
node += nodes.Text(': ' + param.annotation)
node += nodes.inline('', ': ', classes=['operator'])
node += nodes.inline('', param.annotation, classes=['annotation'])
if param.default is not param.empty:
if param.annotation is not param.empty:
node += nodes.Text(' = ' + str(param.default))
node += nodes.inline('', ' = ', classes=['operator'])
else:
node += nodes.Text('=' + str(param.default))
node += nodes.inline('', '=', classes=['operator'])
node += nodes.inline('', param.default, classes=['default_value'])

params += node
last_kind = param.kind

if last_kind == Parameter.POSITIONAL_ONLY:
# PEP-570: Separator for Positional Only Parameter: /
params += nodes.Text('/')
params += nodes.inline('', '/', classes=['operator'])

return params

Expand Down
59 changes: 35 additions & 24 deletions tests/test_domain_py.py
Expand Up @@ -243,8 +243,9 @@ def test_pyfunction_signature(app):
assert_node(doctree[1], addnodes.desc, desctype="function",
domain="py", objtype="function", noindex=False)
assert_node(doctree[1][0][1],
[desc_parameterlist, desc_parameter, ("name",
": str")])
[desc_parameterlist, desc_parameter, ([nodes.inline, "name"],
[nodes.inline, ": "],
[nodes.inline, "str"])])


def test_pyfunction_signature_full(app):
Expand All @@ -259,17 +260,25 @@ def test_pyfunction_signature_full(app):
assert_node(doctree[1], addnodes.desc, desctype="function",
domain="py", objtype="function", noindex=False)
assert_node(doctree[1][0][1],
[desc_parameterlist, ([desc_parameter, ("a",
": str")],
[desc_parameter, ("b",
"=1")],
[desc_parameter, ("*args",
": str")],
[desc_parameter, ("c",
": bool",
" = True")],
[desc_parameter, ("**kwargs",
": str")])])
[desc_parameterlist, ([desc_parameter, ([nodes.inline, "a"],
[nodes.inline, ": "],
[nodes.inline, "str"])],
[desc_parameter, ([nodes.inline, "b"],
[nodes.inline, "="],
[nodes.inline, "1"])],
[desc_parameter, ([nodes.inline, "*"],
[nodes.inline, "args"],
[nodes.inline, ": "],
[nodes.inline, "str"])],
[desc_parameter, ([nodes.inline, "c"],
[nodes.inline, ": "],
[nodes.inline, "bool"],
[nodes.inline, " = "],
[nodes.inline, "True"])],
[desc_parameter, ([nodes.inline, "**"],
[nodes.inline, "kwargs"],
[nodes.inline, ": "],
[nodes.inline, "str"])])])


@pytest.mark.skipif(sys.version_info < (3, 8), reason='python 3.8+ is required.')
Expand All @@ -278,20 +287,22 @@ def test_pyfunction_signature_full_py38(app):
text = ".. py:function:: hello(*, a)"
doctree = restructuredtext.parse(app, text)
assert_node(doctree[1][0][1],
[desc_parameterlist, ("*",
[desc_parameter, ("a",
"=None")])])
[desc_parameterlist, ([nodes.inline, "*"],
[desc_parameter, ([nodes.inline, "a"],
[nodes.inline, "="],
[nodes.inline, "None"])])])

# case: separator in the middle
text = ".. py:function:: hello(a, /, b, *, c)"
doctree = restructuredtext.parse(app, text)
assert_node(doctree[1][0][1],
[desc_parameterlist, ([desc_parameter, "a"],
"/",
[desc_parameter, "b"],
"*",
[desc_parameter, ("c",
"=None")])])
[desc_parameterlist, ([desc_parameter, nodes.inline, "a"],
[nodes.inline, "/"],
[desc_parameter, nodes.inline, "b"],
[nodes.inline, "*"],
[desc_parameter, ([nodes.inline, "c"],
[nodes.inline, "="],
[nodes.inline, "None"])])])

# case: separator in the middle (2)
text = ".. py:function:: hello(a, /, *, b)"
Expand All @@ -307,8 +318,8 @@ def test_pyfunction_signature_full_py38(app):
text = ".. py:function:: hello(a, /)"
doctree = restructuredtext.parse(app, text)
assert_node(doctree[1][0][1],
[desc_parameterlist, ([desc_parameter, "a"],
"/")])
[desc_parameterlist, ([desc_parameter, nodes.inline, "a"],
[nodes.inline, "/"])])


def test_optional_pyfunction_signature(app):
Expand Down

0 comments on commit 19feb1b

Please sign in to comment.