Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions conan/tools/sbom/cyclonedx.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,21 +194,28 @@ def cyclonedx_1_6(conanfile, name=None, add_build=False, add_tests=False, **kwar
return sbom_cyclonedx_1_6


def _is_expr(license_value):
v = license_value.upper()
return " AND " in v or " OR " in v or " WITH " in v


def _calculate_licenses(component):
from conan.tools.sbom.spdx_licenses import NORMALIZED_VALID_SPDX_LICENSES
licenses = component.conanfile.license

if isinstance(licenses, str): # Just one license
field = "id" if licenses.lower() in NORMALIZED_VALID_SPDX_LICENSES else "name"
return [{"license": {field: licenses}}]

return [
# More than one license
{"license": {
"id" if lic.lower() in NORMALIZED_VALID_SPDX_LICENSES else "name": lic
}}
for lic in licenses
]
licenses = component.conanfile.license
if isinstance(licenses, str):
licenses = [licenses]

result = []
for lic in licenses:
if lic.lower() in NORMALIZED_VALID_SPDX_LICENSES:
field = "id"
elif _is_expr(lic):
field = "expression"
else:
field = "name"
result.append({"license": {field: lic}})
return result


def _calculate_bomref(component):
Expand Down
23 changes: 23 additions & 0 deletions test/unittests/tools/sbom/test_spdx_expression.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import pytest

from conan.tools.sbom.cyclonedx import _calculate_licenses
from conan.test.utils.mocks import ConanFileMock


@pytest.mark.parametrize(
"license_value, expected",
[
("MIT", "id"),
("mit", "id"),
("MIT OR Apache-2.0", "expression"),
("( MIT AND ( MIT ) )", "expression"),
("(MIT WITH (MIT))", "expression"),
("custom license", "name"),
],
)
def test_license_field(license_value, expected):
component = type("Component", (), {})()
component.conanfile = ConanFileMock()
component.conanfile.license = license_value
field = next(iter(_calculate_licenses(component)[0]["license"]))
assert field == expected
Loading