Skip to content

Commit

Permalink
Remove json_clean
Browse files Browse the repository at this point in the history
  • Loading branch information
martinRenou committed Jul 5, 2021
1 parent 38ad84f commit 71f6cf9
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 183 deletions.
5 changes: 2 additions & 3 deletions ipykernel/comm/comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from traitlets.config import LoggingConfigurable
from ipykernel.kernelbase import Kernel

from ipykernel.jsonutil import json_clean
from traitlets import Instance, Unicode, Bytes, Bool, Dict, Any, default


Expand Down Expand Up @@ -62,10 +61,10 @@ def _publish_msg(self, msg_type, data=None, metadata=None, buffers=None, **keys)
"""Helper for sending a comm message on IOPub"""
data = {} if data is None else data
metadata = {} if metadata is None else metadata
content = json_clean(dict(data=data, comm_id=self.comm_id, **keys))
content = dict(data=data, comm_id=self.comm_id, **keys)
self.kernel.session.send(self.kernel.iopub_socket, msg_type,
content,
metadata=json_clean(metadata),
metadata=metadata,
parent=self.kernel.get_parent("shell"),
ident=self.topic,
buffers=buffers,
Expand Down
5 changes: 2 additions & 3 deletions ipykernel/datapub.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

from traitlets.config import Configurable
from traitlets import Instance, Dict, CBytes, Any
from ipykernel.jsonutil import json_clean
try:
# available since ipyparallel 5.0.0
from ipyparallel.serialize import serialize_object
Expand Down Expand Up @@ -46,7 +45,7 @@ def publish_data(self, data):
buffer_threshold=session.buffer_threshold,
item_threshold=session.item_threshold,
)
content = json_clean(dict(keys=list(data.keys())))
content = dict(keys=list(data.keys()))
session.send(self.pub_socket, 'data_message', content=content,
parent=self.parent_header,
buffers=buffers,
Expand All @@ -66,6 +65,6 @@ def publish_data(data):
DeprecationWarning,
stacklevel=2
)

from ipykernel.zmqshell import ZMQInteractiveShell
ZMQInteractiveShell.instance().data_pub.publish_data(data)
42 changes: 27 additions & 15 deletions ipykernel/debugger.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import logging
import os
import re
import json

import zmq
from zmq.utils import jsonapi

from tornado.queues import Queue
from tornado.locks import Event

from IPython.core.getipython import get_ipython

from jupyter_client.jsonutil import date_default

from .compiler import (get_file_name, get_tmp_directory, get_tmp_hash_seed)

from IPython.core.getipython import get_ipython
import debugpy

from .jsonutil import json_clean


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


class DebugpyMessageQueue:

HEADER = 'Content-Length: '
Expand Down Expand Up @@ -60,7 +63,7 @@ def put_tcp_frame(self, frame):
self.header_pos = self.tcp_buffer.find(DebugpyMessageQueue.HEADER)
if self.header_pos == -1:
return

self.log.debug('QUEUE - found header at pos %i', self.header_pos)

#Finds separator
Expand Down Expand Up @@ -96,7 +99,7 @@ def put_tcp_frame(self, frame):

async def get_message(self):
return await self.message_queue.get()


class DebugpyClient:

Expand Down Expand Up @@ -125,15 +128,20 @@ def _forward_event(self, msg):
def _send_request(self, msg):
if self.routing_id is None:
self.routing_id = self.debugpy_stream.socket.getsockopt(ROUTING_ID)
content = jsonapi.dumps(msg)
content = jsonapi.dumps(
msg,
default=date_default,
ensure_ascii=False,
allow_nan=False,
)
content_length = str(len(content))
buf = (DebugpyMessageQueue.HEADER + content_length + DebugpyMessageQueue.SEPARATOR).encode('ascii')
buf += content
self.log.debug("DEBUGPYCLIENT:")
self.log.debug(self.routing_id)
self.log.debug(buf)
self.debugpy_stream.send_multipart((self.routing_id, buf))

async def _wait_for_response(self):
# Since events are never pushed to the message_queue
# we can safely assume the next message in queue
Expand All @@ -143,7 +151,7 @@ async def _wait_for_response(self):
async def _handle_init_sequence(self):
# 1] Waits for initialized event
await self.init_event.wait()

# 2] Sends configurationDone request
configurationDone = {
'type': 'request',
Expand Down Expand Up @@ -195,6 +203,7 @@ async def send_dap_request(self, msg):
self.log.debug(rep)
return rep


class Debugger:

# Requests that requires that the debugger has started
Expand All @@ -204,7 +213,7 @@ class Debugger:
'variables', 'attach',
'configurationDone'
]

# Requests that can be handled even if the debugger is not running
static_debug_msg_types = [
'debugInfo', 'inspectVariables'
Expand All @@ -217,7 +226,7 @@ def __init__(self, log, debugpy_stream, event_callback, shell_socket, session):
self.session = session
self.is_started = False
self.event_callback = event_callback

self.started_debug_handlers = {}
for msg_type in Debugger.started_debug_msg_types:
self.started_debug_handlers[msg_type] = getattr(self, msg_type)
Expand Down Expand Up @@ -266,7 +275,7 @@ def start(self):
}
self.session.send(self.shell_socket, 'execute_request', content,
None, (self.shell_socket.getsockopt(ROUTING_ID)))

ident, msg = self.session.recv(self.shell_socket, mode=0)
self.debugpy_initialized = msg['content']['status'] == 'ok'
self.debugpy_client.connect_tcp_socket()
Expand Down Expand Up @@ -420,8 +429,12 @@ async def inspectVariables(self, message):
for k, v in get_ipython().user_ns.items():
if self.accept_variable(k):
try:
val = json_clean(v)

