USA Swimming meet result (.cl2 / SDIF v3) parser and analysis library
Project description
tunas
A Python library for parsing USA Swimming meet result files (.cl2 / Hy-Tek SDIF v3) into structured Python objects and performing offline qualifying time standard lookups.
📖 Documentation: https://ajoe2.github.io/tunas/
Installation
pip install tunas
Requires Python 3.12+ and has zero runtime dependencies outside the standard library.
Quick Start
read_cl2 is the main entry point. It parses files, directories, lists of paths, or text streams, returning a list of Meet objects and a ParseReport:
from tunas import read_cl2
meets, report = read_cl2("results.cl2")
for meet in meets:
print(f"{meet.name} ({meet.start_date})")
for swim in meet.individual_swims:
outcome = swim.time if swim.time is not None else swim.status.value
print(f" {swim.swimmer.full_name:<24} {swim.event.name:<16} {outcome}")
if report.warnings:
print(f"{len(report.warnings)} records flagged — inspect report.warnings")
Core Concepts
All parsed data is contained in independent Meet objects:
Meet: Ownsswimmers,clubs, andresults(split intomeet.individual_swimsandmeet.relays).- Swim: Has a
.time(TimeorNone) and.status(ResultStatuse.g.,OK,DQ,NS). Scratches and disqualifications are preserved. Event: An enum of(distance, stroke, course). Filter withswimmer.swims_in(event)ormeet.individual_swims_for(event).- Relays: Contain
RelaySwimlegs. Each leg reports its individual event, sorting alongside flat-start swims. - Scoping: Meets are independent; swimmers and clubs are scoped to their respective meet. Group by
id_short(orid_long) to track athletes across meets.
from tunas import read_cl2, Event
meets, _ = read_cl2("season/")
for meet in meets:
for swim in meet.swimmers[0].swims_in(Event.FREE_100_SCY):
print(meet.name, swim.session.value, swim.time)
Offline Time Standards
USA Swimming motivational standards (B through AAAA) are bundled locally for offline lookup:
from tunas import qualifies_for, Sex, Event, Time
# Get the fastest standard achieved (or None):
qualifies_for(Time.parse("1:05.23"), Event.FREE_100_SCY, age=12, sex=Sex.FEMALE)
# → TimeStandard.BB
Also supports all_qualified(...) and standard_time(...) lookups.
Error Handling
Parsing is lenient by default to recover from common exporter bugs; warnings are collected in a ParseReport.
meets, report = read_cl2("messy/")
for w in report.warnings:
print(f"{w.source}:{w.line_no} [{w.severity.value}] {w.record_type}: {w.reason}")
Use strict=True to fail fast and raise ParseError on the first warning. Structural violations always raise.
Features
- SDIF v3 Parser: Parses
.cl2meet result files including relays and splits. - Clean Object Model: Slotted dataclasses with direct object references and zero global state.
- Offline Standards: Local O(1) lookup of USA Swimming B through AAAA motivational cuts.
- Lenient Parsing: Detailed warning reports by default; strict validation mode available.
- Parallel Execution: Deterministic concurrent parsing of multiple files on thread pool.
- Type-Safe: Fully typed (
py.typed).
Documentation
- Getting Started
- Parsing & Errors
- Data Model
- Cookbook / Recipes
- File Format (SDIF)
- API Reference
- Architecture & Design
Full docs site: https://ajoe2.github.io/tunas/
Development
Managed with uv:
uv sync # Setup environment
uv run pytest # Run offline test suite
uv run pytest --cov=tunas # Run with coverage check (95% gate)
uv run ruff check && uv run mypy src/tunas # Lint and type check
Status
tunas is in alpha. The public API is stable, but subject to revision before 1.0.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tunas-0.1.1.tar.gz.
File metadata
- Download URL: tunas-0.1.1.tar.gz
- Upload date:
- Size: 71.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec23c38cb14a97e923163b2d6e32e4f4f0cd0e80a76ba8b3aa9aa7ffb3a8271f
|
|
| MD5 |
910e06030a0f6c30722b8b9418172980
|
|
| BLAKE2b-256 |
23bc08423cab0a73ce3a0b1dc12f479a6d1ef99b75e618203b44ff09d7a42115
|
Provenance
The following attestation bundles were made for tunas-0.1.1.tar.gz:
Publisher:
publish.yml on ajoe2/tunas
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tunas-0.1.1.tar.gz -
Subject digest:
ec23c38cb14a97e923163b2d6e32e4f4f0cd0e80a76ba8b3aa9aa7ffb3a8271f - Sigstore transparency entry: 1625777527
- Sigstore integration time:
-
Permalink:
ajoe2/tunas@56183a91d66f269c933b56f6a7aad14615d600e9 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/ajoe2
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@56183a91d66f269c933b56f6a7aad14615d600e9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file tunas-0.1.1-py3-none-any.whl.
File metadata
- Download URL: tunas-0.1.1-py3-none-any.whl
- Upload date:
- Size: 77.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a01c9749d9d927ef7e62776b7e2cab07f4041dd58b4aa5643539d0e6b2c7d85
|
|
| MD5 |
98177cabfddc7b99271dea9950c893ab
|
|
| BLAKE2b-256 |
5aef0dc427903a8665dbefcdf8862e4e67b1cb68f569b8484691094b00ae630e
|
Provenance
The following attestation bundles were made for tunas-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on ajoe2/tunas
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tunas-0.1.1-py3-none-any.whl -
Subject digest:
2a01c9749d9d927ef7e62776b7e2cab07f4041dd58b4aa5643539d0e6b2c7d85 - Sigstore transparency entry: 1625777539
- Sigstore integration time:
-
Permalink:
ajoe2/tunas@56183a91d66f269c933b56f6a7aad14615d600e9 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/ajoe2
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@56183a91d66f269c933b56f6a7aad14615d600e9 -
Trigger Event:
release
-
Statement type: