jupyter-server-ydoc 1.0.0rc1__tar.gz → 1.0.1__tar.gz
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-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/PKG-INFO +3 -3
- jupyter_server_ydoc-1.0.1/jupyter_server_ydoc/_version.py +1 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/pytest_plugin.py +17 -9
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/test_utils.py +30 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/pyproject.toml +2 -1
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/tests/test_documents.py +11 -8
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/tests/test_handlers.py +11 -15
- jupyter_server_ydoc-1.0.0rc1/jupyter_server_ydoc/_version.py +0 -1
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/.gitignore +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/LICENSE +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/README.md +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter-config/jupyter_server_ydoc.json +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/__init__.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/app.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/events/awareness.yaml +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/events/session.yaml +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/handlers.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/loaders.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/rooms.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/stores.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/utils.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/websocketserver.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/setup.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/tests/__init__.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/tests/conftest.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/tests/test_app.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/tests/test_loaders.py +0 -0
- {jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/tests/test_rooms.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: jupyter-server-ydoc
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: jupyter-server extension integrating collaborative shared models.
|
|
5
5
|
Author-email: Jupyter Development Team <jupyter@googlegroups.com>
|
|
6
6
|
License: # Licensing terms
|
|
@@ -62,7 +62,6 @@ License: # Licensing terms
|
|
|
62
62
|
|
|
63
63
|
# Copyright (c) Jupyter Development Team.
|
|
64
64
|
# Distributed under the terms of the Modified BSD License.
|
|
65
|
-
License-File: LICENSE
|
|
66
65
|
Classifier: Framework :: Jupyter
|
|
67
66
|
Classifier: Intended Audience :: Developers
|
|
68
67
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -83,13 +82,14 @@ Requires-Dist: jupyter-ydoc<4.0.0,>=2.1.2
|
|
|
83
82
|
Requires-Dist: pycrdt
|
|
84
83
|
Requires-Dist: pycrdt-websocket<0.16.0,>=0.15.0
|
|
85
84
|
Provides-Extra: test
|
|
85
|
+
Requires-Dist: anyio; extra == 'test'
|
|
86
86
|
Requires-Dist: coverage; extra == 'test'
|
|
87
|
+
Requires-Dist: httpx-ws>=0.5.2; extra == 'test'
|
|
87
88
|
Requires-Dist: importlib-metadata>=4.8.3; (python_version < '3.10') and extra == 'test'
|
|
88
89
|
Requires-Dist: jupyter-server-fileid[test]; extra == 'test'
|
|
89
90
|
Requires-Dist: jupyter-server[test]>=2.4.0; extra == 'test'
|
|
90
91
|
Requires-Dist: pytest-cov; extra == 'test'
|
|
91
92
|
Requires-Dist: pytest>=7.0; extra == 'test'
|
|
92
|
-
Requires-Dist: websockets; extra == 'test'
|
|
93
93
|
Description-Content-Type: text/markdown
|
|
94
94
|
|
|
95
95
|
# jupyter-server-ydoc
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.1"
|
{jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/pytest_plugin.py
RENAMED
|
@@ -9,14 +9,19 @@ from typing import Any
|
|
|
9
9
|
|
|
10
10
|
import nbformat
|
|
11
11
|
import pytest
|
|
12
|
+
from httpx_ws import aconnect_ws
|
|
12
13
|
from jupyter_server_ydoc.loaders import FileLoader
|
|
13
14
|
from jupyter_server_ydoc.rooms import DocumentRoom
|
|
14
15
|
from jupyter_server_ydoc.stores import SQLiteYStore
|
|
15
16
|
from jupyter_ydoc import YNotebook, YUnicode
|
|
16
17
|
from pycrdt_websocket import WebsocketProvider
|
|
17
|
-
from websockets import connect
|
|
18
18
|
|
|
19
|
-
from .test_utils import
|
|
19
|
+
from .test_utils import (
|
|
20
|
+
FakeContentsManager,
|
|
21
|
+
FakeEventLogger,
|
|
22
|
+
FakeFileIDManager,
|
|
23
|
+
Websocket,
|
|
24
|
+
)
|
|
20
25
|
|
|
21
26
|
|
|
22
27
|
@pytest.fixture
|
|
@@ -126,8 +131,8 @@ def rtc_fetch_session(jp_fetch):
|
|
|
126
131
|
@pytest.fixture
|
|
127
132
|
def rtc_connect_awareness_client(jp_http_port, jp_base_url):
|
|
128
133
|
async def _inner(room_id: str) -> Any:
|
|
129
|
-
return
|
|
130
|
-
f"
|
|
134
|
+
return aconnect_ws(
|
|
135
|
+
f"http://127.0.0.1:{jp_http_port}{jp_base_url}api/collaboration/room/{room_id}"
|
|
131
136
|
)
|
|
132
137
|
|
|
133
138
|
return _inner
|
|
@@ -138,8 +143,12 @@ def rtc_connect_doc_client(jp_http_port, jp_base_url, rtc_fetch_session):
|
|
|
138
143
|
async def _inner(format: str, type: str, path: str) -> Any:
|
|
139
144
|
resp = await rtc_fetch_session(format, type, path)
|
|
140
145
|
data = json.loads(resp.body.decode("utf-8"))
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
room_name = f"{data['format']}:{data['type']}:{data['fileId']}"
|
|
147
|
+
return (
|
|
148
|
+
aconnect_ws(
|
|
149
|
+
f"http://127.0.0.1:{jp_http_port}{jp_base_url}api/collaboration/room/{room_name}?sessionId={data['sessionId']}"
|
|
150
|
+
),
|
|
151
|
+
room_name,
|
|
143
152
|
)
|
|
144
153
|
|
|
145
154
|
return _inner
|
|
@@ -162,9 +171,8 @@ def rtc_add_doc_to_store(rtc_connect_doc_client):
|
|
|
162
171
|
|
|
163
172
|
doc.observe(_on_document_change)
|
|
164
173
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
):
|
|
174
|
+
websocket, room_name = await rtc_connect_doc_client(format, type, path)
|
|
175
|
+
async with websocket as ws, WebsocketProvider(doc.ydoc, Websocket(ws, room_name)):
|
|
168
176
|
await event.wait()
|
|
169
177
|
await sleep(0.1)
|
|
170
178
|
|
{jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/test_utils.py
RENAMED
|
@@ -6,6 +6,7 @@ from __future__ import annotations
|
|
|
6
6
|
from datetime import datetime
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
|
+
from anyio import Lock
|
|
9
10
|
from jupyter_server import _tz as tz
|
|
10
11
|
|
|
11
12
|
|
|
@@ -55,3 +56,32 @@ class FakeContentsManager:
|
|
|
55
56
|
class FakeEventLogger:
|
|
56
57
|
def emit(self, schema_id: str, data: dict) -> None:
|
|
57
58
|
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)
|
|
@@ -11,6 +11,7 @@ else:
|
|
|
11
11
|
|
|
12
12
|
import pytest
|
|
13
13
|
from anyio import create_task_group, sleep
|
|
14
|
+
from jupyter_server_ydoc.test_utils import Websocket
|
|
14
15
|
from pycrdt_websocket import WebsocketProvider
|
|
15
16
|
|
|
16
17
|
jupyter_ydocs = {ep.name: ep.load() for ep in entry_points(group="jupyter_ydoc")}
|
|
@@ -32,12 +33,12 @@ async def test_dirty(
|
|
|
32
33
|
await rtc_create_file(file_path)
|
|
33
34
|
jupyter_ydoc = jupyter_ydocs[file_type]()
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
websocket, room_name = await rtc_connect_doc_client(file_format, file_type, file_path)
|
|
37
|
+
async with websocket as ws, WebsocketProvider(jupyter_ydoc.ydoc, Websocket(ws, room_name)):
|
|
38
|
+
for _ in range(2):
|
|
39
|
+
jupyter_ydoc.dirty = True
|
|
40
|
+
await sleep(rtc_document_save_delay * 1.5)
|
|
41
|
+
assert not jupyter_ydoc.dirty
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
async def cleanup(jp_serverapp):
|
|
@@ -59,7 +60,8 @@ async def test_room_concurrent_initialization(
|
|
|
59
60
|
await rtc_create_file(file_path)
|
|
60
61
|
|
|
61
62
|
async def connect(file_format, file_type, file_path):
|
|
62
|
-
|
|
63
|
+
websocket, room_name = await rtc_connect_doc_client(file_format, file_type, file_path)
|
|
64
|
+
async with websocket:
|
|
63
65
|
pass
|
|
64
66
|
|
|
65
67
|
t0 = time()
|
|
@@ -84,7 +86,8 @@ async def test_room_sequential_opening(
|
|
|
84
86
|
|
|
85
87
|
async def connect(file_format, file_type, file_path):
|
|
86
88
|
t0 = time()
|
|
87
|
-
|
|
89
|
+
websocket, room_name = await rtc_connect_doc_client(file_format, file_type, file_path)
|
|
90
|
+
async with websocket:
|
|
88
91
|
pass
|
|
89
92
|
t1 = time()
|
|
90
93
|
return t1 - t0
|
|
@@ -8,6 +8,7 @@ from asyncio import Event, sleep
|
|
|
8
8
|
from typing import Any
|
|
9
9
|
|
|
10
10
|
from jupyter_events.logger import EventLogger
|
|
11
|
+
from jupyter_server_ydoc.test_utils import Websocket
|
|
11
12
|
from jupyter_ydoc import YUnicode
|
|
12
13
|
from pycrdt_websocket import WebsocketProvider
|
|
13
14
|
|
|
@@ -77,9 +78,8 @@ async def test_room_handler_doc_client_should_connect(rtc_create_file, rtc_conne
|
|
|
77
78
|
doc = YUnicode()
|
|
78
79
|
doc.observe(_on_document_change)
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
):
|
|
81
|
+
websocket, room_name = await rtc_connect_doc_client("text", "file", path)
|
|
82
|
+
async with websocket as ws, WebsocketProvider(doc.ydoc, Websocket(ws, room_name)):
|
|
83
83
|
await event.wait()
|
|
84
84
|
await sleep(0.1)
|
|
85
85
|
|
|
@@ -114,9 +114,8 @@ async def test_room_handler_doc_client_should_emit_awareness_event(
|
|
|
114
114
|
listener=my_listener,
|
|
115
115
|
)
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
):
|
|
117
|
+
websocket, room_name = await rtc_connect_doc_client("text", "file", path)
|
|
118
|
+
async with websocket as ws, WebsocketProvider(doc.ydoc, Websocket(ws, room_name)):
|
|
120
119
|
await event.wait()
|
|
121
120
|
await sleep(0.1)
|
|
122
121
|
|
|
@@ -147,9 +146,8 @@ async def test_room_handler_doc_client_should_cleanup_room_file(
|
|
|
147
146
|
doc = YUnicode()
|
|
148
147
|
doc.observe(_on_document_change)
|
|
149
148
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
):
|
|
149
|
+
websocket, room_name = await rtc_connect_doc_client("text", "file", path)
|
|
150
|
+
async with websocket as ws, WebsocketProvider(doc.ydoc, Websocket(ws, room_name)):
|
|
153
151
|
await event.wait()
|
|
154
152
|
await sleep(0.1)
|
|
155
153
|
|
|
@@ -173,18 +171,16 @@ async def test_room_handler_doc_client_should_cleanup_room_file(
|
|
|
173
171
|
path2, _ = await rtc_create_file("test2.txt", "test2")
|
|
174
172
|
|
|
175
173
|
try:
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
):
|
|
174
|
+
websocket, room_name = await rtc_connect_doc_client("text2", "file2", path2)
|
|
175
|
+
async with websocket as ws, WebsocketProvider(doc.ydoc, Websocket(ws, room_name)):
|
|
179
176
|
await event.wait()
|
|
180
177
|
await sleep(0.1)
|
|
181
178
|
except Exception:
|
|
182
179
|
pass
|
|
183
180
|
|
|
184
181
|
try:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
):
|
|
182
|
+
websocket, room_name = await rtc_connect_doc_client("text2", "file2", path2)
|
|
183
|
+
async with websocket as ws, WebsocketProvider(doc.ydoc, Websocket(ws, room_name)):
|
|
188
184
|
await event.wait()
|
|
189
185
|
await sleep(0.1)
|
|
190
186
|
except Exception:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.0.0rc1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter-config/jupyter_server_ydoc.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/events/awareness.yaml
RENAMED
|
File without changes
|
{jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/events/session.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter_server_ydoc-1.0.0rc1 → jupyter_server_ydoc-1.0.1}/jupyter_server_ydoc/websocketserver.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|