class KernelRunner(QObject): """ Used to control the iPython kernel in a non-blocking manner so the UI remains responsive. """ kernel_started = pyqtSignal(QtKernelManager, QtKernelClient) kernel_finished = pyqtSignal() # Used to build context with user defined envars when running the REPL. default_envars = os.environ.copy() def __init__(self, cwd, envars): """ Initialise the kernel runner with a target current working directory. """ super().__init__() self.cwd = cwd self.envars = dict(envars) def start_kernel(self): """ Create the expected context, start the kernel, obtain a client and emit a signal when both are started. """ logger.info(sys.path) os.chdir(self.cwd) # Ensure the kernel runs with the expected CWD. # Add user defined envars to os.environ so they can be picked up by # the child process running the kernel. logger.info("Starting iPython kernel with user defined envars: " "{}".format(self.envars)) for k, v in self.envars.items(): os.environ[k] = v # Ensure the expected paths are in PYTHONPATH of the subprocess so the # kernel and Mu-installed third party applications can be found. if "PYTHONPATH" not in os.environ: paths = sys.path + [MODULE_DIR] os.environ["PYTHONPATH"] = os.pathsep.join(paths) if MODULE_DIR not in os.environ["PYTHONPATH"]: # This is needed on Windows to ensure user installed third party # packages are available in the REPL. new_path = os.pathsep.join([os.environ["PYTHONPATH"], MODULE_DIR]) os.environ["PYTHONPATH"] = new_path logger.info("REPL PYTHONPATH: {}".format(os.environ["PYTHONPATH"])) self.repl_kernel_manager = QtKernelManager() self.repl_kernel_manager.start_kernel() self.repl_kernel_client = self.repl_kernel_manager.client() self.kernel_started.emit(self.repl_kernel_manager, self.repl_kernel_client) def stop_kernel(self): """ Clean up the context, stop the client connections to the kernel, affect an immediate shutdown of the kernel and emit a "finished" signal. """ os.environ.clear() for k, v in self.default_envars.items(): os.environ[k] = v self.repl_kernel_client.stop_channels() self.repl_kernel_manager.shutdown_kernel(now=True) self.kernel_finished.emit()
class KernelRunner(QObject): """ Used to control the iPython kernel in a non-blocking manner so the UI remains responsive. """ kernel_started = pyqtSignal(QtKernelManager, QtKernelClient) kernel_finished = pyqtSignal() def __init__(self, cwd): """ Initialise the kernel runner with a target current working directory. """ super().__init__() self.cwd = cwd def start_kernel(self): """ Start the kernel, obtain a client and emit a signal when both are started. """ os.chdir(self.cwd) # Ensure the kernel runs with the expected CWD. self.repl_kernel_manager = QtKernelManager() self.repl_kernel_manager.start_kernel() self.repl_kernel_client = self.repl_kernel_manager.client() self.kernel_started.emit(self.repl_kernel_manager, self.repl_kernel_client) def stop_kernel(self): """ Stop the client connections to the kernel, affect an immediate shutdown of the kernel and emit a "finished" signal. """ self.repl_kernel_client.stop_channels() self.repl_kernel_manager.shutdown_kernel(now=True) self.kernel_finished.emit()
class KernelRunner(QObject): """ Used to control the iPython kernel in a non-blocking manner so the UI remains responsive. """ kernel_started = pyqtSignal(QtKernelManager, QtKernelClient) kernel_finished = pyqtSignal() # Used to build context with user defined envars when running the REPL. default_envars = os.environ.copy() def __init__(self, cwd, envars): """ Initialise the kernel runner with a target current working directory. """ super().__init__() self.cwd = cwd self.envars = dict(envars) def start_kernel(self): """ Create the expected context, start the kernel, obtain a client and emit a signal when both are started. """ logger.info(sys.path) os.chdir(self.cwd) # Ensure the kernel runs with the expected CWD. # Add user defined envars to os.environ so they can be picked up by # the child process running the kernel. logger.info('Starting iPython kernel with user defined envars: ' '{}'.format(self.envars)) for k, v in self.envars.items(): os.environ[k] = v if sys.platform == 'darwin': parent_dir = os.path.dirname(__file__) if '.app/Contents/Resources/app/mu' in parent_dir: # Mu is running as a macOS app bundle. Ensure the expected # paths are in PYTHONPATH of the subprocess so the kernel can # be found. os.environ['PYTHONPATH'] = ':'.join(sys.path) self.repl_kernel_manager = QtKernelManager() self.repl_kernel_manager.start_kernel() self.repl_kernel_client = self.repl_kernel_manager.client() self.kernel_started.emit(self.repl_kernel_manager, self.repl_kernel_client) def stop_kernel(self): """ Clean up the context, stop the client connections to the kernel, affect an immediate shutdown of the kernel and emit a "finished" signal. """ os.environ.clear() for k, v in self.default_envars.items(): os.environ[k] = v self.repl_kernel_client.stop_channels() self.repl_kernel_manager.shutdown_kernel(now=True) self.kernel_finished.emit()
def run(self): self.mutex.lock() kernel_manager = QtKernelManager(kernel_name="""python3""") kernel_manager.start_kernel() kernel_client = kernel_manager.client() kernel_client.start_channels() # notify to update ui self.initialized.emit(kernel_manager, kernel_client) # wait for exit self.wait_condition.wait(self.mutex) self.mutex.unlock() # stop channels and kernel kernel_client.stop_channels() kernel_manager.shutdown_kernel()
def run(self): self.mutex.lock() kernel_manager = QtKernelManager(kernel_name='python3') kernel_manager.start_kernel() kernel_client = kernel_manager.client() kernel_client.start_channels() # notify to update ui self.initialized.emit(kernel_manager, kernel_client) # wait for exit self.wait_condition.wait(self.mutex) self.mutex.unlock() # stop channels and kernel kernel_client.stop_channels() kernel_manager.shutdown_kernel( now=True) # add now=True; Fix exit error; 200924 liugang
class KernelRunner(QObject): """ Used to control the iPython kernel in a non-blocking manner so the UI remains responsive. """ kernel_started = pyqtSignal(QtKernelManager, QtKernelClient) kernel_finished = pyqtSignal() def start_kernel(self): self.repl_kernel_manager = QtKernelManager() self.repl_kernel_manager.start_kernel() self.repl_kernel_client = self.repl_kernel_manager.client() self.kernel_started.emit(self.repl_kernel_manager, self.repl_kernel_client) def stop_kernel(self): self.repl_kernel_client.stop_channels() self.repl_kernel_manager.shutdown_kernel(now=True) self.kernel_finished.emit()
class KernelRunner(QObject): """ Used to control the iPython kernel in a non-blocking manner so the UI remains responsive. """ kernel_started = pyqtSignal(QtKernelManager, QtKernelClient) kernel_finished = pyqtSignal() def __init__(self, cwd): """ Initialise the kernel runner with a target current working directory. """ super().__init__() self.cwd = cwd def start_kernel(self): """ Start the kernel, obtain a client and emit a signal when both are started. """ logger.info(sys.path) os.chdir(self.cwd) # Ensure the kernel runs with the expected CWD. self.repl_kernel_manager = QtKernelManager() self.repl_kernel_manager.start_kernel() self.repl_kernel_client = self.repl_kernel_manager.client() self.kernel_started.emit(self.repl_kernel_manager, self.repl_kernel_client) def stop_kernel(self): """ Stop the client connections to the kernel, affect an immediate shutdown of the kernel and emit a "finished" signal. """ self.repl_kernel_client.stop_channels() self.repl_kernel_manager.shutdown_kernel(now=True) self.kernel_finished.emit()
class Tests(unittest.TestCase): def setUp(self): """Open a kernel.""" self.kernel_manager = QtKernelManager() self.kernel_manager.start_kernel() self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels(shell=True, iopub=True) self.blocking_client = self.kernel_client.blocking_client() self.blocking_client.start_channels(shell=True, iopub=True) self.comm_manager = self.kernel_client.comm_manager # Check if client is working self.blocking_client.execute('print(0)') try: self._get_next_msg() self._get_next_msg() except TimeoutError: # Maybe it works now? self.blocking_client.execute('print(0)') self._get_next_msg() self._get_next_msg() def tearDown(self): """Close the kernel.""" if self.kernel_manager: self.kernel_manager.shutdown_kernel(now=True) if self.kernel_client: self.kernel_client.shutdown() def _get_next_msg(self, timeout=10): # Get status messages timeout_time = time.time() + timeout msg_type = 'status' while msg_type == 'status': if timeout_time < time.time(): raise TimeoutError try: msg = self.blocking_client.get_iopub_msg(timeout=3) msg_type = msg['header']['msg_type'] except Empty: pass return msg def test_kernel_to_frontend(self): """Communicate from the kernel to the frontend.""" comm_manager = self.comm_manager blocking_client = self.blocking_client class DummyCommHandler(): def __init__(self): comm_manager.register_target('test_api', self.comm_open) self.last_msg = None def comm_open(self, comm, msg): comm.on_msg(self.comm_message) comm.on_close(self.comm_message) self.last_msg = msg['content']['data'] self.comm = comm def comm_message(self, msg): self.last_msg = msg['content']['data'] handler = DummyCommHandler() blocking_client.execute( "from ipykernel.comm import Comm\n" "comm = Comm(target_name='test_api', data='open')\n" "comm.send('message')\n" "comm.close('close')\n" "del comm\n" "print('Done')\n" ) # Get input msg = self._get_next_msg() assert msg['header']['msg_type'] == 'execute_input' # Open comm msg = self._get_next_msg() assert msg['header']['msg_type'] == 'comm_open' comm_manager._dispatch(msg) assert handler.last_msg == 'open' assert handler.comm.comm_id == msg['content']['comm_id'] # Get message msg = self._get_next_msg() assert msg['header']['msg_type'] == 'comm_msg' comm_manager._dispatch(msg) assert handler.last_msg == 'message' assert handler.comm.comm_id == msg['content']['comm_id'] # Get close msg = self._get_next_msg() assert msg['header']['msg_type'] == 'comm_close' comm_manager._dispatch(msg) assert handler.last_msg == 'close' assert handler.comm.comm_id == msg['content']['comm_id'] # Get close msg = self._get_next_msg() assert msg['header']['msg_type'] == 'stream' def test_frontend_to_kernel(self): """Communicate from the frontend to the kernel.""" comm_manager = self.comm_manager blocking_client = self.blocking_client blocking_client.execute( "class DummyCommHandler():\n" " def __init__(self):\n" " get_ipython().kernel.comm_manager.register_target(\n" " 'test_api', self.comm_open)\n" " def comm_open(self, comm, msg):\n" " comm.on_msg(self.comm_message)\n" " comm.on_close(self.comm_message)\n" " print(msg['content']['data'])\n" " def comm_message(self, msg):\n" " print(msg['content']['data'])\n" "dummy = DummyCommHandler()\n" ) # Get input msg = self._get_next_msg() assert msg['header']['msg_type'] == 'execute_input' # Open comm comm = comm_manager.new_comm('test_api', data='open') msg = self._get_next_msg() assert msg['header']['msg_type'] == 'stream' assert msg['content']['text'] == 'open\n' # Get message comm.send('message') msg = self._get_next_msg() assert msg['header']['msg_type'] == 'stream' assert msg['content']['text'] == 'message\n' # Get close comm.close('close') msg = self._get_next_msg() # Received message has a header and parent header. The parent header has # the info about the close message type in Python 3 assert msg['parent_header']['msg_type'] == 'comm_close' assert msg['msg_type'] == 'stream' assert msg['content']['text'] == 'close\n'
class QIPythonWidget(RichJupyterWidget): """ Convenience class for a live IPython console widget. We can replace the standard banner using the customBanner argument""" kernel_status_signal = QtCore.pyqtSignal(object) def __init__(self, customBanner=None, *args, **kwargs): if customBanner != None: self.banner = customBanner super().__init__() self.font_size = 6 self.kernel_manager = QtKernelManager() self.kernel_manager.start_kernel() self.kernel_manager.kernel.gui = 'qt' self.kernel_client = self._kernel_manager.client() self.kernel_client.start_channels() self.kernel_client.iopub_channel.message_received.connect( self.update_kernel_status) def stop(): self.kernel_client.stop_channels() self.kernel_manager.shutdown_kernel() self.exit_requested.connect(stop) self.init_logging_level() def init_logging_level(self): self.logging_level = {} for i in range(101): if logging.getLevelName(i)[:5] != 'Level': self.logging_level[logging.getLevelName(i)] = i def _handle_stream(self, msg): """ Handle stdout, stderr, and stdin. """ self.log.debug("stream: %s", msg.get('content', '')) for level in self.logging_level.keys(): if level in msg['content']['text']: self.kernel_status_signal.emit(self.logging_level[level]) if self.include_output(msg): self.flush_clearoutput() self.append_stream(msg['content']['text']) def update_kernel_status(self, msg): try: if msg['header']['msg_type'] == 'status': self.kernel_status = msg['content']['execution_state'] self.kernel_status_signal.emit(self.kernel_status) except Exception as e: print(e) def shutdown_kernel(self): self.kernel_client.stop_channels() self.kernel_manager.shutdown_kernel() def restart_kernel(self): self.kernel_client.stop_channels() self.kernel_manager.shutdown_kernel() self.kernel_manager = QtKernelManager() self.kernel_manager.start_kernel() self.kernel_manager.kernel.gui = 'qt' self.kernel_client = self._kernel_manager.client() self.kernel_client.start_channels() self.kernel_client.iopub_channel.message_received.connect( self.update_kernel_status) def pushVariables(self, variableDict): """ Given a dictionary containing name / value pairs, push those variables to the IPython console widget """ self.kernel_manager.kernel.shell.push(variableDict) def clearTerminal(self): """ Clears the terminal """ self._control.clear() def printText(self, text): """ Prints some plain text to the console """ self._append_plain_text(text) def executeCommand(self, command): self.printText(command + '\n') """ Execute a command in the frame of the console widget """ self._execute(command, False)