Skip to content

Commit 0404622

Browse files
committed
Use pycrdt instead of y-py
1 parent 8ea8da6 commit 0404622

File tree

7 files changed

+81
-108
lines changed

7 files changed

+81
-108
lines changed

jupyter_ydoc/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
import sys
55

6-
from ._version import __version__ # noqa
7-
from .yblob import YBlob # noqa
8-
from .yfile import YFile # noqa
9-
from .ynotebook import YNotebook # noqa
10-
from .yunicode import YUnicode # noqa
6+
from ._version import __version__
7+
from .yblob import YBlob
8+
from .yfile import YFile
9+
from .ynotebook import YNotebook
10+
from .yunicode import YUnicode
1111

1212
# See compatibility note on `group` keyword in
1313
# https://docs.python.org/3/library/importlib.metadata.html#entry-points

jupyter_ydoc/ybasedoc.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
# Distributed under the terms of the Modified BSD License.
33

44
from abc import ABC, abstractmethod
5-
from typing import Any, Callable, Optional
5+
from typing import Any, Callable, Dict, Optional
66

7-
import y_py as Y
7+
from pycrdt import Doc, Map
88

99

1010
class YBaseDoc(ABC):
@@ -15,19 +15,20 @@ class YBaseDoc(ABC):
1515
subscribe to changes in the document.
1616
"""
1717

18-
def __init__(self, ydoc: Optional[Y.YDoc] = None):
18+
def __init__(self, ydoc: Optional[Doc] = None):
1919
"""
2020
Constructs a YBaseDoc.
2121
22-
:param ydoc: The :class:`y_py.YDoc` that will hold the data of the document, if provided.
23-
:type ydoc: :class:`y_py.YDoc`, optional.
22+
:param ydoc: The :class:`pycrdt.Doc` that will hold the data of the document, if provided.
23+
:type ydoc: :class:`pycrdt.Doc`, optional.
2424
"""
2525
if ydoc is None:
26-
self._ydoc = Y.YDoc()
26+
self._ydoc = Doc()
2727
else:
2828
self._ydoc = ydoc
29-
self._ystate = self._ydoc.get_map("state")
30-
self._subscriptions = {}
29+
self._ystate = Map()
30+
self._ydoc["state"] = self._ystate
31+
self._subscriptions: Dict[Any, str] = {}
3132

3233
@property
3334
@abstractmethod
@@ -40,22 +41,22 @@ def version(self) -> str:
4041
"""
4142

4243
@property
43-
def ystate(self) -> Y.YMap:
44+
def ystate(self) -> Map:
4445
"""
45-
A :class:`y_py.YMap` containing the state of the document.
46+
A :class:`pycrdt.Map` containing the state of the document.
4647
4748
:return: The document's state.
48-
:rtype: :class:`y_py.YMap`
49+
:rtype: :class:`pycrdt.Map`
4950
"""
5051
return self._ystate
5152

5253
@property
53-
def ydoc(self) -> Y.YDoc:
54+
def ydoc(self) -> Doc:
5455
"""
55-
The underlying :class:`y_py.YDoc` that contains the data.
56+
The underlying :class:`pycrdt.Doc` that contains the data.
5657
5758
:return: The document's ydoc.
58-
:rtype: :class:`y_py.YDoc`
59+
:rtype: :class:`pycrdt.Doc`
5960
"""
6061
return self._ydoc
6162

@@ -87,7 +88,7 @@ def dirty(self) -> Optional[bool]:
8788
:return: Whether the document is dirty.
8889
:rtype: Optional[bool]
8990
"""
90-
return self._ystate["dirty"]
91+
return self._ystate.get("dirty")
9192

9293
@dirty.setter
9394
def dirty(self, value: bool) -> None:
@@ -97,8 +98,7 @@ def dirty(self, value: bool) -> None:
9798
:param value: Whether the document is clean or dirty.
9899
:type value: bool
99100
"""
100-
with self._ydoc.begin_transaction() as t:
101-
self._ystate.set(t, "dirty", value)
101+
self._ystate["dirty"] = value
102102

