Skip to content

Commit

Permalink
Fix KeyError with type hints on the first arg of bound methods (#200)
Browse files Browse the repository at this point in the history
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bernát Gábor <[email protected]>
  • Loading branch information
3 people authored Jan 7, 2022
1 parent d50a24e commit 650fbc5
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## dev

- Fixed `normalize_source_lines()` messing with the indentation of methods with decorators that have parameters starting with `def`.
- Handle `ValueError` or `TypeError` being raised when signature of an object cannot be determined
- Fix `KeyError` being thrown when argument is not documented (e.g. `cls` argument for class methods, and `self` for methods)

## 1.14.0

Expand Down
5 changes: 4 additions & 1 deletion src/sphinx_autodoc_typehints/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,10 @@ def process_docstring(
for arg_name, annotation in type_hints.items():
if arg_name == "return":
continue # this is handled separately later
default = inspect.Parameter.empty if signature is None else signature.parameters[arg_name].default
if signature is None or arg_name not in signature.parameters:
default = inspect.Parameter.empty
else:
default = signature.parameters[arg_name].default
if arg_name.endswith("_"):
arg_name = f"{arg_name[:-1]}\\_"

Expand Down
43 changes: 33 additions & 10 deletions tests/test_sphinx_autodoc_typehints.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from functools import cmp_to_key
from io import StringIO
from textwrap import dedent, indent
from types import ModuleType
from types import FunctionType, ModuleType
from typing import (
IO,
Any,
Expand Down Expand Up @@ -54,7 +54,7 @@ def get_type(self) -> type:
return type(self)

class Inner:
pass
...


class B(Generic[T]):
Expand All @@ -63,23 +63,32 @@ class B(Generic[T]):


class C(B[str]):
pass
...


class D(typing_extensions.Protocol):
pass
...


class E(typing_extensions.Protocol[T]): # type: ignore # Invariant type variable "T" used in protocol where covariant
pass
...


class Slotted:
__slots__ = ()


class Metaclass(type):
pass
...


class HintedMethods:
@classmethod
def from_magic(cls: type[T]) -> T:
...

def method(self: T) -> T:
...


PY310_PLUS = sys.version_info >= (3, 10)
Expand Down Expand Up @@ -673,13 +682,13 @@ def test_normalize_source_lines_async_def() -> None:
source = """
async def async_function():
class InnerClass:
def __init__(self): pass
def __init__(self): ...
"""

expected = """
async def async_function():
class InnerClass:
def __init__(self): pass
def __init__(self): ...
"""

assert normalize_source_lines(dedent(source)) == dedent(expected)
Expand All @@ -699,7 +708,7 @@ def test_normalize_source_lines_def_starting_decorator_parameter() -> None:
),
)
def __init__(bound_args): # noqa: N805
pass
...
"""

expected = """
Expand All @@ -715,7 +724,7 @@ def __init__(bound_args): # noqa: N805
),
)
def __init__(bound_args): # noqa: N805
pass
...
"""

assert normalize_source_lines(dedent(source)) == dedent(expected)
Expand All @@ -728,3 +737,17 @@ def test_default_no_signature(obj: Any) -> None:
lines: list[str] = []
process_docstring(app, "what", "name", obj, None, lines)
assert lines == []


@pytest.mark.parametrize("method", [HintedMethods.from_magic, HintedMethods().method])
def test_bound_class_method(method: FunctionType) -> None:
config = create_autospec(
Config,
typehints_fully_qualified=False,
simplify_optional_unions=False,
typehints_document_rtype=False,
always_document_param_types=True,
typehints_defaults=True,
)
app: Sphinx = create_autospec(Sphinx, config=config)
process_docstring(app, "class", method.__qualname__, method, None, [])

0 comments on commit 650fbc5

Please sign in to comment.