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

Commit 7cbe53a

Browse files
authored
feat: migrate @expert annotations (#1160)
Closes #1155. ### Summary of Changes - add `expertAnnotations` to `AnnotationStore` - add migration for `@expert` annotations to another version, with the possibilities: - If the codomain contains only one element, the annotation will be migrated to that element. - If one mapped apiv2 element has the same type as the annotated apiv1 element, the annotation will be migrated as expected. - Else, the element will be marked with a `@todo` annotation. ### Testing Instructions run the migrate command or view and run the `test_migration.py` file
1 parent 9491c2c commit 7cbe53a

File tree

8 files changed

+308
-4
lines changed

8 files changed

+308
-4
lines changed

package-parser/package_parser/processing/annotations/model/_AnnotationStore.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
CompleteAnnotation,
1212
DescriptionAnnotation,
1313
EnumAnnotation,
14+
ExpertAnnotation,
1415
GroupAnnotation,
1516
MoveAnnotation,
1617
PureAnnotation,
@@ -28,6 +29,7 @@ class AnnotationStore:
2829
completeAnnotations: list[CompleteAnnotation] = field(default_factory=list)
2930
descriptionAnnotations: list[DescriptionAnnotation] = field(default_factory=list)
3031
enumAnnotations: list[EnumAnnotation] = field(default_factory=list)
32+
expertAnnotations: list[ExpertAnnotation] = field(default_factory=list)
3133
groupAnnotations: list[GroupAnnotation] = field(default_factory=list)
3234
moveAnnotations: list[MoveAnnotation] = field(default_factory=list)
3335
pureAnnotations: list[PureAnnotation] = field(default_factory=list)
@@ -63,6 +65,10 @@ def from_json(json: Any) -> AnnotationStore:
6365
for annotation in json["enumAnnotations"].values():
6466
enumAnnotations.append(EnumAnnotation.from_json(annotation))
6567

68+
expertAnnotations = []
69+
for annotation in json["expertAnnotations"].values():
70+
expertAnnotations.append(ExpertAnnotation.from_json(annotation))
71+
6672
groupAnnotations = []
6773
for annotation in json["groupAnnotations"].values():
6874
groupAnnotations.append(GroupAnnotation.from_json(annotation))
@@ -97,6 +103,7 @@ def from_json(json: Any) -> AnnotationStore:
97103
completeAnnotations,
98104
descriptionAnnotations,
99105
enumAnnotations,
106+
expertAnnotations,
100107
groupAnnotations,
101108
moveAnnotations,
102109
pureAnnotations,
@@ -117,6 +124,8 @@ def add_annotation(self, annotation: AbstractAnnotation) -> None:
117124
self.descriptionAnnotations.append(annotation)
118125
elif isinstance(annotation, EnumAnnotation):
119126
self.enumAnnotations.append(annotation)
127+
elif isinstance(annotation, ExpertAnnotation):
128+
self.expertAnnotations.append(annotation)
120129
elif isinstance(annotation, GroupAnnotation):
121130
self.groupAnnotations.append(annotation)
122131
elif isinstance(annotation, MoveAnnotation):
@@ -155,6 +164,10 @@ def to_json(self) -> dict:
155164
annotation.target: annotation.to_json()
156165
for annotation in self.enumAnnotations
157166
},
167+
"expertAnnotations": {
168+
annotation.target: annotation.to_json()
169+
for annotation in self.expertAnnotations
170+
},
158171
"groupAnnotations": {
159172
annotation.target: annotation.to_json()
160173
for annotation in self.groupAnnotations

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
migrate_called_after_annotation,
1111
migrate_description_annotation,
1212
migrate_enum_annotation,
13+
migrate_expert_annotation,
1314
migrate_group_annotation,
1415
migrate_move_annotation,
1516
migrate_remove_annotation,
@@ -66,6 +67,12 @@ def migrate_annotations(
6667
for annotation in migrate_enum_annotation(enum_annotation, mapping):
6768
migrated_annotation_store.add_annotation(annotation)
6869

70+
for expert_annotation in annotationsv1.expertAnnotations:
71+
mapping = _get_mapping_from_annotation(expert_annotation, mappings)
72+
if mapping is not None:
73+
for annotation in migrate_expert_annotation(expert_annotation, mapping):
74+
migrated_annotation_store.add_annotation(annotation)
75+
6976
for group_annotation in annotationsv1.groupAnnotations:
7077
mapping = _get_mapping_from_annotation(group_annotation, mappings)
7178
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
@@ -4,6 +4,7 @@
44
from ._migrate_called_after_annotation import migrate_called_after_annotation
55
from ._migrate_description_annotation import migrate_description_annotation
66
from ._migrate_enum_annotation import migrate_enum_annotation
7+
from ._migrate_expert_annotation import migrate_expert_annotation
78
from ._migrate_group_annotation import migrate_group_annotation
89
from ._migrate_move_annotation import migrate_move_annotation
910
from ._migrate_remove_annotation import migrate_remove_annotation

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
ConstantAnnotation,
99
DescriptionAnnotation,
1010
EnumAnnotation,
11+
ExpertAnnotation,
1112
GroupAnnotation,
1213
MoveAnnotation,
1314
OptionalAnnotation,
@@ -28,7 +29,10 @@
2829

2930

3031
def _get_further_information(annotation: AbstractAnnotation) -> str:
31-
if isinstance(annotation, (CompleteAnnotation, PureAnnotation, RemoveAnnotation)):
32+
if isinstance(
33+
annotation,
34+
(CompleteAnnotation, ExpertAnnotation, PureAnnotation, RemoveAnnotation),
35+
):
3236
return ""
3337
if isinstance(annotation, BoundaryAnnotation):
3438
return " with the interval '" + str(annotation.interval.to_json()) + "'"
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from copy import deepcopy
2+
3+
from package_parser.processing.annotations.model import (
4+
AbstractAnnotation,
5+
EnumReviewResult,
6+
ExpertAnnotation,
7+
TodoAnnotation,
8+
)
9+
from package_parser.processing.api.model import Attribute, Result
10+
from package_parser.processing.migration.model import (
11+
ManyToOneMapping,
12+
Mapping,
13+
OneToOneMapping,
14+
)
15+
16+
from ._constants import migration_author
17+
from ._get_annotated_api_element import get_annotated_api_element
18+
from ._get_migration_text import get_migration_text
19+
20+
21+
def migrate_expert_annotation(
22+
expert_annotation: ExpertAnnotation, mapping: Mapping
23+
) -> list[AbstractAnnotation]:
24+
expert_annotation = deepcopy(expert_annotation)
25+
authors = expert_annotation.authors
26+
authors.append(migration_author)
27+
expert_annotation.authors = authors
28+
migrate_text = get_migration_text(expert_annotation, mapping)
29+
30+
if isinstance(mapping, (ManyToOneMapping, OneToOneMapping)):
31+
element = mapping.get_apiv2_elements()[0]
32+
if isinstance(element, (Attribute, Result)):
33+
return []
34+
expert_annotation.target = element.id
35+
return [expert_annotation]
36+
37+
annotated_apiv1_element = get_annotated_api_element(
38+
expert_annotation, mapping.get_apiv1_elements()
39+
)
40+
if annotated_apiv1_element is None:
41+
return []
42+
43+
expert_annotations: list[AbstractAnnotation] = []
44+
for element in mapping.get_apiv2_elements():
45+
if isinstance(element, type(annotated_apiv1_element)) and not isinstance(
46+
element, (Attribute, Result)
47+
):
48+
expert_annotations.append(
49+
ExpertAnnotation(
50+
element.id,
51+
authors,
52+
expert_annotation.reviewers,
53+
expert_annotation.comment,
54+
EnumReviewResult.NONE,
55+
)
56+
)
57+
elif not isinstance(element, (Attribute, Result)):
58+
expert_annotations.append(
59+
TodoAnnotation(
60+
element.id,
61+
authors,
62+
expert_annotation.reviewers,
63+
expert_annotation.comment,
64+
EnumReviewResult.NONE,
65+
migrate_text,
66+
)
67+
)
68+
return expert_annotations

package-parser/tests/processing/annotations/model/test_annotations.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
)
2727

2828

29-
def test_annotation_store():
29+
def test_annotation_store() -> None:
3030
annotations = AnnotationStore()
3131
annotations.removeAnnotations.append(
3232
RemoveAnnotation(
@@ -168,6 +168,15 @@ def test_annotation_store():
168168
newTodo="TODO replace me",
169169
)
170170
)
171+
annotations.expertAnnotations.append(
172+
ExpertAnnotation(
173+
target="test/expert",
174+
authors=["$autogen$"],
175+
reviewers=[],
176+
comment="",
177+
reviewResult=EnumReviewResult.NONE,
178+
)
179+
)
171180
json_store = {
172181
"schemaVersion": ANNOTATION_SCHEMA_VERSION,
173182
"boundaryAnnotations": {
@@ -197,6 +206,15 @@ def test_annotation_store():
197206
"pairs": [{"instanceName": "test", "stringValue": "test"}],
198207
}
199208
},
209+
"expertAnnotations": {
210+
"test/expert": {
211+
"target": "test/expert",
212+
"authors": ["$autogen$"],
213+
"reviewers": [],
214+
"comment": "",
215+
"reviewResult": "",
216+
}
217+
},
200218
"removeAnnotations": {
201219
"test/remove": {
202220
"target": "test/remove",
@@ -653,7 +671,9 @@ def test_annotation_store():
653671
"test import and export of rename annotation",
654672
"test import and export of todo annotation",
655673
],
656-
)
657-
def test_conversion_between_json_and_annotation(annotation: AbstractAnnotation, json):
674+
) # type: ignore
675+
def test_conversion_between_json_and_annotation(
676+
annotation: AbstractAnnotation, json: dict
677+
) -> None:
658678
assert annotation.to_json() == json
659679
assert type(annotation).from_json(json) == annotation

0 commit comments

Comments
 (0)