Skip to content

Comments

tomlrt exposes comments at every level of a document: end-of-line, above an entry, above a section header, and at the top or bottom of the file.

End-of-line comments

Table.comments is a live MutableMapping[str, str] keyed by entry name. Assign a string to set or replace the comment; del removes it entirely.

doc = tomlrt.loads("""
[server]
host = "localhost"  # default
port = 8080
""")

server = doc.table("server")
server.comments["port"] = "override with $PORT"
del server.comments["host"]                 # remove the comment entirely

print(tomlrt.dumps(doc))
# [server]
# host = "localhost"
# port = 8080 # override with $PORT

Comments above an entry

Table.leading_comments is keyed by entry name and stores the attached run of bare comment lines immediately above that entry (no leading #):

server.leading_comments["port"] = (
    "Port the server listens on.",
    "Defaults to 8080.",
)

Section header comments

Table.header_comment is the end-of-line comment on the [section] line itself; Table.header_leading_comments is the run of # … lines immediately above it:

server.header_comment = "HTTP listener"
server.header_leading_comments = ("Server configuration.",)

Array-item comments

Array exposes comments, leading_comments, and leading_block keyed by integer index:

tags = doc.array("tags")
tags.comments[0] = "primary"
tags.leading_comments[1] = ("alternate",)
tags.leading_block[2] = ("older note", None, "attached note")

Inline-table comments

Because tomlrt targets TOML 1.1, inline tables may span multiple lines and carry comments. Table.comments, Table.leading_comments, and Table.leading_block work on an inline table just as they do on a [section], keyed by entry name:

doc = tomlrt.loads('pkg = { name = "tomlrt", version = "0.1" }\n')
pkg = doc.table("pkg")
pkg.comments["name"] = "the package name"

print(tomlrt.dumps(doc))
# pkg = {
#     name = "tomlrt", # the package name
#     version = "0.1",
# }

A single-line inline table has nowhere to put a comment, so setting one promotes the table to multi-line form automatically — exactly as it does for an inline array. You can also control the layout explicitly with Table.multiline / Table.set_multiline(multiline=…); collapsing back to a single line raises if it would orphan a comment.

For a dotted-key inline table such as { a.b = 1 }, address the comment through the inner table — doc["t"]["a"].comments["b"] — mirroring how a top-level a.b = 1 is reached via doc["a"].comments["b"].

Table.header_comment, Table.header_leading_comments, and Table.header_leading_block remain unavailable on inline tables: an inline table has no header line to attach them to.

Blank-separated leading blocks

leading_comments and header_leading_comments cover only the run of # … lines that sit directly above an entry, array element, or section header. A comment group separated from its construct by a blank line is not part of either view.

Table.leading_block, Array.leading_block, and Table.header_leading_block are the full-region counterparts: they expose both blank-separated groups and the attached run as a tuple in which each str is a bare comment line and each None is a blank line. The same distinction applies to section entries, multiline inline-table entries, and multiline array elements.

[a]
x = 1

# orphan

[b]
y = 2
assert doc["b"].header_leading_block == (None, "orphan", None)
doc["b"].header_leading_block = ("orphan", None, "attached")

For the first slot in a document, Document.preamble is disjoint from this view: it is read and written through Document.preamble only.

Document preamble and epilogue

The top-of-file and bottom-of-file comment blocks are reachable via Document.preamble and Document.epilogue, and both have setters that replace the entire block. Assign () to clear.

doc.preamble = ("Generated by build.py — do not edit.",)
doc.epilogue = ("end of file",)

A "preamble" is the document's opening comment paragraph — the run of # … lines before the first blank line. Comments below that blank line belong to the first key or section, not the preamble.

The "epilogue" is the trailing comment block after all structural content. Unlike the preamble it may span blank-separated groups, so it is a tuple[str | None, ...] with None for each blank line.