Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
Signed-off-by: Jan Kowalleck <[email protected]>
  • Loading branch information
jkowalleck committed Jun 15, 2023
1 parent 8ea2265 commit 1d13eb9
Show file tree
Hide file tree
Showing 18 changed files with 125 additions and 1 deletion.
3 changes: 2 additions & 1 deletion cyclonedx/serialization/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,10 @@ def deserialize(cls, o: object) -> SortedSet[LicenseChoice]:

@classmethod
def serialize(cls, o: object) -> List[LicenseChoice]:
# need to call `list(o)`, because `o` could be any iterable.
licenses: List[LicenseChoice] = list(o) # type: ignore[call-overload]
if len(licenses) > 1:
expression = next(license for license in licenses if license.expression)
expression = next((l for l in licenses if l.expression), None)
if expression:
warnings.warn(
f'Licenses: found an expression {expression!r}, dropping the rest of: {licenses!r}',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"components": [{"bom-ref": "testing", "licenses": [{"expression": "(Apache-2.0 OR MIT)"}], "name": "expression-preferred", "type": "library", "version": ""}], "dependencies": [{"ref": "testing"}], "metadata": {"timestamp": "2022-06-15T13:09:38+00:00", "tools": [{"name": "cyclonedx-python-lib", "vendor": "CycloneDX", "version": "4.0.0"}]}, "serialNumber": "urn:uuid:66f6f3d4-0d24-4db3-b69c-bd547be9b0d3", "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"components": [{"bom-ref": "testing", "licenses": [{"license": {"id": "Apache-2.0", "text": {"content": "VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=", "contentType": "text/plain", "encoding": "base64"}, "url": "https://www.apache.org/licenses/LICENSE-2.0.txt"}}, {"license": {"name": "OSI_APACHE"}}], "name": "multiple-licenses", "type": "library", "version": ""}], "dependencies": [{"ref": "testing"}], "metadata": {"timestamp": "2022-06-15T13:05:12+00:00"}, "serialNumber": "urn:uuid:92f71d34-625a-4497-9891-3333c56a7af1", "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"components": [{"bom-ref": "testing", "licenses": [{"expression": "(Apache-2.0 OR MIT)"}], "name": "expression-preferred", "type": "library", "version": ""}], "dependencies": [{"ref": "testing"}], "metadata": {"timestamp": "2022-06-15T13:09:38+00:00", "tools": [{"name": "cyclonedx-python-lib", "vendor": "CycloneDX", "version": "4.0.0"}]}, "serialNumber": "urn:uuid:66f6f3d4-0d24-4db3-b69c-bd547be9b0d3", "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"components": [{"bom-ref": "testing", "licenses": [{"license": {"id": "Apache-2.0", "text": {"content": "VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=", "contentType": "text/plain", "encoding": "base64"}, "url": "https://www.apache.org/licenses/LICENSE-2.0.txt"}}, {"license": {"name": "OSI_APACHE"}}], "name": "multiple-licenses", "type": "library", "version": ""}], "dependencies": [{"ref": "testing"}], "metadata": {"timestamp": "2022-06-15T13:05:12+00:00"}, "serialNumber": "urn:uuid:92f71d34-625a-4497-9891-3333c56a7af1", "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"components": [{"bom-ref": "testing", "licenses": [{"expression": "(Apache-2.0 OR MIT)"}], "name": "expression-preferred", "type": "library"}], "dependencies": [{"ref": "testing"}], "metadata": {"timestamp": "2022-06-15T13:09:38+00:00", "tools": [{"externalReferences": [{"type": "build-system", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/actions"}, {"type": "distribution", "url": "https://pypi.org/project/cyclonedx-python-lib/"}, {"type": "documentation", "url": "https://cyclonedx.github.io/cyclonedx-python-lib/"}, {"type": "issue-tracker", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/issues"}, {"type": "license", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE"}, {"type": "release-notes", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md"}, {"type": "vcs", "url": "https://github.com/CycloneDX/cyclonedx-python-lib"}, {"type": "website", "url": "https://cyclonedx.org"}], "name": "cyclonedx-python-lib", "vendor": "CycloneDX", "version": "4.0.0"}]}, "serialNumber": "urn:uuid:66f6f3d4-0d24-4db3-b69c-bd547be9b0d3", "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"components": [{"bom-ref": "testing", "licenses": [{"license": {"id": "Apache-2.0", "text": {"content": "VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=", "contentType": "text/plain", "encoding": "base64"}, "url": "https://www.apache.org/licenses/LICENSE-2.0.txt"}}, {"license": {"name": "OSI_APACHE"}}], "name": "multiple-licenses", "type": "library"}], "dependencies": [{"ref": "testing"}], "metadata": {"timestamp": "2022-06-15T13:05:12+00:00"}, "serialNumber": "urn:uuid:92f71d34-625a-4497-9891-3333c56a7af1", "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><ns0:bom xmlns:ns0="http://cyclonedx.org/schema/bom/1.0" version="1"><ns0:components><ns0:component type="library"><ns0:name>expression-preferred</ns0:name><ns0:version /><ns0:modified>false</ns0:modified></ns0:component></ns0:components></ns0:bom>
1 change: 1 addition & 0 deletions tests/fixtures/xml/1.0/regression365_multiple-licenses.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><ns0:bom xmlns:ns0="http://cyclonedx.org/schema/bom/1.0" version="1"><ns0:components><ns0:component type="library"><ns0:name>multiple-licenses</ns0:name><ns0:version /><ns0:modified>false</ns0:modified></ns0:component></ns0:components></ns0:bom>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><ns0:bom xmlns:ns0="http://cyclonedx.org/schema/bom/1.1" serialNumber="urn:uuid:66f6f3d4-0d24-4db3-b69c-bd547be9b0d3" version="1"><ns0:components><ns0:component type="library" bom-ref="testing"><ns0:name>expression-preferred</ns0:name><ns0:version /><ns0:licenses><ns0:license><ns0:id>Apache-2.0</ns0:id><ns0:text content-type="text/plain" encoding="base64">VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=</ns0:text><ns0:url>https://www.apache.org/licenses/LICENSE-2.0.txt</ns0:url></ns0:license></ns0:licenses><ns0:licenses><ns0:license><ns0:name>OSI_APACHE</ns0:name></ns0:license></ns0:licenses><ns0:licenses><ns0:expression>(Apache-2.0 OR MIT)</ns0:expression></ns0:licenses></ns0:component></ns0:components></ns0:bom>
1 change: 1 addition & 0 deletions tests/fixtures/xml/1.1/regression365_multiple-licenses.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><ns0:bom xmlns:ns0="http://cyclonedx.org/schema/bom/1.1" serialNumber="urn:uuid:92f71d34-625a-4497-9891-3333c56a7af1" version="1"><ns0:components><ns0:component type="library" bom-ref="testing"><ns0:name>multiple-licenses</ns0:name><ns0:version /><ns0:licenses><ns0:license><ns0:id>Apache-2.0</ns0:id><ns0:text content-type="text/plain" encoding="base64">VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=</ns0:text><ns0:url>https://www.apache.org/licenses/LICENSE-2.0.txt</ns0:url></ns0:license></ns0:licenses><ns0:licenses><ns0:license><ns0:name>OSI_APACHE</ns0:name></ns0:license></ns0:licenses></ns0:component></ns0:components></ns0:bom>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><ns0:bom xmlns:ns0="http://cyclonedx.org/schema/bom/1.2" serialNumber="urn:uuid:66f6f3d4-0d24-4db3-b69c-bd547be9b0d3" version="1"><ns0:metadata><ns0:timestamp>2022-06-15T13:09:38+00:00</ns0:timestamp><ns0:tools><ns0:tool><ns0:vendor>CycloneDX</ns0:vendor><ns0:name>cyclonedx-python-lib</ns0:name><ns0:version>4.0.0</ns0:version></ns0:tool></ns0:tools></ns0:metadata><ns0:components><ns0:component type="library" bom-ref="testing"><ns0:name>expression-preferred</ns0:name><ns0:version /><ns0:licenses><ns0:license><ns0:id>Apache-2.0</ns0:id><ns0:text content-type="text/plain" encoding="base64">VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=</ns0:text><ns0:url>https://www.apache.org/licenses/LICENSE-2.0.txt</ns0:url></ns0:license></ns0:licenses><ns0:licenses><ns0:license><ns0:name>OSI_APACHE</ns0:name></ns0:license></ns0:licenses><ns0:licenses><ns0:expression>(Apache-2.0 OR MIT)</ns0:expression></ns0:licenses></ns0:component></ns0:components><ns0:dependencies><ns0:dependency ref="testing" /></ns0:dependencies></ns0:bom>
1 change: 1 addition & 0 deletions tests/fixtures/xml/1.2/regression365_multiple-licenses.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><ns0:bom xmlns:ns0="http://cyclonedx.org/schema/bom/1.2" serialNumber="urn:uuid:92f71d34-625a-4497-9891-3333c56a7af1" version="1"><ns0:metadata><ns0:timestamp>2022-06-15T13:05:12+00:00</ns0:timestamp></ns0:metadata><ns0:components><ns0:component type="library" bom-ref="testing"><ns0:name>multiple-licenses</ns0:name><ns0:version /><ns0:licenses><ns0:license><ns0:id>Apache-2.0</ns0:id><ns0:text content-type="text/plain" encoding="base64">VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=</ns0:text><ns0:url>https://www.apache.org/licenses/LICENSE-2.0.txt</ns0:url></ns0:license></ns0:licenses><ns0:licenses><ns0:license><ns0:name>OSI_APACHE</ns0:name></ns0:license></ns0:licenses></ns0:component></ns0:components><ns0:dependencies><ns0:dependency ref="testing" /></ns0:dependencies></ns0:bom>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><ns0:bom xmlns:ns0="http://cyclonedx.org/schema/bom/1.3" serialNumber="urn:uuid:66f6f3d4-0d24-4db3-b69c-bd547be9b0d3" version="1"><ns0:metadata><ns0:timestamp>2022-06-15T13:09:38+00:00</ns0:timestamp><ns0:tools><ns0:tool><ns0:vendor>CycloneDX</ns0:vendor><ns0:name>cyclonedx-python-lib</ns0:name><ns0:version>4.0.0</ns0:version></ns0:tool></ns0:tools></ns0:metadata><ns0:components><ns0:component type="library" bom-ref="testing"><ns0:name>expression-preferred</ns0:name><ns0:version /><ns0:licenses><ns0:license><ns0:id>Apache-2.0</ns0:id><ns0:text content-type="text/plain" encoding="base64">VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=</ns0:text><ns0:url>https://www.apache.org/licenses/LICENSE-2.0.txt</ns0:url></ns0:license></ns0:licenses><ns0:licenses><ns0:license><ns0:name>OSI_APACHE</ns0:name></ns0:license></ns0:licenses><ns0:licenses><ns0:expression>(Apache-2.0 OR MIT)</ns0:expression></ns0:licenses></ns0:component></ns0:components><ns0:dependencies><ns0:dependency ref="testing" /></ns0:dependencies></ns0:bom>
1 change: 1 addition & 0 deletions tests/fixtures/xml/1.3/regression365_multiple-licenses.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><ns0:bom xmlns:ns0="http://cyclonedx.org/schema/bom/1.3" serialNumber="urn:uuid:92f71d34-625a-4497-9891-3333c56a7af1" version="1"><ns0:metadata><ns0:timestamp>2022-06-15T13:05:12+00:00</ns0:timestamp></ns0:metadata><ns0:components><ns0:component type="library" bom-ref="testing"><ns0:name>multiple-licenses</ns0:name><ns0:version /><ns0:licenses><ns0:license><ns0:id>Apache-2.0</ns0:id><ns0:text content-type="text/plain" encoding="base64">VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=</ns0:text><ns0:url>https://www.apache.org/licenses/LICENSE-2.0.txt</ns0:url></ns0:license></ns0:licenses><ns0:licenses><ns0:license><ns0:name>OSI_APACHE</ns0:name></ns0:license></ns0:licenses></ns0:component></ns0:components><ns0:dependencies><ns0:dependency ref="testing" /></ns0:dependencies></ns0:bom>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><ns0:bom xmlns:ns0="http://cyclonedx.org/schema/bom/1.4" serialNumber="urn:uuid:66f6f3d4-0d24-4db3-b69c-bd547be9b0d3" version="1"><ns0:metadata><ns0:timestamp>2022-06-15T13:09:38+00:00</ns0:timestamp><ns0:tools><ns0:tool><ns0:vendor>CycloneDX</ns0:vendor><ns0:name>cyclonedx-python-lib</ns0:name><ns0:version>4.0.0</ns0:version><ns0:externalReferences><ns0:reference type="build-system"><ns0:url>https://github.com/CycloneDX/cyclonedx-python-lib/actions</ns0:url></ns0:reference><ns0:reference type="distribution"><ns0:url>https://pypi.org/project/cyclonedx-python-lib/</ns0:url></ns0:reference><ns0:reference type="documentation"><ns0:url>https://cyclonedx.github.io/cyclonedx-python-lib/</ns0:url></ns0:reference><ns0:reference type="issue-tracker"><ns0:url>https://github.com/CycloneDX/cyclonedx-python-lib/issues</ns0:url></ns0:reference><ns0:reference type="license"><ns0:url>https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE</ns0:url></ns0:reference><ns0:reference type="release-notes"><ns0:url>https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md</ns0:url></ns0:reference><ns0:reference type="vcs"><ns0:url>https://github.com/CycloneDX/cyclonedx-python-lib</ns0:url></ns0:reference><ns0:reference type="website"><ns0:url>https://cyclonedx.org</ns0:url></ns0:reference></ns0:externalReferences></ns0:tool></ns0:tools></ns0:metadata><ns0:components><ns0:component type="library" bom-ref="testing"><ns0:name>expression-preferred</ns0:name><ns0:licenses><ns0:license><ns0:id>Apache-2.0</ns0:id><ns0:text content-type="text/plain" encoding="base64">VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=</ns0:text><ns0:url>https://www.apache.org/licenses/LICENSE-2.0.txt</ns0:url></ns0:license></ns0:licenses><ns0:licenses><ns0:license><ns0:name>OSI_APACHE</ns0:name></ns0:license></ns0:licenses><ns0:licenses><ns0:expression>(Apache-2.0 OR MIT)</ns0:expression></ns0:licenses></ns0:component></ns0:components><ns0:dependencies><ns0:dependency ref="testing" /></ns0:dependencies></ns0:bom>
1 change: 1 addition & 0 deletions tests/fixtures/xml/1.4/regression365_multiple-licenses.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><ns0:bom xmlns:ns0="http://cyclonedx.org/schema/bom/1.4" serialNumber="urn:uuid:92f71d34-625a-4497-9891-3333c56a7af1" version="1"><ns0:metadata><ns0:timestamp>2022-06-15T13:05:12+00:00</ns0:timestamp></ns0:metadata><ns0:components><ns0:component type="library" bom-ref="testing"><ns0:name>multiple-licenses</ns0:name><ns0:licenses><ns0:license><ns0:id>Apache-2.0</ns0:id><ns0:text content-type="text/plain" encoding="base64">VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=</ns0:text><ns0:url>https://www.apache.org/licenses/LICENSE-2.0.txt</ns0:url></ns0:license></ns0:licenses><ns0:licenses><ns0:license><ns0:name>OSI_APACHE</ns0:name></ns0:license></ns0:licenses></ns0:component></ns0:components><ns0:dependencies><ns0:dependency ref="testing" /></ns0:dependencies></ns0:bom>
107 changes: 107 additions & 0 deletions tests/test_regression365.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# encoding: utf-8
# This file is part of CycloneDX Python Lib
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) OWASP Foundation. All Rights Reserved.

import re
from datetime import datetime, timezone
from itertools import chain, product
from os.path import dirname, join
from typing import Type, Union
from unittest import TestCase
from uuid import UUID

from ddt import ddt, idata, unpack

from cyclonedx.model import AttachedText, Encoding, License, LicenseChoice, XsUri
from cyclonedx.model.bom import Bom, Component
from cyclonedx.output.json import Json, JsonV1Dot2, JsonV1Dot3, JsonV1Dot4
from cyclonedx.output.xml import Xml, XmlV1Dot0, XmlV1Dot1, XmlV1Dot2, XmlV1Dot3, XmlV1Dot4

_bom_multiple_licenses = Bom(serial_number=UUID(hex='92f71d34625a449798913333c56a7af1'))
_bom_multiple_licenses.metadata.timestamp = datetime(2022, 6, 15, 13, 5, 12, 0, timezone.utc)
_bom_multiple_licenses.metadata.tools = []
_bom_multiple_licenses.components.add(Component(
name='multiple-licenses',
bom_ref='testing',
licenses=[
LicenseChoice(
license=License(
id='Apache-2.0',
text=AttachedText(
content='VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=',
encoding=Encoding.BASE_64
),
url=XsUri('https://www.apache.org/licenses/LICENSE-2.0.txt')
)
),
LicenseChoice(license=License(name='OSI_APACHE'))
]))

