Silent data loss: emptying an implicitly-created table (dotted key) makes it vanish from as_string() while unwrap() still contains it
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 76/100
Direzione di ricerca
Start with the dotted-key table creation in items.py around lines 1948-1949, then trace Container._render_table in container.py lines 672-708 and removal logic in lines 476-514. Reproduce the minimal examples and add regression coverage for remove() and clear() on implicit tables. Done means as_string() output reparses to the same unwrap() structure without affecting explicit tables, whole-table deletion, inline tables, or AoT elements.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
After removing keys from a table that was created implicitly (via a dotted key, with no [header] of its own), an empty intermediate table remains in the in-memory model (unwrap() / dict view) but is silently dropped from as_string() / dumps() output. The rendered document no longer round-trips: parse(doc.as_string()).unwrap() != doc.unwrap() — data is lost without any warning.
This is a silent data loss: no exception, no error, the output is perfectly valid TOML — it just no longer contains a table the user can still see in the in-memory model.
Minimal reproduction (copy-paste)
import tomlkit
doc = tomlkit.parse("[a]\nb.c = 1\nd = 2\n")
del doc["a"]["b"]["c"] # empty the implicitly-created table `a.b`
s = doc.as_string()
print(repr(s)) # '[a]\nd = 2\n' <- no trace of `a.b`
print(doc.unwrap()) # {'a': {'b': {}, 'd': 2}} <- `a.b` still here
print(tomlkit.parse(s).unwrap())# {'a': {'d': 2}} <- `a.b` lost
Also works with pure top-level dotted keys, remove(), and clear():
doc = tomlkit.parse("a.b.c = 1\na.d = 2\n")
doc["a"]["b"].remove("c")
# as_string() -> 'a.d = 2\n'
# unwrap() -> {'a': {'b': {}, 'd': 2}}
# reparse -> {'a': {'d': 2}}
doc = tomlkit.parse("[a]\nb.c = 1\nd = 2\n")
doc["a"]["b"].clear()
# same mismatch
What is NOT affected (verified)
- Tables with an explicit
[a.b]header: the empty header is preserved ([a.b]\n), round-trips fine. - Deleting the whole table (
del doc["a"]["b"]): consistent. - Inline tables and AoT elements: consistent.
So the bug is specific to implicit tables — those created by dotted keys (b.c = 1, a.b.c = 1) or by out-of-order [a.b] sections where the parent got no header of its own.
Frequency
A random-mutation fuzz (parse -> 1-4 random delete/add/replace ops -> compare unwrap() vs parse(as_string()).unwrap()) hit this in 274 of 3000 runs. It is the dominant round-trip failure mode.
Root cause
When the parser creates an intermediate table from a dotted key, it sets Table._is_super_table = True (items.py:1948-1949). is_super_table() returns that frozen flag first, so the if not self: return False fallback (which would correctly make an empty table render its own header) is never reached after the table has been emptied.
Container._render_table (container.py:672-708) then treats the table as a super table: no [a.b] header is emitted, and with no children left to render, the table renders as the empty string — while Container.remove / _remove_at (container.py:476-514) never invalidate the frozen _is_super_table flag on the emptied table, and the table stays in the parent's _body and dict view (hence unwrap() still contains it).
Expected
Either the emptied implicit table keeps rendering (e.g. as [a.b], matching the explicit-header behavior), or it is removed from the in-memory model together with the rendered output — but unwrap() and parse(as_string()).unwrap() should never disagree.
Related
- #204 "Deleting a table creates invalid output" (closed) — different symptom (duplicate headers when deleting a whole multi-tier table); this one is about the contents of an implicit table being emptied.
Environment
tomlkit master @ 8c959b5 (0.15.1+), Python 3.12.
- Lingua principale
- Python
- Stelle
- 850
- Fork
- 163
- Merge medio
- 13m
- PR unite (30g)
- 2
Preparare l'ambiente
Non abbiamo ancora controllato i file di configurazione di questo progetto. Parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di python-poetry/tomlkit
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
python-poetry/tomlkit#546 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
python-poetry/tomlkit#614 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 68/100
python-poetry/tomlkit#603 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 52/100
python-poetry/tomlkit#580 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 72/100
python-poetry/tomlkit#577 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di python-poetry/tomlkit
Issue simili
-
Broken links found in docsApertadocs pydanty:is-working
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
pydantic/pydantic-ai#8863 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
run-llama/llama_index#23278 ·
I maintainer di solito rispondono entro 2 giorni
-
documentation from-review-extraction github-actions priority: low severity:nit
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 92/100
LearningCircuit/local-deep-research#6946 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
oracle/langchain-oracle#323 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
tenstorrent/tt-metal#58057 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno