DSV Parser
Parser for DSV swim-meet files (.dsv5 through .dsv8, including .dsv8z) into a typed data schema. Usable as a Python library, as a CLI, and as a FastAPI service whose OpenAPI document exposes the same schema to services in other languages.
Format 6, 7 and 8 are covered in full, transcribed from the official specifications of the Deutscher Schwimm-Verband.
Tech Stack
Format Coverage
| Format | Valid | State |
|---|---|---|
| 8 | from 01.08.2026 | Complete, specification of 14.03.2026 |
| 7 | 01.01.2023 – 31.12.2026 | Complete, specification of 31.08.2022 |
| 6 | 01.09.2015 – 31.07.2023 | Complete, specification of 01.11.2015 |
| 5 | until 31.12.2015 | Derived from the Format 6 change log |
All four types (Wettkampfdefinitions-, Vereinsmelde-, Vereinsergebnis- and Wettkampfergebnisliste) with every element and attribute. The packed .dsv8z variant is unwrapped transparently.
Checked against nine real EasyWk files in Format 6 and 7, about 26 000 elements, with no errors or warnings. Details in the format reference.
Quick Start
Prerequisites
| Tool | Version | Needed for |
|---|---|---|
| uv | — | dependencies, every make target |
| Python | 3.12 | fetched by uv from .python-version |
| Docker + Compose | — | make up, make image |
| pre-commit | — | the formatting hook before a commit (optional) |
Install
As a dependency of another project:
pip install dsv-parser # library + CLI
pip install "dsv-parser[api]" # plus the FastAPI service
uv add dsv-parser
Every GitHub Release is published to PyPI automatically, so the version there tracks the tags in this repository.
To work on the parser itself:
make install # uv sync --extra api
The api extra adds FastAPI and uvicorn. The parser itself needs only Pydantic, so a library-only consumer can leave the extra out.
Run
make dev # CLI help with every subcommand
make spec # the element table as implemented
make serve # FastAPI on :8000 with reload
make up # the same in Docker
make ps # container status and health
make logs # follow the logs
make down # stop and remove
Use it
from dsv_parser import parse_file
result = parse_file("2026-06-13-Berlin-Pr.DSV8")
print(result.document.meet.name, result.document.file_type)
for swim in result.document.individual_results:
print(swim.place, swim.name, swim.time_millis)
for entry in result.diagnostics.entries:
print(entry.render())
dsv-parser parse meet.DSV8 -o meet.json # document as JSON
dsv-parser parse meet.DSV8 --summary # header and element counts only
dsv-parser check meet.DSV8 # validate, exit 1 on data loss
dsv-parser spec --json # element table as data
HTTP Surface
| Method | Path | Purpose |
|---|---|---|
POST |
/parse |
Parse a file and return the document |
POST |
/check |
Validate a file without returning the document |
GET |
/spec |
Element table and all code lists |
GET |
/health |
Liveness and the supported format versions |
GET |
/openapi.json |
The schema, for generated clients |
curl -F file=@meet.DSV8 http://localhost:8000/parse
curl -F file=@meet.DSV8 http://localhost:8000/check
A readable upload always returns 200. Content problems come back as diagnostics rather than HTTP errors, since a partially readable file is a normal result. Check clean and diagnostics, not the status code.
The document schema in /openapi.json is the same Pydantic model the library returns. See the HTTP API.
Configuration
| Variable | Default | Effect |
|---|---|---|
LOG_LEVEL |
INFO |
Log level |
There is nothing else. The service holds no state and can be mounted into another app with app.include_router(dsv_parser.api.router).
Design
The attribute layouts live as data in dsv_parser/spec/elements.py, one entry per element, with versions= and file_types= wherever the four format versions or the four list kinds differ. For example, WETTKAMPF has no best-list attribute in a Vereinsmeldeliste, which moves the two qualification attributes one position forward. In the table that is a single file_types= on one attribute.
flowchart LR
A["bytes<br/>.dsv · .dsv8z"] -->|decoding| B["text"]
B -->|lexer| C["element lines"]
C -->|binder| D["element models"]
D -->|parser| E["DsvDocument"]
T[("spec table<br/>spec/elements.py")] -.->|layout| C
T -.->|layout| D
C -.-> G(["diagnostics"])
D -.-> G
E -.-> G
More in the architecture notes.
Common Commands
make help # every target
make test # unit tests, offline, no coverage gate
make test-it # full run incl. integration and coverage
make lint # ruff check
make format # ruff: import order and formatting
make format-check # the same, read-only
make typecheck # mypy
make audit # pip-audit
make image # build the runtime image
make clean # remove caches and the venv
Further Reading
- Architecture — pipeline, element table, decisions
- Format reference — the format and the version differences
- Data schema — how the document is laid out
- HTTP API — endpoints, payloads, client generation
- CLI — subcommands, flags, exit codes
- Extending — adding elements, versions and code lists
License
MIT — use it, change it, ship it, commercially or not.
Metadata
Release files for dsv-parser 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dsv_parser-1.0.0.tar.gz | 68.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dsv_parser-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 121.8 kB
Release files / dsv_parser-1.0.0.tar.gz
| Download URL | dsv_parser-1.0.0.tar.gz |
|---|---|
| Size | 68.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1446fdf21c6c01ee5a4e302da9b2f7c3aa244be1fb59f1da43277634a34a8594
|
|
BLAKE2b-256 checksum How to use checksums |
42fbd634dc44423950ead64f101e047dae0af857d5d902767dd654242f56ba81
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.
Transparency logRelease files / dsv_parser-1.0.0-py3-none-any.whl
| Download URL | dsv_parser-1.0.0-py3-none-any.whl |
|---|---|
| Size | 53.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
548258ee7d968bc26fc0147a5b5ea3bc965862cbf49b31ac32c211f53e5cb42c
|
|
BLAKE2b-256 checksum How to use checksums |
3347873f50025d384e13f9ad6488fd618929faf5928c9c7fa3fe1e1d23846fb1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.
Transparency log