Skip to content

Commit

Permalink
Merge pull request #9931 from tk0miya/9075_autodoc_unqualified_typehints
Browse files Browse the repository at this point in the history
Close #9075: autodoc: Add a config variable autodoc_unqualified_typehints
  • Loading branch information
tk0miya committed Dec 11, 2021
2 parents b5ee2d0 + c71ff1c commit d3162d1
Show file tree
Hide file tree
Showing 10 changed files with 405 additions and 118 deletions.
3 changes: 3 additions & 0 deletions CHANGES
Expand Up @@ -13,6 +13,9 @@ Deprecated
Features added
--------------

* #9075: autodoc: Add a config variable :confval:`autodoc_unqualified_typehints`
to suppress the leading module names of typehints of function signatures (ex.
``io.StringIO`` -> ``StringIO``)
* #9831: Autosummary now documents only the members specified in a module's
``__all__`` attribute if :confval:`autosummary_ignore_module_all` is set to
``False``. The default behaviour is unchanged. Autogen also now supports
Expand Down
7 changes: 7 additions & 0 deletions doc/usage/extensions/autodoc.rst
Expand Up @@ -662,6 +662,13 @@ There are also config values that you can set:
.. __: https://mypy.readthedocs.io/en/latest/kinds_of_types.html#type-aliases
.. versionadded:: 3.3

.. confval:: autodoc_unqualified_typehints

If True, the leading module names of typehints of function signatures (ex.

This comment has been minimized.

Copy link
@mara004

mara004 Dec 14, 2021

This phrase sounds a bit incomplete to me...

This comment has been minimized.

Copy link
@tk0miya

tk0miya Dec 14, 2021

Author Member

I'm not a native English speaker. So I can't modify this better. Could you update this please? @mara004

This comment has been minimized.

Copy link
@mara004

mara004 Dec 14, 2021

I'm not a native speaker either, but it just sounds like the ending of the phrase is missing.
I'd maybe write something like If True, the leading module names of typhints of function signatures are excluded or alternatively [...] are removed or [...] are cropped off.

This comment has been minimized.

Copy link
@tk0miya

tk0miya Dec 18, 2021

Author Member

Indeed. I'll update this soon. Thanks!

``io.StringIO`` -> ``StringIO``). Defaults to False.

.. versionadded:: 4.4

.. confval:: autodoc_preserve_defaults

If True, the default argument values of functions will be not evaluated on
Expand Down
24 changes: 19 additions & 5 deletions sphinx/domains/python.py
Expand Up @@ -80,7 +80,8 @@ class ModuleEntry(NamedTuple):
deprecated: bool


def type_to_xref(target: str, env: BuildEnvironment = None) -> addnodes.pending_xref:
def type_to_xref(target: str, env: BuildEnvironment = None, suppress_prefix: bool = False
) -> addnodes.pending_xref:
"""Convert a type string to a cross reference node."""
if target == 'None':
reftype = 'obj'
Expand All @@ -101,6 +102,8 @@ def type_to_xref(target: str, env: BuildEnvironment = None) -> addnodes.pending_
elif target.startswith('~'):
target = target[1:]
text = target.split('.')[-1]
elif suppress_prefix:
text = target.split('.')[-1]
else:
text = target

Expand Down Expand Up @@ -150,6 +153,8 @@ def unparse(node: ast.AST) -> List[Node]:
return unparse(node.value)
elif isinstance(node, ast.Index):
return unparse(node.value)
elif isinstance(node, ast.Invert):
return [addnodes.desc_sig_punctuation('', '~')]
elif isinstance(node, ast.List):
result = [addnodes.desc_sig_punctuation('', '[')]
if node.elts:
Expand Down Expand Up @@ -180,6 +185,8 @@ def unparse(node: ast.AST) -> List[Node]:
if isinstance(subnode, nodes.Text):
result[i] = nodes.literal('', '', subnode)
return result
elif isinstance(node, ast.UnaryOp):
return unparse(node.op) + unparse(node.operand)
elif isinstance(node, ast.Tuple):
if node.elts:
result = []
Expand Down Expand Up @@ -209,12 +216,19 @@ def unparse(node: ast.AST) -> List[Node]:

