diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 759a13cc8..0b4e2b015 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,7 +76,7 @@ jobs: run: | hatch run typing:test hatch run lint:style - pipx run 'validate-pyproject[all]' pyproject.toml + pipx run interrogate -vv . pipx run doc8 --max-line-length=200 check_release: @@ -89,7 +89,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} test_docs: - runs-on: ubuntu-latest + runs-on: windows-latest steps: - uses: actions/checkout@v3 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f5fe3326b..419f3dc57 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,16 +5,19 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: - - id: end-of-file-fixer - id: check-case-conflict + - id: check-ast + - id: check-docstring-first - id: check-executables-have-shebangs - - id: requirements-txt-fixer - id: check-added-large-files - id: check-case-conflict + - id: check-merge-conflict + - id: check-json - id: check-toml - id: check-yaml - - id: forbid-new-submodules - - id: check-builtin-literals + - id: debug-statements + exclude: ipykernel/kernelapp.py + - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema @@ -33,7 +36,7 @@ repos: - id: black - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.177 + rev: v0.0.189 hooks: - id: ruff args: ["--fix"] diff --git a/docs/conf.py b/docs/conf.py index 9a47e1769..b5edf98a9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,6 +36,14 @@ "sphinxcontrib_github_alt", ] +try: + import enchant # noqa + + extensions += ["sphinxcontrib.spelling"] +except ImportError: + pass + + github_project_url = "https://github.com/ipython/ipykernel" # Add any paths that contain templates here, relative to this directory. diff --git a/examples/embedding/inprocess_qtconsole.py b/examples/embedding/inprocess_qtconsole.py index 3ac4ae485..c346a97fb 100644 --- a/examples/embedding/inprocess_qtconsole.py +++ b/examples/embedding/inprocess_qtconsole.py @@ -1,3 +1,4 @@ +"""An in-process qt console app.""" import os import sys @@ -8,6 +9,7 @@ def print_process_id(): + """Print the process id.""" print("Process ID is:", os.getpid()) @@ -42,6 +44,7 @@ def init_asyncio_patch(): def main(): + """The main entry point.""" # Print the ID of the main process print_process_id() diff --git a/examples/embedding/inprocess_terminal.py b/examples/embedding/inprocess_terminal.py index 2f8d5453d..79e11e03a 100644 --- a/examples/embedding/inprocess_terminal.py +++ b/examples/embedding/inprocess_terminal.py @@ -1,3 +1,4 @@ +"""An in-process terminal example.""" import os import sys @@ -8,6 +9,7 @@ def print_process_id(): + """Print the process id.""" print("Process ID is:", os.getpid()) @@ -42,6 +44,7 @@ def init_asyncio_patch(): def main(): + """The main function.""" print_process_id() # Create an in-process kernel diff --git a/examples/embedding/internal_ipkernel.py b/examples/embedding/internal_ipkernel.py index 9aa2783a0..ee4424288 100644 --- a/examples/embedding/internal_ipkernel.py +++ b/examples/embedding/internal_ipkernel.py @@ -1,3 +1,4 @@ +"""An internal ipykernel example.""" # ----------------------------------------------------------------------------- # Imports # ----------------------------------------------------------------------------- @@ -26,8 +27,10 @@ def mpl_kernel(gui): class InternalIPKernel: + """An internal ipykernel class.""" + def init_ipkernel(self, backend): - # Start IPython kernel with GUI event loop and mpl support + """Start IPython kernel with GUI event loop and mpl support.""" self.ipkernel = mpl_kernel(backend) # To create and track active qt consoles self.consoles = [] @@ -41,6 +44,7 @@ def init_ipkernel(self, backend): # self.namespace['ipkernel'] = self.ipkernel # dbg def print_namespace(self, evt=None): + """Print the namespace.""" print("\n***Variables in User namespace***") for k, v in self.namespace.items(): if not k.startswith("_"): @@ -52,8 +56,10 @@ def new_qt_console(self, evt=None): return connect_qtconsole(self.ipkernel.abs_connection_file, profile=self.ipkernel.profile) def count(self, evt=None): + """Get the app counter value.""" self.namespace["app_counter"] += 1 def cleanup_consoles(self, evt=None): + """Clean up the consoles.""" for c in self.consoles: c.kill() diff --git a/examples/embedding/ipkernel_qtapp.py b/examples/embedding/ipkernel_qtapp.py index 7d6e61cf0..608c4e426 100755 --- a/examples/embedding/ipkernel_qtapp.py +++ b/examples/embedding/ipkernel_qtapp.py @@ -26,13 +26,17 @@ # Functions and classes # ----------------------------------------------------------------------------- class SimpleWindow(Qt.QWidget, InternalIPKernel): + """A custom Qt widget for IPykernel.""" + def __init__(self, app): + """Initialize the widget.""" Qt.QWidget.__init__(self) self.app = app self.add_widgets() self.init_ipkernel("qt") def add_widgets(self): + """Add the widget.""" self.setGeometry(300, 300, 400, 70) self.setWindowTitle("IPython in your app") diff --git a/examples/embedding/ipkernel_wxapp.py b/examples/embedding/ipkernel_wxapp.py index 2caad5be2..f24ed9392 100755 --- a/examples/embedding/ipkernel_wxapp.py +++ b/examples/embedding/ipkernel_wxapp.py @@ -36,6 +36,7 @@ class MyFrame(wx.Frame, InternalIPKernel): """ def __init__(self, parent, title): + """Initialize the frame.""" wx.Frame.__init__(self, parent, -1, title, pos=(150, 150), size=(350, 285)) # Create the menubar @@ -99,7 +100,10 @@ def OnTimeToClose(self, evt): class MyApp(wx.App): + """A custom wx app.""" + def OnInit(self): + """Initialize app.""" frame = MyFrame(None, "Simple wxPython App") self.SetTopWindow(frame) frame.Show(True) diff --git a/hatch_build.py b/hatch_build.py index deb21ff47..71dc49be3 100644 --- a/hatch_build.py +++ b/hatch_build.py @@ -1,3 +1,4 @@ +"""A custom hatch build hook for ipykernel.""" import os import shutil import sys @@ -6,7 +7,10 @@ class CustomHook(BuildHookInterface): + """The IPykernel build hook.""" + def initialize(self, version, build_data): + """Initialize the hook.""" here = os.path.abspath(os.path.dirname(__file__)) sys.path.insert(0, here) from ipykernel.kernelspec import make_ipkernel_cmd, write_kernel_spec diff --git a/ipykernel/__main__.py b/ipykernel/__main__.py index f66b36c8e..a1050e32e 100644 --- a/ipykernel/__main__.py +++ b/ipykernel/__main__.py @@ -1,3 +1,4 @@ +"""The cli entry point for ipykernel.""" if __name__ == "__main__": from ipykernel import kernelapp as app diff --git a/ipykernel/comm/comm.py b/ipykernel/comm/comm.py index 6ec6ff3d3..8f3c2dff3 100644 --- a/ipykernel/comm/comm.py +++ b/ipykernel/comm/comm.py @@ -16,6 +16,8 @@ # this is the class that will be created if we do comm.create_comm class BaseComm(comm.base_comm.BaseComm): + """The base class for comms.""" + kernel: Optional[Kernel] = None def publish_msg(self, msg_type, data=None, metadata=None, buffers=None, **keys): @@ -69,6 +71,7 @@ def _default_comm_id(self): return uuid.uuid4().hex def __init__(self, target_name='', data=None, metadata=None, buffers=None, **kwargs): + """Initialize a comm.""" # Handle differing arguments between base classes. had_kernel = 'kernel' in kwargs kernel = kwargs.pop('kernel', None) diff --git a/ipykernel/comm/manager.py b/ipykernel/comm/manager.py index c11b56205..f18e272d2 100644 --- a/ipykernel/comm/manager.py +++ b/ipykernel/comm/manager.py @@ -10,12 +10,14 @@ class CommManager(comm.base_comm.CommManager, traitlets.config.LoggingConfigurable): + """A comm manager.""" kernel = traitlets.Instance("ipykernel.kernelbase.Kernel") comms = traitlets.Dict() targets = traitlets.Dict() def __init__(self, **kwargs): + """Initialize the manager.""" # CommManager doesn't take arguments, so we explicitly forward arguments comm.base_comm.CommManager.__init__(self) traitlets.config.LoggingConfigurable.__init__(self, **kwargs) diff --git a/ipykernel/compiler.py b/ipykernel/compiler.py index 387e49b3e..fe5561594 100644 --- a/ipykernel/compiler.py +++ b/ipykernel/compiler.py @@ -1,3 +1,4 @@ +"""Compiler helpers for the debugger.""" import os import sys import tempfile @@ -6,6 +7,7 @@ def murmur2_x86(data, seed): + """Get the murmur2 hash.""" m = 0x5BD1E995 data = [chr(d) for d in str.encode(data, "utf8")] length = len(data) @@ -70,17 +72,20 @@ def _convert_to_long_pathname(filename): def get_tmp_directory(): + """Get a temp directory.""" tmp_dir = convert_to_long_pathname(tempfile.gettempdir()) pid = os.getpid() return tmp_dir + os.sep + "ipykernel_" + str(pid) def get_tmp_hash_seed(): + """Get a temp hash seed.""" hash_seed = 0xC70F6907 return hash_seed def get_file_name(code): + """Get a file name.""" cell_name = os.environ.get("IPYKERNEL_CELL_NAME") if cell_name is None: name = murmur2_x86(code, get_tmp_hash_seed()) @@ -89,9 +94,13 @@ def get_file_name(code): class XCachingCompiler(CachingCompiler): + """A custom caching compiler.""" + def __init__(self, *args, **kwargs): + """Initialize the compiler.""" super().__init__(*args, **kwargs) self.log = None def get_code_name(self, raw_code, code, number): + """Get the code name.""" return get_file_name(raw_code) diff --git a/ipykernel/control.py b/ipykernel/control.py index 1aaf9a7e8..d78a4ebe1 100644 --- a/ipykernel/control.py +++ b/ipykernel/control.py @@ -1,16 +1,21 @@ +"""A thread for a control channel.""" from threading import Thread from tornado.ioloop import IOLoop class ControlThread(Thread): + """A thread for a control channel.""" + def __init__(self, **kwargs): + """Initialize the thread.""" Thread.__init__(self, name="Control", **kwargs) self.io_loop = IOLoop(make_current=False) self.pydev_do_not_trace = True self.is_pydev_daemon_thread = True def run(self): + """Run the thread.""" self.name = "Control" try: self.io_loop.start() diff --git a/ipykernel/datapub.py b/ipykernel/datapub.py index d8fe04093..4b1c7a501 100644 --- a/ipykernel/datapub.py +++ b/ipykernel/datapub.py @@ -28,6 +28,7 @@ class ZMQDataPublisher(Configurable): + """A zmq data publisher.""" topic = topic = CBytes(b"datapub") session = Instance(Session, allow_none=True) diff --git a/ipykernel/debugger.py b/ipykernel/debugger.py index 224678232..43ae68300 100644 --- a/ipykernel/debugger.py +++ b/ipykernel/debugger.py @@ -1,3 +1,4 @@ +"""Debugger implementation for the IPython kernel.""" import os import re import sys @@ -44,13 +45,19 @@ class _FakeCode: + """Fake code class.""" + def __init__(self, co_filename, co_name): + """Init.""" self.co_filename = co_filename self.co_name = co_name class _FakeFrame: + """Fake frame class.""" + def __init__(self, f_code, f_globals, f_locals): + """Init.""" self.f_code = f_code self.f_globals = f_globals self.f_locals = f_locals @@ -58,28 +65,37 @@ def __init__(self, f_code, f_globals, f_locals): class _DummyPyDB: + """Fake PyDb class.""" + def __init__(self): + """Init.""" from _pydevd_bundle.pydevd_api import PyDevdAPI self.variable_presentation = PyDevdAPI.VariablePresentation() class VariableExplorer: + """A variable explorer.""" + def __init__(self): + """Initialize the explorer.""" self.suspended_frame_manager = SuspendedFramesManager() self.py_db = _DummyPyDB() self.tracker = _FramesTracker(self.suspended_frame_manager, self.py_db) self.frame = None def track(self): + """Start tracking.""" var = get_ipython().user_ns self.frame = _FakeFrame(_FakeCode("", get_file_name("sys._getframe()")), var, var) self.tracker.track("thread1", pydevd_frame_utils.create_frames_list_from_frame(self.frame)) def untrack_all(self): + """Stop tracking.""" self.tracker.untrack_all() def get_children_variables(self, variable_ref=None): + """Get the child variables for a variable reference.""" var_ref = variable_ref if not var_ref: var_ref = id(self.frame) @@ -88,6 +104,7 @@ def get_children_variables(self, variable_ref=None): class DebugpyMessageQueue: + """A debugpy message queue.""" HEADER = "Content-Length: " HEADER_LENGTH = 16 @@ -95,6 +112,7 @@ class DebugpyMessageQueue: SEPARATOR_LENGTH = 4 def __init__(self, event_callback, log): + """Init the queue.""" self.tcp_buffer = "" self._reset_tcp_pos() self.event_callback = event_callback @@ -120,6 +138,7 @@ def _put_message(self, raw_msg): self.message_queue.put_nowait(msg) def put_tcp_frame(self, frame): + """Put a tcp frame in the queue.""" self.tcp_buffer += frame self.log.debug("QUEUE - received frame") @@ -166,11 +185,15 @@ def put_tcp_frame(self, frame): self._reset_tcp_pos() async def get_message(self): + """Get a message from the queue.""" return await self.message_queue.get() class DebugpyClient: + """A client for debugpy.""" + def __init__(self, log, debugpy_stream, event_callback): + """Initialize the client.""" self.log = log self.debugpy_stream = debugpy_stream self.event_callback = event_callback @@ -237,6 +260,7 @@ async def _handle_init_sequence(self): return attach_rep def get_host_port(self): + """Get the host debugpy port.""" if self.debugpy_port == -1: socket = self.debugpy_stream.socket socket.bind_to_random_port("tcp://" + self.debugpy_host) @@ -247,10 +271,12 @@ def get_host_port(self): return self.debugpy_host, self.debugpy_port def connect_tcp_socket(self): + """Connect to the tcp socket.""" self.debugpy_stream.socket.connect(self._get_endpoint()) self.routing_id = self.debugpy_stream.socket.getsockopt(ROUTING_ID) def disconnect_tcp_socket(self): + """Disconnect from the tcp socket.""" self.debugpy_stream.socket.disconnect(self._get_endpoint()) self.routing_id = None self.init_event = Event() @@ -258,9 +284,11 @@ def disconnect_tcp_socket(self): self.wait_for_attach = True def receive_dap_frame(self, frame): + """Receive a dap frame.""" self.message_queue.put_tcp_frame(frame) async def send_dap_request(self, msg): + """Send a dap request.""" self._send_request(msg) if self.wait_for_attach and msg["command"] == "attach": rep = await self._handle_init_sequence() @@ -274,6 +302,7 @@ async def send_dap_request(self, msg): class Debugger: + """The debugger class.""" # Requests that requires that the debugger has started started_debug_msg_types = [ @@ -292,6 +321,7 @@ class Debugger: def __init__( self, log, debugpy_stream, event_callback, shell_socket, session, just_my_code=True ): + """Initialize the debugger.""" self.log = log self.debugpy_client = DebugpyClient(log, debugpy_stream, self._handle_event) self.shell_socket = shell_socket @@ -361,6 +391,7 @@ def _accept_stopped_thread(self, thread_name): return thread_name not in forbid_list async def handle_stopped_event(self): + """Handle a stopped event.""" # Wait for a stopped event message in the stopped queue # This message is used for triggering the 'threads' request event = await self.stopped_queue.get() @@ -376,6 +407,7 @@ def tcp_client(self): return self.debugpy_client def start(self): + """Start the debugger.""" if not self.debugpy_initialized: tmp_dir = get_tmp_directory() if not os.path.exists(tmp_dir): @@ -405,6 +437,7 @@ def start(self): return self.debugpy_initialized def stop(self): + """Stop the debugger.""" self.debugpy_client.disconnect_tcp_socket() # Restore remove cleanup transformers @@ -414,6 +447,7 @@ def stop(self): cleanup_transforms.insert(index, func) async def dumpCell(self, message): + """Handle a dump cell message.""" code = message["arguments"]["code"] file_name = get_file_name(code) @@ -430,11 +464,13 @@ async def dumpCell(self, message): return reply async def setBreakpoints(self, message): + """Handle a set breakpoints message.""" source = message["arguments"]["source"]["path"] self.breakpoint_list[source] = message["arguments"]["breakpoints"] return await self._forward_message(message) async def source(self, message): + """Handle a source message.""" reply = {"type": "response", "request_seq": message["seq"], "command": message["command"]} source_path = message["arguments"]["source"]["path"] if os.path.isfile(source_path): @@ -449,6 +485,7 @@ async def source(self, message): return reply async def stackTrace(self, message): + """Handle a stack trace message.""" reply = await self._forward_message(message) # The stackFrames array can have the following content: # { frames from the notebook} @@ -470,6 +507,7 @@ async def stackTrace(self, message): return reply def accept_variable(self, variable_name): + """Accept a variable by name.""" forbid_list = [ "__name__", "__doc__", @@ -498,6 +536,7 @@ def accept_variable(self, variable_name): return cond async def variables(self, message): + """Handle a variables message.""" reply = {} if not self.stopped_threads: variables = self.variable_explorer.get_children_variables( @@ -513,6 +552,7 @@ async def variables(self, message): return reply async def attach(self, message): + """Handle an attach message.""" host, port = self.debugpy_client.get_host_port() message["arguments"]["connect"] = {"host": host, "port": port} message["arguments"]["logToFile"] = True @@ -525,6 +565,7 @@ async def attach(self, message): return await self._forward_message(message) async def configurationDone(self, message): + """Handle a configuration done message.""" reply = { "seq": message["seq"], "type": "response", @@ -535,6 +576,7 @@ async def configurationDone(self, message): return reply async def debugInfo(self, message): + """Handle a debug info message.""" breakpoint_list = [] for key, value in self.breakpoint_list.items(): breakpoint_list.append({"source": key, "breakpoints": value}) @@ -558,6 +600,7 @@ async def debugInfo(self, message): return reply async def inspectVariables(self, message): + """Handle an insepct variables message.""" self.variable_explorer.untrack_all() # looks like the implementation of untrack_all in ptvsd # destroys objects we nee din track. We have no choice but @@ -568,6 +611,7 @@ async def inspectVariables(self, message): return self._build_variables_response(message, variables) async def richInspectVariables(self, message): + """Handle a rich inspect variables message.""" reply = { "type": "response", "sequence_seq": message["seq"], @@ -619,6 +663,7 @@ async def richInspectVariables(self, message): return reply async def modules(self, message): + """Handle a modules message.""" modules = list(sys.modules.values()) startModule = message.get("startModule", 0) moduleCount = message.get("moduleCount", len(modules)) @@ -633,6 +678,7 @@ async def modules(self, message): return reply async def process_request(self, message): + """Process a request.""" reply = {} if message["command"] == "initialize": diff --git a/ipykernel/displayhook.py b/ipykernel/displayhook.py index e7c98c01d..0727997cc 100644 --- a/ipykernel/displayhook.py +++ b/ipykernel/displayhook.py @@ -20,6 +20,7 @@ class ZMQDisplayHook: topic = b"execute_result" def __init__(self, session, pub_socket): + """Initialize the hook.""" self.session = session self.pub_socket = pub_socket self.parent_header = {} @@ -29,6 +30,7 @@ def get_execution_count(self): return 0 def __call__(self, obj): + """Handle a hook call.""" if obj is None: return @@ -45,6 +47,7 @@ def __call__(self, obj): ) def set_parent(self, parent): + """Set the parent header.""" self.parent_header = extract_header(parent) @@ -64,6 +67,7 @@ def set_parent(self, parent): self.parent_header = extract_header(parent) def start_displayhook(self): + """Start the display hook.""" self.msg = self.session.msg( "execute_result", { @@ -78,6 +82,7 @@ def write_output_prompt(self): self.msg["content"]["execution_count"] = self.prompt_count def write_format_data(self, format_dict, md_dict=None): + """Write format data to the message.""" self.msg["content"]["data"] = json_clean(encode_images(format_dict)) self.msg["content"]["metadata"] = md_dict diff --git a/ipykernel/eventloops.py b/ipykernel/eventloops.py index b2a312d90..76d1c700f 100644 --- a/ipykernel/eventloops.py +++ b/ipykernel/eventloops.py @@ -83,6 +83,7 @@ def register_integration(*toolkitnames): """ def decorator(func): + """Integration registration decorator.""" for name in toolkitnames: loop_map[name] = func @@ -221,6 +222,7 @@ def OnInit(self): @loop_wx.exit def loop_wx_exit(kernel): + """Exit the wx loop.""" import wx wx.Exit() @@ -298,6 +300,7 @@ def start(self): @loop_tk.exit def loop_tk_exit(kernel): + """Exit the tk loop.""" try: kernel.app_wrapper.app.destroy() del kernel.app_wrapper @@ -317,6 +320,7 @@ def loop_gtk(kernel): @loop_gtk.exit def loop_gtk_exit(kernel): + """Exit the gtk loop.""" kernel._gtk.stop() @@ -332,6 +336,7 @@ def loop_gtk3(kernel): @loop_gtk3.exit def loop_gtk3_exit(kernel): + """Exit the gtk3 loop.""" kernel._gtk.stop() @@ -376,6 +381,7 @@ def handle_int(etype, value, tb): @loop_cocoa.exit def loop_cocoa_exit(kernel): + """Exit the cocoa loop.""" from ._eventloop_macos import stop stop() diff --git a/ipykernel/gui/gtk3embed.py b/ipykernel/gui/gtk3embed.py index 42c7e181f..3847683cd 100644 --- a/ipykernel/gui/gtk3embed.py +++ b/ipykernel/gui/gtk3embed.py @@ -32,6 +32,7 @@ class GTKEmbed: """A class to embed a kernel into the GTK main event loop.""" def __init__(self, kernel): + """Initialize the embed.""" self.kernel = kernel # These two will later store the real gtk functions when we hijack them self.gtk_main = None @@ -63,6 +64,7 @@ def iterate_kernel(self): return True def stop(self): + """Stop the embed.""" # FIXME: this one isn't getting called because we have no reliable # kernel shutdown. We need to fix that: once the kernel has a # shutdown mechanism, it can call this. @@ -86,6 +88,7 @@ def _hijack_gtk(self): """ def dummy(*args, **kw): + """No-op.""" pass # save and trap main and main_quit from gtk diff --git a/ipykernel/gui/gtkembed.py b/ipykernel/gui/gtkembed.py index a97a62a06..5d9171bb8 100644 --- a/ipykernel/gui/gtkembed.py +++ b/ipykernel/gui/gtkembed.py @@ -29,6 +29,7 @@ class GTKEmbed: """A class to embed a kernel into the GTK main event loop.""" def __init__(self, kernel): + """Initialize the embed.""" self.kernel = kernel # These two will later store the real gtk functions when we hijack them self.gtk_main = None @@ -60,6 +61,7 @@ def iterate_kernel(self): return True def stop(self): + """Stop the embed.""" # FIXME: this one isn't getting called because we have no reliable # kernel shutdown. We need to fix that: once the kernel has a # shutdown mechanism, it can call this. @@ -83,6 +85,7 @@ def _hijack_gtk(self): """ def dummy(*args, **kw): + """No-op.""" pass # save and trap main and main_quit from gtk diff --git a/ipykernel/heartbeat.py b/ipykernel/heartbeat.py index 3f10997c6..cf2d6d5ae 100644 --- a/ipykernel/heartbeat.py +++ b/ipykernel/heartbeat.py @@ -29,6 +29,7 @@ class Heartbeat(Thread): """A simple ping-pong style heartbeat that runs in a thread.""" def __init__(self, context, addr=None): + """Initialize the heartbeat thread.""" if addr is None: addr = ("tcp", localhost(), 0) Thread.__init__(self, name="Heartbeat") @@ -44,6 +45,7 @@ def __init__(self, context, addr=None): self.name = "Heartbeat" def pick_port(self): + """Pick a port for the heartbeat.""" if self.transport == "tcp": s = socket.socket() # '*' means all interfaces to 0MQ, which is '' to socket.socket @@ -89,6 +91,7 @@ def _bind_socket(self): return def run(self): + """Run the heartbeat thread.""" self.name = "Heartbeat" self.socket = self.context.socket(zmq.ROUTER) self.socket.linger = 1000 diff --git a/ipykernel/inprocess/blocking.py b/ipykernel/inprocess/blocking.py index 17f334f48..2274bed39 100644 --- a/ipykernel/inprocess/blocking.py +++ b/ipykernel/inprocess/blocking.py @@ -21,11 +21,15 @@ class BlockingInProcessChannel(InProcessChannel): + """A blocking in-process channel.""" + def __init__(self, *args, **kwds): + """Initialize the channel.""" super().__init__(*args, **kwds) self._in_queue: Queue[object] = Queue() def call_handlers(self, msg): + """Call the handlers for a message.""" self._in_queue.put(msg) def get_msg(self, block=True, timeout=None): @@ -52,6 +56,8 @@ def msg_ready(self): class BlockingInProcessStdInChannel(BlockingInProcessChannel): + """A blocking in-process stdin channel.""" + def call_handlers(self, msg): """Overridden for the in-process channel. @@ -67,6 +73,7 @@ def call_handlers(self, msg): class BlockingInProcessKernelClient(InProcessKernelClient): + """A blocking in-process kernel client.""" # The classes to use for the various channels. shell_channel_class = Type(BlockingInProcessChannel) @@ -74,7 +81,7 @@ class BlockingInProcessKernelClient(InProcessKernelClient): stdin_channel_class = Type(BlockingInProcessStdInChannel) def wait_for_ready(self): - # Wait for kernel info reply on shell channel + """Wait for kernel info reply on shell channel.""" while True: self.kernel_info() try: diff --git a/ipykernel/inprocess/channels.py b/ipykernel/inprocess/channels.py index 84629ff5d..9b054e043 100644 --- a/ipykernel/inprocess/channels.py +++ b/ipykernel/inprocess/channels.py @@ -18,17 +18,21 @@ class InProcessChannel: proxy_methods: List[object] = [] def __init__(self, client=None): + """Initialze the channel.""" super().__init__() self.client = client self._is_alive = False def is_alive(self): + """Test if the channel is alive.""" return self._is_alive def start(self): + """Start the channel.""" self._is_alive = True def stop(self): + """Stop the channel.""" self._is_alive = False def call_handlers(self, msg): @@ -39,6 +43,7 @@ def call_handlers(self, msg): raise NotImplementedError("call_handlers must be defined in a subclass.") def flush(self, timeout=1.0): + """Flush the channel.""" pass def call_handlers_later(self, *args, **kwds): @@ -70,27 +75,34 @@ class InProcessHBChannel: time_to_dead = 3.0 def __init__(self, client=None): + """Initialize the channel.""" super().__init__() self.client = client self._is_alive = False self._pause = True def is_alive(self): + """Test if the channel is alive.""" return self._is_alive def start(self): + """Start the channel.""" self._is_alive = True def stop(self): + """Stop the channel.""" self._is_alive = False def pause(self): + """Pause the channel.""" self._pause = True def unpause(self): + """Unpause the channel.""" self._pause = False def is_beating(self): + """Test if the channel is beating.""" return not self._pause diff --git a/ipykernel/inprocess/client.py b/ipykernel/inprocess/client.py index d6bfc9a5f..124d5cf3e 100644 --- a/ipykernel/inprocess/client.py +++ b/ipykernel/inprocess/client.py @@ -62,11 +62,13 @@ def _default_blocking_class(self): return BlockingInProcessKernelClient def get_connection_info(self): + """Get the connection info for the client.""" d = super().get_connection_info() d["kernel"] = self.kernel return d def start_channels(self, *args, **kwargs): + """Start the channels on the client.""" super().start_channels() self.kernel.frontends.append(self) @@ -106,6 +108,7 @@ def hb_channel(self): def execute( self, code, silent=False, store_history=True, user_expressions=None, allow_stdin=None ): + """Execute code on the client.""" if allow_stdin is None: allow_stdin = self.allow_stdin content = dict( @@ -120,6 +123,7 @@ def execute( return msg["header"]["msg_id"] def complete(self, code, cursor_pos=None): + """Get code completion.""" if cursor_pos is None: cursor_pos = len(code) content = dict(code=code, cursor_pos=cursor_pos) @@ -128,6 +132,7 @@ def complete(self, code, cursor_pos=None): return msg["header"]["msg_id"] def inspect(self, code, cursor_pos=None, detail_level=0): + """Get code inspection.""" if cursor_pos is None: cursor_pos = len(code) content = dict( @@ -140,12 +145,14 @@ def inspect(self, code, cursor_pos=None, detail_level=0): return msg["header"]["msg_id"] def history(self, raw=True, output=False, hist_access_type="range", **kwds): + """Get code history.""" content = dict(raw=raw, output=output, hist_access_type=hist_access_type, **kwds) msg = self.session.msg("history_request", content) self._dispatch_to_kernel(msg) return msg["header"]["msg_id"] def shutdown(self, restart=False): + """Handle shutdown.""" # FIXME: What to do here? raise NotImplementedError("Cannot shutdown in-process kernel") @@ -166,11 +173,13 @@ def comm_info(self, target_name=None): return msg["header"]["msg_id"] def input(self, string): + """Handle kernel input.""" if self.kernel is None: raise RuntimeError("Cannot send input reply. No kernel exists.") self.kernel.raw_input_str = string def is_complete(self, code): + """Handle an is_complete request.""" msg = self.session.msg("is_complete_request", {"code": code}) self._dispatch_to_kernel(msg) return msg["header"]["msg_id"] @@ -194,15 +203,19 @@ def _dispatch_to_kernel(self, msg): self.shell_channel.call_handlers_later(reply_msg) def get_shell_msg(self, block=True, timeout=None): + """Get a shell message.""" return self.shell_channel.get_msg(block, timeout) def get_iopub_msg(self, block=True, timeout=None): + """Get an iopub message.""" return self.iopub_channel.get_msg(block, timeout) def get_stdin_msg(self, block=True, timeout=None): + """Get a stdin message.""" return self.stdin_channel.get_msg(block, timeout) def get_control_msg(self, block=True, timeout=None): + """Get a control message.""" return self.control_channel.get_msg(block, timeout) diff --git a/ipykernel/inprocess/ipkernel.py b/ipykernel/inprocess/ipkernel.py index f185ddc35..df34303b4 100644 --- a/ipykernel/inprocess/ipkernel.py +++ b/ipykernel/inprocess/ipkernel.py @@ -24,6 +24,7 @@ class InProcessKernel(IPythonKernel): + """An in-process kernel.""" # ------------------------------------------------------------------------- # InProcessKernel interface @@ -67,6 +68,7 @@ def _default_iopub_socket(self): stdin_socket = Instance(DummySocket, ()) # type:ignore[assignment] def __init__(self, **traits): + """Initialize the kernel.""" super().__init__(**traits) self._underlying_iopub_socket.observe(self._io_dispatch, names=["message_sent"]) @@ -163,6 +165,7 @@ def _default_stderr(self): class InProcessInteractiveShell(ZMQInteractiveShell): + """An in-process interactive shell.""" kernel: InProcessKernel = Instance( "ipykernel.inprocess.ipkernel.InProcessKernel", allow_none=True diff --git a/ipykernel/inprocess/manager.py b/ipykernel/inprocess/manager.py index fbbd34236..5649e8cab 100644 --- a/ipykernel/inprocess/manager.py +++ b/ipykernel/inprocess/manager.py @@ -42,15 +42,18 @@ def _default_session(self): # -------------------------------------------------------------------------- def start_kernel(self, **kwds): + """Start the kernel.""" from ipykernel.inprocess.ipkernel import InProcessKernel self.kernel = InProcessKernel(parent=self, session=self.session) def shutdown_kernel(self): + """Shutdown the kernel.""" self.kernel.iopub_thread.stop() self._kill_kernel() def restart_kernel(self, now=False, **kwds): + """Restart the kernel.""" self.shutdown_kernel() self.start_kernel(**kwds) @@ -62,15 +65,19 @@ def _kill_kernel(self): self.kernel = None def interrupt_kernel(self): + """Interrupt the kernel.""" raise NotImplementedError("Cannot interrupt in-process kernel.") def signal_kernel(self, signum): + """Send a signal to the kernel.""" raise NotImplementedError("Cannot signal in-process kernel.") def is_alive(self): + """Test if the kernel is alive.""" return self.kernel is not None def client(self, **kwargs): + """Get a client for the kernel.""" kwargs["kernel"] = self.kernel return super().client(**kwargs) diff --git a/ipykernel/inprocess/socket.py b/ipykernel/inprocess/socket.py index 477c36a47..7e48789e9 100644 --- a/ipykernel/inprocess/socket.py +++ b/ipykernel/inprocess/socket.py @@ -28,9 +28,11 @@ def _context_default(self): # ------------------------------------------------------------------------- def recv_multipart(self, flags=0, copy=True, track=False): + """Recv a multipart message.""" return self.queue.get_nowait() def send_multipart(self, msg_parts, flags=0, copy=True, track=False): + """Send a multipart message.""" msg_parts = list(map(zmq.Message, msg_parts)) self.queue.put_nowait(msg_parts) self.message_sent += 1 diff --git a/ipykernel/iostream.py b/ipykernel/iostream.py index 5ea77452e..22b50a2a4 100644 --- a/ipykernel/iostream.py +++ b/ipykernel/iostream.py @@ -190,6 +190,7 @@ def stop(self): event_pipe.close() def close(self): + """Close the IOPub thread.""" if self.closed: return self.socket.close() @@ -244,6 +245,7 @@ class BackgroundSocket: io_thread = None def __init__(self, io_thread): + """Initialize the socket.""" self.io_thread = io_thread def __getattr__(self, attr): @@ -264,6 +266,7 @@ def __getattr__(self, attr): super().__getattr__(attr) # type:ignore[misc] def __setattr__(self, attr, value): + """Set an attribute on the socket.""" if attr == "io_thread" or (attr.startswith("__") and attr.endswith("__")): super().__setattr__(attr, value) else: @@ -278,6 +281,7 @@ def __setattr__(self, attr, value): setattr(self.io_thread.socket, attr, value) def send(self, msg, *args, **kwargs): + """Send a message to the socket.""" return self.send_multipart([msg], *args, **kwargs) def send_multipart(self, *args, **kwargs): @@ -438,9 +442,11 @@ def _is_master_process(self): return os.getpid() == self._master_pid def set_parent(self, parent): + """Set the parent header.""" self.parent_header = extract_header(parent) def close(self): + """Close the stream.""" if sys.platform.startswith("linux") or sys.platform.startswith("darwin"): self._should_watch = False self.watch_fd_thread.join() @@ -565,6 +571,7 @@ def write(self, string: str) -> Optional[int]: # type:ignore[override] return len(string) def writelines(self, sequence): + """Write lines to the stream.""" if self.pub_thread is None: raise ValueError("I/O operation on closed file") else: @@ -572,6 +579,7 @@ def writelines(self, sequence): self.write(string) def writable(self): + """Test whether the stream is writable.""" return True def _flush_buffer(self): diff --git a/ipykernel/ipkernel.py b/ipykernel/ipkernel.py index 4dfe59c46..f4b67caa2 100644 --- a/ipykernel/ipkernel.py +++ b/ipykernel/ipkernel.py @@ -67,6 +67,8 @@ def _get_comm_manager(*args, **kwargs): class IPythonKernel(KernelBase): + """The IPython Kernel class.""" + shell = Instance("IPython.core.interactiveshell.InteractiveShellABC", allow_none=True) shell_class = Type(ZMQInteractiveShell) @@ -100,6 +102,7 @@ def _user_ns_changed(self, change): _sys_eval_input = Any() def __init__(self, **kwargs): + """Initialize the kernel.""" super().__init__(**kwargs) # Initialize the Debugger @@ -200,10 +203,12 @@ def banner(self): return self.shell.banner async def poll_stopped_queue(self): + """Poll the stopped queue.""" while True: await self.debugger.handle_stopped_event() def start(self): + """Start the kernel.""" self.shell.exit_now = False if self.debugpy_stream is None: self.log.warning("debugpy_stream undefined, debugging will not be enabled") @@ -335,6 +340,7 @@ async def do_execute( *, cell_id=None, ): + """Handle code execution.""" shell = self.shell # we'll need this a lot here self._forward_input(allow_stdin) @@ -469,6 +475,7 @@ async def run_cell(*args, **kwargs): return reply_content def do_complete(self, code, cursor_pos): + """Handle code completion.""" if _use_experimental_60_completion and self.use_experimental_completions: return self._experimental_do_complete(code, cursor_pos) @@ -489,6 +496,7 @@ def do_complete(self, code, cursor_pos): } async def do_debug_request(self, msg): + """Handle a debug request.""" if _is_debugpy_available: return await self.debugger.process_request(msg) @@ -532,6 +540,7 @@ def _experimental_do_complete(self, code, cursor_pos): } def do_inspect(self, code, cursor_pos, detail_level=0, omit_sections=()): + """Handle code inspection.""" name = token_at_cursor(code, cursor_pos) reply_content: t.Dict[str, t.Any] = {"status": "ok"} @@ -569,6 +578,7 @@ def do_history( pattern=None, unique=False, ): + """Handle code history.""" if hist_access_type == "tail": hist = self.shell.history_manager.get_tail( n, raw=raw, output=output, include_latest=True @@ -592,10 +602,12 @@ def do_history( } def do_shutdown(self, restart): + """Handle kernel shutdown.""" self.shell.exit_now = True return dict(status="ok", restart=restart) def do_is_complete(self, code): + """Handle an is_complete request.""" transformer_manager = getattr(self.shell, "input_transformer_manager", None) if transformer_manager is None: # input_splitter attribute is deprecated @@ -607,6 +619,7 @@ def do_is_complete(self, code): return r def do_apply(self, content, bufs, msg_id, reply_metadata): + """Handle an apply request.""" try: from ipyparallel.serialize import serialize_object, unpack_apply_message except ImportError: @@ -671,6 +684,7 @@ def do_apply(self, content, bufs, msg_id, reply_metadata): return reply_content, result_buf def do_clear(self): + """Clear the kernel.""" self.shell.reset(False) return dict(status="ok") @@ -679,7 +693,10 @@ def do_clear(self): class Kernel(IPythonKernel): + """DEPRECATED. An alias for the IPython kernel class.""" + def __init__(self, *args, **kwargs): # pragma: no cover + """DEPRECATED.""" import warnings warnings.warn( diff --git a/ipykernel/kernelapp.py b/ipykernel/kernelapp.py index 3f4aa708a..24355b14b 100644 --- a/ipykernel/kernelapp.py +++ b/ipykernel/kernelapp.py @@ -111,6 +111,8 @@ class IPKernelApp(BaseIPythonApplication, InteractiveShellApp, ConnectionFileMixin): + """The IPYKernel application class.""" + name = "ipython-kernel" aliases = Dict(kernel_aliases) flags = Dict(kernel_flags) @@ -197,13 +199,16 @@ def abs_connection_file(self): ).tag(config=True) def init_crash_handler(self): + """Initialize the crash handler.""" sys.excepthook = self.excepthook def excepthook(self, etype, evalue, tb): + """Handle an exception.""" # write uncaught traceback to 'real' stderr, not zmq-forwarder traceback.print_exception(etype, evalue, tb, file=sys.__stderr__) def init_poller(self): + """Initialize the poller.""" if sys.platform == "win32": if self.interrupt or self.parent_handle: self.poller = ParentPollerWindows(self.interrupt, self.parent_handle) @@ -268,6 +273,7 @@ def write_connection_file(self): ) def cleanup_connection_file(self): + """Clean up our connection file.""" cf = self.abs_connection_file self.log.debug("Cleaning up connection file: %s", cf) try: @@ -278,6 +284,7 @@ def cleanup_connection_file(self): self.cleanup_ipc_files() def init_connection_file(self): + """Initialize our connection file.""" if not self.connection_file: self.connection_file = "kernel-%s.json" % os.getpid() try: @@ -298,7 +305,7 @@ def init_connection_file(self): self.exit(1) def init_sockets(self): - # Create a context, a session, and the kernel sockets. + """Create a context, a session, and the kernel sockets.""" self.log.info("Starting the kernel at pid: %i", os.getpid()) assert self.context is None, "init_sockets cannot be called twice!" self.context = context = zmq.Context() @@ -324,6 +331,7 @@ def init_sockets(self): self.init_iopub(context) def init_control(self, context): + """Initialize the control channel.""" self.control_socket = context.socket(zmq.ROUTER) self.control_socket.linger = 1000 self.control_port = self._bind_socket(self.control_socket, self.control_port) @@ -346,6 +354,7 @@ def init_control(self, context): self.control_thread = ControlThread(daemon=True) def init_iopub(self, context): + """Initialize the iopub channel.""" self.iopub_socket = context.socket(zmq.PUB) self.iopub_socket.linger = 1000 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port) @@ -517,6 +526,7 @@ def register(signum, file=sys.__stderr__, all_threads=True, chain=False, **kwarg faulthandler.register = register def init_signal(self): + """Initialize the signal handler.""" signal.signal(signal.SIGINT, signal.SIG_IGN) def init_kernel(self): @@ -580,6 +590,7 @@ def print_tb(etype, evalue, stb): shell._showtraceback = _showtraceback def init_shell(self): + """Initialize the shell channel.""" self.shell = getattr(self.kernel, "shell", None) if self.shell: self.shell.configurables.append(self) @@ -653,6 +664,7 @@ def init_pdb(self): @catch_config_error def initialize(self, argv=None): + """Initialize the application.""" self._init_asyncio_patch() super().initialize(argv) if self.subapp is not None: @@ -691,6 +703,7 @@ def initialize(self, argv=None): sys.stderr.flush() def start(self): + """Start the application.""" if self.subapp is not None: return self.subapp.start() if self.poller is not None: diff --git a/ipykernel/kernelbase.py b/ipykernel/kernelbase.py index e5032c738..768056cfd 100644 --- a/ipykernel/kernelbase.py +++ b/ipykernel/kernelbase.py @@ -68,6 +68,7 @@ def _accepts_cell_id(meth): class Kernel(SingletonConfigurable): + """The base kernel class.""" # --------------------------------------------------------------------------- # Kernel interface @@ -259,6 +260,7 @@ def _parent_header(self): ] def __init__(self, **kwargs): + """Initialize the kernel.""" super().__init__(**kwargs) # Build dict of handlers for message types self.shell_handlers = {} @@ -769,6 +771,7 @@ def do_execute( raise NotImplementedError async def complete_request(self, stream, ident, parent): + """Handle a completion request.""" content = parent["content"] code = content["code"] cursor_pos = content["cursor_pos"] @@ -791,6 +794,7 @@ def do_complete(self, code, cursor_pos): } async def inspect_request(self, stream, ident, parent): + """Handle an inspect request.""" content = parent["content"] reply_content = self.do_inspect( @@ -812,6 +816,7 @@ def do_inspect(self, code, cursor_pos, detail_level=0, omit_sections=()): return {"status": "ok", "data": {}, "metadata": {}, "found": False} async def history_request(self, stream, ident, parent): + """Handle a history request.""" content = parent["content"] reply_content = self.do_history(**content) @@ -838,6 +843,7 @@ def do_history( return {"status": "ok", "history": []} async def connect_request(self, stream, ident, parent): + """Handle a connect request.""" if self._recorded_ports is not None: content = self._recorded_ports.copy() else: @@ -858,12 +864,14 @@ def kernel_info(self): } async def kernel_info_request(self, stream, ident, parent): + """Handle a kernel info request.""" content = {"status": "ok"} content.update(self.kernel_info) msg = self.session.send(stream, "kernel_info_reply", content, parent, ident) self.log.debug("%s", msg) async def comm_info_request(self, stream, ident, parent): + """Handle a comm info request.""" content = parent["content"] target_name = content.get("target_name", None) @@ -900,12 +908,14 @@ def _send_interupt_children(self): pass async def interrupt_request(self, stream, ident, parent): + """Handle an interrupt request.""" self._send_interupt_children() content = parent["content"] self.session.send(stream, "interrupt_reply", content, parent, ident=ident) return async def shutdown_request(self, stream, ident, parent): + """Handle a shutdown request.""" content = self.do_shutdown(parent["content"]["restart"]) if inspect.isawaitable(content): content = await content @@ -930,6 +940,7 @@ def do_shutdown(self, restart): return {"status": "ok", "restart": restart} async def is_complete_request(self, stream, ident, parent): + """Handle an is_complete request.""" content = parent["content"] code = content["code"] @@ -945,6 +956,7 @@ def do_is_complete(self, code): return {"status": "unknown"} async def debug_request(self, stream, ident, parent): + """Handle a debug request.""" content = parent["content"] reply_content = self.do_debug_request(content) if inspect.isawaitable(reply_content): @@ -954,6 +966,7 @@ async def debug_request(self, stream, ident, parent): self.log.debug("%s", reply_msg) def get_process_metric_value(self, process, name, attribute=None): + """Get the process metric value.""" try: metric_value = getattr(process, name)() if attribute is not None: # ... a named tuple @@ -966,6 +979,7 @@ def get_process_metric_value(self, process, name, attribute=None): return None async def usage_request(self, stream, ident, parent): + """Handle a usage request.""" reply_content = {"hostname": socket.gethostname(), "pid": os.getpid()} current_process = psutil.Process() all_processes = [current_process] + current_process.children(recursive=True) @@ -1005,6 +1019,7 @@ async def do_debug_request(self, msg): # --------------------------------------------------------------------------- async def apply_request(self, stream, ident, parent): # pragma: no cover + """Handle an apply request.""" self.log.warning("apply_request is deprecated in kernel_base, moving to ipyparallel.") try: content = parent["content"] diff --git a/ipykernel/kernelspec.py b/ipykernel/kernelspec.py index 64bc0acae..4f2fc33b2 100644 --- a/ipykernel/kernelspec.py +++ b/ipykernel/kernelspec.py @@ -168,11 +168,13 @@ class InstallIPythonKernelSpecApp(Application): name = Unicode("ipython-kernel-install") def initialize(self, argv=None): + """Initialize the app.""" if argv is None: argv = sys.argv[1:] self.argv = argv def start(self): + """Start the app.""" import argparse parser = argparse.ArgumentParser( diff --git a/ipykernel/log.py b/ipykernel/log.py index aca21d25b..d55c21d04 100644 --- a/ipykernel/log.py +++ b/ipykernel/log.py @@ -1,3 +1,4 @@ +"""A PUB log handler.""" import warnings from zmq.log.handlers import PUBHandler @@ -15,6 +16,7 @@ class EnginePUBHandler(PUBHandler): engine = None def __init__(self, engine, *args, **kwargs): + """Initialize the handler.""" PUBHandler.__init__(self, *args, **kwargs) self.engine = engine diff --git a/ipykernel/parentpoller.py b/ipykernel/parentpoller.py index 139b833e4..e48c5b4de 100644 --- a/ipykernel/parentpoller.py +++ b/ipykernel/parentpoller.py @@ -1,3 +1,4 @@ +"""A parent poller for unix.""" # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. @@ -22,10 +23,12 @@ class ParentPollerUnix(Thread): """ def __init__(self): + """Initialize the poller.""" super().__init__() self.daemon = True def run(self): + """Run the poller.""" # We cannot use os.waitpid because it works only for child processes. from errno import EINTR diff --git a/ipykernel/pickleutil.py b/ipykernel/pickleutil.py index ed7d4a7b8..8e2dbe5f3 100644 --- a/ipykernel/pickleutil.py +++ b/ipykernel/pickleutil.py @@ -118,6 +118,8 @@ def use_cloudpickle(): class CannedObject: + """A canned object.""" + def __init__(self, obj, keys=None, hook=None): """can an object for safe pickling @@ -145,6 +147,7 @@ def __init__(self, obj, keys=None, hook=None): self.buffers = [] def get_object(self, g=None): + """Get an object.""" if g is None: g = {} obj = self.obj @@ -161,15 +164,18 @@ class Reference(CannedObject): """object for wrapping a remote reference by name.""" def __init__(self, name): + """Initialize the reference.""" if not isinstance(name, str): raise TypeError("illegal name: %r" % name) self.name = name self.buffers = [] def __repr__(self): + """Get the string repr of the reference.""" return "" % self.name def get_object(self, g=None): + """Get an object in the reference.""" if g is None: g = {} @@ -180,19 +186,25 @@ class CannedCell(CannedObject): """Can a closure cell""" def __init__(self, cell): + """Initialize the canned cell.""" self.cell_contents = can(cell.cell_contents) def get_object(self, g=None): + """Get an object in the cell.""" cell_contents = uncan(self.cell_contents, g) def inner(): + """Inner function.""" return cell_contents return inner.__closure__[0] # type:ignore[index] class CannedFunction(CannedObject): + """Can a function.""" + def __init__(self, f): + """Initialize the can""" self._check_type(f) self.code = f.__code__ self.defaults: typing.Optional[typing.List[typing.Any]] @@ -216,6 +228,7 @@ def _check_type(self, obj): assert isinstance(obj, FunctionType), "Not a function type" def get_object(self, g=None): + """Get an object out of the can.""" # try to load function back into its module: if not self.module.startswith("__"): __import__(self.module) @@ -236,7 +249,10 @@ def get_object(self, g=None): class CannedClass(CannedObject): + """A canned class object.""" + def __init__(self, cls): + """Initialize the can.""" self._check_type(cls) self.name = cls.__name__ self.old_style = not isinstance(cls, type) @@ -256,12 +272,16 @@ def _check_type(self, obj): assert isinstance(obj, class_type), "Not a class type" def get_object(self, g=None): + """Get an object from the can.""" parents = tuple(uncan(p, g) for p in self.parents) return type(self.name, parents, uncan_dict(self._canned_dict, g=g)) class CannedArray(CannedObject): + """A canned numpy array.""" + def __init__(self, obj): + """Initialize the can.""" from numpy import ascontiguousarray self.shape = obj.shape @@ -283,6 +303,7 @@ def __init__(self, obj): self.buffers = [buffer(obj)] def get_object(self, g=None): + """Get the object.""" from numpy import frombuffer data = self.buffers[0] @@ -294,6 +315,8 @@ def get_object(self, g=None): class CannedBytes(CannedObject): + """A canned bytes object.""" + @staticmethod def wrap(buf: typing.Union[memoryview, bytes, typing.SupportsBytes]) -> bytes: """Cast a buffer or memoryview object to bytes""" @@ -304,18 +327,24 @@ def wrap(buf: typing.Union[memoryview, bytes, typing.SupportsBytes]) -> bytes: return buf def __init__(self, obj): + """Initialize the can.""" self.buffers = [obj] def get_object(self, g=None): + """Get the canned object.""" data = self.buffers[0] return self.wrap(data) class CannedBuffer(CannedBytes): + """A canned buffer.""" + wrap = buffer # type:ignore[assignment] class CannedMemoryView(CannedBytes): + """A canned memory view.""" + wrap = memoryview # type:ignore[assignment] @@ -377,6 +406,7 @@ def can(obj): def can_class(obj): + """Can a class object.""" if isinstance(obj, class_type) and obj.__module__ == "__main__": return CannedClass(obj) else: @@ -427,6 +457,7 @@ def uncan(obj, g=None): def uncan_dict(obj, g=None): + """Uncan a dict object.""" if istype(obj, dict): newobj = {} for k, v in obj.items(): @@ -437,6 +468,7 @@ def uncan_dict(obj, g=None): def uncan_sequence(obj, g=None): + """Uncan a sequence.""" if istype(obj, sequence_types): t = type(obj) return t([uncan(i, g) for i in obj]) diff --git a/ipykernel/tests/test_message_spec.py b/ipykernel/tests/test_message_spec.py index 1ba5f7651..5710cf297 100644 --- a/ipykernel/tests/test_message_spec.py +++ b/ipykernel/tests/test_message_spec.py @@ -252,9 +252,10 @@ class HistoryReply(Reply): "display_data": DisplayData(), "header": RHeader(), } -""" -Specifications of `content` part of the reply messages. -""" + +# ----------------------------------------------------------------------------- +# Specifications of `content` part of the reply messages. +# ----------------------------------------------------------------------------- def validate_message(msg, msg_type=None, parent=None): diff --git a/ipykernel/trio_runner.py b/ipykernel/trio_runner.py index 280501acf..333eb2461 100644 --- a/ipykernel/trio_runner.py +++ b/ipykernel/trio_runner.py @@ -1,3 +1,4 @@ +"""A trio loop runner.""" import builtins import logging import signal @@ -9,11 +10,15 @@ class TrioRunner: + """A trio loop runner.""" + def __init__(self): + """Initialize the runner.""" self._cell_cancel_scope = None self._trio_token = None def initialize(self, kernel, io_loop): + """Initialize the runner.""" kernel.shell.set_trio_runner(self) kernel.shell.run_line_magic("autoawait", "trio") kernel.shell.magics_manager.magics["line"]["autoawait"] = lambda _: warnings.warn( @@ -24,12 +29,14 @@ def initialize(self, kernel, io_loop): bg_thread.start() def interrupt(self, signum, frame): + """Interuppt the runner.""" if self._cell_cancel_scope: self._cell_cancel_scope.cancel() else: raise Exception("Kernel interrupted but no cell is running") def run(self): + """Run the loop.""" old_sig = signal.signal(signal.SIGINT, self.interrupt) def log_nursery_exc(exc): @@ -37,6 +44,7 @@ def log_nursery_exc(exc): logging.error("An exception occurred in a global nursery task.\n%s", exc) async def trio_main(): + """Run the main loop.""" self._trio_token = trio.lowlevel.current_trio_token() async with trio.open_nursery() as nursery: # TODO This hack prevents the nursery from cancelling all child @@ -49,7 +57,10 @@ async def trio_main(): signal.signal(signal.SIGINT, old_sig) def __call__(self, async_fn): + """Handle a function call.""" + async def loc(coro): + """A thread runner context.""" self._cell_cancel_scope = trio.CancelScope() with self._cell_cancel_scope: return await coro diff --git a/ipykernel/zmqshell.py b/ipykernel/zmqshell.py index ff418b863..2d08c1136 100644 --- a/ipykernel/zmqshell.py +++ b/ipykernel/zmqshell.py @@ -194,6 +194,8 @@ def unregister_hook(self, hook): @magics_class class KernelMagics(Magics): + """Kernel magics.""" + # ------------------------------------------------------------------------ # Magic overrides # ------------------------------------------------------------------------ @@ -467,6 +469,7 @@ def _update_exit_now(self, change): # Over ZeroMQ, GUI control isn't done with PyOS_InputHook as there is no # interactive input being read; we provide event loop support in ipkernel def enable_gui(self, gui): + """Enable a given guil.""" from .eventloops import enable_gui as real_enable_gui try: @@ -491,6 +494,7 @@ def init_environment(self): env["GIT_PAGER"] = "cat" def init_hooks(self): + """Initialize hooks.""" super().init_hooks() self.set_hook("show_in_pager", page.as_hook(payloadpage.page), 99) @@ -526,6 +530,7 @@ def ask_exit(self): self.payload_manager.write_payload(payload) def run_cell(self, *args, **kwargs): + """Run a cell.""" self._last_traceback = None return super().run_cell(*args, **kwargs) @@ -586,14 +591,17 @@ def set_parent(self, parent): pass def get_parent(self): + """Get the parent header.""" return self.parent_header def init_magics(self): + """Initialize magics.""" super().init_magics() self.register_magics(KernelMagics) self.magics_manager.register_alias("ed", "edit") def init_virtualenv(self): + """Initialize virtual environment.""" # Overridden not to do virtualenv detection, because it's probably # not appropriate in a kernel. To use a kernel in a virtualenv, install # it inside the virtualenv. diff --git a/pyproject.toml b/pyproject.toml index 9904b54b9..b35209add 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,8 @@ docs = [ "sphinx", "myst_parser", "pydata_sphinx_theme", - "sphinxcontrib_github_alt" + "sphinxcontrib_github_alt", + "sphinxcontrib-spelling" ] test = [ "pytest>=7.0", @@ -99,7 +100,7 @@ dependencies = ["mypy>=0.990"] test = "mypy --install-types --non-interactive {args:.}" [tool.hatch.envs.lint] -dependencies = ["black==22.10.0", "mdformat>0.7", "ruff==0.0.177"] +dependencies = ["black==22.10.0", "mdformat>0.7", "ruff==0.0.189"] detached = true [tool.hatch.envs.lint.scripts] style = [ @@ -250,3 +251,16 @@ unfixable = [ # N802 Function name `assertIn` should be lowercase # F841 Local variable `t` is assigned to but never used "ipykernel/tests/*" = ["B011", "F841", "C408", "E402", "T201", "B007", "N802", "F841"] + +[tool.interrogate] +ignore-init-module=true +ignore-private=true +ignore-semiprivate=true +ignore-property-decorators=true +ignore-nested-functions=true +ignore-nested-classes=true +fail-under=95 +exclude = ["docs", "*/tests"] + +[tool.check-wheel-contents] +toplevel = ["ipykernel/", "ipykernel_launcher.py"]