103103
@property
104104
def path(self) -> Optional[str]:
@@ -118,8 +118,7 @@ def path(self, value: str) -> None:
118118
:param value: Document's path.
119119
:type value: str
120120
"""
121-
with self._ydoc.begin_transaction() as t:
122-
self._ystate.set(t, "path", value)
121+
self._ystate["path"] = value
123122

124123
@abstractmethod
125124
def get(self) -> Any:

jupyter_ydoc/yblob.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from functools import partial
66
from typing import Any, Callable, Optional, Union
77

8-
import y_py as Y
8+
from pycrdt import Doc, Map
99

1010
from .ybasedoc import YBaseDoc
1111

@@ -28,15 +28,16 @@ class YBlob(YBaseDoc):
2828
}
2929
"""
3030

31-
def __init__(self, ydoc: Optional[Y.YDoc] = None):
31+
def __init__(self, ydoc: Optional[Doc] = None):
3232
"""
3333
Constructs a YBlob.
3434
35-
:param ydoc: The :class:`y_py.YDoc` that will hold the data of the document, if provided.
36-
:type ydoc: :class:`y_py.YDoc`, optional.
35+
:param ydoc: The :class:`pycrdt.Doc` that will hold the data of the document, if provided.
36+
:type ydoc: :class:`pycrdt.Doc`, optional.
3737
"""
3838
super().__init__(ydoc)
39-
self._ysource = self._ydoc.get_map("source")
39+
self._ysource = Map()
40+
self._ydoc["source"] = self._ysource
4041

4142
@property
4243
def version(self) -> str:
@@ -55,7 +56,7 @@ def get(self) -> bytes:
5556
:return: Document's content.
5657
:rtype: bytes
5758
"""
58-
return base64.b64decode(self._ysource.get("base64", "").encode())
59+
return base64.b64decode(self._ysource["base64"].encode())
5960

6061
def set(self, value: Union[bytes, str]) -> None:
6162
"""
@@ -66,8 +67,7 @@ def set(self, value: Union[bytes, str]) -> None:
6667
"""
6768
if isinstance(value, bytes):
6869
value = base64.b64encode(value).decode()
69-
with self._ydoc.begin_transaction() as t:
70-
self._ysource.set(t, "base64", value)
70+
self._ysource["base64"] = value
7171

7272
def observe(self, callback: Callable[[str, Any], None]) -> None:
7373
"""

jupyter_ydoc/ynotebook.py

Lines changed: 35 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from typing import Any, Callable, Dict, Optional
88
from uuid import uuid4
99

10-
import y_py as Y
10+
from pycrdt import Array, Doc, Map, Text
1111

1212
from .utils import cast_all
1313
from .ybasedoc import YBaseDoc
@@ -47,16 +47,18 @@ class YNotebook(YBaseDoc):
4747
}
4848
"""
4949

50-
def __init__(self, ydoc: Optional[Y.YDoc] = None):
50+
def __init__(self, ydoc: Optional[Doc] = None):
5151
"""
5252
Constructs a YNotebook.
5353
54-
:param ydoc: The :class:`y_py.YDoc` that will hold the data of the document, if provided.
55-
:type ydoc: :class:`y_py.YDoc`, optional.
54+
:param ydoc: The :class:`pycrdt.Doc` that will hold the data of the document, if provided.
55+
:type ydoc: :class:`pycrdt.Doc`, optional.
5656
"""
5757
super().__init__(ydoc)
58-
self._ymeta = self._ydoc.get_map("meta")
59-
self._ycells = self._ydoc.get_array("cells")
58+
self._ymeta = Map()
59+
self._ycells = Array()
60+
self._ydoc["meta"] = self._ymeta
61+
self._ydoc["cells"] = self._ycells
6062

6163
@property
6264
def version(self) -> str:
@@ -74,7 +76,7 @@ def ycells(self):
7476
Returns the Y-cells.
7577
7678
:return: The Y-cells.
77-
:rtype: :class:`y_py.YArray`
79+
:rtype: :class:`pycrdt.Array`
7880
"""
7981
return self._ycells
8082

