spdx_tools.spdx.parser.jsonlikedict.annotation_parser

  1# SPDX-FileCopyrightText: 2022 spdx contributors
  2#
  3# SPDX-License-Identifier: Apache-2.0
  4from datetime import datetime
  5
  6from beartype.typing import Dict, List, Optional
  7
  8from spdx_tools.spdx.datetime_conversions import datetime_from_str
  9from spdx_tools.spdx.model import Actor, Annotation, AnnotationType
 10from spdx_tools.spdx.parser.actor_parser import ActorParser
 11from spdx_tools.spdx.parser.error import SPDXParsingError
 12from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import (
 13    append_parsed_field_or_log_error,
 14    parse_field_or_log_error,
 15)
 16from spdx_tools.spdx.parser.logger import Logger
 17from spdx_tools.spdx.parser.parsing_functions import (
 18    construct_or_raise_parsing_error,
 19    raise_parsing_error_if_logger_has_messages,
 20)
 21
 22
 23class AnnotationParser:
 24    logger: Logger
 25    actor_parser: ActorParser
 26
 27    def __init__(self):
 28        self.logger = Logger()
 29        self.actor_parser = ActorParser()
 30
 31    def parse_all_annotations(self, input_doc_dict: Dict) -> List[Annotation]:
 32        annotations = []
 33        self.parse_annotations_from_object(annotations, [input_doc_dict])
 34        reviews: List[Dict] = input_doc_dict.get("revieweds", [])
 35        for review in reviews:
 36            annotations = append_parsed_field_or_log_error(
 37                self.logger, annotations, review, lambda x: self.parse_review(x, spdx_id=input_doc_dict.get("SPDXID"))
 38            )
 39        packages: List[Dict] = input_doc_dict.get("packages", [])
 40        self.parse_annotations_from_object(annotations, packages)
 41        files: List[Dict] = input_doc_dict.get("files", [])
 42        self.parse_annotations_from_object(annotations, files)
 43        snippets: List[Dict] = input_doc_dict.get("snippets", [])
 44        self.parse_annotations_from_object(annotations, snippets)
 45
 46        raise_parsing_error_if_logger_has_messages(self.logger, "annotations")
 47        return annotations
 48
 49    def parse_annotations_from_object(self, annotations: List[Annotation], element_list: List[Dict]):
 50        for element in element_list:
 51            element_spdx_id: Optional[str] = element.get("SPDXID")
 52            element_annotations: List[Dict] = element.get("annotations", [])
 53            annotations.extend(
 54                parse_field_or_log_error(
 55                    self.logger,
 56                    element_annotations,
 57                    lambda y: self.parse_annotation(y, spdx_id=element_spdx_id),
 58                    [],
 59                    True,
 60                )
 61            )
 62
 63    def parse_annotation(self, annotation_dict: Dict, spdx_id: Optional[str] = None) -> Annotation:
 64        logger = Logger()
 65        spdx_id: Optional[str] = annotation_dict.get("SPDXID") or spdx_id
 66
 67        annotation_type: Optional[AnnotationType] = parse_field_or_log_error(
 68            logger, annotation_dict.get("annotationType"), self.parse_annotation_type
 69        )
 70
 71        annotator: Optional[Actor] = parse_field_or_log_error(
 72            logger, annotation_dict.get("annotator"), self.actor_parser.parse_actor
 73        )
 74
 75        annotation_date: Optional[datetime] = parse_field_or_log_error(
 76            logger, annotation_dict.get("annotationDate"), datetime_from_str
 77        )
 78
 79        annotation_comment: Optional[str] = annotation_dict.get("comment")
 80        raise_parsing_error_if_logger_has_messages(logger, "Annotation")
 81        annotation_dict = construct_or_raise_parsing_error(
 82            Annotation,
 83            dict(
 84                spdx_id=spdx_id,
 85                annotation_type=annotation_type,
 86                annotator=annotator,
 87                annotation_date=annotation_date,
 88                annotation_comment=annotation_comment,
 89            ),
 90        )
 91
 92        return annotation_dict
 93
 94    @staticmethod
 95    def parse_annotation_type(annotation_type: str) -> AnnotationType:
 96        try:
 97            return AnnotationType[annotation_type]
 98        except KeyError:
 99            raise SPDXParsingError([f"Invalid AnnotationType: {annotation_type}"])
