tomli-w
A lil' TOML writer for Python — the write-only counterpart to Tomli, producing spec-compliant TOML v1.0.0 from plain dicts.
Repository Health
Technical Analysis
Tomli-W is a small, focused Python library that does exactly one thing: turn a mapping into TOML text. It is the write-only counterpart to Tomli (now folded into the standard library as tomllib’s read side), built by the same author to complete the round-trip story for TOML in Python. There is no schema layer, no CLI, and no configuration object to learn — just two functions, dumps and dump, that accept any collections.abc.Mapping and return or write valid TOML.
Despite its small surface area, the library makes deliberate, well-documented choices about ambiguous TOML writing decisions: it preserves input key order rather than sorting, it defaults to single-line strings to guarantee lossless round-trips (with an opt-in multiline_strings flag), it supports decimal.Decimal alongside native numeric types, and it lets callers tune array indentation. These choices are explained in the README’s FAQ rather than buried in source comments, making the library’s behavior predictable for anyone parsing TOML back out with Tomli or tomllib.
What You Get
- A
dumps(obj)function that returns a TOML-formatted string from anyMapping - A
dump(obj, fp)function that writes TOML directly to a binary file handle - Full TOML v1.0.0 compliance, including tables, arrays of tables, inline tables, and all TOML scalar types
- Deterministic output that preserves the input mapping’s key order instead of sorting
- Support for
decimal.Decimalvalues in addition toint,float,bool,date,datetime, andtime - Configurable array indentation via the
indentkeyword argument - An opt-in
multiline_stringsflag for callers who don’t need byte-exact round-trips - A
py.typedmarker and full type hints for static analysis
Common Use Cases
- Writing generated or programmatically-modified configuration files back to TOML (e.g. updating a
pyproject.tomlsnippet) - Persisting application settings or state as TOML from an in-memory dict
- Building small CLI tools or scaffolding generators that emit
.tomlproject files - Round-tripping TOML: read with Tomli/
tomllib, mutate the resulting dict, write back with Tomli-W - Exporting structured data (from JSON, YAML, or a database record) into TOML format for interchange
Under The Hood
Architecture
The entire library lives in src/tomli_w/_writer.py, a single ~230-line module with a two-function public API (dump/dumps in __init__.py) built on a generator-based core. gen_table_chunks recursively walks the input mapping, splitting each table’s items into literal key-value pairs versus nested tables/arrays-of-tables (is_aot), yielding TOML text chunks lazily rather than building one large string in memory. A small Context object (immutable via Final fields) threads allow_multiline, indent_str, and an inline-table render cache (keyed by id()) through the recursive calls, avoiding global state and redundant re-rendering of shared/cached inline tables. Formatting concerns are cleanly separated into single-purpose functions — format_literal, format_string, format_inline_table, format_inline_array, format_key_part — each handling exactly one TOML grammar production. There is no dependency on the Tomli parser or any TOML AST; the writer works directly against plain Python Mapping/ARRAY_TYPES inputs, which keeps the dependency graph at zero.
Tech Stack
Tomli-W has zero runtime dependencies and targets Python 3.10+. It is built and packaged with flit_core (declared in pyproject.toml’s [build-system]), uses bump2version for release version bumping (guarded by a # DO NOT EDIT comment on the version line), and ships a py.typed marker for downstream type checking. The test suite pulls in pytest plus a tests/requirements.txt for fixtures, and tox (via [tool.tox] in pyproject.toml) orchestrates matrixed test runs across Python 3.10 through 3.14 (plus PyPy 3.10) as well as dedicated benchmark and profile environments.
Code Quality
The project has an extensive test suite under tests/, including hand-written unit tests (test_types.py, test_invalid.py, test_write_file.py, test_style.py) and a large corpus of TOML compliance fixtures vendored from the toml-lang test suite plus BurntSushi’s TOML test data, giving broad coverage of edge cases in string escaping, numeric formatting, and table nesting. mypy is configured with a strict profile (disallow_untyped_defs, check_untyped_defs, warn_unreachable, strict_equality, implicit_reexport = false), and pytest runs with --strict-markers --strict-config plus xfail_strict = true, both of which fail the suite on soft misconfiguration rather than allowing it to pass silently. CI (GitHub Actions) runs a dedicated pre-commit/linters job ahead of the test matrix, and the test matrix itself spans three operating systems and six Python interpreters (including a pre-release build with continue-on-error), reflecting a codebase optimized for long-term interpreter compatibility rather than rapid feature growth.
What Makes It Unique
Tomli-W’s distinguishing choice is prioritizing lossless parse/write round-trips over cosmetic output: it explicitly avoids TOML multi-line string syntax by default because converting \r\n sequences to that form can silently change the represented bytes — a subtlety the README documents and lets advanced users override via multiline_strings. It also treats decimal.Decimal as a first-class numeric type (round-tripping through Tomli without precision loss) and deliberately does not sort output keys, preserving the caller’s intended ordering. Combined with its zero-dependency, single-module implementation, this makes it less a general “TOML library” and more a narrowly-scoped, spec-literal writer meant to be paired one-to-one with Tomli/tomllib for exact round-trip fidelity.
Used by 2 apps in this directory
deepagents
AI Agents · AI Development
The batteries-included Python agent harness — planning, sub-agents, filesystem, shell, memory, and skills bundled in, built on LangGraph.
Ossature
AI Development
An open-source build system that turns written specs and architecture into working code — an LLM generates code under tight constraints, task by task with narrow context windows, instead of attempting an entire codebase at once.