jupyter-server-ydoc 2.1.0b0__py3-none-any.whl → 2.1.1__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_server_ydoc/_version.py +1 -1
- jupyter_server_ydoc/app.py +1 -1
- jupyter_server_ydoc/handlers.py +28 -6
- jupyter_server_ydoc/pytest_plugin.py +4 -4
- jupyter_server_ydoc/rooms.py +3 -2
- jupyter_server_ydoc/stores.py +2 -2
- jupyter_server_ydoc/test_utils.py +0 -30
- jupyter_server_ydoc/websocketserver.py +4 -5
- {jupyter_server_ydoc-2.1.0b0.dist-info → jupyter_server_ydoc-2.1.1.dist-info}/METADATA +8 -3
- jupyter_server_ydoc-2.1.1.dist-info/RECORD +19 -0
- jupyter_server_ydoc-2.1.0b0.dist-info/RECORD +0 -19
- {jupyter_server_ydoc-2.1.0b0.data → jupyter_server_ydoc-2.1.1.data}/data/etc/jupyter/jupyter_server_config.d/jupyter_collaboration.json +0 -0
- {jupyter_server_ydoc-2.1.0b0.dist-info → jupyter_server_ydoc-2.1.1.dist-info}/WHEEL +0 -0
- {jupyter_server_ydoc-2.1.0b0.dist-info → jupyter_server_ydoc-2.1.1.dist-info}/licenses/LICENSE +0 -0
jupyter_server_ydoc/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2.1.
|
|
1
|
+
__version__ = "2.1.1"
|
jupyter_server_ydoc/app.py
CHANGED
|
@@ -10,7 +10,7 @@ from jupyter_server.extension.application import ExtensionApp
|
|
|
10
10
|
from jupyter_ydoc import ydocs as YDOCS
|
|
11
11
|
from jupyter_ydoc.ybasedoc import YBaseDoc
|
|
12
12
|
from pycrdt import Doc
|
|
13
|
-
from
|
|
13
|
+
from pycrdt.store import BaseYStore
|
|
14
14
|
from traitlets import Bool, Float, Type
|
|
15
15
|
|
|
16
16
|
from .handlers import (
|
jupyter_server_ydoc/handlers.py
CHANGED
|
@@ -15,9 +15,9 @@ from jupyter_server.auth import authorized
|
|
|
15
15
|
from jupyter_server.base.handlers import APIHandler, JupyterHandler
|
|
16
16
|
from jupyter_server.utils import ensure_async
|
|
17
17
|
from jupyter_ydoc import ydocs as YDOCS
|
|
18
|
-
from pycrdt import Doc, UndoManager
|
|
19
|
-
from
|
|
20
|
-
from
|
|
18
|
+
from pycrdt import Doc, Encoder, UndoManager
|
|
19
|
+
from pycrdt.store import BaseYStore
|
|
20
|
+
from pycrdt.websocket import YRoom
|
|
21
21
|
from tornado import web
|
|
22
22
|
from tornado.websocket import WebSocketHandler
|
|
23
23
|
|
|
@@ -120,7 +120,7 @@ class YDocWebSocketHandler(WebSocketHandler, JupyterHandler):
|
|
|
120
120
|
updates_file_path = f".{file_type}:{file_id}.y"
|
|
121
121
|
ystore = self._ystore_class(
|
|
122
122
|
path=updates_file_path,
|
|
123
|
-
log=self.log,
|
|
123
|
+
log=self.log,
|
|
124
124
|
)
|
|
125
125
|
self.room = DocumentRoom(
|
|
126
126
|
self._room_id,
|
|
@@ -273,7 +273,7 @@ class YDocWebSocketHandler(WebSocketHandler, JupyterHandler):
|
|
|
273
273
|
if self._room_id != "JupyterLab:globalAwareness":
|
|
274
274
|
self._emit_awareness_event(self.current_user.username, "join")
|
|
275
275
|
|
|
276
|
-
async def send(self, message):
|
|
276
|
+
async def send(self, message: bytes) -> None:
|
|
277
277
|
"""
|
|
278
278
|
Send a message to the client.
|
|
279
279
|
"""
|
|
@@ -299,16 +299,38 @@ class YDocWebSocketHandler(WebSocketHandler, JupyterHandler):
|
|
|
299
299
|
if header == MessageType.RAW:
|
|
300
300
|
msg = decoder.read_var_string()
|
|
301
301
|
if msg == "save":
|
|
302
|
+
save_id = decoder.read_var_uint()
|
|
303
|
+
save_reply = {
|
|
304
|
+
"type": "save",
|
|
305
|
+
"responseTo": save_id,
|
|
306
|
+
}
|
|
302
307
|
try:
|
|
303
308
|
room = cast(DocumentRoom, self.room)
|
|
304
|
-
room._save_to_disc()
|
|
309
|
+
save_task = room._save_to_disc()
|
|
310
|
+
# task may be missing if save was already in progress
|
|
311
|
+
if save_task:
|
|
312
|
+
await save_task
|
|
313
|
+
await self.send(
|
|
314
|
+
self._encode_json_message({**save_reply, "status": "success"})
|
|
315
|
+
)
|
|
316
|
+
else:
|
|
317
|
+
await self.send(
|
|
318
|
+
self._encode_json_message({**save_reply, "status": "skipped"})
|
|
319
|
+
)
|
|
305
320
|
except Exception:
|
|
306
321
|
self.log.error("Couldn't save content from room: %s", self._room_id)
|
|
322
|
+
await self.send(self._encode_json_message({**save_reply, "status": "failed"}))
|
|
307
323
|
return
|
|
308
324
|
|
|
309
325
|
self._message_queue.put_nowait(message)
|
|
310
326
|
self._websocket_server.ypatch_nb += 1
|
|
311
327
|
|
|
328
|
+
def _encode_json_message(self, message: dict) -> bytes:
|
|
329
|
+
encoder = Encoder()
|
|
330
|
+
encoder.write_var_uint(MessageType.RAW)
|
|
331
|
+
encoder.write_var_string(json.dumps(message))
|
|
332
|
+
return encoder.to_bytes()
|
|
333
|
+
|
|
312
334
|
def on_close(self) -> None:
|
|
313
335
|
"""
|
|
314
336
|
On connection close.
|
|
@@ -14,13 +14,13 @@ from jupyter_server_ydoc.loaders import FileLoader
|
|
|
14
14
|
from jupyter_server_ydoc.rooms import DocumentRoom
|
|
15
15
|
from jupyter_server_ydoc.stores import SQLiteYStore
|
|
16
16
|
from jupyter_ydoc import YNotebook, YUnicode
|
|
17
|
-
from
|
|
17
|
+
from pycrdt import Provider
|
|
18
|
+
from pycrdt.websocket.websocket import HttpxWebsocket
|
|
18
19
|
|
|
19
20
|
from .test_utils import (
|
|
20
21
|
FakeContentsManager,
|
|
21
22
|
FakeEventLogger,
|
|
22
23
|
FakeFileIDManager,
|
|
23
|
-
Websocket,
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
|
|
@@ -231,7 +231,7 @@ def rtc_add_doc_to_store(rtc_connect_doc_client):
|
|
|
231
231
|
doc.observe(_on_document_change)
|
|
232
232
|
|
|
233
233
|
websocket, room_name = await rtc_connect_doc_client(format, type, path)
|
|
234
|
-
async with websocket as ws,
|
|
234
|
+
async with websocket as ws, Provider(doc.ydoc, HttpxWebsocket(ws, room_name)):
|
|
235
235
|
await event.wait()
|
|
236
236
|
await sleep(0.1)
|
|
237
237
|
|
|
@@ -243,7 +243,7 @@ def rtc_create_SQLite_store_factory(jp_serverapp):
|
|
|
243
243
|
db = SQLiteYStore(
|
|
244
244
|
path=f"{type}:{path}",
|
|
245
245
|
# `SQLiteYStore` here is a subclass of booth `LoggingConfigurable`
|
|
246
|
-
# and `
|
|
246
|
+
# and `pycrdt.store.SQLiteYStore`, but mypy gets lost:
|
|
247
247
|
config=jp_serverapp.config, # type:ignore[call-arg]
|
|
248
248
|
)
|
|
249
249
|
_ = create_task(db.start())
|
jupyter_server_ydoc/rooms.py
CHANGED
|
@@ -9,8 +9,8 @@ from typing import Any, Callable
|
|
|
9
9
|
|
|
10
10
|
from jupyter_events import EventLogger
|
|
11
11
|
from jupyter_ydoc import ydocs as YDOCS
|
|
12
|
-
from
|
|
13
|
-
from
|
|
12
|
+
from pycrdt.websocket import YRoom
|
|
13
|
+
from pycrdt.store import BaseYStore, YDocNotFound
|
|
14
14
|
|
|
15
15
|
from .loaders import FileLoader
|
|
16
16
|
from .utils import JUPYTER_COLLABORATION_EVENTS_URI, LogLevel, OutOfBandChanges
|
|
@@ -280,6 +280,7 @@ class DocumentRoom(YRoom):
|
|
|
280
280
|
self._saving_document = asyncio.create_task(
|
|
281
281
|
self._maybe_save_document(self._saving_document)
|
|
282
282
|
)
|
|
283
|
+
return self._saving_document
|
|
283
284
|
|
|
284
285
|
async def _maybe_save_document(self, saving_document: asyncio.Task | None) -> None:
|
|
285
286
|
"""
|
jupyter_server_ydoc/stores.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Copyright (c) Jupyter Development Team.
|
|
2
2
|
# Distributed under the terms of the Modified BSD License.
|
|
3
3
|
|
|
4
|
-
from
|
|
5
|
-
from
|
|
4
|
+
from pycrdt.store import SQLiteYStore as _SQLiteYStore
|
|
5
|
+
from pycrdt.store import TempFileYStore as _TempFileYStore
|
|
6
6
|
from traitlets import Int, Unicode
|
|
7
7
|
from traitlets.config import LoggingConfigurable
|
|
8
8
|
|
|
@@ -6,7 +6,6 @@ from __future__ import annotations
|
|
|
6
6
|
from datetime import datetime
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
|
-
from anyio import Lock
|
|
10
9
|
from jupyter_server import _tz as tz
|
|
11
10
|
|
|
12
11
|
|
|
@@ -56,32 +55,3 @@ class FakeContentsManager:
|
|
|
56
55
|
class FakeEventLogger:
|
|
57
56
|
def emit(self, schema_id: str, data: dict) -> None:
|
|
58
57
|
print(data)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class Websocket:
|
|
62
|
-
def __init__(self, websocket: Any, path: str):
|
|
63
|
-
self._websocket = websocket
|
|
64
|
-
self._path = path
|
|
65
|
-
self._send_lock = Lock()
|
|
66
|
-
|
|
67
|
-
@property
|
|
68
|
-
def path(self) -> str:
|
|
69
|
-
return self._path
|
|
70
|
-
|
|
71
|
-
def __aiter__(self):
|
|
72
|
-
return self
|
|
73
|
-
|
|
74
|
-
async def __anext__(self) -> bytes:
|
|
75
|
-
try:
|
|
76
|
-
message = await self.recv()
|
|
77
|
-
except Exception:
|
|
78
|
-
raise StopAsyncIteration()
|
|
79
|
-
return message
|
|
80
|
-
|
|
81
|
-
async def send(self, message: bytes) -> None:
|
|
82
|
-
async with self._send_lock:
|
|
83
|
-
await self._websocket.send_bytes(message)
|
|
84
|
-
|
|
85
|
-
async def recv(self) -> bytes:
|
|
86
|
-
b = await self._websocket.receive_bytes()
|
|
87
|
-
return bytes(b)
|
|
@@ -7,10 +7,9 @@ import asyncio
|
|
|
7
7
|
from logging import Logger
|
|
8
8
|
from typing import Any, Callable
|
|
9
9
|
|
|
10
|
-
from
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
from pycrdt_websocket.ystore import BaseYStore
|
|
10
|
+
from pycrdt import Channel
|
|
11
|
+
from pycrdt.store import BaseYStore
|
|
12
|
+
from pycrdt.websocket import WebsocketServer, YRoom
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
class RoomNotFound(LookupError):
|
|
@@ -133,7 +132,7 @@ class JupyterWebsocketServer(WebsocketServer):
|
|
|
133
132
|
await self.start_room(room)
|
|
134
133
|
return room
|
|
135
134
|
|
|
136
|
-
async def serve(self, websocket:
|
|
135
|
+
async def serve(self, websocket: Channel) -> None:
|
|
137
136
|
# start monitoring here as the event loop is not yet available when initializing the object
|
|
138
137
|
if self.monitor_task is None:
|
|
139
138
|
self.monitor_task = asyncio.create_task(self._monitor())
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jupyter-server-ydoc
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: jupyter-server extension integrating collaborative shared models.
|
|
5
|
+
Project-URL: Documentation, https://jupyterlab-realtime-collaboration.readthedocs.io/
|
|
6
|
+
Project-URL: Repository, https://github.com/jupyterlab/jupyter-collaboration
|
|
7
|
+
Project-URL: Changelog, https://jupyterlab-realtime-collaboration.readthedocs.io/en/latest/changelog.html
|
|
8
|
+
Project-URL: Source, https://github.com/jupyterlab/jupyter-collaboration/tree/main/projects/jupyter-server-ydoc
|
|
9
|
+
Project-URL: Issues, https://github.com/jupyterlab/jupyter-collaboration/issues/new/choose
|
|
5
10
|
Author-email: Jupyter Development Team <jupyter@googlegroups.com>
|
|
6
11
|
License: # Licensing terms
|
|
7
12
|
|
|
@@ -79,9 +84,9 @@ Requires-Dist: jsonschema>=4.18.0
|
|
|
79
84
|
Requires-Dist: jupyter-events>=0.11.0
|
|
80
85
|
Requires-Dist: jupyter-server-fileid<1,>=0.7.0
|
|
81
86
|
Requires-Dist: jupyter-server<3.0.0,>=2.15.0
|
|
82
|
-
Requires-Dist: jupyter-ydoc
|
|
87
|
+
Requires-Dist: jupyter-ydoc<4.0.0,>=3.0.3
|
|
83
88
|
Requires-Dist: pycrdt
|
|
84
|
-
Requires-Dist: pycrdt-websocket<0.
|
|
89
|
+
Requires-Dist: pycrdt-websocket<0.17.0,>=0.16.0
|
|
85
90
|
Provides-Extra: test
|
|
86
91
|
Requires-Dist: anyio; extra == 'test'
|
|
87
92
|
Requires-Dist: coverage; extra == 'test'
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
jupyter_server_ydoc/__init__.py,sha256=B8H7XLhzgrTCQD8304Lx91FYXslwabsnV9OuYu4M4Hw,346
|
|
2
|
+
jupyter_server_ydoc/_version.py,sha256=zPJIgPGcoSNiD0qme18OnYJYE3A9VVytlhO-V5DaAW0,22
|
|
3
|
+
jupyter_server_ydoc/app.py,sha256=GuHiXa2CYvJYEa7dxh9ml5ejcKdjihxCpsbo_AY033c,8150
|
|
4
|
+
jupyter_server_ydoc/handlers.py,sha256=1ZCdwtrlqY2Q9d_A-HV2RL7-bmzcgKvF4H_6PoYoOpQ,28794
|
|
5
|
+
jupyter_server_ydoc/loaders.py,sha256=XUQqg2EbfQUYlQVjHY183gYKeVZ6x92VHy4EsOQz4fA,11303
|
|
6
|
+
jupyter_server_ydoc/pytest_plugin.py,sha256=wpRsCss-TxgCeo8zqJru-YsKflfCGG-T2dbhcfQtMeY,8746
|
|
7
|
+
jupyter_server_ydoc/rooms.py,sha256=dKronZ09LeXS7B5zLQwT6JMbsat75C22-MTg1tjbIq4,13086
|
|
8
|
+
jupyter_server_ydoc/stores.py,sha256=AeGtSA25r5gNRLFp8NPTfjrZMrCrHuGG-8Bjos7iIP0,982
|
|
9
|
+
jupyter_server_ydoc/test_utils.py,sha256=IFXUPf1efHd4DgC1GT7ZMJMhKryKlB0Lx4vU2-mhz4Q,1540
|
|
10
|
+
jupyter_server_ydoc/utils.py,sha256=_wI4CFOEZK4MSMYCZe2moSbggUTRdGxY4qTzSDEFzdE,2183
|
|
11
|
+
jupyter_server_ydoc/websocketserver.py,sha256=4Pxl4EIVIz5TxzNWlSDF6KNzZVkzy5SsgvwJx0PoGtY,5099
|
|
12
|
+
jupyter_server_ydoc/events/awareness.yaml,sha256=2FrCci5rZIaU4rn8pIPZJkd132YAZdzKjSNSwjOY7Dk,755
|
|
13
|
+
jupyter_server_ydoc/events/fork.yaml,sha256=3OrhQjhVyLjlBJWMiffbnZodL3GzFafLwEmSBFrK33o,1303
|
|
14
|
+
jupyter_server_ydoc/events/session.yaml,sha256=PS0MxowpRwY5QFYm-LJvHUxKHnsictV8_6VEwfhYxcQ,1596
|
|
15
|
+
jupyter_server_ydoc-2.1.1.data/data/etc/jupyter/jupyter_server_config.d/jupyter_collaboration.json,sha256=0thh2hJUxAKkZSmneJMG0U6QJRjdM6zGlwrTedEt-Jk,94
|
|
16
|
+
jupyter_server_ydoc-2.1.1.dist-info/METADATA,sha256=SiWPyXIdSy7weNnIj5lHu7OqOX8oXTRwmhi47vacjcs,5571
|
|
17
|
+
jupyter_server_ydoc-2.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
18
|
+
jupyter_server_ydoc-2.1.1.dist-info/licenses/LICENSE,sha256=mhO0ZW9EiWOPg0dUgB-lNbJ0CGwRmTdbeAg_se1SOnY,2833
|
|
19
|
+
jupyter_server_ydoc-2.1.1.dist-info/RECORD,,
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
jupyter_server_ydoc/__init__.py,sha256=B8H7XLhzgrTCQD8304Lx91FYXslwabsnV9OuYu4M4Hw,346
|
|
2
|
-
jupyter_server_ydoc/_version.py,sha256=72sTjjXH8lKUBOrH9ADJVFplt-JL7YxNRjHxZ7aL25E,24
|
|
3
|
-
jupyter_server_ydoc/app.py,sha256=6Zca0acaEFCKyUbXdmcPmVk1Dgu91Y-DFjYR16WKFlg,8161
|
|
4
|
-
jupyter_server_ydoc/handlers.py,sha256=WbQLlExk84GsZ0JNA5cmNCbWucruQi0FhQaKG_ZQGiY,27808
|
|
5
|
-
jupyter_server_ydoc/loaders.py,sha256=XUQqg2EbfQUYlQVjHY183gYKeVZ6x92VHy4EsOQz4fA,11303
|
|
6
|
-
jupyter_server_ydoc/pytest_plugin.py,sha256=yMVlk7fvHXiM7g6ua0Ophc96cFwC0bmTWVDbbUeu2DE,8741
|
|
7
|
-
jupyter_server_ydoc/rooms.py,sha256=isX4vHhhvi5WgHtUJBsj29aXw99qoyrO4UOvCij0VbU,13066
|
|
8
|
-
jupyter_server_ydoc/stores.py,sha256=_5J6eNs3R5Tv88PCc-GGuszxQstfvNoBCYABqzBzJXA,1004
|
|
9
|
-
jupyter_server_ydoc/test_utils.py,sha256=utUwB5FThc_SCQshhUbLNih9GUa5qBcmMgU6-jx0ZnA,2275
|
|
10
|
-
jupyter_server_ydoc/utils.py,sha256=_wI4CFOEZK4MSMYCZe2moSbggUTRdGxY4qTzSDEFzdE,2183
|
|
11
|
-
jupyter_server_ydoc/websocketserver.py,sha256=h1yTgJcsCK17_97Ne5x-lbgIFsxylwnltxagcuAlTJY,5185
|
|
12
|
-
jupyter_server_ydoc/events/awareness.yaml,sha256=2FrCci5rZIaU4rn8pIPZJkd132YAZdzKjSNSwjOY7Dk,755
|
|
13
|
-
jupyter_server_ydoc/events/fork.yaml,sha256=3OrhQjhVyLjlBJWMiffbnZodL3GzFafLwEmSBFrK33o,1303
|
|
14
|
-
jupyter_server_ydoc/events/session.yaml,sha256=PS0MxowpRwY5QFYm-LJvHUxKHnsictV8_6VEwfhYxcQ,1596
|
|
15
|
-
jupyter_server_ydoc-2.1.0b0.data/data/etc/jupyter/jupyter_server_config.d/jupyter_collaboration.json,sha256=0thh2hJUxAKkZSmneJMG0U6QJRjdM6zGlwrTedEt-Jk,94
|
|
16
|
-
jupyter_server_ydoc-2.1.0b0.dist-info/METADATA,sha256=xlOlMQTVFDIpYv6qF0-NYbm_Jlu5P-dR1UYUESVeun0,5117
|
|
17
|
-
jupyter_server_ydoc-2.1.0b0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
18
|
-
jupyter_server_ydoc-2.1.0b0.dist-info/licenses/LICENSE,sha256=mhO0ZW9EiWOPg0dUgB-lNbJ0CGwRmTdbeAg_se1SOnY,2833
|
|
19
|
-
jupyter_server_ydoc-2.1.0b0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{jupyter_server_ydoc-2.1.0b0.dist-info → jupyter_server_ydoc-2.1.1.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|