Skip to content

Commit

Permalink
Merge pull request #9672 from jakobandersen/py_nodes
Browse files Browse the repository at this point in the history
Py, use more desc_sig_* nodes
  • Loading branch information
jakobandersen committed Oct 3, 2021
2 parents 9922923 + 9c16825 commit ebea432
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 105 deletions.
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]:
"""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

0 comments on commit ebea432

Please sign in to comment.