Skip to content

Commit 5f4e240

Browse files
Add tests cleanup readme (#2232)
1 parent cf97c27 commit 5f4e240

29 files changed

Lines changed: 6288 additions & 628 deletions

sbom/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ package(default_visibility = ["//visibility:public"])
1414
exports_files([
1515
"defs.bzl",
1616
"extensions.bzl",
17+
"cpp_metadata.json",
18+
"crates_metadata.json",
1719
])
1820

1921
# Filegroup for all SBOM-related bzl files

sbom/SBOM_Readme.md

Lines changed: 70 additions & 230 deletions
Large diffs are not rendered by default.

sbom/docs/requirements/component_requirements.rst

Lines changed: 0 additions & 88 deletions
This file was deleted.

sbom/docs/requirements/feature_requirements.rst

Lines changed: 0 additions & 92 deletions
This file was deleted.

sbom/internal/generator/BUILD

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,19 @@ py_library(
2626
],
2727
)
2828

29+
py_library(
30+
name = "utils",
31+
srcs = ["utils.py"],
32+
)
33+
2934
py_library(
3035
name = "spdx_formatter",
3136
srcs = ["spdx_formatter.py"],
37+
deps = [":utils"],
3238
)
3339

3440
py_library(
3541
name = "cyclonedx_formatter",
3642
srcs = ["cyclonedx_formatter.py"],
43+
deps = [":utils"],
3744
)

