Validator for Transit Operational Data Standard (TODS) feeds, formerly the Operational Data Standard (ODS)
Project description
tods-validate
A validator for Transit Operational Data Standard (TODS) feeds, with a CLI and a GitHub Action.
TODS is an open standard for describing scheduled transit operations: crew runs, deadheads, vehicle assignments, and other non-public service that GTFS does not cover. It works as an overlay on an agency's GTFS feed. The standard was originally published by Cal-ITP as the Operational Data Standard (ODS) and is now maintained with MobilityData under its current name. This validator checks feeds against the current spec, TODS v2.1.0.
tods-validate reads a TODS package, checks it against the spec, and reports
findings in language a scheduler can act on. Each finding says what is wrong,
where, and what good looks like, and cites the spec section it comes from.
Install
Requires Python 3.11 or newer.
pipx install tods-validate
or pip install tods-validate into an environment of your choice.
Usage
Point it at the directory or .zip file containing your TODS files. If your
GTFS feed lives in a separate file, pass it with --gtfs so trip, stop,
service, and block references can be checked:
tods-validate exports/tods/ --gtfs exports/gtfs.zip
When the TODS files sit next to the GTFS files in one package, the GTFS files are picked up automatically:
$ tods-validate /tmp/demo-feed
tods-validate: /tmp/demo-feed (TODS v2.1.0)
2 errors:
ERROR TODS-E203 [run_events.txt, row 4, field 'end_time']
run_events.txt row 4: end_time is '9:45', which is not a valid time. Use HH:MM:SS, e.g. '09:45:00' or '25:10:00' for 1:10 AM the next service day.
ERROR TODS-E307 [run_events.txt, row 4, field 'trip_id']
run_events.txt row 4: trip_id 'WKDY-1002' does not exist in the companion GTFS trips.txt (after applying trips_supplement.txt). Run events that represent work on a trip must reference a scheduled trip.
Fix: Correct the trip_id, or add the trip via trips_supplement.txt if it is non-revenue service.
Summary: 2 error(s), 0 warning(s), 0 info.
$ echo $?
1
The exit code is 0 when no errors are found, 1 when there are errors, and 2
when the package cannot be read at all. Warnings do not fail the run unless
you pass --fail-on warning.
Other output formats:
--format jsonprints a stable JSON document for tooling.--format markdownprints a report suitable for pasting into an issue.--format githubprints GitHub Actions workflow annotations.
To suppress findings your agency has decided to accept, pass
--ignore TODS-W206 (repeatable), or put the policy in a
tods-validate.toml next to where you run the validator:
ignore = ["TODS-W206", "TODS-I108"]
fail-on = "warning"
Command-line flags win over the file. A config file in another location can
be passed with --config path/to/file.toml.
References into GTFS are resolved after applying the supplement files, so a
trip added by trips_supplement.txt is a valid target for
run_events.trip_id, and a stop deleted by stops_supplement.txt is not.
Merging supplements into GTFS
The spec says that GTFS plus the supplement files should form a valid GTFS
dataset (the "TODS-Supplemented GTFS"). The merge subcommand materializes
that dataset so you can test the claim, or hand the operational feed to a
tool that only speaks GTFS:
tods-validate merge exports/tods/ --gtfs exports/gtfs.zip -o supplemented.zip
GTFS files without a supplement are copied through unchanged; supplemented files get their rows deleted, updated, and added per the spec's evaluation rules, and the command reports what changed per file. Validate the TODS package first so the merge rests on clean inputs.
A CI job that checks the merged feed with MobilityData's gtfs-validator:
- uses: ChelseaKR/tods-validate@v0
with:
path: feed/tods
gtfs: feed/gtfs
- run: |
pipx install tods-validate
tods-validate merge feed/tods --gtfs feed/gtfs -o supplemented.zip
- run: |
curl -sSL -o gtfs-validator.jar https://github.com/MobilityData/gtfs-validator/releases/latest/download/gtfs-validator-cli.jar
java -jar gtfs-validator.jar -i supplemented.zip -o validator-report
GitHub Action
If your TODS export lives in a repository, this workflow validates it on every pull request and annotates findings inline:
name: Validate TODS feed
on: [pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ChelseaKR/tods-validate@v0
with:
path: feed/tods
gtfs: feed/gtfs # omit if GTFS files sit next to the TODS files
Rules
The full catalog of checks, with IDs, severities, and spec citations, is in docs/rules.md. Rule IDs are stable: a CI pipeline can safely filter or suppress specific IDs.
Ambiguities in the spec discovered while building the validator are tracked in docs/spec-questions.md.
What this does not check
tods-validate validates the TODS files and their references into the
companion GTFS feed. It does not re-validate the GTFS feed itself, and it
does not check that the merged ("TODS-Supplemented") GTFS dataset is valid
GTFS. For those, run MobilityData's
gtfs-validator, optionally
on the merged feed.
Development
git clone https://github.com/ChelseaKR/tods-validate
cd tods-validate
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest
Lint and type-check with ruff check src tests scripts and mypy. The rule
catalog is generated: after adding or changing a rule, run
python scripts/generate_rules_doc.py and commit the result; CI fails if it
drifts.
License
Apache-2.0, matching the TODS specification repository.
Project details
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 tods_validate-0.3.0.tar.gz.
File metadata
- Download URL: tods_validate-0.3.0.tar.gz
- Upload date:
- Size: 51.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a58b871781a59b201521b2f280199cc848759a559de91789988ce9ac8ceb5c45
|
|
| MD5 |
35c83ce2c9946010e4c9a6f30593279e
|
|
| BLAKE2b-256 |
b5d24a1f20e1828b02d2152a6895ec01bdf135694421520cdab63db75b902a6a
|
File details
Details for the file tods_validate-0.3.0-py3-none-any.whl.
File metadata
- Download URL: tods_validate-0.3.0-py3-none-any.whl
- Upload date:
- Size: 41.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8659d1f173a7557cea2701584af942e6ab8e02fcafbd3c6b7ba689b3406fb266
|
|
| MD5 |
5cc292dbdf26eb5c87de8de032eb4cfe
|
|
| BLAKE2b-256 |
78c151e3eeedd20b6a77a2c010a4978bc348599834161de2c5a4c4159969062e
|