Format: text/x-python
⬇ Download File (4.0 KB)
   1  """Connection file-related utilities for the kernel
   2  """
   3  # Copyright (c) IPython Development Team.
   4  # Distributed under the terms of the Modified BSD License.
   5  from __future__ import annotations
   6  
   7  import json
   8  import sys
   9  from subprocess import PIPE, Popen
  10  from typing import TYPE_CHECKING, Any
  11  
  12  import jupyter_client
  13  from jupyter_client import write_connection_file
  14  
  15  if TYPE_CHECKING:
  16      from ipykernel.kernelapp import IPKernelApp
  17  
  18  
  19  def get_connection_file(app: IPKernelApp | None = None) -> str:
  20      """Return the path to the connection file of an app
  21  
  22      Parameters
  23      ----------
  24      app : IPKernelApp instance [optional]
  25          If unspecified, the currently running app will be used
  26      """
  27      from traitlets.utils import filefind
  28  
  29      if app is None:
  30          from ipykernel.kernelapp import IPKernelApp
  31  
  32          if not IPKernelApp.initialized():
  33              msg = "app not specified, and not in a running Kernel"
  34              raise RuntimeError(msg)
  35  
  36          app = IPKernelApp.instance()
  37      return filefind(app.connection_file, [".", app.connection_dir])
  38  
  39  
  40  def _find_connection_file(connection_file):
  41      """Return the absolute path for a connection file
  42  
  43      - If nothing specified, return current Kernel's connection file
  44      - Otherwise, call jupyter_client.find_connection_file
  45      """
  46      if connection_file is None:
  47          # get connection file from current kernel
  48          return get_connection_file()
  49      return jupyter_client.find_connection_file(connection_file)
  50  
  51  
  52  def get_connection_info(
  53      connection_file: str | None = None, unpack: bool = False
  54  ) -> str | dict[str, Any]:
  55      """Return the connection information for the current Kernel.
  56  
  57      Parameters
  58      ----------
  59      connection_file : str [optional]
  60          The connection file to be used. Can be given by absolute path, or
  61          IPython will search in the security directory.
  62          If run from IPython,
  63  
  64          If unspecified, the connection file for the currently running
  65          IPython Kernel will be used, which is only allowed from inside a kernel.
  66  
  67      unpack : bool [default: False]
  68          if True, return the unpacked dict, otherwise just the string contents
  69          of the file.
  70  
  71      Returns
  72      -------
  73      The connection dictionary of the current kernel, as string or dict,
  74      depending on `unpack`.
  75      """
  76      cf = _find_connection_file(connection_file)
  77  
  78      with open(cf) as f:
  79          info_str = f.read()
  80  
  81      if unpack:
  82          info = json.loads(info_str)
  83          # ensure key is bytes:
  84          info["key"] = info.get("key", "").encode()
  85          return info  # type:ignore[no-any-return]
  86  
  87      return info_str
  88  
  89  
  90  def connect_qtconsole(
  91      connection_file: str | None = None, argv: list[str] | None = None
  92  ) -> Popen[Any]:
  93      """Connect a qtconsole to the current kernel.
  94  
  95      This is useful for connecting a second qtconsole to a kernel, or to a
  96      local notebook.
  97  
  98      Parameters
  99      ----------
 100      connection_file : str [optional]
 101          The connection file to be used. Can be given by absolute path, or
 102          IPython will search in the security directory.
 103          If run from IPython,
 104  
 105          If unspecified, the connection file for the currently running
 106          IPython Kernel will be used, which is only allowed from inside a kernel.
 107  
 108      argv : list [optional]
 109          Any extra args to be passed to the console.
 110  
 111      Returns
 112      -------
 113      :class:`subprocess.Popen` instance running the qtconsole frontend
 114      """
 115      argv = [] if argv is None else argv
 116  
 117      cf = _find_connection_file(connection_file)
 118  
 119      cmd = ";".join(["from qtconsole import qtconsoleapp", "qtconsoleapp.main()"])
 120  
 121      kwargs: dict[str, Any] = {}
 122      # Launch the Qt console in a separate session & process group, so
 123      # interrupting the kernel doesn't kill it.
 124      kwargs["start_new_session"] = True
 125  
 126      return Popen(
 127          [sys.executable, "-c", cmd, "--existing", cf, *argv],
 128          stdout=PIPE,
 129          stderr=PIPE,
 130          close_fds=(sys.platform != "win32"),
 131          **kwargs,
 132      )
 133  
 134  
 135  __all__ = [
 136      "write_connection_file",
 137      "get_connection_file",
 138      "get_connection_info",
 139      "connect_qtconsole",
 140  ]
 141