sbom/internal/generator/cyclonedx_formatter.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,10 @@
66
CycloneDX 1.6 Specification: https://cyclonedx.org/docs/1.6/json/
77
"""
88

9-
import re
109
import uuid
1110
from typing import Any
1211

13-
14-
def _normalize_spdx_license(expr: str) -> str:
15-
"""Normalize SPDX boolean operators to uppercase as required by the spec.
16-
17-
dash-license-scan returns lowercase operators (e.g. 'Apache-2.0 or MIT').
18-
SPDX 2.3 Appendix IV and CycloneDX 1.6 both require uppercase OR/AND/WITH.
19-
Uses space-delimited substitution to avoid modifying license identifiers
20-
that contain 'or'/'and' as substrings (e.g. GPL-2.0-or-later).
21-
"""
22-
expr = re.sub(r" or ", " OR ", expr, flags=re.IGNORECASE)
23-
expr = re.sub(r" and ", " AND ", expr, flags=re.IGNORECASE)
24-
expr = re.sub(r" with ", " WITH ", expr, flags=re.IGNORECASE)
25-
return expr
12+
from sbom.internal.generator.utils import _normalize_spdx_license
2613

2714

2815
def generate_cyclonedx(

sbom/internal/generator/sbom_generator.py

Lines changed: 40 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,44 @@ def filter_repos(repos: list[str], exclude_patterns: list[str]) -> list[str]:
546546
return filtered
547547

548548

549+
def _build_crate_result(
550+
crate_name: str,
551+
version: str,
552+
crate_meta: dict[str, Any],
553+
) -> dict[str, Any]:
554+
"""Build a crate component dict from parsed name/version and cache metadata."""
555+
result: dict[str, Any] = {
556+
"name": crate_name,
557+
"version": version,
558+
"purl": f"pkg:cargo/{crate_name}@{version}",
559+
"type": "library",
560+
"source": "crates.io",
561+
}
562+
if crate_meta.get("license"):
563+
result["license"] = crate_meta["license"]
564+
if crate_meta.get("description"):
565+
result["description"] = crate_meta["description"]
566+
if crate_meta.get("supplier"):
567+
result["supplier"] = crate_meta["supplier"]
568+
if crate_meta.get("cpe"):
569+
result["cpe"] = crate_meta["cpe"]
570+
if crate_meta.get("aliases"):
571+
result["aliases"] = crate_meta["aliases"]
572+
if crate_meta.get("pedigree_ancestors"):
573+
result["pedigree_ancestors"] = crate_meta["pedigree_ancestors"]
574+
if crate_meta.get("pedigree_descendants"):
575+
result["pedigree_descendants"] = crate_meta["pedigree_descendants"]
576+
if crate_meta.get("pedigree_variants"):
577+
result["pedigree_variants"] = crate_meta["pedigree_variants"]
578+
if crate_meta.get("pedigree_notes"):
579+
result["pedigree_notes"] = crate_meta["pedigree_notes"]
580+
if crate_meta.get("repository"):
581+
result["url"] = crate_meta["repository"]
582+
if crate_meta.get("checksum"):
583+
result["checksum"] = crate_meta["checksum"]
584+
return result
585+
586+
549587
def resolve_component(
550588
repo_name: str, metadata: dict[str, Any]
551589
) -> dict[str, Any] | None:
@@ -711,37 +749,7 @@ def resolve_component(
711749
crate_meta = cached_crates.get(crate_name) or cached_crates.get(
712750
crate_name.replace("-", "_"), {}
713751
)
714-
715-
result = {
716-
"name": crate_name,
717-
"version": version,
718-
"purl": f"pkg:cargo/{crate_name}@{version}",
719-
"type": "library",
720-
"source": "crates.io",
721-
}
722-
if crate_meta.get("license"):
723-
result["license"] = crate_meta["license"]
724-
if crate_meta.get("description"):
725-
result["description"] = crate_meta["description"]
726-
if crate_meta.get("supplier"):
727-
result["supplier"] = crate_meta["supplier"]
728-
if crate_meta.get("cpe"):
729-
result["cpe"] = crate_meta["cpe"]
730-
if crate_meta.get("aliases"):
731-
result["aliases"] = crate_meta["aliases"]
732-
if crate_meta.get("pedigree_ancestors"):
733-
result["pedigree_ancestors"] = crate_meta["pedigree_ancestors"]
734-
if crate_meta.get("pedigree_descendants"):
735-
result["pedigree_descendants"] = crate_meta["pedigree_descendants"]
736-
if crate_meta.get("pedigree_variants"):
737-
result["pedigree_variants"] = crate_meta["pedigree_variants"]
738-
if crate_meta.get("pedigree_notes"):
739-
result["pedigree_notes"] = crate_meta["pedigree_notes"]
740-
if crate_meta.get("repository"):
741-
result["url"] = crate_meta["repository"]
742-
if crate_meta.get("checksum"):
743-
result["checksum"] = crate_meta["checksum"]
744-
return result
752+
return _build_crate_result(crate_name, version, crate_meta)
745753

746754
# Handle legacy crate universe format (e.g., crates_io__tokio-1.10.0)
747755
if repo_name.startswith("crates_io__") or "_crates__" in repo_name:
@@ -759,37 +767,7 @@ def resolve_component(
759767
crate_meta = cached_crates.get(crate_name) or cached_crates.get(
760768
crate_name.replace("-", "_"), {}
761769
)
762-
763-
result = {
764-
"name": crate_name,
765-
"version": version,
766-
"purl": f"pkg:cargo/{crate_name}@{version}",
767-
"type": "library",
768-
"source": "crates.io",
769-
}
770-
if crate_meta.get("license"):
771-
result["license"] = crate_meta["license"]
772-
if crate_meta.get("description"):
773-
result["description"] = crate_meta["description"]
774-
if crate_meta.get("supplier"):
775-
result["supplier"] = crate_meta["supplier"]
776-
if crate_meta.get("cpe"):
777-
result["cpe"] = crate_meta["cpe"]
778-
if crate_meta.get("aliases"):
779-
result["aliases"] = crate_meta["aliases"]
780-
if crate_meta.get("pedigree_ancestors"):
781-
result["pedigree_ancestors"] = crate_meta["pedigree_ancestors"]
782-
if crate_meta.get("pedigree_descendants"):
783-
result["pedigree_descendants"] = crate_meta["pedigree_descendants"]
784-
if crate_meta.get("pedigree_variants"):
785-
result["pedigree_variants"] = crate_meta["pedigree_variants"]
786-
if crate_meta.get("pedigree_notes"):
787-
result["pedigree_notes"] = crate_meta["pedigree_notes"]
788-
if crate_meta.get("repository"):
789-
result["url"] = crate_meta["repository"]
790-
if crate_meta.get("checksum"):
791-
result["checksum"] = crate_meta["checksum"]
792-
return result
770+
return _build_crate_result(crate_name, version, crate_meta)
793771

794772
# Check if repo is a sub-library of a known parent (e.g., boost.config+ -> boost)
795773
# rules_boost splits Boost into individual repos like boost.config+, boost.assert+, etc.

sbom/internal/generator/spdx_formatter.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,7 @@
1010
import uuid
1111
from typing import Any
1212

13-
14-
def _normalize_spdx_license(expr: str) -> str:
15-
"""Normalize SPDX boolean operators to uppercase as required by the spec.
16-
17-
dash-license-scan returns lowercase operators (e.g. 'Apache-2.0 or MIT').
18-
SPDX 2.3 requires uppercase OR/AND/WITH (Appendix IV).
19-
Uses space-delimited substitution to avoid modifying license identifiers
20-
that contain 'or'/'and' as substrings (e.g. GPL-2.0-or-later).
21-
"""
22-
expr = re.sub(r" or ", " OR ", expr, flags=re.IGNORECASE)
23-
expr = re.sub(r" and ", " AND ", expr, flags=re.IGNORECASE)
24-
expr = re.sub(r" with ", " WITH ", expr, flags=re.IGNORECASE)
25-
return expr
13+
from sbom.internal.generator.utils import _normalize_spdx_license
2614

2715

2816
def generate_spdx(

sbom/internal/generator/utils.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""Shared utilities for SBOM formatters."""
2+
3+
import re
4+
5+
6+
def _normalize_spdx_license(expr: str) -> str:
7+
"""Normalize SPDX boolean operators to uppercase as required by the spec.
8+
9+
dash-license-scan returns lowercase operators (e.g. 'Apache-2.0 or MIT').
10+
SPDX 2.3 requires uppercase OR/AND/WITH (Appendix IV).
11+
Uses space-delimited substitution to avoid modifying license identifiers
12+
that contain 'or'/'and' as substrings (e.g. GPL-2.0-or-later).
13+
"""
14+
expr = re.sub(r" or ", " OR ", expr, flags=re.IGNORECASE)
15+
expr = re.sub(r" and ", " AND ", expr, flags=re.IGNORECASE)
16+
expr = re.sub(r" with ", " WITH ", expr, flags=re.IGNORECASE)
17+
return expr

0 commit comments

Comments
 (0)