Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-ipykernel for
openSUSE:Factory checked in at 2023-06-04 00:12:32
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ipykernel (Old)
and /work/SRC/openSUSE:Factory/.python-ipykernel.new.15902 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-ipykernel"
Sun Jun 4 00:12:32 2023 rev:37 rq:1090502 version:6.23.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-ipykernel/python-ipykernel.changes
2023-04-04 21:27:51.331725423 +0200
+++
/work/SRC/openSUSE:Factory/.python-ipykernel.new.15902/python-ipykernel.changes
2023-06-04 00:12:42.273570604 +0200
@@ -1,0 +2,11 @@
+Fri Jun 2 12:42:05 UTC 2023 - Ben Greiner <[email protected]>
+
+- Update to 6.23.1
+ * Avoid echoing onto a captured FD #1111 (@minrk)
+- Release 6.23.0
+ * Support control<>iopub messages to e.g. unblock comm_msg from
+ command execution #1114 (@tkrabel-db)
+ * Add outstream hook similar to display publisher #1110
+ (@maartenbreddels)
+
+-------------------------------------------------------------------
Old:
----
ipykernel-6.22.0.tar.gz
New:
----
ipykernel-6.23.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-ipykernel.spec ++++++
--- /var/tmp/diff_new_pack.RJ7VWM/_old 2023-06-04 00:12:42.933574550 +0200
+++ /var/tmp/diff_new_pack.RJ7VWM/_new 2023-06-04 00:12:42.937574573 +0200
@@ -17,7 +17,7 @@
Name: python-ipykernel
-Version: 6.22.0
+Version: 6.23.1
Release: 0
Summary: IPython Kernel for Jupyter
License: BSD-3-Clause
++++++ ipykernel-6.22.0.tar.gz -> ipykernel-6.23.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/.github/workflows/ci.yml
new/ipykernel-6.23.1/.github/workflows/ci.yml
--- old/ipykernel-6.22.0/.github/workflows/ci.yml 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/.github/workflows/ci.yml 2020-02-02
01:00:00.000000000 +0100
@@ -57,17 +57,24 @@
run: |
hatch run cov:nowarn || hatch run test:nowarn --lf
- - name: Coverage
- run: |
- pip install codecov coverage[toml]
- codecov
-
- name: Check Launcher
run: |
pip install .
cd $HOME
python -m ipykernel_launcher --help
+ - uses: jupyterlab/maintainer-tools/.github/actions/upload-coverage@v1
+
+ coverage:
+ runs-on: ubuntu-latest
+ needs:
+ - build
+ steps:
+ - uses: actions/checkout@v3
+ - uses: jupyterlab/maintainer-tools/.github/actions/report-coverage@v1
+ with:
+ fail_under: 80
+
test_lint:
name: Test Lint
runs-on: ubuntu-latest
@@ -143,6 +150,11 @@
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
with:
dependency_type: minimum
+
+ - name: List installed packages
+ run: |
+ hatch run test:list
+
- name: Run the unit tests
run: |
hatch run test:nowarn || hatch run test:nowarn --lf
@@ -190,7 +202,7 @@
tests_check: # This job does nothing and is only used for the branch
protection
if: always()
needs:
- - build
+ - coverage
- test_docs
- test_without_debugpy
- test_miniumum_versions
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/.pre-commit-config.yaml
new/ipykernel-6.23.1/.pre-commit-config.yaml
--- old/ipykernel-6.22.0/.pre-commit-config.yaml 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/.pre-commit-config.yaml 2020-02-02
01:00:00.000000000 +0100
@@ -21,7 +21,7 @@
- id: trailing-whitespace
- repo: https://github.com/python-jsonschema/check-jsonschema
- rev: 0.21.0
+ rev: 0.22.0
hooks:
- id: check-github-workflows
@@ -31,12 +31,12 @@
- id: mdformat
- repo: https://github.com/psf/black
- rev: 23.1.0
+ rev: 23.3.0
hooks:
- id: black
- repo: https://github.com/charliermarsh/ruff-pre-commit
- rev: v0.0.254
+ rev: v0.0.263
hooks:
- id: ruff
args: ["--fix"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/.readthedocs.yaml
new/ipykernel-6.23.1/.readthedocs.yaml
--- old/ipykernel-6.22.0/.readthedocs.yaml 2020-02-02 01:00:00.000000000
+0100
+++ new/ipykernel-6.23.1/.readthedocs.yaml 2020-02-02 01:00:00.000000000
+0100
@@ -1,8 +1,14 @@
version: 2
+
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.11"
+
sphinx:
configuration: docs/conf.py
+
python:
- version: 3.8
install:
# install itself with pip install .
- method: pip
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/CHANGELOG.md
new/ipykernel-6.23.1/CHANGELOG.md
--- old/ipykernel-6.22.0/CHANGELOG.md 2020-02-02 01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/CHANGELOG.md 2020-02-02 01:00:00.000000000 +0100
@@ -2,6 +2,45 @@
<!-- <START NEW CHANGELOG ENTRY> -->
+## 6.23.1
+
+([Full
Changelog](https://github.com/ipython/ipykernel/compare/v6.23.0...d63c33afb9872f2781997b2428d7e9e0c1d23d41))
+
+### Bugs fixed
+
+- Avoid echoing onto a captured FD
[#1111](https://github.com/ipython/ipykernel/pull/1111)
([@minrk](https://github.com/minrk))
+
+### Maintenance and upkeep improvements
+
+- update readthedocs env to 3.11
[#1117](https://github.com/ipython/ipykernel/pull/1117)
([@minrk](https://github.com/minrk))
+
+### Contributors to this release
+
+([GitHub contributors page for this
release](https://github.com/ipython/ipykernel/graphs/contributors?from=2023-05-08&to=2023-05-15&type=c))
+
+[@minrk](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aminrk+updated%3A2023-05-08..2023-05-15&type=Issues)
+
+<!-- <END NEW CHANGELOG ENTRY> -->
+
+## 6.23.0
+
+([Full
Changelog](https://github.com/ipython/ipykernel/compare/v6.22.0...3dd6dc9712ff6eb0a53cf79969dcefa0ba1b086e))
+
+### Enhancements made
+
+- Support control\<>iopub messages to e.g. unblock comm_msg from command
execution [#1114](https://github.com/ipython/ipykernel/pull/1114)
([@tkrabel-db](https://github.com/tkrabel-db))
+- Add outstream hook similar to display publisher
[#1110](https://github.com/ipython/ipykernel/pull/1110)
([@maartenbreddels](https://github.com/maartenbreddels))
+
+### Maintenance and upkeep improvements
+
+- Use local coverage [#1109](https://github.com/ipython/ipykernel/pull/1109)
([@blink1073](https://github.com/blink1073))
+
+### Contributors to this release
+
+([GitHub contributors page for this
release](https://github.com/ipython/ipykernel/graphs/contributors?from=2023-03-20&to=2023-05-08&type=c))
+
+[@blink1073](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Ablink1073+updated%3A2023-03-20..2023-05-08&type=Issues)
|
[@maartenbreddels](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Amaartenbreddels+updated%3A2023-03-20..2023-05-08&type=Issues)
|
[@pre-commit-ci](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Apre-commit-ci+updated%3A2023-03-20..2023-05-08&type=Issues)
|
[@tkrabel-db](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Atkrabel-db+updated%3A2023-03-20..2023-05-08&type=Issues)
+
## 6.22.0
([Full
Changelog](https://github.com/ipython/ipykernel/compare/v6.21.3...e2972d763b5357d4e1cb9b5355593583ca6d5657))
@@ -18,8 +57,6 @@
[@martinRenou](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3AmartinRenou+updated%3A2023-03-06..2023-03-20&type=Issues)
|
[@pre-commit-ci](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Apre-commit-ci+updated%3A2023-03-06..2023-03-20&type=Issues)
-<!-- <END NEW CHANGELOG ENTRY> -->
-
## 6.21.3
([Full
Changelog](https://github.com/ipython/ipykernel/compare/v6.21.2...e46f75b93c388886f4b6ba32182e29c3cc486984))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/PKG-INFO
new/ipykernel-6.23.1/PKG-INFO
--- old/ipykernel-6.22.0/PKG-INFO 2020-02-02 01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/PKG-INFO 2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: ipykernel
-Version: 6.22.0
+Version: 6.23.1
Summary: IPython Kernel for Jupyter
Project-URL: Homepage, https://ipython.org
Author-email: IPython Development Team <[email protected]>
@@ -91,7 +91,6 @@
# IPython Kernel for Jupyter
[](https://github.com/ipython/ipykernel/actions/workflows/ci.yml/badge.svg?query=branch%3Amain++)
-[](https://codecov.io/gh/ipython/ipykernel)
[](http://ipykernel.readthedocs.io/en/latest/?badge=latest)
This package provides the IPython kernel for Jupyter.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/README.md
new/ipykernel-6.23.1/README.md
--- old/ipykernel-6.22.0/README.md 2020-02-02 01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/README.md 2020-02-02 01:00:00.000000000 +0100
@@ -1,7 +1,6 @@
# IPython Kernel for Jupyter
[](https://github.com/ipython/ipykernel/actions/workflows/ci.yml/badge.svg?query=branch%3Amain++)
-[](https://codecov.io/gh/ipython/ipykernel)
[](http://ipykernel.readthedocs.io/en/latest/?badge=latest)
This package provides the IPython kernel for Jupyter.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/codecov.yml
new/ipykernel-6.23.1/codecov.yml
--- old/ipykernel-6.22.0/codecov.yml 2020-02-02 01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/codecov.yml 1970-01-01 01:00:00.000000000 +0100
@@ -1,9 +0,0 @@
-coverage:
- status:
- project:
- default:
- target: auto
- threshold: 1
- patch:
- default:
- target: 0%
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/_version.py
new/ipykernel-6.23.1/ipykernel/_version.py
--- old/ipykernel-6.22.0/ipykernel/_version.py 2020-02-02 01:00:00.000000000
+0100
+++ new/ipykernel-6.23.1/ipykernel/_version.py 2020-02-02 01:00:00.000000000
+0100
@@ -5,7 +5,7 @@
from typing import List
# Version string must appear intact for hatch versioning
-__version__ = "6.22.0"
+__version__ = "6.23.1"
# Build up version_info tuple for backwards compatibility
pattern = r"(?P<major>\d+).(?P<minor>\d+).(?P<patch>\d+)(?P<rest>.*)"
@@ -17,4 +17,4 @@
version_info = tuple(parts)
kernel_protocol_version_info = (5, 3)
-kernel_protocol_version = "%s.%s" % kernel_protocol_version_info
+kernel_protocol_version = "{}.{}".format(*kernel_protocol_version_info)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/comm/comm.py
new/ipykernel-6.23.1/ipykernel/comm/comm.py
--- old/ipykernel-6.22.0/ipykernel/comm/comm.py 2020-02-02 01:00:00.000000000
+0100
+++ new/ipykernel-6.23.1/ipykernel/comm/comm.py 2020-02-02 01:00:00.000000000
+0100
@@ -3,6 +3,7 @@
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
+import threading
import uuid
from typing import Optional
from warnings import warn
@@ -11,6 +12,7 @@
import traitlets.config
from traitlets import Bool, Bytes, Instance, Unicode, default
+from ipykernel.control import CONTROL_THREAD_NAME
from ipykernel.jsonutil import json_clean
from ipykernel.kernelbase import Kernel
@@ -30,6 +32,11 @@
metadata = {} if metadata is None else metadata
content = json_clean(dict(data=data, comm_id=self.comm_id, **keys))
+ if threading.current_thread().name == CONTROL_THREAD_NAME:
+ channel_from_which_to_get_parent_header = "control"
+ else:
+ channel_from_which_to_get_parent_header = "shell"
+
if self.kernel is None:
self.kernel = Kernel.instance()
@@ -38,7 +45,7 @@
msg_type,
content,
metadata=json_clean(metadata),
- parent=self.kernel.get_parent("shell"),
+
parent=self.kernel.get_parent(channel_from_which_to_get_parent_header),
ident=self.topic,
buffers=buffers,
)
@@ -80,6 +87,7 @@
"The `ipykernel.comm.Comm` class has been deprecated. Please
use the `comm` module instead."
"For creating comms, use the function `from comm import
create_comm`.",
DeprecationWarning,
+ stacklevel=2,
)
# Handle differing arguments between base classes.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/connect.py
new/ipykernel-6.23.1/ipykernel/connect.py
--- old/ipykernel-6.22.0/ipykernel/connect.py 2020-02-02 01:00:00.000000000
+0100
+++ new/ipykernel-6.23.1/ipykernel/connect.py 2020-02-02 01:00:00.000000000
+0100
@@ -117,7 +117,7 @@
kwargs["start_new_session"] = True
return Popen(
- [sys.executable, "-c", cmd, "--existing", cf, *argv],
+ [sys.executable, "-c", cmd, "--existing", cf, *argv], # noqa
stdout=PIPE,
stderr=PIPE,
close_fds=(sys.platform != "win32"),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/control.py
new/ipykernel-6.23.1/ipykernel/control.py
--- old/ipykernel-6.22.0/ipykernel/control.py 2020-02-02 01:00:00.000000000
+0100
+++ new/ipykernel-6.23.1/ipykernel/control.py 2020-02-02 01:00:00.000000000
+0100
@@ -3,20 +3,22 @@
from tornado.ioloop import IOLoop
+CONTROL_THREAD_NAME = "Control"
+
class ControlThread(Thread):
"""A thread for a control channel."""
def __init__(self, **kwargs):
"""Initialize the thread."""
- Thread.__init__(self, name="Control", **kwargs)
+ Thread.__init__(self, name=CONTROL_THREAD_NAME, **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"
+ self.name = CONTROL_THREAD_NAME
try:
self.io_loop.start()
finally:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/gui/gtk3embed.py
new/ipykernel-6.23.1/ipykernel/gui/gtk3embed.py
--- old/ipykernel-6.22.0/ipykernel/gui/gtk3embed.py 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/ipykernel/gui/gtk3embed.py 2020-02-02
01:00:00.000000000 +0100
@@ -14,7 +14,9 @@
import sys
import warnings
-warnings.warn("The Gtk3 event loop for ipykernel is deprecated",
category=DeprecationWarning)
+warnings.warn(
+ "The Gtk3 event loop for ipykernel is deprecated",
category=DeprecationWarning, stacklevel=2
+)
# Third-party
import gi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/gui/gtkembed.py
new/ipykernel-6.23.1/ipykernel/gui/gtkembed.py
--- old/ipykernel-6.22.0/ipykernel/gui/gtkembed.py 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/ipykernel/gui/gtkembed.py 2020-02-02
01:00:00.000000000 +0100
@@ -14,7 +14,9 @@
import sys
import warnings
-warnings.warn("The Gtk3 event loop for ipykernel is deprecated",
category=DeprecationWarning)
+warnings.warn(
+ "The Gtk3 event loop for ipykernel is deprecated",
category=DeprecationWarning, stacklevel=2
+)
# Third-party
import gobject
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/iostream.py
new/ipykernel-6.23.1/ipykernel/iostream.py
--- old/ipykernel-6.22.0/ipykernel/iostream.py 2020-02-02 01:00:00.000000000
+0100
+++ new/ipykernel-6.23.1/ipykernel/iostream.py 2020-02-02 01:00:00.000000000
+0100
@@ -13,6 +13,7 @@
from binascii import b2a_hex
from collections import deque
from io import StringIO, TextIOBase
+from threading import local
from typing import Any, Callable, Deque, Optional
from weakref import WeakSet
@@ -134,7 +135,8 @@
except zmq.ZMQError as e:
warnings.warn(
"Couldn't bind IOPub Pipe to 127.0.0.1: %s" % e
- + "\nsubprocess output will be unavailable."
+ + "\nsubprocess output will be unavailable.",
+ stacklevel=2,
)
self._pipe_flag = False
pipe_in.close()
@@ -362,7 +364,7 @@
echo : bool
whether to echo output
watchfd : bool (default, True)
- Watch the file descripttor corresponding to the replaced stream.
+ Watch the file descriptor corresponding to the replaced stream.
This is useful if you know some underlying code will write directly
the file descriptor by its number. It will spawn a watching thread,
that will swap the give file descriptor for a pipe, read from the
@@ -402,22 +404,43 @@
self.echo = None
self._isatty = bool(isatty)
self._should_watch = False
+ self._local = local()
if (
watchfd
- and (sys.platform.startswith("linux") or
sys.platform.startswith("darwin"))
- and ("PYTEST_CURRENT_TEST" not in os.environ)
+ and (
+ (sys.platform.startswith("linux") or
sys.platform.startswith("darwin"))
+ # Pytest set its own capture. Don't redirect from within
pytest.
+ and ("PYTEST_CURRENT_TEST" not in os.environ)
+ )
+ # allow forcing watchfd (mainly for tests)
+ or watchfd == "force"
):
- # Pytest set its own capture. Dont redirect from within pytest.
-
self._should_watch = True
self._setup_stream_redirects(name)
if echo:
if hasattr(echo, "read") and hasattr(echo, "write"):
+ # make sure we aren't trying to echo on the FD we're watching!
+ # that would cause an infinite loop, always echoing on itself
+ if self._should_watch:
+ try:
+ echo_fd = echo.fileno()
+ except Exception:
+ echo_fd = None
+
+ if echo_fd is not None and echo_fd ==
self._original_stdstream_fd:
+ # echo on the _copy_ we made during
+ # this is the actual terminal FD now
+ echo = io.TextIOWrapper(
+ io.FileIO(
+ self._original_stdstream_copy,
+ "w",
+ )
+ )
self.echo = echo
else:
- msg = "echo argument must be a file like object"
+ msg = "echo argument must be a file-like object"
raise ValueError(msg)
def isatty(self):
@@ -430,7 +453,7 @@
def _setup_stream_redirects(self, name):
pr, pw = os.pipe()
- fno = getattr(sys, name).fileno()
+ fno = self._original_stdstream_fd = getattr(sys, name).fileno()
self._original_stdstream_copy = os.dup(fno)
os.dup2(pw, fno)
@@ -452,7 +475,13 @@
"""Close the stream."""
if self._should_watch:
self._should_watch = False
+ # thread won't wake unless there's something to read
+ # writing something after _should_watch will not be echoed
+ os.write(self._original_stdstream_fd, b'\0')
self.watch_fd_thread.join()
+ # restore original FDs
+ os.dup2(self._original_stdstream_copy, self._original_stdstream_fd)
+ os.close(self._original_stdstream_copy)
if self._exc:
etype, value, tb = self._exc
traceback.print_exception(etype, value, tb)
@@ -524,11 +553,19 @@
# There should be a better way to do this.
self.session.pid = os.getpid()
content = {"name": self.name, "text": data}
+ msg = self.session.msg("stream", content,
parent=self.parent_header)
+
+ # Each transform either returns a new
+ # message or None. If None is returned,
+ # the message has been 'used' and we return.
+ for hook in self._hooks:
+ msg = hook(msg)
+ if msg is None:
+ return
+
self.session.send(
self.pub_thread,
- "stream",
- content=content,
- parent=self.parent_header,
+ msg,
ident=self.topic,
)
@@ -600,3 +637,49 @@
old_buffer = self._buffer
self._buffer = StringIO()
return old_buffer
+
+ @property
+ def _hooks(self):
+ if not hasattr(self._local, "hooks"):
+ # create new list for a new thread
+ self._local.hooks = []
+ return self._local.hooks
+
+ def register_hook(self, hook):
+ """
+ Registers a hook with the thread-local storage.
+
+ Parameters
+ ----------
+ hook : Any callable object
+
+ Returns
+ -------
+ Either a publishable message, or `None`.
+ The hook callable must return a message from
+ the __call__ method if they still require the
+ `session.send` method to be called after transformation.
+ Returning `None` will halt that execution path, and
+ session.send will not be called.
+ """
+ self._hooks.append(hook)
+
+ def unregister_hook(self, hook):
+ """
+ Un-registers a hook with the thread-local storage.
+
+ Parameters
+ ----------
+ hook : Any callable object which has previously been
+ registered as a hook.
+
+ Returns
+ -------
+ bool - `True` if the hook was removed, `False` if it wasn't
+ found.
+ """
+ try:
+ self._hooks.remove(hook)
+ return True
+ except ValueError:
+ return False
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/ipkernel.py
new/ipykernel-6.23.1/ipykernel/ipkernel.py
--- old/ipykernel-6.22.0/ipykernel/ipkernel.py 2020-02-02 01:00:00.000000000
+0100
+++ new/ipykernel-6.23.1/ipykernel/ipkernel.py 2020-02-02 01:00:00.000000000
+0100
@@ -704,5 +704,6 @@
warnings.warn(
"Kernel is a deprecated alias of ipykernel.ipkernel.IPythonKernel",
DeprecationWarning,
+ stacklevel=2,
)
super().__init__(*args, **kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/kernelspec.py
new/ipykernel-6.23.1/ipykernel/kernelspec.py
--- old/ipykernel-6.22.0/ipykernel/kernelspec.py 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/ipykernel/kernelspec.py 2020-02-02
01:00:00.000000000 +0100
@@ -227,7 +227,7 @@
)
opts = parser.parse_args(self.argv)
if opts.env:
- opts.env = {k: v for (k, v) in opts.env}
+ opts.env = dict(opts.env)
try:
dest = install(
user=opts.user,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/parentpoller.py
new/ipykernel-6.23.1/ipykernel/parentpoller.py
--- old/ipykernel-6.22.0/ipykernel/parentpoller.py 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/ipykernel/parentpoller.py 2020-02-02
01:00:00.000000000 +0100
@@ -115,6 +115,7 @@
"""Parent poll failed. If the frontend dies,
the kernel may be left running. Please let us know
about your system (bitness, Python, etc.) at
- [email protected]"""
+ [email protected]""",
+ stacklevel=2,
)
return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/pickleutil.py
new/ipykernel-6.23.1/ipykernel/pickleutil.py
--- old/ipykernel-6.22.0/ipykernel/pickleutil.py 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/ipykernel/pickleutil.py 2020-02-02
01:00:00.000000000 +0100
@@ -300,7 +300,7 @@
data = self.buffers[0]
if self.pickled:
# we just pickled it
- return pickle.loads(data)
+ return pickle.loads(data) # noqa
else:
return frombuffer(data, dtype=self.dtype).reshape(self.shape)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/pylab/backend_inline.py
new/ipykernel-6.23.1/ipykernel/pylab/backend_inline.py
--- old/ipykernel-6.22.0/ipykernel/pylab/backend_inline.py 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/ipykernel/pylab/backend_inline.py 2020-02-02
01:00:00.000000000 +0100
@@ -11,4 +11,5 @@
"`ipykernel.pylab.backend_inline` is deprecated, directly "
"use `matplotlib_inline.backend_inline`",
DeprecationWarning,
+ stacklevel=2,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/pylab/config.py
new/ipykernel-6.23.1/ipykernel/pylab/config.py
--- old/ipykernel-6.22.0/ipykernel/pylab/config.py 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/ipykernel/pylab/config.py 2020-02-02
01:00:00.000000000 +0100
@@ -10,4 +10,5 @@
warnings.warn(
"`ipykernel.pylab.config` is deprecated, directly use
`matplotlib_inline.config`",
DeprecationWarning,
+ stacklevel=2,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/serialize.py
new/ipykernel-6.23.1/ipykernel/serialize.py
--- old/ipykernel-6.22.0/ipykernel/serialize.py 2020-02-02 01:00:00.000000000
+0100
+++ new/ipykernel-6.23.1/ipykernel/serialize.py 2020-02-02 01:00:00.000000000
+0100
@@ -122,7 +122,7 @@
"""
bufs = list(buffers)
pobj = bufs.pop(0)
- canned = pickle.loads(pobj)
+ canned = pickle.loads(pobj) # noqa
if istype(canned, sequence_types) and len(canned) < MAX_ITEMS:
for c in canned:
_restore_buffers(c, bufs)
@@ -183,9 +183,9 @@
bufs = list(bufs) # allow us to pop
assert len(bufs) >= 2, "not enough buffers!"
pf = bufs.pop(0)
- f = uncan(pickle.loads(pf), g)
+ f = uncan(pickle.loads(pf), g) # noqa
pinfo = bufs.pop(0)
- info = pickle.loads(pinfo)
+ info = pickle.loads(pinfo) # noqa
arg_bufs, kwarg_bufs = bufs[: info["narg_bufs"]], bufs[info["narg_bufs"] :]
args_list = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/tests/test_io.py
new/ipykernel-6.23.1/ipykernel/tests/test_io.py
--- old/ipykernel-6.22.0/ipykernel/tests/test_io.py 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/ipykernel/tests/test_io.py 2020-02-02
01:00:00.000000000 +0100
@@ -1,7 +1,12 @@
"""Test IO capturing functionality"""
import io
+import os
+import subprocess
+import sys
+import time
import warnings
+from unittest import mock
import pytest
import zmq
@@ -10,20 +15,28 @@
from ipykernel.iostream import MASTER, BackgroundSocket, IOPubThread, OutStream
-def test_io_api():
- """Test that wrapped stdout has the same API as a normal TextIO object"""
- session = Session()
[email protected]
+def ctx():
ctx = zmq.Context()
- pub = ctx.socket(zmq.PUB)
- thread = IOPubThread(pub)
- thread.start()
+ yield ctx
+ ctx.destroy()
- stream = OutStream(session, thread, "stdout")
- # cleanup unused zmq objects before we start testing
- thread.stop()
- thread.close()
- ctx.term()
[email protected]
+def iopub_thread(ctx):
+ with ctx.socket(zmq.PUB) as pub:
+ thread = IOPubThread(pub)
+ thread.start()
+
+ yield thread
+ thread.stop()
+ thread.close()
+
+
+def test_io_api(iopub_thread):
+ """Test that wrapped stdout has the same API as a normal TextIO object"""
+ session = Session()
+ stream = OutStream(session, iopub_thread, "stdout")
assert stream.errors is None
assert not stream.isatty()
@@ -43,28 +56,21 @@
stream.write(b"") # type:ignore
-def test_io_isatty():
+def test_io_isatty(iopub_thread):
session = Session()
- ctx = zmq.Context()
- pub = ctx.socket(zmq.PUB)
- thread = IOPubThread(pub)
- thread.start()
-
- stream = OutStream(session, thread, "stdout", isatty=True)
+ stream = OutStream(session, iopub_thread, "stdout", isatty=True)
assert stream.isatty()
-def test_io_thread():
- ctx = zmq.Context()
- pub = ctx.socket(zmq.PUB)
- thread = IOPubThread(pub)
+def test_io_thread(iopub_thread):
+ thread = iopub_thread
thread._setup_pipe_in()
msg = [thread._pipe_uuid, b"a"]
thread._handle_pipe_msg(msg)
ctx1, pipe = thread._setup_pipe_out()
pipe.close()
thread._pipe_in.close()
- thread._check_mp_mode = lambda: MASTER # type:ignore
+ thread._check_mp_mode = lambda: MASTER
thread._really_send([b"hi"])
ctx1.destroy()
thread.close()
@@ -72,40 +78,139 @@
thread._really_send(None)
-def test_background_socket():
- ctx = zmq.Context()
- pub = ctx.socket(zmq.PUB)
- thread = IOPubThread(pub)
- sock = BackgroundSocket(thread)
+def test_background_socket(iopub_thread):
+ sock = BackgroundSocket(iopub_thread)
assert sock.__class__ == BackgroundSocket
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
sock.linger = 101
- assert thread.socket.linger == 101
- assert sock.io_thread == thread
+ assert iopub_thread.socket.linger == 101
+ assert sock.io_thread == iopub_thread
sock.send(b"hi")
-def test_outstream():
+def test_outstream(iopub_thread):
session = Session()
- ctx = zmq.Context()
- pub = ctx.socket(zmq.PUB)
- thread = IOPubThread(pub)
- thread.start()
-
+ pub = iopub_thread.socket
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
stream = OutStream(session, pub, "stdout")
- stream = OutStream(session, thread, "stdout", pipe=object())
+ stream.close()
+ stream = OutStream(session, iopub_thread, "stdout", pipe=object())
+ stream.close()
- stream = OutStream(session, thread, "stdout", watchfd=False)
+ stream = OutStream(session, iopub_thread, "stdout", watchfd=False)
stream.close()
- stream = OutStream(session, thread, "stdout", isatty=True,
echo=io.StringIO())
- with pytest.raises(io.UnsupportedOperation):
- stream.fileno()
- stream._watch_pipe_fd()
- stream.flush()
- stream.write("hi")
- stream.writelines(["ab", "cd"])
- assert stream.writable()
+ stream = OutStream(session, iopub_thread, "stdout", isatty=True,
echo=io.StringIO())
+
+ with stream:
+ with pytest.raises(io.UnsupportedOperation):
+ stream.fileno()
+ stream._watch_pipe_fd()
+ stream.flush()
+ stream.write("hi")
+ stream.writelines(["ab", "cd"])
+ assert stream.writable()
+
+
+def subprocess_test_echo_watch():
+ # handshake Pub subscription
+ session = Session(key=b'abc')
+
+ # use PUSH socket to avoid subscription issues
+ with zmq.Context() as ctx, ctx.socket(zmq.PUSH) as pub:
+ pub.connect(os.environ["IOPUB_URL"])
+ iopub_thread = IOPubThread(pub)
+ iopub_thread.start()
+ stdout_fd = sys.stdout.fileno()
+ sys.stdout.flush()
+ stream = OutStream(
+ session,
+ iopub_thread,
+ "stdout",
+ isatty=True,
+ echo=sys.stdout,
+ watchfd="force",
+ )
+ save_stdout = sys.stdout
+ with stream, mock.patch.object(sys, "stdout", stream):
+ # write to low-level FD
+ os.write(stdout_fd, b"fd\n")
+ # print (writes to stream)
+ print("print\n", end="")
+ sys.stdout.flush()
+ # write to unwrapped __stdout__ (should also go to original FD)
+ sys.__stdout__.write("__stdout__\n")
+ sys.__stdout__.flush()
+ # write to original sys.stdout (should be the same as __stdout__)
+ save_stdout.write("stdout\n")
+ save_stdout.flush()
+ # is there another way to flush on the FD?
+ fd_file = os.fdopen(stdout_fd, "w")
+ fd_file.flush()
+ # we don't have a sync flush on _reading_ from the watched pipe
+ time.sleep(1)
+ stream.flush()
+ iopub_thread.stop()
+ iopub_thread.close()
+
+
[email protected](sys.platform.startswith("win"), reason="Windows")
+def test_echo_watch(ctx):
+ """Test echo on underlying FD while capturing the same FD
+
+ Test runs in a subprocess to avoid messing with pytest output capturing.
+ """
+ s = ctx.socket(zmq.PULL)
+ port = s.bind_to_random_port("tcp://127.0.0.1")
+ url = f"tcp://127.0.0.1:{port}"
+ session = Session(key=b'abc')
+ messages = []
+ stdout_chunks = []
+ with s:
+ env = dict(os.environ)
+ env["IOPUB_URL"] = url
+ env["PYTHONUNBUFFERED"] = "1"
+ env.pop("PYTEST_CURRENT_TEST", None)
+ p = subprocess.run(
+ [
+ sys.executable,
+ "-c",
+ f"import {__name__}; {__name__}.subprocess_test_echo_watch()",
+ ],
+ env=env,
+ capture_output=True,
+ text=True,
+ timeout=10,
+ )
+ print(f"{p.stdout=}")
+ print(f"{p.stderr}=", file=sys.stderr)
+ assert p.returncode == 0
+ while s.poll(timeout=100):
+ ident, msg = session.recv(s)
+ assert msg is not None # for type narrowing
+ if msg["header"]["msg_type"] == "stream" and
msg["content"]["name"] == "stdout":
+ stdout_chunks.append(msg["content"]["text"])
+
+ # check outputs
+ # use sets of lines to ignore ordering issues with
+ # async flush and watchfd thread
+
+ # Check the stream output forwarded over zmq
+ zmq_stdout = "".join(stdout_chunks)
+ assert set(zmq_stdout.strip().splitlines()) == {
+ "fd",
+ "print",
+ "stdout",
+ "__stdout__",
+ }
+
+ # Check what was written to the process stdout (kernel terminal)
+ # just check that each output source went to the terminal
+ assert set(p.stdout.strip().splitlines()) == {
+ "fd",
+ "print",
+ "stdout",
+ "__stdout__",
+ }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/tests/test_pickleutil.py
new/ipykernel-6.23.1/ipykernel/tests/test_pickleutil.py
--- old/ipykernel-6.22.0/ipykernel/tests/test_pickleutil.py 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/ipykernel/tests/test_pickleutil.py 2020-02-02
01:00:00.000000000 +0100
@@ -16,7 +16,7 @@
def loads(obj):
- return uncan(pickle.loads(obj))
+ return uncan(pickle.loads(obj)) # noqa
def test_no_closure():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/trio_runner.py
new/ipykernel-6.23.1/ipykernel/trio_runner.py
--- old/ipykernel-6.22.0/ipykernel/trio_runner.py 2020-02-02
01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/ipykernel/trio_runner.py 2020-02-02
01:00:00.000000000 +0100
@@ -22,7 +22,7 @@
kernel.shell.set_trio_runner(self)
kernel.shell.run_line_magic("autoawait", "trio")
kernel.shell.magics_manager.magics["line"]["autoawait"] = lambda _:
warnings.warn(
- "Autoawait isn't allowed in Trio background loop mode."
+ "Autoawait isn't allowed in Trio background loop mode.",
stacklevel=2
)
self._interrupted = False
bg_thread = threading.Thread(target=io_loop.start, daemon=True,
name="TornadoBackground")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel/zmqshell.py
new/ipykernel-6.23.1/ipykernel/zmqshell.py
--- old/ipykernel-6.22.0/ipykernel/zmqshell.py 2020-02-02 01:00:00.000000000
+0100
+++ new/ipykernel-6.23.1/ipykernel/zmqshell.py 2020-02-02 01:00:00.000000000
+0100
@@ -363,7 +363,7 @@
connection_file = get_connection_file()
info = get_connection_info(unpack=False)
except Exception as e:
- warnings.warn("Could not get connection info: %r" % e)
+ warnings.warn("Could not get connection info: %r" % e,
stacklevel=2)
return
# if it's in the default dir, truncate to basename
@@ -399,7 +399,7 @@
try:
connect_qtconsole(argv=arg_split(arg_s, os.name == "posix"))
except Exception as e:
- warnings.warn("Could not start qtconsole: %r" % e)
+ warnings.warn("Could not start qtconsole: %r" % e, stacklevel=2)
return
@line_magic
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/ipykernel_launcher.py
new/ipykernel-6.23.1/ipykernel_launcher.py
--- old/ipykernel-6.22.0/ipykernel_launcher.py 2020-02-02 01:00:00.000000000
+0100
+++ new/ipykernel-6.23.1/ipykernel_launcher.py 2020-02-02 01:00:00.000000000
+0100
@@ -9,7 +9,7 @@
if __name__ == "__main__":
# Remove the CWD from sys.path while we load stuff.
# This is added back by InteractiveShellApp.init_path()
- if sys.path[0] == "":
+ if sys.path[0] == "": # noqa
del sys.path[0]
from ipykernel import kernelapp as app
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ipykernel-6.22.0/pyproject.toml
new/ipykernel-6.23.1/pyproject.toml
--- old/ipykernel-6.22.0/pyproject.toml 2020-02-02 01:00:00.000000000 +0100
+++ new/ipykernel-6.23.1/pyproject.toml 2020-02-02 01:00:00.000000000 +0100
@@ -91,6 +91,7 @@
[tool.hatch.envs.test]
features = ["test"]
[tool.hatch.envs.test.scripts]
+list = "python -m pip freeze"
test = "python -m pytest -vv {args}"
nowarn = "test -W default {args}"
@@ -116,7 +117,7 @@
test = "mypy --install-types --non-interactive {args:.}"
[tool.hatch.envs.lint]
-dependencies = ["black==23.1.0", "mdformat>0.7", "ruff==0.0.254"]
+dependencies = ["black==23.3.0", "mdformat>0.7", "ruff==0.0.263"]
detached = true
[tool.hatch.envs.lint.scripts]
style = [
@@ -191,6 +192,8 @@
]
[tool.coverage.run]
+relative_files = true
+source = ["ipykernel"]
omit = [
"ipykernel/tests/*",
"ipykernel/datapub.py",
@@ -296,7 +299,11 @@
# PLR2004 Magic value used in comparison
# PLW0603 Using the global statement to update ...
# PLW2901 `for` loop variable ...
-"ipykernel/tests/*" = ["B011", "F841", "C408", "E402", "T201", "B007", "N802",
"F841", "EM101", "EM102", "EM103", "PLR2004", "PLW0603", "PLW2901"]
+# PLC1901 `stderr == ""` can be simplified to `not stderr` as an empty string
is falsey
+# B018 Found useless expression. Either assign it to a variable or remove it.
+# S603 `subprocess` call: check for execution of untrusted input
+"ipykernel/tests/*" = ["B011", "F841", "C408", "E402", "T201", "B007", "N802",
"F841", "EM101",
+ "EM102", "EM103", "PLR2004", "PLW0603", "PLW2901", "PLC1901", "B018",
"S603"]
[tool.interrogate]
ignore-init-module=true