Skip to content

API reference

The complete public surface, generated from the docstrings in the source.

Stability

Anything imported from the top-level tomlrt namespace is part of the public, semver-stable API:

Symbol Kind
loads, load function
dumps, dump function
Document, Table, Array, AoT class
FormatOptions class
TomlInput type alias
TOMLError, TOMLParseError exception

Anything not re-exported from tomlrt/__init__.py (modules prefixed with _, internal helpers) may change without notice and should not be imported by user code.

Top-level functions

loads

loads(text: str) -> Document

Parse a TOML document string into a Document.

load

load(fp: IO[bytes]) -> Document

Parse a TOML document from a binary file-like object.

The file must be opened in binary mode (open(path, "rb")).

dumps

dumps(data: Mapping[str, Any]) -> str

Serialize a Document back to a TOML string.

A mapping that is not already a Document is wrapped in one first, so tomlrt.dumps({"a": 1}) works.

dump

dump(data: Mapping[str, Any], fp: IO[bytes]) -> None

Serialize a Document and write it to a binary stream.

The file must be opened in binary mode (open(path, "wb")).

Accepts a plain mapping as well as a Document (see dumps).

Formatting

FormatOptions dataclass

Canonical formatting options shared by all format() methods.

normalize_comments rewrites comment text to canonical # body form and strips trailing whitespace. Layout around comments is canonicalised regardless.

indent is the number of spaces added at each nested multiline array or inline-table level.

eol_comment_spaces is the number of spaces inserted before supported end-of-line comments.

multiline_trailing_comma controls whether the final item in a multiline array or inline table has a comma.

normalize_comments class-attribute instance-attribute

normalize_comments: bool = True

indent class-attribute instance-attribute

indent: int = 2

eol_comment_spaces class-attribute instance-attribute

eol_comment_spaces: int = 1

multiline_trailing_comma class-attribute instance-attribute

multiline_trailing_comma: bool = True

Containers

Document

Top-level TOML document.

A Document is the root of a parsed TOML file. It is a dict subclass and can be passed wherever a dict or Mapping is expected.

__init__

__init__(data: Mapping[str, Any] | None = None) -> None

Return a fresh empty document, optionally populated from data.

With a mapping:

  • nested mappings become standard [section] blocks (not inline tables);
  • lists of mappings become [[array.of.tables]] blocks;
  • everything else is set with ordinary key-value assignment.

A Table / AoT / Array view that is not already attached to a document attaches live: the returned document keeps your object, so later mutations through either reference are visible on the other. A view already attached to another document is deep-cloned instead, so the two never share state. Plain dict / list values are always snapshot-copied.

render

render() -> str

Serialize the document back to a TOML string.

Equivalent to tomlrt.dumps(self).

table

table(key: str | Sequence[str]) -> Table

Return the value at key typed as a Table.

key may be a single name, a dotted-string path, or a sequence of names.

array

array(key: str | Sequence[str]) -> Array

Return the value at key typed as an Array.

aot

aot(key: str | Sequence[str]) -> AoT

Return the value at key typed as an array-of-tables (AoT).

entry

entry(key: str | Sequence[str]) -> Any

Resolve a (possibly dotted) key path; raises KeyError if missing.

Raises TypeError if descent passes through a non-table, and ValueError for an empty path or a path with empty segments.

get_table

get_table(key: str | Sequence[str]) -> Table | None
get_table(key: str | Sequence[str], default: _T) -> Table | _T
get_table(key: str | Sequence[str], default: object = None) -> object

Like table(key) but returns default if the key is missing.

get_array

get_array(key: str | Sequence[str]) -> Array | None
get_array(key: str | Sequence[str], default: _T) -> Array | _T
get_array(key: str | Sequence[str], default: object = None) -> object

Like array(key) but returns default if the key is missing.

get_aot

get_aot(key: str | Sequence[str]) -> AoT | None
get_aot(key: str | Sequence[str], default: _T) -> AoT | _T
get_aot(key: str | Sequence[str], default: object = None) -> object

Like aot(key) but returns default if the key is missing.

get_entry

get_entry(key: str | Sequence[str], default: Any = None) -> Any

Like entry(key) but returns default if the path is missing.

install

install(path: str | Sequence[str], value: TomlInput) -> Any

Set value at the (possibly dotted) path.

Intermediate sections are created as needed via ensure_table. Returns the live view stored at the leaf.

