Skip to content

Commit 44e97f3

Browse files
authored
Merge branch 'CycloneDX:main' into feat/bom.definitions
2 parents ff93c59 + c72d5f4 commit 44e97f3

File tree

480 files changed

+4761
-10865
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

480 files changed

+4761
-10865
lines changed

CHANGELOG.md

Lines changed: 52 additions & 714 deletions
Large diffs are not rendered by default.

cyclonedx/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@
2222

2323
# !! version is managed by semantic_release
2424
# do not use typing here, or else `semantic_release` might have issues finding the variable
25-
__version__ = "7.6.2" # noqa:Q000
25+
__version__ = "8.0.0" # noqa:Q000

cyclonedx/builder/__init__.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# This file is part of CycloneDX Python Library
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
# SPDX-License-Identifier: Apache-2.0
16+
# Copyright (c) OWASP Foundation. All Rights Reserved.
17+
18+
"""
19+
Builders used in this library.
20+
"""

cyclonedx/builder/this.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# This file is part of CycloneDX Python Library
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
# SPDX-License-Identifier: Apache-2.0
16+
# Copyright (c) OWASP Foundation. All Rights Reserved.
17+
18+
"""Representation of this very python library."""
19+
20+
__all__ = ['this_component', 'this_tool', ]
21+
22+
from .. import __version__ as __ThisVersion # noqa: N812
23+
from ..model import ExternalReference, ExternalReferenceType, XsUri
24+
from ..model.component import Component, ComponentType
25+
from ..model.license import DisjunctiveLicense, LicenseAcknowledgement
26+
from ..model.tool import Tool
27+
28+
# !!! keep this file in sync with `pyproject.toml`
29+
30+
31+
def this_component() -> Component:
32+
"""Representation of this very python library as a :class:`Component`."""
33+
return Component(
34+
type=ComponentType.LIBRARY,
35+
group='CycloneDX',
36+
name='cyclonedx-python-lib',
37+
version=__ThisVersion or 'UNKNOWN',
38+
description='Python library for CycloneDX',
39+
licenses=(DisjunctiveLicense(id='Apache-2.0',
40+
acknowledgement=LicenseAcknowledgement.DECLARED),),
41+
external_references=(
42+
# let's assume this is not a fork
43+
ExternalReference(
44+
type=ExternalReferenceType.WEBSITE,
45+
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/#readme')
46+
),
47+
ExternalReference(
48+
type=ExternalReferenceType.DOCUMENTATION,
49+
url=XsUri('https://cyclonedx-python-library.readthedocs.io/')
50+
),
51+
ExternalReference(
52+
type=ExternalReferenceType.VCS,
53+
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib')
54+
),
55+
ExternalReference(
56+
type=ExternalReferenceType.BUILD_SYSTEM,
57+
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/actions')
58+
),
59+
ExternalReference(
60+
type=ExternalReferenceType.ISSUE_TRACKER,
61+
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/issues')
62+
),
63+
ExternalReference(
64+
type=ExternalReferenceType.LICENSE,
65+
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE')
66+
),
67+
ExternalReference(
68+
type=ExternalReferenceType.RELEASE_NOTES,
69+
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md')
70+
),
71+
# we cannot assert where the lib was fetched from, but we can give a hint
72+
ExternalReference(
73+
type=ExternalReferenceType.DISTRIBUTION,
74+
url=XsUri('https://pypi.org/project/cyclonedx-python-lib/')
75+
),
76+
),
77+
# to be extended...
78+
)
79+
80+
81+
def this_tool() -> Tool:
82+
"""Representation of this very python library as a :class:`Tool`."""
83+
return Tool.from_component(this_component())

cyclonedx/model/__init__.py

Lines changed: 0 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import serializable
3535
from sortedcontainers import SortedSet
3636

