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

Commit 5361f82

Browse files
authored
feat: migrate @move annotation (#1149)
Closes #1143. ### Summary of Changes - add migration for `@move` annotations to another version, with the possibilities: - If the mapped apiv2 element is a class or global function, the annotation will be migrated as expected. - Else, a `@todo` annotation will mark the element. - new get_migration_text function that creates the text for a todo annotation or comment ### Testing Instructions run the migrate command or view and run the `test_migration.py` file Co-authored-by: Aclrian <[email protected]>
1 parent c00bea6 commit 5361f82

16 files changed

+553
-248
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
migrate_todo_annotation,
1313
migrate_value_annotation,
1414
)
15+
from package_parser.processing.migration.annotations._migrate_move_annotation import (
16+
migrate_move_annotation,
17+
)
1518
from package_parser.processing.migration.model import Mapping
1619

1720

@@ -45,6 +48,12 @@ def migrate_annotations(
4548
for annotation in migrate_enum_annotation(enum_annotation, mapping):
4649
migrated_annotation_store.add_annotation(annotation)
4750

51+
for move_annotation in annotationsv1.moveAnnotations:
52+
mapping = _get_mapping_from_annotation(move_annotation, mappings)
53+
if mapping is not None:
54+
for annotation in migrate_move_annotation(move_annotation, mapping):
55+
migrated_annotation_store.add_annotation(annotation)
56+
4857
for rename_annotation in annotationsv1.renameAnnotations:
4958
mapping = _get_mapping_from_annotation(rename_annotation, mappings)
5059
if mapping is not None:

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from ._constants import migration_author
2+
from ._get_migration_text import get_migration_text
23
from ._migrate_boundary_annotation import migrate_boundary_annotation
34
from ._migrate_enum_annotation import migrate_enum_annotation
45
from ._migrate_rename_annotation import migrate_rename_annotation
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
from package_parser.processing.annotations.model import (
2+
AbstractAnnotation,
3+
BoundaryAnnotation,
4+
CalledAfterAnnotation,
5+
CompleteAnnotation,
6+
ConstantAnnotation,
7+
DescriptionAnnotation,
8+
EnumAnnotation,
9+
GroupAnnotation,
10+
MoveAnnotation,
11+
OptionalAnnotation,
12+
PureAnnotation,
13+
RemoveAnnotation,
14+
RenameAnnotation,
15+
TodoAnnotation,
16+
ValueAnnotation,
17+
)
18+
from package_parser.processing.migration import Mapping
19+
20+
21+
def _get_further_information(annotation: AbstractAnnotation) -> str:
22+
if isinstance(annotation, (CompleteAnnotation, PureAnnotation, RemoveAnnotation)):
23+
return ""
24+
if isinstance(annotation, BoundaryAnnotation):
25+
return " with the interval '" + str(annotation.interval.to_json()) + "'"
26+
if isinstance(annotation, CalledAfterAnnotation):
27+
return (
28+
" with the method '"
29+
+ annotation.calledAfterName
30+
+ "' that should be called before"
31+
)
32+
if isinstance(annotation, DescriptionAnnotation):
33+
return " with the new description '" + annotation.newDescription + "'"
34+
if isinstance(annotation, EnumAnnotation):
35+
return (
36+
" with the new enum '"
37+
+ annotation.enumName
38+
+ " ("
39+
+ ", ".join(
40+
map(
41+
lambda enum_pair: enum_pair.stringValue
42+
+ ", "
43+
+ enum_pair.instanceName,
44+
annotation.pairs,
45+
)
46+
)
47+
+ ")'"
48+
)
49+
if isinstance(annotation, GroupAnnotation):
50+
return (
51+
" with the group name '"
52+
+ annotation.groupName
53+
+ "' and the grouped parameters: '"
54+
+ ", ".join(annotation.parameters)
55+
+ "'"
56+
)
57+
if isinstance(annotation, MoveAnnotation):
58+
return " with the destination: '" + annotation.destination + "'"
59+
if isinstance(annotation, RenameAnnotation):
60+
return " with the new name '" + annotation.newName + "'"
61+
if isinstance(annotation, TodoAnnotation):
62+
return " with the todo '" + annotation.newTodo + "'"
63+
if isinstance(annotation, ValueAnnotation):
64+
value = " with the variant '" + annotation.variant.value
65+
if isinstance(annotation, (ConstantAnnotation, OptionalAnnotation)):
66+
value += (
67+
"' and the default Value '"
68+
+ annotation.defaultValue
69+
+ " ( type: "
70+
+ annotation.defaultValueType.value
71+
+ " )"
72+
)
73+
value += "'"
74+
return value
75+
return " with the data '" + str(annotation.to_json()) + "'"
76+
77+
78+
def get_migration_text(annotation: AbstractAnnotation, mapping: Mapping) -> str:
79+
class_name = str(annotation.__class__.__name__)
80+
if class_name.endswith("Annotation"):
81+
class_name = class_name[:-10]
82+
if issubclass(type(annotation), ValueAnnotation):
83+
class_name = "Value"
84+
85+
migrate_text = (
86+
"The @" + class_name + " Annotation" + _get_further_information(annotation)
87+
)
88+
migrate_text += (
89+
" from the previous version was at '"
90+
+ annotation.target
91+
+ "' and the possible alternatives in the new version of the api are: "
92+
+ ", ".join(
93+
map(
94+
lambda api_element: api_element.id
95+
if hasattr(api_element, "id")
96+
else api_element.name,
97+
mapping.get_apiv2_elements(),
98+
)
99+
)
100+
)
101+
return migrate_text

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

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
)
2626