ensure_table

ensure_table(key: str | Sequence[str], *, promote_inline: bool = False) -> Table

Return the table at key, creating it if missing.

If any prefix already exists as a section, descent continues from there. Intermediate components missing entirely are left implicit; only the deepest component gets an explicit [a.b.c] header. Raises TOMLError if a component cannot be descended through: an existing array-of-tables, or a non-table value or (unless promote_inline) inline table.

promote_inline converts an inline-style ancestor into an explicit section in place instead of raising, preserving its other entries. Used by install, since the deepest component is getting an explicit header regardless.

promote_inline

promote_inline(key: str) -> Table

Convert an inline-table entry at key into a section header.

Returns the live view at key after promotion. Raises KeyError if the key is missing, or TypeError if it doesn't refer to an inline-style table.

promote_array

promote_array(key: str) -> AoT

Convert an array-of-inline-tables at key into an AoT.

Returns the live AoT view at key. Raises KeyError if the key is missing, TypeError if it refers to a non-array, or TOMLError for an empty array or an array with non-inline-table elements.

preamble deletable property writable

preamble: tuple[str, ...]

The document's opening comment paragraph, as bare comment texts.

The preamble is the run of # … lines before the first blank line. Comments below that blank line belong to the first key or section (its leading_comments / leading_block), not the preamble.

