Created
October 20, 2025 16:33
-
-
Save pombredanne/144854016e1141714dfd639ad71ad3a0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def to_spdx(project, version=spdx.SPDX_SPEC_VERSION_2_3, include_files=False, _fake_test_uuid=None): | |
| """ | |
| Generate output for the provided ``project`` in SPDX document format. | |
| The output file is created in the ``project`` "output/" directory. | |
| Return the path of the generated output file. | |
| """ | |
| if version not in [spdx.SPDX_SPEC_VERSION_2_2, spdx.SPDX_SPEC_VERSION_2_3]: | |
| raise ValueError(f"SPDX {version} is not supported.") | |
| if _fake_test_uuid: | |
| project_uuid = _fake_test_uuid | |
| else: | |
| project_uuid = project.uuid | |
| output_file = project.get_output_file_path("results", "spdx.json") | |
| document_spdx_id = f"SPDXRef-DOCUMENT-{project_uuid}" | |
| discoveredpackage_qs = get_queryset(project, "discoveredpackage") | |
| discovereddependency_qs = get_queryset(project, "discovereddependency") | |
| packages_as_spdx = [] | |
| license_expressions = [] | |
| relationships = [] | |
| project_inputs_as_spdx_packages = get_inputs_as_spdx_packages(project) | |
| if project_inputs_as_spdx_packages: | |
| packages_as_spdx.extend(project_inputs_as_spdx_packages) | |
| # Use the Project's input as the root element that the SPDX document describes. | |
| # This ensures "documentDescribes" points only to the main subject of the SBOM, | |
| # not to every dependency or file in the project. | |
| # See https://github.com/spdx/spdx-spec/issues/395 and | |
| # https://github.com/aboutcode-org/scancode.io/issues/564#issuecomment-3269296563 | |
| # for detailed context. | |
| if len(project_inputs_as_spdx_packages) == 1: | |
| describe_spdx_id = project_inputs_as_spdx_packages[0].spdx_id | |
| # Fallback to the Project as the SPDX root element for the "documentDescribes", | |
| # if more than one input, or if no inputs, are available. | |
| else: | |
| project_as_root_package = spdx.Package( | |
| spdx_id=f"SPDXRef-scancodeio-project-{project_uuid}", | |
| name=project.name, | |
| files_analyzed=True, | |
| ) | |
| packages_as_spdx.append(project_as_root_package) | |
| describe_spdx_id = project_as_root_package.spdx_id | |
| for package in discoveredpackage_qs: | |
| spdx_package = package.as_spdx() | |
| packages_as_spdx.append(spdx_package) | |
| if license_expression := package.declared_license_expression: | |
| license_expressions.append(license_expression) | |
| spdx_relationship = spdx.Relationship( | |
| spdx_id=describe_spdx_id, | |
| related_spdx_id=spdx_package.spdx_id, | |
| relationship="DEPENDS_ON", | |
| ) | |
| relationships.append(spdx_relationship) | |
| for dependency in discovereddependency_qs: | |
| spdx_relationship = get_dependency_as_spdx_relationship( | |
| dependency, | |
| document_spdx_id, | |
| packages_as_spdx, | |
| ) | |
| relationships.append(spdx_relationship) | |
| files_as_spdx = [] | |
| if include_files: | |
| files_as_spdx = [ | |
| resource.as_spdx() | |
| for resource in get_queryset(project, "codebaseresource").files() | |
| ] | |
| document = spdx.Document( | |
| version=version, | |
| spdx_id=document_spdx_id, | |
| name=f"scancodeio_{project.name}", | |
| namespace=f"https://scancode.io/spdxdocs/{project_uuid}", | |
| describes=[describe_spdx_id], | |
| creation_info=spdx.CreationInfo(tool=f"ScanCode.io-{scancodeio_version}"), | |
| packages=packages_as_spdx, | |
| files=files_as_spdx, | |
| extracted_licenses=_get_spdx_extracted_licenses(license_expressions), | |
| relationships=relationships, | |
| comment=SCAN_NOTICE, | |
| ) | |
| with output_file.open("w") as file: | |
| file.write(document.as_json()) | |
| return output_file |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment