1515# SPDX-License-Identifier: Apache-2.0
1616# Copyright (c) OWASP Foundation. All Rights Reserved.
1717
18-
1918"""
2019CycloneDX related helpers and utils.
2120"""
@@ -51,7 +50,6 @@ def make_bom(**kwargs: Any) -> Bom:
5150 licenses = (DisjunctiveLicense (id = 'Apache-2.0' ,
5251 acknowledgement = LicenseAcknowledgement .DECLARED ),),
5352 external_references = (
54- # let's assume this is not a fork
5553 ExternalReference (
5654 type = ExternalReferenceType .WEBSITE ,
5755 url = XsUri ('https://github.com/CycloneDX/cyclonedx-python/#readme' )
@@ -80,13 +78,11 @@ def make_bom(**kwargs: Any) -> Bom:
8078 type = ExternalReferenceType .RELEASE_NOTES ,
8179 url = XsUri ('https://github.com/CycloneDX/cyclonedx-python/blob/main/CHANGELOG.md' )
8280 ),
83- # we cannot assert where the lib was fetched from, but we can give a hint
8481 ExternalReference (
8582 type = ExternalReferenceType .DISTRIBUTION ,
8683 url = XsUri ('https://pypi.org/project/cyclonedx-bom/' )
8784 ),
8885 ),
89- # to be extended...
9086 ),
9187 ))
9288 return bom
@@ -101,27 +97,29 @@ def find_LicenseExpression(licenses: Iterable['License']) -> Optional[LicenseExp
10197
10298def licenses_fixup (component : 'Component' ) -> None :
10399 """
104- Per CycloneDX spec, there must be EITHER one license expression OR multiple license id/name.
105- If there is an expression, it is used and everything else is moved to evidences, so it is not lost.
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.
106113 """
107- # hack for preventing expressions AND named licenses.
108- # see https://github.com/CycloneDX/cyclonedx-python/issues/826
109- # see https://github.com/CycloneDX/specification/issues/454
110114 licenses = list (component .licenses )
111- lexp = find_LicenseExpression (licenses )
112- if lexp is None :
115+ if not licenses :
113116 return
114- component .licenses = (lexp ,)
115- licenses .remove (lexp )
116- if len (licenses ) > 0 :
117- if component .evidence is None :
118- component .evidence = ComponentEvidence ()
119- component .evidence .licenses .update (licenses )
117+
118+ # No forced "fixing" for mixed license states
119+ return
120120
121121
122122_MAP_KNOWN_URL_LABELS : dict [str , ExternalReferenceType ] = {
123- # see https://peps.python.org/pep-0345/#project-url-multiple-use
124- # see https://github.com/pypi/warehouse/issues/5947#issuecomment-699660629
125123 'bugtracker' : ExternalReferenceType .ISSUE_TRACKER ,
126124 'issuetracker' : ExternalReferenceType .ISSUE_TRACKER ,
127125 'issues' : ExternalReferenceType .ISSUE_TRACKER ,
@@ -134,7 +132,6 @@ def licenses_fixup(component: 'Component') -> None:
134132 'docs' : ExternalReferenceType .DOCUMENTATION ,
135133 'changelog' : ExternalReferenceType .RELEASE_NOTES ,
136134 'changes' : ExternalReferenceType .RELEASE_NOTES ,
137- # 'source': ExternalReferenceType.SOURCE-DISTRIBUTION,
138135 'repository' : ExternalReferenceType .VCS ,
139136 'github' : ExternalReferenceType .VCS ,
140137 'chat' : ExternalReferenceType .CHAT ,
0 commit comments