spdx_tools.spdx3.bump_from_spdx2.package

  1# SPDX-FileCopyrightText: 2023 spdx contributors
  2#
  3# SPDX-License-Identifier: Apache-2.0
  4from beartype.typing import List, Optional, Union
  5
  6from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor
  7from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none
  8from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum
  9from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion
 10from spdx_tools.spdx3.model import (
 11    ExternalIdentifier,
 12    ExternalIdentifierType,
 13    ExternalMap,
 14    ExternalReference,
 15    ExternalReferenceType,
 16)
 17from spdx_tools.spdx3.model.software import Package, SoftwarePurpose
 18from spdx_tools.spdx3.payload import Payload
 19from spdx_tools.spdx.model import Actor as Spdx2_Actor
 20from spdx_tools.spdx.model import ExternalDocumentRef, SpdxNoAssertion
 21from spdx_tools.spdx.model.package import ExternalPackageRef
 22from spdx_tools.spdx.model.package import Package as Spdx2_Package
 23from spdx_tools.spdx.spdx_element_utils import get_full_element_spdx_id
 24
 25
 26def bump_package(
 27    spdx2_package: Spdx2_Package,
 28    payload: Payload,
 29    document_namespace: str,
 30    external_document_refs: List[ExternalDocumentRef],
 31    imports: List[ExternalMap],
 32):
 33    spdx_id = get_full_element_spdx_id(spdx2_package, document_namespace, external_document_refs)
 34    if ":" in spdx2_package.spdx_id:
 35        imports.append(
 36            ExternalMap(
 37                external_id=spdx2_package.spdx_id,
 38                defining_document=f"{spdx2_package.spdx_id.split(':')[0]}:SPDXRef-DOCUMENT",
 39            )
 40        )
 41
 42    download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location")
 43    print_missing_conversion("package2.file_name", 0, "https://github.com/spdx/spdx-3-model/issues/83")
 44    if isinstance(spdx2_package.supplier, Spdx2_Actor):
 45        supplied_by_spdx_id = [bump_actor(spdx2_package.supplier, payload, document_namespace)]
 46    else:
 47        supplied_by_spdx_id = None
 48    if isinstance(spdx2_package.originator, Spdx2_Actor):
 49        originated_by_spdx_id = [bump_actor(spdx2_package.originator, payload, document_namespace)]
 50    else:
 51        originated_by_spdx_id = None
 52    print_missing_conversion("package2.files_analyzed", 0, "https://github.com/spdx/spdx-3-model/issues/84")
 53    print_missing_conversion(
 54        "package2.verification_code", 1, "of IntegrityMethod, https://github.com/spdx/spdx-3-model/issues/85"
 55    )
 56    integrity_methods = [bump_checksum(checksum) for checksum in spdx2_package.checksums]
 57    copyright_text = None
 58    if isinstance(spdx2_package.copyright_text, str):
 59        copyright_text = spdx2_package.copyright_text
 60    elif isinstance(spdx2_package.copyright_text, SpdxNoAssertion):
 61        print_missing_conversion("package2.copyright_text", 0)
 62    print_missing_conversion(
 63        "package2.license_info_from_files, package2.license_comment",
 64        0,
 65        "and missing definition of license profile",
 66    )
 67
 68    external_reference = []
 69    external_identifier = []
 70    purl_refs = [
 71        external_ref for external_ref in spdx2_package.external_references if external_ref.reference_type == "purl"
 72    ]
 73    exactly_one_purl_without_comment = len(purl_refs) == 1 and purl_refs[0].comment is None
 74    package_url = None
 75    if exactly_one_purl_without_comment:
 76        package_url = purl_refs[0].locator
 77    for spdx2_external_ref in spdx2_package.external_references:
 78        if exactly_one_purl_without_comment and spdx2_external_ref.reference_type == "purl":
 79            continue
 80        id_or_ref = bump_external_package_ref(spdx2_external_ref)
 81        if isinstance(id_or_ref, ExternalReference):
 82            external_reference.append(id_or_ref)
 83        elif isinstance(id_or_ref, ExternalIdentifier):
 84            external_identifier.append(id_or_ref)
 85
 86    package_purpose = (
 87        SoftwarePurpose[spdx2_package.primary_package_purpose.name] if spdx2_package.primary_package_purpose else None
 88    )
 89
 90    payload.add_element(
 91        Package(
 92            spdx_id,
 93            spdx2_package.name,
 94            summary=spdx2_package.summary,
 95            description=spdx2_package.description,
 96            comment=spdx2_package.comment,
 97            verified_using=integrity_methods,
 98            external_reference=external_reference,
 99            external_identifier=external_identifier,
100            originated_by=originated_by_spdx_id,
101            supplied_by=supplied_by_spdx_id,
102            built_time=spdx2_package.built_date,
103            release_time=spdx2_package.release_date,
104            valid_until_time=spdx2_package.valid_until_date,
105            primary_purpose=package_purpose,
106            package_version=spdx2_package.version,
107            download_location=download_location,
108            package_url=package_url,
109            homepage=spdx2_package.homepage,
110            source_info=spdx2_package.source_info,
111            copyright_text=copyright_text,
112            attribution_text=", ".join(spdx2_package.attribution_texts),
113        )
114    )
115
116
117external_ref_type_map = {
118    "cpe22Type": ExternalIdentifierType.CPE22,
119    "cpe23Type": ExternalIdentifierType.CPE23,
120    "advisory": ExternalReferenceType.SECURITY_ADVISORY,
121    "fix": ExternalReferenceType.SECURITY_FIX,
122    "url": None,
123    "swid": ExternalIdentifierType.SWID,
124    "maven-central": None,
125    "npm": None,
126    "nuget": None,
127    "bower": None,
128    "purl": ExternalIdentifierType.PURL,
129    "swh": ExternalIdentifierType.SWHID,
130    "gitoid": ExternalIdentifierType.GITOID,
131}
132
133
134def bump_external_package_ref(
135    spdx2_external_ref: ExternalPackageRef,
136) -> Optional[Union[ExternalReference, ExternalIdentifier]]:
137    reference_type = spdx2_external_ref.reference_type
138    locator = spdx2_external_ref.locator
139    comment = spdx2_external_ref.comment
140
141    if reference_type not in external_ref_type_map:
142        print_missing_conversion(
143            reference_type,
144            0,
145            f"Conversion of ExternalPackageRef of type {reference_type} is currently not supported."
146            f"https://github.com/spdx/spdx-3-model/issues/81",
147        )
148        return None
149
150    id_or_ref_type = external_ref_type_map[reference_type]
151
152    if isinstance(id_or_ref_type, ExternalReferenceType):
153        return ExternalReference(id_or_ref_type, [locator], None, comment)
154    elif isinstance(id_or_ref_type, ExternalIdentifierType):
155        return ExternalIdentifier(id_or_ref_type, locator, comment)
def bump_package( spdx2_package: spdx_tools.spdx.model.package.Package, payload: spdx_tools.spdx3.payload.Payload, document_namespace: str, external_document_refs: list[spdx_tools.spdx.model.external_document_ref.ExternalDocumentRef], imports: list[spdx_tools.spdx3.model.external_map.ExternalMap]):
 27def bump_package(
 28    spdx2_package: Spdx2_Package,
 29    payload: Payload,
 30    document_namespace: str,
 31    external_document_refs: List[ExternalDocumentRef],
 32    imports: List[ExternalMap],
 33):
 34    spdx_id = get_full_element_spdx_id(spdx2_package, document_namespace, external_document_refs)
 35    if ":" in spdx2_package.spdx_id:
 36        imports.append(
 37            ExternalMap(
 38                external_id=spdx2_package.spdx_id,
 39                defining_document=f"{spdx2_package.spdx_id.split(':')[0]}:SPDXRef-DOCUMENT",
 40            )
 41        )
 42
 43    download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location")
 44    print_missing_conversion("package2.file_name", 0, "https://github.com/spdx/spdx-3-model/issues/83")
 45    if isinstance(spdx2_package.supplier, Spdx2_Actor):
 46        supplied_by_spdx_id = [bump_actor(spdx2_package.supplier, payload, document_namespace)]
 47    else:
 48        supplied_by_spdx_id = None
 49    if isinstance(spdx2_package.originator, Spdx2_Actor):
 50        originated_by_spdx_id = [bump_actor(spdx2_package.originator, payload, document_namespace)]
 51    else:
 52        originated_by_spdx_id = None
 53    print_missing_conversion("package2.files_analyzed", 0, "https://github.com/spdx/spdx-3-model/issues/84")
 54    print_missing_conversion(
 55        "package2.verification_code", 1, "of IntegrityMethod, https://github.com/spdx/spdx-3-model/issues/85"
 56    )
 57    integrity_methods = [bump_checksum(checksum) for checksum in spdx2_package.checksums]
 58    copyright_text = None
 59    if isinstance(spdx2_package.copyright_text, str):
 60        copyright_text = spdx2_package.copyright_text
 61    elif isinstance(spdx2_package.copyright_text, SpdxNoAssertion):
 62        print_missing_conversion("package2.copyright_text", 0)
 63    print_missing_conversion(
 64        "package2.license_info_from_files, package2.license_comment",
 65        0,
 66        "and missing definition of license profile",
 67    )
 68
 69    external_reference = []
 70    external_identifier = []
 71    purl_refs = [
 72        external_ref for external_ref in spdx2_package.external_references if external_ref.reference_type == "purl"
 73    ]
 74    exactly_one_purl_without_comment = len(purl_refs) == 1 and purl_refs[0].comment is None
 75    package_url = None
 76    if exactly_one_purl_without_comment:
 77        package_url = purl_refs[0].locator
 78    for spdx2_external_ref in spdx2_package.external_references:
 79        if exactly_one_purl_without_comment and spdx2_external_ref.reference_type == "purl":
 80            continue
 81        id_or_ref = bump_external_package_ref(spdx2_external_ref)
 82        if isinstance(id_or_ref, ExternalReference):
 83            external_reference.append(id_or_ref)
 84        elif isinstance(id_or_ref, ExternalIdentifier):
 85            external_identifier.append(id_or_ref)
 86
 87    package_purpose = (
 88        SoftwarePurpose[spdx2_package.primary_package_purpose.name] if spdx2_package.primary_package_purpose else None
 89    )
 90
 91    payload.add_element(
 92        Package(
 93            spdx_id,
 94            spdx2_package.name,
 95            summary=spdx2_package.summary,
 96            description=spdx2_package.description,
 97            comment=spdx2_package.comment,
 98            verified_using=integrity_methods,
 99            external_reference=external_reference,
100            external_identifier=external_identifier,
101            originated_by=originated_by_spdx_id,
102            supplied_by=supplied_by_spdx_id,
103            built_time=spdx2_package.built_date,
104            release_time=spdx2_package.release_date,
105            valid_until_time=spdx2_package.valid_until_date,
106            primary_purpose=package_purpose,
107            package_version=spdx2_package.version,
108            download_location=download_location,
109            package_url=package_url,
110            homepage=spdx2_package.homepage,
111            source_info=spdx2_package.source_info,
112            copyright_text=copyright_text,
113            attribution_text=", ".join(spdx2_package.attribution_texts),
114        )
115    )
external_ref_type_map = {'cpe22Type': <ExternalIdentifierType.CPE22: 1>, 'cpe23Type': <ExternalIdentifierType.CPE23: 2>, 'advisory': <ExternalReferenceType.SECURITY_ADVISORY: 26>, 'fix': <ExternalReferenceType.SECURITY_FIX: 27>, 'url': None, 'swid': <ExternalIdentifierType.SWID: 9>, 'maven-central': None, 'npm': None, 'nuget': None, 'bower': None, 'purl': <ExternalIdentifierType.PURL: 6>, 'swh': <ExternalIdentifierType.SWHID: 8>, 'gitoid': <ExternalIdentifierType.GITOID: 5>}
135def bump_external_package_ref(
136    spdx2_external_ref: ExternalPackageRef,
137) -> Optional[Union[ExternalReference, ExternalIdentifier]]:
138    reference_type = spdx2_external_ref.reference_type
139    locator = spdx2_external_ref.locator
140    comment = spdx2_external_ref.comment
141
142    if reference_type not in external_ref_type_map:
143        print_missing_conversion(
144            reference_type,
145            0,
146            f"Conversion of ExternalPackageRef of type {reference_type} is currently not supported."
147            f"https://github.com/spdx/spdx-3-model/issues/81",
148        )
149        return None
150
151    id_or_ref_type = external_ref_type_map[reference_type]
152
153    if isinstance(id_or_ref_type, ExternalReferenceType):
154        return ExternalReference(id_or_ref_type, [locator], None, comment)
155    elif isinstance(id_or_ref_type, ExternalIdentifierType):
156        return ExternalIdentifier(id_or_ref_type, locator, comment)