_bom_expression_preferred = Bom(serial_number=UUID(hex='66f6f3d40d244db3b69cbd547be9b0d3'))
_bom_expression_preferred.metadata.timestamp = datetime(2022, 6, 15, 13, 9, 38, 0, timezone.utc)
_bom_multiple_licenses.metadata.tools = []
_bom_expression_preferred.components.add(Component(
name='expression-preferred',
bom_ref='testing',
licenses=[
LicenseChoice(
license=License(
id='Apache-2.0',
text=AttachedText(
content='VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=',
encoding=Encoding.BASE_64
),
url=XsUri('https://www.apache.org/licenses/LICENSE-2.0.txt')
)
),
LicenseChoice(expression='(Apache-2.0 OR MIT)'),
LicenseChoice(license=License(name='OSI_APACHE'))
]))


@ddt
class Regression365(TestCase):
"""
This is a regression test against https://github.com/CycloneDX/cyclonedx-python-lib/issues/365
license list serialization must be like:
- if list contains any expressions: serialize the first expression only
- if list contains no expression: serialize all items
"""

@idata(chain(
product(
[_bom_multiple_licenses, _bom_expression_preferred],
['xml'],
[XmlV1Dot4, XmlV1Dot3, XmlV1Dot2, XmlV1Dot1, XmlV1Dot0]
),
product(
[_bom_multiple_licenses, _bom_expression_preferred],
['json'],
[JsonV1Dot4, JsonV1Dot3, JsonV1Dot2]
),
))
@unpack
def test_serialize(self, bom: Bom, target: str, schema_type: Union[Type[Json], Type[Xml]]) -> None:
serializer = schema_type(bom)
serialized = serializer.output_as_string()

expected_file = join(
dirname(__file__),
f'fixtures/{target}/{serializer.get_schema_version()}/regression365_{bom.components[0].name}.{target}')
with open(expected_file, 'r') as expected_fh:
self.assertEqual(expected_fh.read(), serialized)

0 comments on commit 1d13eb9

Please sign in to comment.