Skip to main content

TomlArg

A unified TOML + CLI parser for configurable Python projects. Every TOML key-value pair becomes a command-line flag with a default value.

tomlarg exposes an ArgumentParser which subclasses argparse.ArgumentParser to allow drop-in replacement - extending support for reading TOML files and keeping argument parsing functionality.

Features

  • Multiple TOML sources from file, string, or already-parsed dict.
  • Tables flattened into dotted flags (--db.pool.size) at any depth.
  • Arrays of tables index-addressable (--servers.1.port).
  • Values typed from the TOML: strings, integers, floats, booleans, datetimes, dates, times and arrays.
  • No dependencies.
  • For Python >=3.12.

Install

pip install tomlarg

Quickstart

# config.toml
name = "myapp"
port = 8080
debug = false
tags = ["web", "api"]

[db]
host = "localhost"

[db.pool]
size = 5

[[servers]]
host = "s1"
port = 8001

[[servers]]
host = "s2"
port = 8002
# main.py
import tomlarg

parser = tomlarg.ArgumentParser(toml_file="config.toml")

args = parser.parse_args()

args.name  # 'myapp'
args.db.pool.size  # 5
args.servers[1].port  # 8002
dict(args)  # the whole tree as plain data
$ python3 main.py --db.pool.size 50 --tags x,y --no-debug

Usage

TOML Flag Read back as
port = 8080 --port args.port
[db] host = "x" --db.host args.db.host
[db.pool] size = 5 --db.pool.size args.db.pool.size
[[servers]] port = 1 --servers.0.port args.servers[0].port
debug = false --debug / --no-debug args.debug
tags = ["a"] --tags a,b,c args.tags

Types come from the TOML value, so --port takes an integer, --updated takes a datetime, and --tags takes a comma-separated list whose element type is inferred. --tags= or a bare --tags gives an empty list.

API

ArgumentParser(*args, toml_file=None, toml_str=None, toml_dict=None, delimiter=".", **kwargs)

Takes everything argparse.ArgumentParser takes. The three TOML arguments are shorthand for the add_toml* methods below, applied in the order listed.

parser = tomlarg.ArgumentParser(prog="myapp", toml_file="config.toml")

delimiter sets the separator used for generated flags and for reading values back. Results stay nested whichever separator is chosen.

parser = tomlarg.ArgumentParser(delimiter="__", toml_file="config.toml")
parser.parse_args(["--db__pool__size", "50"]).db.pool.size  # 50

add_toml(path)

Record a TOML file, given as a Path or str. A missing file raises FileNotFoundError here, not at parse time.

parser.add_toml("profile.toml")

add_toml_str(text)

Record a TOML document. Malformed TOML raises tomllib.TOMLDecodeError here, not at parse time.

parser.add_toml_str("[user]\nname = 'x'")

add_toml_dict(data)

Record already-parsed TOML. data is any Mapping, which is how a table from an enclosing document is passed.

parser.add_toml_dict(pyproject["tool"]["myapp"])

Sources merge in the order added, key by key, so a later source overrides only the leaves it names:

# base.toml                # prod.toml
[db]                       [db]
host = "localhost"         host = "db.internal"
port = 5432
[db.pool]                  [db.pool]
size = 5                   size = 20
timeout = 30
db.host         = 'db.internal'   # from prod
db.port         = 5432            # kept from base
db.pool.size    = 20              # from prod
db.pool.timeout = 30              # kept from base

add_argument(*args, **kwargs)

Inherited from argparse, with the same signature. A flag you declare keeps its type=, help= and everything else, and the TOML value becomes its default. Sources are applied at parse time, so this may be called before or after them.

Declaring a flag for a table stops that table being expanded, which is the escape hatch for passing one whole:

parser.add_argument(
    "--labels", type=json.loads, help="Labels"
)  # --labels '{"env":"dev"}'

parse_args(args=None, namespace=None)

Applies the sources, then parses. Precedence, highest first: command line, TOML, add_argument defaults.

Returns a tomlarg.Namespace, a subclass of argparse.Namespace addressable by delimited path. args.db.pool.size and getattr(args, "db.pool.size") resolve the same value, and dict(args) converts the whole tree back to plain data with arrays of tables as real lists.

parse_known_args(args=None, namespace=None)

As argparse, returning the namespace and the unrecognised arguments.

parser.parse_known_args(["--nope"])  # (Namespace(port=8080), ['--nope'])

format_help() and format_usage()

Apply the sources too, so TOML-derived flags are listed without parsing first.

Examples

Example of overriding --db.host and --servers.1.port flags:

$ python3 examples/basic --db.host db.internal --servers.1.port 9999

Example showing multiple TOML sources can be added:

$ python3 examples/layered

Example of printing help and usage message:

$ python3 examples/basic --help
usage: basic [-h] [--port PORT] [--labels LABELS] [--name NAME] [--debug | --no-debug]
             [--tags [TAGS]] [--updated UPDATED] [--db.host DB.HOST]
             [--db.port DB.PORT] [--db.pool.size DB.POOL.SIZE]
             [--servers.0.host SERVERS.0.HOST] [--servers.0.port SERVERS.0.PORT]
             [--servers.1.host SERVERS.1.HOST] [--servers.1.port SERVERS.1.PORT]

options:
  -h, --help            show this help message and exit
  --port PORT           port to listen on
  --labels LABELS       labels as a JSON object
  --name NAME
  --debug, --no-debug
  --tags [TAGS]
  --updated UPDATED
  --db.host DB.HOST
  ...

See examples.

Errors

Situation Error
Two sources give a key different types cannot replace integer 'port' with string
A key needs a flag another argument owns TOML key 'port' needs --port, which is already taken by an argument storing to 'p'
One dest nests inside another 'db' is both a value and a prefix of 'db.host'
A key is named after a built-in flag TOML key 'help' is the dest of --help, which stores nothing
A value has no command-line spelling unsupported TOML value type for 'when': unknown
A key is empty, or holds the delimiter key '' is empty, so it has no flag
A source is not a mapping TOML data must be a mapping, not list

Todo

  • TOML comment parser to attach argument parameters e.g. choices, required, deprecated.
  • Abbreviating dotted keys (allow_abbrev defaults to false currently).
  • Subparsers.

Metadata

Release files for tomlarg 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tomlarg 0.2.1
File Size Uploaded
tomlarg-0.2.1.tar.gz 11.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tomlarg 0.2.1
File Interpreter ABI Platform
tomlarg-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 24.8 kB

Release files / tomlarg-0.2.1.tar.gz

Download URL tomlarg-0.2.1.tar.gz
Size 11.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a302b108d9c6a1907f7d89d2cb71b6ef7879081c7ee65df53b1144d7819ea163
BLAKE2b-256 checksum
How to use checksums
1fd99ce350f8212e62653eb3a29b2663175f321be9d9d53953cde49a138d9aaa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.

Transparency log

Release files / tomlarg-0.2.1-py3-none-any.whl

Download URL tomlarg-0.2.1-py3-none-any.whl
Size 13.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
55a94ebf42b98e01ef26837dbdee7b66e88e3941ec0dc5cfb477af7f6060d9e3
BLAKE2b-256 checksum
How to use checksums
4aabaed034ab01b4d6b3f5fc7e5392def37ae935cca535221e000e6385033c6d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

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