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)) self.qsend(msg_type, content, json_clean(metadata), buffers)
def write_format_data(self, format_dict, md_dict=None): # print("WRITING FORMAT DATA:", format_dict) if 0 in format_dict: # have multiple outputs new_format_dict = {} for i in format_dict: new_format_dict[i] = json_clean(encode_images(format_dict[i])) self.msg['content']['data'] = new_format_dict else: self.msg['content']['data'] = json_clean( encode_images(format_dict)) self.msg['content']['metadata'] = md_dict
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)) self.kernel.session.send(self.kernel.iopub_socket, msg_type, content, metadata=json_clean(metadata), parent=self.kernel._parent_header, ident=self.topic, buffers=buffers, )
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)) self.kernel.session.send(self.kernel.iopub_socket, msg_type, content, metadata=json_clean(metadata), parent=self.kernel._parent_header, ident=self.topic, buffers=buffers, )
def proxy_iopub_channel(self): while True: try: msg = client.get_iopub_msg(block=False) if(not msg["content"].get("metadata", {}).get("echo", False)): log.msg("[iopub] {}".format(pformat(json_clean(msg)))) yield self.publish(u"io.timbr.kernel.{}.iopub".format(_key), json_clean(msg)) except ValueError as ve: # This happens when an "invalid signature" is encountered which for us probably # means that the message did not originate from this kernel log.msg("ValueError") except Empty: yield sleep(0.1)
def complete_request(self, stream, ident, parent): """Colab-specific complete_request handler. Overrides the default to allow providing additional metadata in the response. Args: stream: Shell stream to send the reply on. ident: Identity of the requester. parent: Parent request message. """ content = parent['content'] code = content['code'] cursor_pos = content['cursor_pos'] matches = self.do_complete(code, cursor_pos) if parent.get('metadata', {}).get('colab_options', {}).get('include_colab_metadata'): matches['metadata'] = { 'colab_types_experimental': _shell_customizations.compute_completion_metadata( self.shell, matches['matches']), } matches = json_clean(matches) self.session.send(stream, 'complete_reply', matches, parent, ident)
def complete_request(self, stream, ident, parent): """Colab-specific complete_request handler. Overrides the default to allow providing additional metadata in the response. Args: stream: Shell stream to send the reply on. ident: Identity of the requester. parent: Parent request message. """ content = parent['content'] code = content['code'] cursor_pos = content['cursor_pos'] matches = self.do_complete(code, cursor_pos) if parent.get('metadata', {}).get('colab_options', {}).get('include_colab_metadata'): matches['metadata'] = { # Filter to only what is needed since there can be a lot of # completions to send. 'colab_types_experimental': [{ 'type_name': self.shell.object_inspect(match)['type_name'] } for match in matches['matches']], } matches = json_clean(matches) self.session.send(stream, 'complete_reply', matches, parent, ident)
def _showtraceback(self, etype, evalue, stb): # try to preserve ordering of tracebacks and print statements sys.stdout.flush() sys.stderr.flush() exc_content = { "traceback": stb, "ename": str(etype.__name__), "evalue": str(evalue), } dh = self.displayhook # Send exception info over pub socket for other clients than the caller # to pick up topic = None if dh.topic: topic = dh.topic.replace(b"execute_result", b"error") dh.session.send( dh.pub_socket, "error", json_clean(exc_content), dh.parent_header, ident=topic, ) # FIXME - Once we rely on Python 3, the traceback is stored on the # exception object, so we shouldn't need to store it here. self._last_traceback = stb
def _showtraceback(self, etype, evalue, stb): # try to preserve ordering of tracebacks and print statements sys.stdout.flush() sys.stderr.flush() exc_content = { u'traceback': stb, u'ename': unicode_type(etype.__name__), u'evalue': py3compat.safe_unicode(evalue), } dh = self.displayhook # Send exception info over pub socket for other clients than the caller # to pick up topic = None if dh.topic: topic = dh.topic.replace(b'execute_result', b'error') exc_msg = dh.session.send(dh.pub_socket, u'error', json_clean(exc_content), dh.parent_header, ident=topic) # FIXME - Once we rely on Python 3, the traceback is stored on the # exception object, so we shouldn't need to store it here. self._last_traceback = stb
def workflow_request(self, stream, ident, parent): try: content = parent['content'] notebook = content['notebook'] except: self.log.error("Got bad msg: ") self.log.error("%s", parent) return metadata = self.init_metadata(parent) reply_content = yield gen.maybe_future( self.do_workflow(notebook, ident, parent)) sys.stdout.flush() sys.stderr.flush() if self._execute_sleep: 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', reply_content, parent, metadata=metadata, ident=ident) self.log.debug("%s", reply_msg)
def _complete_execute_request(self, request: RequestInfo, reply_content): # Flush output before sending the reply. sys.stdout.flush() sys.stderr.flush() # FIXME: on rare occasions, the flush doesn't seem to make it to the # clients... This seems to mitigate the problem, but we definitely need # to better understand what's going on. if self._execute_sleep: time.sleep(self._execute_sleep) # Send the reply. reply_content = json_clean(reply_content) request.response_meta = self.finish_metadata(request.parent, request.response_meta, reply_content) reply_msg = self.session.send(request.stream, u'execute_reply', reply_content, request.parent, metadata=request.response_meta, ident=request.ident) if not request.silent and reply_msg['content'][ 'status'] == u'error' and request.stop_on_error: self._abort_queues()
def _showtraceback(self, etype, evalue, stb): # try to preserve ordering of tracebacks and print statements sys.stdout.flush() sys.stderr.flush() exc_content = { u'traceback' : stb, u'ename' : unicode_type(etype.__name__), u'evalue' : py3compat.safe_unicode(evalue), } dh = self.displayhook # Send exception info over pub socket for other clients than the caller # to pick up topic = None if dh.topic: topic = dh.topic.replace(b'execute_result', b'error') exc_msg = dh.session.send(dh.pub_socket, u'error', json_clean(exc_content), dh.parent_header, ident=topic) # FIXME - Hack: store exception info in shell object. Right now, the # caller is reading this info after the fact, we need to fix this logic # to remove this hack. Even uglier, we need to store the error status # here, because in the main loop, the logic that sets it is being # skipped because runlines swallows the exceptions. exc_content[u'status'] = u'error' self._reply_content = exc_content # /FIXME return exc_content
def publish(self, data, metadata=None, source=None): self._flush_streams() if metadata is None: metadata = {} self._validate_data(data, metadata) content = {} content['data'] = encode_images(data) content['metadata'] = metadata # Use 2-stage process to send a message, # in order to put it through the transform # hooks before potentially sending. msg = self.session.msg( u'display_data', json_clean(content), parent=self.parent_header ) # Each transform either returns a new # message or None. If None is returned, # the message has been 'used' and we return. for hook in self.thread_local.hooks: msg = hook(msg) if msg is None: return self.session.send( self.pub_socket, msg, ident=self.topic )
def _publish_msg(self, msg_type, data=None, metadata=None, buffers=None, **keys): """Helper for sending a comm message on IOPub""" if threading.current_thread().name != 'MainThread' and IOLoop.initialized(): # make sure we never send on a zmq socket outside the main IOLoop thread IOLoop.instance().add_callback(lambda : self._publish_msg(msg_type, data, metadata, buffers, **keys)) return 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)) self.kernel.session.send(self.kernel.iopub_socket, msg_type, content, metadata=json_clean(metadata), parent=self.kernel._parent_header, ident=self.topic, buffers=buffers, )
def proxy_iopub_channel(self): while True: try: msg = client.get_iopub_msg(block=False) if (not msg["content"].get("metadata", {}).get( "echo", False)): log.msg("[iopub] {}".format(pformat(json_clean(msg)))) yield self.publish( u"io.timbr.kernel.{}.iopub".format(_key), json_clean(msg)) except ValueError as ve: # This happens when an "invalid signature" is encountered which for us probably # means that the message did not originate from this kernel log.msg("ValueError") except Empty: yield sleep(0.1)
def publish(self, data, metadata=None, source=None): self._flush_streams() if metadata is None: metadata = {} self._validate_data(data, metadata) content = {} content['data'] = encode_images(data) content['metadata'] = metadata # Use 2-stage process to send a message, # in order to put it through the transform # hooks before potentially sending. msg = self.session.msg(u'display_data', json_clean(content), parent=self.parent_header) # Each transform either returns a new # message or None. If None is returned, # the message has been 'used' and we return. for hook in self._hooks: msg = hook(msg) if msg is None: return self.session.send(self.pub_socket, msg, ident=self.topic)
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)) msg = self.kernel_client.session.msg(msg_type, content=content, parent=self.parent_header, metadata=metadata) self.kernel_client.shell_channel.send(msg)
def _get_port_data(self, event, obj, **extra_data): """ Get data for a single port on a node. """ data = extra_data if obj is None: return data # Add object ID if available. obj_id = self.object_tracker.get_id(obj) if obj_id is not None: data['id'] = obj_id # Add value if the object is primitive. if self.is_primitive(obj): data['value'] = json_clean(obj) elif isinstance(obj, types.ModuleType): data['value'] = obj.__name__ # Add type information if type is not builtin. obj_type = obj.__class__ module_name = get_class_module_name(obj_type) if module_name != 'builtins' or isinstance(obj, types.ModuleType): data['module'] = module_name data['qual_name'] = get_class_qual_name(obj_type) # Add object annotation, if it exists. note = self.annotator.notate_object(obj) if note: data['annotation'] = self._annotation_key(note) return data
def send_execute_reply(self, stream, ident, parent, md, reply_content): """ Send a reply to execute_request """ # Flush output before sending the reply. self._flush_execute_output() # Cleanup the reply and prepare metadata reply_content = json_clean(reply_content) md = md.copy() md['status'] = reply_content['status'] if reply_content['status'] == 'error' and \ reply_content['ename'] == 'UnmetDependency': md['dependencies_met'] = False # Publish the reply reply_msg = self.session.send(stream, u'execute_reply', reply_content, parent, metadata=md, ident=ident) # Handle the reply message content = parent[u'content'] stop_on_error = content.get('stop_on_error', True) silent = content[u'silent'] self.log.debug("%s", reply_msg) if not silent and reply_msg['content']['status'] == u'error' and stop_on_error: self._abort_queues() self._publish_idle() if hasattr(stream, 'flush'): stream.flush()
async def execute_request(self, stream, ident, parent): """handle an execute_request""" try: content = parent['content'] code = content['code'] silent = content['silent'] store_history = content.get('store_history', not silent) user_expressions = content.get('user_expressions', {}) allow_stdin = content.get('allow_stdin', False) except: self.log.error("Got bad msg: ") self.log.error("%s", parent) return stop_on_error = content.get('stop_on_error', True) metadata = self.init_metadata(parent) # Re-broadcast our input for the benefit of listening clients, and # start computing output if not silent: self.execution_count += 1 self._publish_execute_input(code, parent, self.execution_count) reply_content = self.do_execute( code, silent, store_history, user_expressions, allow_stdin, ) if inspect.isawaitable(reply_content): reply_content = await reply_content # Flush output before sending the reply. sys.stdout.flush() sys.stderr.flush() # FIXME: on rare occasions, the flush doesn't seem to make it to the # clients... This seems to mitigate the problem, but we definitely need # to better understand what's going on. if self._execute_sleep: 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', reply_content, parent, metadata=metadata, ident=ident) self.log.debug("%s", reply_msg) if not silent and reply_msg['content'][ 'status'] == 'error' and stop_on_error: await self._abort_queues()
def _send_error(self, exc_content): topic = (self.displayhook.topic.replace(b'execute_result', b'err') if self.displayhook.topic else None) self.displayhook.session.send(self.displayhook.pub_socket, u'error', jsonutil.json_clean(exc_content), self.displayhook.parent_header, ident=topic)
def debug_request(self, stream, ident, parent): content = parent['content'] reply_content = yield gen.maybe_future(self.do_debug_request(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)
def complete_request(self, stream, ident, parent): content = parent['content'] code = content['code'] cursor_pos = content['cursor_pos'] matches = yield gen.maybe_future(self.do_complete(code, cursor_pos)) matches = json_clean(matches) self.session.send(stream, "complete_reply", matches, parent, ident)
def history_request(self, stream, ident, parent): content = parent['content'] reply_content = self.do_history(**content) reply_content = json_clean(reply_content) msg = self.session.send(stream, 'history_reply', reply_content, parent, ident) self.log.debug("%s", msg)
def publish(self, data, metadata=None, source=None): if not isinstance(data, dict): raise TypeError('data must be a dict, got: %r' % data) if metadata is not None and not isinstance(metadata, dict): raise TypeError('metadata must be a dict, got: %r' % data) content = {} content['data'] = encode_images(data) content['metadata'] = metadata print(json.dumps(json_clean(content)))
def is_complete_request(self, stream, ident, parent): content = parent['content'] code = content['code'] reply_content = self.do_is_complete(code) 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)
def complete_request(self, stream, ident, parent): content = parent['content'] code = content['code'] cursor_pos = content['cursor_pos'] matches = self.do_complete(code, cursor_pos) matches = json_clean(matches) completion_msg = self.session.send(stream, 'complete_reply', matches, parent, ident)
def history_request(self, stream, ident, parent): content = parent["content"] reply_content = yield gen.maybe_future(self.do_history(**content)) reply_content = json_clean(reply_content) msg = self.session.send(stream, "history_reply", reply_content, parent, ident) self.log.debug("%s", msg)
def is_complete_request(self, stream, ident, parent): content = parent["content"] code = content["code"] reply_content = yield gen.maybe_future(self.do_is_complete(code)) 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)
def f(stream, ident, parent, *args, **kwargs): kernel._publish_status(u'busy', parent) md = kernel.init_metadata(parent) content = parent['content'] # Set the parent message of the display hook and out streams. kernel.shell.set_parent(parent) reply_content = {} try: reply_content[u'result'] = handler(stream, ident, parent, *args, **kwargs) except: status = u'error' etype, evalue, tb = sys.exc_info() import traceback tb_list = traceback.format_exception(etype, evalue, tb) reply_content.update(kernel.shell._showtraceback(etype, evalue, tb_list)) else: status = u'ok' reply_content[u'status'] = status sys.stdout.flush() sys.stderr.flush() # this should be refactored probably to use existing IPython code if reply_content['status'] == 'ok': reply_content[u'user_expressions'] = \ kernel.shell.user_expressions(content.get(u'user_expressions', {})) else: # If there was an error, don't even try to compute # expressions reply_content[u'user_expressions'] = {} # Payloads should be retrieved regardless of outcome, so we can both # recover partial output (that could have been generated early in a # block, before an error) and clear the payload system always. reply_content[u'payload'] = kernel.shell.payload_manager.read_payload() # Be agressive about clearing the payload because we don't want # it to sit in memory until the next execute_request comes in. kernel.shell.payload_manager.clear_payload() # Flush output before sending the reply. sys.stdout.flush() sys.stderr.flush() # FIXME: on rare occasions, the flush doesn't seem to make it to the # clients... This seems to mitigate the problem, but we definitely need # to better understand what's going on. if kernel._execute_sleep: time.sleep(kernel._execute_sleep) reply_content = json_clean(reply_content) md['status'] = reply_content['status'] if (reply_content['status'] == 'error' and reply_content['ename'] == 'UnmetDependency'): md['dependencies_met'] = False md = kernel.finish_metadata(parent, md, reply_content) reply_msg = kernel.session.send(stream, key + u'_reply', reply_content, parent, metadata=md, ident=ident) kernel.log.debug("%s", reply_msg) kernel._publish_status(u'idle', parent)
async def debug_request(self, stream, ident, parent): content = parent["content"] 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)
def complete_request(self, stream, ident, parent): content = parent['content'] code = content['code'] cursor_pos = content['cursor_pos'] matches = yield gen.maybe_future(self.do_complete(code, cursor_pos)) matches = json_clean(matches) completion_msg = self.session.send(stream, 'complete_reply', matches, parent, ident)
def publish( self, data, metadata=None, source=None, transient=None, update=False, ): """Publish a display-data message Parameters ---------- data: dict A mime-bundle dict, keyed by mime-type. metadata: dict, optional Metadata associated with the data. transient: dict, optional, keyword-only Transient data that may only be relevant during a live display, such as display_id. Transient data should not be persisted to documents. update: bool, optional, keyword-only If True, send an update_display_data message instead of display_data. """ self._flush_streams() if metadata is None: metadata = {} if transient is None: transient = {} self._validate_data(data, metadata) content = {} content['data'] = encode_images(data) content['metadata'] = metadata content['transient'] = transient msg_type = 'update_display_data' if update else 'display_data' # Use 2-stage process to send a message, # in order to put it through the transform # hooks before potentially sending. msg = self.session.msg(msg_type, json_clean(content), parent=self.parent_header) # Each transform either returns a new # message or None. If None is returned, # the message has been 'used' and we return. for hook in self._hooks: msg = hook(msg) if msg is None: return self.session.send( self.pub_socket, msg, ident=self.topic, )
def is_primitive(self, obj): """ Is the object considered primitive? Only primitive objects will be captured as "value" data for object slots and function inputs and outputs. (This does not preclude getting "id" data if object is also weak-referenceable.) Almost always, scalar types (bool, int, float, string, etc.) should be considered primitive. The default implementation allows any object which is JSON-able (essentially, the scalar types plus the built-in container types if their contents are JSON-able). Note: any objects stored as "value" data will be deep-copied. """ try: json_clean(obj) except ValueError: return False return True
async def is_complete_request(self, stream, ident, parent): content = parent["content"] code = content["code"] 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)
def inspect_request(self, stream, ident, parent): content = parent['content'] reply_content = self.do_inspect(content['code'], content['cursor_pos'], content.get('detail_level', 0)) # 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)
def complete_request(self, stream, ident, parent): content = parent['content'] code = content['code'] cursor_pos = content['cursor_pos'] matches = self.do_complete(code, cursor_pos) matches = json_clean(matches) completion_msg = self.session.send(stream, 'complete_reply', matches, parent, ident) self.log.debug("%s", completion_msg)
def execute_request(self, stream, ident, parent): """handle an execute_request""" try: content = parent[u'content'] code = py3compat.cast_unicode_py2(content[u'code']) silent = content[u'silent'] store_history = content.get(u'store_history', not silent) user_expressions = content.get('user_expressions', {}) allow_stdin = content.get('allow_stdin', False) except: self.log.error("Got bad msg: ") self.log.error("%s", parent) return stop_on_error = content.get('stop_on_error', True) md = self._make_metadata(parent['metadata']) # Re-broadcast our input for the benefit of listening clients, and # start computing output if not silent: self.execution_count += 1 self._publish_execute_input(code, parent, self.execution_count) reply_content = self.do_execute(code, silent, store_history, user_expressions, allow_stdin) # Flush output before sending the reply. sys.stdout.flush() sys.stderr.flush() # FIXME: on rare occasions, the flush doesn't seem to make it to the # clients... This seems to mitigate the problem, but we definitely need # to better understand what's going on. if self._execute_sleep: time.sleep(self._execute_sleep) # Send the reply. reply_content = json_clean(reply_content) md['status'] = reply_content['status'] if reply_content['status'] == 'error' and \ reply_content['ename'] == 'UnmetDependency': md['dependencies_met'] = False reply_msg = self.session.send(stream, u'execute_reply', reply_content, parent, metadata=md, ident=ident) self.log.debug("%s", reply_msg) if not silent and reply_msg['content']['status'] == u'error' and stop_on_error: self._abort_queues()
def publish(self, data, metadata=None, source=None): self._flush_streams() if metadata is None: metadata = {} self._validate_data(data, metadata) content = {} content['data'] = encode_images(data) content['metadata'] = metadata self.session.send( self.pub_socket, u'display_data', json_clean(content), parent=self.parent_header, ident=self.topic, )
def matplotlib_post_run(data_list): png_data = None figure = plt.gcf() # Always try to get the current figure. # This is not efficient, but we can support any libraries # that use matplotlib. png_data = print_figure(figure, fmt='png') figure.clear() if png_data is not None: width, height = _pngxy(png_data) data = encode_images({'image/png':png_data}) metadata = {'image/png':dict(width=width, height=height)} data_list.append(json_clean(dict(data=data, metadata=metadata)))
def publish(self, data, metadata=None, source=None, transient=None, update=False, ): """Publish a display-data message Parameters ---------- data: dict A mime-bundle dict, keyed by mime-type. metadata: dict, optional Metadata associated with the data. transient: dict, optional, keyword-only Transient data that may only be relevant during a live display, such as display_id. Transient data should not be persisted to documents. update: bool, optional, keyword-only If True, send an update_display_data message instead of display_data. """ self._flush_streams() if metadata is None: metadata = {} if transient is None: transient = {} self._validate_data(data, metadata) content = {} content['data'] = encode_images(data) content['metadata'] = metadata content['transient'] = transient msg_type = 'update_display_data' if update else 'display_data' # Use 2-stage process to send a message, # in order to put it through the transform # hooks before potentially sending. msg = self.session.msg( msg_type, json_clean(content), parent=self.parent_header ) # Each transform either returns a new # message or None. If None is returned, # the message has been 'used' and we return. for hook in self._hooks: msg = hook(msg) if msg is None: return self.session.send( self.pub_socket, msg, ident=self.topic, )
def execute_request(self, stream, ident, parent): """handle an execute_request - overridden for ipyparallel metadata Once ipykernel has init/finish_metadata, this should be removed. """ try: content = parent[u'content'] code = cast_unicode_py2(content[u'code']) silent = content[u'silent'] store_history = content.get(u'store_history', not silent) user_expressions = content.get('user_expressions', {}) allow_stdin = content.get('allow_stdin', False) except: self.log.error("Got bad msg: ") self.log.error("%s", parent) return stop_on_error = content.get('stop_on_error', True) md = self.init_metadata(parent) # Re-broadcast our input for the benefit of listening clients, and # start computing output if not silent: self.execution_count += 1 self._publish_execute_input(code, parent, self.execution_count) reply_content = self.do_execute(code, silent, store_history, user_expressions, allow_stdin) # finish building metadata md = self.finish_metadata(parent, md, reply_content) # Flush output before sending the reply. sys.stdout.flush() sys.stderr.flush() # Send the reply. reply_content = json_clean(reply_content) reply_msg = self.session.send(stream, u'execute_reply', reply_content, parent, metadata=md, ident=ident) self.log.debug("%s", reply_msg) if not silent and reply_msg['content']['status'] == u'error' and stop_on_error: self._abort_queues()
def send_execute_reply(self, stream, ident, parent, metadata, reply_content): """ Send a reply to execute_request """ # This function is mostly copy-pasted from the last part of # ipykernel's execute_reply method. # It is extracted to allow overriding in subclasses. # Splash kernel overrides it for async replies: instead # of returning result immediately it only calls the original # implementation when async reply is received. content = parent[u'content'] stop_on_error = content.get('stop_on_error', True) silent = content[u'silent'] # ============ BEGIN COPY-PASTE ============ # Flush output before sending the reply. sys.stdout.flush() sys.stderr.flush() # FIXME: on rare occasions, the flush doesn't seem to make it to the # clients... This seems to mitigate the problem, but we definitely need # to better understand what's going on. if self._execute_sleep: 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, u'execute_reply', reply_content, parent, metadata=metadata, ident=ident) self.log.debug("%s", reply_msg) if not silent and reply_msg['content']['status'] == u'error' and stop_on_error: self._abort_queues() # ============== END COPY-PASTE ============== # fix idle signal handling for async replies self._publish_idle() if hasattr(stream, 'flush'): stream.flush()
def publish_data(self, data): """publish a data_message on the IOPub channel Parameters ---------- data : dict The data to be published. Think of it as a namespace. """ session = self.session buffers = serialize_object(data, buffer_threshold=session.buffer_threshold, item_threshold=session.item_threshold, ) content = json_clean(dict(keys=list(data.keys()))) session.send(self.pub_socket, 'data_message', content=content, parent=self.parent_header, buffers=buffers, ident=self.topic, )
def _input_request(self, prompt, ident, parent, password=False): # Flush output before making the request. self.raw_input_str = None sys.stderr.flush() sys.stdout.flush() # Send the input request. content = json_clean(dict(prompt=prompt, password=password)) msg = self.session.msg(u'input_request', content, parent) for frontend in self.frontends: if frontend.session.session == parent['header']['session']: frontend.stdin_channel.call_handlers(msg) break else: logging.error('No frontend found for raw_input request') return str() # Await a response. while self.raw_input_str is None: frontend.stdin_channel.process_events() return self.raw_input_str
def _input_request(self, prompt, ident, parent, password=False): # Flush output before making the request. sys.stderr.flush() sys.stdout.flush() # flush the stdin socket, to purge stale replies while True: try: self.stdin_socket.recv_multipart(zmq.NOBLOCK) except zmq.ZMQError as e: if e.errno == zmq.EAGAIN: break else: raise # Send the input request. content = json_clean(dict(prompt=prompt, password=password)) self.session.send(self.stdin_socket, u'input_request', content, parent, ident=ident) # Await a response. while True: try: ident, reply = self.session.recv(self.stdin_socket, 0) except Exception: self.log.warn("Invalid Message:", exc_info=True) except KeyboardInterrupt: # re-raise KeyboardInterrupt, to truncate traceback raise KeyboardInterrupt else: break try: value = py3compat.unicode_to_str(reply['content']['value']) except: self.log.error("Bad input_reply: %s", parent) value = '' if value == '\x04': # EOF raise EOFError return value
def _showtraceback(self, etype, evalue, stb): # try to preserve ordering of tracebacks and print statements sys.stdout.flush() sys.stderr.flush() exc_content = { u'traceback' : stb, u'ename' : unicode_type(etype.__name__), u'evalue' : py3compat.safe_unicode(evalue), } dh = self.displayhook # Send exception info over pub socket for other clients than the caller # to pick up topic = None if dh.topic: topic = dh.topic.replace(b'execute_result', b'error') exc_msg = dh.session.send(dh.pub_socket, u'error', json_clean(exc_content), dh.parent_header, ident=topic) # FIXME - Once we rely on Python 3, the traceback is stored on the # exception object, so we shouldn't need to store it here. self._last_traceback = stb
def write_format_data(self, format_dict, md_dict=None): self.msg['content']['data'] = json_clean(encode_images(format_dict)) self.msg['content']['metadata'] = md_dict