From ae80e988edf362ce99a880063639e4cd74bc44bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 8 Dec 2020 19:08:42 +0100 Subject: [PATCH] fix: Fix attribute parser for Python 3.9 It seems `ast` has changed in Python 3.9. Some objects who previously had a `value` attribute don't have it anymore. Issue #73: https://github.com/pawamoy/pytkdocs/issues/73 Issue #75: https://github.com/pawamoy/pytkdocs/issues/75 --- src/pytkdocs/parsers/attributes.py | 7 ++++++- tests/fixtures/parsing/annotations.py | 10 ++++++++++ tests/test_parsers/test_annotations.py | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/parsing/annotations.py create mode 100644 tests/test_parsers/test_annotations.py diff --git a/src/pytkdocs/parsers/attributes.py b/src/pytkdocs/parsers/attributes.py index ae3146b..065bcbb 100644 --- a/src/pytkdocs/parsers/attributes.py +++ b/src/pytkdocs/parsers/attributes.py @@ -16,7 +16,12 @@ def node_to_annotation(node) -> Union[str, object]: elif isinstance(node.annotation, (ast.Constant, ast.Str)): return node.annotation.s elif isinstance(node.annotation, ast.Subscript): - return f"{node.annotation.value.id}[{node_to_annotation(node.annotation.slice.value)}]" # type: ignore + value_id = node.annotation.value.id # type: ignore + if hasattr(node.annotation.slice, "value"): + value = node.annotation.slice.value # type: ignore + else: + value = node.annotation.slice + return f"{value_id}[{node_to_annotation(value)}]" else: return inspect.Signature.empty elif isinstance(node, ast.Subscript): diff --git a/tests/fixtures/parsing/annotations.py b/tests/fixtures/parsing/annotations.py new file mode 100644 index 0000000..0ee8899 --- /dev/null +++ b/tests/fixtures/parsing/annotations.py @@ -0,0 +1,10 @@ +from typing import Any, Dict, List + + +class C: + def __init__(self): + # https://github.com/pawamoy/pytkdocs/issues/73 + self.dict_annotation: Dict[str, Any] = {} + + # https://github.com/pawamoy/pytkdocs/issues/75 + self.list_annotation: List[str] = [] diff --git a/tests/test_parsers/test_annotations.py b/tests/test_parsers/test_annotations.py new file mode 100644 index 0000000..6ce2adf --- /dev/null +++ b/tests/test_parsers/test_annotations.py @@ -0,0 +1,20 @@ +"""Tests for [the `parsers.attributes` module][pytkdocs.parsers.attributes] on annotations.""" + + +from tests.fixtures.parsing import annotations + +from pytkdocs.parsers.attributes import get_instance_attributes + + +class TestAnnotations: + def setup(self): + """Setup reusable attributes.""" + self.attributes = get_instance_attributes(annotations.C.__init__) + + def test_parse_dict_annotation(self): + assert "dict_annotation" in self.attributes + assert self.attributes["dict_annotation"]["annotation"] == "Dict[str, Any]" + + def test_parse_list_annotation(self): + assert "list_annotation" in self.attributes + assert self.attributes["list_annotation"]["annotation"] == "List[str]"