diff --git a/CHANGELOG.md b/CHANGELOG.md index 69cfb89..888e9b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Fix the incompatiblity with 3.13 because of the `datetime.replace()` change. ([#333](https://github.com/python-poetry/tomlkit/issues/333)) - Revert the change of parsing out-of-order tables. ([#347](https://github.com/python-poetry/tomlkit/issues/347)) +- Keep the nested out-of-order table. ([#361](https://github.com/python-poetry/tomlkit/issues/361)) ## [0.12.5] - 2024-05-08 diff --git a/tests/test_toml_document.py b/tests/test_toml_document.py index f968b4e..9331478 100644 --- a/tests/test_toml_document.py +++ b/tests/test_toml_document.py @@ -676,6 +676,31 @@ def test_remove_from_out_of_order_table(): assert json.dumps(document) == '{"a": {"x": 1}, "c": {"z": 3}}' +def test_update_nested_out_of_order_table(): + doc = parse("""\ +[root1.root2.a.b.c] + value = 2 +[WALRUS] + goo = "gjob" +[root1.root2.x] + value = 4 +""") + doc["root1"]["root2"]["a"].add("tmp", "hi") + assert ( + doc.as_string() + == """\ +[root1.root2.a] +tmp = "hi" +[root1.root2.a.b.c] + value = 2 +[WALRUS] + goo = "gjob" +[root1.root2.x] + value = 4 +""" + ) + + def test_updating_nested_value_keeps_correct_indent(): content = """ [Key1] diff --git a/tomlkit/container.py b/tomlkit/container.py index e14112f..33d499e 100644 --- a/tomlkit/container.py +++ b/tomlkit/container.py @@ -155,7 +155,7 @@ def _validate_out_of_order_table(self, key: SingleKey | None = None) -> None: return if key not in self._map or not isinstance(self._map[key], tuple): return - OutOfOrderTableProxy(self, self._map[key]) + OutOfOrderTableProxy.validate(self, self._map[key]) def append( self, key: Key | str | None, item: Item, validate: bool = True @@ -785,8 +785,38 @@ def _previous_item(self, idx: int | None = None, ignore=(Null,)) -> Item | None: return prev[-1] if prev else None +def _validate_out_of_order_table( + container: Container, indices: tuple[int, ...] +) -> None: + """Validate out of order tables in the given container""" + # Append all items to a temp container to see if there is any error + temp_container = Container(True) + for i in indices: + _, item = container._body[i] + + if isinstance(item, Table): + for k, v in item.value.body: + temp_container.append(k, v, validate=False) + + temp_container._validate_out_of_order_table() + + class OutOfOrderTableProxy(_CustomDict): - def __init__(self, container: Container, indices: tuple[int]) -> None: + @staticmethod + def validate(container: Container, indices: tuple[int, ...]) -> None: + """Validate out of order tables in the given container""" + # Append all items to a temp container to see if there is any error + temp_container = Container(True) + for i in indices: + _, item = container._body[i] + + if isinstance(item, Table): + for k, v in item.value.body: + temp_container.append(k, v, validate=False) + + temp_container._validate_out_of_order_table() + + def __init__(self, container: Container, indices: tuple[int, ...]) -> None: self._container = container self._internal_container = Container(True) self._tables = [] @@ -799,7 +829,7 @@ def __init__(self, container: Container, indices: tuple[int]) -> None: self._tables.append(item) table_idx = len(self._tables) - 1 for k, v in item.value.body: - self._internal_container.append(k, v, validate=False) + self._internal_container._raw_append(k, v) self._tables_map[k] = table_idx if k is not None: dict.__setitem__(self, k.key, v)