diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml index af7a0d6d3..deab0631b 100644 --- a/.github/workflows/downstream.yml +++ b/.github/workflows/downstream.yml @@ -10,45 +10,45 @@ concurrency: cancel-in-progress: true jobs: - tests: + ipykernel: runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - matrix: - python-version: ["3.9"] - fail-fast: false + timeout-minutes: 10 steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Base Setup - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - - - name: Test IPykernel - uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 + - uses: actions/checkout@v2 + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 with: package_name: ipykernel package_spec: "pyqt5 ipykernel[test]" - - name: Test NBClient - uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 + nbclient: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v2 + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 with: package_name: nbclient env_values: IPYKERNEL_CELL_NAME=\ - # Note: Currently fails - # - name: Test QtConsole - # uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 - # with: - # package_name: qtconsole - - - name: Test nbconvert - uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 + nbconvert: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v2 + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 with: package_name: nbconvert - - name: Test jupyter_server - uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 + jupyter_server: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v2 + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 with: package_name: jupyter_server diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 12eae70ca..f3e840b73 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -122,7 +122,7 @@ jobs: - name: Install miniumum versions uses: jupyterlab/maintainer-tools/.github/actions/install-minimums@v1 - name: Run the unit tests - run: pytest -vv jupyter_client || pytest -vv jupyter_client --lf + run: pytest -vv -W default jupyter_client || pytest -vv -W default jupyter_client --lf test_prereleases: name: Test Prereleases @@ -150,16 +150,8 @@ jobs: timeout-minutes: 10 steps: - uses: actions/checkout@v2 - - name: Base Setup - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - - name: Build SDist - run: | - pip install build - python -m build --sdist - - uses: actions/upload-artifact@v2 - with: - name: "sdist" - path: dist/*.tar.gz + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyterlab/maintainer-tools/.github/actions/make-sdist@v1 test_sdist: runs-on: ubuntu-latest @@ -167,19 +159,5 @@ jobs: name: Install from SDist and Test timeout-minutes: 20 steps: - - name: Base Setup - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - - name: Download sdist - uses: actions/download-artifact@v2 - - name: Install From SDist - run: | - set -ex - cd sdist - mkdir test - tar --strip-components=1 -zxvf *.tar.gz -C ./test - cd test - pip install .[test] - - name: Run Test - run: | - cd sdist/test - pytest -vv || pytest -vv --lf + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyterlab/maintainer-tools/.github/actions/test-sdist@v1 diff --git a/.mailmap b/.mailmap index bd6544e25..e39230250 100644 --- a/.mailmap +++ b/.mailmap @@ -26,7 +26,7 @@ David Hirschfeld dhirschfeld David P. Sanders David Warde-Farley David Warde-Farley <> Doug Blank Doug Blank -Eugene Van den Bulke Eugene Van den Bulke +Eugene Van den Bulke Eugene Van den Bulke Evan Patterson Evan Patterson Evan Patterson diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cf55d0568..364892699 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,25 +1,61 @@ +ci: + skip: [check-jsonschema] + repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.1.0 + hooks: + - id: end-of-file-fixer + - id: check-case-conflict + - id: check-executables-have-shebangs + - id: requirements-txt-fixer + - id: check-added-large-files + - id: check-case-conflict + - id: check-toml + - id: check-yaml + - id: debug-statements + - id: forbid-new-submodules + - id: check-builtin-literals + - id: trailing-whitespace + - repo: https://github.com/asottile/reorder_python_imports - rev: v2.7.1 + rev: v3.0.1 hooks: - id: reorder-python-imports + - repo: https://github.com/psf/black - rev: 22.1.0 + rev: 22.3.0 hooks: - id: black args: ["--line-length", "100"] + - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.5.1 + rev: v2.6.1 hooks: - id: prettier - - repo: https://gitlab.com/pycqa/flake8 - rev: "3.9.2" + + - repo: https://github.com/pycqa/flake8 + rev: 4.0.1 hooks: - id: flake8 - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 + additional_dependencies: + [ + "flake8-bugbear==20.1.4", + "flake8-logging-format==0.6.0", + "flake8-implicit-str-concat==0.2.0", + ] + + - repo: https://github.com/PyCQA/doc8 + rev: 0.11.0 hooks: - - id: end-of-file-fixer - - id: check-case-conflict - - id: check-executables-have-shebangs - - id: requirements-txt-fixer + - id: doc8 + args: [--max-line-length=100] + + - repo: https://github.com/sirosen/check-jsonschema + rev: 0.14.2 + hooks: + - id: check-jsonschema + name: "Check GitHub Workflows" + files: ^\.github/workflows/ + types: [yaml] + args: ["--schemafile", "https://json.schemastore.org/github-workflow"] diff --git a/docs/kernels.rst b/docs/kernels.rst index d4f39e7c5..c8b7060e0 100644 --- a/docs/kernels.rst +++ b/docs/kernels.rst @@ -121,7 +121,9 @@ The user location takes priority over the system locations, and the case of the names is ignored, so selecting kernels works the same way whether or not the filesystem is case sensitive. Since kernelspecs show up in URLs and other places, -a kernelspec is required to have a simple name, only containing ASCII letters, ASCII numbers, and the simple separators: ``-`` hyphen, ``.`` period, ``_`` underscore. +a kernelspec is required to have a simple name, only containing ASCII letters, +ASCII numbers, and the simple separators: ``-`` hyphen, ``.`` period, ``_`` +underscore. Other locations may also be searched if the :envvar:`JUPYTER_PATH` environment variable is set. @@ -143,7 +145,8 @@ JSON serialised dictionary containing the following keys and values: When loading notebooks, if no matching kernelspec key (may differ across machines) is found, a kernel with a matching `language` will be used. This allows a notebook written on any Python or Julia kernel to be properly associated - with the user's Python or Julia kernel, even if they aren't listed under the same name as the author's. + with the user's Python or Julia kernel, even if they aren't listed under the + same name as the author's. - **interrupt_mode** (optional): May be either ``signal`` or ``message`` and specifies how a client is supposed to interrupt cell execution on this kernel, either by sending an interrupt ``signal`` via the operating system's diff --git a/docs/messaging.rst b/docs/messaging.rst index 5ae5965f5..22c426ffa 100644 --- a/docs/messaging.rst +++ b/docs/messaging.rst @@ -73,7 +73,7 @@ kernel has dedicated sockets for the following functions: appropriately. 4. **Control**: This channel is identical to Shell, but operates on a separate - socket to avoid queueing behind execution requests. The control channel is + socket to avoid queueing behind execution requests. The control channel is used for shutdown and restart messages, as well as for debugging messages. For a smoother user experience, we recommend running the control channel in @@ -100,8 +100,10 @@ The message `header` contains information about the message, such as unique identifiers for the originating session and the actual message id, the type of message, the version of the Jupyter protocol, and the date the message was created. -In addition, there is a username field, e.g. for the process that generated the message, if applicable. -This can be useful in collaborative settings where multiple users may be interacting with the same kernel simultaneously, +In addition, there is a username field, e.g. for the process that generated the +message, if applicable. +This can be useful in collaborative settings where multiple users may be +interacting with the same kernel simultaneously, so that frontends can label the various messages in a meaningful way. .. sourcecode:: python @@ -173,7 +175,8 @@ Metadata -------- The `metadata` dict contains information about the message that is not part of the content. -This is not often used, but can be an extra location to store information about requests and replies, +This is not often used, but can be an extra location to store information about +requests and replies, such as extensions adding information about request or execution context. Content @@ -254,7 +257,8 @@ but does not describe the actual *implementation* at the wire level in zeromq. This section describes the protocol that must be implemented by Jupyter kernels and clients talking to each other over zeromq. -The reference implementation of the message spec is our :class:`~jupyter_client.session.Session` class. +The reference implementation of the message spec is our +:class:`~jupyter_client.session.Session` class. .. note:: @@ -372,16 +376,20 @@ Request-Reply In general, the ROUTER/DEALER sockets follow a request-reply pattern: -The client sends an ``_request`` message (such as ``execute_request``) on its shell (DEALER) socket. +The client sends an ``_request`` message (such as ``execute_request``) +on its shell (DEALER) socket. The kernel receives that request and immediately publishes a ``status: busy`` message on IOPub. -The kernel then processes the request and sends the appropriate ``_reply`` message, such as ``execute_reply``. +The kernel then processes the request and sends the appropriate +``_reply`` message, such as ``execute_reply``. After processing the request and publishing associated IOPub messages, if any, the kernel publishes a ``status: idle`` message. -This idle status message indicates that IOPub messages associated with a given request have all been received. +This idle status message indicates that IOPub messages associated with a given +request have all been received. All reply messages have a ``'status'`` field, which will have one of the following values: -- ``status='ok'``: The request was processed successfully, and the remaining content of the reply is specified in the appropriate section below. +- ``status='ok'``: The request was processed successfully, and the remaining + content of the reply is specified in the appropriate section below. - ``status='error'``: The request failed due to an error. When status is 'error', the usual content of a successful reply should be omitted, instead the following fields should be present:: @@ -1115,7 +1123,8 @@ Message type: ``debug_reply``:: The ``content`` dicts of the `debug_request` and `debug_reply` messages respectively follow the specification of the `Request` and `Response` messages from the `Debug Adapter Protocol (DAP) `_ as of version 1.39 or later. -Debug requests and replies are sent over the `control` channel to prevent queuing behind execution requests. +Debug requests and replies are sent over the `control` channel to prevent +queuing behind execution requests. Additions to the DAP ~~~~~~~~~~~~~~~~~~~~ @@ -1126,7 +1135,9 @@ The Jupyter debugger protocol makes several additions to the DAP: - the `debugInfo` request and response messages - the `inspectVariables` request and response messages -In order to support the debugging of notebook cells and of Jupyter consoles, which are not based on source files, we need a message to submit code to the debugger to which breakpoints can be added. +In order to support the debugging of notebook cells and of Jupyter consoles, +which are not based on source files, we need a message to submit code to the +debugger to which breakpoints can be added. Content of the `dumpCell` request:: @@ -1148,7 +1159,10 @@ In order to support the debugging of notebook cells and of Jupyter consoles, whi } } -In order to support page reloading, or a client connecting at a later stage, Jupyter kernels must store the state of the debugger (such as breakpoints, whether the debugger is currently stopped). The `debugInfo` request is a DAP `Request` with no extra argument. +In order to support page reloading, or a client connecting at a later stage, +Jupyter kernels must store the state of the debugger (such as breakpoints, +whether the debugger is currently stopped). The `debugInfo` request is a DAP +`Request` with no extra argument. Content of the `debugInfo` request:: @@ -1176,13 +1190,15 @@ In order to support page reloading, or a client connecting at a later stage, Jup ], 'stoppedThreads' : list(int), # threads in which the debugger is currently in a stopped state 'richRendering' : bool, # whether the debugger supports rich rendering of variables - 'exceptionPaths' : list(str), # exception names used to match leaves or nodes in a tree of exception + 'exceptionPaths' : list(str), # exception names used to match leaves or nodes in a tree of exception } } The `source_breakpoint` schema is specified by the Debug Adapter Protocol. -The `inspectVariables` is meant to retrieve the values of all the variables that have been defined in the kernel. It is a DAP `Request` with no extra argument. +The `inspectVariables` is meant to retrieve the values of all the variables +that have been defined in the kernel. It is a DAP `Request` with no extra +argument. Content of the `inspectVariables` request:: @@ -1208,7 +1224,8 @@ The `inspectVariables` is meant to retrieve the values of all the variables that } } -The ``richInspectVariables`` request allows to get the rich representation of a variable that has been defined in the kernel. +The ``richInspectVariables`` request allows to get the rich representation of a +variable that has been defined in the kernel. Content of the ``richInspectVariables`` request:: @@ -1598,7 +1615,8 @@ Custom Messages .. versionadded:: 4.1 -Message spec 4.1 (IPython 2.0) added a messaging system for developers to add their own objects with Frontend +Message spec 4.1 (IPython 2.0) added a messaging system for developers to add +their own objects with Frontend and Kernel-side components, and allow them to communicate with each other. To do this, IPython adds a notion of a ``Comm``, which exists on both sides, and can communicate in either direction. @@ -1623,7 +1641,8 @@ The code handling the message on the receiving side is responsible for maintaini of target_name keys to constructors. After a ``comm_open`` message has been sent, there should be a corresponding Comm instance on both sides. -The ``data`` key is always a dict and can be any extra JSON information used in initialization of the comm. +The ``data`` key is always a dict and can be any extra JSON information used in +initialization of the comm. If the ``target_name`` key is not found on the receiving side, then it should immediately reply with a ``comm_close`` message to avoid an inconsistent state. @@ -1635,7 +1654,8 @@ Comm Messages Comm messages are one-way communications to update comm state, used for synchronizing widget state, or simply requesting actions of a comm's counterpart. -Essentially, each comm pair defines their own message specification implemented inside the ``data`` dict. +Essentially, each comm pair defines their own message specification implemented +inside the ``data`` dict. There are no expected replies (of course, one side can send another ``comm_msg`` in reply). @@ -1740,12 +1760,14 @@ Kernel info: Execution: -- ``user_variables`` is removed from ``execute_request/reply`` because it is redundant with ``user_expressions`` +- ``user_variables`` is removed from ``execute_request/reply`` because it is + redundant with ``user_expressions`` - ``password`` key added to ``input_request`` Output: -- ``data`` key in stream messages renamed to ``text`` for consistency with the notebook format. +- ``data`` key in stream messages renamed to ``text`` for consistency with the + notebook format. - ``application/json`` in mimebundles should be unpacked JSON data, not a double-serialized JSON string. @@ -1758,7 +1780,8 @@ Inspection: Completion: -- ``complete_request``: ``line``, ``block``, and ``text`` keys are removed in favor of a single ``code`` for context. +- ``complete_request``: ``line``, ``block``, and ``text`` keys are removed in + favor of a single ``code`` for context. Lexing is up to the kernel. - ``complete_reply``: - ``matched_text`` is removed in favor of ``cursor_start`` and ``cursor_end``. @@ -1769,7 +1792,8 @@ Completion: --- - ``comm_open/close/msg`` messages added -- ``clear_output``: ``stdout``, ``stderr``, and ``display`` boolean keys for selective clearing are removed, +- ``clear_output``: ``stdout``, ``stderr``, and ``display`` boolean keys for + selective clearing are removed, and ``wait`` is added. The selective clearing keys are ignored in v4 and the default behavior remains the same, so v4 ``clear_output`` messages will be safely handled by a v4.1 frontend. @@ -1785,7 +1809,8 @@ Notes Many frontends, especially those implemented in javascript, reported cursor_pos as the interpreter's string index, -which is not the same as the unicode character offset if the interpreter uses UTF-16 (e.g. javascript or Python 2 on macOS), +which is not the same as the unicode character offset if the interpreter uses +UTF-16 (e.g. javascript or Python 2 on macOS), which stores "astral-plane" characters such as ``𝐚 (U+1D41A)`` as surrogate pairs, taking up two indices instead of one, causing a unicode offset drift of one per astral-plane character. @@ -1797,11 +1822,16 @@ for frontends that did the right thing. For this reason, in protocol versions prior to 5.2, ``cursor_pos`` is officially ambiguous in the presence of astral plane unicode characters. -Frontends claiming to implement protocol 5.2 **MUST** identify cursor_pos as the encoding-independent unicode character offset. -Kernels may choose to expect the UTF-16 offset from requests implementing protocol 5.1 and earlier, in order to behave correctly with the most popular frontends. -But they should know that doing so *introduces* the inverse bug for the frontends that do not have this bug. - -As an example, use a python3 kernel and evaluate ``𨭎𨭎𨭎𨭎𨭎 = 10``. Then type ``𨭎𨭎`` followed by the tab key and see if it properly completes. +Frontends claiming to implement protocol 5.2 **MUST** identify cursor_pos as +the encoding-independent unicode character offset. +Kernels may choose to expect the UTF-16 offset from requests implementing +protocol 5.1 and earlier, in order to behave correctly with the most popular +frontends. +But they should know that doing so *introduces* the inverse bug for the +frontends that do not have this bug. + +As an example, use a python3 kernel and evaluate ``𨭎𨭎𨭎𨭎𨭎 = 10``. Then type +``𨭎𨭎`` followed by the tab key and see if it properly completes. Known affected frontends (as of 2017-06): diff --git a/docs/pending-kernels.rst b/docs/pending-kernels.rst index 4699feb0a..03a161e3f 100644 --- a/docs/pending-kernels.rst +++ b/docs/pending-kernels.rst @@ -3,14 +3,19 @@ Pending Kernels *Added in 7.1.0* -In scenarios where an kernel takes a long time to start (e.g. kernels running remotely), it can be advantageous to immediately return the kernel's model and ID from key methods like ``.start_kernel()`` and ``.shutdown_kernel()``. The kernel will continue its task without blocking other managerial actions. +In scenarios where an kernel takes a long time to start (e.g. kernels running +remotely), it can be advantageous to immediately return the kernel's model and +ID from key methods like ``.start_kernel()`` and ``.shutdown_kernel()``. The +kernel will continue its task without blocking other managerial actions. This intermediate state is called a **"pending kernel"**. How they work ------------- -When ``.start_kernel()`` or ``.shutdown_kernel()`` is called, a ``Future`` is created under the ``KernelManager.ready`` property. This property can be awaited anytime to ensure that the kernel moves out of its pending state, e.g.: +When ``.start_kernel()`` or ``.shutdown_kernel()`` is called, a ``Future`` is +created under the ``KernelManager.ready`` property. This property can be +awaited anytime to ensure that the kernel moves out of its pending state, e.g.: .. code-block:: python @@ -19,18 +24,26 @@ When ``.start_kernel()`` or ``.shutdown_kernel()`` is called, a ``Future`` is cr # of its pending state. await kernel_manager.ready -Once the kernel is finished pending, ``.ready.done()`` will be ``True`` and either 1) ``.ready.result()`` will return ``None`` or 2) ``.ready.exception()`` will return a raised exception +Once the kernel is finished pending, ``.ready.done()`` will be ``True`` and +either 1) ``.ready.result()`` will return ``None`` or 2) ``.ready.exception()`` +will return a raised exception Using pending kernels --------------------- -The most common way to interact with pending kernels is through the ``MultiKernelManager``—the object that manages a collection of kernels—by setting its ``use_pending_kernels`` trait to ``True``. Pending kernels are "opt-in"; they are not used by default in the ``MultiKernelManager``. +The most common way to interact with pending kernels is through the `` +MultiKernelManager``—the object that manages a collection of kernels—by setting +its ``use_pending_kernels`` trait to ``True``. Pending kernels are "opt-in"; +they are not used by default in the ``MultiKernelManager``. -When ``use_pending_kernels`` is ``True``, the following changes are made to the ``MultiKernelManager``: +When ``use_pending_kernels`` is ``True``, the following changes are made to the +``MultiKernelManager``: -1. ``start_kernel`` and ``stop_kernel`` return immediately while running the pending task in a background thread. +1. ``start_kernel`` and ``stop_kernel`` return immediately while running the + pending task in a background thread. 2. The following methods raise a ``RuntimeError`` if a kernel is pending: * ``restart_kernel`` * ``interrupt_kernel`` * ``shutdown_kernel`` -3. ``shutdown_all`` will wait for all pending kernels to become ready before attempting to shut them down. +3. ``shutdown_all`` will wait for all pending kernels to become ready before + attempting to shut them down. diff --git a/docs/provisioning.rst b/docs/provisioning.rst index d3586dd86..de1eb4500 100644 --- a/docs/provisioning.rst +++ b/docs/provisioning.rst @@ -139,7 +139,8 @@ behavior, there's a good chance you can simply extend custom functionality. In this example, RBACProvisioner will verify whether the current user is -in the role meant for this kernel by calling a method implemented within *this* provisioner. If the user is not in the role, an exception will be thrown. +in the role meant for this kernel by calling a method implemented within *this* +provisioner. If the user is not in the role, an exception will be thrown. .. code:: python diff --git a/docs/wrapperkernels.rst b/docs/wrapperkernels.rst index ed7a7a8e7..00717f447 100644 --- a/docs/wrapperkernels.rst +++ b/docs/wrapperkernels.rst @@ -14,7 +14,9 @@ such as bash. A simple kernel for bash, written using this machinery The `Metakernel `_ library makes it easier to -write a wrapper kernel that includes a base set of line and cell magics. It also has a ``ProcessKernel`` subclass that makes it easy to write kernels that use ``pexpect``. +write a wrapper kernel that includes a base set of line and cell magics. It +also has a ``ProcessKernel`` subclass that makes it easy to write kernels that +use ``pexpect``. See `Octave Kernel `_ as an example. diff --git a/jupyter_client/connect.py b/jupyter_client/connect.py index 7ca56292f..1b81585f2 100644 --- a/jupyter_client/connect.py +++ b/jupyter_client/connect.py @@ -117,7 +117,7 @@ def write_connection_file( + int(hb_port <= 0) ) if transport == "tcp": - for i in range(ports_needed): + for _ in range(ports_needed): sock = socket.socket() # struct.pack('ii', (0,0)) is 8 null bytes sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, b"\0" * 8) @@ -129,7 +129,7 @@ def write_connection_file( ports.append(port) else: N = 1 - for i in range(ports_needed): + for _ in range(ports_needed): while os.path.exists("%s-%s" % (ip, str(N))): N += 1 ports.append(N) @@ -450,7 +450,7 @@ def cleanup_connection_file(self) -> None: self._connection_file_written = False try: os.remove(self.connection_file) - except (IOError, OSError, AttributeError): + except (OSError, AttributeError): pass def cleanup_ipc_files(self) -> None: @@ -461,7 +461,7 @@ def cleanup_ipc_files(self) -> None: ipcfile = "%s-%i" % (self.ip, port) try: os.remove(ipcfile) - except (IOError, OSError): + except OSError: pass def _record_random_port_names(self) -> None: diff --git a/jupyter_client/kernelspec.py b/jupyter_client/kernelspec.py index 8d83842ea..5a1796ef4 100644 --- a/jupyter_client/kernelspec.py +++ b/jupyter_client/kernelspec.py @@ -412,7 +412,7 @@ def install_kernel_spec( def install_native_kernel_spec(self, user=False): """DEPRECATED: Use ipykernel.kernelspec.install""" warnings.warn( - "install_native_kernel_spec is deprecated." " Use ipykernel.kernelspec import install.", + "install_native_kernel_spec is deprecated. Use ipykernel.kernelspec import install.", stacklevel=2, ) from ipykernel.kernelspec import install diff --git a/jupyter_client/launcher.py b/jupyter_client/launcher.py index 818b4c81a..72399a5f0 100644 --- a/jupyter_client/launcher.py +++ b/jupyter_client/launcher.py @@ -157,7 +157,7 @@ def launch_kernel( proc = Popen(cmd, **kwargs) except Exception as ex: try: - msg = "Failed to run command:\n{}\n" " PATH={!r}\n" " with kwargs:\n{!r}\n" + msg = "Failed to run command:\n{}\n PATH={!r}\n with kwargs:\n{!r}\n" # exclude environment variables, # which may contain access tokens and the like. without_env = {key: value for key, value in kwargs.items() if key != "env"} diff --git a/jupyter_client/localinterfaces.py b/jupyter_client/localinterfaces.py index 80f96a324..70906fd04 100644 --- a/jupyter_client/localinterfaces.py +++ b/jupyter_client/localinterfaces.py @@ -102,7 +102,7 @@ def _load_ips_ifconfig(): try: out = _get_output("ifconfig") - except (IOError, OSError): + except OSError: # no ifconfig, it's usually in /sbin and /sbin is not on everyone's PATH out = _get_output("/sbin/ifconfig") @@ -237,16 +237,16 @@ def _load_ips(suppress_exceptions=True): if os.name == "nt": try: return _load_ips_ipconfig() - except (IOError, NoIPAddresses): + except (OSError, NoIPAddresses): pass else: try: return _load_ips_ip() - except (IOError, OSError, NoIPAddresses): + except (OSError, NoIPAddresses): pass try: return _load_ips_ifconfig() - except (IOError, OSError, NoIPAddresses): + except (OSError, NoIPAddresses): pass # lowest priority, use gethostbyname diff --git a/jupyter_client/manager.py b/jupyter_client/manager.py index 969985ab9..a9054aa56 100644 --- a/jupyter_client/manager.py +++ b/jupyter_client/manager.py @@ -519,7 +519,7 @@ async def _async_restart_kernel(self, now: bool = False, newports: bool = False, kernel. """ if self._launch_args is None: - raise RuntimeError("Cannot restart the kernel. " "No previous call to 'start_kernel'.") + raise RuntimeError("Cannot restart the kernel. No previous call to 'start_kernel'.") # Stop currently running kernel. await ensure_async(self.shutdown_kernel(now=now, restart=True)) diff --git a/jupyter_client/provisioning/provisioner_base.py b/jupyter_client/provisioning/provisioner_base.py index f01f035d4..749f28dcd 100644 --- a/jupyter_client/provisioning/provisioner_base.py +++ b/jupyter_client/provisioning/provisioner_base.py @@ -185,7 +185,7 @@ async def get_provisioner_info(self) -> Dict[str, Any]: NOTE: The superclass method must always be called first to ensure proper serialization. """ - provisioner_info: Dict[str, Any] = dict() + provisioner_info: Dict[str, Any] = {} provisioner_info['kernel_id'] = self.kernel_id provisioner_info['connection_info'] = self.connection_info return provisioner_info diff --git a/jupyter_client/session.py b/jupyter_client/session.py index e56b4f861..fff2e31f5 100644 --- a/jupyter_client/session.py +++ b/jupyter_client/session.py @@ -968,7 +968,7 @@ def feed_identities( else: msg_list = t.cast(t.List[zmq.Message], msg_list) failed = True - for idx, m in enumerate(msg_list): + for idx, m in enumerate(msg_list): # noqa if m.bytes == DELIM: failed = False break diff --git a/jupyter_client/ssh/tunnel.py b/jupyter_client/ssh/tunnel.py index 40826c736..02b23f0a6 100644 --- a/jupyter_client/ssh/tunnel.py +++ b/jupyter_client/ssh/tunnel.py @@ -41,7 +41,7 @@ def select_random_ports(n): """Select and return n random ports that are available.""" ports = [] sockets = [] - for i in range(n): + for _ in range(n): sock = socket.socket() sock.bind(("", 0)) ports.append(sock.getsockname()[1]) diff --git a/jupyter_client/tests/test_adapter.py b/jupyter_client/tests/test_adapter.py index c54217f10..9f45c0267 100644 --- a/jupyter_client/tests/test_adapter.py +++ b/jupyter_client/tests/test_adapter.py @@ -314,7 +314,7 @@ def test_complete_request(self): msg = self.msg( "complete_request", { - "code": "def foo():\n" " a.is\n" "foo()", + "code": "def foo():\n a.is\nfoo()", "cursor_pos": 19, }, ) @@ -352,7 +352,7 @@ def test_inspect_request(self): msg = self.msg( "inspect_request", { - "code": "def foo():\n" " apple\n" "bar()", + "code": "def foo():\n apple\nbar()", "cursor_pos": 18, "detail_level": 1, }, diff --git a/jupyter_client/tests/test_connect.py b/jupyter_client/tests/test_connect.py index 8fbe0f2a8..7075c9d91 100644 --- a/jupyter_client/tests/test_connect.py +++ b/jupyter_client/tests/test_connect.py @@ -35,8 +35,8 @@ def __exit__(self, exc, value, tb): class DummyConsoleApp(JupyterApp, JupyterConsoleApp): - def initialize(self, argv=[]): - JupyterApp.initialize(self, argv=argv) + def initialize(self, argv=None): + JupyterApp.initialize(self, argv=argv or []) self.init_connection_file() diff --git a/jupyter_client/tests/test_kernelmanager.py b/jupyter_client/tests/test_kernelmanager.py index 13a6f5422..f71d74209 100644 --- a/jupyter_client/tests/test_kernelmanager.py +++ b/jupyter_client/tests/test_kernelmanager.py @@ -45,7 +45,7 @@ def config(transport): def _install_kernel(name="signaltest", extra_env=None): if extra_env is None: - extra_env = dict() + extra_env = {} kernel_dir = pjoin(paths.jupyter_data_dir(), "kernels", name) os.makedirs(kernel_dir) with open(pjoin(kernel_dir, "kernel.json"), "w") as f: diff --git a/jupyter_client/tests/test_restarter.py b/jupyter_client/tests/test_restarter.py index eb66c9630..54d8283cd 100644 --- a/jupyter_client/tests/test_restarter.py +++ b/jupyter_client/tests/test_restarter.py @@ -19,7 +19,7 @@ def _install_kernel(name="problemtest", extra_env=None): if extra_env is None: - extra_env = dict() + extra_env = {} kernel_dir = pjoin(paths.jupyter_data_dir(), "kernels", name) os.makedirs(kernel_dir) with open(pjoin(kernel_dir, "kernel.json"), "w") as f: diff --git a/jupyter_client/threaded.py b/jupyter_client/threaded.py index 54e44a3d7..f7f49ae06 100644 --- a/jupyter_client/threaded.py +++ b/jupyter_client/threaded.py @@ -164,7 +164,7 @@ def flush(self, timeout: float = 1.0) -> None: # gets to perform at least one full poll. stop_time = time.time() + timeout assert self.ioloop is not None - for i in range(2): + for _ in range(2): self._flushed = False self.ioloop.add_callback(self._flush) while not self._flushed and time.time() < stop_time: diff --git a/pyproject.toml b/pyproject.toml index 8a0cf3c0a..ec1e4c659 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,15 +49,9 @@ filterwarnings= [ # (To be fixed in Tornado 6.2) "ignore:There is no current event loop:DeprecationWarning:tornado", - # Workaround for distutils.Version used in ipykernel - "ignore:The distutils package is deprecated and slated for removal:DeprecationWarning:ipykernel", - # ZMQ uses Future internally, which raises a DeprecationWarning # When there is no loop running. # We could eventually find a way to make sure these are only created # when there is a running event loop. "ignore:There is no current event loop:DeprecationWarning:zmq", - - # Workaround for imp used in ipykernel - "ignore:the imp module is deprecated in favour of importlib:DeprecationWarning" ] diff --git a/setup.cfg b/setup.cfg index 725b0b2fe..be4af3a75 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,8 +1,21 @@ [flake8] -max-line-length = 100 - -[nosetests] -warningfilters=default +ignore = E501, W503, E402 +builtins = c, get_config +exclude = + .cache, + .github, + docs, + setup.py +enable-extensions = G +extend-ignore = + G001, G002, G004, G200, G201, G202, + # black adds spaces around ':' + E203, +per-file-ignores = + # B011: Do not call assert False since python -O removes these calls + # F841 local variable 'foo' is assigned to but never used + # B007 Loop control variable + jupyter_client/tests/*: B011, F841, B007 [metadata] name = jupyter_client