Skip to content

refactor(DX): rename get_instance() #469

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
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
35 changes: 19 additions & 16 deletions cyclonedx/output/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"""

import os
import warnings
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, Iterable, Literal, Mapping, Optional, Type, Union, overload

Expand All @@ -41,11 +42,6 @@ def __init__(self, bom: 'Bom', **kwargs: int) -> None:
self._bom = bom
self._generated: bool = False

def _chained_components(self, container: Union['Bom', 'Component']) -> Iterable['Component']:
for component in container.components:
yield component
yield from self._chained_components(component)

@property
@abstractmethod
def schema_version(self) -> SchemaVersion:
Expand Down Expand Up @@ -95,40 +91,37 @@ def output_to_file(self, filename: str, allow_overwrite: bool = False, *,


@overload
def get_instance(bom: 'Bom', output_format: Literal[OutputFormat.JSON],
schema_version: SchemaVersion = ...) -> 'JsonOutputter':
def make_outputter(bom: 'Bom', output_format: Literal[OutputFormat.JSON],
schema_version: SchemaVersion) -> 'JsonOutputter':
...


@overload
def get_instance(bom: 'Bom', output_format: Literal[OutputFormat.XML] = ...,
schema_version: SchemaVersion = ...) -> 'XmlOutputter':
def make_outputter(bom: 'Bom', output_format: Literal[OutputFormat.XML],
schema_version: SchemaVersion) -> 'XmlOutputter':
...


@overload
def get_instance(bom: 'Bom', output_format: OutputFormat = ...,
schema_version: SchemaVersion = ...
) -> Union['XmlOutputter', 'JsonOutputter']:
def make_outputter(bom: 'Bom', output_format: OutputFormat,
schema_version: SchemaVersion) -> Union['XmlOutputter', 'JsonOutputter']:
...


def get_instance(bom: 'Bom', output_format: OutputFormat = OutputFormat.XML,
schema_version: SchemaVersion = LATEST_SUPPORTED_SCHEMA_VERSION) -> BaseOutput:
def make_outputter(bom: 'Bom', output_format: OutputFormat, schema_version: SchemaVersion) -> BaseOutput:
"""
Helper method to quickly get the correct output class/formatter.

Pass in your BOM and optionally an output format and schema version (defaults to XML and latest schema version).


Raises error when no instance could be built.
Raises error when no instance could be made.

:param bom: Bom
:param output_format: OutputFormat
:param schema_version: SchemaVersion
:return: BaseOutput
"""
# all exceptions are undocumented, as they are pure functional, and should be prevented by correct typing...
if TYPE_CHECKING: # pragma: no cover
BY_SCHEMA_VERSION: Mapping[SchemaVersion, Type[BaseOutput]]
if OutputFormat.JSON is output_format:
Expand All @@ -142,3 +135,13 @@ def get_instance(bom: 'Bom', output_format: OutputFormat = OutputFormat.XML,
if klass is None:
raise ValueError(f'Unknown {output_format.name}/schema_version: {schema_version!r}')
return klass(bom)


def get_instance(bom: 'Bom', output_format: OutputFormat = OutputFormat.XML,
schema_version: SchemaVersion = LATEST_SUPPORTED_SCHEMA_VERSION) -> BaseOutput:
"""DEPRECATED. use :func:`make_outputter` instead!"""
warnings.warn(
'function `get_instance()` is deprecated, use `make_outputter()` instead.',
DeprecationWarning
)
return make_outputter(bom, output_format, schema_version)
48 changes: 43 additions & 5 deletions cyclonedx/validation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@


from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, Optional, Protocol
from typing import TYPE_CHECKING, Any, Literal, Optional, Protocol, Union, overload

from ..schema import OutputFormat

if TYPE_CHECKING: # pragma: no cover
from ..schema import SchemaVersion
from .json import JsonValidator
from .xml import XmlValidator


class ValidationError:
Expand All @@ -41,8 +43,8 @@ def __str__(self) -> str:
return str(self.data)


class SchemaBasedValidator(Protocol):
"""Schema based Validator protocol"""
class SchemabasedValidator(Protocol):
"""Schema-based Validator protocol"""

def validate_str(self, data: str) -> Optional[ValidationError]:
"""Validate a string
Expand All @@ -55,8 +57,8 @@ def validate_str(self, data: str) -> Optional[ValidationError]:
...


class BaseSchemaBasedValidator(ABC, SchemaBasedValidator):
"""Base Schema based Validator"""
class BaseSchemabasedValidator(ABC, SchemabasedValidator):
"""Base Schema-based Validator"""

def __init__(self, schema_version: 'SchemaVersion') -> None:
self.__schema_version = schema_version
Expand All @@ -79,3 +81,39 @@ def output_format(self) -> OutputFormat:
def _schema_file(self) -> Optional[str]:
"""get the schema file according to schema version."""
...


@overload
def make_schemabased_validator(output_format: Literal[OutputFormat.JSON], schema_version: 'SchemaVersion'
) -> 'JsonValidator':
...


@overload
def make_schemabased_validator(output_format: Literal[OutputFormat.XML], schema_version: 'SchemaVersion'
) -> 'XmlValidator':
...


@overload
def make_schemabased_validator(output_format: OutputFormat, schema_version: 'SchemaVersion'
) -> Union['JsonValidator', 'XmlValidator']:
...


