wdlfmt — a formatter for Workflow Description Language (WDL)
wdlfmt is an opinionated, lossless formatter for WDL v1.0 that enforces consistency and targets the BioWDL Style Guidelines.
For now there is no automated way of styling or checking the style of WDL files according to these guidelines. — BioWDL Style Guidelines
wdlfmt aims to solve this problem.
Installation
pip install wdlfmt
For development, clone the repo and use pixi:
git clone https://github.com/Chris1221/wdlfmt.git
cd wdlfmt && pixi install
pixi run test
Usage
By default, formatted output is written to stdout and a style compliance checklist is printed to stderr:
wdlfmt my_task.wdl
Format in place with -i:
wdlfmt -i my_task.wdl
Suppress the checklist with --no-check:
wdlfmt --no-check my_task.wdl
Check if files are already formatted (CI enforcement):
wdlfmt --check my_task.wdl # exits 0 if formatted, 1 if not
Redirect formatted WDL to a file while keeping the checklist visible:
wdlfmt my_task.wdl > formatted.wdl
What the formatter does
wdlfmt rewrites WDL files with consistent style, preserving all comments:
| Rule | Example (before → after) |
|---|---|
| 4-space indentation | tabs / mixed spaces → 4 spaces |
| Heredoc command syntax | command { ... } → command <<< ... >>> |
| Double-quoted strings | 'hello' → "hello" |
Spaces around = |
key=value → key = value |
BioWDL style compliance checklist
After every format run, wdlfmt emits a per-rule checklist to stderr. Rules the formatter enforces are shown as confirmed guarantees; content rules that depend on the file's naming and structure are checked and reported:
BioWDL Style Guide Compliance
──────────────────────────────────────────────────────
Formatter guarantees
✓ 4-space indentation
✓ Heredoc (<<<) command syntax
✓ Double-quote string literals
✓ Spaces around = operator
Content checks
✓ Task names are UpperCamelCase
✓ Workflow names are UpperCamelCase
✓ Struct names are UpperCamelCase
✗ Call aliases are lowerCamelCase
Non-conforming aliases: myAlias
✓ Line length ≤ 100 chars
! set -e -o pipefail in multi-command blocks
Missing in: block 1
! parameter_meta section present
Missing in: task 'MyTask'
✓ docker defined in runtime blocks
──────────────────────────────────────────────────────
1 failed · 2 warning(s) · 9 passed
Symbols: ✓ pass · ✗ fail (rule violated) · ! warn (advisory)
Content rules
| Rule | Level | Description |
|---|---|---|
| Task names are UpperCamelCase | fail | task myTask → rename to MyTask |
| Workflow names are UpperCamelCase | fail | Same convention for workflows |
| Struct names are UpperCamelCase | fail | Same convention for structs |
| Call aliases are lowerCamelCase | fail/warn | call Foo as Bar fails; call Foo (no alias) warns |
| Line length ≤ 100 chars | fail | Reports offending line numbers |
set -e -o pipefail in command blocks |
warn | Advisory for multi-command blocks |
parameter_meta section present |
warn | Advisory per task/workflow |
docker in runtime blocks |
warn | Advisory per runtime block |
Python API
import wdlfmt
# Format a WDL string
formatted = wdlfmt.format_wdl_str(wdl_text)
# Run the style checker on already-formatted text
results = wdlfmt.check_style(formatted)
for r in results:
print(r.rule, r.status.value, r.details)
Technical overview
wdlfmt is built on ANTLR4 and a visitor-pattern formatter registry.
Parsing. The WDL v1.0 grammar (wdlfmt/grammar/WdlV1Lexer.g4 and WdlV1Parser.g4) is compiled to Python by ANTLR4. Parsing produces a typed parse tree where every node is a strongly-typed context object (e.g. TaskContext, Task_commandContext).
Comment preservation. WDL comments (#) are placed on a separate ANTLR token channel (channel 2) and are invisible to the default parse tree walk. wdlfmt extracts them from the token stream before visiting the tree, injects them as lightweight CommentContext nodes at the correct positions, and then emits them as part of the formatted output. This makes formatting lossless.
Formatter registry. wdlfmt/formatters/ contains a subclass of Formatter for each WDL context type (TaskFormatter, WorkflowFormatter, StructFormatter, etc.). Each subclass declares which context type it handles via a formats class attribute. The registry is built at import time by inspecting all Formatter subclasses, so adding support for a new context type requires only a new subclass — no wiring code.
Command block formatting. WDL command <<< blocks contain shell script. wdlfmt extracts the shell body, replaces WDL interpolation expressions (~{...}) with safe placeholders, passes the result through shfmt (bundled via shfmt-py), then restores the original expressions. This ensures shell code inside WDL tasks is also consistently formatted.
Style checker. The StyleChecker in wdlfmt/checker.py operates on the already-formatted text using regex — no re-parsing. This keeps it fast and decoupled from the formatter internals.
Metadata
Release files for wdlfmt 0.2.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 | Provenance | Actions |
|---|---|---|---|---|
| wdlfmt-0.2.0.tar.gz | 62.7 kB | Without provenance | Details for wdlfmt-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| wdlfmt-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for wdlfmt-0.2.0-py3-none-any.whl |
Total release size: 123.6 kB
Release files / wdlfmt-0.2.0.tar.gz
| Download URL | wdlfmt-0.2.0.tar.gz |
|---|---|
| Size | 62.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1d6cfd2bf4fc3f986dfec9ed0a8592d739bd67b8425fc4a6ea1c8c4c106e27b1
|
|
BLAKE2b-256 checksum How to use checksums |
4aa627bdac2145584068126492a712f2c1bfa7162d6ce7e40d8c33be181edf04
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / wdlfmt-0.2.0-py3-none-any.whl
| Download URL | wdlfmt-0.2.0-py3-none-any.whl |
|---|---|
| Size | 60.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a0a96dcd6306921aa3349ac1c67a2ec4f1b7c21bd5956878af6ba89c4bde3340
|
|
BLAKE2b-256 checksum How to use checksums |
bd44fd55e28c5b4963b10cd23c4cd0e9acf6d62e044eb2563e7942cbdc7a4783
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Security for wdlfmt 0.2.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.