Skip to content

Fix spurious KeyAlreadyPresent on valid out-of-order child table (#571) - #592

Open
chiliec wants to merge 2 commits into
python-poetry:masterfrom
chiliec:fix/issue-571-out-of-order-proxy-validation
Open

Fix spurious KeyAlreadyPresent on valid out-of-order child table (#571)#592
chiliec wants to merge 2 commits into
python-poetry:masterfrom
chiliec:fix/issue-571-out-of-order-proxy-validation

Conversation

@chiliec

@chiliec chiliec commented Aug 27, 2026

Copy link
Copy Markdown

Fixes #571.

Problem

A regression in 0.15.1 rejects a valid document when a table has an out-of-order child, its concrete parent is declared afterwards, and another table separates a later sibling child:

import tomlkit

tomlkit.loads("""\
[tool.ruff]
[tool.ruff.lint.a]
[tool.ruff.lint]
[[tool.poetry.source]]
[tool.ruff.lint.b]
""")
# tomlkit.exceptions.ParseError: Key "lint" already exists. at line 5 col 0

tomllib and tomlkit 0.13.3 / 0.14.0 / 0.15.0 all accept it.

Root cause

The concrete+super validation added in 0.15.1 (_validate_table_candidate) treats only Table/AoT as table-like:

if isinstance(existing, (Table, AoT)) != isinstance(v, (Table, AoT)):
    raise KeyAlreadyPresent(k)

When lint is spread across out-of-order headers, current.value.item("lint") returns an OutOfOrderTableProxy, not a Table. So the left side is False while the candidate [tool.ruff.lint.b] is a Table (False != True), and valid input is reported as a type conflict.

Fix

  • Recognise OutOfOrderTableProxy as table-like in the type-conflict check.
  • When the existing entry is a proxy, recurse into each of its concrete Table fragments (existing._tables) so a genuine duplicate is still detected, rather than rejecting outright.

Real duplicates — including out-of-order ones like [a.b] / [a] / [a.b] — remain rejected.

Test

Adds test_parse_accepts_out_of_order_child_with_intervening_table (the issue's exact document; asserts the parsed structure matches tomllib and the round-trip is byte-for-byte preserved). Also adds a CHANGELOG entry.

Verification (local, Python 3.11)

  • RED→GREEN: with the fix reverted the new test fails (Key "lint" already exists); with it, it passes.
  • pytest tests/1053 passed, 0 failed (full suite incl. the BurntSushi toml-test conformance corpus), no regressions.
  • The parsed result equals tomllib.loads(...) and dumps(doc) reproduces the input exactly.
  • ruff check introduces no new lint errors in the changed regions.

chiliec and others added 2 commits August 27, 2026 05:47
…hon-poetry#571)

_validate_table_candidate treated only Table/AoT as table-like. When a table
is spread across out-of-order headers, its existing entry is an
OutOfOrderTableProxy, so the isinstance(existing, (Table, AoT)) check was False
while the candidate was a Table. The mismatch raised KeyAlreadyPresent for a
document that tomllib and tomlkit <= 0.15.0 accept (a regression introduced by
the concrete+super validation in 0.15.1).

Recognise OutOfOrderTableProxy as table-like in the type-conflict check, and
when the existing entry is a proxy recurse into each of its concrete table
fragments so genuine duplicates are still rejected.

Adds a regression test and a CHANGELOG entry. Full suite passes (1053 tests).

Fixes python-poetry#571.

Signed-off-by: Vladimir Babin <vovababin@gmail.com>
@dimbleby

Copy link
Copy Markdown
Contributor

explain why not #572

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regression in 0.15.1: valid out-of-order child table raises KeyAlreadyPresent

2 participants