37-
from .. import __version__ as __ThisToolVersion # noqa: N812
3837
from .._internal.compare import ComparableTuple as _ComparableTuple
3938
from ..exception.model import (
4039
InvalidLocaleTypeException,
@@ -1129,139 +1128,6 @@ def __repr__(self) -> str:
11291128
return f'<Note id={id(self)}, locale={self.locale}>'
11301129

11311130

1132-
@serializable.serializable_class
1133-
class Tool:
1134-
"""
1135-
This is our internal representation of the `toolType` complex type within the CycloneDX standard.
1136-
1137-
Tool(s) are the things used in the creation of the CycloneDX document.
1138-
1139-
Tool might be deprecated since CycloneDX 1.5, but it is not deprecated in this library.
1140-
In fact, this library will try to provide a compatibility layer if needed.
1141-
1142-
.. note::
1143-
See the CycloneDX Schema for toolType: https://cyclonedx.org/docs/1.3/#type_toolType
1144-
"""
1145-
1146-
def __init__(
1147-
self, *,
1148-
vendor: Optional[str] = None,
1149-
name: Optional[str] = None,
1150-
version: Optional[str] = None,
1151-
hashes: Optional[Iterable[HashType]] = None,
1152-
external_references: Optional[Iterable[ExternalReference]] = None,
1153-
) -> None:
1154-
self.vendor = vendor
1155-
self.name = name
1156-
self.version = version
1157-
self.hashes = hashes or [] # type:ignore[assignment]
1158-
self.external_references = external_references or [] # type:ignore[assignment]
1159-
1160-
@property
1161-
@serializable.xml_sequence(1)
1162-
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
1163-
def vendor(self) -> Optional[str]:
1164-
"""
1165-
The name of the vendor who created the tool.
1166-
1167-
Returns:
1168-
`str` if set else `None`
1169-
"""
1170-
return self._vendor
1171-
1172-
@vendor.setter
1173-
def vendor(self, vendor: Optional[str]) -> None:
1174-
self._vendor = vendor
1175-
1176-
@property
1177-
@serializable.xml_sequence(2)
1178-
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
1179-
def name(self) -> Optional[str]:
1180-
"""
1181-
The name of the tool.
1182-
1183-
Returns:
1184-
`str` if set else `None`
1185-
"""
1186-
return self._name
1187-
1188-
@name.setter
1189-
def name(self, name: Optional[str]) -> None:
1190-
self._name = name
1191-
1192-
@property
1193-
@serializable.xml_sequence(3)
1194-
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
1195-
def version(self) -> Optional[str]:
1196-
"""
1197-
The version of the tool.
1198-
1199-
Returns:
1200-
`str` if set else `None`
1201-
"""
1202-
return self._version
1203-
1204-
@version.setter
1205-
def version(self, version: Optional[str]) -> None:
1206-
self._version = version
1207-
1208-
@property
1209-
@serializable.type_mapping(_HashTypeRepositorySerializationHelper)
1210-
@serializable.xml_sequence(4)
1211-
def hashes(self) -> 'SortedSet[HashType]':
1212-
"""
1213-
The hashes of the tool (if applicable).
1214-
1215-
Returns:
1216-
Set of `HashType`
1217-
"""
1218-
return self._hashes
1219-
1220-
@hashes.setter
1221-
def hashes(self, hashes: Iterable[HashType]) -> None:
1222-
self._hashes = SortedSet(hashes)
1223-
1224-
@property
1225-
@serializable.view(SchemaVersion1Dot4)
1226-
@serializable.view(SchemaVersion1Dot5)
1227-
@serializable.view(SchemaVersion1Dot6)
1228-
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference')
1229-
@serializable.xml_sequence(5)
1230-
def external_references(self) -> 'SortedSet[ExternalReference]':
1231-
"""
1232-
External References provides a way to document systems, sites, and information that may be relevant but which
1233-
are not included with the BOM.
1234-
1235-
Returns:
1236-
Set of `ExternalReference`
1237-
"""
1238-
return self._external_references
1239-
1240-
@external_references.setter
1241-
def external_references(self, external_references: Iterable[ExternalReference]) -> None:
1242-
self._external_references = SortedSet(external_references)
1243-
1244-
def __eq__(self, other: object) -> bool:
1245-
if isinstance(other, Tool):
1246-
return hash(other) == hash(self)
1247-
return False
1248-
1249-
def __lt__(self, other: Any) -> bool:
1250-
if isinstance(other, Tool):
1251-
return _ComparableTuple((
1252-
self.vendor, self.name, self.version
1253-
)) < _ComparableTuple((
1254-
other.vendor, other.name, other.version
1255-
))
1256-
return NotImplemented
1257-
1258-
def __hash__(self) -> int:
1259-
return hash((self.vendor, self.name, self.version, tuple(self.hashes), tuple(self.external_references)))
1260-
1261-
def __repr__(self) -> str:
1262-
return f'<Tool name={self.name}, version={self.version}, vendor={self.vendor}>'
1263-
1264-
12651131
@serializable.serializable_class
12661132
class IdentifiableAction:
12671133
"""
@@ -1397,43 +1263,3 @@ def __hash__(self) -> int:
13971263

13981264
def __repr__(self) -> str:
13991265
return f'<Copyright text={self.text}>'
1400-
1401-
1402-
ThisTool = Tool(
1403-
vendor='CycloneDX',
1404-
name='cyclonedx-python-lib',
1405-
version=__ThisToolVersion or 'UNKNOWN',
1406-
external_references=[
1407-
ExternalReference(
1408-
type=ExternalReferenceType.BUILD_SYSTEM,
1409-
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/actions')
1410-
),
1411-
ExternalReference(
1412-
type=ExternalReferenceType.DISTRIBUTION,
1413-
url=XsUri('https://pypi.org/project/cyclonedx-python-lib/')
1414-
),
1415-
ExternalReference(
1416-
type=ExternalReferenceType.DOCUMENTATION,
1417-
url=XsUri('https://cyclonedx-python-library.readthedocs.io/')
1418-
),
1419-
ExternalReference(
1420-
type=ExternalReferenceType.ISSUE_TRACKER,
1421-
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/issues')
1422-
),
1423-
ExternalReference(
1424-
type=ExternalReferenceType.LICENSE,
1425-
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE')
1426-
),
1427-
ExternalReference(
1428-
type=ExternalReferenceType.RELEASE_NOTES,
1429-
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md')
1430-
),
1431-
ExternalReference(
1432-
type=ExternalReferenceType.VCS,
1433-
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib')
1434-
),
1435-
ExternalReference(
1436-
type=ExternalReferenceType.WEBSITE,
1437-
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/#readme')
1438-
)
1439-
])

cyclonedx/model/bom.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,15 @@
3737
SchemaVersion1Dot6,
3838
)
3939
from ..serialization import LicenseRepositoryHelper, UrnUuidHelper
40-
from . import ExternalReference, Property, ThisTool, Tool
40+
from . import ExternalReference, Property
4141
from .bom_ref import BomRef
4242
from .component import Component
4343
from .contact import OrganizationalContact, OrganizationalEntity
4444
from .definition import DefinitionRepository, _DefinitionRepositoryHelper
4545
from .dependency import Dependable, Dependency
4646
from .license import License, LicenseExpression, LicenseRepository
4747
from .service import Service
48+
from .tool import Tool, ToolRepository, _ToolRepositoryHelper
4849
from .vulnerability import Vulnerability
4950

5051
if TYPE_CHECKING: # pragma: no cover
@@ -62,7 +63,7 @@ class BomMetaData:
6263

6364
def __init__(
6465
self, *,
65-
tools: Optional[Iterable[Tool]] = None,
66+
tools: Optional[Union[Iterable[Tool], ToolRepository]] = None,
6667
authors: Optional[Iterable[OrganizationalContact]] = None,
6768
component: Optional[Component] = None,
6869
supplier: Optional[OrganizationalEntity] = None,
@@ -91,9 +92,6 @@ def __init__(
9192
DeprecationWarning)
9293
self.definitions = definitions
9394

94-
if not tools:
95-
self.tools.add(ThisTool)
96-
9795
@property
9896
@serializable.type_mapping(serializable.helpers.XsdDateTime)
9997
@serializable.xml_sequence(1)
@@ -122,22 +120,22 @@ def timestamp(self, timestamp: datetime) -> None:
122120
# ... # TODO since CDX1.5
123121

124122
@property
125-
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'tool')
123+
@serializable.type_mapping(_ToolRepositoryHelper)
126124
@serializable.xml_sequence(3)
127-
def tools(self) -> 'SortedSet[Tool]':
125+
def tools(self) -> ToolRepository:
128126
"""
129127
Tools used to create this BOM.
130128
131129
Returns:
132-
`Set` of `Tool` objects.
130+
:class:`ToolRepository` object.
133131
"""
134-
# TODO since CDX1.5 also supports `Component` and `Services`, not only `Tool`
135132
return self._tools
136133

137134
@tools.setter
138-
def tools(self, tools: Iterable[Tool]) -> None:
139-
# TODO since CDX1.5 also supports `Component` and `Services`, not only `Tool`
140-
self._tools = SortedSet(tools)
135+
def tools(self, tools: Union[Iterable[Tool], ToolRepository]) -> None:
136+
self._tools = tools \
137+
if isinstance(tools, ToolRepository) \
138+
else ToolRepository(tools=tools)
141139

142140
@property
143141
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'author')
@@ -312,7 +310,7 @@ def __eq__(self, other: object) -> bool:
312310
def __hash__(self) -> int:
313311
return hash((
314312
tuple(self.authors), self.component, tuple(self.licenses), self.manufacture, tuple(self.properties),
315-
self.supplier, self.timestamp, tuple(self.tools), self.manufacturer,
313+
self.supplier, self.timestamp, self.tools, self.manufacturer,
316314
))
317315

318316
def __repr__(self) -> str:

cyclonedx/model/license.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ class LicenseExpression:
250250
"""
251251

252252
def __init__(
253-
self, value: str, # *, # all optional args are intended to be keyword-args
253+
self, value: str, *,
254254
acknowledgement: Optional[LicenseAcknowledgement] = None,
255255
) -> None:
256256
self._value = value

0 commit comments

Comments
 (0)