Skip to content

Commit

Permalink
Resolve "Text data type does not delete as expected" (#68)
Browse files Browse the repository at this point in the history
* Adjust check for zero-length ranges and rename variables

Fixes #67

* Remove variable assignment for inserted value length

* Add, document and reorder convenience methods for text manipulation

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Revert "Remove variable assignment for inserted value length"

This reverts commit cebe3d5.

* Combine deletion and insertion into a single-line replacement

* Have the slice check returning a slice again

The range length is computed outside/after the slice check

* Add and adjust tests for insertion and deletion

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Revert changes on manipulation methods, but keep docstrings

* Add test for single character replacements

---------

Co-authored-by: Jakob Zahn <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Jan 22, 2024
1 parent 8d8dce2 commit 60f1c4a
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 10 deletions.
20 changes: 12 additions & 8 deletions python/pycrdt/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ def _check_slice(self, key: slice) -> tuple[int, int]:
else:
start = key.start
if key.stop is None:
stop = len(self) - start
stop = len(self)
elif key.stop < 0:
raise RuntimeError("Negative stop not supported")
else:
stop = key.stop - start
stop = key.stop
return start, stop

def __delitem__(self, key: int | slice) -> None:
Expand All @@ -86,8 +86,9 @@ def __delitem__(self, key: int | slice) -> None:
self.integrated.remove_range(txn._txn, key, 1)
elif isinstance(key, slice):
start, stop = self._check_slice(key)
if start != stop:
self.integrated.remove_range(txn._txn, start, stop)
length = stop - start
if length > 0:
self.integrated.remove_range(txn._txn, start, length)
else:
raise RuntimeError(f"Index not supported: {key}")

Expand All @@ -104,17 +105,20 @@ def __setitem__(self, key: int | slice, value: str) -> None:
self.integrated.insert(txn._txn, key, value)
elif isinstance(key, slice):
start, stop = self._check_slice(key)
if start != stop:
self.integrated.remove_range(txn._txn, start, stop)
length = stop - start
if length > 0:
self.integrated.remove_range(txn._txn, start, length)
self.integrated.insert(txn._txn, start, value)
else:
raise RuntimeError(f"Index not supported: {key}")

def clear(self) -> None:
"""Remove the entire range of characters."""
del self[:]

def insert(self, index, text: str) -> None:
self[index:index] = text
def insert(self, index: int, value: str) -> None:
"""Insert 'value' at character position 'index'."""
self[index:index] = value

def observe(self, callback: Callable[[Any], None]) -> str:
_callback = partial(observe_callback, callback, self.doc)
Expand Down
21 changes: 19 additions & 2 deletions tests/test_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

hello = "Hello"
world = ", World"
sir = " Sir"
punct = "!"


Expand Down Expand Up @@ -37,8 +38,24 @@ def test_api():
assert len(text) == 0
text[:] = hello + world + punct
assert str(text) == hello + world + punct
text[len(hello) : len(hello) + len(world)] = " Sir"
assert str(text) == hello + " Sir" + punct
text[len(hello) : len(hello) + len(world)] = sir
assert str(text) == hello + sir + punct
# single character replacement
text[len(text) - 1] = "?"
assert str(text) == hello + sir + "?"
# deletion with only an index
del text[len(text) - 1]
assert str(text) == hello + sir
# deletion of an arbitrary range
del text[len(hello) : len(hello) + len(sir)]
assert str(text) == hello
# deletion with start index == range length
text += str(text)
del text[len(hello) : 2 * len(hello)]
assert str(text) == hello
# deletion with a range of 0
del text[len(hello) : len(hello)]
assert str(text) == hello


def test_to_py():
Expand Down

0 comments on commit 60f1c4a

Please sign in to comment.