Skip to content

Commit

Permalink
Merge branch 'CycloneDX:main' into feat/bom.definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
hakandilek authored Oct 15, 2024
2 parents ff93c59 + c72d5f4 commit 44e97f3
Show file tree
Hide file tree
Showing 480 changed files with 4,761 additions and 10,865 deletions.
766 changes: 52 additions & 714 deletions CHANGELOG.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion cyclonedx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@

# !! version is managed by semantic_release
# do not use typing here, or else `semantic_release` might have issues finding the variable
__version__ = "7.6.2" # noqa:Q000
__version__ = "8.0.0" # noqa:Q000
20 changes: 20 additions & 0 deletions cyclonedx/builder/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# This file is part of CycloneDX Python Library
#
# 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.

"""
Builders used in this library.
"""
83 changes: 83 additions & 0 deletions cyclonedx/builder/this.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# This file is part of CycloneDX Python Library
#
# 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.

"""Representation of this very python library."""

__all__ = ['this_component', 'this_tool', ]

from .. import __version__ as __ThisVersion # noqa: N812
from ..model import ExternalReference, ExternalReferenceType, XsUri
from ..model.component import Component, ComponentType
from ..model.license import DisjunctiveLicense, LicenseAcknowledgement
from ..model.tool import Tool

# !!! keep this file in sync with `pyproject.toml`


def this_component() -> Component:
"""Representation of this very python library as a :class:`Component`."""
return Component(
type=ComponentType.LIBRARY,
group='CycloneDX',
name='cyclonedx-python-lib',
version=__ThisVersion or 'UNKNOWN',
description='Python library for CycloneDX',
licenses=(DisjunctiveLicense(id='Apache-2.0',
acknowledgement=LicenseAcknowledgement.DECLARED),),
external_references=(
# let's assume this is not a fork
ExternalReference(
type=ExternalReferenceType.WEBSITE,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/#readme')
),
ExternalReference(
type=ExternalReferenceType.DOCUMENTATION,
url=XsUri('https://cyclonedx-python-library.readthedocs.io/')
),
ExternalReference(
type=ExternalReferenceType.VCS,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib')
),
ExternalReference(
type=ExternalReferenceType.BUILD_SYSTEM,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/actions')
),
ExternalReference(
type=ExternalReferenceType.ISSUE_TRACKER,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/issues')
),
ExternalReference(
type=ExternalReferenceType.LICENSE,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE')
),
ExternalReference(
type=ExternalReferenceType.RELEASE_NOTES,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md')
),
# we cannot assert where the lib was fetched from, but we can give a hint
ExternalReference(
type=ExternalReferenceType.DISTRIBUTION,
url=XsUri('https://pypi.org/project/cyclonedx-python-lib/')
),
),
# to be extended...
)


def this_tool() -> Tool:
"""Representation of this very python library as a :class:`Tool`."""
return Tool.from_component(this_component())
174 changes: 0 additions & 174 deletions cyclonedx/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import serializable
from sortedcontainers import SortedSet

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


@serializable.serializable_class
class Tool:
"""
This is our internal representation of the `toolType` complex type within the CycloneDX standard.
Tool(s) are the things used in the creation of the CycloneDX document.
Tool might be deprecated since CycloneDX 1.5, but it is not deprecated in this library.
In fact, this library will try to provide a compatibility layer if needed.
.. note::
See the CycloneDX Schema for toolType: https://cyclonedx.org/docs/1.3/#type_toolType
"""

def __init__(
self, *,
vendor: Optional[str] = None,
name: Optional[str] = None,
version: Optional[str] = None,
hashes: Optional[Iterable[HashType]] = None,
external_references: Optional[Iterable[ExternalReference]] = None,
) -> None:
self.vendor = vendor
self.name = name
self.version = version
self.hashes = hashes or [] # type:ignore[assignment]
self.external_references = external_references or [] # type:ignore[assignment]

@property
@serializable.xml_sequence(1)
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
def vendor(self) -> Optional[str]:
"""
The name of the vendor who created the tool.
Returns:
`str` if set else `None`
"""
return self._vendor

@vendor.setter
def vendor(self, vendor: Optional[str]) -> None:
self._vendor = vendor

@property
@serializable.xml_sequence(2)
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
def name(self) -> Optional[str]:
"""
The name of the tool.
Returns:
`str` if set else `None`
"""
return self._name

@name.setter
def name(self, name: Optional[str]) -> None:
self._name = name

@property
@serializable.xml_sequence(3)
@serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING)
def version(self) -> Optional[str]:
"""
The version of the tool.
Returns:
`str` if set else `None`
"""
return self._version

@version.setter
def version(self, version: Optional[str]) -> None:
self._version = version

@property
@serializable.type_mapping(_HashTypeRepositorySerializationHelper)
@serializable.xml_sequence(4)
def hashes(self) -> 'SortedSet[HashType]':
"""
The hashes of the tool (if applicable).
Returns:
Set of `HashType`
"""
return self._hashes

@hashes.setter
def hashes(self, hashes: Iterable[HashType]) -> None:
self._hashes = SortedSet(hashes)

