Skip to content
This repository was archived by the owner on Jan 19, 2025. It is now read-only.

Commit 36026ea

Browse files
authored
feat: add @remove migration (#1151)
Closes #1144. ### Summary of Changes - Migration of `@remove` annotations through a mapping from old api elements to new api elements. If the mapped apiv2 element is removable (a class or function), change the target of the annotation. Otherwise, mark the api element that are not removable with an `@todo` annotation. - New methods `get_annotated_api_element` and `get_annotated_api_element_by_type` to get the element from an annotation by its id. ### Testing Instructions run the migrate command or view and run the `test_migration.py` file Co-authored-by: Aclrian <[email protected]>
1 parent 5361f82 commit 36026ea

File tree

9 files changed

+351
-72
lines changed

9 files changed

+351
-72
lines changed

package-parser/package_parser/processing/migration/_migrate.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
from package_parser.processing.migration.annotations._migrate_move_annotation import (
1616
migrate_move_annotation,
1717
)
18+
from package_parser.processing.migration.annotations._migrate_remove_annotation import (
19+
migrate_remove_annotation,
20+
)
1821
from package_parser.processing.migration.model import Mapping
1922

2023

@@ -60,6 +63,12 @@ def migrate_annotations(
6063
for annotation in migrate_rename_annotation(rename_annotation, mapping):
6164
migrated_annotation_store.add_annotation(annotation)
6265

66+
for remove_annotation in annotationsv1.removeAnnotations:
67+
mapping = _get_mapping_from_annotation(remove_annotation, mappings)
68+
if mapping is not None:
69+
for annotation in migrate_remove_annotation(remove_annotation, mapping):
70+
migrated_annotation_store.add_annotation(annotation)
71+
6372
for todo_annotation in annotationsv1.todoAnnotations:
6473
mapping = _get_mapping_from_annotation(todo_annotation, mappings)
6574
if mapping is not None:
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from typing import List, Optional, TypeVar, Union
2+
3+
from package_parser.processing.annotations.model import AbstractAnnotation
4+
from package_parser.processing.api.model import (
5+
Attribute,
6+
Class,
7+
Function,
8+
Parameter,
9+
Result,
10+
)
11+
12+
API_ELEMENTS = TypeVar("API_ELEMENTS", Class, Function, Parameter)
13+
14+
15+
def get_annotated_api_element(
16+
annotation: AbstractAnnotation,
17+
api_element_list: List[Union[Attribute, Class, Function, Parameter, Result]],
18+
) -> Optional[Union[Class, Function, Parameter]]:
19+
for element in api_element_list:
20+
if (
21+
isinstance(element, (Class, Function, Parameter))
22+
and element.id == annotation.target
23+
):
24+
return element
25+
return None
26+
27+
28+
def get_annotated_api_element_by_type(
29+
annotation: AbstractAnnotation,
30+
api_element_list: List[Union[Attribute, Class, Function, Parameter, Result]],
31+
api_type: type[API_ELEMENTS],
32+
) -> Optional[API_ELEMENTS]:
33+
for element in api_element_list:
34+
if isinstance(element, api_type) and element.id == annotation.target:
35+
return element
36+
return None

package-parser/package_parser/processing/migration/annotations/_migrate_move_annotation.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
)
2121

2222
from ._constants import migration_author
23+
from ._get_annotated_api_element import get_annotated_api_element
2324
from ._get_migration_text import get_migration_text
2425

2526

@@ -61,15 +62,9 @@ def migrate_move_annotation(
6162
move_annotation.target = element.id
6263
return [move_annotation]
6364

64-
annotated_apiv1_element = None
65-
for element in mapping.get_apiv1_elements():
66-
if (
67-
not isinstance(element, (Attribute, Result))
68-
and move_annotation.target == element.id
69-
):
70-
annotated_apiv1_element = element
71-
break
72-
65+
annotated_apiv1_element = get_annotated_api_element(
66+
move_annotation, mapping.get_apiv1_elements()
67+
)
7368
if annotated_apiv1_element is None:
7469
return []
7570

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
from copy import deepcopy
2+
3+
from package_parser.processing.annotations.model import (
4+
AbstractAnnotation,
5+
EnumReviewResult,
6+
RemoveAnnotation,
7+
TodoAnnotation,
8+
)
9+
from package_parser.processing.api.model import (
10+
Attribute,
11+
Class,
12+
Function,
13+
Parameter,
14+
Result,
15+
)
16+
from package_parser.processing.migration.model import (
17+
ManyToOneMapping,
18+
Mapping,
19+
OneToOneMapping,
20+
)
21+
22+
from ._constants import migration_author
23+
from ._get_annotated_api_element import get_annotated_api_element
24+
from ._get_migration_text import get_migration_text
25+
26+
27+
def is_removeable(element: Attribute | Class | Function | Parameter | Result) -> bool:
28+
return isinstance(element, (Class, Function))
29+
30+
31+
def migrate_remove_annotation(
32+
remove_annotation: RemoveAnnotation, mapping: Mapping
33+
) -> list[AbstractAnnotation]:
34+
remove_annotation = deepcopy(remove_annotation)
35+
authors = remove_annotation.authors
36+
authors.append(migration_author)
37+
remove_annotation.authors = authors
38+
migrate_text = get_migration_text(remove_annotation, mapping)
39+
40+
if isinstance(mapping, (ManyToOneMapping, OneToOneMapping)):
41+
element = mapping.get_apiv2_elements()[0]
42+
if isinstance(element, (Attribute, Result)):
43+
return []
44+
if not is_removeable(element):
45+
return [
46+
TodoAnnotation(
47+
element.id,
48+
authors,
49+
remove_annotation.reviewers,
50+
remove_annotation.comment,
51+
EnumReviewResult.NONE,
52+
migrate_text,
53+
)
54+
]
55+
remove_annotation.target = element.id
56+
return [remove_annotation]
57+
58+
annotated_apiv1_element = get_annotated_api_element(
59+
remove_annotation, mapping.get_apiv1_elements()
60+
)
61+
if annotated_apiv1_element is None:
62+
return []
63+
64+
remove_annotations: list[AbstractAnnotation] = []
65+
for element in mapping.get_apiv2_elements():
66+
if (
67+
isinstance(element, type(annotated_apiv1_element))
68+
and is_removeable(element)
69+
and not isinstance(element, (Attribute, Result))
70+
):
71+
remove_annotations.append(
72+
RemoveAnnotation(
73+
element.id,
74+
authors,
75+
remove_annotation.reviewers,
76+
remove_annotation.comment,
77+
EnumReviewResult.NONE,
78+
)
79+
)
80+
elif not isinstance(element, (Attribute, Result)):
81+
remove_annotations.append(
82+
TodoAnnotation(
83+
element.id,
84+
authors,
85+
remove_annotation.reviewers,
86+
remove_annotation.comment,
87+
EnumReviewResult.NONE,
88+
migrate_text,
89+
)
90+
)
91+
return remove_annotations

package-parser/package_parser/processing/migration/annotations/_migrate_todo_annotation.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
)
1414

1515
from ._constants import migration_author
16+
from ._get_annotated_api_element import get_annotated_api_element
1617
from ._get_migration_text import get_migration_text
1718

1819

@@ -34,15 +35,9 @@ def migrate_todo_annotation(
3435

3536
migrate_text = get_migration_text(todo_annotation, mapping)
3637

37-
annotated_apiv1_element = None
38-
for element in mapping.get_apiv1_elements():
39-
if (
40-
not isinstance(element, (Attribute, Result))
41-
and todo_annotation.target == element.id
42-
):
43-
annotated_apiv1_element = element
44-
break
45-
38+
annotated_apiv1_element = get_annotated_api_element(
39+
todo_annotation, mapping.get_apiv1_elements()
40+
)
4641
if annotated_apiv1_element is None:
4742
return []
4843

package-parser/package_parser/processing/migration/annotations/_migrate_value_annotation.py

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from copy import deepcopy
2-
from typing import Optional, Tuple, TypeVar
2+
from typing import Optional, Tuple
33

44
from package_parser.processing.annotations.model import (
55
AbstractAnnotation,
@@ -14,8 +14,6 @@
1414
from package_parser.processing.api.model import (
1515
AbstractType,
1616
Attribute,
17-
Class,
18-
Function,
1917
NamedType,
2018
Parameter,
2119
Result,
@@ -30,6 +28,7 @@
3028
)
3129

3230
from ._constants import migration_author
31+
from ._get_annotated_api_element import get_annotated_api_element_by_type
3332
from ._get_migration_text import get_migration_text
3433

3534

@@ -254,26 +253,6 @@ def _have_same_value(
254253
return None
255254

256255

257-
API_ELEMENTS = TypeVar("API_ELEMENTS", Class, Function, Parameter)
258-
259-
260-
def get_api_element_from_mapping(
261-
annotation: AbstractAnnotation, mapping: Mapping, api_type: type[API_ELEMENTS]
262-
) -> Optional[API_ELEMENTS]:
263-
element_list = [
264-
element
265-
for element in mapping.get_apiv1_elements()
266-
if (
267-
isinstance(element, api_type)
268-
and hasattr(element, "id")
269-
and element.id == annotation.target
270-
)
271-
]
272-
if len(element_list) != 1:
273-
return None
274-
return element_list[0]
275-
276-
277256
def migrate_constant_annotation(
278257
constant_annotation: ConstantAnnotation, parameterv2: Parameter, mapping: Mapping
279258
) -> Optional[ConstantAnnotation]:
@@ -291,7 +270,9 @@ def migrate_constant_annotation(
291270
constant_annotation.defaultValue,
292271
)
293272

294-
parameterv1 = get_api_element_from_mapping(constant_annotation, mapping, Parameter)
273+
parameterv1 = get_annotated_api_element_by_type(
274+
constant_annotation, mapping.get_apiv1_elements(), Parameter
275+
)
295276
if parameterv1 is None:
296277
return None
297278
if _have_same_type(
@@ -312,7 +293,9 @@ def migrate_constant_annotation(
312293
def migrate_omitted_annotation(
313294
omitted_annotation: OmittedAnnotation, parameterv2: Parameter, mapping: Mapping
314295
) -> Optional[OmittedAnnotation]:
315-
parameterv1 = get_api_element_from_mapping(omitted_annotation, mapping, Parameter)
296+
parameterv1 = get_annotated_api_element_by_type(
297+
omitted_annotation, mapping.get_apiv1_elements(), Parameter
298+
)
316299
if parameterv1 is None:
317300
return None
318301
type_and_same_value = _have_same_value(parameterv1, parameterv2)
@@ -346,7 +329,9 @@ def migrate_omitted_annotation(
346329
def migrate_optional_annotation(
347330
optional_annotation: OptionalAnnotation, parameterv2: Parameter, mapping: Mapping
348331
) -> Optional[OptionalAnnotation]:
349-
parameterv1 = get_api_element_from_mapping(optional_annotation, mapping, Parameter)
332+
parameterv1 = get_annotated_api_element_by_type(
333+
optional_annotation, mapping.get_apiv1_elements(), Parameter
334+
)
350335
if parameterv1 is None:
351336
return None
352337
if parameterv2.type is not None and _have_same_type(
@@ -380,7 +365,9 @@ def migrate_optional_annotation(
380365
def migrate_required_annotation(
381366
required_annotation: RequiredAnnotation, parameterv2: Parameter, mapping: Mapping
382367
) -> Optional[RequiredAnnotation]:
383-
parameterv1 = get_api_element_from_mapping(required_annotation, mapping, Parameter)
368+
parameterv1 = get_annotated_api_element_by_type(
369+
required_annotation, mapping.get_apiv1_elements(), Parameter
370+
)
384371
if parameterv1 is None:
385372
return None
386373
type_and_same_value = _have_same_value(parameterv1, parameterv2)

0 commit comments

Comments
 (0)