Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 17 additions & 19 deletions src/yamltrip/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
)

if TYPE_CHECKING:
from collections.abc import Sequence
from collections.abc import Callable, Sequence

from ._core import Feature
from ._types import KeyPart
Expand Down Expand Up @@ -316,20 +316,8 @@ def remove(self, *keys: KeyPart, prune: bool = False) -> Document:
def append(self, *keys: KeyPart, value: Any) -> Document:
"""Append a single item to the sequence at path."""
route = _make_route(keys)
op = Op.append(value)
patch = Patch(route=route, operation=op)
try:
return self._apply_patches([patch])
except PatchError as e:
kind = _classify_patch_error(e)
if kind == _PatchErrorKind.FLOW_SEQUENCE:
current = self[keys]
new_list = [*list(current), value]
replace_op = Op.replace(new_list)
return self._apply_patches([Patch(route=route, operation=replace_op)])
if kind == _PatchErrorKind.NOT_A_SEQUENCE:
raise NodeTypeError(str(e)) from None
raise
patch = Patch(route=route, operation=Op.append(value))
return self._with_flow_seq_fallback(keys, [patch], lambda lst: [*lst, value])

def insert(self, *keys: KeyPart, index: int, value: Any) -> Document:
"""Insert an item at a specific position in the sequence at path.
Expand Down Expand Up @@ -361,15 +349,25 @@ def extend_list(self, *keys: KeyPart, values: Sequence[Any]) -> Document:
return self
route = _make_route(keys)
patches = [Patch(route=route, operation=Op.append(v)) for v in values]
return self._with_flow_seq_fallback(keys, patches, lambda lst: [*lst, *values])

def _with_flow_seq_fallback(
self,
keys: tuple[KeyPart, ...],
patches: list[Patch],
fallback_fn: Callable[[list[Any]], list[Any]],
) -> Document:
"""Apply patches, falling back to get→mutate→replace for flow sequences."""
try:
return self._apply_patches(patches)
except PatchError as e:
kind = _classify_patch_error(e)
if kind == _PatchErrorKind.FLOW_SEQUENCE:
current = self[keys]
new_list = [*list(current), *values]
replace_op = Op.replace(new_list)
return self._apply_patches([Patch(route=route, operation=replace_op)])
new_list = fallback_fn(list(self[keys]))
route = _make_route(keys)
return self._apply_patches(
[Patch(route=route, operation=Op.replace(new_list))]
)
if kind == _PatchErrorKind.NOT_A_SEQUENCE:
raise NodeTypeError(str(e)) from None
raise
Expand Down
Loading