val = jsonapi.dumps(
v,
default=date_default,
ensure_ascii=False,
allow_nan=False,
)
except ValueError:
val = str(v)
var_list.append({
Expand Down Expand Up @@ -478,4 +491,3 @@ async def process_request(self, message):
self.log.info('The debugger has stopped')

return reply

3 changes: 1 addition & 2 deletions ipykernel/displayhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import sys

from IPython.core.displayhook import DisplayHook
from ipykernel.jsonutil import encode_images, json_clean
from traitlets import Instance, Dict, Any
from jupyter_client.session import extract_header, Session

Expand Down Expand Up @@ -68,7 +67,7 @@ def write_output_prompt(self):
self.msg['content']['execution_count'] = self.prompt_count

def write_format_data(self, format_dict, md_dict=None):
self.msg['content']['data'] = json_clean(encode_images(format_dict))
self.msg['content']['data'] = format_dict
self.msg['content']['metadata'] = md_dict

def finish_displayhook(self):
Expand Down
3 changes: 1 addition & 2 deletions ipykernel/inprocess/ipkernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import sys

from IPython.core.interactiveshell import InteractiveShellABC
from ipykernel.jsonutil import json_clean
from traitlets import Any, Enum, Instance, List, Type, default
from ipykernel.ipkernel import IPythonKernel
from ipykernel.zmqshell import ZMQInteractiveShell
Expand Down Expand Up @@ -98,7 +97,7 @@ def _input_request(self, prompt, ident, parent, password=False):
sys.stdout.flush()

# Send the input request.
content = json_clean(dict(prompt=prompt, password=password))
content = dict(prompt=prompt, password=password)
msg = self.session.msg('input_request', content, parent)
for frontend in self.frontends:
if frontend.session.session == parent['header']['session']:
Expand Down
48 changes: 4 additions & 44 deletions ipykernel/jsonutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ def encode_images(format_dict):


def json_clean(obj):
"""Clean an object to ensure it's safe to encode in JSON.
"""Deprecated, this is a no-op now.
Clean an object to ensure it's safe to encode in JSON.
Atomic, immutable objects are returned unmodified. Sets and tuples are
converted to lists, lists are copied and dicts are also copied.
Expand All @@ -91,46 +93,4 @@ def json_clean(obj):
it simply sanitizes it so that there will be no encoding errors later.
"""
# types that are 'atomic' and ok in json as-is.
atomic_ok = (bool, str, type(None))

# containers that we need to convert into lists
container_to_list = (list, tuple, set, types.GeneratorType)

# Since bools are a subtype of Integrals, which are a subtype of Reals,
# we have to check them in that order.

if isinstance(obj, atomic_ok):
return obj

if isinstance(obj, numbers.Integral):
# cast int to int, in case subclasses override __str__ (e.g. boost enum, #4598)
return int(obj)

if isinstance(obj, numbers.Real):
# cast out-of-range floats to their reprs
if math.isnan(obj) or math.isinf(obj):
return repr(obj)
return float(obj)

if isinstance(obj, bytes):
# unanmbiguous binary data is base64-encoded
# (this probably should have happened upstream)
return b2a_base64(obj).decode('ascii')

if isinstance(obj, container_to_list) or (
hasattr(obj, '__iter__') and hasattr(obj, next_attr_name)):
return [json_clean(x) for x in obj]

if isinstance(obj, dict):
# If all OK, proceed by making the new dict that will be json-safe
out = {}
for k, v in obj.items():
out[str(k)] = json_clean(v)
return out

if isinstance(obj, datetime):
return obj.strftime(ISO8601)

# we don't understand it, it's probably an unserializable object
raise ValueError("Can't clean for JSON: %r" % obj)
return obj
9 changes: 1 addition & 8 deletions ipykernel/kernelbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

from traitlets.config.configurable import SingletonConfigurable
from IPython.core.error import StdinNotImplementedError
from ipykernel.jsonutil import json_clean
from traitlets import (
Any, Instance, Float, Dict, List, Set, Integer, Unicode, Bool,
observe, default
Expand Down Expand Up @@ -656,7 +655,6 @@ async def execute_request(self, stream, ident, parent):
time.sleep(self._execute_sleep)

# Send the reply.
reply_content = json_clean(reply_content)
metadata = self.finish_metadata(parent, metadata, reply_content)

reply_msg = self.session.send(stream, 'execute_reply',
Expand All @@ -683,7 +681,6 @@ async def complete_request(self, stream, ident, parent):
if inspect.isawaitable(matches):
matches = await matches

matches = json_clean(matches)
self.session.send(stream, "complete_reply", matches, parent, ident)

def do_complete(self, code, cursor_pos):
Expand All @@ -706,7 +703,6 @@ async def inspect_request(self, stream, ident, parent):
reply_content = await reply_content

# Before we send this object over, we scrub it for JSON usage
reply_content = json_clean(reply_content)
msg = self.session.send(stream, 'inspect_reply',
reply_content, parent, ident)
self.log.debug("%s", msg)
Expand All @@ -723,7 +719,6 @@ async def history_request(self, stream, ident, parent):
if inspect.isawaitable(reply_content):
reply_content = await reply_content

reply_content = json_clean(reply_content)
msg = self.session.send(stream, 'history_reply',
reply_content, parent, ident)
self.log.debug("%s", msg)
Expand Down Expand Up @@ -813,7 +808,6 @@ async def is_complete_request(self, stream, ident, parent):
reply_content = self.do_is_complete(code)
if inspect.isawaitable(reply_content):
reply_content = await reply_content
reply_content = json_clean(reply_content)
reply_msg = self.session.send(stream, 'is_complete_reply',
reply_content, parent, ident)
self.log.debug("%s", reply_msg)
Expand All @@ -829,7 +823,6 @@ async def debug_request(self, stream, ident, parent):
reply_content = self.do_debug_request(content)
if inspect.isawaitable(reply_content):
reply_content = await reply_content
reply_content = json_clean(reply_content)
reply_msg = self.session.send(stream, 'debug_reply', reply_content,
parent, ident)
self.log.debug("%s", reply_msg)
Expand Down Expand Up @@ -1001,7 +994,7 @@ def _input_request(self, prompt, ident, parent, password=False):
raise

# Send the input request.
content = json_clean(dict(prompt=prompt, password=password))
content = dict(prompt=prompt, password=password)
self.session.send(self.stdin_socket, 'input_request', content, parent,
ident=ident)

Expand Down
Loading

0 comments on commit 71f6cf9

Please sign in to comment.