diff --git a/CHANGELOG.md b/CHANGELOG.md index d36550d8..321bbf4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixed +- Add a missing separator when appending to an array whose last value is followed by standalone comments. - Arithmetic and `replace()` results for `Integer`, `Float`, `String`, `DateTime`, `Date` and `Time` no longer share the original item's `Trivia`, so changing the result's comment or indentation no longer rewrites the item still stored in the document. ## [0.15.2] - 2026-10-16 diff --git a/tests/test_items.py b/tests/test_items.py index 36f4afd2..ee6174af 100644 --- a/tests/test_items.py +++ b/tests/test_items.py @@ -521,6 +521,28 @@ def test_modify_array_with_comment() -> None: assert doc.as_string() == "x = [\n 2\n]" +@pytest.mark.parametrize("trailing_comma", [False, True]) +@pytest.mark.parametrize("operation", ["append", "extend", "insert"]) +@pytest.mark.parametrize("comments", ["# trailing\n", "# first\n# trailing\n"]) +def test_append_after_standalone_array_comments( + trailing_comma: bool, operation: str, comments: str +) -> None: + doc = parse("x = [\n1" + ("," if trailing_comma else "") + "\n" + comments + "]\n") + array = doc["x"] + if operation == "append": + array.append(2) + elif operation == "extend": + array.extend([2, 3]) + else: + array.insert(len(array) + 5, 2) + + expected = [1, 2, 3] if operation == "extend" else [1, 2] + rendered = doc.as_string() + assert array == expected + assert parse(rendered)["x"] == expected + assert comments in rendered + + def test_append_to_multiline_array_with_comment() -> None: doc = parse( """\ diff --git a/tomlkit/items.py b/tomlkit/items.py index a73fab8a..6cc0515f 100644 --- a/tomlkit/items.py +++ b/tomlkit/items.py @@ -1675,6 +1675,10 @@ def insert(self, pos: int, value: Any) -> None: # type: ignore[override] indent = self._value[idx].indent if idx > 0: last_item = self._value[idx - 1] + last_value_item = last_item + if pos > 0 and length: + # Standalone comments may follow the preceding array value. + last_value_item = self._value[self._index_map[min(pos, length) - 1]] if indent is None: indent = last_item.indent if not isinstance(last_item.value, Null) and "\n" in default_indent: @@ -1683,14 +1687,14 @@ def insert(self, pos: int, value: Any) -> None: # type: ignore[override] comma = last_item.comma comma_in_indent = indent is not None and "," in indent.s if ( - last_item.comma is None - and not isinstance(last_item.value, Null) + last_value_item.comma is None + and not isinstance(last_value_item.value, Null) and not comma_in_indent ): # Add comma to the last item to separate it from the following # items, unless the new item's indent already starts with a # comma (comma-first style). - last_item.comma = Whitespace(",") + last_value_item.comma = Whitespace(",") if indent is not None and "," in indent.s: # Comma-first style: the item that will follow the new one brings # its own leading comma, so the new item must not add a trailing