Skip to content

Commit f0fe33d

Browse files
committed
WIP configurable formatter
1 parent 1b85ff5 commit f0fe33d

File tree

1 file changed

+29
-16
lines changed

1 file changed

+29
-16
lines changed

sphinx_autodoc_typehints.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import sys
33
import textwrap
44
import typing
5-
from typing import Any, AnyStr, Tuple, TypeVar, get_type_hints
5+
from functools import partial
6+
from typing import Any, AnyStr, Callable, Tuple, TypeVar, get_type_hints
67

78
from sphinx.util import logging
89
from sphinx.util.inspect import signature as Signature
@@ -84,9 +85,16 @@ def get_annotation_args(annotation, module: str, class_name: str) -> Tuple:
8485
return getattr(annotation, '__args__', ())
8586

8687

87-
def format_annotation(annotation,
88+
def format_annotation(annotation: Any,
8889
fully_qualified: bool = False,
89-
simplify_optional_unions: bool = True) -> str:
90+
simplify_optional_unions: bool = True,
91+
typehints_formatter: Callable = lambda _annotation, **_opts: None) -> str:
92+
# all options except for the formatter:
93+
opts = dict(fully_qualified=fully_qualified, simplify_optional_unions=simplify_optional_unions)
94+
formatted = typehints_formatter(annotation, **opts)
95+
if formatted is not None:
96+
return formatted
97+
9098
# Special cases
9199
if annotation is None or annotation is type(None): # noqa: E721
92100
return ':py:obj:`None`'
@@ -130,18 +138,18 @@ def format_annotation(annotation,
130138
args_format = '\\[:py:data:`{prefix}typing.Union`\\[{{}}]]'.format(prefix=prefix)
131139
args = tuple(x for x in args if x is not type(None)) # noqa: E721
132140
elif full_name == 'typing.Callable' and args and args[0] is not ...:
141+
opts_shortened = dict(opts, typehints_formatter=typehints_formatter)
142+
del opts_shortened['fully_qualified']
133143
formatted_args = '\\[\\[' + ', '.join(
134-
format_annotation(
135-
arg, simplify_optional_unions=simplify_optional_unions)
144+
format_annotation(arg, **opts_shortened)
136145
for arg in args[:-1]) + ']'
137-
formatted_args += ', ' + format_annotation(
138-
args[-1], simplify_optional_unions=simplify_optional_unions) + ']'
146+
formatted_args += ', ' + format_annotation(args[-1], **opts_shortened) + ']'
139147
elif full_name == 'typing.Literal':
140148
formatted_args = '\\[' + ', '.join(repr(arg) for arg in args) + ']'
141149

142150
if args and not formatted_args:
143151
formatted_args = args_format.format(', '.join(
144-
format_annotation(arg, fully_qualified, simplify_optional_unions)
152+
format_annotation(arg, **opts, typehints_formatter=typehints_formatter)
145153
for arg in args))
146154

147155
return ':py:{role}:`{prefix}{full_name}`{formatted_args}'.format(
@@ -410,22 +418,29 @@ def process_docstring(app, what, name, obj, options, lines):
410418
obj = obj.fget
411419

412420
if callable(obj):
421+
413422
if inspect.isclass(obj):
414423
obj = getattr(obj, '__init__')
415424

416425
obj = inspect.unwrap(obj)
417426
type_hints = get_all_type_hints(obj, name)
427+
if not type_hints:
428+
return
429+
430+
fmt = partial(
431+
format_annotation,
432+
fully_qualified=app.config.typehints_fully_qualified,
433+
simplify_optional_unions=app.config.simplify_optional_unions,
434+
typehints_formatter=app.config.typehints_formatter,
435+
)
418436

419437
for argname, annotation in type_hints.items():
420438
if argname == 'return':
421439
continue # this is handled separately later
422440
if argname.endswith('_'):
423441
argname = '{}\\_'.format(argname[:-1])
424442

425-
formatted_annotation = format_annotation(
426-
annotation,
427-
fully_qualified=app.config.typehints_fully_qualified,
428-
simplify_optional_unions=app.config.simplify_optional_unions)
443+
formatted_annotation = fmt(annotation)
429444

430445
searchfor = [':{} {}:'.format(field, argname)
431446
for field in ('param', 'parameter', 'arg', 'argument')]
@@ -451,10 +466,7 @@ def process_docstring(app, what, name, obj, options, lines):
451466
if what == 'method' and name.endswith('.__init__'):
452467
return
453468

454-
formatted_annotation = format_annotation(
455-
type_hints['return'], fully_qualified=app.config.typehints_fully_qualified,
456-
simplify_optional_unions=app.config.simplify_optional_unions
457-
)
469+
formatted_annotation = fmt(type_hints['return'])
458470

459471
insert_index = len(lines)
460472
for i, line in enumerate(lines):
@@ -485,6 +497,7 @@ def setup(app):
485497
app.add_config_value('typehints_fully_qualified', False, 'env')
486498
app.add_config_value('typehints_document_rtype', True, 'env')
487499
app.add_config_value('simplify_optional_unions', True, 'env')
500+
app.add_config_value('typehints_formatter', lambda _annotation, **_opts: None, 'env')
488501
app.connect('builder-inited', builder_ready)
489502
app.connect('autodoc-process-signature', process_signature)
490503
app.connect('autodoc-process-docstring', process_docstring)

0 commit comments

Comments
 (0)