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
actor_parser: spdx_tools.spdx.parser.actor_parser.ActorParser
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:
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