Skip to content

Commit 68bac13

Browse files
committed
Make json_clean a no-op for jupyter-client >= 7
1 parent c36de65 commit 68bac13

File tree

4 files changed

+45
-20
lines changed

4 files changed

+45
-20
lines changed

ipykernel/datapub.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,6 @@ def publish_data(data):
6666
DeprecationWarning,
6767
stacklevel=2
6868
)
69-
69+
7070
from ipykernel.zmqshell import ZMQInteractiveShell
7171
ZMQInteractiveShell.instance().data_pub.publish_data(data)

ipykernel/debugger.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,21 @@
77
from tornado.queues import Queue
88
from tornado.locks import Event
99

10+
from IPython.core.getipython import get_ipython
11+
12+
try:
13+
from jupyter_client.jsonutil import json_default
14+
except ImportError:
15+
from jupyter_client.jsonutil import date_default as json_default
16+
1017
from .compiler import (get_file_name, get_tmp_directory, get_tmp_hash_seed)
1118

12-
from IPython.core.getipython import get_ipython
1319

14-
from .jsonutil import json_clean
1520

1621
# Required for backwards compatiblity
1722
ROUTING_ID = getattr(zmq, 'ROUTING_ID', None) or zmq.IDENTITY
1823

24+
1925
class DebugpyMessageQueue:
2026

2127
HEADER = 'Content-Length: '
@@ -58,7 +64,7 @@ def put_tcp_frame(self, frame):
5864
self.header_pos = self.tcp_buffer.find(DebugpyMessageQueue.HEADER)
5965
if self.header_pos == -1:
6066
return
61-
67+
6268
self.log.debug('QUEUE - found header at pos %i', self.header_pos)
6369

6470
#Finds separator
@@ -94,7 +100,7 @@ def put_tcp_frame(self, frame):
94100

95101
async def get_message(self):
96102
return await self.message_queue.get()
97-
103+
98104

99105
class DebugpyClient:
100106

