meta_package_manager.sbom packageΒΆ
Export the installed-package inventory as Software Bill of Materials documents.
This subpackage is the home of every SBOM-flavored writer in mpm. Its
existence mirrors the optional [sbom] install extra defined in
pyproject.toml: a default pip install meta-package-manager does not
pull cyclonedx-python-lib or spdx-tools, so the modules below guard
their heavy imports with try/except and expose
spdx_support / cyclonedx_support flags that callers check before
instantiating the rendering classes.
Modules:
meta_package_manager.sbom.basedefinesSBOM, the abstract base each format extends, andExportFormat, the user-facing format enum.meta_package_manager.sbom.spdxdefinesSPDX, the SPDX 2.3 writer including the per-package upstream-SBOM merge logic that powers--bundledmode on Homebrew formulae shipped withHOMEBREW_SBOM=1.meta_package_manager.sbom.cyclonedxdefinesCycloneDX, the CycloneDX 1.7 writer.
The public surface re-exported here is the only API
meta_package_manager.cli and the test suite depend on. Internal
helpers (license parsing, checksum maps, etc.) stay in their respective
format modules.
- class meta_package_manager.sbom.SBOM(export_format=ExportFormat.JSON)[source]ΒΆ
Bases:
objectUtilities shared by all SBOM classes.
Defaults to JSON export format.
- bundled_scan: bool = TrueΒΆ
Whether the scan was a
--bundledenrichment pass.Set by
set_scan_completeness()from the CLI.Truemeans the metadata extractors ran and upstream per-package SBOMs were merged (the default).Falseis the--minimalmode: bare inventory only, no extractor calls. Subclasses use this flag to populate completeness markers in their respective standards (incompletevscompletein CycloneDX,EXTRACTEDlicense handling in SPDX).
- stats()[source]ΒΆ
Return a summary of what landed in the document.
Format-agnostic counters live in the base implementation; SPDX and CycloneDX subclasses extend the returned dict with their own merged-documents, dependency-graph, and any other format-specific counts. Surfaced by the CLI as a post-run INFO-level summary and usable by tests or programmatic consumers without re-parsing the rendered document.
- set_scan_completeness(bundled)[source]ΒΆ
Record whether the run was a bundled enrichment pass.
Called once by the CLI right after
init_doc()and before the firstadd_package(). The information flows into per-format completeness markers in the rendered document.- Return type:
- finalize()[source]ΒΆ
Resolve any deferred state before
export().Some constructs cannot be emitted at
add_package()time because they reference packages that may not have been added yet: a Homebrew formulaβs runtime dependency on another formula listed later in the scan, for example. Subclasses queue those duringadd_packageand flush them here. The base implementation is a no-op so subclasses can rely on it being called exactly once.- Return type:
- class meta_package_manager.sbom.SPDX(export_format=ExportFormat.JSON)[source]ΒΆ
Bases:
SBOMGenerates an SPDX document from a list of packages.
Defaults to JSON export format.
- DOC_ID = 'SPDXRef-DOCUMENT'ΒΆ
Document root ID.
- document: DocumentΒΆ
- classmethod normalize_spdx_id(str)[source]ΒΆ
SPDX IDs must only contain letters, numbers,
.and-.- Return type:
- init_doc()[source]ΒΆ
SPDX document metadata specifications.
- Return type:
- add_package(manager, package, metadata=PackageMetadata(download_url=None, homepage=None, vcs_url=None, issue_tracker_url=None, distribution_url=None, license_declared=None, license_concluded=None, copyright_text=None, supplier=None, originator=None, description=None, summary=None, cpe=None, dependencies=(), checksums=(), files=(), files_analyzed=False, install_date=None, build_date=None, release_date=None, external_sbom_path=None, extra_purls=(), extras={}))[source]ΒΆ
SPDX package metadata specifications.
- Return type:
- finalize()[source]ΒΆ
Emit pending dependency relationships.
Walks the queue built by
add_package()and emits each relationship only when both ends resolve to packages we actually included in the document. Dangling references (the target package is not installed) are dropped silently: the SBOM only describes what is on the system, not what could be.- Return type:
- stats()[source]ΒΆ
Extend the base stats with SPDX-specific counters.
Adds the number of upstream documents merged into the aggregate, the count of transitive packages those upstream documents contributed (over and above the inventory pass), and the total relationship count partitioned into dependency vs descriptive edges.
packages_totalfrom the base reports inventory packages only;packages_in_documenthere is the full count after merge, which is what consumers of the file actually see.
- class meta_package_manager.sbom.CycloneDX(export_format=ExportFormat.JSON)[source]ΒΆ
Bases:
SBOMGenerates a CycloneDX document from a list of packages.
Defaults to JSON export format.
- document: BomΒΆ
- init_doc()[source]ΒΆ
CycloneDX document metadata specifications.
- Return type:
- add_package(manager, package, metadata=PackageMetadata(download_url=None, homepage=None, vcs_url=None, issue_tracker_url=None, distribution_url=None, license_declared=None, license_concluded=None, copyright_text=None, supplier=None, originator=None, description=None, summary=None, cpe=None, dependencies=(), checksums=(), files=(), files_analyzed=False, install_date=None, build_date=None, release_date=None, external_sbom_path=None, extra_purls=(), extras={}))[source]ΒΆ
CycloneDX package metadata specifications.
- Return type:
- finalize()[source]ΒΆ
Resolve queued dependency edges between Components.
Mirrors
meta_package_manager.sbom.spdx.SPDX.finalize(). Dangling references (the dependency target is not in the inventory) are dropped silently.- Return type:
- stats()[source]ΒΆ
Extend the base stats with CycloneDX-specific counters.
CycloneDX has no merge-content equivalent: per-package upstream SBOMs are linked through
externalReferences[type=bom]rather than spliced in. The merged-document count therefore reports the number of components carrying a BOM external reference. The dependency-edge total walks the registered dependency graph and sums thedependsOncollection size across every entry.
- export()[source]ΒΆ
Serialize the document to its string representation.
Note
Unlike
meta_package_manager.sbom.spdx.SPDX.export(), the generated document is not validated against its schema here. CycloneDX schema validation relies oncyclonedx-python-libβs[validation]extra, which pulls injsonschemaand, transitively,rfc3987-syntax,lark, andlxml. To keep that stack out ofmpmβs runtime dependencies, the validation runs in the test suite instead. Seetests/test_cli_sbom.py.- Return type:
- class meta_package_manager.sbom.ExportFormat(*values)[source]ΒΆ
Bases:
StrEnumA user-friendly version of
spdx_tools.spdx.formats.FileFormat.Map format to user-friendly IDs.
- JSON = 'json'ΒΆ
- XML = 'xml'ΒΆ
- YAML = 'yaml'ΒΆ
- TAG_VALUE = 'tag'ΒΆ
- RDF_XML = 'rdf'ΒΆ
SubmodulesΒΆ
meta_package_manager.sbom.base moduleΒΆ
Format-agnostic SBOM base class and export-format enum.
Kept deliberately free of SPDX or CycloneDX dependencies: instantiating
SBOM directly is meaningless, but importing the symbols here
is safe even when the optional [sbom] extra is not installed.
- class meta_package_manager.sbom.base.ExportFormat(*values)[source]ΒΆ
Bases:
StrEnumA user-friendly version of
spdx_tools.spdx.formats.FileFormat.Map format to user-friendly IDs.
- JSON = 'json'ΒΆ
- XML = 'xml'ΒΆ
- YAML = 'yaml'ΒΆ
- TAG_VALUE = 'tag'ΒΆ
- RDF_XML = 'rdf'ΒΆ
- class meta_package_manager.sbom.base.SBOM(export_format=ExportFormat.JSON)[source]ΒΆ
Bases:
objectUtilities shared by all SBOM classes.
Defaults to JSON export format.
- bundled_scan: bool = TrueΒΆ
Whether the scan was a
--bundledenrichment pass.Set by
set_scan_completeness()from the CLI.Truemeans the metadata extractors ran and upstream per-package SBOMs were merged (the default).Falseis the--minimalmode: bare inventory only, no extractor calls. Subclasses use this flag to populate completeness markers in their respective standards (incompletevscompletein CycloneDX,EXTRACTEDlicense handling in SPDX).
- stats()[source]ΒΆ
Return a summary of what landed in the document.
Format-agnostic counters live in the base implementation; SPDX and CycloneDX subclasses extend the returned dict with their own merged-documents, dependency-graph, and any other format-specific counts. Surfaced by the CLI as a post-run INFO-level summary and usable by tests or programmatic consumers without re-parsing the rendered document.
- set_scan_completeness(bundled)[source]ΒΆ
Record whether the run was a bundled enrichment pass.
Called once by the CLI right after
init_doc()and before the firstadd_package(). The information flows into per-format completeness markers in the rendered document.- Return type:
- finalize()[source]ΒΆ
Resolve any deferred state before
export().Some constructs cannot be emitted at
add_package()time because they reference packages that may not have been added yet: a Homebrew formulaβs runtime dependency on another formula listed later in the scan, for example. Subclasses queue those duringadd_packageand flush them here. The base implementation is a no-op so subclasses can rely on it being called exactly once.- Return type:
meta_package_manager.sbom.cyclonedx moduleΒΆ
CycloneDX 1.7 writer.
Heavy cyclonedx-python-lib imports are guarded behind a try/except
block; cyclonedx_support reports whether the
CycloneDX class can actually be used.
The license-normalization helper is shared with spdx and is
imported from there rather than duplicated: SPDX license expressions are
the lingua franca CycloneDX builds on, so the dependency direction is
intentional and acyclic.
- class meta_package_manager.sbom.cyclonedx.CycloneDX(export_format=ExportFormat.JSON)[source]ΒΆ
Bases:
SBOMGenerates a CycloneDX document from a list of packages.
Defaults to JSON export format.
- document: BomΒΆ
- init_doc()[source]ΒΆ
CycloneDX document metadata specifications.
- Return type:
- add_package(manager, package, metadata=PackageMetadata(download_url=None, homepage=None, vcs_url=None, issue_tracker_url=None, distribution_url=None, license_declared=None, license_concluded=None, copyright_text=None, supplier=None, originator=None, description=None, summary=None, cpe=None, dependencies=(), checksums=(), files=(), files_analyzed=False, install_date=None, build_date=None, release_date=None, external_sbom_path=None, extra_purls=(), extras={}))[source]ΒΆ
CycloneDX package metadata specifications.
- Return type:
- finalize()[source]ΒΆ
Resolve queued dependency edges between Components.
Mirrors
meta_package_manager.sbom.spdx.SPDX.finalize(). Dangling references (the dependency target is not in the inventory) are dropped silently.- Return type:
- stats()[source]ΒΆ
Extend the base stats with CycloneDX-specific counters.
CycloneDX has no merge-content equivalent: per-package upstream SBOMs are linked through
externalReferences[type=bom]rather than spliced in. The merged-document count therefore reports the number of components carrying a BOM external reference. The dependency-edge total walks the registered dependency graph and sums thedependsOncollection size across every entry.
- export()[source]ΒΆ
Serialize the document to its string representation.
Note
Unlike
meta_package_manager.sbom.spdx.SPDX.export(), the generated document is not validated against its schema here. CycloneDX schema validation relies oncyclonedx-python-libβs[validation]extra, which pulls injsonschemaand, transitively,rfc3987-syntax,lark, andlxml. To keep that stack out ofmpmβs runtime dependencies, the validation runs in the test suite instead. Seetests/test_cli_sbom.py.- Return type:
meta_package_manager.sbom.spdx moduleΒΆ
SPDX 2.3 writer plus the per-package upstream-SBOM merge logic.
Heavy spdx_tools imports are guarded behind a try/except block so
this module is importable even when the optional [sbom] extra is not
installed; in that case spdx_support is False and the
SPDX class is still defined for type-hint compatibility but
will not function (every public method depends on the missing imports).
_parse_license_expression and _coerce_spdx_string live here
because they both touch spdx_tools types; cyclonedx
imports the former for its own license normalization, which is one-way
and acyclic.
- class meta_package_manager.sbom.spdx.SPDX(export_format=ExportFormat.JSON)[source]ΒΆ
Bases:
SBOMGenerates an SPDX document from a list of packages.
Defaults to JSON export format.
- DOC_ID = 'SPDXRef-DOCUMENT'ΒΆ
Document root ID.
- document: DocumentΒΆ
- classmethod normalize_spdx_id(str)[source]ΒΆ
SPDX IDs must only contain letters, numbers,
.and-.- Return type:
- init_doc()[source]ΒΆ
SPDX document metadata specifications.
- Return type:
- add_package(manager, package, metadata=PackageMetadata(download_url=None, homepage=None, vcs_url=None, issue_tracker_url=None, distribution_url=None, license_declared=None, license_concluded=None, copyright_text=None, supplier=None, originator=None, description=None, summary=None, cpe=None, dependencies=(), checksums=(), files=(), files_analyzed=False, install_date=None, build_date=None, release_date=None, external_sbom_path=None, extra_purls=(), extras={}))[source]ΒΆ
SPDX package metadata specifications.
- Return type:
- finalize()[source]ΒΆ
Emit pending dependency relationships.
Walks the queue built by
add_package()and emits each relationship only when both ends resolve to packages we actually included in the document. Dangling references (the target package is not installed) are dropped silently: the SBOM only describes what is on the system, not what could be.- Return type:
- stats()[source]ΒΆ
Extend the base stats with SPDX-specific counters.
Adds the number of upstream documents merged into the aggregate, the count of transitive packages those upstream documents contributed (over and above the inventory pass), and the total relationship count partitioned into dependency vs descriptive edges.
packages_totalfrom the base reports inventory packages only;packages_in_documenthere is the full count after merge, which is what consumers of the file actually see.