try:
tree = ast_parse(annotation)
result = unparse(tree)
for i, node in enumerate(result):
result: List[Node] = []
for node in unparse(tree):
if isinstance(node, nodes.literal):
result[i] = node[0]
result.append(node[0])
elif isinstance(node, nodes.Text) and node.strip():
result[i] = type_to_xref(str(node), env)
if (result and isinstance(result[-1], addnodes.desc_sig_punctuation) and
result[-1].astext() == '~'):
result.pop()
result.append(type_to_xref(str(node), env, suppress_prefix=True))
else:
result.append(type_to_xref(str(node), env))
else:
result.append(node)
return result
except SyntaxError:
return [type_to_xref(annotation, env)]
Expand Down
16 changes: 16 additions & 0 deletions sphinx/ext/autodoc/__init__.py
Expand Up @@ -1295,6 +1295,8 @@ def can_document_member(cls, member: Any, membername: str, isattr: bool, parent:
def format_args(self, **kwargs: Any) -> str:
if self.config.autodoc_typehints in ('none', 'description'):
kwargs.setdefault('show_annotation', False)
if self.config.autodoc_unqualified_typehints:
kwargs.setdefault('unqualified_typehints', True)

try:
self.env.app.emit('autodoc-before-process-signature', self.object, False)
Expand Down Expand Up @@ -1323,6 +1325,9 @@ def add_directive_header(self, sig: str) -> None:
self.add_line(' :async:', sourcename)

def format_signature(self, **kwargs: Any) -> str:
if self.config.autodoc_unqualified_typehints:
kwargs.setdefault('unqualified_typehints', True)

sigs = []
if (self.analyzer and
'.'.join(self.objpath) in self.analyzer.overloads and
Expand Down Expand Up @@ -1561,6 +1566,8 @@ def get_user_defined_function_or_method(obj: Any, attr: str) -> Any:
def format_args(self, **kwargs: Any) -> str:
if self.config.autodoc_typehints in ('none', 'description'):
kwargs.setdefault('show_annotation', False)
if self.config.autodoc_unqualified_typehints:
kwargs.setdefault('unqualified_typehints', True)

try:
self._signature_class, self._signature_method_name, sig = self._get_signature()
Expand All @@ -1582,6 +1589,9 @@ def format_signature(self, **kwargs: Any) -> str:
# do not show signatures
return ''

if self.config.autodoc_unqualified_typehints:
kwargs.setdefault('unqualified_typehints', True)

sig = super().format_signature()
sigs = []

Expand Down Expand Up @@ -2110,6 +2120,8 @@ def import_object(self, raiseerror: bool = False) -> bool:
def format_args(self, **kwargs: Any) -> str:
if self.config.autodoc_typehints in ('none', 'description'):
kwargs.setdefault('show_annotation', False)
if self.config.autodoc_unqualified_typehints:
kwargs.setdefault('unqualified_typehints', True)

try:
if self.object == object.__init__ and self.parent != object:
Expand Down Expand Up @@ -2160,6 +2172,9 @@ def document_members(self, all_members: bool = False) -> None:
pass

def format_signature(self, **kwargs: Any) -> str:
if self.config.autodoc_unqualified_typehints:
kwargs.setdefault('unqualified_typehints', True)

sigs = []
if (self.analyzer and
'.'.join(self.objpath) in self.analyzer.overloads and
Expand Down Expand Up @@ -2833,6 +2848,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('autodoc_typehints_description_target', 'all', True,
ENUM('all', 'documented'))
app.add_config_value('autodoc_type_aliases', {}, True)
app.add_config_value('autodoc_unqualified_typehints', False, 'env')
app.add_config_value('autodoc_warningiserror', True, True)
app.add_config_value('autodoc_inherit_docstrings', True, True)
app.add_event('autodoc-before-process-signature')
Expand Down
9 changes: 6 additions & 3 deletions sphinx/util/inspect.py
Expand Up @@ -744,10 +744,13 @@ def evaluate(annotation: Any, globalns: Dict, localns: Dict) -> Any:


def stringify_signature(sig: inspect.Signature, show_annotation: bool = True,
show_return_annotation: bool = True) -> str:
show_return_annotation: bool = True,
unqualified_typehints: bool = False) -> str:
"""Stringify a Signature object.
:param show_annotation: Show annotation in result
:param unqualified_typehints: Show annotations as unqualified
(ex. io.StringIO -> StringIO)
"""
args = []
last_kind = None
Expand All @@ -771,7 +774,7 @@ def stringify_signature(sig: inspect.Signature, show_annotation: bool = True,

if show_annotation and param.annotation is not param.empty:
arg.write(': ')
arg.write(stringify_annotation(param.annotation))
arg.write(stringify_annotation(param.annotation, unqualified_typehints))
if param.default is not param.empty:
if show_annotation and param.annotation is not param.empty:
arg.write(' = ')
Expand All @@ -791,7 +794,7 @@ def stringify_signature(sig: inspect.Signature, show_annotation: bool = True,
show_return_annotation is False):
return '(%s)' % ', '.join(args)
else:
annotation = stringify_annotation(sig.return_annotation)
annotation = stringify_annotation(sig.return_annotation, unqualified_typehints)
return '(%s) -> %s' % (', '.join(args), annotation)


Expand Down

0 comments on commit d3162d1

Please sign in to comment.