@@ -123,15 +129,20 @@ def _forward_event(self, msg):
123129
def _send_request(self, msg):
124130
if self.routing_id is None:
125131
self.routing_id = self.debugpy_stream.socket.getsockopt(ROUTING_ID)
126-
content = jsonapi.dumps(msg)
132+
content = jsonapi.dumps(
133+
msg,
134+
default=json_default,
135+
ensure_ascii=False,
136+
allow_nan=False,
137+
)
127138
content_length = str(len(content))
128139
buf = (DebugpyMessageQueue.HEADER + content_length + DebugpyMessageQueue.SEPARATOR).encode('ascii')
129140
buf += content
130141
self.log.debug("DEBUGPYCLIENT:")
131142
self.log.debug(self.routing_id)
132143
self.log.debug(buf)
133144
self.debugpy_stream.send_multipart((self.routing_id, buf))
134-
145+
135146
async def _wait_for_response(self):
136147
# Since events are never pushed to the message_queue
137148
# we can safely assume the next message in queue
@@ -141,7 +152,7 @@ async def _wait_for_response(self):
141152
async def _handle_init_sequence(self):
142153
# 1] Waits for initialized event
143154
await self.init_event.wait()
144-
155+
145156
# 2] Sends configurationDone request
146157
configurationDone = {
147158
'type': 'request',
@@ -193,6 +204,7 @@ async def send_dap_request(self, msg):
193204
self.log.debug(rep)
194205
return rep
195206

207+
196208
class Debugger:
197209

198210
# Requests that requires that the debugger has started
@@ -202,7 +214,7 @@ class Debugger:
202214
'variables', 'attach',
203215
'configurationDone'
204216
]
205-
217+
206218
# Requests that can be handled even if the debugger is not running
207219
static_debug_msg_types = [
208220
'debugInfo', 'inspectVariables', 'richInspectVariables'
@@ -215,7 +227,7 @@ def __init__(self, log, debugpy_stream, event_callback, shell_socket, session):
215227
self.session = session
216228
self.is_started = False
217229
self.event_callback = event_callback
218-
230+
219231
self.started_debug_handlers = {}
220232
for msg_type in Debugger.started_debug_msg_types:
221233
self.started_debug_handlers[msg_type] = getattr(self, msg_type)
@@ -264,7 +276,7 @@ def start(self):
264276
}
265277
self.session.send(self.shell_socket, 'execute_request', content,
266278
None, (self.shell_socket.getsockopt(ROUTING_ID)))
267-
279+
268280
ident, msg = self.session.recv(self.shell_socket, mode=0)
269281
self.debugpy_initialized = msg['content']['status'] == 'ok'
270282
self.debugpy_client.connect_tcp_socket()
@@ -424,8 +436,12 @@ async def inspectVariables(self, message):
424436
for k, v in get_ipython().user_ns.items():
425437
if self.accept_variable(k):
426438
try:
427-
val = json_clean(v)
428-
439+
val = jsonapi.dumps(
440+
v,
441+
default=json_default,
442+
ensure_ascii=False,
443+
allow_nan=False,
444+
)
429445
except ValueError:
430446
val = str(v)
431447
var_list.append({
@@ -486,7 +502,7 @@ async def richInspectVariables(self, message):
486502
'data': {},
487503
'metadata': {}
488504
}
489-
505+
490506
for key, value in repr_data.items():
491507
body['data']['key'] = value
492508
if repr_metadata.has_key(key):

ipykernel/inprocess/ipkernel.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,12 @@ def _default_shell_class(self):
152152

153153
@default('stdout')
154154
def _default_stdout(self):
155-
return OutStream(self.session, self.iopub_thread, 'stdout',
155+
return OutStream(self.session, self.iopub_thread, 'stdout',
156156
watchfd=False)
157157

158158
@default('stderr')
159159
def _default_stderr(self):
160-
return OutStream(self.session, self.iopub_thread, 'stderr',
160+
return OutStream(self.session, self.iopub_thread, 'stderr',
161161
watchfd=False)
162162

163163
#-----------------------------------------------------------------------------

ipykernel/jsonutil.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import types
1010
from datetime import datetime
1111
import numbers
12+
from jupyter_client._version import version_info as jupyter_client_version
1213

1314
next_attr_name = '__next__'
1415

@@ -42,6 +43,9 @@
4243
# front of PDF base64-encoded
4344
PDF64 = b'JVBER'
4445

46+
JUPYTER_CLIENT_MAJOR_VERSION = jupyter_client_version[0]
47+
48+
4549
def encode_images(format_dict):
4650
"""b64-encodes images in a displaypub format dict
4751
@@ -68,7 +72,9 @@ def encode_images(format_dict):
6872

6973

7074
def json_clean(obj):
71-
"""Clean an object to ensure it's safe to encode in JSON.
75+
"""Deprecated, this is a no-op for jupyter-client>=7.
76+
77+
Clean an object to ensure it's safe to encode in JSON.
7278
7379
Atomic, immutable objects are returned unmodified. Sets and tuples are
7480
converted to lists, lists are copied and dicts are also copied.
@@ -89,6 +95,9 @@ def json_clean(obj):
8995
it simply sanitizes it so that there will be no encoding errors later.
9096
9197
"""
98+
if JUPYTER_CLIENT_MAJOR_VERSION >= 7:
99+
return obj
100+
92101
# types that are 'atomic' and ok in json as-is.
93102
atomic_ok = (str, type(None))
94103

@@ -110,10 +119,10 @@ def json_clean(obj):
110119
if math.isnan(obj) or math.isinf(obj):
111120
return repr(obj)
112121
return float(obj)
113-
122+
114123
if isinstance(obj, atomic_ok):
115124
return obj
116-
125+
117126
if isinstance(obj, bytes):
118127
# unanmbiguous binary data is base64-encoded
119128
# (this probably should have happened upstream)
@@ -142,6 +151,6 @@ def json_clean(obj):
142151
return out
143152
if isinstance(obj, datetime):
144153
return obj.strftime(ISO8601)
145-
154+
146155
# we don't understand it, it's probably an unserializable object
147156
raise ValueError("Can't clean for JSON: %r" % obj)

0 commit comments

Comments
 (0)