This document is intended for automated, agentic helpers and human maintainers who want to understand how to work with the repository in the agentic age.
pyproject.toml
ruff.toml
mkdocs.yaml
.
├── cridlib/ # Python package
│ ├── __init__.py # public API: get, parse, CRIDError
│ ├── get.py # get() – generate a CRID for a given timestamp
│ ├── lib.py # CRID class, error hierarchy, canonicalize_show()
│ ├── parse.py # parse() – parse an existing CRID string
│ ├── util.py # get_session() – requests Session with retry/backoff
│ └── strategy/ # data-source strategies
│ ├── now.py # current show via songticker.rabe.ch
│ ├── past.py # past show via archiv.rabe.ch (RAAR)
│ └── future.py # future show via LibreTime API (internal)
├── docs/ # MkDocs documentation helpers
└── tests/ # pytest-based unit tests
├── conftest.py
├── strategy/
├── test_get.py
├── test_lib.py
└── test_parse.py
The code is a library that generates and parses
RaBe CRIDs (Content Reference
Identifiers). The public API is exposed via cridlib.get() and
cridlib.parse(). Depending on the requested timestamp the get() function
delegates to one of three strategy modules that call different RaBe services
to discover the show name.
-
Continuous Integration is GitHub Actions based; reusable workflows are referenced from the shared
radiorabe/actionsrepository:.github/workflows/lint-and-test.yaml– triggers on pushes to feature branches (notmain,develop, orgh-pages); runs pre-commit andpytestvia the sharedtest-pre-commitandtest-python-poetryreusable workflows..github/workflows/semantic-release.yaml– triggers on pushes tomain; bumps the version and creates a GitHub release based on conventional commit messages..github/workflows/release.yaml– triggers on pull requests, pushes tomain, and release creation events; builds and publishes the Python package to PyPI via the sharedrelease-python-poetryreusable workflow.
-
Release process follows the conventional commits standard. Commit type
fix:triggers a PATCH bump,feat:a MINOR bump, and a footerBREAKING CHANGE:a MAJOR bump. All other types are allowed but do not trigger a release. Once a commit lands onmain, the release and PyPI publish happen automatically.
Key modules:
-
lib.py– defines theCRIDclass (scheme validation, authority check, version parsing, show slug extraction, media-fragment clock parsing), acanonicalize_show()helper usingpython-slugify, and the full error hierarchy (CRIDErrorand subclasses). -
get.py– the main entry-pointget(timestamp, fragment). Compares the requested timestamp to now and dispatches tostrategy.now,strategy.past, orstrategy.futureto obtain the show name, then constructs and returns aCRID. -
parse.py– thin wrapper aroundCRID(value)that provides the publicparse()function. -
util.py–get_session()returns arequests.Sessionpre-configured with exponential-backoff retry logic. -
strategy/now.py– fetches the current show from the RaBe Songticker (songticker.rabe.ch) XML feed. -
strategy/past.py– fetches a past show from the RAAR archive API (archiv.rabe.ch). -
strategy/future.py– fetches a future show from the LibreTime live-info API (internal RaBe endpoint); covers at most seven days ahead.
Key characteristics:
- Fully type-annotated, linted with
ruff(all rules enabled, seeruff.toml), and statically checked viapytest-mypyintegrated into the test run. - All external HTTP calls are made through
util.get_session()and are mocked in tests withrequests_mock. - Show names are canonicalized to URL-safe slugs using
python-slugify. - Timestamps use
datetimewith explicit timezone awareness (pytz/zoneinfo).
-
Unit tests use
pytestwith fixtures defined intests/conftest.pyandtests/strategy/conftest.py;freezegunis used for deterministic timestamps. -
External HTTP calls are fully mocked via
requests_mockfixtures (klangbecken_mock,archiv_mock,libretime_mock, etc.), so the test suite runs entirely offline. Tests — including doctests — must never reach production APIs; always userequests_mockfixtures orrequests_mock.Mocker()context managers instead. -
The
pytestconfiguration inpyproject.tomlruns linting (--ruff), type-checking (--mypy), doctest extraction from Markdown files (--doctest-glob='*.md') and module docstrings (--doctest-modules), and enforces 100 % code coverage (--cov-fail-under=100). -
Tests are randomised (
--random-order) to surface order-dependent failures.
Maintainers (and intelligent agents) should be comfortable with:
- Python 3.12+ – typing, timezone handling (
zoneinfofrom the standard library for strategy modules,pytzas a third-party dependency used in tests and theget()docstring example),datetime,pathlib,xml.etree.ElementTree. - Poetry for dependency management and publishing.
- GitHub Actions & conventional commits for CI/CD and releases.
- pytest with mocking, doctest, and plugins (
pytest-cov,pytest-mypy,pytest-ruff,pytest-random-order,freezegun,requests_mock). - Libraries used:
requests(withHTTPAdapter/Retry) for HTTP calls.uritoolsfor URI composition and splitting.python-slugifyfor show-name canonicalization.pytz/zoneinfofor timezone conversions.
- Familiarity with the RaBe CRID spec and TV-Anytime media fragments.
- Understanding of the RaBe data sources: Songticker, RAAR archive, LibreTime.
Tests must never reach production APIs — all external HTTP calls must be mocked. No network access to RaBe services is required or permitted when running the test suite.
The following actions are good candidates for autonomous agents:
- Run the test suite and verify 100 % coverage. Always use
poetry run pytest(orpoetry shell+pytest) rather than installing packages system-wide; the lockfile ensures a reproducible environment. Ifpytest-mypyreports missing stubs, add the appropriatetypes-...packages viapoetry add --group dev. - Lint and type-check with
ruffand the pytest plugins; propose fixes for violations. - Dependency maintenance: test upgrades and raise PRs or apply fixes. An agent can monitor the GitHub Advisory DB for security issues.
- Merge request review: check for correctness, style, type annotations, and coverage.
- Documentation: regenerate API docs via
mkdocs/docs/gen_ref_pages.py; keepREADME.mdexamples in sync with the actual API. Agents may updateAGENTS.mditself. - Environment setup: ensure pre-commit hooks work (
pre-commit run --all-files) and thatpoetry installproduces a clean environment.
Agents must follow the existing conventional-commit rules when pushing changes.
# preferred: use Poetry to manage the environment
poetry install # creates and populates a virtualenv automatically
# run all tests (linting, type-checking, doctests, coverage)
poetry run pytest
# lint only
poetry run ruff check .
poetry run ruff format --check .
# build documentation locally
poetry run mkdocs serve
# if you need interactive access
poetry shellAgents should run inside an environment that has:
- Python 3.12 (or newer) with all
poetrydev dependencies installed viapoetry install. - Prefer
poetry runwhen executing tests, linters or scripts rather than manually creating or activating venvs. - Avoid system-wide
pip installto prevent "externally managed" environment errors. - Network access to GitHub and PyPI.
- Credential management (GitHub token, PyPI token) is handled via the
secretsmechanism in GitHub Actions; agents must not hardcode secrets.
This file may be updated over time as new responsibilities arise or the
project evolves. See README.md for user-facing instructions and refer back
here for agentic assistance guidelines.