wslink 2.2.2__tar.gz → 2.3.1__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {wslink-2.2.2 → wslink-2.3.1}/PKG-INFO +1 -1
- {wslink-2.2.2 → wslink-2.3.1}/setup.cfg +1 -1
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/backends/generic/core.py +1 -1
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/backends/jupyter/core.py +1 -41
- wslink-2.3.1/src/wslink/emitter.py +73 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/protocol.py +15 -3
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/websocket.py +7 -3
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink.egg-info/PKG-INFO +1 -1
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink.egg-info/SOURCES.txt +1 -0
- {wslink-2.2.2 → wslink-2.3.1}/MANIFEST.in +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/README.rst +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/setup.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/LICENSE +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/__init__.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/backends/__init__.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/backends/aiohttp/__init__.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/backends/aiohttp/launcher.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/backends/aiohttp/relay.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/backends/generic/__init__.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/backends/jupyter/__init__.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/backends/tornado/__init__.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/backends/tornado/core.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/chunking.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/launcher.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/publish.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/relay.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/server.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/ssl_context.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink/uri.py +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink.egg-info/dependency_links.txt +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink.egg-info/requires.txt +0 -0
- {wslink-2.2.2 → wslink-2.3.1}/src/wslink.egg-info/top_level.txt +0 -0
@@ -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__()
|
@@ -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)
|
@@ -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,
|
@@ -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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|