Skip to main content

wdlfmt — a formatter for Workflow Description Language (WDL)

PyPI version CI Python versions Downloads License: MIT

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)

Source distribution for wdlfmt 0.2.0
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)

Table of built distributions (wheels) for wdlfmt 0.2.0
File Interpreter ABI Platform Actions
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.

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