Skip to content

Commit 238fec1

Browse files
authored
fix: Significant slowdown on nested tables depending on syntax (#324)
1 parent e9ccbe7 commit 238fec1

File tree

3 files changed

+24
-23
lines changed

3 files changed

+24
-23
lines changed

tomlkit/container.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,19 @@ def _get_last_index_before_table(self) -> int:
147147
last_index = i
148148
return last_index + 1
149149

150-
def append(self, key: Key | str | None, item: Item) -> Container:
150+
def _validate_out_of_order_table(self, key: SingleKey | None = None) -> None:
151+
if key is None:
152+
for k in self._map:
153+
assert k is not None
154+
self._validate_out_of_order_table(k)
155+
return
156+
if key not in self._map or not isinstance(self._map[key], tuple):
157+
return
158+
OutOfOrderTableProxy(self, self._map[key])
159+
160+
def append(
161+
self, key: Key | str | None, item: Item, validate: bool = True
162+
) -> Container:
151163
"""Similar to :meth:`add` but both key and value must be given."""
152164
if not isinstance(key, Key) and key is not None:
153165
key = SingleKey(key)
@@ -229,8 +241,8 @@ def append(self, key: Key | str | None, item: Item) -> Container:
229241
else:
230242
self._raw_append(key, item)
231243

232-
# Building a temporary proxy to check for errors
233-
OutOfOrderTableProxy(self, self._map[key])
244+
if validate:
245+
self._validate_out_of_order_table(key)
234246

235247
return self
236248

@@ -288,7 +300,7 @@ def append(self, key: Key | str | None, item: Item) -> Container:
288300
self._raw_append(key, item)
289301
return self
290302

291-
def _raw_append(self, key: Key, item: Item) -> None:
303+
def _raw_append(self, key: Key | None, item: Item) -> None:
292304
if key in self._map:
293305
current_idx = self._map[key]
294306
if not isinstance(current_idx, tuple):
@@ -299,7 +311,7 @@ def _raw_append(self, key: Key, item: Item) -> None:
299311
raise KeyAlreadyPresent(key)
300312

301313
self._map[key] = current_idx + (len(self._body),)
302-
else:
314+
elif key is not None:
303315
self._map[key] = len(self._body)
304316

305317
self._body.append((key, item))
@@ -607,21 +619,8 @@ def __iter__(self) -> Iterator[str]:
607619

608620
# Dictionary methods
609621
def __getitem__(self, key: Key | str) -> Item | Container:
610-
if not isinstance(key, Key):
611-
key = SingleKey(key)
612-
613-
idx = self._map.get(key)
614-
if idx is None:
615-
raise NonExistentKey(key)
616-
617-
if isinstance(idx, tuple):
618-
# The item we are getting is an out of order table
619-
# so we need a proxy to retrieve the proper objects
620-
# from the parent container
621-
return OutOfOrderTableProxy(self, idx)
622-
623-
item = self._body[idx][1]
624-
if item.is_boolean():
622+
item = self.item(key)
623+
if isinstance(item, Item) and item.is_boolean():
625624
return item.value
626625

627626
return item
@@ -800,11 +799,13 @@ def __init__(self, container: Container, indices: tuple[int]) -> None:
800799
self._tables.append(item)
801800
table_idx = len(self._tables) - 1
802801
for k, v in item.value.body:
803-
self._internal_container.append(k, v)
802+
self._internal_container.append(k, v, validate=False)
804803
self._tables_map[k] = table_idx
805804
if k is not None:
806805
dict.__setitem__(self, k.key, v)
807806

807+
self._internal_container._validate_out_of_order_table()
808+
808809
def unwrap(self) -> str:
809810
return self._internal_container.unwrap()
810811

tomlkit/items.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1617,7 +1617,7 @@ def raw_append(self, key: Key | str | None, _item: Any) -> Table:
16171617
if not isinstance(_item, Item):
16181618
_item = item(_item)
16191619

1620-
self._value.append(key, _item)
1620+
self._value.append(key, _item, validate=False)
16211621

16221622
if isinstance(key, Key):
16231623
key = next(iter(key)).key

tomlkit/parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,7 @@ def _parse_table(
10301030
InternalParserError,
10311031
"_parse_item() returned None on a non-bracket character.",
10321032
)
1033-
1033+
table.value._validate_out_of_order_table()
10341034
if isinstance(result, Null):
10351035
result = table
10361036

0 commit comments

Comments
 (0)