Skip to content

Commit 6a23934

Browse files
committed
feat: skip license fixup for CycloneDX schema 1.7+ (fixes #995)
1 parent 00d15db commit 6a23934

File tree

1 file changed

+22
-17
lines changed
  • cyclonedx_py/_internal/utils

1 file changed

+22
-17
lines changed

cyclonedx_py/_internal/utils/cdx.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from re import compile as re_compile
2424
from typing import Any, Optional
2525

26+
from cyclonedx.schema import SchemaVersion
2627
from cyclonedx.builder.this import this_component as lib_component
2728
from cyclonedx.model import ExternalReference, ExternalReferenceType, XsUri
2829
from cyclonedx.model.bom import Bom
@@ -95,29 +96,33 @@ def find_LicenseExpression(licenses: Iterable['License']) -> Optional[LicenseExp
9596
return None
9697

9798

98-
def licenses_fixup(component: 'Component') -> None:
99+
def licenses_fixup(component: Component) -> None:
99100
"""
100-
CycloneDX 1.7 compliant license handling.
101-
102-
Rules:
103-
- A component may have:
104-
1. One license expression
105-
2. One or more named licenses
106-
3. A mix of expression + named licenses (allowed by spec)
107-
108-
Behavior:
109-
- Single license expression → leave as-is.
110-
- Only named licenses → leave as-is.
111-
- Mixed expression + named → leave as-is (spec allows this).
112-
- No licenses are moved to evidence unless explicitly desired.
101+
Skip license fixup for CycloneDX 1.7 and newer.
102+
103+
In CycloneDX 1.7+, license expressions and named licenses
104+
may coexist. Older versions still require normalization.
113105
"""
106+
# Detect schema version via internal BOM reference
107+
bom = getattr(component, "_bom", None)
108+
if bom is not None:
109+
schema_version = getattr(bom.metadata, "schema_version", None)
110+
if schema_version is not None and schema_version >= SchemaVersion.V1_7:
111+
return
112+
113+
# ---- Legacy behavior (< 1.7) ----
114114
licenses = list(component.licenses)
115-
if not licenses:
115+
lexp = find_LicenseExpression(licenses)
116+
if lexp is None:
116117
return
117118

118-
# No forced "fixing" for mixed license states
119-
return
119+
component.licenses = (lexp,)
120+
licenses.remove(lexp)
120121

122+
if licenses:
123+
if component.evidence is None:
124+
component.evidence = ComponentEvidence()
125+
component.evidence.licenses.update(licenses)
121126

122127
_MAP_KNOWN_URL_LABELS: dict[str, ExternalReferenceType] = {
123128
'bugtracker': ExternalReferenceType.ISSUE_TRACKER,

0 commit comments

Comments
 (0)