Skip to content

Commit 4a981b4

Browse files
authored
Respect existing forms of final annotations (#33)
1 parent bc862a2 commit 4a981b4

File tree

2 files changed

+27
-30
lines changed

2 files changed

+27
-30
lines changed

auto_typing_final/transform.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,18 @@ def _make_operation_from_assignments_to_one_name(nodes: list[SgNode]) -> Operati
9595
return RemoveFinal(assignments)
9696

9797

98-
def _attribute_is_exact_identifier(node: SgNode, imports_result: ImportsResult, identifier_name: str) -> bool:
98+
def _match_exact_identifier(node: SgNode, imports_result: ImportsResult, identifier_name: str) -> str | None:
9999
match tuple((inner_child.kind(), inner_child) for inner_child in node.children()):
100100
case (("identifier", first_identifier), (".", _), ("identifier", second_identifier)):
101-
return (
102-
first_identifier.text() in imports_result.module_aliases and second_identifier.text() == identifier_name
103-
)
104-
return False
101+
for alias in imports_result.module_aliases:
102+
if alias == first_identifier.text() and second_identifier.text() == identifier_name:
103+
return node.text()
104+
return None
105105

106106

107-
def _strip_identifier_from_type_annotation(
107+
def _strip_identifier_from_type_annotation( # noqa: C901, PLR0911
108108
node: SgNode, imports_result: ImportsResult, identifier_name: str
109-
) -> str | None:
109+
) -> tuple[str, str] | None:
110110
type_node_children: Final = node.children()
111111
if len(type_node_children) != 1:
112112
return None
@@ -116,20 +116,22 @@ def _strip_identifier_from_type_annotation(
116116
if kind == "subscript":
117117
match tuple((child.kind(), child) for child in inner_type_node.children()):
118118
case (("attribute", attribute), ("[", _), *kinds_and_nodes, ("]", _)):
119-
if _attribute_is_exact_identifier(attribute, imports_result, identifier_name):
120-
return "".join(node.text() for _, node in kinds_and_nodes)
119+
if existing_final := _match_exact_identifier(attribute, imports_result, identifier_name):
120+
return existing_final, "".join(node.text() for _, node in kinds_and_nodes)
121121
elif kind == "generic_type" and imports_result.has_from_import:
122122
match tuple((child.kind(), child) for child in inner_type_node.children()):
123123
case (("identifier", identifier), ("type_parameter", type_parameter)):
124124
if identifier.text() != identifier_name:
125125
return None
126126
match tuple((inner_child.kind(), inner_child) for inner_child in type_parameter.children()):
127127
case (("[", _), *kinds_and_nodes, ("]", _)):
128-
return "".join(node.text() for _, node in kinds_and_nodes)
129-
elif (kind == "identifier" and inner_type_node.text() == identifier_name) or (
130-
kind == "attribute" and _attribute_is_exact_identifier(inner_type_node, imports_result, identifier_name)
128+
return identifier_name, "".join(node.text() for _, node in kinds_and_nodes)
129+
elif kind == "identifier" and inner_type_node.text() == identifier_name:
130+
return identifier_name, ""
131+
elif kind == "attribute" and (
132+
existing_final := _match_exact_identifier(inner_type_node, imports_result, identifier_name)
131133
):
132-
return ""
134+
return existing_final, ""
133135
return None
134136

135137

@@ -145,10 +147,10 @@ def _make_changed_text_from_operation( # noqa: C901
145147
match _strip_identifier_from_type_annotation(annotation, imports_result, identifier_name):
146148
case None:
147149
yield node, f"{left}: {final_value}[{annotation.text()}] = {right}"
148-
case "":
149-
yield node, f"{left}: {final_value} = {right}"
150-
case new_annotation:
151-
yield node, f"{left}: {final_value}[{new_annotation}] = {right}"
150+
case existing_final, "":
151+
yield node, f"{left}: {existing_final} = {right}"
152+
case existing_final, new_annotation:
153+
yield node, f"{left}: {existing_final}[{new_annotation}] = {right}"
152154

153155
case RemoveFinal(assignments):
154156
for assignment in assignments:
@@ -157,9 +159,9 @@ def _make_changed_text_from_operation( # noqa: C901
157159
yield node, f"{left} = {right}"
158160
case AssignmentWithAnnotation(node, left, annotation, right):
159161
match _strip_identifier_from_type_annotation(annotation, imports_result, identifier_name):
160-
case "":
162+
case _, "":
161163
yield node, f"{left} = {right}"
162-
case str(new_annotation):
164+
case _, new_annotation:
163165
yield node, f"{left}: {new_annotation} = {right}"
164166

165167

tests/test_main.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -671,11 +671,10 @@ def test_add_import(case: str) -> None:
671671
def f():
672672
a: Final[int] = 1
673673
---
674-
import typing
675674
from typing import Final
676675
677676
def f():
678-
a: typing.Final[int] = 1
677+
a: Final[int] = 1
679678
""",
680679
IMPORT_STYLES_TO_IMPORT_CONFIGS["typing-final"],
681680
),
@@ -686,11 +685,10 @@ def f():
686685
b: typing.Final = 2
687686
c: Final = 3
688687
---
689-
import typing
690688
def f():
691-
a: typing.Final = 1
689+
a: Final = 1
692690
b: typing.Final = 2
693-
c: typing.Final = 3
691+
c: Final = 3
694692
""",
695693
IMPORT_STYLES_TO_IMPORT_CONFIGS["typing-final"],
696694
),
@@ -703,12 +701,11 @@ def f():
703701
b: typing.Final = 2
704702
c: Final = 3
705703
---
706-
from typing import Final
707704
import typing
708705
709706
def f():
710707
a: Final = 1
711-
b: Final = 2
708+
b: typing.Final = 2
712709
c: Final = 3
713710
""",
714711
IMPORT_STYLES_TO_IMPORT_CONFIGS["final"],
@@ -720,11 +717,10 @@ def f():
720717
def f():
721718
a: tp.Final = 1
722719
---
723-
import typing
724720
import typing as tp
725721
726722
def f():
727-
a: typing.Final = 1
723+
a: tp.Final = 1
728724
""",
729725
IMPORT_STYLES_TO_IMPORT_CONFIGS["typing-final"],
730726
),
@@ -735,11 +731,10 @@ def f():
735731
def f():
736732
a: tp.Final = 1
737733
---
738-
from typing import Final
739734
import typing as tp
740735
741736
def f():
742-
a: Final = 1
737+
a: tp.Final = 1
743738
""",
744739
IMPORT_STYLES_TO_IMPORT_CONFIGS["final"],
745740
),

0 commit comments

Comments
 (0)