Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Py, use more desc_sig_* nodes #9672

Merged
merged 22 commits into from Oct 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGES
Expand Up @@ -9,6 +9,12 @@ Incompatible changes

* #9649: ``searchindex.js``: the embedded data has changed format to allow
objects with the same name in different domains.
* #9672: The rendering of Python domain declarations is implemented
with more docutils nodes to allow better CSS styling.
It may break existing styling.
* #9672: the signature of
:py:meth:`domains.py.PyObject.get_signature_prefix` has changed to
return a list of nodes instead of a plain string.

Deprecated
----------
Expand All @@ -22,6 +28,7 @@ Features added
* #9691: C, added new info-field ``retval``
for :rst:dir:`c:function` and :rst:dir:`c:macro`.
* C++, added new info-field ``retval`` for :rst:dir:`cpp:function`.
* #9672: More CSS classes on Python domain descriptions

Bugs fixed
----------
Expand Down
119 changes: 79 additions & 40 deletions sphinx/domains/python.py
Expand Up @@ -118,11 +118,21 @@ def unparse(node: ast.AST) -> List[Node]:
result.extend(unparse(node.right))
return result
elif isinstance(node, ast.BitOr):
return [nodes.Text(' '), addnodes.desc_sig_punctuation('', '|'), nodes.Text(' ')]
return [addnodes.desc_sig_space(),
addnodes.desc_sig_punctuation('', '|'),
addnodes.desc_sig_space()]
elif isinstance(node, ast.Constant): # type: ignore
if node.value is Ellipsis:
return [addnodes.desc_sig_punctuation('', "...")]
elif isinstance(node.value, bool):
return [addnodes.desc_sig_keyword('', repr(node.value))]
elif isinstance(node.value, int):
return [addnodes.desc_sig_literal_number('', repr(node.value))]
elif isinstance(node.value, str):
return [addnodes.desc_sig_literal_string('', repr(node.value))]
else:
# handles None, which is further handled by type_to_xref later
# and fallback for other types that should be converted
return [nodes.Text(repr(node.value))]
elif isinstance(node, ast.Expr):
return unparse(node.value)
Expand All @@ -136,7 +146,9 @@ def unparse(node: ast.AST) -> List[Node]:
# once
for elem in node.elts:
result.extend(unparse(elem))
result.append(addnodes.desc_sig_punctuation('', ', '))
result.append(addnodes.desc_sig_punctuation('', ','))
result.append(addnodes.desc_sig_space())
result.pop()
result.pop()
result.append(addnodes.desc_sig_punctuation('', ']'))
return result
Expand All @@ -161,7 +173,9 @@ def unparse(node: ast.AST) -> List[Node]:
result = []
for elem in node.elts:
result.extend(unparse(elem))
result.append(addnodes.desc_sig_punctuation('', ', '))
result.append(addnodes.desc_sig_punctuation('', ','))
result.append(addnodes.desc_sig_space())
result.pop()
result.pop()
else:
result = [addnodes.desc_sig_punctuation('', '('),
Expand Down Expand Up @@ -222,13 +236,13 @@ def _parse_arglist(arglist: str, env: BuildEnvironment = None) -> addnodes.desc_
if param.annotation is not param.empty:
children = _parse_annotation(param.annotation, env)
node += addnodes.desc_sig_punctuation('', ':')
node += nodes.Text(' ')
node += addnodes.desc_sig_space()
node += addnodes.desc_sig_name('', '', *children) # type: ignore
if param.default is not param.empty:
if param.annotation is not param.empty:
node += nodes.Text(' ')
node += addnodes.desc_sig_space()
node += addnodes.desc_sig_operator('', '=')
node += nodes.Text(' ')
node += addnodes.desc_sig_space()
else:
node += addnodes.desc_sig_operator('', '=')
node += nodes.inline('', param.default, classes=['default_value'],
Expand Down Expand Up @@ -418,11 +432,11 @@ class PyObject(ObjectDescription[Tuple[str, str]]):

allow_nesting = False

def get_signature_prefix(self, sig: str) -> str:
def get_signature_prefix(self, sig: str) -> List[nodes.Node]:
tk0miya marked this conversation as resolved.
Show resolved Hide resolved
"""May return a prefix to put before the object name in the
signature.
"""
return ''
return []

def needs_arglist(self) -> bool:
"""May return true if an empty argument list is to be generated even if
Expand Down Expand Up @@ -476,7 +490,7 @@ def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]

sig_prefix = self.get_signature_prefix(sig)
if sig_prefix:
signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
signode += addnodes.desc_annotation(str(sig_prefix), '', *sig_prefix)

if prefix:
signode += addnodes.desc_addname(prefix, prefix)
Expand Down Expand Up @@ -507,7 +521,9 @@ def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]

anno = self.options.get('annotation')
if anno:
signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
signode += addnodes.desc_annotation(' ' + anno, '',
addnodes.desc_sig_space(),
nodes.Text(anno))

return fullname, prefix

Expand Down Expand Up @@ -609,11 +625,12 @@ class PyFunction(PyObject):
'async': directives.flag,
})

def get_signature_prefix(self, sig: str) -> str:
def get_signature_prefix(self, sig: str) -> List[nodes.Node]:
if 'async' in self.options:
return 'async '
return [addnodes.desc_sig_keyword('', 'async'),
addnodes.desc_sig_space()]
else:
return ''
return []

def needs_arglist(self) -> bool:
return True
Expand Down Expand Up @@ -670,11 +687,17 @@ def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]
typ = self.options.get('type')
if typ:
annotations = _parse_annotation(typ, self.env)
signode += addnodes.desc_annotation(typ, '', nodes.Text(': '), *annotations)
signode += addnodes.desc_annotation(typ, '',
addnodes.desc_sig_punctuation('', ':'),
addnodes.desc_sig_space(), *annotations)

value = self.options.get('value')
if value:
signode += addnodes.desc_annotation(value, ' = ' + value)
signode += addnodes.desc_annotation(value, '',
addnodes.desc_sig_space(),
addnodes.desc_sig_punctuation('', '='),
addnodes.desc_sig_space(),
nodes.Text(value))

return fullname, prefix

Expand All @@ -698,11 +721,12 @@ class PyClasslike(PyObject):

allow_nesting = True

def get_signature_prefix(self, sig: str) -> str:
def get_signature_prefix(self, sig: str) -> List[nodes.Node]:
if 'final' in self.options:
return 'final %s ' % self.objtype
return [nodes.Text('final'), addnodes.desc_sig_space(),
nodes.Text(self.objtype), addnodes.desc_sig_space()]
else:
return '%s ' % self.objtype
return [nodes.Text(self.objtype), addnodes.desc_sig_space()]

def get_index_text(self, modname: str, name_cls: Tuple[str, str]) -> str:
if self.objtype == 'class':
Expand Down Expand Up @@ -734,25 +758,27 @@ def needs_arglist(self) -> bool:
else:
return True

def get_signature_prefix(self, sig: str) -> str:
prefix = []
def get_signature_prefix(self, sig: str) -> List[nodes.Node]:
prefix: List[nodes.Node] = []
if 'final' in self.options:
prefix.append('final')
prefix.append(nodes.Text('final'))
prefix.append(addnodes.desc_sig_space())
if 'abstractmethod' in self.options:
prefix.append('abstract')
prefix.append(nodes.Text('abstract'))
prefix.append(addnodes.desc_sig_space())
if 'async' in self.options:
prefix.append('async')
prefix.append(nodes.Text('async'))
prefix.append(addnodes.desc_sig_space())
if 'classmethod' in self.options:
prefix.append('classmethod')
prefix.append(nodes.Text('classmethod'))
prefix.append(addnodes.desc_sig_space())
if 'property' in self.options:
prefix.append('property')
prefix.append(nodes.Text('property'))
prefix.append(addnodes.desc_sig_space())
if 'staticmethod' in self.options:
prefix.append('static')

if prefix:
return ' '.join(prefix) + ' '
else:
return ''
prefix.append(nodes.Text('static'))
prefix.append(addnodes.desc_sig_space())
return prefix

def get_index_text(self, modname: str, name_cls: Tuple[str, str]) -> str:
name, cls = name_cls
Expand Down Expand Up @@ -831,11 +857,18 @@ def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]
typ = self.options.get('type')
if typ:
annotations = _parse_annotation(typ, self.env)
signode += addnodes.desc_annotation(typ, '', nodes.Text(': '), *annotations)
signode += addnodes.desc_annotation(typ, '',
addnodes.desc_sig_punctuation('', ':'),
addnodes.desc_sig_space(),
*annotations)

value = self.options.get('value')
if value:
signode += addnodes.desc_annotation(value, ' = ' + value)
signode += addnodes.desc_annotation(value, '',
addnodes.desc_sig_space(),
addnodes.desc_sig_punctuation('', '='),
addnodes.desc_sig_space(),
nodes.Text(value))

return fullname, prefix

Expand Down Expand Up @@ -870,19 +903,25 @@ def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]
typ = self.options.get('type')
if typ:
annotations = _parse_annotation(typ, self.env)
signode += addnodes.desc_annotation(typ, '', nodes.Text(': '), *annotations)
signode += addnodes.desc_annotation(typ, '',
addnodes.desc_sig_punctuation('', ':'),
addnodes.desc_sig_space(),
*annotations)

return fullname, prefix

def get_signature_prefix(self, sig: str) -> str:
prefix = []
def get_signature_prefix(self, sig: str) -> List[nodes.Node]:
prefix: List[nodes.Node] = []
if 'abstractmethod' in self.options:
prefix.append('abstract')
prefix.append(nodes.Text('abstract'))
prefix.append(addnodes.desc_sig_space())
if 'classmethod' in self.options:
prefix.append('class')
prefix.append(nodes.Text('class'))
prefix.append(addnodes.desc_sig_space())

prefix.append('property')
return ' '.join(prefix) + ' '
prefix.append(nodes.Text('property'))
prefix.append(addnodes.desc_sig_space())
return prefix

def get_index_text(self, modname: str, name_cls: Tuple[str, str]) -> str:
name, cls = name_cls
Expand Down