Skip to content

Commit e6e5d38

Browse files
authored
fix: delete keys from out of order table (#379)
1 parent 8c1671a commit e6e5d38

File tree

5 files changed

+101
-11
lines changed

5 files changed

+101
-11
lines changed

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Change Log
22

3+
## [0.13.2] - 2024-08-14
4+
5+
### Fixed
6+
7+
- Fix deleting keys from an out-of-order table does not remove all table parts. ([#379](https://github.com/python-poetry/tomlkit/issues/379))
8+
39
## [0.13.1] - 2024-08-14
410

511
### Fixed
@@ -414,7 +420,8 @@
414420
- Fixed handling of super tables with different sections.
415421
- Fixed raw strings escaping.
416422

417-
[unreleased]: https://github.com/sdispater/tomlkit/compare/0.13.1...master
423+
[unreleased]: https://github.com/sdispater/tomlkit/compare/0.13.2...master
424+
[0.13.2]: https://github.com/sdispater/tomlkit/releases/tag/0.13.2
418425
[0.13.1]: https://github.com/sdispater/tomlkit/releases/tag/0.13.1
419426
[0.13.0]: https://github.com/sdispater/tomlkit/releases/tag/0.13.0
420427
[0.12.5]: https://github.com/sdispater/tomlkit/releases/tag/0.12.5

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "tomlkit"
3-
version = "0.13.1"
3+
version = "0.13.2"
44
description = "Style preserving TOML library"
55
authors = [
66
"Sébastien Eustace <[email protected]>",

tests/test_toml_document.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,3 +1109,81 @@ def test_item_preserves_the_order():
11091109
age = 42
11101110
"""
11111111
assert tomlkit.dumps(doc) == expected
1112+
1113+
1114+
def test_delete_out_of_order_table_key():
1115+
content = """\
1116+
[foo]
1117+
name = "foo"
1118+
1119+
[bar.a.b]
1120+
name = "bar-a-b"
1121+
1122+
[foo.a]
1123+
name = "foo-a"
1124+
1125+
[bar.a]
1126+
name = "bar-a"
1127+
1128+
[baz]
1129+
name = "baz"
1130+
1131+
[bar.a.c]
1132+
name = "bar-a-c"
1133+
"""
1134+
doc = parse(content)
1135+
del doc["bar"]["a"]
1136+
assert (
1137+
doc.as_string()
1138+
== """\
1139+
[foo]
1140+
name = "foo"
1141+
1142+
[foo.a]
1143+
name = "foo-a"
1144+
1145+
[baz]
1146+
name = "baz"
1147+
1148+
"""
1149+
)
1150+
1151+
1152+
def test_overwrite_out_of_order_table_key():
1153+
content = """\
1154+
[foo]
1155+
name = "foo"
1156+
1157+
[bar.a.b]
1158+
name = "bar-a-b"
1159+
1160+
[foo.a]
1161+
name = "foo-a"
1162+
1163+
[bar.a]
1164+
name = "bar-a"
1165+
1166+
[baz]
1167+
name = "baz"
1168+
1169+
[bar.a.c]
1170+
name = "bar-a-c"
1171+
"""
1172+
doc = parse(content)
1173+
doc["bar"]["a"] = {"name": "bar-a-updated"}
1174+
assert (
1175+
doc.as_string()
1176+
== """\
1177+
[foo]
1178+
name = "foo"
1179+
1180+
[bar.a]
1181+
name = "bar-a-updated"
1182+
[foo.a]
1183+
name = "foo-a"
1184+
1185+
[baz]
1186+
name = "baz"
1187+
1188+
"""
1189+
)

tomlkit/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
from tomlkit.api import ws
2828

2929

30-
__version__ = "0.13.1"
30+
__version__ = "0.13.2"
3131
__all__ = [
3232
"aot",
3333
"array",

tomlkit/container.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ def __init__(self, container: Container, indices: tuple[int, ...]) -> None:
814814
table_idx = len(self._tables) - 1
815815
for k, v in item.value.body:
816816
self._internal_container._raw_append(k, v)
817-
self._tables_map[k] = table_idx
817+
self._tables_map.setdefault(k, []).append(table_idx)
818818
if k is not None:
819819
dict.__setitem__(self, k.key, v)
820820

@@ -835,8 +835,12 @@ def __getitem__(self, key: Key | str) -> Any:
835835

836836
def __setitem__(self, key: Key | str, item: Any) -> None:
837837
if key in self._tables_map:
838-
table = self._tables[self._tables_map[key]]
839-
table[key] = item
838+
# Overwrite the first table and remove others
839+
indices = self._tables_map[key]
840+
while len(indices) > 1:
841+
table = self._tables[indices.pop()]
842+
self._remove_table(table)
843+
self._tables[indices[0]][key] = item
840844
elif self._tables:
841845
table = self._tables[0]
842846
table[key] = item
@@ -856,15 +860,16 @@ def _remove_table(self, table: Table) -> None:
856860
break
857861

858862
def __delitem__(self, key: Key | str) -> None:
859-
if key in self._tables_map:
860-
table = self._tables[self._tables_map[key]]
863+
if key not in self._tables_map:
864+
raise NonExistentKey(key)
865+
866+
for i in reversed(self._tables_map[key]):
867+
table = self._tables[i]
861868
del table[key]
862869
if not table and len(self._tables) > 1:
863870
self._remove_table(table)
864-
del self._tables_map[key]
865-
else:
866-
raise NonExistentKey(key)
867871

872+
del self._tables_map[key]
868873
del self._internal_container[key]
869874
if key is not None:
870875
dict.__delitem__(self, key)

0 commit comments

Comments
 (0)