2727
from ._constants import migration_author
28+
from ._get_migration_text import get_migration_text
2829

2930

3031
def migrate_interval_to_fit_parameter_type(
@@ -80,16 +81,7 @@ def migrate_boundary_annotation(
8081
authors.append(migration_author)
8182
boundary_annotation.authors = authors
8283

83-
migrate_text = (
84-
"The @Boundary Annotation with the interval '"
85-
+ str(boundary_annotation.interval.to_json())
86-
+ "' from the previous version was at '"
87-
+ boundary_annotation.target
88-
+ "' and the possible alternatives in the new version of the api are: "
89-
+ ", ".join(
90-
map(lambda api_element: api_element.name, mapping.get_apiv2_elements())
91-
)
92-
)
84+
migrate_text = get_migration_text(boundary_annotation, mapping)
9385

9486
if isinstance(mapping, (OneToOneMapping, ManyToOneMapping)):
9587
parameter = mapping.get_apiv2_elements()[0]

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

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
)
2626

2727
from ._constants import migration_author
28+
from ._get_migration_text import get_migration_text
2829

2930

3031
def _contains_string(type_: AbstractType) -> bool:
@@ -56,23 +57,7 @@ def migrate_enum_annotation(
5657
authors.append(migration_author)
5758
enum_annotation.authors = authors
5859

59-
migrate_text = (
60-
"The @Enum Annotation with the new name '"
61-
+ enum_annotation.enumName
62-
+ " ("
63-
+ ", ".join(
64-
map(
65-
lambda enum_pair: enum_pair.stringValue + ", " + enum_pair.instanceName,
66-
enum_annotation.pairs,
67-
)
68-
)
69-
+ ")' from the previous version was at '"
70-
+ enum_annotation.target
71-
+ "' and the possible alternatives in the new version of the api are: "
72-
+ ", ".join(
73-
map(lambda api_element: api_element.name, mapping.get_apiv2_elements())
74-
)
75-
)
60+
migrate_text = get_migration_text(enum_annotation, mapping)
7661

7762
if isinstance(mapping, (OneToOneMapping, ManyToOneMapping)):
7863
parameter = mapping.get_apiv2_elements()[0]
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
from copy import deepcopy
2+
3+
from package_parser.processing.annotations.model import (
4+
AbstractAnnotation,
5+
EnumReviewResult,
6+
MoveAnnotation,
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_migration_text import get_migration_text
24+
25+
26+
def is_moveable(element: Attribute | Class | Function | Parameter | Result) -> bool:
27+
if isinstance(element, (Attribute, Result)):
28+
return False
29+
if isinstance(element, Function):
30+
# check for global function
31+
element_parents = element.id.split("/")
32+
return len(element_parents) == 3
33+
return isinstance(element, Class)
34+
35+
36+
# pylint: disable=duplicate-code
37+
def migrate_move_annotation(
38+
move_annotation: MoveAnnotation, mapping: Mapping
39+
) -> list[AbstractAnnotation]:
40+
move_annotation = deepcopy(move_annotation)
41+
authors = move_annotation.authors
42+
authors.append(migration_author)
43+
move_annotation.authors = authors
44+
migrate_text = get_migration_text(move_annotation, mapping)
45+
46+
if isinstance(mapping, (ManyToOneMapping, OneToOneMapping)):
47+
element = mapping.get_apiv2_elements()[0]
48+
if isinstance(element, (Attribute, Result)):
49+
return []
50+
if not is_moveable(element):
51+
return [
52+
TodoAnnotation(
53+
element.id,
54+
authors,
55+
move_annotation.reviewers,
56+
move_annotation.comment,
57+
EnumReviewResult.NONE,
58+
migrate_text,
59+
)
60+
]
61+
move_annotation.target = element.id
62+
return [move_annotation]
63+
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+
73+
if annotated_apiv1_element is None:
74+
return []
75+
76+
move_annotations: list[AbstractAnnotation] = []
77+
for element in mapping.get_apiv2_elements():
78+
if (
79+
isinstance(element, type(annotated_apiv1_element))
80+
and is_moveable(element)
81+
and not isinstance(element, (Attribute, Result))
82+
):
83+
move_annotations.append(
84+
MoveAnnotation(
85+
element.id,
86+
authors,
87+
move_annotation.reviewers,
88+
move_annotation.comment,
89+
EnumReviewResult.NONE,
90+
move_annotation.destination,
91+
)
92+
)
93+
elif not isinstance(element, (Attribute, Result)):
94+
move_annotations.append(
95+
TodoAnnotation(
96+
element.id,
97+
authors,
98+
move_annotation.reviewers,
99+
move_annotation.comment,
100+
EnumReviewResult.UNSURE,
101+
migrate_text,
102+
)
103+
)
104+
return move_annotations

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

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
)
1515

1616
from ._constants import migration_author
17+
from ._get_migration_text import get_migration_text
1718

1819

1920
def migrate_rename_annotation(
@@ -32,16 +33,7 @@ def migrate_rename_annotation(
3233
rename_annotation.target = element.id
3334
return [rename_annotation]
3435

35-
migrate_text = (
36-
"The @Rename Annotation with the new name '"
37-
+ rename_annotation.newName
38-
+ "' from the previous version was at '"
39-
+ rename_annotation.target
40-
+ "' and the possible alternatives in the new version of the api are: "
41-
+ ", ".join(
42-
map(lambda api_element: api_element.name, mapping.get_apiv2_elements())
43-
)
44-
)
36+
migrate_text = get_migration_text(rename_annotation, mapping)
4537

4638
todo_annotations: list[AbstractAnnotation] = []
4739
for element in mapping.get_apiv2_elements():

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
)
1414

1515
from ._constants import migration_author
16+
from ._get_migration_text import get_migration_text
1617

1718

19+
# pylint: disable=duplicate-code
1820
def migrate_todo_annotation(
1921
todo_annotation: TodoAnnotation, mapping: Mapping
2022
) -> list[AbstractAnnotation]:
@@ -30,21 +32,19 @@ def migrate_todo_annotation(
3032
todo_annotation.target = element.id
3133
return [todo_annotation]
3234

33-
migrate_text = (
34-
"The @Todo Annotation with the todo '"
35-
+ todo_annotation.newTodo
36-
+ "' from the previous version was at '"
37-
+ todo_annotation.target
38-
+ "' and the possible alternatives in the new version of the api are: "
39-
+ ", ".join(
40-
map(lambda api_element: api_element.name, mapping.get_apiv2_elements())
41-
)
42-
)
35+
migrate_text = get_migration_text(todo_annotation, mapping)
4336

4437
annotated_apiv1_element = None
4538
for element in mapping.get_apiv1_elements():
46-
if not isinstance(element, (Attribute, Result)) and element.id:
39+
if (
40+
not isinstance(element, (Attribute, Result))
41+
and todo_annotation.target == element.id
42+
):
4743
annotated_apiv1_element = element
44+
break
45+
46+
if annotated_apiv1_element is None:
47+
return []
4848

4949
todo_annotations: list[AbstractAnnotation] = []
5050
for element in mapping.get_apiv2_elements():

0 commit comments

Comments
 (0)