Skip to content

Commit fcb82ae

Browse files
authored
fix: Missing newline at end of file with multiple array of tables can corrupt during dumping (#422)
Fixes #381 Signed-off-by: Frost Ming <[email protected]>
1 parent d4e1ecd commit fcb82ae

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
### Fixed
1010

11+
- Fix missing newline when parsing a separated array of tables without trailing new line. ([#381](https://github.com/python-poetry/tomlkit/issues/381))
1112
- Fix non-existing key error when deleting an item from an out-of-order table. ([#383](https://github.com/python-poetry/tomlkit/issues/383))
1213
- Ensure newline is added between the plain values and the first table. ([#387](https://github.com/python-poetry/tomlkit/issues/387))
1314
- Fix repeated whitespace when removing an array item. ([#405](https://github.com/python-poetry/tomlkit/issues/405))

tests/test_toml_document.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,3 +1257,39 @@ def test_delete_key_from_out_of_order_table():
12571257
d = 4
12581258
"""
12591259
)
1260+
1261+
1262+
def test_parse_aot_without_ending_newline():
1263+
content = '''\
1264+
[[products]]
1265+
name = "Hammer"
1266+
1267+
[foo]
1268+
1269+
[bar]
1270+
1271+
[[products]]
1272+
name = "Nail"'''
1273+
doc = parse(content)
1274+
assert (
1275+
doc.as_string()
1276+
== """\
1277+
[[products]]
1278+
name = "Hammer"
1279+
1280+
[[products]]
1281+
name = "Nail"
1282+
[foo]
1283+
1284+
[bar]
1285+
1286+
"""
1287+
)
1288+
assert doc == {
1289+
"products": [
1290+
{"name": "Hammer"},
1291+
{"name": "Nail"},
1292+
],
1293+
"foo": {},
1294+
"bar": {},
1295+
}

tomlkit/container.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,20 @@ def as_string(self) -> str:
488488
for k, v in self._body:
489489
if k is not None:
490490
if isinstance(v, Table):
491+
if (
492+
s.strip(" ")
493+
and not s.strip(" ").endswith("\n")
494+
and "\n" not in v.trivia.indent
495+
):
496+
s += "\n"
491497
s += self._render_table(k, v)
492498
elif isinstance(v, AoT):
499+
if (
500+
s.strip(" ")
501+
and not s.strip(" ").endswith("\n")
502+
and "\n" not in v.trivia.indent
503+
):
504+
s += "\n"
493505
s += self._render_aot(k, v)
494506
else:
495507
s += self._render_simple_item(k, v)
@@ -538,6 +550,12 @@ def _render_table(self, key: Key, table: Table, prefix: str | None = None) -> st
538550

539551
for k, v in table.value.body:
540552
if isinstance(v, Table):
553+
if (
554+
cur.strip(" ")
555+
and not cur.strip(" ").endswith("\n")
556+
and "\n" not in v.trivia.indent
557+
):
558+
cur += "\n"
541559
if v.is_super_table():
542560
if k.is_dotted() and not key.is_dotted():
543561
# Dotted key inside table
@@ -547,6 +565,12 @@ def _render_table(self, key: Key, table: Table, prefix: str | None = None) -> st
547565
else:
548566
cur += self._render_table(k, v, prefix=_key)
549567
elif isinstance(v, AoT):
568+
if (
569+
cur.strip(" ")
570+
and not cur.strip(" ").endswith("\n")
571+
and "\n" not in v.trivia.indent
572+
):
573+
cur += "\n"
550574
cur += self._render_aot(k, v, prefix=_key)
551575
else:
552576
cur += self._render_simple_item(

0 commit comments

Comments
 (0)