diff --git a/cyclonedx/model/component.py b/cyclonedx/model/component.py
index 89ea379c..74c4ecca 100644
--- a/cyclonedx/model/component.py
+++ b/cyclonedx/model/component.py
@@ -1774,6 +1774,7 @@ def get_pypi_url(self) -> str:
def __comparable_tuple(self) -> _ComparableTuple:
return _ComparableTuple((
self.type, self.group, self.name, self.version,
+ self.bom_ref.value,
None if self.purl is None else _ComparablePackageURL(self.purl),
self.swid, self.cpe, _ComparableTuple(self.swhids),
self.supplier, self.author, self.publisher,
diff --git a/cyclonedx/model/contact.py b/cyclonedx/model/contact.py
index 2385528d..3266bd92 100644
--- a/cyclonedx/model/contact.py
+++ b/cyclonedx/model/contact.py
@@ -163,10 +163,10 @@ def street_address(self, street_address: Optional[str]) -> None:
def __comparable_tuple(self) -> _ComparableTuple:
return _ComparableTuple((
- self.bom_ref,
self.country, self.region, self.locality, self.postal_code,
self.post_office_box_number,
- self.street_address
+ self.street_address,
+ None if self.bom_ref is None else self.bom_ref.value,
))
def __eq__(self, other: object) -> bool:
diff --git a/cyclonedx/model/definition.py b/cyclonedx/model/definition.py
index d10072fa..675e5476 100644
--- a/cyclonedx/model/definition.py
+++ b/cyclonedx/model/definition.py
@@ -256,7 +256,7 @@ def external_references(self, external_references: Iterable[ExternalReference])
def __comparable_tuple(self) -> _ComparableTuple:
# all properties are optional - so need to compare all, in hope that one is unique
return _ComparableTuple((
- self.bom_ref, self.identifier,
+ self.identifier, self.bom_ref.value,
self.title, self.text,
_ComparableTuple(self.descriptions),
_ComparableTuple(self.open_cre), self.parent, _ComparableTuple(self.properties),
@@ -373,7 +373,9 @@ def requirements(self, requirements: Iterable[Union[str, BomRef]]) -> None:
def __comparable_tuple(self) -> _ComparableTuple:
# all properties are optional - so need to compare all, in hope that one is unique
return _ComparableTuple((
- self.bom_ref, self.identifier, self.title, self.description, _ComparableTuple(self.requirements)
+ self.identifier, self.bom_ref.value,
+ self.title, self.description,
+ _ComparableTuple(self.requirements)
))
def __lt__(self, other: Any) -> bool:
@@ -545,8 +547,9 @@ def external_references(self, external_references: Iterable[ExternalReference])
def __comparable_tuple(self) -> _ComparableTuple:
# all properties are optional - so need to apply all, in hope that one is unique
return _ComparableTuple((
- self.bom_ref,
- self.name, self.version, self.description, self.owner,
+ self.name, self.version,
+ self.bom_ref.value,
+ self.description, self.owner,
_ComparableTuple(self.requirements), _ComparableTuple(self.levels),
_ComparableTuple(self.external_references)
))
diff --git a/cyclonedx/model/service.py b/cyclonedx/model/service.py
index 640f1765..91541f6b 100644
--- a/cyclonedx/model/service.py
+++ b/cyclonedx/model/service.py
@@ -355,6 +355,7 @@ def release_notes(self, release_notes: Optional[ReleaseNotes]) -> None:
def __comparable_tuple(self) -> _ComparableTuple:
return _ComparableTuple((
self.group, self.name, self.version,
+ self.bom_ref.value,
self.provider, self.description,
self.authenticated, _ComparableTuple(self.data), _ComparableTuple(self.endpoints),
_ComparableTuple(self.external_references), _ComparableTuple(self.licenses),
diff --git a/cyclonedx/model/vulnerability.py b/cyclonedx/model/vulnerability.py
index bec10c7e..fc6d1ce1 100644
--- a/cyclonedx/model/vulnerability.py
+++ b/cyclonedx/model/vulnerability.py
@@ -1334,7 +1334,7 @@ def properties(self, properties: Iterable[Property]) -> None:
def __comparable_tuple(self) -> _ComparableTuple:
return _ComparableTuple((
- self.id,
+ self.id, self.bom_ref.value,
self.source, _ComparableTuple(self.references),
_ComparableTuple(self.ratings), _ComparableTuple(self.cwes), self.description,
self.detail, self.recommendation, self.workaround, _ComparableTuple(self.advisories),
diff --git a/tests/_data/models.py b/tests/_data/models.py
index 6bba3499..1b083a4d 100644
--- a/tests/_data/models.py
+++ b/tests/_data/models.py
@@ -1401,6 +1401,37 @@ def get_bom_with_definitions_and_detailed_standards() -> Bom:
]))
+def get_bom_for_issue540_duplicate_components() -> Bom:
+ # tests https://github.com/CycloneDX/cyclonedx-python-lib/issues/540
+ bom = _make_bom()
+ bom.metadata.component = root_component = Component(
+ name='myApp',
+ type=ComponentType.APPLICATION,
+ bom_ref='myApp'
+ )
+ component1 = Component(
+ type=ComponentType.LIBRARY,
+ name='some-component',
+ bom_ref='some-component'
+ )
+ bom.components.add(component1)
+ bom.register_dependency(root_component, [component1])
+ component2 = Component(
+ type=ComponentType.LIBRARY,
+ name='some-library',
+ bom_ref='some-library1'
+ )
+ bom.components.add(component2)
+ bom.register_dependency(component1, [component2])
+ component3 = Component(
+ type=ComponentType.LIBRARY,
+ name='some-library',
+ bom_ref='some-library2'
+ )
+ bom.components.add(component3)
+ bom.register_dependency(component1, [component3])
+ return bom
+
# ---
diff --git a/tests/_data/own/json/1.5/issue677.json b/tests/_data/own/json/1.5/issue677.json
new file mode 100644
index 00000000..090d97f8
--- /dev/null
+++ b/tests/_data/own/json/1.5/issue677.json
@@ -0,0 +1,49 @@
+{
+ "bomFormat": "CycloneDX",
+ "specVersion": "1.5",
+ "serialNumber": "urn:uuid:66fa5692-2e9d-45c5-830a-ec8ccaf7dcc9",
+ "version": 1,
+ "metadata": {
+ "component": {
+ "description": "see issue #677 - https://github.com/CycloneDX/cyclonedx-python-lib/issues/677",
+ "type": "application",
+ "name": "test"
+ }
+ },
+ "components": [
+ {
+ "type": "operating-system",
+ "bom-ref": "test12",
+ "name": "alpine"
+ },
+ {
+ "type": "container",
+ "bom-ref": "test11",
+ "name": "alpine"
+ },
+ {
+ "type": "operating-system",
+ "bom-ref": "test22",
+ "name": "alpine"
+ },
+ {
+ "type": "container",
+ "bom-ref": "test21",
+ "name": "alpine"
+ }
+ ],
+ "dependencies": [
+ {
+ "ref": "test11",
+ "dependsOn": [
+ "test12"
+ ]
+ },
+ {
+ "ref": "test21",
+ "dependsOn": [
+ "test22"
+ ]
+ }
+ ]
+}
diff --git a/tests/_data/own/json/1.5/issue753.json b/tests/_data/own/json/1.5/issue753.json
new file mode 100644
index 00000000..15123220
--- /dev/null
+++ b/tests/_data/own/json/1.5/issue753.json
@@ -0,0 +1,37 @@
+{
+ "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+ "bomFormat": "CycloneDX",
+ "specVersion": "1.5",
+ "version": 1,
+ "metadata": {
+ "component": {
+ "type": "application",
+ "name": "example",
+ "version": "1.2.3",
+ "bom-ref": "topref"
+ }
+ },
+ "components": [
+ {
+ "type": "library",
+ "name": "styled-engine",
+ "version": "5.16.6",
+ "bom-ref": "@mui/styled-engine@npm:5.16.6 [296f2]"
+ },
+ {
+ "type": "library",
+ "name": "styled-engine",
+ "version": "5.16.6",
+ "bom-ref": "@mui/styled-engine@npm:5.16.6 [3135b]"
+ }
+ ],
+ "dependencies": [
+ {
+ "ref": "topref",
+ "dependsOn": [
+ "@mui/styled-engine@npm:5.16.6 [296f2]",
+ "@mui/styled-engine@npm:5.16.6 [3135b]"
+ ]
+ }
+ ]
+}
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.0.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.0.xml.bin
new file mode 100644
index 00000000..dd1947eb
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.0.xml.bin
@@ -0,0 +1,20 @@
+
+
+
+
+ some-component
+
+ false
+
+
+ some-library
+
+ false
+
+
+ some-library
+
+ false
+
+
+
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.1.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.1.xml.bin
new file mode 100644
index 00000000..6d4d9bdb
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.1.xml.bin
@@ -0,0 +1,17 @@
+
+
+
+
+ some-component
+
+
+
+ some-library
+
+
+
+ some-library
+
+
+
+
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.json.bin
new file mode 100644
index 00000000..fd8f32b5
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.json.bin
@@ -0,0 +1,57 @@
+{
+ "components": [
+ {
+ "bom-ref": "some-component",
+ "name": "some-component",
+ "type": "library",
+ "version": ""
+ },
+ {
+ "bom-ref": "some-library1",
+ "name": "some-library",
+ "type": "library",
+ "version": ""
+ },
+ {
+ "bom-ref": "some-library2",
+ "name": "some-library",
+ "type": "library",
+ "version": ""
+ }
+ ],
+ "dependencies": [
+ {
+ "dependsOn": [
+ "some-component"
+ ],
+ "ref": "myApp"
+ },
+ {
+ "dependsOn": [
+ "some-library1",
+ "some-library2"
+ ],
+ "ref": "some-component"
+ },
+ {
+ "ref": "some-library1"
+ },
+ {
+ "ref": "some-library2"
+ }
+ ],
+ "metadata": {
+ "component": {
+ "bom-ref": "myApp",
+ "name": "myApp",
+ "type": "application",
+ "version": ""
+ },
+ "timestamp": "2023-01-07T13:44:32.312678+00:00"
+ },
+ "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
+ "version": 1,
+ "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json",
+ "bomFormat": "CycloneDX",
+ "specVersion": "1.2"
+}
\ No newline at end of file
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.xml.bin
new file mode 100644
index 00000000..625bc1dc
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.xml.bin
@@ -0,0 +1,35 @@
+
+
+
+ 2023-01-07T13:44:32.312678+00:00
+
+ myApp
+
+
+
+
+
+ some-component
+
+
+
+ some-library
+
+
+
+ some-library
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.json.bin
new file mode 100644
index 00000000..601c5974
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.json.bin
@@ -0,0 +1,57 @@
+{
+ "components": [
+ {
+ "bom-ref": "some-component",
+ "name": "some-component",
+ "type": "library",
+ "version": ""
+ },
+ {
+ "bom-ref": "some-library1",
+ "name": "some-library",
+ "type": "library",
+ "version": ""
+ },
+ {
+ "bom-ref": "some-library2",
+ "name": "some-library",
+ "type": "library",
+ "version": ""
+ }
+ ],
+ "dependencies": [
+ {
+ "dependsOn": [
+ "some-component"
+ ],
+ "ref": "myApp"
+ },
+ {
+ "dependsOn": [
+ "some-library1",
+ "some-library2"
+ ],
+ "ref": "some-component"
+ },
+ {
+ "ref": "some-library1"
+ },
+ {
+ "ref": "some-library2"
+ }
+ ],
+ "metadata": {
+ "component": {
+ "bom-ref": "myApp",
+ "name": "myApp",
+ "type": "application",
+ "version": ""
+ },
+ "timestamp": "2023-01-07T13:44:32.312678+00:00"
+ },
+ "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
+ "version": 1,
+ "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json",
+ "bomFormat": "CycloneDX",
+ "specVersion": "1.3"
+}
\ No newline at end of file
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.xml.bin
new file mode 100644
index 00000000..9ca84692
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.xml.bin
@@ -0,0 +1,35 @@
+
+
+
+ 2023-01-07T13:44:32.312678+00:00
+
+ myApp
+
+
+
+
+
+ some-component
+
+
+
+ some-library
+
+
+
+ some-library
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.json.bin
new file mode 100644
index 00000000..1da35538
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.json.bin
@@ -0,0 +1,53 @@
+{
+ "components": [
+ {
+ "bom-ref": "some-component",
+ "name": "some-component",
+ "type": "library"
+ },
+ {
+ "bom-ref": "some-library1",
+ "name": "some-library",
+ "type": "library"
+ },
+ {
+ "bom-ref": "some-library2",
+ "name": "some-library",
+ "type": "library"
+ }
+ ],
+ "dependencies": [
+ {
+ "dependsOn": [
+ "some-component"
+ ],
+ "ref": "myApp"
+ },
+ {
+ "dependsOn": [
+ "some-library1",
+ "some-library2"
+ ],
+ "ref": "some-component"
+ },
+ {
+ "ref": "some-library1"
+ },
+ {
+ "ref": "some-library2"
+ }
+ ],
+ "metadata": {
+ "component": {
+ "bom-ref": "myApp",
+ "name": "myApp",
+ "type": "application"
+ },
+ "timestamp": "2023-01-07T13:44:32.312678+00:00"
+ },
+ "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
+ "version": 1,
+ "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
+ "bomFormat": "CycloneDX",
+ "specVersion": "1.4"
+}
\ No newline at end of file
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.xml.bin
new file mode 100644
index 00000000..22db0779
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.xml.bin
@@ -0,0 +1,31 @@
+
+
+
+ 2023-01-07T13:44:32.312678+00:00
+
+ myApp
+
+
+
+
+ some-component
+
+
+ some-library
+
+
+ some-library
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.json.bin
new file mode 100644
index 00000000..64c0371b
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.json.bin
@@ -0,0 +1,63 @@
+{
+ "components": [
+ {
+ "bom-ref": "some-component",
+ "name": "some-component",
+ "type": "library"
+ },
+ {
+ "bom-ref": "some-library1",
+ "name": "some-library",
+ "type": "library"
+ },
+ {
+ "bom-ref": "some-library2",
+ "name": "some-library",
+ "type": "library"
+ }
+ ],
+ "dependencies": [
+ {
+ "dependsOn": [
+ "some-component"
+ ],
+ "ref": "myApp"
+ },
+ {
+ "dependsOn": [
+ "some-library1",
+ "some-library2"
+ ],
+ "ref": "some-component"
+ },
+ {
+ "ref": "some-library1"
+ },
+ {
+ "ref": "some-library2"
+ }
+ ],
+ "metadata": {
+ "component": {
+ "bom-ref": "myApp",
+ "name": "myApp",
+ "type": "application"
+ },
+ "timestamp": "2023-01-07T13:44:32.312678+00:00"
+ },
+ "properties": [
+ {
+ "name": "key1",
+ "value": "val1"
+ },
+ {
+ "name": "key2",
+ "value": "val2"
+ }
+ ],
+ "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
+ "version": 1,
+ "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+ "bomFormat": "CycloneDX",
+ "specVersion": "1.5"
+}
\ No newline at end of file
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.xml.bin
new file mode 100644
index 00000000..9146c15a
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.xml.bin
@@ -0,0 +1,35 @@
+
+
+
+ 2023-01-07T13:44:32.312678+00:00
+
+ myApp
+
+
+
+
+ some-component
+
+
+ some-library
+
+
+ some-library
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ val1
+ val2
+
+
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.json.bin
new file mode 100644
index 00000000..0ce6b2c9
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.json.bin
@@ -0,0 +1,63 @@
+{
+ "components": [
+ {
+ "bom-ref": "some-component",
+ "name": "some-component",
+ "type": "library"
+ },
+ {
+ "bom-ref": "some-library1",
+ "name": "some-library",
+ "type": "library"
+ },
+ {
+ "bom-ref": "some-library2",
+ "name": "some-library",
+ "type": "library"
+ }
+ ],
+ "dependencies": [
+ {
+ "dependsOn": [
+ "some-component"
+ ],
+ "ref": "myApp"
+ },
+ {
+ "dependsOn": [
+ "some-library1",
+ "some-library2"
+ ],
+ "ref": "some-component"
+ },
+ {
+ "ref": "some-library1"
+ },
+ {
+ "ref": "some-library2"
+ }
+ ],
+ "metadata": {
+ "component": {
+ "bom-ref": "myApp",
+ "name": "myApp",
+ "type": "application"
+ },
+ "timestamp": "2023-01-07T13:44:32.312678+00:00"
+ },
+ "properties": [
+ {
+ "name": "key1",
+ "value": "val1"
+ },
+ {
+ "name": "key2",
+ "value": "val2"
+ }
+ ],
+ "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
+ "version": 1,
+ "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
+ "bomFormat": "CycloneDX",
+ "specVersion": "1.6"
+}
\ No newline at end of file
diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.xml.bin
new file mode 100644
index 00000000..c64cf536
--- /dev/null
+++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.xml.bin
@@ -0,0 +1,35 @@
+
+
+
+ 2023-01-07T13:44:32.312678+00:00
+
+ myApp
+
+
+
+
+ some-component
+
+
+ some-library
+
+
+ some-library
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ val1
+ val2
+
+
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.0.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.0.xml.bin
index e70bbd27..5262d1d2 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.0.xml.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.0.xml.bin
@@ -4,13 +4,13 @@
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
+ pkg:pypi/pathlib2@2.3.5
false
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5
+ pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
false
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin
index baf7bca9..7e9f29bb 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin
@@ -1,15 +1,15 @@
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
+ pkg:pypi/pathlib2@2.3.5
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5
+ pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin
index 651e8e36..cba8ccc0 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin
@@ -1,16 +1,16 @@
{
"components": [
{
- "bom-ref": "dummy-b",
+ "bom-ref": "dummy-a",
"name": "dummy",
- "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6",
+ "purl": "pkg:pypi/pathlib2@2.3.5",
"type": "library",
"version": "2.3.5"
},
{
- "bom-ref": "dummy-a",
+ "bom-ref": "dummy-b",
"name": "dummy",
- "purl": "pkg:pypi/pathlib2@2.3.5",
+ "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6",
"type": "library",
"version": "2.3.5"
}
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin
index cf695a4d..8e52087f 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin
@@ -4,15 +4,15 @@
2023-01-07T13:44:32.312678+00:00
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
+ pkg:pypi/pathlib2@2.3.5
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5
+ pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin
index 6ebec9dd..4f4e5528 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin
@@ -1,16 +1,16 @@
{
"components": [
{
- "bom-ref": "dummy-b",
+ "bom-ref": "dummy-a",
"name": "dummy",
- "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6",
+ "purl": "pkg:pypi/pathlib2@2.3.5",
"type": "library",
"version": "2.3.5"
},
{
- "bom-ref": "dummy-a",
+ "bom-ref": "dummy-b",
"name": "dummy",
- "purl": "pkg:pypi/pathlib2@2.3.5",
+ "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6",
"type": "library",
"version": "2.3.5"
}
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin
index 9b5b5f7a..56808073 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin
@@ -4,15 +4,15 @@
2023-01-07T13:44:32.312678+00:00
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
+ pkg:pypi/pathlib2@2.3.5
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5
+ pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin
index f1eeb9dc..5745f1cf 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin
@@ -1,16 +1,16 @@
{
"components": [
{
- "bom-ref": "dummy-b",
+ "bom-ref": "dummy-a",
"name": "dummy",
- "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6",
+ "purl": "pkg:pypi/pathlib2@2.3.5",
"type": "library",
"version": "2.3.5"
},
{
- "bom-ref": "dummy-a",
+ "bom-ref": "dummy-b",
"name": "dummy",
- "purl": "pkg:pypi/pathlib2@2.3.5",
+ "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6",
"type": "library",
"version": "2.3.5"
}
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin
index cb9ea370..81a3cb22 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin
@@ -4,15 +4,15 @@
2023-01-07T13:44:32.312678+00:00
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
+ pkg:pypi/pathlib2@2.3.5
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5
+ pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin
index 206aaec4..a88cf7ae 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin
@@ -1,16 +1,16 @@
{
"components": [
{
- "bom-ref": "dummy-b",
+ "bom-ref": "dummy-a",
"name": "dummy",
- "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6",
+ "purl": "pkg:pypi/pathlib2@2.3.5",
"type": "library",
"version": "2.3.5"
},
{
- "bom-ref": "dummy-a",
+ "bom-ref": "dummy-b",
"name": "dummy",
- "purl": "pkg:pypi/pathlib2@2.3.5",
+ "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6",
"type": "library",
"version": "2.3.5"
}
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin
index 2944adfc..36630746 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin
@@ -4,15 +4,15 @@
2023-01-07T13:44:32.312678+00:00
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
+ pkg:pypi/pathlib2@2.3.5
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5
+ pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin
index 77097c87..1251020b 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin
@@ -1,16 +1,16 @@
{
"components": [
{
- "bom-ref": "dummy-b",
+ "bom-ref": "dummy-a",
"name": "dummy",
- "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6",
+ "purl": "pkg:pypi/pathlib2@2.3.5",
"type": "library",
"version": "2.3.5"
},
{
- "bom-ref": "dummy-a",
+ "bom-ref": "dummy-b",
"name": "dummy",
- "purl": "pkg:pypi/pathlib2@2.3.5",
+ "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6",
"type": "library",
"version": "2.3.5"
}
diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin
index 92263f13..18390367 100644
--- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin
+++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin
@@ -4,15 +4,15 @@
2023-01-07T13:44:32.312678+00:00
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
+ pkg:pypi/pathlib2@2.3.5
-
+
dummy
2.3.5
- pkg:pypi/pathlib2@2.3.5
+ pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6
diff --git a/tests/test_model_component.py b/tests/test_model_component.py
index 8212cf53..19c97561 100644
--- a/tests/test_model_component.py
+++ b/tests/test_model_component.py
@@ -144,17 +144,17 @@ def test_multiple_basic_components(self) -> None:
self.assertNotEqual(c1, c2)
def test_external_references(self) -> None:
- c = Component(name='test-component')
- c.external_references.add(ExternalReference(
+ c1 = Component(name='test-component')
+ c1.external_references.add(ExternalReference(
type=ExternalReferenceType.OTHER,
url=XsUri('https://cyclonedx.org'),
comment='No comment'
))
- self.assertEqual(c.name, 'test-component')
- self.assertIsNone(c.version)
- self.assertEqual(c.type, ComponentType.LIBRARY)
- self.assertEqual(len(c.external_references), 1)
- self.assertEqual(len(c.hashes), 0)
+ self.assertEqual(c1.name, 'test-component')
+ self.assertIsNone(c1.version)
+ self.assertEqual(c1.type, ComponentType.LIBRARY)
+ self.assertEqual(len(c1.external_references), 1)
+ self.assertEqual(len(c1.hashes), 0)
c2 = Component(name='test2-component')
self.assertEqual(c2.name, 'test2-component')
@@ -172,39 +172,35 @@ def test_empty_component_with_version(self) -> None:
self.assertEqual(len(c.hashes), 0)
def test_component_equal_1(self) -> None:
- c = Component(name='test-component')
- c.external_references.add(ExternalReference(
+ c1 = Component(name='test-component')
+ c1.external_references.add(ExternalReference(
type=ExternalReferenceType.OTHER,
url=XsUri('https://cyclonedx.org'),
comment='No comment'
))
-
c2 = Component(name='test-component')
c2.external_references.add(ExternalReference(
type=ExternalReferenceType.OTHER,
url=XsUri('https://cyclonedx.org'),
comment='No comment'
))
-
- self.assertEqual(c, c2)
+ self.assertEqual(c1, c2)
def test_component_equal_2(self) -> None:
- props: List[Property] = [
+ props: List[Property] = (
Property(name='prop1', value='val1'),
- Property(name='prop2', value='val2')
- ]
-
- c = Component(
+ Property(name='prop2', value='val2'),
+ )
+ c1 = Component(
name='test-component', version='1.2.3', properties=props
)
c2 = Component(
name='test-component', version='1.2.3', properties=props
)
-
- self.assertEqual(c, c2)
+ self.assertEqual(c1, c2)
def test_component_equal_3(self) -> None:
- c = Component(
+ c1 = Component(
name='test-component', version='1.2.3', properties=[
Property(name='prop1', value='val1'),
Property(name='prop2', value='val2')
@@ -216,8 +212,16 @@ def test_component_equal_3(self) -> None:
Property(name='prop4', value='val4')
]
)
+ self.assertNotEqual(c1, c2)
- self.assertNotEqual(c, c2)
+ def test_component_equal_4(self) -> None:
+ c1 = Component(
+ name='test-component', version='1.2.3', bom_ref='ref1'
+ )
+ c2 = Component(
+ name='test-component', version='1.2.3', bom_ref='ref2'
+ )
+ self.assertNotEqual(c1, c2)
def test_same_1(self) -> None:
c1 = get_component_setuptools_simple()
diff --git a/tests/test_model_vulnerability.py b/tests/test_model_vulnerability.py
index d4a556ac..7f818043 100644
--- a/tests/test_model_vulnerability.py
+++ b/tests/test_model_vulnerability.py
@@ -188,7 +188,7 @@ def test_sort(self) -> None:
datetime2 = datetime1 + timedelta(seconds=5)
# expected sort order: (id, description, detail, source, created, published)
- expected_order = [0, 6, 1, 7, 2, 9, 10, 8, 3, 4, 5, 11]
+ expected_order = [0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9, 11]
vulnerabilities = [
Vulnerability(bom_ref='0', id='a', description='a', detail='a',
source=source1, created=datetime1, published=datetime1),
diff --git a/tests/test_real_world_examples.py b/tests/test_real_world_examples.py
index 1df29fca..0fe3e480 100644
--- a/tests/test_real_world_examples.py
+++ b/tests/test_real_world_examples.py
@@ -17,6 +17,7 @@
import unittest
from datetime import datetime
+from json import loads as json_loads
from os.path import join
from typing import Any
from unittest.mock import patch
@@ -36,3 +37,19 @@ def test_webgoat_6_1(self, *_: Any, **__: Any) -> None:
def test_regression_issue_630(self, *_: Any, **__: Any) -> None:
with open(join(OWN_DATA_DIRECTORY, 'xml', '1.6', 'regression_issue630.xml')) as input_xml:
Bom.from_xml(input_xml)
+
+ def test_regression_issue677(self, *_: Any, **__: Any) -> None:
+ # tests https://github.com/CycloneDX/cyclonedx-python-lib/issues/677
+ with open(join(OWN_DATA_DIRECTORY, 'json', '1.5', 'issue677.json')) as input_json:
+ json = json_loads(input_json.read())
+ bom = Bom.from_json(json)
+ self.assertEqual(4, len(bom.components))
+ bom.validate()
+
+ def test_regression_issue753(self, *_: Any, **__: Any) -> None:
+ # tests https://github.com/CycloneDX/cyclonedx-python-lib/issues/753
+ with open(join(OWN_DATA_DIRECTORY, 'json', '1.5', 'issue753.json')) as input_json:
+ json = json_loads(input_json.read())
+ bom = Bom.from_json(json)
+ self.assertEqual(2, len(bom.components))
+ bom.validate()