Skip to content

Commit 2b60c35

Browse files
committed
Support text slice assignment
1 parent b22674c commit 2b60c35

File tree

2 files changed

+28
-22
lines changed

2 files changed

+28
-22
lines changed

python/pycrdt/text.py

+24-22
Original file line numberDiff line numberDiff line change
@@ -57,27 +57,32 @@ def __iadd__(self, value: str) -> Text:
5757
self.integrated.insert(txn._txn, len(self), value)
5858
return self
5959

60+
def _check_slice(self, key: slice) -> tuple[int, int]:
61+
if key.step is not None:
62+
raise RuntimeError("Step not supported")
63+
if key.start is None:
64+
start = 0
65+
elif key.start < 0:
66+
raise RuntimeError("Negative start not supported")
67+
else:
68+
start = key.start
69+
if key.stop is None:
70+
stop = len(self) - start
71+
elif key.stop < 0:
72+
raise RuntimeError("Negative stop not supported")
73+
else:
74+
stop = key.stop - start
75+
return start, stop
76+
6077
def __delitem__(self, key: int | slice) -> None:
6178
with self.doc.transaction() as txn:
6279
self._forbid_read_transaction(txn)
6380
if isinstance(key, int):
6481
self.integrated.remove_range(txn._txn, key, 1)
6582
elif isinstance(key, slice):
66-
if key.step is not None:
67-
raise RuntimeError("Step not supported")
68-
if key.start is None:
69-
i = 0
70-
elif key.start < 0:
71-
raise RuntimeError("Negative start not supported")
72-
else:
73-
i = key.start
74-
if key.stop is None:
75-
n = len(self) - i
76-
elif key.stop < 0:
77-
raise RuntimeError("Negative stop not supported")
78-
else:
79-
n = key.stop - i
80-
self.integrated.remove_range(txn._txn, i, n)
83+
start, stop = self._check_slice(key)
84+
if start != stop:
85+
self.integrated.remove_range(txn._txn, start, stop)
8186
else:
8287
raise RuntimeError(f"Index not supported: {key}")
8388

@@ -93,13 +98,10 @@ def __setitem__(self, key: int | slice, value: str) -> None:
9398
del self[key]
9499
self.integrated.insert(txn._txn, key, value)
95100
elif isinstance(key, slice):
96-
if key.step is not None:
97-
raise RuntimeError("Step not supported")
98-
if key.start != key.stop:
99-
raise RuntimeError("Start and stop should be equal")
100-
if len(self) <= key.start < 0:
101-
raise RuntimeError("Index out of range")
102-
self.integrated.insert(txn._txn, key.start, value)
101+
start, stop = self._check_slice(key)
102+
if start != stop:
103+
self.integrated.remove_range(txn._txn, start, stop)
104+
self.integrated.insert(txn._txn, start, value)
103105
else:
104106
raise RuntimeError(f"Index not supported: {key}")
105107

tests/test_text.py

+4
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,7 @@ def test_api():
3535
assert str(text) == hello + world + punct
3636
text.clear()
3737
assert len(text) == 0
38+
text[:] = hello + world + punct
39+
assert str(text) == hello + world + punct
40+
text[len(hello) : len(hello) + len(world)] = " Sir"
41+
assert str(text) == hello + " Sir" + punct

0 commit comments

Comments
 (0)