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, parse, load function
dumps, dump function
document function
Document, Table, Array, AoT 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.

parse

parse(text: str) -> Document

Alias for loads.

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, "wb")).

dumps

dumps(doc: Document) -> str

Serialize a Document back to a TOML string.

dump

dump(doc: Document, 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")).

document

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

Return a fresh Document, optionally populated from data.

Without arguments, returns an empty document.

With a mapping, recursively populates the document so that:

  • 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.

Existing Table / AoT / Array views are deep-cloned, so the returned document shares no mutable state with data.

Containers

Document

Top-level TOML document. Subclass of Table.

render

render() -> str

Serialize the document back to a TOML string.

Equivalent to tomlrt.dumps(self). Restores the original line-ending style detected at parse time.

preamble property writable

preamble: tuple[str, ...]

Comment block at the top of the document.

A "preamble" is the run of # … lines that opens the file and is blank-line-separated from anything below. Comments that sit directly above the first key (no blank line) are not preamble — they are the leading comments of that key, accessed via leading_comments. In a document with no structural content, the entire opening comment block is treated as preamble.

Setter accepts a sequence of bare comment texts (without the leading #) and replaces the current preamble; assign () to remove. Newlines inside any line are rejected.

epilogue property writable

epilogue: tuple[str, ...]

Comment block at the very end of the document.

Returns the trailing run of # … lines that follows all structural content. Empty when the document has no structural content (in that case everything is preamble).

Setter accepts a sequence of bare comment texts and replaces the current epilogue. Assign () to remove.

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

Table

A logical TOML table.

All mapping flavours in tomlrt (top-level document, standard table, inline table, and the synthetic mappings spawned by dotted keys) inherit from Table, which is itself a subclass of dict. So values typed as Table cover every nested mapping you can encounter while walking a document, and isinstance(t, dict) is True and **t works.

Storage model

A Table is a view over the parsed concrete syntax tree (CST) — the physical tree of nodes that records every byte of the original document, including whitespace, comments, quote style and key order. Every mutation writes to the CST first and the dict storage is then refreshed from there. The CST is the single source of truth — render and every iteration ultimately read from it; the dict storage is a cache that mirrors the CST data and exists for two reasons:

  • fast dict-style lookup, len, in, iteration, and ** unpacking; and
  • stable object identity for nested containers, so that doc["foo"] is doc["foo"].

Once a Table is detached (see below) the CST link is severed and the dict storage takes over as the only source of truth for that orphan subtree.

Held references

Held references behave like ordinary Python dict references:

  • If the binding goes away (del doc['foo']), the held Table is orphaned: its dict storage is intact and reads still work, but it is no longer connected to the document and mutations through it do not appear in Document.render.
  • Re-binding the path (doc['foo'] = {...} or doc.install('foo', Table.section())) installs a fresh Table; held references to the old table are unaffected.

Live vs snapshot containers

Assignment of a container value follows one rule: a container is attached to at most one CST location.

  • Assigning a fresh, unattached Array, Table.section result, Table.inline result, or AoT attaches in place: the user's reference becomes the live view at the destination, so later mutations through that reference show up in the document. doc[k] is myvalue after the assign.
  • Assigning a container that is already attached somewhere (any document, including self) deep-clones the source. The two slots are independent — mutations to one don't bleed into the other.
  • Plain dict and list values are snapshot on assignment. Mutations to the original mapping / list after assignment are not reflected in the document. Use Table.section, Table.inline, or Array to opt in to live semantics. Typed containers nested inside a plain dict / list still attach live recursively, even though the surrounding plain container is a snapshot.

section classmethod

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

Return a detached [k] standard-section table.

Use from an assignment site:

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

The returned Table is live: it is not yet connected to any document, but mutations -- t[k] = v, t.update(...), nested Table.section / AoT / Array assignments -- are recorded against its own private CST and survive into the document on assignment. Assigning the table installs it in place: doc[k] is t afterwards, and further mutations through t are visible in dumps.

Assigning a section table that is already attached somewhere deep-clones it; a single CST section lives at one location at a time.

inline classmethod

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

Return a fresh inline table that attaches live on assignment.

Use from an assignment site: doc[k] = Table.inline({...}). Unlike a plain dict (which is snapshotted on assignment), the returned object becomes the live view at the assignment site: subsequent mutations through the original reference are reflected in the document, and doc[k] is the_inline after assignment.

The inline table can be populated incrementally before assignment (t = Table.inline(); t["a"] = 1; doc[k] = t); all such mutations end up in the document.

If the same inline-table object is assigned a second time (or after it has already been installed elsewhere), it is cloned: a single inline table is attached to at most one location in at most one document.

install

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

Install value at path, descending dotted segments.

path accepts a dotted string (split on .) or a tuple of literal segments (use the tuple form to express a segment containing a literal dot, e.g. ("foo.bar",)).

value follows the same rules as ordinary assignment (t[k] = value); install only adds the dotted-path descent. Existing values at path (including sub-sections) are replaced. Implicit intermediate tables are left implicit, so install(("tool", "poetry"), Table.section({})) produces a single [tool.poetry] header, not a [tool] + nested.

Returns the freshly-installed live view (Table, AoT, Array) or the leaf value.

to_dict

to_dict() -> dict[str, Any]

Return a deep, plain-Python copy of this table.

Walks the table recursively and converts every nested Table / AoT / Array view into an ordinary dict / list. The result shares no mutable state with the document and is safe to hand to consumers that expect real dict/list objects.

table

table(key: str) -> Table

Return the table at key, typed as Table.

key accepts a dotted path (e.g. "tool.poetry").

Raises KeyError if any segment is missing, or TypeError if the destination is not a table.

get_table

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

Like table, but returns default if key is missing.

Wrong-type entries raise TypeError.

array

array(key: str) -> Array

Return the array at key, typed as Array.

key accepts a dotted path.

Raises KeyError if any segment is missing, or TypeError if the destination is not an inline array.

get_array

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

Like array, but returns default if key is missing.

Wrong-type entries raise TypeError.

aot

aot(key: str) -> AoT

Return the array-of-tables at key, typed as AoT.

key accepts a dotted path.

Raises KeyError if any segment is missing, or TypeError if the destination is not an array of tables.

get_aot

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

Like aot, but returns default if key is missing.

Wrong-type entries raise TypeError.

comments property

comments: MutableMapping[str, str]

Live mapping of key -> end-of-line comment text.

Only keys that currently carry a comment are present; deleting a key removes its comment. Reads return the comment text without the leading # or surrounding whitespace.

leading_comments property

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

Live mapping of key -> tuple of comment lines above it.

Only keys with a non-empty leading comment block are present. Assigning an empty tuple or deleting a key removes the block.

header_comment deletable property writable

header_comment: str | None

End-of-line comment on this table's [name] / [[name]] line.

None means the header has no trailing comment. Setting None removes any existing comment.

Raises TOMLError for the top-level Document, for inline tables, and for any logical table that exists only through implicit parents (no physical header in source).

For tables declared via multiple discontiguous [name] sections, this refers to the first such header.

header_leading_comments deletable property writable

header_leading_comments: tuple[str, ...]

Comment lines immediately above this table's header.

Returns the contiguous block of # ... lines ending right above the [name] / [[name]] line. Earlier blank-line separated comments are not included. Assigning an empty tuple removes the block.

Raises TOMLError for the top-level Document, for inline tables, and for any logical table that exists only through implicit parents (no physical header in source).

promote_inline

promote_inline(key: str) -> Table

Promote an inline-table-valued key to a standard table.

After promotion the entry is rendered as a separate [parent.key] section, allowing comments and dotted-key expansions on its members.

promote_array

promote_array(key: str) -> AoT

Promote an array-of-inline-tables-valued key to an AoT.

After promotion the entries are rendered as repeated [[parent.key]] sections, allowing comments and dotted-key expansions on each entry's members.

ensure_table

ensure_table(key: str | tuple[str, ...]) -> Table

Return the table at key, creating an empty one if absent.

key accepts a dotted path as a string, or a tuple of literal segments (use the tuple form to express a segment containing a literal dot, e.g. ("foo.bar",)). If the destination already exists and is table-shaped (an explicit section, an implicit super-table, or an inline table), the existing live view is returned and no mutation occurs.

Raises TOMLError when the path names a non-table value.

Array

An inline TOML array.

__init__

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

Construct a standalone inline array.

Array([1, 2, 3]) builds an inline array; Array([1, 2, 3], multiline=True) lays it out one item per line with indent indentation. Such an array is detached until assigned into a document (doc[k] = arr).

comments property

comments: MutableMapping[int, str]

Live mapping of index -> end-of-line comment text.

Only items that currently carry a comment are present; deleting an item removes its comment. Reads return the comment text without the leading # or surrounding whitespace.

leading_comments property

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

Live mapping of index -> tuple of comment lines above item.

multiline property writable

multiline: bool

Whether the array currently renders across multiple lines.

set_multiline

set_multiline(*, multiline: bool, indent: str = '    ') -> Array

Switch this array between single-line and multi-line layout.

indent controls the per-item indentation when multiline is true and is ignored otherwise. Returns self so calls may be chained.

Switching to single-line layout when any item carries an EOL or leading comment is rejected with TOMLError: a # comment runs to end of line, so collapsing such an array would produce invalid TOML. Clear the offending comments first via comments / leading_comments if you really want a single-line layout.

to_list

to_list() -> list[Any]

Return a deep, plain-Python copy of this array.

Walks recursively, converting nested Table / AoT / Array views into ordinary dict / list containers.

array

array(index: SupportsIndex) -> Array

Return self[index] typed as a nested Array.

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, but returns default if index is out of range.

Wrong-type entries raise TypeError.

table

table(index: SupportsIndex) -> Table

Return self[index] typed as a nested Table.

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, but returns default if index is out of range.

Wrong-type entries raise TypeError.

AoT

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

__init__

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

Construct a standalone array-of-tables.

add

add(entry: Mapping[str, TomlInput] = MappingProxyType({})) -> Table

Append entry and return the new Table view.

Convenience over append for the common build-and-mutate idiom: pkg = aot.add({"name": "foo"}); pkg["version"] = "1.0". entry defaults to an empty mapping, so aot.add() adds a blank entry and returns it for further population.

to_list

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

Return a deep, plain-Python copy of this array-of-tables.

Each entry is converted to an ordinary dict (with nested views recursively flattened to plain containers). The result shares no mutable state with the document.

Type aliases

TomlInput module-attribute

TomlInput: TypeAlias = 'Scalar | Array | AoT | Table | Mapping[str, Any] | list[Any]'

What you can pass in to mutators and factories: any Table, Array, or AoT, any TOML scalar (str, int, float, bool, datetime, date, time), or any plain Mapping[str, Any] / list[Any] — the latter two become an inline table/section or inline array respectively.

Errors

TOMLError

Base class for all tomlrt errors.

TOMLParseError

Raised when a TOML document cannot be parsed.

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.