@@ -98,8 +100,8 @@ def get_cell(self, index: int) -> Dict[str, Any]:
98100
:return: A cell.
99101
:rtype: Dict[str, Any]
100102
"""
101-
meta = json.loads(self._ymeta.to_json())
102-
cell = json.loads(self._ycells[index].to_json())
103+
meta = json.loads(str(self._ymeta))
104+
cell = json.loads(str(self._ycells[index]))
103105
cast_all(cell, float, int) # cells coming from Yjs have e.g. execution_count as float
104106
if "id" in cell and meta["nbformat"] == 4 and meta["nbformat_minor"] <= 4:
105107
# strip cell IDs if we have notebook format 4.0-4.4
@@ -112,26 +114,17 @@ def get_cell(self, index: int) -> Dict[str, Any]:
112114
del cell["attachments"]
113115
return cell
114116

115-
def append_cell(self, value: Dict[str, Any], txn: Optional[Y.YTransaction] = None) -> None:
117+
def append_cell(self, value: Dict[str, Any]) -> None:
116118
"""
117119
Appends a cell.
118120
119121
:param value: A cell.
120122
:type value: Dict[str, Any]
121-
122-
:param txn: A YTransaction, defaults to None
123-
:type txn: :class:`y_py.YTransaction`, optional.
124123
"""
125124
ycell = self.create_ycell(value)
126-
if txn is None:
127-
with self._ydoc.begin_transaction() as txn:
128-
self._ycells.append(txn, ycell)
129-
else:
130-
self._ycells.append(txn, ycell)
131-
132-
def set_cell(
133-
self, index: int, value: Dict[str, Any], txn: Optional[Y.YTransaction] = None
134-
) -> None:
125+
self._ycells.append(ycell)
126+
127+
def set_cell(self, index: int, value: Dict[str, Any]) -> None:
135128
"""
136129
Sets a cell into indicated position.
137130
@@ -140,60 +133,48 @@ def set_cell(
140133
141134
:param value: A cell.
142135
:type value: Dict[str, Any]
143-
144-
:param txn: A YTransaction, defaults to None
145-
:type txn: :class:`y_py.YTransaction`, optional.
146136
"""
147137
ycell = self.create_ycell(value)
148-
self.set_ycell(index, ycell, txn)
138+
self.set_ycell(index, ycell)
149139

150-
def create_ycell(self, value: Dict[str, Any]) -> Y.YMap:
140+
def create_ycell(self, value: Dict[str, Any]) -> Map:
151141
"""
152142
Creates YMap with the content of the cell.
153143
154144
:param value: A cell.
155145
:type value: Dict[str, Any]
156146
157147
:return: A new cell.
158-
:rtype: :class:`y_py.YMap`
148+
:rtype: :class:`pycrdt.Map`
159149
"""
160150
cell = copy.deepcopy(value)
161151
if "id" not in cell:
162152
cell["id"] = str(uuid4())
163153
cell_type = cell["cell_type"]
164154
cell_source = cell["source"]
165155
cell_source = "".join(cell_source) if isinstance(cell_source, list) else cell_source
166-
cell["source"] = Y.YText(cell_source)
167-
cell["metadata"] = Y.YMap(cell.get("metadata", {}))
156+
cell["source"] = Text(cell_source)
157+
cell["metadata"] = Map(cell.get("metadata", {}))
168158

169159
if cell_type in ("raw", "markdown"):
170160
if "attachments" in cell and not cell["attachments"]:
171161
del cell["attachments"]
172162
elif cell_type == "code":
173-
cell["outputs"] = Y.YArray(cell.get("outputs", []))
163+
cell["outputs"] = Array(cell.get("outputs", []))
174164

175-
return Y.YMap(cell)
165+
return Map(cell)
176166

177-
def set_ycell(self, index: int, ycell: Y.YMap, txn: Optional[Y.YTransaction] = None) -> None:
167+
def set_ycell(self, index: int, ycell: Map) -> None:
178168
"""
179169
Sets a Y cell into the indicated position.
180170
181171
:param index: The index of the cell.
182172
:type index: int
183173
184174
:param ycell: A YMap with the content of a cell.
185-
:type ycell: :class:`y_py.YMap`
186-
187-
:param txn: A YTransaction, defaults to None
188-
:type txn: :class:`y_py.YTransaction`, optional.
175+
:type ycell: :class:`pycrdt.Map`
189176
"""
190-
if txn is None:
191-
with self._ydoc.begin_transaction() as txn:
192-
self._ycells.delete(txn, index)
193-
self._ycells.insert(txn, index, ycell)
194-
else:
195-
self._ycells.delete(txn, index)
196-
self._ycells.insert(txn, index, ycell)
177+
self._ycells[index] = ycell
197178

198179
def get(self) -> Dict:
199180
"""
@@ -202,7 +183,7 @@ def get(self) -> Dict:
202183
:return: Document's content.
203184
:rtype: Dict
204185
"""
205-
meta = json.loads(self._ymeta.to_json())
186+
meta = json.loads(str(self._ymeta))
206187
cast_all(meta, float, int) # notebook coming from Yjs has e.g. nbformat as float
207188
cells = []
208189
for i in range(len(self._ycells)):
@@ -247,29 +228,23 @@ def set(self, value: Dict) -> None:
247228
}
248229
]
249230

250-
with self._ydoc.begin_transaction() as t:
231+
with self._ydoc.transaction():
251232
# clear document
252-
cells_len = len(self._ycells)
253-
for key in self._ymeta:
254-
self._ymeta.pop(t, key)
255-
if cells_len:
256-
self._ycells.delete_range(t, 0, cells_len)
257-
for key in [k for k in self._ystate if k not in ("dirty", "path")]:
258-
self._ystate.pop(t, key)
233+
self._ymeta.clear()
234+
self._ycells.clear()
235+
for key in [k for k in self._ystate.keys() if k not in ("dirty", "path")]:
236+
del self._ystate[key]
259237

260238
# initialize document
261-
# workaround for https://github.com/y-crdt/ypy/issues/126:
262-
# self._ycells.extend(t, [self.create_ycell(cell) for cell in cells])
263-
for cell in cells:
264-
self._ycells.append(t, self.create_ycell(cell))
265-
self._ymeta.set(t, "nbformat", nb.get("nbformat", NBFORMAT_MAJOR_VERSION))
266-
self._ymeta.set(t, "nbformat_minor", nb.get("nbformat_minor", NBFORMAT_MINOR_VERSION))
239+
self._ycells.extend([self.create_ycell(cell) for cell in cells])
240+
self._ymeta["nbformat"] = nb.get("nbformat", NBFORMAT_MAJOR_VERSION)
241+
self._ymeta["nbformat_minor"] = nb.get("nbformat_minor", NBFORMAT_MINOR_VERSION)
267242

268243
metadata = nb.get("metadata", {})
269244
metadata.setdefault("language_info", {"name": ""})
270245
metadata.setdefault("kernelspec", {"name": "", "display_name": ""})
271246

272-
self._ymeta.set(t, "metadata", Y.YMap(metadata))
247+
self._ymeta["metadata"] = Map(metadata)
273248

274249
def observe(self, callback: Callable[[str, Any], None]) -> None:
275250
"""

0 commit comments

Comments
 (0)