spdx_tools.spdx.spdx_element_utils
1# SPDX-FileCopyrightText: 2022 spdx contributors 2# 3# SPDX-License-Identifier: Apache-2.0 4import hashlib 5 6from beartype.typing import List, Optional, Type, Union 7 8from spdx_tools.spdx.model import ( 9 ChecksumAlgorithm, 10 Document, 11 ExternalDocumentRef, 12 File, 13 Package, 14 PackageVerificationCode, 15 Snippet, 16) 17 18 19def get_element_type_from_spdx_id( 20 spdx_id: str, document: Document 21) -> Optional[Union[Type[Package], Type[File], Type[Snippet]]]: 22 if spdx_id in [package.spdx_id for package in document.packages]: 23 return Package 24 if spdx_id in [file.spdx_id for file in document.files]: 25 return File 26 if spdx_id in [snippet.spdx_id for snippet in document.snippets]: 27 return Snippet 28 return None 29 30 31def get_full_element_spdx_id( 32 element: Union[Package, File, Snippet], 33 document_namespace: str, 34 external_document_refs: List[ExternalDocumentRef], 35) -> str: 36 """ 37 Returns the spdx_id of the element prefixed with the correct document namespace and, 38 if the element is from an external document, sets the correct entry in the imports property. 39 """ 40 if ":" not in element.spdx_id: 41 return f"{document_namespace}#{element.spdx_id}" 42 43 external_id, local_id = element.spdx_id.split(":") 44 external_uri = None 45 for entry in external_document_refs: 46 if entry.document_ref_id == external_id: 47 external_uri = entry.document_uri 48 break 49 50 if not external_uri: 51 raise ValueError(f"external id {external_id} not found in external document references") 52 53 return external_uri + "#" + local_id 54 55 56def calculate_package_verification_code(files: List[File]) -> PackageVerificationCode: 57 list_of_file_hashes = [] 58 for file in files: 59 file_checksum_value = None 60 for checksum in file.checksums: 61 if checksum.algorithm == ChecksumAlgorithm.SHA1: 62 file_checksum_value = checksum.value 63 if not file_checksum_value: 64 try: 65 file_checksum_value = calculate_file_checksum(file.name, ChecksumAlgorithm.SHA1) 66 except FileNotFoundError: 67 raise FileNotFoundError( 68 f"Cannot calculate package verification code because the file '{file.name}' " 69 f"provides no SHA1 checksum and can't be found at the specified location." 70 ) 71 list_of_file_hashes.append(file_checksum_value) 72 73 list_of_file_hashes.sort() 74 hasher = hashlib.new("sha1") 75 hasher.update("".join(list_of_file_hashes).encode("utf-8")) 76 value = hasher.hexdigest() 77 return PackageVerificationCode(value) 78 79 80def calculate_file_checksum(file_name: str, hash_algorithm=ChecksumAlgorithm.SHA1) -> str: 81 BUFFER_SIZE = 65536 82 83 file_hash = hashlib.new(hash_algorithm.name.lower()) 84 with open(file_name, "rb") as file_handle: 85 while True: 86 data = file_handle.read(BUFFER_SIZE) 87 if not data: 88 break 89 file_hash.update(data) 90 91 return file_hash.hexdigest()
def
get_element_type_from_spdx_id( spdx_id: str, document: spdx_tools.spdx.model.document.Document) -> Union[type[spdx_tools.spdx.model.package.Package], type[spdx_tools.spdx.model.file.File], type[spdx_tools.spdx.model.snippet.Snippet], NoneType]:
20def get_element_type_from_spdx_id( 21 spdx_id: str, document: Document 22) -> Optional[Union[Type[Package], Type[File], Type[Snippet]]]: 23 if spdx_id in [package.spdx_id for package in document.packages]: 24 return Package 25 if spdx_id in [file.spdx_id for file in document.files]: 26 return File 27 if spdx_id in [snippet.spdx_id for snippet in document.snippets]: 28 return Snippet 29 return None
def
get_full_element_spdx_id( element: Union[spdx_tools.spdx.model.package.Package, spdx_tools.spdx.model.file.File, spdx_tools.spdx.model.snippet.Snippet], document_namespace: str, external_document_refs: list[spdx_tools.spdx.model.external_document_ref.ExternalDocumentRef]) -> str:
32def get_full_element_spdx_id( 33 element: Union[Package, File, Snippet], 34 document_namespace: str, 35 external_document_refs: List[ExternalDocumentRef], 36) -> str: 37 """ 38 Returns the spdx_id of the element prefixed with the correct document namespace and, 39 if the element is from an external document, sets the correct entry in the imports property. 40 """ 41 if ":" not in element.spdx_id: 42 return f"{document_namespace}#{element.spdx_id}" 43 44 external_id, local_id = element.spdx_id.split(":") 45 external_uri = None 46 for entry in external_document_refs: 47 if entry.document_ref_id == external_id: 48 external_uri = entry.document_uri 49 break 50 51 if not external_uri: 52 raise ValueError(f"external id {external_id} not found in external document references") 53 54 return external_uri + "#" + local_id
Returns the spdx_id of the element prefixed with the correct document namespace and, if the element is from an external document, sets the correct entry in the imports property.
def
calculate_package_verification_code( files: list[spdx_tools.spdx.model.file.File]) -> spdx_tools.spdx.model.package.PackageVerificationCode:
57def calculate_package_verification_code(files: List[File]) -> PackageVerificationCode: 58 list_of_file_hashes = [] 59 for file in files: 60 file_checksum_value = None 61 for checksum in file.checksums: 62 if checksum.algorithm == ChecksumAlgorithm.SHA1: 63 file_checksum_value = checksum.value 64 if not file_checksum_value: 65 try: 66 file_checksum_value = calculate_file_checksum(file.name, ChecksumAlgorithm.SHA1) 67 except FileNotFoundError: 68 raise FileNotFoundError( 69 f"Cannot calculate package verification code because the file '{file.name}' " 70 f"provides no SHA1 checksum and can't be found at the specified location." 71 ) 72 list_of_file_hashes.append(file_checksum_value) 73 74 list_of_file_hashes.sort() 75 hasher = hashlib.new("sha1") 76 hasher.update("".join(list_of_file_hashes).encode("utf-8")) 77 value = hasher.hexdigest() 78 return PackageVerificationCode(value)
def
calculate_file_checksum(file_name: str, hash_algorithm=<ChecksumAlgorithm.SHA1: 1>) -> str:
81def calculate_file_checksum(file_name: str, hash_algorithm=ChecksumAlgorithm.SHA1) -> str: 82 BUFFER_SIZE = 65536 83 84 file_hash = hashlib.new(hash_algorithm.name.lower()) 85 with open(file_name, "rb") as file_handle: 86 while True: 87 data = file_handle.read(BUFFER_SIZE) 88 if not data: 89 break 90 file_hash.update(data) 91 92 return file_hash.hexdigest()