spdx_tools.spdx3.bump_from_spdx2.relationship
1# SPDX-FileCopyrightText: 2023 spdx contributors 2# 3# SPDX-License-Identifier: Apache-2.0 4import logging 5import sys 6 7from beartype.typing import Dict, List, Optional, Tuple, Union 8 9from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion 10from spdx_tools.spdx3.model import LifecycleScopeType, Relationship, RelationshipCompleteness, RelationshipType 11from spdx_tools.spdx3.model.software import ( 12 DependencyConditionalityType, 13 SoftwareDependencyLinkType, 14 SoftwareDependencyRelationship, 15) 16from spdx_tools.spdx3.payload import Payload 17from spdx_tools.spdx.model.relationship import Relationship as Spdx2_Relationship 18from spdx_tools.spdx.model.relationship import RelationshipType as Spdx2_RelationshipType 19from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion 20from spdx_tools.spdx.model.spdx_none import SpdxNone 21 22# bump relationship type, map each relationship type to the corresponding class in 3.0, 23# the relationship type, other arguments and if swapped 24relationship_mapping: Dict[ 25 Spdx2_RelationshipType, 26 Tuple[ 27 Union[Relationship, SoftwareDependencyRelationship], 28 RelationshipType, 29 Dict[str, Union[bool, LifecycleScopeType, SoftwareDependencyLinkType, DependencyConditionalityType]], 30 ], 31] = { 32 Spdx2_RelationshipType.AMENDS: (Relationship, RelationshipType.AMENDS, {}), 33 Spdx2_RelationshipType.ANCESTOR_OF: (Relationship, RelationshipType.ANCESTOR, {}), 34 Spdx2_RelationshipType.BUILD_DEPENDENCY_OF: ( 35 SoftwareDependencyRelationship, 36 RelationshipType.DEPENDS_ON, 37 { 38 "scope": LifecycleScopeType.BUILD, 39 "linkage": SoftwareDependencyLinkType.TOOL, 40 }, 41 ), 42 Spdx2_RelationshipType.BUILD_TOOL_OF: ( 43 SoftwareDependencyRelationship, 44 RelationshipType.DEPENDS_ON, 45 {"scope": LifecycleScopeType.BUILD, "linkage": SoftwareDependencyLinkType.TOOL}, 46 ), 47 Spdx2_RelationshipType.CONTAINED_BY: (Relationship, RelationshipType.CONTAINS, {"swap": True}), 48 Spdx2_RelationshipType.CONTAINS: ( 49 Relationship, 50 RelationshipType.CONTAINS, 51 {}, 52 ), # might be deleted in favor of depends on 53 Spdx2_RelationshipType.COPY_OF: (Relationship, RelationshipType.COPY, {}), 54 Spdx2_RelationshipType.DATA_FILE_OF: (None, None, {}), # not defined, probably input/ output 55 Spdx2_RelationshipType.DEPENDENCY_MANIFEST_OF: ( 56 SoftwareDependencyRelationship, 57 RelationshipType.DEPENDS_ON, 58 {}, 59 ), # "expect purpose has been set to manifest" 60 Spdx2_RelationshipType.DEPENDENCY_OF: ( 61 SoftwareDependencyRelationship, 62 RelationshipType.DEPENDS_ON, 63 {"swap": True}, 64 ), 65 Spdx2_RelationshipType.DEPENDS_ON: (SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, {}), 66 Spdx2_RelationshipType.DESCENDANT_OF: (Relationship, RelationshipType.ANCESTOR, {"swap": True}), 67 Spdx2_RelationshipType.DESCRIBED_BY: (Relationship, RelationshipType.DESCRIBES, {"swap": True}), 68 Spdx2_RelationshipType.DESCRIBES: ( 69 Relationship, 70 RelationshipType.DESCRIBES, 71 {}, 72 ), # might be deleted in favor of root 73 # property 74 Spdx2_RelationshipType.DEV_DEPENDENCY_OF: ( 75 SoftwareDependencyRelationship, 76 RelationshipType.DEPENDS_ON, 77 {"scope": LifecycleScopeType.DEVELOPMENT}, 78 ), 79 Spdx2_RelationshipType.DEV_TOOL_OF: ( 80 SoftwareDependencyRelationship, 81 RelationshipType.DEPENDS_ON, 82 {"scope": LifecycleScopeType.DEVELOPMENT, "linkage": SoftwareDependencyLinkType.TOOL}, 83 ), 84 Spdx2_RelationshipType.DISTRIBUTION_ARTIFACT: (None, None, {}), # not defined yet, purpose? 85 Spdx2_RelationshipType.DOCUMENTATION_OF: (Relationship, RelationshipType.DOCUMENTATION, {}), 86 Spdx2_RelationshipType.DYNAMIC_LINK: ( 87 SoftwareDependencyRelationship, 88 RelationshipType.DEPENDS_ON, 89 {"linkage": SoftwareDependencyLinkType.DYNAMIC}, 90 ), 91 Spdx2_RelationshipType.EXAMPLE_OF: (Relationship, RelationshipType.EXAMPLE, {}), 92 Spdx2_RelationshipType.EXPANDED_FROM_ARCHIVE: (Relationship, RelationshipType.EXPANDED_FROM_ARCHIVE, {}), 93 Spdx2_RelationshipType.FILE_ADDED: (Relationship, RelationshipType.FILE_ADDED, {}), 94 Spdx2_RelationshipType.FILE_DELETED: (Relationship, RelationshipType.FILE_DELETED, {}), 95 Spdx2_RelationshipType.FILE_MODIFIED: (Relationship, RelationshipType.FILE_MODIFIED, {}), 96 Spdx2_RelationshipType.GENERATED_FROM: (Relationship, RelationshipType.GENERATES, {"swap": True}), 97 Spdx2_RelationshipType.GENERATES: (Relationship, RelationshipType.GENERATES, {}), 98 Spdx2_RelationshipType.HAS_PREREQUISITE: ( 99 SoftwareDependencyRelationship, 100 RelationshipType.DEPENDS_ON, 101 {"conditionality": DependencyConditionalityType.PREREQUISITE}, 102 ), 103 Spdx2_RelationshipType.METAFILE_OF: (Relationship, RelationshipType.METAFILE, {}), 104 Spdx2_RelationshipType.OPTIONAL_COMPONENT_OF: (None, None, {}), # converted to depends on and purpose? not clear 105 Spdx2_RelationshipType.OPTIONAL_DEPENDENCY_OF: ( 106 SoftwareDependencyRelationship, 107 RelationshipType.DEPENDS_ON, 108 {"conditionality": DependencyConditionalityType.OPTIONAL}, 109 ), 110 Spdx2_RelationshipType.OTHER: (Relationship, RelationshipType.OTHER, {}), 111 Spdx2_RelationshipType.PACKAGE_OF: (SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, {}), 112 Spdx2_RelationshipType.PATCH_APPLIED: (Relationship, RelationshipType.PATCH, {"swap": True}), 113 Spdx2_RelationshipType.PATCH_FOR: (Relationship, RelationshipType.PATCH, {}), 114 Spdx2_RelationshipType.PREREQUISITE_FOR: ( 115 SoftwareDependencyRelationship, 116 RelationshipType.DEPENDS_ON, 117 {"conditionality": DependencyConditionalityType.PREREQUISITE}, 118 ), 119 Spdx2_RelationshipType.PROVIDED_DEPENDENCY_OF: ( 120 SoftwareDependencyRelationship, 121 RelationshipType.DEPENDS_ON, 122 {"scope": LifecycleScopeType.BUILD, "conditionality": DependencyConditionalityType.PROVIDED}, 123 ), 124 Spdx2_RelationshipType.RUNTIME_DEPENDENCY_OF: ( 125 SoftwareDependencyRelationship, 126 RelationshipType.DEPENDS_ON, 127 {"scope": LifecycleScopeType.RUNTIME}, 128 ), 129 Spdx2_RelationshipType.STATIC_LINK: ( 130 SoftwareDependencyRelationship, 131 RelationshipType.DEPENDS_ON, 132 {"linkage": SoftwareDependencyLinkType.STATIC}, 133 ), 134 Spdx2_RelationshipType.TEST_CASE_OF: (Relationship, RelationshipType.TEST_CASE, {}), 135 Spdx2_RelationshipType.TEST_DEPENDENCY_OF: ( 136 SoftwareDependencyRelationship, 137 RelationshipType.DEPENDS_ON, 138 {"scope": LifecycleScopeType.TEST}, 139 ), 140 Spdx2_RelationshipType.TEST_OF: (Relationship, RelationshipType.TEST, {}), 141 Spdx2_RelationshipType.TEST_TOOL_OF: ( 142 SoftwareDependencyRelationship, 143 RelationshipType.DEPENDS_ON, 144 {"scope": LifecycleScopeType.TEST, "linkage": SoftwareDependencyLinkType.TOOL}, 145 ), 146 Spdx2_RelationshipType.VARIANT_OF: (Relationship, RelationshipType.VARIANT, {}), 147 Spdx2_RelationshipType.REQUIREMENT_DESCRIPTION_FOR: (Relationship, RelationshipType.REQUIREMENT_FOR, {}), 148 Spdx2_RelationshipType.SPECIFICATION_FOR: (Relationship, RelationshipType.SPECIFICATION_FOR, {}), 149} 150 151 152def bump_relationships( 153 spdx2_relationships: List[Spdx2_Relationship], 154 payload: Payload, 155 document_namespace: str, 156): 157 generated_relationships: Dict[Tuple[str, str], List[Relationship]] = {} 158 for counter, spdx2_relationship in enumerate(spdx2_relationships): 159 relationship = bump_relationship(spdx2_relationship, document_namespace, counter) 160 if relationship: 161 generated_relationships.setdefault( 162 (relationship.from_element, relationship.relationship_type.name), [] 163 ).append(relationship) 164 165 for relationships in generated_relationships.values(): 166 if len(relationships) > 1: 167 _merge_relationships_and_add_to_payload(relationships, payload) 168 else: 169 payload.add_element(relationships[0]) 170 171 172def bump_relationship( 173 spdx2_relationship: Spdx2_Relationship, 174 document_namespace: str, 175 counter: int, 176) -> Optional[Union[Relationship, SoftwareDependencyRelationship]]: 177 completeness, to = determine_completeness_and_to(spdx2_relationship.related_spdx_element_id) 178 spdx_id = "#".join([document_namespace, f"SPDXRef-Relationship-{counter}"]) 179 relationship_class, relationship_type, parameters = relationship_mapping[spdx2_relationship.relationship_type] 180 if relationship_class is None: 181 print_missing_conversion(spdx2_relationship.relationship_type.name, 0) 182 return 183 184 swap_direction = parameters.get("swap", False) 185 186 if swap_direction: 187 if not to: 188 print_missing_conversion("Swapped Relationship to NoAssertion/None", 0) 189 return 190 from_element = to[0] 191 to = [spdx2_relationship.spdx_element_id] 192 else: 193 from_element = spdx2_relationship.spdx_element_id 194 195 if relationship_class == SoftwareDependencyRelationship: 196 from_element = spdx2_relationship.spdx_element_id 197 198 return SoftwareDependencyRelationship( 199 spdx_id, 200 f"{document_namespace}#{from_element}", 201 relationship_type, 202 [f"{document_namespace}#{t}" for t in to], 203 comment=spdx2_relationship.comment, 204 completeness=completeness, 205 scope=parameters.get("scope"), 206 software_linkage=parameters.get("linkage"), 207 conditionality=parameters.get("conditionality"), 208 ) 209 210 return Relationship( 211 spdx_id, 212 f"{document_namespace}#{from_element}", 213 relationship_type, 214 [f"{document_namespace}#{t}" for t in to], 215 comment=spdx2_relationship.comment, 216 completeness=completeness, 217 ) 218 219 220def determine_completeness_and_to( 221 related_spdx_element_id: Union[str, SpdxNone, SpdxNoAssertion] 222) -> Tuple[Optional[RelationshipCompleteness], List[str]]: 223 if isinstance(related_spdx_element_id, SpdxNoAssertion): 224 completeness = RelationshipCompleteness.NOASSERTION 225 to = [] 226 elif isinstance(related_spdx_element_id, SpdxNone): 227 completeness = RelationshipCompleteness.COMPLETE 228 to = [] 229 else: 230 completeness = None 231 to = [related_spdx_element_id] 232 return completeness, to 233 234 235def _merge_relationships_and_add_to_payload(relationships: List[Relationship], payload: Payload): 236 to = [] 237 completeness = None 238 spdx_id = None 239 merged_relationship = relationships[0] 240 for merged_relationship in relationships: 241 if merged_relationship.comment: 242 payload.add_element(merged_relationship) 243 continue 244 if merged_relationship.completeness: 245 if completeness and completeness != merged_relationship.completeness: 246 logging.warning( 247 f"Contradicting information about completeness of relationship: {merged_relationship}", sys.stderr 248 ) 249 else: 250 completeness = merged_relationship.completeness 251 252 to += merged_relationship.to 253 spdx_id = merged_relationship.spdx_id 254 if to: 255 merged_relationship.spdx_id = spdx_id 256 merged_relationship.to = to 257 merged_relationship.completeness = completeness 258 merged_relationship.comment = None 259 payload.add_element(merged_relationship)
relationship_mapping: dict[spdx_tools.spdx.model.relationship.RelationshipType, tuple[typing.Union[spdx_tools.spdx3.model.relationship.Relationship, spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship], spdx_tools.spdx3.model.relationship.RelationshipType, dict[str, typing.Union[bool, spdx_tools.spdx3.model.lifecycle_scoped_relationship.LifecycleScopeType, spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyLinkType, spdx_tools.spdx3.model.software.software_dependency_relationship.DependencyConditionalityType]]]] =
{<RelationshipType.AMENDS: 1>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.AMENDS: 2>, {}), <RelationshipType.ANCESTOR_OF: 2>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.ANCESTOR: 3>, {}), <RelationshipType.BUILD_DEPENDENCY_OF: 3>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'scope': <LifecycleScopeType.BUILD: 2>, 'linkage': <SoftwareDependencyLinkType.TOOL: 3>}), <RelationshipType.BUILD_TOOL_OF: 4>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'scope': <LifecycleScopeType.BUILD: 2>, 'linkage': <SoftwareDependencyLinkType.TOOL: 3>}), <RelationshipType.CONTAINED_BY: 5>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.CONTAINS: 8>, {'swap': True}), <RelationshipType.CONTAINS: 6>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.CONTAINS: 8>, {}), <RelationshipType.COPY_OF: 7>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.COPY: 10>, {}), <RelationshipType.DATA_FILE_OF: 8>: (None, None, {}), <RelationshipType.DEPENDENCY_MANIFEST_OF: 9>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {}), <RelationshipType.DEPENDENCY_OF: 10>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'swap': True}), <RelationshipType.DEPENDS_ON: 11>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {}), <RelationshipType.DESCENDANT_OF: 12>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.ANCESTOR: 3>, {'swap': True}), <RelationshipType.DESCRIBED_BY: 13>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.DESCRIBES: 15>, {'swap': True}), <RelationshipType.DESCRIBES: 14>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.DESCRIBES: 15>, {}), <RelationshipType.DEV_DEPENDENCY_OF: 15>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'scope': <LifecycleScopeType.DEVELOPMENT: 3>}), <RelationshipType.DEV_TOOL_OF: 16>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'scope': <LifecycleScopeType.DEVELOPMENT: 3>, 'linkage': <SoftwareDependencyLinkType.TOOL: 3>}), <RelationshipType.DISTRIBUTION_ARTIFACT: 17>: (None, None, {}), <RelationshipType.DOCUMENTATION_OF: 18>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.DOCUMENTATION: 19>, {}), <RelationshipType.DYNAMIC_LINK: 19>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'linkage': <SoftwareDependencyLinkType.DYNAMIC: 2>}), <RelationshipType.EXAMPLE_OF: 20>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.EXAMPLE: 22>, {}), <RelationshipType.EXPANDED_FROM_ARCHIVE: 21>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.EXPANDED_FROM_ARCHIVE: 24>, {}), <RelationshipType.FILE_ADDED: 22>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.FILE_ADDED: 26>, {}), <RelationshipType.FILE_DELETED: 23>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.FILE_DELETED: 27>, {}), <RelationshipType.FILE_MODIFIED: 24>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.FILE_MODIFIED: 28>, {}), <RelationshipType.GENERATED_FROM: 25>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.GENERATES: 32>, {'swap': True}), <RelationshipType.GENERATES: 26>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.GENERATES: 32>, {}), <RelationshipType.HAS_PREREQUISITE: 27>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'conditionality': <DependencyConditionalityType.PREREQUISITE: 4>}), <RelationshipType.METAFILE_OF: 28>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.METAFILE: 38>, {}), <RelationshipType.OPTIONAL_COMPONENT_OF: 29>: (None, None, {}), <RelationshipType.OPTIONAL_DEPENDENCY_OF: 30>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'conditionality': <DependencyConditionalityType.OPTIONAL: 1>}), <RelationshipType.OTHER: 31>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.OTHER: 42>, {}), <RelationshipType.PACKAGE_OF: 32>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {}), <RelationshipType.PATCH_APPLIED: 33>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.PATCH: 45>, {'swap': True}), <RelationshipType.PATCH_FOR: 34>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.PATCH: 45>, {}), <RelationshipType.PREREQUISITE_FOR: 35>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'conditionality': <DependencyConditionalityType.PREREQUISITE: 4>}), <RelationshipType.PROVIDED_DEPENDENCY_OF: 36>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'scope': <LifecycleScopeType.BUILD: 2>, 'conditionality': <DependencyConditionalityType.PROVIDED: 3>}), <RelationshipType.RUNTIME_DEPENDENCY_OF: 38>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'scope': <LifecycleScopeType.RUNTIME: 5>}), <RelationshipType.STATIC_LINK: 40>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'linkage': <SoftwareDependencyLinkType.STATIC: 1>}), <RelationshipType.TEST_CASE_OF: 41>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.TEST_CASE: 56>, {}), <RelationshipType.TEST_DEPENDENCY_OF: 42>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'scope': <LifecycleScopeType.TEST: 4>}), <RelationshipType.TEST_OF: 43>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.TEST: 55>, {}), <RelationshipType.TEST_TOOL_OF: 44>: (<class 'spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship'>, <RelationshipType.DEPENDS_ON: 13>, {'scope': <LifecycleScopeType.TEST: 4>, 'linkage': <SoftwareDependencyLinkType.TOOL: 3>}), <RelationshipType.VARIANT_OF: 45>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.VARIANT: 62>, {}), <RelationshipType.REQUIREMENT_DESCRIPTION_FOR: 37>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.REQUIREMENT_FOR: 51>, {}), <RelationshipType.SPECIFICATION_FOR: 39>: (<class 'spdx_tools.spdx3.model.relationship.Relationship'>, <RelationshipType.SPECIFICATION_FOR: 53>, {})}
def
bump_relationships( spdx2_relationships: list[spdx_tools.spdx.model.relationship.Relationship], payload: spdx_tools.spdx3.payload.Payload, document_namespace: str):
153def bump_relationships( 154 spdx2_relationships: List[Spdx2_Relationship], 155 payload: Payload, 156 document_namespace: str, 157): 158 generated_relationships: Dict[Tuple[str, str], List[Relationship]] = {} 159 for counter, spdx2_relationship in enumerate(spdx2_relationships): 160 relationship = bump_relationship(spdx2_relationship, document_namespace, counter) 161 if relationship: 162 generated_relationships.setdefault( 163 (relationship.from_element, relationship.relationship_type.name), [] 164 ).append(relationship) 165 166 for relationships in generated_relationships.values(): 167 if len(relationships) > 1: 168 _merge_relationships_and_add_to_payload(relationships, payload) 169 else: 170 payload.add_element(relationships[0])
def
bump_relationship( spdx2_relationship: spdx_tools.spdx.model.relationship.Relationship, document_namespace: str, counter: int) -> Union[spdx_tools.spdx3.model.relationship.Relationship, spdx_tools.spdx3.model.software.software_dependency_relationship.SoftwareDependencyRelationship, NoneType]:
173def bump_relationship( 174 spdx2_relationship: Spdx2_Relationship, 175 document_namespace: str, 176 counter: int, 177) -> Optional[Union[Relationship, SoftwareDependencyRelationship]]: 178 completeness, to = determine_completeness_and_to(spdx2_relationship.related_spdx_element_id) 179 spdx_id = "#".join([document_namespace, f"SPDXRef-Relationship-{counter}"]) 180 relationship_class, relationship_type, parameters = relationship_mapping[spdx2_relationship.relationship_type] 181 if relationship_class is None: 182 print_missing_conversion(spdx2_relationship.relationship_type.name, 0) 183 return 184 185 swap_direction = parameters.get("swap", False) 186 187 if swap_direction: 188 if not to: 189 print_missing_conversion("Swapped Relationship to NoAssertion/None", 0) 190 return 191 from_element = to[0] 192 to = [spdx2_relationship.spdx_element_id] 193 else: 194 from_element = spdx2_relationship.spdx_element_id 195 196 if relationship_class == SoftwareDependencyRelationship: 197 from_element = spdx2_relationship.spdx_element_id 198 199 return SoftwareDependencyRelationship( 200 spdx_id, 201 f"{document_namespace}#{from_element}", 202 relationship_type, 203 [f"{document_namespace}#{t}" for t in to], 204 comment=spdx2_relationship.comment, 205 completeness=completeness, 206 scope=parameters.get("scope"), 207 software_linkage=parameters.get("linkage"), 208 conditionality=parameters.get("conditionality"), 209 ) 210 211 return Relationship( 212 spdx_id, 213 f"{document_namespace}#{from_element}", 214 relationship_type, 215 [f"{document_namespace}#{t}" for t in to], 216 comment=spdx2_relationship.comment, 217 completeness=completeness, 218 )
def
determine_completeness_and_to( related_spdx_element_id: Union[str, spdx_tools.spdx.model.spdx_none.SpdxNone, spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion]) -> tuple[typing.Optional[spdx_tools.spdx3.model.relationship.RelationshipCompleteness], list[str]]:
221def determine_completeness_and_to( 222 related_spdx_element_id: Union[str, SpdxNone, SpdxNoAssertion] 223) -> Tuple[Optional[RelationshipCompleteness], List[str]]: 224 if isinstance(related_spdx_element_id, SpdxNoAssertion): 225 completeness = RelationshipCompleteness.NOASSERTION 226 to = [] 227 elif isinstance(related_spdx_element_id, SpdxNone): 228 completeness = RelationshipCompleteness.COMPLETE 229 to = [] 230 else: 231 completeness = None 232 to = [related_spdx_element_id] 233 return completeness, to