Setting replaces the preamble with a sequence of comment texts (without the leading #); assign () to remove. Line terminators within a comment are rejected.

epilogue deletable property writable

epilogue: tuple[str | None, ...]

Comment block at the very end of the document.

The trailing comments that follow all structural content, as bare comment texts (without the leading #) with None for each blank line, in source order. With no structural content everything is preamble instead.

Setting replaces the epilogue with the same shape; assign () to remove. Line terminators within a comment are rejected.

Raises TOMLError if called with a non-empty value on a document with no structural content.

comments property

comments: MutableMapping[str, str]

Mapping view of EOL comments on this container's direct keys.

For a section-backed container the view is keyed by direct key and requires attachment to a Document to mutate. For an inline table the view is keyed by direct leaf key over the backing inline value; setting a comment promotes a single-line table to multi-line (a single line has nowhere to hold a comment).

leading_comments property

leading_comments: MutableMapping[str, tuple[str, ...]]

Mapping view of leading-comment blocks on this container's direct keys.

Returns only the attached comment run immediately above each key (no blank line between). For the full block, including any above-blank groups and the blank-line structure between them, see leading_block.

Mutating the view requires the container to be attached to a Document. On an inline table the view is keyed by direct leaf key over the backing inline value; it has the same attached-run semantics as a section-backed table, and setting comments promotes a single-line table to multi-line.

leading_block property

leading_block: MutableMapping[str, tuple[str | None, ...]]

Mapping view of full leading-trivia blocks on direct keys.

Each entry is a tuple[str | None, ...] of comment strings interleaved with None (one per blank line), in source order; the slot's own column indent is implicit and re-applied on write.

For the document's first key, the opening comment paragraph is the Document.preamble and is omitted here; this block starts after the first blank line.

Mutating the view requires the container to be attached to a Document. On an inline table the view is keyed by direct leaf key over the backing inline value; an opening-bracket EOL comment is framing and is not part of the first entry's block.

sort

sort(*, key: Callable[[str], SupportsRichComparison] | None = None, reverse: bool = False) -> None

Sort direct child keys in place, preserving per-key trivia.

Mirrors list.sort: keyword-only key / reverse, stable, in-place. Structural keys (children bound to an AoT or to a section Table, i.e. one rendered with a [header]) are always placed after bare keys; otherwise a bare key after a section header would re-bind under it. key and reverse apply within, never across, the partitions. Implicit sections built from dotted keys (e.g. a.x = 1) sort as bare keys.

Inline containers have no structural children, so the partition is a no-op and key / reverse behave as on a plain dict.

See has_header for the predicate that defines the partition; a custom key function can call it to decide which side of the split a given child sits on.

format

format(*, options: FormatOptions | None = None, comments: bool | None = None) -> None

Canonicalise this container's formatting in place.

Rewrites this subtree to the canonical layout:

  • Keys, = spacing, and header brackets use canonical whitespace.
  • Sibling key/value slots have no blank line between them; section / array-of-tables headers get one.
  • Orphan comment blocks above slots are preserved, with each blank-line run collapsed to one.
  • Inline values keep their shape (single-line stays single-line, multi-line stays multi-line).
  • Newlines use the owning document's style.

comments= is deprecated; use FormatOptions(normalize_comments=...) instead. Supplying both arguments raises ValueError.

Detached factory-style containers (Table.section() / Table.inline() not yet assigned anywhere) and inline dotted navigators are unsupported and raise TOMLError.

to_dict

to_dict() -> dict[str, Any]

Materialise a plain-Python dict (recursive).

Table

A logical TOML table.

Every nested mapping in a document is a Table. Table is a dict subclass, so isinstance(t, dict) holds and it can be passed wherever a dict or Mapping is expected.

The same Table class backs both standard [section] blocks and inline {x = 1} tables. Use is_inline to tell them apart when walking a parsed document.

section classmethod

section(mapping: Mapping[str, TomlInput] | None = None) -> Table

Return a standard-section table, optionally populated from mapping.

Assign the result to install a [k] block:

doc[k] = Table.section({"x": 1})

inline classmethod

inline(mapping: Mapping[str, TomlInput] | None = None) -> Table

Return an inline table, optionally populated from mapping.

Assign the result to install a {x = 1} value:

doc[k] = Table.inline({"x": 1})

is_inline property

is_inline: bool

True for inline {...} tables, False for [section] blocks.

multiline property writable

multiline: bool

Whether this inline table is laid out across multiple lines.

Raises TOMLError on a non-inline table.

set_multiline

set_multiline(*, multiline: bool, indent: int = 4) -> Table

Switch this inline table between single-line and multi-line form.

When laying out multi-line, entries are indented by indent spaces.

Raises TOMLError on a non-inline table, and when collapsing a multi-line table that carries comments anywhere in it (they would have nowhere to live on one line).

Returns self for chaining.

table

table(key: str | Sequence[str]) -> Table

Return the value at key typed as a Table.

key may be a single name, a dotted-string path, or a sequence of names.

array

array(key: str | Sequence[str]) -> Array

Return the value at key typed as an Array.

aot

aot(key: str | Sequence[str]) -> AoT

Return the value at key typed as an array-of-tables (AoT).

entry

entry(key: str | Sequence[str]) -> Any

Resolve a (possibly dotted) key path; raises KeyError if missing.

Raises TypeError if descent passes through a non-table, and ValueError for an empty path or a path with empty segments.

get_table

get_table(key: str | Sequence[str]) -> Table | None
get_table(key: str | Sequence[str], default: _T) -> Table | _T
get_table(key: str | Sequence[str], default: object = None) -> object

Like table(key) but returns default if the key is missing.

get_array

get_array(key: str | Sequence[str]) -> Array | None
get_array(key: str | Sequence[str], default: _T) -> Array | _T
get_array(key: str | Sequence[str], default: object = None) -> object

Like array(key) but returns default if the key is missing.

get_aot

get_aot(key: str | Sequence[str]) -> AoT | None
get_aot(key: str | Sequence[str], default: _T) -> AoT | _T
get_aot(key: str | Sequence[str], default: object = None) -> object

Like aot(key) but returns default if the key is missing.

get_entry

get_entry(key: str | Sequence[str], default: Any = None) -> Any

Like entry(key) but returns default if the path is missing.

install

install(path: str | Sequence[str], value: TomlInput) -> Any

Set value at the (possibly dotted) path.

Intermediate sections are created as needed via ensure_table. Returns the live view stored at the leaf.

ensure_table

ensure_table(key: str | Sequence[str], *, promote_inline: bool = False) -> Table

Return the table at key, creating it if missing.

If any prefix already exists as a section, descent continues from there. Intermediate components missing entirely are left implicit; only the deepest component gets an explicit [a.b.c] header. Raises TOMLError if a component cannot be descended through: an existing array-of-tables, or a non-table value or (unless promote_inline) inline table.

promote_inline converts an inline-style ancestor into an explicit section in place instead of raising, preserving its other entries. Used by install, since the deepest component is getting an explicit header regardless.

promote_inline

promote_inline(key: str) -> Table

Convert an inline-table entry at key into a section header.

Returns the live view at key after promotion. Raises KeyError if the key is missing, or TypeError if it doesn't refer to an inline-style table.

promote_array

promote_array(key: str) -> AoT

Convert an array-of-inline-tables at key into an AoT.

Returns the live AoT view at key. Raises KeyError if the key is missing, TypeError if it refers to a non-array, or TOMLError for an empty array or an array with non-inline-table elements.

header_comment deletable property writable

header_comment: str | None

The EOL comment on this container's section header, or None.

Containers without a header line (the document root, or implicit sections opened only by a nested [a.b] header) read as None. Setting on such a container raises TOMLError; inline tables also raise.

header_leading_comments deletable property writable

header_leading_comments: tuple[str, ...]

The attached comment block immediately above this container's header.

Containers without a header line (the document root, or implicit sections opened only by a nested [a.b] header) read as (). Setting on such a container raises TOMLError; inline tables also raise.

Excludes any above-blank groups — those are visible via header_leading_block.

header_leading_block deletable property writable

header_leading_block: tuple[str | None, ...]

The full leading-trivia block above this container's header.

A tuple[str | None, ...] of comment strings interleaved with None (one per blank line), in source order. Containers without a header line (the document root, or implicit sections opened only by a nested [a.b] header) read as (). Setting on such a container raises TOMLError; inline tables also raise.

For the document's first section, the opening comment paragraph is the Document.preamble and is omitted here; this block starts after the first blank line.

comments property

comments: MutableMapping[str, str]

Mapping view of EOL comments on this container's direct keys.

For a section-backed container the view is keyed by direct key and requires attachment to a Document to mutate. For an inline table the view is keyed by direct leaf key over the backing inline value; setting a comment promotes a single-line table to multi-line (a single line has nowhere to hold a comment).

leading_comments property

leading_comments: MutableMapping[str, tuple[str, ...]]

Mapping view of leading-comment blocks on this container's direct keys.

Returns only the attached comment run immediately above each key (no blank line between). For the full block, including any above-blank groups and the blank-line structure between them, see leading_block.

Mutating the view requires the container to be attached to a Document. On an inline table the view is keyed by direct leaf key over the backing inline value; it has the same attached-run semantics as a section-backed table, and setting comments promotes a single-line table to multi-line.

leading_block property

leading_block: MutableMapping[str, tuple[str | None, ...]]

Mapping view of full leading-trivia blocks on direct keys.

Each entry is a tuple[str | None, ...] of comment strings interleaved with None (one per blank line), in source order; the slot's own column indent is implicit and re-applied on write.

For the document's first key, the opening comment paragraph is the Document.preamble and is omitted here; this block starts after the first blank line.

Mutating the view requires the container to be attached to a Document. On an inline table the view is keyed by direct leaf key over the backing inline value; an opening-bracket EOL comment is framing and is not part of the first entry's block.

has_header

has_header(key: str) -> bool

Whether key's rendered block contains a structural header.

This describes the whole block, not the child table itself: with [a.b], doc.has_header("a") is true although a is implicit and only b owns the header. Structural headers are [header] sections and [[header]] array-of-tables entries. Returns False for bare key = value leaves, inline tables, implicit sections built entirely from dotted keys (e.g. a.x = 1), and missing keys.

sort

sort(*, key: Callable[[str], SupportsRichComparison] | None = None, reverse: bool = False) -> None

Sort direct child keys in place, preserving per-key trivia.

Mirrors list.sort: keyword-only key / reverse, stable, in-place. Structural keys (children bound to an AoT or to a section Table, i.e. one rendered with a [header]) are always placed after bare keys; otherwise a bare key after a section header would re-bind under it. key and reverse apply within, never across, the partitions. Implicit sections built from dotted keys (e.g. a.x = 1) sort as bare keys.

Inline containers have no structural children, so the partition is a no-op and key / reverse behave as on a plain dict.

See has_header for the predicate that defines the partition; a custom key function can call it to decide which side of the split a given child sits on.

format

format(*, options: FormatOptions | None = None, comments: bool | None = None) -> None

Canonicalise this container's formatting in place.

Rewrites this subtree to the canonical layout:

  • Keys, = spacing, and header brackets use canonical whitespace.
  • Sibling key/value slots have no blank line between them; section / array-of-tables headers get one.
  • Orphan comment blocks above slots are preserved, with each blank-line run collapsed to one.
  • Inline values keep their shape (single-line stays single-line, multi-line stays multi-line).
  • Newlines use the owning document's style.

comments= is deprecated; use FormatOptions(normalize_comments=...) instead. Supplying both arguments raises ValueError.

Detached factory-style containers (Table.section() / Table.inline() not yet assigned anywhere) and inline dotted navigators are unsupported and raise TOMLError.

to_dict

to_dict() -> dict[str, Any]

Materialise a plain-Python dict (recursive).

Array

An inline TOML array.

Array is a list subclass, so isinstance(arr, list) holds and it can be passed wherever a list or Sequence is expected.

__init__

__init__(items: Iterable[TomlInput] = (), *, multiline: bool = False, indent: int = 4) -> None

Construct a standalone inline array.

Array([1, 2, 3]) builds an inline array; multiline=True lays items out one per line, indented by indent spaces.

multiline property writable

multiline: bool

True iff this array is rendered in multi-line form.

set_multiline

set_multiline(*, multiline: bool, indent: int = 4) -> Array

Switch this array between flush single-line and multi-line form.

When laying out multi-line, items are indented by indent spaces.

Raises TOMLError when collapsing a multi-line array that carries comments anywhere in it, including inside nested values, since they would have nowhere to live on one line.

Returns self for chaining.

table

table(index: SupportsIndex) -> Table

Return self[index] typed as a Table.

array

array(index: SupportsIndex) -> Array

Return self[index] typed as a nested Array.

get_table

get_table(index: SupportsIndex) -> Table | None
get_table(index: SupportsIndex, default: _T) -> Table | _T
get_table(index: SupportsIndex, default: object = None) -> object

Like table(index) but returns default for out-of-range.

get_array

get_array(index: SupportsIndex) -> Array | None
get_array(index: SupportsIndex, default: _T) -> Array | _T
get_array(index: SupportsIndex, default: object = None) -> object

Like array(index) but returns default for out-of-range.

comments property

comments: MutableMapping[int, str]

EOL comment view, indexed by item position.

leading_comments property

leading_comments: MutableMapping[int, tuple[str, ...]]

Attached leading-comment view, indexed by item position.

leading_block property

leading_block: MutableMapping[int, tuple[str | None, ...]]

Full leading-block view, indexed by item position.

Comment lines are strings and blank lines are None.

format

format(*, options: FormatOptions | None = None, comments: bool | None = None) -> None

Canonicalise this array's formatting in place.

Rewrites whitespace, indentation, separators, and newlines while preserving shape (single-line stays single-line, multi-line stays multi-line) and orphan comment text.

comments= is deprecated; use FormatOptions(normalize_comments=...) instead. Supplying both arguments raises ValueError.

to_list

to_list() -> list[Any]

Materialise a plain-Python list (recursive).

AoT

An Array-of-tables, e.g. [[products]] repeated.

AoT is a list[Table] subclass, so isinstance(aot, list) holds and it can be passed wherever a list or Sequence is expected.

__init__

__init__(entries: Iterable[Mapping[str, TomlInput]] = ()) -> None

Construct a standalone array-of-tables.

add

add(entry: Mapping[str, TomlInput] | None = None) -> Table

Append a fresh [[path]] entry and return its Table view.

entry may be initial body content or None. Attached AoTs append to the owning document.

to_list

to_list() -> list[dict[str, Any]]

Materialise a list of plain-Python dicts (recursive).

Type aliases

TomlInput module-attribute

TomlInput: TypeAlias = str | int | float | bool | datetime | date | time | Array | AoT | Table | Mapping[str, Any] | list[Any]

Values accepted by mutators and factories.

Includes Table, Array, AoT, any TOML scalar (str, int, float, bool, datetime, date, time), and plain Mapping[str, Any] / list[Any].

The nested list / Mapping arms intentionally use Any for elements: tightening to a recursive alias would trip over Python's invariant container generics (a list[int] is not assignable to list[TomlInput]). Invalid elements are rejected at runtime when the value is assigned.

Errors

TOMLError

Base class for all tomlrt errors.

TOMLParseError

Raised when a TOML document cannot be parsed.

The human-readable problem description is available via str(exc) (or exc.args[0]) and has the form "{message} (line L, column C)".

Attributes:

Name Type Description
line int

1-based line number where the error was detected.

col int

1-based column number where the error was detected.

offset int

0-based byte offset into the source.

line instance-attribute

line: int = line

col instance-attribute

col: int = col

offset instance-attribute

offset: int = offset