spdx_tools.spdx.parser.tagvalue.helper_methods
1# SPDX-FileCopyrightText: 2023 spdx contributors 2# 3# SPDX-License-Identifier: Apache-2.0 4import re 5 6from beartype.typing import Any, Callable, Dict, Optional 7from ply.yacc import YaccProduction 8 9from spdx_tools.spdx.casing_tools import camel_case_to_snake_case 10from spdx_tools.spdx.model import ( 11 Annotation, 12 Checksum, 13 ChecksumAlgorithm, 14 CreationInfo, 15 ExtractedLicensingInfo, 16 File, 17 Package, 18 Snippet, 19) 20from spdx_tools.spdx.parser.error import SPDXParsingError 21 22 23def grammar_rule(doc): 24 # this is a helper method to use decorators for the parsing methods instead of docstrings 25 def decorate(func): 26 func.__doc__ = doc 27 return func 28 29 return decorate 30 31 32def str_from_text(text: Optional[str]) -> Optional[str]: 33 regex = re.compile("<text>((.|\n)+)</text>", re.UNICODE) 34 match = regex.match(text) 35 if match: 36 return match.group(1) 37 elif isinstance(text, str): 38 return text 39 else: 40 return None 41 42 43def parse_checksum(checksum_str: str) -> Checksum: 44 # The lexer and the corresponding regex for the token CHECKSUM and EXT_DOC_REF_CHECKSUM ensure that the passed 45 # checksum_str is formatted in the way that the following lines of code can't cause an error. 46 algorithm, value = checksum_str.split(":") 47 algorithm = ChecksumAlgorithm[algorithm.upper().replace("-", "_")] 48 value = value.strip() 49 checksum = Checksum(algorithm, value) 50 return checksum 51 52 53def set_value( 54 parsed_value: YaccProduction, 55 dict_to_fill: Dict[str, Any], 56 argument_name: Optional[str] = None, 57 method_to_apply: Callable = lambda x: x, 58): 59 if not argument_name: 60 argument_name = get_property_name(parsed_value[1]) 61 if argument_name in dict_to_fill: 62 dict_to_fill["logger"].append(f"Multiple values for {parsed_value[1]} found. Line: {parsed_value.lineno(1)}") 63 return 64 try: 65 dict_to_fill[argument_name] = method_to_apply(parsed_value[2]) 66 except SPDXParsingError as err: 67 dict_to_fill["logger"].append(err.get_messages()) 68 except ValueError as err: 69 dict_to_fill["logger"].append(err.args[0]) 70 except KeyError: 71 dict_to_fill["logger"].append(f"Invalid {parsed_value[1]}: {parsed_value[2]}. Line: {parsed_value.lineno(1)}") 72 73 74def get_property_name(tag: str): 75 if tag not in TAG_DATA_MODEL_FIELD.keys(): 76 return camel_case_to_snake_case(tag) 77 return TAG_DATA_MODEL_FIELD[tag][1] 78 79 80# This dictionary serves as a mapping from a tag to the corresponding class and field in the internal data model. 81# This mapping is not complete as we only list the values which can be parsed by a generic method and don't need any 82# individual logic. 83TAG_DATA_MODEL_FIELD = { 84 "SPDXVersion": (CreationInfo, "spdx_version"), 85 "DataLicense": (CreationInfo, "data_license"), 86 "DocumentName": (CreationInfo, "name"), 87 "DocumentComment": (CreationInfo, "document_comment"), 88 "DocumentNamespace": (CreationInfo, "document_namespace"), 89 "Creator": (CreationInfo, "creator"), 90 "Created": (CreationInfo, "created"), 91 "CreatorComment": (CreationInfo, "creator_comment"), 92 "LicenseListVersion": (CreationInfo, "license_list_version"), 93 "ExternalDocumentRef": (CreationInfo, "external_document_refs"), 94 "FileName": (File, "name"), 95 "FileType": (File, "file_type"), 96 "FileChecksum": (File, "checksums"), 97 "FileNotice": (File, "notice"), 98 "FileCopyrightText": (File, "copyright_text"), 99 "LicenseComments": (File, "license_comment"), 100 "FileComment": (File, "comment"), 101 "LicenseConcluded": (File, "license_concluded"), 102 "LicenseDeclared": (File, "license_declared"), 103 "PackageName": (Package, "name"), 104 "PackageComment": (Package, "comment"), 105 "PackageCopyrightText": (Package, "copyright_text"), 106 "PackageLicenseComments": (Package, "license_comment"), 107 "PackageLicenseDeclared": (Package, "license_declared"), 108 "PackageLicenseConcluded": (Package, "license_concluded"), 109 "PackageFileName": (Package, "file_name"), 110 "PackageVersion": (Package, "version"), 111 "PackageDownloadLocation": (Package, "download_location"), 112 "PackageSummary": (Package, "summary"), 113 "PackageSourceInfo": (Package, "source_info"), 114 "PackageSupplier": (Package, "supplier"), 115 "PackageOriginator": (Package, "originator"), 116 "PackageDescription": (Package, "description"), 117 "PackageHomePage": (Package, "homepage"), 118 "SnippetSPDXID": (Snippet, "spdx_id"), 119 "SnippetFromFileSPDXID": (Snippet, "file_spdx_id"), 120 "SnippetName": (Snippet, "name"), 121 "SnippetComment": (Snippet, "comment"), 122 "SnippetCopyrightText": (Snippet, "copyright_text"), 123 "SnippetLicenseComments": (Snippet, "license_comment"), 124 "SnippetLicenseConcluded": (Snippet, "license_concluded"), 125 "SnippetByteRange": (Snippet, "byte_range"), 126 "SnippetLineRange": (Snippet, "line_range"), 127 "Annotator": (Annotation, "annotator"), 128 "SPDXREF": (Annotation, "spdx_id"), 129 "AnnotationComment": (Annotation, "annotation_comment"), 130 "LicenseID": (ExtractedLicensingInfo, "license_id"), 131 "ExtractedText": (ExtractedLicensingInfo, "extracted_text"), 132 "LicenseComment": (ExtractedLicensingInfo, "comment"), 133 "LicenseName": (ExtractedLicensingInfo, "license_name"), 134}
def
grammar_rule(doc):
def
str_from_text(text: Optional[str]) -> Optional[str]:
44def parse_checksum(checksum_str: str) -> Checksum: 45 # The lexer and the corresponding regex for the token CHECKSUM and EXT_DOC_REF_CHECKSUM ensure that the passed 46 # checksum_str is formatted in the way that the following lines of code can't cause an error. 47 algorithm, value = checksum_str.split(":") 48 algorithm = ChecksumAlgorithm[algorithm.upper().replace("-", "_")] 49 value = value.strip() 50 checksum = Checksum(algorithm, value) 51 return checksum
def
set_value( parsed_value: ply.yacc.YaccProduction, dict_to_fill: dict[str, typing.Any], argument_name: Optional[str] = None, method_to_apply: Callable = <function <lambda>>):
54def set_value( 55 parsed_value: YaccProduction, 56 dict_to_fill: Dict[str, Any], 57 argument_name: Optional[str] = None, 58 method_to_apply: Callable = lambda x: x, 59): 60 if not argument_name: 61 argument_name = get_property_name(parsed_value[1]) 62 if argument_name in dict_to_fill: 63 dict_to_fill["logger"].append(f"Multiple values for {parsed_value[1]} found. Line: {parsed_value.lineno(1)}") 64 return 65 try: 66 dict_to_fill[argument_name] = method_to_apply(parsed_value[2]) 67 except SPDXParsingError as err: 68 dict_to_fill["logger"].append(err.get_messages()) 69 except ValueError as err: 70 dict_to_fill["logger"].append(err.args[0]) 71 except KeyError: 72 dict_to_fill["logger"].append(f"Invalid {parsed_value[1]}: {parsed_value[2]}. Line: {parsed_value.lineno(1)}")
def
get_property_name(tag: str):
TAG_DATA_MODEL_FIELD =
{'SPDXVersion': (<class 'spdx_tools.spdx.model.document.CreationInfo'>, 'spdx_version'), 'DataLicense': (<class 'spdx_tools.spdx.model.document.CreationInfo'>, 'data_license'), 'DocumentName': (<class 'spdx_tools.spdx.model.document.CreationInfo'>, 'name'), 'DocumentComment': (<class 'spdx_tools.spdx.model.document.CreationInfo'>, 'document_comment'), 'DocumentNamespace': (<class 'spdx_tools.spdx.model.document.CreationInfo'>, 'document_namespace'), 'Creator': (<class 'spdx_tools.spdx.model.document.CreationInfo'>, 'creator'), 'Created': (<class 'spdx_tools.spdx.model.document.CreationInfo'>, 'created'), 'CreatorComment': (<class 'spdx_tools.spdx.model.document.CreationInfo'>, 'creator_comment'), 'LicenseListVersion': (<class 'spdx_tools.spdx.model.document.CreationInfo'>, 'license_list_version'), 'ExternalDocumentRef': (<class 'spdx_tools.spdx.model.document.CreationInfo'>, 'external_document_refs'), 'FileName': (<class 'spdx_tools.spdx.model.file.File'>, 'name'), 'FileType': (<class 'spdx_tools.spdx.model.file.File'>, 'file_type'), 'FileChecksum': (<class 'spdx_tools.spdx.model.file.File'>, 'checksums'), 'FileNotice': (<class 'spdx_tools.spdx.model.file.File'>, 'notice'), 'FileCopyrightText': (<class 'spdx_tools.spdx.model.file.File'>, 'copyright_text'), 'LicenseComments': (<class 'spdx_tools.spdx.model.file.File'>, 'license_comment'), 'FileComment': (<class 'spdx_tools.spdx.model.file.File'>, 'comment'), 'LicenseConcluded': (<class 'spdx_tools.spdx.model.file.File'>, 'license_concluded'), 'LicenseDeclared': (<class 'spdx_tools.spdx.model.file.File'>, 'license_declared'), 'PackageName': (<class 'spdx_tools.spdx.model.package.Package'>, 'name'), 'PackageComment': (<class 'spdx_tools.spdx.model.package.Package'>, 'comment'), 'PackageCopyrightText': (<class 'spdx_tools.spdx.model.package.Package'>, 'copyright_text'), 'PackageLicenseComments': (<class 'spdx_tools.spdx.model.package.Package'>, 'license_comment'), 'PackageLicenseDeclared': (<class 'spdx_tools.spdx.model.package.Package'>, 'license_declared'), 'PackageLicenseConcluded': (<class 'spdx_tools.spdx.model.package.Package'>, 'license_concluded'), 'PackageFileName': (<class 'spdx_tools.spdx.model.package.Package'>, 'file_name'), 'PackageVersion': (<class 'spdx_tools.spdx.model.package.Package'>, 'version'), 'PackageDownloadLocation': (<class 'spdx_tools.spdx.model.package.Package'>, 'download_location'), 'PackageSummary': (<class 'spdx_tools.spdx.model.package.Package'>, 'summary'), 'PackageSourceInfo': (<class 'spdx_tools.spdx.model.package.Package'>, 'source_info'), 'PackageSupplier': (<class 'spdx_tools.spdx.model.package.Package'>, 'supplier'), 'PackageOriginator': (<class 'spdx_tools.spdx.model.package.Package'>, 'originator'), 'PackageDescription': (<class 'spdx_tools.spdx.model.package.Package'>, 'description'), 'PackageHomePage': (<class 'spdx_tools.spdx.model.package.Package'>, 'homepage'), 'SnippetSPDXID': (<class 'spdx_tools.spdx.model.snippet.Snippet'>, 'spdx_id'), 'SnippetFromFileSPDXID': (<class 'spdx_tools.spdx.model.snippet.Snippet'>, 'file_spdx_id'), 'SnippetName': (<class 'spdx_tools.spdx.model.snippet.Snippet'>, 'name'), 'SnippetComment': (<class 'spdx_tools.spdx.model.snippet.Snippet'>, 'comment'), 'SnippetCopyrightText': (<class 'spdx_tools.spdx.model.snippet.Snippet'>, 'copyright_text'), 'SnippetLicenseComments': (<class 'spdx_tools.spdx.model.snippet.Snippet'>, 'license_comment'), 'SnippetLicenseConcluded': (<class 'spdx_tools.spdx.model.snippet.Snippet'>, 'license_concluded'), 'SnippetByteRange': (<class 'spdx_tools.spdx.model.snippet.Snippet'>, 'byte_range'), 'SnippetLineRange': (<class 'spdx_tools.spdx.model.snippet.Snippet'>, 'line_range'), 'Annotator': (<class 'spdx_tools.spdx.model.annotation.Annotation'>, 'annotator'), 'SPDXREF': (<class 'spdx_tools.spdx.model.annotation.Annotation'>, 'spdx_id'), 'AnnotationComment': (<class 'spdx_tools.spdx.model.annotation.Annotation'>, 'annotation_comment'), 'LicenseID': (<class 'spdx_tools.spdx.model.extracted_licensing_info.ExtractedLicensingInfo'>, 'license_id'), 'ExtractedText': (<class 'spdx_tools.spdx.model.extracted_licensing_info.ExtractedLicensingInfo'>, 'extracted_text'), 'LicenseComment': (<class 'spdx_tools.spdx.model.extracted_licensing_info.ExtractedLicensingInfo'>, 'comment'), 'LicenseName': (<class 'spdx_tools.spdx.model.extracted_licensing_info.ExtractedLicensingInfo'>, 'license_name')}