Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions cyclonedx/contrib/bom/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,19 @@

class BomRefDiscriminator:
"""
Ensure that a collection of BomRef objects has unique, non‑empty values.

The discriminator inspects the provided BomRef instances and assigns new,
automatically generated identifiers to any BomRef whose value is missing
or duplicates another. Original values are preserved so they can be
restored later via `reset()` or by using this class as a context manager.
Ensure that a collection of BomRef objects
has unique, non‑empty :attr:`cyclonedx.model.bom_ref.BomRef.value`.

The discriminator inspects each provided BomRef and assigns a newly
generated identifier to any instance whose ``value`` is missing or
duplicates an earlier one.
All original values are preserved and can be restored via :meth:`reset()`
or by using this class as a context manager.
"""

def __init__(self, bomrefs: Iterable['BomRef'], prefix: str = 'BomRef') -> None:
# do not use dict/set here, different BomRefs with same value have same hash and would shadow each other
# NOTE: do not use dict/set here, different BomRefs with same value
# have same hash and would shadow each other.
self._bomrefs = tuple((bomref, bomref.value) for bomref in bomrefs)
self._prefix = prefix

Expand All @@ -52,10 +55,11 @@ def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:

def discriminate(self) -> None:
"""
Enforce uniqueness across all BomRef values.
Enforce uniqueness across all
:attr:`cyclonedx.model.bom_ref.BomRef.value`s.

Any BomRef whose value is `None` or duplicates a previously encountered
value is assigned a newly generated unique identifier.
Any BomRef whose ``value`` is ``None`` or duplicates a previously
encountered value is assigned a newly generated unique identifier.
"""
known_values = []
for bomref, _ in self._bomrefs:
Expand All @@ -67,7 +71,8 @@ def discriminate(self) -> None:

def reset(self) -> None:
"""
Restore all BomRef values to their original state.
Restore all :attr:`cyclonedx.model.bom_ref.BomRef.value`s to
their original state.
"""
for bomref, original_value in self._bomrefs:
bomref.value = original_value
Expand All @@ -78,12 +83,13 @@ def _make_unique(self) -> str:
@classmethod
def from_bom(cls, bom: 'Bom', prefix: str = 'BomRef') -> 'BomRefDiscriminator':
"""
Create a discriminator for all BomRefs contained within a BOM.
Create a discriminator for all :class:`cyclonedx.model.bom_ref.BomRefs`
contained within a Bom.

This includes BomRefs from
- components
- services
- vulnerabilities
* :attr:`cyclonedx.model.bom.Bom.components`
* :attr:`cyclonedx.model.bom.Bom.services`
* :attr:`cyclonedx.model.bom.Bom.vulnerabilities`
"""
return cls(chain(
map(lambda c: c.bom_ref, bom._get_all_components()),
Expand Down
Loading