Coverage for /home/benjarobin/Bootlin/projects/Schneider-Electric-Senux/sbom-cve-check/src/sbom_cve_check/sbom/registry.py: 97%
35 statements
« prev ^ index » next coverage.py v7.11.1, created at 2025-11-28 15:37 +0100
« prev ^ index » next coverage.py v7.11.1, created at 2025-11-28 15:37 +0100
1# -*- coding: utf-8 -*-
2# SPDX-License-Identifier: GPL-2.0-only
4import pathlib
5from collections.abc import Callable, Iterable
6from typing import TypeVar
8from ..utils.class_utils import Singleton
9from ..utils.plugin import import_builtin_plugin
10from .sbom_base import Sbom
12_SbomT = TypeVar("_SbomT", bound=Sbom)
15class SbomTypeRegistry(metaclass=Singleton):
16 def __init__(self) -> None:
17 self._sbom_types: dict[str, type[Sbom]] = {}
19 def register_type(self, type_name: str, sbom_type: type[Sbom]) -> None:
20 assert type_name not in self._sbom_types
21 self._sbom_types[type_name] = sbom_type
23 @property
24 def type_names(self) -> Iterable[str]:
25 return self._sbom_types.keys()
27 def create(self, type_name: str | None, path: pathlib.Path) -> Sbom:
28 if type_name is None:
29 # Try to autodetect SBOM type from the file extension
30 for name, sbom_type in self._sbom_types.items():
31 if sbom_type.can_handle_sbom(path):
32 type_name = name
33 break
34 else:
35 raise ValueError(f"Can not autodetect SBOM format: {path.name}")
37 cls_sbom: type[Sbom] = self._sbom_types[type_name]
38 return cls_sbom(path)
41def register_sbom(name: str) -> Callable[[type[_SbomT]], type[_SbomT]]:
42 def decorator(cls: type[_SbomT]) -> type[_SbomT]:
43 SbomTypeRegistry().register_type(name, cls)
44 return cls
46 return decorator
49def __register_builtin_types() -> None:
50 modules = [".sbom_spdx2", ".sbom_spdx3"]
51 for mod in modules:
52 import_builtin_plugin(__package__, mod)
55__register_builtin_types()