def make_schemabased_validator(output_format: OutputFormat, schema_version: 'SchemaVersion'
) -> 'BaseSchemabasedValidator':
"""get the default Schema-based Validator for a certain :class:``OutputFormat``.

Raises error when no instance could be made.
"""
if TYPE_CHECKING: # pragma: no cover
from typing import Type
Validator: Type[BaseSchemabasedValidator]
if OutputFormat.JSON is output_format:
from .json import JsonValidator as Validator
elif OutputFormat.XML is output_format:
from .xml import XmlValidator as Validator
else:
raise ValueError(f'Unexpected output_format: {output_format!r}')
return Validator(schema_version)
8 changes: 4 additions & 4 deletions cyclonedx/validation/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

from ..exception import MissingOptionalDependencyException
from ..schema._res import BOM_JSON as _S_BOM, BOM_JSON_STRICT as _S_BOM_STRICT, JSF as _S_JSF, SPDX_JSON as _S_SPDX
from . import BaseSchemaBasedValidator, SchemaBasedValidator, ValidationError
from . import BaseSchemabasedValidator, SchemabasedValidator, ValidationError

_missing_deps_error: Optional[Tuple[MissingOptionalDependencyException, ImportError]] = None
try:
Expand All @@ -45,7 +45,7 @@
), err


class _BaseJsonValidator(BaseSchemaBasedValidator, ABC):
class _BaseJsonValidator(BaseSchemabasedValidator, ABC):
@property
def output_format(self) -> Literal[OutputFormat.JSON]:
return OutputFormat.JSON
Expand Down Expand Up @@ -98,15 +98,15 @@ def __make_validator_registry() -> Registry[Any]:
])


class JsonValidator(_BaseJsonValidator, BaseSchemaBasedValidator, SchemaBasedValidator):
class JsonValidator(_BaseJsonValidator, BaseSchemabasedValidator, SchemabasedValidator):
"""Validator for CycloneDX documents in JSON format."""

@property
def _schema_file(self) -> Optional[str]:
return _S_BOM.get(self.schema_version)


class JsonStrictValidator(_BaseJsonValidator, BaseSchemaBasedValidator, SchemaBasedValidator):
class JsonStrictValidator(_BaseJsonValidator, BaseSchemabasedValidator, SchemabasedValidator):
"""Strict validator for CycloneDX documents in JSON format.

In contrast to :class:`~JsonValidator`,
Expand Down
61 changes: 0 additions & 61 deletions cyclonedx/validation/schema.py

This file was deleted.

6 changes: 3 additions & 3 deletions cyclonedx/validation/xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from ..exception import MissingOptionalDependencyException
from ..schema import OutputFormat
from ..schema._res import BOM_XML as _S_BOM
from . import BaseSchemaBasedValidator, SchemaBasedValidator, ValidationError
from . import BaseSchemabasedValidator, SchemabasedValidator, ValidationError

if TYPE_CHECKING: # pragma: no cover
from ..schema import SchemaVersion
Expand All @@ -37,7 +37,7 @@
), err


class _BaseXmlValidator(BaseSchemaBasedValidator, ABC):
class _BaseXmlValidator(BaseSchemabasedValidator, ABC):

@property
def output_format(self) -> Literal[OutputFormat.XML]:
Expand Down Expand Up @@ -86,7 +86,7 @@ def _validator(self) -> 'XMLSchema':
return self.__validator


class XmlValidator(_BaseXmlValidator, BaseSchemaBasedValidator, SchemaBasedValidator):
class XmlValidator(_BaseXmlValidator, BaseSchemabasedValidator, SchemabasedValidator):
"""Validator for CycloneDX documents in XML format."""

@property
Expand Down
9 changes: 5 additions & 4 deletions examples/complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
from cyclonedx.model import OrganizationalEntity, XsUri
from cyclonedx.model.bom import Bom
from cyclonedx.model.component import Component, ComponentType
from cyclonedx.output import get_instance as get_outputter
from cyclonedx.output import make_outputter, LATEST_SUPPORTED_SCHEMA_VERSION
from cyclonedx.output.json import JsonV1Dot4
from cyclonedx.schema import SchemaVersion, OutputFormat
from cyclonedx.validation.json import JsonStrictValidator
from cyclonedx.validation.schema import get_instance as get_validator
from cyclonedx.validation import make_schemabased_validator

from typing import TYPE_CHECKING

Expand Down Expand Up @@ -99,10 +99,11 @@
# region XML
"""demo with implicit instructions for SchemaVersion, outputter and validator. TypeCheckers will catch errors."""

my_xml_outputter: 'XmlOutputter' = get_outputter(bom, OutputFormat.XML)
my_xml_outputter: 'XmlOutputter' = make_outputter(bom, OutputFormat.XML, LATEST_SUPPORTED_SCHEMA_VERSION)
serialized_xml = my_xml_outputter.output_as_string(indent=2)
print(serialized_xml)
my_xml_validator: 'XmlValidator' = get_validator(my_xml_outputter.output_format, my_xml_outputter.schema_version)
my_xml_validator: 'XmlValidator' = make_schemabased_validator(
my_xml_outputter.output_format, my_xml_outputter.schema_version)
try:
validation_errors = my_xml_validator.validate_str(serialized_xml)
if validation_errors:
Expand Down
79 changes: 0 additions & 79 deletions tests/test_e2e_environment.py

This file was deleted.

Loading