Whole file
python-poetry/tomlkit
The author described this change as “fix: reject out-of-order concrete+super table redefinitions at parse time (#530)”. It counts as a record because the check below fails on the code as it stood at f40ae4632 and passes on d3c76f0bb, with nothing else changed between the two runs.
Projectpython-poetry/tomlkit
Fix saved2026-06-23
Sharing licenceMIT · LICENSE
Change size+18 −0
What the code was meant to do, written into the code itself as a save note
fix: reject out-of-order concrete+super table redefinitions at parse time (#530)
The change
| 327 | 327 | self._validate_table_candidate(current, item) | |
| 328 | 328 | elif not item.is_super_table(): | |
| 329 | 329 | raise KeyAlreadyPresent(key) | |
| 330 | + | else: | |
| 331 | + | # An existing concrete table (current) is being extended by | |
| 332 | + | # a super-table (item) — e.g. [a] b=1 then [a.b] c=2 out of | |
| 333 | + | # order, or [a] b.c=1 then [a.b] d=2. Validate that the | |
| 334 | + | # super-table does not redefine any existing key, raising | |
| 335 | + | # early at parse time. When validation passes, fall through | |
| 336 | + | # — _raw_append below will create an out-of-order entry and | |
| 337 | + | # preserve table ordering in the document. | |
| 338 | + | assert isinstance(current, Table) | |
| 339 | + | self._validate_table_candidate(current, item) | |
| 330 | 340 | elif isinstance(item, AoT): | |
| 331 | 341 | if not isinstance(current, AoT): | |
| 332 | 342 | # Tried to define an AoT after a table with the same name. | |
| ⋯ | |||
| 370 | 380 | previous_item.trivia.trail += "\n" | |
| 371 | 381 | ||
| 372 | 382 | self._raw_append(key, item) | |
| 383 | + | if validate and key is not None: | |
| 384 | + | self._validate_out_of_order_table(key) | |
| 373 | 385 | return self | |
| 374 | 386 | ||
| 375 | 387 | def _validate_table_candidate(self, current: Table, candidate: Table) -> None: | |
| ⋯ | |||
| 394 | 406 | continue | |
| 395 | 407 | ||
| 396 | 408 | if not k.is_dotted(): | |
| 409 | + | # Even when the candidate key itself is not dotted, an | |
| 410 | + | # existing dotted key may already use it as a prefix — | |
| 411 | + | # e.g. [a] b.c=1 then [a.b] d=2 (b prefixes b.c). | |
| 412 | + | for existing_key in current.value._map: | |
| 413 | + | if existing_key.is_dotted() and next(iter(existing_key)) == k: | |
| 414 | + | raise TOMLKitError("Redefinition of an existing table") | |
| 397 | 415 | continue | |
| 398 | 416 | ||
| 399 | 417 | head = next(iter(k)) | |
The check that tells the two apart
fail→pass·tests/test_toml_document.py::test_reject_out_of_order_dotted_key_redefinition_at_parse
Check file tests/test_toml_document.py, taken without changes from the fix and copied onto the older code, so the exact same check runs against both versions.
Origin and history
The code before itf40ae46323992b1cda523424bdfb30de899eb4f6
Broken version dated2026-06-23
Moduletomlkit.container
Units changedContainer
Fingerprint57848d512d751519
Checked2026-08-18 by goldset/0.1
Every field above is generated by our program. None of it is written by hand.
Other bugs found in python-poetry/tomlkit
- 2026-07-15Fix top-level scalar captured by a table rendered from a dotted key (#550)
- 2026-07-14Fix array of tables replacing a dotted key swallowing the next sibling (#542) (#549)
- 2026-07-14fix: avoid duplicate table header when adding a key to an out-of-order table (#545)
- 2026-06-23fix: keep newline after dotted inline table (#533)
- 2026-06-23raise on malformed array element instead of dropping it (#527)
- 2026-06-23Fix ParseError when a sub-table extends an array of tables out of order (#498)