Skip to main content

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

Python Pydantic FastAPI Uvicorn OpenAPI uv Hatch Ruff mypy pytest pytest-cov pip-audit pre-commit GNU Make Docker GitHub Actions


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)

Source distribution for dsv-parser 1.0.0
File Size Uploaded
dsv_parser-1.0.0.tar.gz 68.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dsv-parser 1.0.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page