Sort parsed documents recursively with sort_keys - #617
Sreekant13 wants to merge 2 commits into
Conversation
dumps(doc, sort_keys=True) sorted only the top-level keys of a parsed document: item() returned an already-parsed Table/InlineTable/AoT unchanged, so only the top-level container reached the sorting rebuild. A plain dict, whose nested values are plain dicts, already sorted recursively. item() now returns a sorted copy of a parsed table-like item. The copy reorders each container's body by key, keeps every key's leading comment and whitespace lines with it, orders a value that renders as its own section after the inline values so a key never folds under a preceding header, keeps inline tables inline, and leaves the input document unmutated. A container holding an out-of-order table is left in place, since its entries cannot be linearly reordered, but its nested tables are still sorted.
The _sort_container_body annotation referenced Container, which items.py otherwise imports lazily inside item(); add it to the TYPE_CHECKING block so ruff no longer flags F821 (undefined name).
|
Verified locally: full suite passes, the new test fails on master as claimed, and I spot-checked the edge cases (comments following keys, out-of-order fragments, no input mutation, deep nesting, top-level AoT). Looks good to me — the (a)/(b) direction call is for the maintainers, but I lean (a) per the comment on #614. |
|
Thanks for the thorough local verification, and agreed on (a): On your two observations, both are pre-existing and I would keep them out of this PR:
Happy to follow up on either separately if the maintainers would like. |
|
Agreed on the scoping — keeping both observations out of this PR is the right call. Nothing further from my side; the rest is up to the maintainers. |
Fixes #614.
Problem
dumps(doc, sort_keys=True)sorts only the top-level keys of a document produced byparse()/loads(). Nested tables, inline tables and arrays of tables keep their original order, even though the same option applied to a plaindictsorts recursively.Cause
item()returns an already-parsedTable/InlineTable/AoTunchanged. For a parsed document the top-level container reaches thedictbranch and is rebuilt sorted, but each nested value is already such an item, so the recursiveitem(value, _sort_keys=True)call returns it as is and never sorts its keys. A plain dict has plain-dict children, which recurse and sort.Change
Under
_sort_keys,item()returns a sorted copy of a parsed table-like item. The copy:A container holding an out-of-order table is left in place, since its entries cannot be linearly reordered, but its nested tables are still sorted.
Tests
Added
test_dumps_with_sorted_keys_recurses_into_a_parsed_document, covering nested tables, an inline table, an array of tables, a scalar kept before a sub-table section, and that the document is not mutated. It fails onmainand passes with this change. The rest of the suite passes (thetoml-testconformance submodule, which this change does not touch, is not exercised here).