Skip to content

Instantly share code, notes, and snippets.

@tk0miya
Last active December 22, 2019 07:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tk0miya/d7b64291a3fbdf839e20ec507e8287fb to your computer and use it in GitHub Desktop.
Save tk0miya/d7b64291a3fbdf839e20ec507e8287fb to your computer and use it in GitHub Desktop.
# extension testbed
# autodoc_typehints_docinfo -- typehint をいい感じに表示する拡張
#
# * 型情報は typehint を書いておいてね
# * conf.py で autodoc_typehints = 'docinfo' と設定する
from docutils import nodes
from sphinx import addnodes
from sphinx.util.docfields import DocFieldTransformer
from sphinx.util.inspect import Signature
def process_signature(app, objtype, name, obj, options, args, retann):
try:
if callable(obj):
signature = app.env.temp_data.setdefault('signatures', {}).setdefault(name, {})
sig = Signature(obj)
for param in sig.parameters.values():
if isinstance(param.annotation, str) and param.name in sig.annotations:
annotation = sig.annotations[param.name]
else:
annotation = param.annotation
if annotation is not param.empty:
signature[param.name] = sig.format_annotation(param.annotation)
except TypeError:
pass
orig_transform_all = DocFieldTransformer.transform_all
def transform_all(self, node):
signature = node.parent[0]
fullname = '.'.join([signature['module'], signature['fullname']])
signatures = self.directive.env.temp_data.get('signatures', {})
if signatures.get(fullname, {}):
field_lists = [n for n in node if isinstance(n, nodes.field_list)]
if field_lists == []:
insert_field_list(node, signatures[fullname])
else:
for field_list in field_lists:
modify_field_list(field_list, signatures[fullname])
orig_transform_all(self, node)
def insert_field_list(node, signature):
field_list = nodes.field_list()
for name, annotation in signature.items():
field_name = nodes.field_name("param " + name, "param " + name)
field_body = nodes.field_body()
field_list += nodes.field("", field_name, field_body)
field_name = nodes.field_name("type " + name, "type " + name)
field_body = nodes.field_body("", nodes.paragraph(annotation, annotation))
field_list += nodes.field("", field_name, field_body)
desc = [n for n in node if isinstance(n, addnodes.desc)]
if desc:
index = node.index(desc[0])
node.insert(index - 1, [field_list])
else:
node += field_list
def modify_field_list(node, signature):
for name, annotation in signature.items():
field_name = nodes.field_name("type " + name, "type " + name)
field_body = nodes.field_body("", nodes.paragraph(annotation, annotation))
node += nodes.field("", field_name, field_body)
def config_inited(app, config):
if config.autodoc_typehints == 'docinfo':
config.autodoc_typehints = 'none'
DocFieldTransformer.transform_all = transform_all
app.connect('autodoc-process-signature', process_signature)
def setup(app):
app.setup_extension('sphinx.ext.autodoc')
app.config.values['autodoc_typehints'][2].candidates += ('docinfo',)
app.connect('config-inited', config_inited)
@shimizukawa
Copy link

autodoc_typehints = 'signature' の場合(ext.pyを適用しないデフォルト動作)

image

この拡張を有効化して autodoc_typehints = 'docinfo' の場合(ext.pyを適用した動作)

image

autodoc_typehints = 'docinfo' の場合(ext.pyを適用した動作)で、 'sphinx.ext.intersphinx'も適用

image

設定

extensions = [
    'sphinx.ext.autodoc',
    'ext',
    'sphinx.ext.intersphinx'
]
autodoc_default_options = {
    'members': True,
    'undoc-members': True,
}
# autodoc_typehints = 'signature'
# autodoc_typehints = 'none'
autodoc_typehints = 'docinfo'
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}

@shimizukawa
Copy link

動かしてみた感じ、 :rtype: は未対応でした

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment