wslink 2.2.2__py3-none-any.whl → 2.3.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- wslink/backends/generic/core.py +1 -1
- wslink/backends/jupyter/core.py +1 -41
- wslink/emitter.py +73 -0
- wslink/protocol.py +15 -3
- wslink/websocket.py +7 -3
- {wslink-2.2.2.dist-info → wslink-2.3.1.dist-info}/METADATA +1 -1
- {wslink-2.2.2.dist-info → wslink-2.3.1.dist-info}/RECORD +9 -8
- {wslink-2.2.2.dist-info → wslink-2.3.1.dist-info}/WHEEL +0 -0
- {wslink-2.2.2.dist-info → wslink-2.3.1.dist-info}/top_level.txt +0 -0
wslink/backends/generic/core.py
CHANGED
wslink/backends/jupyter/core.py
CHANGED
@@ -1,49 +1,9 @@
|
|
1
|
-
import asyncio
|
2
1
|
from functools import partial
|
2
|
+
from wslink.emitter import EventEmitter
|
3
3
|
from wslink.backends.generic.core import GenericServer
|
4
4
|
from IPython.core.getipython import get_ipython
|
5
5
|
|
6
6
|
|
7
|
-
class EventEmitter:
|
8
|
-
def __init__(self):
|
9
|
-
self._listeners = {}
|
10
|
-
|
11
|
-
def clear(self):
|
12
|
-
self._listeners = {}
|
13
|
-
|
14
|
-
def emit(self, event, *args, **kwargs):
|
15
|
-
listeners = self._listeners.get(event)
|
16
|
-
if listeners is None:
|
17
|
-
return
|
18
|
-
|
19
|
-
loop = asyncio.get_running_loop()
|
20
|
-
coroutine_run = (
|
21
|
-
loop.create_task if (loop and loop.is_running()) else asyncio.run
|
22
|
-
)
|
23
|
-
|
24
|
-
for listener in listeners:
|
25
|
-
if asyncio.iscoroutinefunction(listener):
|
26
|
-
coroutine_run(listener(*args, **kwargs))
|
27
|
-
else:
|
28
|
-
listener(*args, **kwargs)
|
29
|
-
|
30
|
-
def add_event_listener(self, event, listener):
|
31
|
-
listeners = self._listeners.get(event)
|
32
|
-
if listeners is None:
|
33
|
-
listeners = set()
|
34
|
-
self._listeners[event] = listeners
|
35
|
-
|
36
|
-
listeners.add(listener)
|
37
|
-
|
38
|
-
def remove_event_listener(self, event, listener):
|
39
|
-
listeners = self._listeners.get(event)
|
40
|
-
if listeners is None:
|
41
|
-
return
|
42
|
-
|
43
|
-
if listener in listeners:
|
44
|
-
listeners.remove(listener)
|
45
|
-
|
46
|
-
|
47
7
|
class WsJupyterComm(EventEmitter):
|
48
8
|
def __init__(self, kernel=None):
|
49
9
|
super().__init__()
|
wslink/emitter.py
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
import asyncio
|
2
|
+
import functools
|
3
|
+
|
4
|
+
|
5
|
+
class EventEmitter:
|
6
|
+
def __init__(self):
|
7
|
+
self._listeners = {}
|
8
|
+
|
9
|
+
def clear(self):
|
10
|
+
self._listeners = {}
|
11
|
+
|
12
|
+
def __call__(self, event, *args, **kwargs):
|
13
|
+
self.emit(event, *args, **kwargs)
|
14
|
+
|
15
|
+
def __getattr__(self, name):
|
16
|
+
return functools.partial(self.emit, name)
|
17
|
+
|
18
|
+
def exception(self, *args, **kwargs):
|
19
|
+
self.emit("exception", *args, **kwargs)
|
20
|
+
|
21
|
+
def error(self, *args, **kwargs):
|
22
|
+
self.emit("error", *args, **kwargs)
|
23
|
+
|
24
|
+
def critical(self, *args, **kwargs):
|
25
|
+
self.emit("critical", *args, **kwargs)
|
26
|
+
|
27
|
+
def info(self, *args, **kwargs):
|
28
|
+
self.emit("info", *args, **kwargs)
|
29
|
+
|
30
|
+
def debug(self, *args, **kwargs):
|
31
|
+
self.emit("debug", *args, **kwargs)
|
32
|
+
|
33
|
+
def emit(self, event, *args, **kwargs):
|
34
|
+
listeners = self._listeners.get(event)
|
35
|
+
if listeners is None:
|
36
|
+
return
|
37
|
+
|
38
|
+
loop = asyncio.get_running_loop()
|
39
|
+
coroutine_run = (
|
40
|
+
loop.create_task if (loop and loop.is_running()) else asyncio.run
|
41
|
+
)
|
42
|
+
|
43
|
+
for listener in listeners:
|
44
|
+
if asyncio.iscoroutinefunction(listener):
|
45
|
+
coroutine_run(listener(*args, **kwargs))
|
46
|
+
else:
|
47
|
+
listener(*args, **kwargs)
|
48
|
+
|
49
|
+
def add_event_listener(self, event, listener):
|
50
|
+
listeners = self._listeners.get(event)
|
51
|
+
if listeners is None:
|
52
|
+
listeners = set()
|
53
|
+
self._listeners[event] = listeners
|
54
|
+
|
55
|
+
listeners.add(listener)
|
56
|
+
|
57
|
+
def remove_event_listener(self, event, listener):
|
58
|
+
listeners = self._listeners.get(event)
|
59
|
+
if listeners is None:
|
60
|
+
return
|
61
|
+
|
62
|
+
if listener in listeners:
|
63
|
+
listeners.remove(listener)
|
64
|
+
|
65
|
+
def has(self, event):
|
66
|
+
return self.listeners_count(event) > 0
|
67
|
+
|
68
|
+
def listeners_count(self, event):
|
69
|
+
listeners = self._listeners.get(event)
|
70
|
+
if listeners is None:
|
71
|
+
return 0
|
72
|
+
|
73
|
+
return len(listeners)
|
wslink/protocol.py
CHANGED
@@ -9,6 +9,7 @@ import traceback
|
|
9
9
|
from wslink import schedule_coroutine
|
10
10
|
from wslink.publish import PublishManager
|
11
11
|
from wslink.chunking import generate_chunks, UnChunker
|
12
|
+
from wslink.websocket import ServerProtocol
|
12
13
|
|
13
14
|
# from http://www.jsonrpc.org/specification, section 5.1
|
14
15
|
METHOD_NOT_FOUND = -32601
|
@@ -141,7 +142,7 @@ class AbstractWebApp:
|
|
141
142
|
|
142
143
|
|
143
144
|
class WslinkHandler(object):
|
144
|
-
def __init__(self, protocol
|
145
|
+
def __init__(self, protocol: ServerProtocol, web_app=None):
|
145
146
|
self.serverProtocol = protocol
|
146
147
|
self.web_app = web_app
|
147
148
|
self.functionMap = {}
|
@@ -153,6 +154,7 @@ class WslinkHandler(object):
|
|
153
154
|
self.pub_manager = PublishManager()
|
154
155
|
self.unchunkers = {}
|
155
156
|
self.network_monitor = protocol.network_monitor
|
157
|
+
self.log_emitter = protocol.log_emitter
|
156
158
|
|
157
159
|
# Build the rpc method dictionary, assuming we were given a serverprotocol
|
158
160
|
if self.getServerProtocol():
|
@@ -253,7 +255,9 @@ class WslinkHandler(object):
|
|
253
255
|
|
254
256
|
async def onMessage(self, is_binary, msg, client_id):
|
255
257
|
if not is_binary:
|
256
|
-
|
258
|
+
error_message = "wslink is not expecting text message:\n> %s"
|
259
|
+
logger.critical(error_message, msg.data)
|
260
|
+
self.log_emitter.critical(error_message % msg.data)
|
257
261
|
return
|
258
262
|
|
259
263
|
full_message = self.unchunkers[client_id].process_chunk(msg.data)
|
@@ -262,7 +266,13 @@ class WslinkHandler(object):
|
|
262
266
|
await self.onCompleteMessage(full_message, client_id)
|
263
267
|
|
264
268
|
async def onCompleteMessage(self, rpc, client_id):
|
265
|
-
|
269
|
+
debug_message = "wslink incoming msg %s"
|
270
|
+
stripped_payload = self.payloadWithSecretStripped(rpc)
|
271
|
+
logger.debug(debug_message, stripped_payload)
|
272
|
+
|
273
|
+
if self.log_emitter.has("debug"):
|
274
|
+
self.log_emitter.debug(debug_message % stripped_payload)
|
275
|
+
|
266
276
|
if "id" not in rpc:
|
267
277
|
return
|
268
278
|
|
@@ -295,6 +305,7 @@ class WslinkHandler(object):
|
|
295
305
|
|
296
306
|
# No matching method found
|
297
307
|
if not methodName in self.functionMap:
|
308
|
+
self.log_emitter.error(f"Method not found: {methodName}")
|
298
309
|
with self.network_monitor:
|
299
310
|
await self.sendWrappedError(
|
300
311
|
rpcid,
|
@@ -328,6 +339,7 @@ class WslinkHandler(object):
|
|
328
339
|
logger.error("Exception raised")
|
329
340
|
logger.error(repr(e_inst))
|
330
341
|
logger.error(captured_trace)
|
342
|
+
self.log_emitter.exception(e_inst)
|
331
343
|
with self.network_monitor:
|
332
344
|
await self.sendWrappedError(
|
333
345
|
rpcid,
|
wslink/websocket.py
CHANGED
@@ -7,8 +7,9 @@ ServerProtocol to hook all the needed LinkProtocols together.
|
|
7
7
|
import logging
|
8
8
|
import asyncio
|
9
9
|
|
10
|
-
from
|
11
|
-
from
|
10
|
+
from wslink import register as exportRpc
|
11
|
+
from wslink import schedule_callback
|
12
|
+
from wslink.emitter import EventEmitter
|
12
13
|
|
13
14
|
logger = logging.getLogger(__name__)
|
14
15
|
|
@@ -125,6 +126,7 @@ class ServerProtocol(object):
|
|
125
126
|
|
126
127
|
def __init__(self):
|
127
128
|
self.network_monitor = NetworkMonitor()
|
129
|
+
self.log_emitter = EventEmitter()
|
128
130
|
self.linkProtocols = []
|
129
131
|
self.secret = None
|
130
132
|
self.initialize()
|
@@ -169,7 +171,9 @@ class ServerProtocol(object):
|
|
169
171
|
try:
|
170
172
|
self.linkProtocols.remove(protocol)
|
171
173
|
except ValueError as e:
|
172
|
-
|
174
|
+
error_message = "Link protocol missing from registered list."
|
175
|
+
logger.error(error_message)
|
176
|
+
self.log_emitter("error", error_message)
|
173
177
|
|
174
178
|
def getLinkProtocols(self):
|
175
179
|
return self.linkProtocols
|
@@ -1,25 +1,26 @@
|
|
1
1
|
wslink/LICENSE,sha256=I44UH7kDVqxDLnnlOWw_hFL2Fz7RjQ_4vPzZv9NYgTU,1483
|
2
2
|
wslink/__init__.py,sha256=qdLGVhzpEXBoraTnLr5S-8bX9oK8pZCQWe8rZRlwAco,2946
|
3
3
|
wslink/chunking.py,sha256=1DJlGG6fjknGFrqPOtqUUc5tCrijldP7Kdx56d5e3Wg,7337
|
4
|
+
wslink/emitter.py,sha256=vgpA9pmqMLLPm7UDVLfbDY2mgvm21pngsRmBhYT0GcU,1971
|
4
5
|
wslink/launcher.py,sha256=8VMs3juObLkyGYQFNLjMoo4qFpKIcxWz0kS-af-DKO4,21170
|
5
|
-
wslink/protocol.py,sha256=
|
6
|
+
wslink/protocol.py,sha256=IUvdYzXaaKP4qllJps6uQ8zvbipbH6MVwU6o6f60Kuc,17265
|
6
7
|
wslink/publish.py,sha256=Xyv9piZT4HxO5l_SA7zeReH8t6tisVHUgU57Hjzgkcg,1595
|
7
8
|
wslink/relay.py,sha256=E8Lzu2Ay7KbOheN1-ArAZawo8lLqdDgJXOZSBuMknYs,86
|
8
9
|
wslink/server.py,sha256=yvhCjpzPOfhbZrpDvW9i4H_uSyuQAe3ZOP-BRBmgHQA,9326
|
9
10
|
wslink/ssl_context.py,sha256=hNOJJCdrStws1Qf6vPvY4vTk9Bf8J5d90W3fS0cRv8o,2290
|
10
11
|
wslink/uri.py,sha256=woCQ4yChUqTMg9IT6YYDtUYeKmCg7OUCEgeBGA-19DY,384
|
11
|
-
wslink/websocket.py,sha256=
|
12
|
+
wslink/websocket.py,sha256=wuwqJwgAWmbvtj-FvRezhzXqdUqdoq7nDpWLmetxNTs,6191
|
12
13
|
wslink/backends/__init__.py,sha256=cyJGjm-YyBSyOEX81owyTbJ3YnrA6dB7--B4LnsEtHI,1214
|
13
14
|
wslink/backends/aiohttp/__init__.py,sha256=SSK5a_lxuEZGyW_mMMipgvAhJQQLhxAImR3jRokFchM,9301
|
14
15
|
wslink/backends/aiohttp/launcher.py,sha256=gHNMvtgNHEwBN_QBRDSCrTp2B4K1PsfV81rKaHi7Cxo,8897
|
15
16
|
wslink/backends/aiohttp/relay.py,sha256=oZAzIQTpsQaObWXaa-_VtoTOUQALC_QLDd9UvWspYaU,13311
|
16
17
|
wslink/backends/generic/__init__.py,sha256=Qu65gWsd2xCSsxybnDtEDI5vMjHN-F5jgPZOyNIxnGs,112
|
17
|
-
wslink/backends/generic/core.py,sha256
|
18
|
+
wslink/backends/generic/core.py,sha256=-tlNgXdvEr8BrwosxBWlUJVk5yiGMLfbK3EWs5VEKNM,4358
|
18
19
|
wslink/backends/jupyter/__init__.py,sha256=Qu65gWsd2xCSsxybnDtEDI5vMjHN-F5jgPZOyNIxnGs,112
|
19
|
-
wslink/backends/jupyter/core.py,sha256=
|
20
|
+
wslink/backends/jupyter/core.py,sha256=F8R3uH4m6RHCrHHRiA5UAgDOLdyGbpuCSAgCZxANREk,2794
|
20
21
|
wslink/backends/tornado/__init__.py,sha256=Qu65gWsd2xCSsxybnDtEDI5vMjHN-F5jgPZOyNIxnGs,112
|
21
22
|
wslink/backends/tornado/core.py,sha256=tPMkkhWuO_ovkisVim0zcegwZKEAG4IRUdd_O_0a_R0,2157
|
22
|
-
wslink-2.
|
23
|
-
wslink-2.
|
24
|
-
wslink-2.
|
25
|
-
wslink-2.
|
23
|
+
wslink-2.3.1.dist-info/METADATA,sha256=vwfCnfjB7VrNadykxK9VYtNT2p4hiPQ_r13R5oMyMOE,3120
|
24
|
+
wslink-2.3.1.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
25
|
+
wslink-2.3.1.dist-info/top_level.txt,sha256=N0d8eqvhwhfW1p1yPTmvxlbzhjz7ZyhBfysNvaFqpQY,7
|
26
|
+
wslink-2.3.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|