Skip to content

Commit ed70577

Browse files
committed
Fix array item removal
1 parent 1a3085c commit ed70577

File tree

3 files changed

+78
-9
lines changed

3 files changed

+78
-9
lines changed

tests/test_items.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,3 +1019,40 @@ def test_removal_of_arrayitem_with_extra_whitespace():
10191019
docstr = doc.as_string()
10201020
parse(docstr)
10211021
assert docstr == expected
1022+
1023+
1024+
def test_badly_formatted_array_and_item_removal():
1025+
expected = """
1026+
x = [
1027+
'0'#a
1028+
,#b
1029+
1030+
# comment
1031+
'1' #c
1032+
, #d
1033+
# another comment
1034+
'2'
1035+
# yet another comment
1036+
,'3', # f
1037+
# comments here
1038+
'4'#g
1039+
# comments there
1040+
,'5' #h
1041+
# comments everywhere
1042+
# so many comments
1043+
,'6' ,
1044+
# you get a comment
1045+
# you get a comment
1046+
'7' ,#j
1047+
# everybody gets a comment!!!
1048+
"8"#c
1049+
,"9", \n "10"
1050+
]
1051+
"""
1052+
assert expected == parse(expected).as_string()
1053+
for i in range(11):
1054+
doc = parse(expected)
1055+
x = doc["x"]
1056+
assert isinstance(x, Array)
1057+
x.remove(str(i))
1058+
parse(doc.as_string())

tomlkit/items.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1138,11 +1138,13 @@ def _group_values(self, value: list[Item]) -> list[_ArrayItemGroup]:
11381138
"""Group the values into (indent, value, comma, comment) tuples"""
11391139
groups = []
11401140
this_group = _ArrayItemGroup()
1141+
start_new_group = False
11411142
for item in value:
11421143
if isinstance(item, Whitespace):
1143-
if "," not in item.s:
1144+
if "," not in item.s or start_new_group:
11441145
groups.append(this_group)
11451146
this_group = _ArrayItemGroup(indent=item)
1147+
start_new_group = False
11461148
else:
11471149
if this_group.value is None:
11481150
# when comma is met and no value is provided, add a dummy Null
@@ -1152,6 +1154,8 @@ def _group_values(self, value: list[Item]) -> list[_ArrayItemGroup]:
11521154
if this_group.value is None:
11531155
this_group.value = Null()
11541156
this_group.comment = item
1157+
# Comments are the last item in a group.
1158+
start_new_group = True
11551159
elif this_group.value is None:
11561160
this_group.value = item
11571161
else:
@@ -1399,6 +1403,7 @@ def __delitem__(self, key: int | slice):
13991403
if not isinstance(key, slice):
14001404
raise IndexError("list index out of range") from e
14011405
else:
1406+
group_rm = self._value[idx]
14021407
del self._value[idx]
14031408
if (
14041409
idx == 0
@@ -1408,6 +1413,37 @@ def __delitem__(self, key: int | slice):
14081413
):
14091414
# Remove the indentation of the first item if not newline
14101415
self._value[idx].indent = None
1416+
comma_in_indent = (
1417+
group_rm.indent is not None and "," in group_rm.indent.s
1418+
)
1419+
comma_in_comma = group_rm.comma is not None and "," in group_rm.comma.s
1420+
if comma_in_indent ^ comma_in_comma:
1421+
# Removed group had one comma. No need to do anything else.
1422+
continue
1423+
if comma_in_indent and comma_in_comma:
1424+
# Removed group had both commas. Add one to the next group.
1425+
group = self._value[idx] if len(self._value) > idx else None
1426+
if group is not None:
1427+
if group.indent is None:
1428+
group.indent = Whitespace(",")
1429+
elif "," not in group.indent.s:
1430+
# Insert the comma after the newline
1431+
try:
1432+
newline_index = group.indent.s.index("\n")
1433+
group.indent._s = (
1434+
group.indent.s[: newline_index + 1]
1435+
+ ","
1436+
+ group.indent.s[newline_index + 1 :]
1437+
)
1438+
except ValueError:
1439+
group.indent._s = "," + group.indent.s
1440+
elif not comma_in_indent and not comma_in_comma:
1441+
# Removed group had no commas. Remove the next comma found.
1442+
for j in range(idx, len(self._value)):
1443+
group = self._value[j]
1444+
if group.indent is not None and "," in group.indent.s:
1445+
group.indent._s = group.indent.s.replace(",", "", 1)
1446+
break
14111447
if len(self._value) > 0:
14121448
v = self._value[-1]
14131449
if not v.is_whitespace():

tomlkit/parser.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -595,15 +595,11 @@ def _parse_array(self) -> Array:
595595
# consume comma
596596
if prev_value and self._current == ",":
597597
self.inc(exception=UnexpectedEofError)
598-
# Check if the previous item is Whitespace
599-
if isinstance(elems[-1], Whitespace) and " " in elems[-1].s:
600-
# Preserve the previous whitespace
601-
comma = Whitespace(elems[-1].s + ",")
602-
# Remove the replaced item
603-
del elems[-1]
598+
# If the previous item is Whitespace, add to it
599+
if isinstance(elems[-1], Whitespace):
600+
elems[-1]._s = elems[-1].s + ","
604601
else:
605-
comma = Whitespace(",")
606-
elems.append(comma)
602+
elems.append(Whitespace(","))
607603
prev_value = False
608604
continue
609605

0 commit comments

Comments
 (0)