|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +Library wrapping [`cyclonedx-python-lib`](https://github.com/CycloneDX/cyclonedx-python-lib) to read/write Siemens [Standard BOM](https://sbom.siemens.io/latest/format.html) (a CycloneDX-compatible SBOM format). Source in [`siemens_standard_bom/`](siemens_standard_bom/). |
| 4 | + |
| 5 | +## Commands (run from repo root) |
| 6 | +- Full check (lint + type + tests, Python 3.10-3.14): `poetry run tox run` |
| 7 | +- Lint + types only: `poetry run tox run -e lint,type` |
| 8 | +- Tests on one interpreter: `poetry run tox run -e 3.12` |
| 9 | +- Single test: `poetry run python -m unittest tests.test_v3_parser.SbomV3ParserTestCase.test_read_sunny_day` |
| 10 | + |
| 11 | +Config: [`tox.toml`](tox.toml), [`pyproject.toml`](pyproject.toml), [`.flake8`](.flake8), [`.mypy.ini`](.mypy.ini). |
| 12 | + |
| 13 | +## Testing |
| 14 | +- Uses stdlib [`unittest`](https://docs.python.org/3/library/unittest.html) (via `unittest discover`), NOT [pytest](https://docs.pytest.org/) -- pytest is installed but not the runner. |
| 15 | +- Run from repo root only: tests read fixtures by relative path ([`tests/v2/`](tests/v2/), [`tests/v3/`](tests/v3/)) and write to `output/` at repo root (gitignored, auto-created). |
| 16 | +- Comparison tests use [`deepdiff`](https://github.com/seperman/deepdiff) and intentionally exclude `bom_ref` values from diffs ([`tests/abstract_sbom_compare.py`](tests/abstract_sbom_compare.py)). |
| 17 | + |
| 18 | +## Architecture |
| 19 | +- Thin wrapper: `StandardBom` wraps `cyclonedx.model.bom.Bom`; `SbomComponent`/`SourceArtifact`/`ExternalComponent` wrap CycloneDX models. Reach the underlying object via `.bom` / `.component`. See [`model.py`](siemens_standard_bom/model.py). |
| 20 | +- Siemens-specific fields are NOT native CycloneDX: they're stored as `Property` entries keyed `siemens:*` (constants at top of [`model.py`](siemens_standard_bom/model.py)) or as typed `ExternalReference`s. Add a field by adding a constant + property getter/setter following existing patterns. |
| 21 | +- Reader supports BOTH v2 and v3 Standard BOM (see backward-compat branches in the `tools`/`authors` getters); keep both working. |
| 22 | +- Output is always CycloneDX JSON v1.6 (`JsonV1Dot6`). [`StandardBomParser.save(..., with_dependencies=False)`](siemens_standard_bom/parser.py) re-reads and strips `dependencies` from the file (prohibited in the [`external` profile](https://sbom.siemens.io/v3/profiles.html)). |
| 23 | + |
| 24 | +## Conventions |
| 25 | +- [mypy](https://mypy.readthedocs.io/en/stable/) `strict = True`, `implicit_reexport = False`; [flake8](https://flake8.pycqa.org/) max line length 140, max complexity 8, doctests checked. |
| 26 | +- Requires Python >=3.10,<4.0 and [Poetry](https://python-poetry.org/) >= 2.0. |
| 27 | +- Release: bump `version` in [`pyproject.toml`](pyproject.toml); pushing a `vX.Y.Z` tag publishes to [PyPI](https://pypi.org/p/siemens-standard-bom) (see [`release.yml`](.github/workflows/release.yml)). The self tool-entry version reads from installed package metadata, so `poetry install` the package for it to report correctly. |
0 commit comments