@property
@serializable.view(SchemaVersion1Dot4)
@serializable.view(SchemaVersion1Dot5)
@serializable.view(SchemaVersion1Dot6)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference')
@serializable.xml_sequence(5)
def external_references(self) -> 'SortedSet[ExternalReference]':
"""
External References provides a way to document systems, sites, and information that may be relevant but which
are not included with the BOM.
Returns:
Set of `ExternalReference`
"""
return self._external_references

@external_references.setter
def external_references(self, external_references: Iterable[ExternalReference]) -> None:
self._external_references = SortedSet(external_references)

def __eq__(self, other: object) -> bool:
if isinstance(other, Tool):
return hash(other) == hash(self)
return False

def __lt__(self, other: Any) -> bool:
if isinstance(other, Tool):
return _ComparableTuple((
self.vendor, self.name, self.version
)) < _ComparableTuple((
other.vendor, other.name, other.version
))
return NotImplemented

def __hash__(self) -> int:
return hash((self.vendor, self.name, self.version, tuple(self.hashes), tuple(self.external_references)))

def __repr__(self) -> str:
return f'<Tool name={self.name}, version={self.version}, vendor={self.vendor}>'


@serializable.serializable_class
class IdentifiableAction:
"""
Expand Down Expand Up @@ -1397,43 +1263,3 @@ def __hash__(self) -> int:

def __repr__(self) -> str:
return f'<Copyright text={self.text}>'


ThisTool = Tool(
vendor='CycloneDX',
name='cyclonedx-python-lib',
version=__ThisToolVersion or 'UNKNOWN',
external_references=[
ExternalReference(
type=ExternalReferenceType.BUILD_SYSTEM,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/actions')
),
ExternalReference(
type=ExternalReferenceType.DISTRIBUTION,
url=XsUri('https://pypi.org/project/cyclonedx-python-lib/')
),
ExternalReference(
type=ExternalReferenceType.DOCUMENTATION,
url=XsUri('https://cyclonedx-python-library.readthedocs.io/')
),
ExternalReference(
type=ExternalReferenceType.ISSUE_TRACKER,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/issues')
),
ExternalReference(
type=ExternalReferenceType.LICENSE,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE')
),
ExternalReference(
type=ExternalReferenceType.RELEASE_NOTES,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md')
),
ExternalReference(
type=ExternalReferenceType.VCS,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib')
),
ExternalReference(
type=ExternalReferenceType.WEBSITE,
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/#readme')
)
])
24 changes: 11 additions & 13 deletions cyclonedx/model/bom.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,15 @@
SchemaVersion1Dot6,
)
from ..serialization import LicenseRepositoryHelper, UrnUuidHelper
from . import ExternalReference, Property, ThisTool, Tool
from . import ExternalReference, Property
from .bom_ref import BomRef
from .component import Component
from .contact import OrganizationalContact, OrganizationalEntity
from .definition import DefinitionRepository, _DefinitionRepositoryHelper
from .dependency import Dependable, Dependency
from .license import License, LicenseExpression, LicenseRepository
from .service import Service
from .tool import Tool, ToolRepository, _ToolRepositoryHelper
from .vulnerability import Vulnerability

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

def __init__(
self, *,
tools: Optional[Iterable[Tool]] = None,
tools: Optional[Union[Iterable[Tool], ToolRepository]] = None,
authors: Optional[Iterable[OrganizationalContact]] = None,
component: Optional[Component] = None,
supplier: Optional[OrganizationalEntity] = None,
Expand Down Expand Up @@ -91,9 +92,6 @@ def __init__(
DeprecationWarning)
self.definitions = definitions

if not tools:
self.tools.add(ThisTool)

@property
@serializable.type_mapping(serializable.helpers.XsdDateTime)
@serializable.xml_sequence(1)
Expand Down Expand Up @@ -122,22 +120,22 @@ def timestamp(self, timestamp: datetime) -> None:
# ... # TODO since CDX1.5

@property
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'tool')
@serializable.type_mapping(_ToolRepositoryHelper)
@serializable.xml_sequence(3)
def tools(self) -> 'SortedSet[Tool]':
def tools(self) -> ToolRepository:
"""
Tools used to create this BOM.
Returns:
`Set` of `Tool` objects.
:class:`ToolRepository` object.
"""
# TODO since CDX1.5 also supports `Component` and `Services`, not only `Tool`
return self._tools

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

@property
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'author')
Expand Down Expand Up @@ -312,7 +310,7 @@ def __eq__(self, other: object) -> bool:
def __hash__(self) -> int:
return hash((
tuple(self.authors), self.component, tuple(self.licenses), self.manufacture, tuple(self.properties),
self.supplier, self.timestamp, tuple(self.tools), self.manufacturer,
self.supplier, self.timestamp, self.tools, self.manufacturer,
))

def __repr__(self) -> str:
Expand Down
2 changes: 1 addition & 1 deletion cyclonedx/model/license.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ class LicenseExpression:
"""

def __init__(
self, value: str, # *, # all optional args are intended to be keyword-args
self, value: str, *,
acknowledgement: Optional[LicenseAcknowledgement] = None,
) -> None:
self._value = value
Expand Down
Loading

0 comments on commit 44e97f3

Please sign in to comment.