Skip to content

Commit

Permalink
Add type hints for attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
david-yan committed Jun 30, 2020
1 parent e6b6119 commit 210a953
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 1 deletion.
21 changes: 21 additions & 0 deletions sphinx_autodoc_typehints.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,27 @@ def process_docstring(app, what, name, obj, options, lines):

if callable(obj):
if inspect.isclass(obj):
# Use type hints from instance and class variables for attributes
outer_obj = inspect.unwrap(obj)
type_hints = get_all_type_hints(outer_obj, name)
for argname, annotation in type_hints.items():
formatted_annotation = format_annotation(
annotation, fully_qualified=app.config.typehints_fully_qualified)

searchfor_attr = '.. attribute:: {}'.format(argname)
searchfor_ivar = ':ivar {}:'.format(argname)
for i, line in enumerate(lines):
if line.startswith(searchfor_attr):
i += 1
while i < len(lines):
if lines[i].startswith(':') or lines[i].startswith('.. '):
break
i += 1
lines.insert(i, ' :type: {}'.format(formatted_annotation))
break
if line.startswith(searchfor_ivar):
lines.insert(i, ':vartype {}: {}'.format(argname, formatted_annotation))
break
obj = getattr(obj, '__init__')

obj = inspect.unwrap(obj)
Expand Down
30 changes: 29 additions & 1 deletion tests/roots/test-dummy/dummy_module.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import typing
from mailbox import Mailbox
from typing import Callable, Union
from typing import Callable, ClassVar, Union

try:
from dataclasses import dataclass
Expand All @@ -24,8 +24,26 @@ class Class:
:param x: foo
:param y: bar
:param z: baz
.. attribute:: x
Multiline
Description
.. attribute:: y
bar
.. attribute:: z
baz
"""

x: bool
y: int
z: ClassVar[str]

def __init__(self, x: bool, y: int, z: typing.Optional[str] = None) -> None:
pass

Expand Down Expand Up @@ -88,8 +106,12 @@ def a_property(self) -> str:
class InnerClass:
"""
Inner class.
:ivar x: foo
"""

x: bool

def inner_method(self, x: bool) -> str:
"""
Inner method.
Expand All @@ -111,9 +133,15 @@ class DummyException(Exception):
"""
Exception docstring
.. attribute:: message
Message description
:param message: blah
"""

message: str

def __init__(self, message: str) -> None:
super().__init__(message)

Expand Down
43 changes: 43 additions & 0 deletions tests/test_sphinx_autodoc_typehints.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,36 @@ class dummy_module.Class(x, y, z=None)
* **z** ("Optional"["str"]) – baz
x
Multiline
Description
Type:
"bool"
y
bar
Type:
"int"
z
baz
Type:
"ClassVar"["str"]
class InnerClass
Inner class.
Variables:
**x** ("bool") -- foo
_InnerClass__dunder_inner_method(x)
Dunder inner method.
Expand All @@ -270,6 +296,8 @@ class InnerClass
Return type:
"str"
x: bool = None
_Class__dunder_method(x)
Dunder method docstring.
Expand Down Expand Up @@ -356,13 +384,28 @@ class InnerClass
Return type:
"str"
x: bool = None
y: int = None
z: ClassVar[str] = None
exception dummy_module.DummyException(message)
Exception docstring
message
Message description
Type:
"str"
Parameters:
**message** ("str") – blah
message: str = None
dummy_module.function(x, y, z_=None)
Function docstring.
Expand Down

0 comments on commit 210a953

Please sign in to comment.