100
101    def parse_review(self, review_dict: Dict, spdx_id: str) -> Annotation:
102        logger = Logger()
103        annotator: Optional[Actor] = parse_field_or_log_error(
104            logger, review_dict.get("reviewer"), self.actor_parser.parse_actor
105        )
106
107        annotation_date: Optional[datetime] = parse_field_or_log_error(
108            logger, review_dict.get("reviewDate"), datetime_from_str
109        )
110
111        annotation_type = AnnotationType.REVIEW
112        comment: Optional[str] = review_dict.get("comment")
113        raise_parsing_error_if_logger_has_messages(logger, "Annotation from revieweds")
114
115        annotation = construct_or_raise_parsing_error(
116            Annotation,
117            dict(
118                spdx_id=spdx_id,
119                annotation_type=annotation_type,
120                annotator=annotator,
121                annotation_date=annotation_date,
122                annotation_comment=comment,
123            ),
124        )
125        return annotation
class AnnotationParser:
 24class AnnotationParser:
 25    logger: Logger
 26    actor_parser: ActorParser
 27
 28    def __init__(self):
 29        self.logger = Logger()
 30        self.actor_parser = ActorParser()
 31
 32    def parse_all_annotations(self, input_doc_dict: Dict) -> List[Annotation]:
 33        annotations = []
 34        self.parse_annotations_from_object(annotations, [input_doc_dict])
 35        reviews: List[Dict] = input_doc_dict.get("revieweds", [])
 36        for review in reviews:
 37            annotations = append_parsed_field_or_log_error(
 38                self.logger, annotations, review, lambda x: self.parse_review(x, spdx_id=input_doc_dict.get("SPDXID"))
 39            )
 40        packages: List[Dict] = input_doc_dict.get("packages", [])
 41        self.parse_annotations_from_object(annotations, packages)
 42        files: List[Dict] = input_doc_dict.get("files", [])
 43        self.parse_annotations_from_object(annotations, files)
 44        snippets: List[Dict] = input_doc_dict.get("snippets", [])
 45        self.parse_annotations_from_object(annotations, snippets)
 46
 47        raise_parsing_error_if_logger_has_messages(self.logger, "annotations")
 48        return annotations
 49
 50    def parse_annotations_from_object(self, annotations: List[Annotation], element_list: List[Dict]):
 51        for element in element_list:
 52            element_spdx_id: Optional[str] = element.get("SPDXID")
 53            element_annotations: List[Dict] = element.get("annotations", [])
 54            annotations.extend(
 55                parse_field_or_log_error(
 56                    self.logger,
 57                    element_annotations,
 58                    lambda y: self.parse_annotation(y, spdx_id=element_spdx_id),
 59                    [],
 60                    True,
 61                )
 62            )
 63
 64    def parse_annotation(self, annotation_dict: Dict, spdx_id: Optional[str] = None) -> Annotation:
 65        logger = Logger()
 66        spdx_id: Optional[str] = annotation_dict.get("SPDXID") or spdx_id
 67
 68        annotation_type: Optional[AnnotationType] = parse_field_or_log_error(
 69            logger, annotation_dict.get("annotationType"), self.parse_annotation_type
 70        )
 71
 72        annotator: Optional[Actor] = parse_field_or_log_error(
 73            logger, annotation_dict.get("annotator"), self.actor_parser.parse_actor
 74        )
 75
 76        annotation_date: Optional[datetime] = parse_field_or_log_error(
 77            logger, annotation_dict.get("annotationDate"), datetime_from_str
 78        )
 79
 80        annotation_comment: Optional[str] = annotation_dict.get("comment")
 81        raise_parsing_error_if_logger_has_messages(logger, "Annotation")
 82        annotation_dict = construct_or_raise_parsing_error(
 83            Annotation,
 84            dict(
 85                spdx_id=spdx_id,
 86                annotation_type=annotation_type,
 87                annotator=annotator,
 88                annotation_date=annotation_date,
 89                annotation_comment=annotation_comment,
 90            ),
 91        )
 92
 93        return annotation_dict
 94
 95    @staticmethod
 96    def parse_annotation_type(annotation_type: str) -> AnnotationType:
 97        try:
 98            return AnnotationType[annotation_type]
 99        except KeyError:
100            raise SPDXParsingError([f"Invalid AnnotationType: {annotation_type}"])
101
102    def parse_review(self, review_dict: Dict, spdx_id: str) -> Annotation:
103        logger = Logger()
104        annotator: Optional[Actor] = parse_field_or_log_error(
105            logger, review_dict.get("reviewer"), self.actor_parser.parse_actor
106        )
107
108        annotation_date: Optional[datetime] = parse_field_or_log_error(
109            logger, review_dict.get("reviewDate"), datetime_from_str
110        )
111
112        annotation_type = AnnotationType.REVIEW
113        comment: Optional[str] = review_dict.get("comment")
114        raise_parsing_error_if_logger_has_messages(logger, "Annotation from revieweds")
115
116        annotation = construct_or_raise_parsing_error(
117            Annotation,
118            dict(
119                spdx_id=spdx_id,
120                annotation_type=annotation_type,
121                annotator=annotator,
122                annotation_date=annotation_date,
123                annotation_comment=comment,
124            ),
125        )
126        return annotation
def parse_all_annotations( self, input_doc_dict: dict) -> list[spdx_tools.spdx.model.annotation.Annotation]:
32    def parse_all_annotations(self, input_doc_dict: Dict) -> List[Annotation]:
33        annotations = []
34        self.parse_annotations_from_object(annotations, [input_doc_dict])
35        reviews: List[Dict] = input_doc_dict.get("revieweds", [])
36        for review in reviews:
37            annotations = append_parsed_field_or_log_error(
38                self.logger, annotations, review, lambda x: self.parse_review(x, spdx_id=input_doc_dict.get("SPDXID"))
39            )
40        packages: List[Dict] = input_doc_dict.get("packages", [])
41        self.parse_annotations_from_object(annotations, packages)
42        files: List[Dict] = input_doc_dict.get("files", [])
43        self.parse_annotations_from_object(annotations, files)
44        snippets: List[Dict] = input_doc_dict.get("snippets", [])
45        self.parse_annotations_from_object(annotations, snippets)
46
47        raise_parsing_error_if_logger_has_messages(self.logger, "annotations")
48        return annotations
def parse_annotations_from_object( self, annotations: list[spdx_tools.spdx.model.annotation.Annotation], element_list: list[dict]):
50    def parse_annotations_from_object(self, annotations: List[Annotation], element_list: List[Dict]):
51        for element in element_list:
52            element_spdx_id: Optional[str] = element.get("SPDXID")
53            element_annotations: List[Dict] = element.get("annotations", [])
54            annotations.extend(
55                parse_field_or_log_error(
56                    self.logger,
57                    element_annotations,
58                    lambda y: self.parse_annotation(y, spdx_id=element_spdx_id),
59                    [],
60                    True,
61                )
62            )
def parse_annotation( self, annotation_dict: dict, spdx_id: Optional[str] = None) -> spdx_tools.spdx.model.annotation.Annotation:
64    def parse_annotation(self, annotation_dict: Dict, spdx_id: Optional[str] = None) -> Annotation:
65        logger = Logger()
66        spdx_id: Optional[str] = annotation_dict.get("SPDXID") or spdx_id
67
68        annotation_type: Optional[AnnotationType] = parse_field_or_log_error(
69            logger, annotation_dict.get("annotationType"), self.parse_annotation_type
70        )
71
72        annotator: Optional[Actor] = parse_field_or_log_error(
73            logger, annotation_dict.get("annotator"), self.actor_parser.parse_actor
74        )
75
76        annotation_date: Optional[datetime] = parse_field_or_log_error(
77            logger, annotation_dict.get("annotationDate"), datetime_from_str
78        )
79
80        annotation_comment: Optional[str] = annotation_dict.get("comment")
81        raise_parsing_error_if_logger_has_messages(logger, "Annotation")
82        annotation_dict = construct_or_raise_parsing_error(
83            Annotation,
84            dict(
85                spdx_id=spdx_id,
86                annotation_type=annotation_type,
87                annotator=annotator,
88                annotation_date=annotation_date,
89                annotation_comment=annotation_comment,
90            ),
91        )
92
93        return annotation_dict
@staticmethod
def parse_annotation_type(annotation_type: str) -> spdx_tools.spdx.model.annotation.AnnotationType:
 95    @staticmethod
 96    def parse_annotation_type(annotation_type: str) -> AnnotationType:
 97        try:
 98            return AnnotationType[annotation_type]
 99        except KeyError:
100            raise SPDXParsingError([f"Invalid AnnotationType: {annotation_type}"])
def parse_review( self, review_dict: dict, spdx_id: str) -> spdx_tools.spdx.model.annotation.Annotation:
102    def parse_review(self, review_dict: Dict, spdx_id: str) -> Annotation:
103        logger = Logger()
104        annotator: Optional[Actor] = parse_field_or_log_error(
105            logger, review_dict.get("reviewer"), self.actor_parser.parse_actor
106        )
107
108        annotation_date: Optional[datetime] = parse_field_or_log_error(
109            logger, review_dict.get("reviewDate"), datetime_from_str
110        )
111
112        annotation_type = AnnotationType.REVIEW
113        comment: Optional[str] = review_dict.get("comment")
114        raise_parsing_error_if_logger_has_messages(logger, "Annotation from revieweds")
115
116        annotation = construct_or_raise_parsing_error(
117            Annotation,
118            dict(
119                spdx_id=spdx_id,
120                annotation_type=annotation_type,
121                annotator=annotator,
122                annotation_date=annotation_date,
123                annotation_comment=comment,
124            ),
125        )
126        return annotation