Skip to content

Commit d3c6b92

Browse files
saquibsaifeeclaude
andcommitted
refactor(output): consolidate normalization and validation into BaseOutput._prepare()
Both JSON and XML serializers now share a single _prepare() hook that runs dependency graph normalization (register_dependency) and ModelValidator before serialization, eliminating duplicated logic. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Saquib Saifee <saquibsaifee2@gmail.com>
1 parent 05397eb commit d3c6b92

3 files changed

Lines changed: 18 additions & 2 deletions

File tree

cyclonedx/output/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727
from itertools import chain
2828
from random import random
2929
from typing import TYPE_CHECKING, Any, Literal, Optional, Union, overload
30+
from warnings import warn as _warn
3031

3132
from ..schema import OutputFormat, SchemaVersion
33+
from ..validation.model import ModelValidationErrorSeverity, ModelValidator
3234

3335
if TYPE_CHECKING: # pragma: no cover
3436
from ..model.bom import Bom
@@ -68,6 +70,20 @@ def get_bom(self) -> 'Bom':
6870
def set_bom(self, bom: 'Bom') -> None:
6971
self._bom = bom
7072

73+
def _prepare(self) -> None:
74+
"""Normalize dependency graph and validate model integrity before serialization."""
75+
bom = self._bom
76+
if bom.metadata.component:
77+
bom.register_dependency(target=bom.metadata.component)
78+
for _c in bom.components:
79+
bom.register_dependency(target=_c)
80+
for _s in bom.services:
81+
bom.register_dependency(target=_s)
82+
for _err in ModelValidator().validate(bom):
83+
if _err.severity is ModelValidationErrorSeverity.ERROR:
84+
raise _err.data
85+
_warn(str(_err.data), stacklevel=3)
86+
7187
@abstractmethod
7288
def generate(self, force_regeneration: bool = False) -> None:
7389
... # pragma: no cover

cyclonedx/output/json.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ def generate(self, force_regeneration: bool = False) -> None:
6868
'specVersion': self.schema_version.to_version()
6969
}
7070
_view = SCHEMA_VERSIONS.get(self.schema_version_enum)
71+
self._prepare()
7172
bom = self.get_bom()
72-
bom.validate()
7373
with BomRefDiscriminator.from_bom(bom):
7474
bom_json: dict[str, Any] = json_loads(
7575
bom.as_json( # type:ignore[attr-defined]

cyclonedx/output/xml.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ def generate(self, force_regeneration: bool = False) -> None:
5757
return
5858

5959
_view = SCHEMA_VERSIONS[self.schema_version_enum]
60+
self._prepare()
6061
bom = self.get_bom()
61-
bom.validate()
6262
xmlns = self.get_target_namespace()
6363
with BomRefDiscriminator.from_bom(bom):
6464
self._bom_xml = '<?xml version="1.0" ?>\n' + xml_dumps( # type:ignore[call-overload]

0 commit comments

Comments
 (0)