jupyter-ydoc 3.3.0__py3-none-any.whl → 3.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jupyter_ydoc/_version.py +1 -1
- jupyter_ydoc/ynotebook.py +8 -3
- jupyter_ydoc/yunicode.py +39 -7
- {jupyter_ydoc-3.3.0.dist-info → jupyter_ydoc-3.3.2.dist-info}/METADATA +1 -1
- jupyter_ydoc-3.3.2.dist-info/RECORD +14 -0
- {jupyter_ydoc-3.3.0.dist-info → jupyter_ydoc-3.3.2.dist-info}/WHEEL +1 -1
- jupyter_ydoc-3.3.0.dist-info/RECORD +0 -14
- {jupyter_ydoc-3.3.0.dist-info → jupyter_ydoc-3.3.2.dist-info}/entry_points.txt +0 -0
- {jupyter_ydoc-3.3.0.dist-info → jupyter_ydoc-3.3.2.dist-info}/licenses/LICENSE +0 -0
jupyter_ydoc/_version.py
CHANGED
jupyter_ydoc/ynotebook.py
CHANGED
|
@@ -345,9 +345,14 @@ class YNotebook(YBaseDoc):
|
|
|
345
345
|
for key in shared_keys:
|
|
346
346
|
if old_cell[key] != new_cell[key]:
|
|
347
347
|
value = new_cell[key]
|
|
348
|
-
if
|
|
349
|
-
|
|
350
|
-
|
|
348
|
+
if (
|
|
349
|
+
key == "outputs"
|
|
350
|
+
and value
|
|
351
|
+
and any(output.get("output_type") == "stream" for output in value)
|
|
352
|
+
):
|
|
353
|
+
# Outputs with stream require complex handling as they have
|
|
354
|
+
# the Text type nested inside; for now skip creating them.
|
|
355
|
+
# Clearing all outputs is fine.
|
|
351
356
|
return False
|
|
352
357
|
|
|
353
358
|
if key in _CELL_KEY_TYPE_MAP:
|
jupyter_ydoc/yunicode.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# Distributed under the terms of the Modified BSD License.
|
|
3
3
|
|
|
4
4
|
from collections.abc import Callable
|
|
5
|
+
from difflib import SequenceMatcher
|
|
5
6
|
from functools import partial
|
|
6
7
|
from typing import Any
|
|
7
8
|
|
|
@@ -9,6 +10,9 @@ from pycrdt import Awareness, Doc, Text
|
|
|
9
10
|
|
|
10
11
|
from .ybasedoc import YBaseDoc
|
|
11
12
|
|
|
13
|
+
# Heuristic threshold as recommended in difflib documentation
|
|
14
|
+
SIMILARITY_THREESHOLD = 0.6
|
|
15
|
+
|
|
12
16
|
|
|
13
17
|
class YUnicode(YBaseDoc):
|
|
14
18
|
"""
|
|
@@ -35,7 +39,7 @@ class YUnicode(YBaseDoc):
|
|
|
35
39
|
:type awareness: :class:`pycrdt.Awareness`, optional.
|
|
36
40
|
"""
|
|
37
41
|
super().__init__(ydoc, awareness)
|
|
38
|
-
self._ysource = self._ydoc.get("source", type=Text)
|
|
42
|
+
self._ysource: Text = self._ydoc.get("source", type=Text)
|
|
39
43
|
self.undo_manager.expand_scope(self._ysource)
|
|
40
44
|
|
|
41
45
|
@property
|
|
@@ -64,17 +68,45 @@ class YUnicode(YBaseDoc):
|
|
|
64
68
|
:param value: The content of the document.
|
|
65
69
|
:type value: str
|
|
66
70
|
"""
|
|
67
|
-
|
|
71
|
+
old_value = self.get()
|
|
72
|
+
if old_value == value:
|
|
68
73
|
# no-op if the values are already the same,
|
|
69
74
|
# to avoid side-effects such as cursor jumping to the top
|
|
70
75
|
return
|
|
71
76
|
|
|
72
77
|
with self._ydoc.transaction():
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
matcher = SequenceMatcher(a=old_value, b=value)
|
|
79
|
+
|
|
80
|
+
if (
|
|
81
|
+
matcher.real_quick_ratio() >= SIMILARITY_THREESHOLD
|
|
82
|
+
and matcher.ratio() >= SIMILARITY_THREESHOLD
|
|
83
|
+
):
|
|
84
|
+
operations = matcher.get_opcodes()
|
|
85
|
+
offset = 0
|
|
86
|
+
for tag, i1, i2, j1, j2 in operations:
|
|
87
|
+
match tag:
|
|
88
|
+
case "replace":
|
|
89
|
+
self._ysource[i1 + offset : i2 + offset] = value[j1:j2]
|
|
90
|
+
offset += (j2 - j1) - (i2 - i1)
|
|
91
|
+
case "delete":
|
|
92
|
+
del self._ysource[i1 + offset : i2 + offset]
|
|
93
|
+
offset -= i2 - i1
|
|
94
|
+
case "insert":
|
|
95
|
+
self._ysource.insert(i1 + offset, value[j1:j2])
|
|
96
|
+
offset += j2 - j1
|
|
97
|
+
case "equal":
|
|
98
|
+
pass
|
|
99
|
+
case _:
|
|
100
|
+
raise ValueError(f"Unknown tag '{tag}' in sequence matcher")
|
|
101
|
+
else:
|
|
102
|
+
# for very different strings, just replace the whole content;
|
|
103
|
+
# this avoids generating a huge number of operations
|
|
104
|
+
|
|
105
|
+
# clear document
|
|
106
|
+
self._ysource.clear()
|
|
107
|
+
# initialize document
|
|
108
|
+
if value:
|
|
109
|
+
self._ysource += value
|
|
78
110
|
|
|
79
111
|
def observe(self, callback: Callable[[str, Any], None]) -> None:
|
|
80
112
|
"""
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
jupyter_ydoc/__init__.py,sha256=itUidK7o0_wS6YcbKKIyt1su7hM3-YppQshFheTQQdw,428
|
|
2
|
+
jupyter_ydoc/_version.py,sha256=v4KIZUrlasa2fZGLAsEoZ179ShRb4xGFjH2KEtqJAUY,171
|
|
3
|
+
jupyter_ydoc/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
jupyter_ydoc/utils.py,sha256=yKvcuqhpylMinmjuscuZ_kY8KPEseFbwcg5K9VzYOfs,810
|
|
5
|
+
jupyter_ydoc/ybasedoc.py,sha256=c0jwhULtTNCjOYHbXhDhKaD6OJYn7hpL4hcLZWyGJsU,5115
|
|
6
|
+
jupyter_ydoc/yblob.py,sha256=JZiXQhONqFS8Cqdglx__AVeS18gyRq0yHq-AQKFPVfw,2316
|
|
7
|
+
jupyter_ydoc/yfile.py,sha256=XTMtAXDWgIOLU2KUQxkLJz2cGvSPlOxpvJc4daXCV6I,198
|
|
8
|
+
jupyter_ydoc/ynotebook.py,sha256=Xplr1x57Y6gWAU84u-Krh9_Xkn_-AN-Vte4DJY5VOfw,13452
|
|
9
|
+
jupyter_ydoc/yunicode.py,sha256=nPNhXLT06TwxvbZL8IhFiMvRYkFoS6Hnpm1MNVlW4b4,4004
|
|
10
|
+
jupyter_ydoc-3.3.2.dist-info/METADATA,sha256=-2RhQiCsCQ_aryHI6YjqCnYIeL06LzjENOxtRduz8_8,2282
|
|
11
|
+
jupyter_ydoc-3.3.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
12
|
+
jupyter_ydoc-3.3.2.dist-info/entry_points.txt,sha256=lgvRG-rpsjRKf8cy7LpO7fqwwXy0sBVMCwhGOHgn4mc,164
|
|
13
|
+
jupyter_ydoc-3.3.2.dist-info/licenses/LICENSE,sha256=dqphsFbhnlzPK7Vlkc66Zc7g7PS-e1dln07GXIVpFCQ,1567
|
|
14
|
+
jupyter_ydoc-3.3.2.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
jupyter_ydoc/__init__.py,sha256=itUidK7o0_wS6YcbKKIyt1su7hM3-YppQshFheTQQdw,428
|
|
2
|
-
jupyter_ydoc/_version.py,sha256=Tz6lmxmxKUkvsL1d8BVDTboI2Qi1KGyuKbw2_SfyWeo,171
|
|
3
|
-
jupyter_ydoc/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
jupyter_ydoc/utils.py,sha256=yKvcuqhpylMinmjuscuZ_kY8KPEseFbwcg5K9VzYOfs,810
|
|
5
|
-
jupyter_ydoc/ybasedoc.py,sha256=c0jwhULtTNCjOYHbXhDhKaD6OJYn7hpL4hcLZWyGJsU,5115
|
|
6
|
-
jupyter_ydoc/yblob.py,sha256=JZiXQhONqFS8Cqdglx__AVeS18gyRq0yHq-AQKFPVfw,2316
|
|
7
|
-
jupyter_ydoc/yfile.py,sha256=XTMtAXDWgIOLU2KUQxkLJz2cGvSPlOxpvJc4daXCV6I,198
|
|
8
|
-
jupyter_ydoc/ynotebook.py,sha256=_nyBC1kKGr1TQlfmFGAMWU1xb0z-vyxRQiLfTukpbAI,13257
|
|
9
|
-
jupyter_ydoc/yunicode.py,sha256=ZLNLTJoy75gxCwI8ZNBv_gD42hrzHfD-J6GOO1WaJIE,2574
|
|
10
|
-
jupyter_ydoc-3.3.0.dist-info/METADATA,sha256=mmVXxTiGc9_QTtRRtjlD2JJpg4Q_JHjaF4tT4JjjQgA,2282
|
|
11
|
-
jupyter_ydoc-3.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
12
|
-
jupyter_ydoc-3.3.0.dist-info/entry_points.txt,sha256=lgvRG-rpsjRKf8cy7LpO7fqwwXy0sBVMCwhGOHgn4mc,164
|
|
13
|
-
jupyter_ydoc-3.3.0.dist-info/licenses/LICENSE,sha256=dqphsFbhnlzPK7Vlkc66Zc7g7PS-e1dln07GXIVpFCQ,1567
|
|
14
|
-
jupyter_ydoc-3.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|