Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-jupyter-core for
openSUSE:Factory checked in at 2026-03-17 19:02:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-jupyter-core (Old)
and /work/SRC/openSUSE:Factory/.python-jupyter-core.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-jupyter-core"
Tue Mar 17 19:02:08 2026 rev:29 rq:1339150 version:5.9.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-jupyter-core/python-jupyter-core.changes
2025-06-23 14:56:29.311863102 +0200
+++
/work/SRC/openSUSE:Factory/.python-jupyter-core.new.8177/python-jupyter-core.changes
2026-03-17 19:02:16.879170177 +0100
@@ -1,0 +2,12 @@
+Sat Dec 13 13:56:04 UTC 2025 - Dirk Müller <[email protected]>
+
+- update to 5.9.1:
+ * nicer traceback in missing loop case outside except in
+ run_sync #437 (@AThePeanut4)
+ * Fix missing `f` specifier in f-string used to print config
+ file path #433 (@krassowski)
+ * validate inputs to is_hidden #429 (@minrk)
+ * [Docs] Use extension:filetype mapping in sphinx configuration
+ #443 (@Carreau)
+
+-------------------------------------------------------------------
Old:
----
jupyter_core-5.8.1.tar.gz
New:
----
jupyter_core-5.9.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-jupyter-core.spec ++++++
--- /var/tmp/diff_new_pack.EHRars/_old 2026-03-17 19:02:17.459193963 +0100
+++ /var/tmp/diff_new_pack.EHRars/_new 2026-03-17 19:02:17.463194127 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-jupyter-core
#
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2025 SUSE LLC and contributors
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -32,7 +32,7 @@
%endif
%{?sle15_python_module_pythons}
Name: python-jupyter-core%{psuffix}
-Version: 5.8.1
+Version: 5.9.1
Release: 0
Summary: Base package on which Jupyter projects rely
License: BSD-3-Clause
++++++ jupyter_core-5.8.1.tar.gz -> jupyter_core-5.9.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/jupyter_core-5.8.1/.github/workflows/codeql-analysis.yml
new/jupyter_core-5.9.1/.github/workflows/codeql-analysis.yml
--- old/jupyter_core-5.8.1/.github/workflows/codeql-analysis.yml
2020-02-02 01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/.github/workflows/codeql-analysis.yml
2020-02-02 01:00:00.000000000 +0100
@@ -40,11 +40,11 @@
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v3
+ uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a
config file.
@@ -56,7 +56,7 @@
# Autobuild attempts to build any compiled languages (C/C++, C#, or
Java).
# If this step fails, then you should remove it and run the build
manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@v3
+ uses: github/codeql-action/autobuild@v4
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -70,4 +70,4 @@
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v3
+ uses: github/codeql-action/analyze@v4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/.github/workflows/downstream.yml
new/jupyter_core-5.9.1/.github/workflows/downstream.yml
--- old/jupyter_core-5.8.1/.github/workflows/downstream.yml 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/.github/workflows/downstream.yml 2020-02-02
01:00:00.000000000 +0100
@@ -14,7 +14,7 @@
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1
with:
@@ -24,7 +24,7 @@
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1
with:
@@ -35,7 +35,7 @@
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1
with:
@@ -46,7 +46,7 @@
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1
with:
@@ -56,7 +56,7 @@
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
@@ -65,12 +65,13 @@
uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1
with:
package_name: jupyter_client
+ package_spec: "anyio .[test]"
pytest_jupyter:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/.github/workflows/test.yml
new/jupyter_core-5.9.1/.github/workflows/test.yml
--- old/jupyter_core-5.8.1/.github/workflows/test.yml 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/.github/workflows/test.yml 2020-02-02
01:00:00.000000000 +0100
@@ -28,19 +28,19 @@
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
- python-version: ["3.8", "3.12", "3.13"]
+ python-version: ["3.12", "3.13", "3.14", "3.14t"]
include:
- os: windows-latest
- python-version: "3.9"
+ python-version: "3.10"
- os: ubuntu-latest
python-version: "3.11"
- os: ubuntu-latest
- python-version: "pypy-3.9"
+ python-version: "pypy-3.10"
- os: macos-latest
python-version: "3.10"
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
cache: pip
@@ -70,7 +70,7 @@
needs:
- build
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: jupyterlab/maintainer-tools/.github/actions/report-coverage@v1
test_minimum_versions:
@@ -78,32 +78,33 @@
timeout-minutes: 20
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
with:
dependency_type: minimum
+ python_version: "3.10"
- name: Run the unit tests
run: |
- hatch run test:nowarn || hatch run test:nowarn --lf
+ hatch run test:test
test_prereleases:
name: Test Prereleases
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
with:
dependency_type: pre
- name: Run the tests
run: |
- hatch run test:nowarn || hatch run test:nowarn --lf
+ hatch run test:test
test_docs:
name: Test Docs
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- name: Build API docs
run: |
@@ -120,7 +121,7 @@
name: Test Lint
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- name: Run Linters
run: |
@@ -135,7 +136,7 @@
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- uses: jupyterlab/maintainer-tools/.github/actions/make-sdist@v1
@@ -152,7 +153,7 @@
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- name: Install Dependencies
@@ -168,7 +169,7 @@
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- uses: jupyterlab/maintainer-tools/.github/actions/check-links@v1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/.pre-commit-config.yaml
new/jupyter_core-5.9.1/.pre-commit-config.yaml
--- old/jupyter_core-5.8.1/.pre-commit-config.yaml 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/.pre-commit-config.yaml 2020-02-02
01:00:00.000000000 +0100
@@ -4,7 +4,7 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v5.0.0
+ rev: v6.0.0
hooks:
- id: check-case-conflict
- id: check-ast
@@ -21,11 +21,11 @@
- id: trailing-whitespace
- repo: https://github.com/python-jsonschema/check-jsonschema
- rev: 0.33.0
+ rev: 0.34.1
hooks:
- id: check-github-workflows
- - repo: https://github.com/executablebooks/mdformat
+ - repo: https://github.com/hukkin/mdformat
rev: 0.7.22
hooks:
- id: mdformat
@@ -39,13 +39,13 @@
types_or: [yaml, html, json]
- repo: https://github.com/adamchainz/blacken-docs
- rev: "1.19.1"
+ rev: "1.20.0"
hooks:
- id: blacken-docs
additional_dependencies: [black==23.7.0]
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: "v1.15.0"
+ rev: "v1.18.2"
hooks:
- id: mypy
files: jupyter_core
@@ -67,16 +67,16 @@
- id: rst-inline-touching-normal
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.11.11
+ rev: v0.14.0
hooks:
- - id: ruff
+ - id: ruff-check
types_or: [python, jupyter]
args: ["--fix", "--show-fixes"]
- id: ruff-format
types_or: [python, jupyter]
- repo: https://github.com/scientific-python/cookie
- rev: "2025.05.02"
+ rev: "2025.10.01"
hooks:
- id: sp-repo-review
additional_dependencies: ["repo-review[cli]"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/CHANGELOG.md
new/jupyter_core-5.9.1/CHANGELOG.md
--- old/jupyter_core-5.8.1/CHANGELOG.md 2020-02-02 01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/CHANGELOG.md 2020-02-02 01:00:00.000000000 +0100
@@ -4,12 +4,50 @@
<!-- START SILENT CHANGELOG ENTRY -->
-## 5.8.1
+## 5.9.1
<!-- END SILENT CHANGELOG ENTRY -->
<!-- <END NEW CHANGELOG ENTRY> -->
+## 5.9.0
+
+([Full
Changelog](https://github.com/jupyter/jupyter_core/compare/v5.8.1...735131c141102c376539303564f5d305dc666333))
+
+### Enhancements made
+
+- nicer traceback in missing loop case outside except in run_sync
[#437](https://github.com/jupyter/jupyter_core/pull/437)
([@AThePeanut4](https://github.com/AThePeanut4))
+
+### Bugs fixed
+
+- Fix missing `f` specifier in f-string used to print config file path
[#433](https://github.com/jupyter/jupyter_core/pull/433)
([@krassowski](https://github.com/krassowski))
+- validate inputs to is_hidden
[#429](https://github.com/jupyter/jupyter_core/pull/429)
([@minrk](https://github.com/minrk))
+
+### Maintenance and upkeep improvements
+
+- try to fix some downstream tests
[#448](https://github.com/jupyter/jupyter_core/pull/448)
([@Carreau](https://github.com/Carreau))
+- remove deprecation warning, platformdirs won't become default
[#447](https://github.com/jupyter/jupyter_core/pull/447)
([@minrk](https://github.com/minrk))
+- Bump github/codeql-action from 3 to 4 in the actions group
[#446](https://github.com/jupyter/jupyter_core/pull/446)
([@dependabot](https://github.com/dependabot))
+- require python 3.10, start to test on 3.14 and 3.14-free-threaded
[#445](https://github.com/jupyter/jupyter_core/pull/445)
([@Carreau](https://github.com/Carreau))
+- remove pywin32 dependency so free-threading can fly (like pypy)
[#441](https://github.com/jupyter/jupyter_core/pull/441)
([@stonebig](https://github.com/stonebig))
+- Bump the actions group across 1 directory with 2 updates
[#440](https://github.com/jupyter/jupyter_core/pull/440)
([@dependabot](https://github.com/dependabot))
+
+### Documentation improvements
+
+- [Docs] Use extension:filetype mapping in sphinx configuration
[#443](https://github.com/jupyter/jupyter_core/pull/443)
([@Carreau](https://github.com/Carreau))
+
+### Contributors to this release
+
+([GitHub contributors page for this
release](https://github.com/jupyter/jupyter_core/graphs/contributors?from=2025-05-27&to=2025-10-16&type=c))
+
+[@AThePeanut4](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3AAThePeanut4+updated%3A2025-05-27..2025-10-16&type=Issues)
|
[@Carreau](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3ACarreau+updated%3A2025-05-27..2025-10-16&type=Issues)
|
[@dependabot](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3Adependabot+updated%3A2025-05-27..2025-10-16&type=Issues)
|
[@krassowski](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3Akrassowski+updated%3A2025-05-27..2025-10-16&type=Issues)
|
[@minrk](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3Aminrk+updated%3A2025-05-27..2025-10-16&type=Issues)
|
[@nikimagic](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3Anikimagic+updated%3A2025-05-27..2025-10-16&type=Issues)
|
[@stonebig](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3Astonebig+updated%3A2025-05-27..2025-10-16&type=Issues)
+
+<!-- START SILENT CHANGELOG ENTRY -->
+
+## 5.8.1
+
+<!-- END SILENT CHANGELOG ENTRY -->
+
<!-- START SILENT CHANGELOG ENTRY -->
## 5.8.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/PKG-INFO
new/jupyter_core-5.9.1/PKG-INFO
--- old/jupyter_core-5.8.1/PKG-INFO 2020-02-02 01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/PKG-INFO 2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: jupyter_core
-Version: 5.8.1
+Version: 5.9.1
Summary: Jupyter core package. A base package on which Jupyter projects rely.
Project-URL: Homepage, https://jupyter.org
Project-URL: Documentation, https://jupyter-core.readthedocs.io/
@@ -15,9 +15,8 @@
Classifier: Intended Audience :: System Administrators
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
-Requires-Python: >=3.8
+Requires-Python: >=3.10
Requires-Dist: platformdirs>=2.5
-Requires-Dist: pywin32>=300; sys_platform == 'win32' and
platform_python_implementation != 'PyPy'
Requires-Dist: traitlets>=5.3
Provides-Extra: docs
Requires-Dist: intersphinx-registry; extra == 'docs'
@@ -34,4 +33,4 @@
Requires-Dist: pytest<9; extra == 'test'
Description-Content-Type: text/plain
-There is no reason to install this package on its own.
\ No newline at end of file
+Jupyter core package. A base package on which Jupyter projects rely.
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/docs/conf.py
new/jupyter_core-5.9.1/docs/conf.py
--- old/jupyter_core-5.8.1/docs/conf.py 2020-02-02 01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/docs/conf.py 2020-02-02 01:00:00.000000000 +0100
@@ -51,7 +51,7 @@
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
-source_suffix = ".rst"
+source_suffix = {".rst": "restructuredtext"}
# The encoding of source files.
# source_encoding = 'utf-8-sig'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/jupyter_core/application.py
new/jupyter_core-5.9.1/jupyter_core/application.py
--- old/jupyter_core-5.8.1/jupyter_core/application.py 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/jupyter_core/application.py 2020-02-02
01:00:00.000000000 +0100
@@ -158,7 +158,7 @@
return
config_text = self.generate_config_file()
- print("Writing default config to: {config_file!r}")
+ print(f"Writing default config to: {config_file!r}")
ensure_dir_exists(Path(config_file).parent.resolve(), 0o700)
with Path.open(Path(config_file), mode="w", encoding="utf-8") as f:
f.write(config_text)
@@ -177,7 +177,7 @@
f_marker.close()
return # so we must have already migrated -> bail out
- from .migrate import get_ipython_dir, migrate
+ from .migrate import get_ipython_dir, migrate # noqa: PLC0415
# No IPython dir, nothing to migrate
if not Path(get_ipython_dir()).exists():
@@ -264,7 +264,7 @@
def start(self) -> None:
"""Start the whole thing"""
if self.subcommand:
- os.execv(self.subcommand, [self.subcommand] + self.argv[1:]) #
noqa: S606
+ os.execv(self.subcommand, [self.subcommand, *self.argv[1:]]) #
noqa: S606
raise NoStart()
if self.subapp:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/jupyter_core/command.py
new/jupyter_core-5.9.1/jupyter_core/command.py
--- old/jupyter_core-5.8.1/jupyter_core/command.py 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/jupyter_core/command.py 2020-02-02
01:00:00.000000000 +0100
@@ -43,7 +43,7 @@
def argcomplete(self) -> None:
"""Trigger auto-completion, if enabled"""
try:
- import argcomplete
+ import argcomplete # noqa: PLC0415
argcomplete.autocomplete(self)
except ImportError:
@@ -123,10 +123,10 @@
if cmd_path is None:
msg = f"{cmd!r} not found"
raise OSError(msg, errno.ENOENT)
- p = Popen([cmd_path] + argv[1:]) # noqa: S603
+ p = Popen([cmd_path, *argv[1:]]) # noqa: S603
# Don't raise KeyboardInterrupt in the parent process.
# Set this after spawning, to avoid subprocess inheriting handler.
- import signal
+ import signal # noqa: PLC0415
signal.signal(signal.SIGINT, signal.SIG_IGN)
p.wait()
@@ -203,7 +203,7 @@
try:
# traitlets >= 5.8 provides some argcomplete support,
# use helper methods to jump to argcomplete
- from traitlets.config.argcomplete_config import (
+ from traitlets.config.argcomplete_config import ( # noqa: PLC0415
get_argcomplete_cwords,
increment_argcomplete_index,
)
@@ -237,7 +237,7 @@
# Avoids argparse gobbling up args passed to subcommand, such as `-h`.
subcommand = argv[1]
else:
- args, opts = parser.parse_known_args()
+ args, _opts = parser.parse_known_args()
subcommand = args.subcommand
if args.version:
print("Selected Jupyter core packages...")
@@ -399,7 +399,7 @@
sys.exit(str(e))
try:
- _execvp(command, [command] + argv[2:])
+ _execvp(command, [command, *argv[2:]])
except OSError as e:
sys.exit(f"Error executing Jupyter command {subcommand!r}: {e}")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/jupyter_core/paths.py
new/jupyter_core-5.9.1/jupyter_core/paths.py
--- old/jupyter_core-5.8.1/jupyter_core/paths.py 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/jupyter_core/paths.py 2020-02-02
01:00:00.000000000 +0100
@@ -15,14 +15,13 @@
import sys
import tempfile
import warnings
+from collections.abc import Iterator
from contextlib import contextmanager
from pathlib import Path
-from typing import Any, Iterator, Literal, Optional, overload
+from typing import Any, overload
import platformdirs
-from .utils import deprecation
-
pjoin = os.path.join
# Capitalize Jupyter in paths only on Windows and MacOS (when not in Homebrew)
@@ -43,10 +42,10 @@
@overload
-def envset(name: str, default: Literal[None]) -> Optional[bool]: ...
+def envset(name: str, default: None) -> bool | None: ...
-def envset(name: str, default: Optional[bool] = False) -> Optional[bool]:
+def envset(name: str, default: bool | None = False) -> bool | None:
"""Return the boolean value of a given environment variable.
An environment variable is considered set if it is assigned to a value
@@ -63,8 +62,7 @@
def use_platform_dirs() -> bool:
"""Determine if platformdirs should be used for system-specific paths.
- We plan for this to default to False in jupyter_core version 5 and to True
- in jupyter_core version 6.
+ The default is False.
"""
return envset("JUPYTER_PLATFORM_DIRS", False)
@@ -182,12 +180,14 @@
if sys.platform == "darwin":
return str(Path(home, "Library", "Jupyter"))
+ # Bug in mypy which thinks it's unreachable:
https://github.com/python/mypy/issues/10773
if sys.platform == "win32":
appdata = os.environ.get("APPDATA", None)
if appdata:
return str(Path(appdata, "jupyter").resolve())
return pjoin(jupyter_config_dir(), "data")
# Linux, non-OS X Unix, AIX, etc.
+ # Bug in mypy which thinks it's unreachable:
https://github.com/python/mypy/issues/10773
xdg = env.get("XDG_DATA_HOME", None)
if not xdg:
xdg = pjoin(home, ".local", "share")
@@ -226,14 +226,8 @@
SYSTEM_JUPYTER_PATH = platformdirs.site_data_dir(
APPNAME, appauthor=False, multipath=True
).split(os.pathsep)
-else:
- deprecation(
- "Jupyter is migrating its paths to use standard platformdirs\n"
- "given by the platformdirs library. To remove this warning and\n"
- "see the appropriate new directories, set the environment variable\n"
- "`JUPYTER_PLATFORM_DIRS=1` and then run `jupyter --paths`.\n"
- "The use of platformdirs will be the default in `jupyter_core` v6"
- )
+else: # noqa: PLR5501
+ # default dirs
if os.name == "nt":
# PROGRAMDATA is not defined by default on XP, and not safe by default
if _win_programdata:
@@ -303,7 +297,7 @@
if site.ENABLE_USER_SITE:
# Check if site.getuserbase() exists to be compatible with virtualenv,
# which often does not have this method.
- userbase: Optional[str]
+ userbase: str | None
userbase = site.getuserbase() if hasattr(site, "getuserbase") else
site.USER_BASE
if userbase:
@@ -400,7 +394,7 @@
# Next is environment or user, depending on the JUPYTER_PREFER_ENV_PATH
flag
user = [jupyter_config_dir()]
if site.ENABLE_USER_SITE:
- userbase: Optional[str]
+ userbase: str | None
# Check if site.getuserbase() exists to be compatible with virtualenv,
# which often does not have this method.
userbase = site.getuserbase() if hasattr(site, "getuserbase") else
site.USER_BASE
@@ -442,7 +436,7 @@
return True
-def is_file_hidden_win(abs_path: str, stat_res: Optional[Any] = None) -> bool:
+def is_file_hidden_win(abs_path: str | Path, stat_res: Any | None = None) ->
bool:
"""Is a file hidden?
This only checks the file itself; it should be called in combination with
@@ -458,7 +452,8 @@
The result of calling stat() on abs_path. If not passed, this function
will call stat() internally.
"""
- if Path(abs_path).name.startswith("."):
+ abs_path = Path(abs_path)
+ if abs_path.name.startswith("."):
return True
if stat_res is None:
@@ -487,7 +482,7 @@
return False
-def is_file_hidden_posix(abs_path: str, stat_res: Optional[Any] = None) ->
bool:
+def is_file_hidden_posix(abs_path: str | Path, stat_res: Any | None = None) ->
bool:
"""Is a file hidden?
This only checks the file itself; it should be called in combination with
@@ -503,12 +498,13 @@
The result of calling stat() on abs_path. If not passed, this function
will call stat() internally.
"""
- if Path(abs_path).name.startswith("."):
+ abs_path = Path(abs_path)
+ if abs_path.name.startswith("."):
return True
if stat_res is None or stat.S_ISLNK(stat_res.st_mode):
try:
- stat_res = Path(abs_path).stat()
+ stat_res = abs_path.stat()
except OSError as e:
if e.errno == errno.ENOENT:
return False
@@ -533,7 +529,7 @@
is_file_hidden = is_file_hidden_posix
-def is_hidden(abs_path: str, abs_root: str = "") -> bool:
+def is_hidden(abs_path: str | Path, abs_root: str | Path = "") -> bool:
"""Is a file hidden or contained in a hidden directory?
This will start with the rightmost path element and work backwards to the
@@ -547,42 +543,56 @@
Parameters
----------
- abs_path : unicode
+ abs_path : str or Path
The absolute path to check for hidden directories.
- abs_root : unicode
+ abs_root : str or Path
The absolute path of the root directory in which hidden directories
should be checked for.
"""
- abs_path = os.path.normpath(abs_path)
- abs_root = os.path.normpath(abs_root)
+ abs_path = Path(os.path.normpath(abs_path))
+ if abs_root:
+ abs_root = Path(os.path.normpath(abs_root))
+ else:
+ abs_root = list(abs_path.parents)[-1]
if abs_path == abs_root:
+ # root itself is never hidden
return False
+ # check that arguments are valid
+ if not abs_path.is_absolute():
+ _msg = f"{abs_path=} is not absolute. abs_path must be absolute."
+ raise ValueError(_msg)
+ if not abs_root.is_absolute():
+ _msg = f"{abs_root=} is not absolute. abs_root must be absolute."
+ raise ValueError(_msg)
+ if not abs_path.is_relative_to(abs_root):
+ _msg = (
+ f"{abs_path=} is not a subdirectory of {abs_root=}. abs_path must
be within abs_root."
+ )
+ raise ValueError(_msg)
+
if is_file_hidden(abs_path):
return True
- if not abs_root:
- abs_root = abs_path.split(os.sep, 1)[0] + os.sep
- inside_root = abs_path[len(abs_root) :]
- if any(part.startswith(".") for part in Path(inside_root).parts):
+ relative_path = abs_path.relative_to(abs_root)
+ if any(part.startswith(".") for part in relative_path.parts):
return True
# check UF_HIDDEN on any location up to root.
# is_file_hidden() already checked the file, so start from its parent dir
- path = str(Path(abs_path).parent)
- while path and path.startswith(abs_root) and path != abs_root:
- if not Path(path).exists():
- path = str(Path(path).parent)
+ for parent in abs_path.parents:
+ if not parent.exists():
continue
+ if parent == abs_root:
+ break
try:
# may fail on Windows junctions
- st = os.lstat(path)
+ st = parent.lstat()
except OSError:
return True
if getattr(st, "st_flags", 0) & UF_HIDDEN:
return True
- path = str(Path(path).parent)
return False
@@ -602,12 +612,12 @@
The path to the file to secure
"""
try:
- import win32api
+ import win32api # noqa: PLC0415
except ImportError:
return _win32_restrict_file_to_user_ctypes(fname)
- import ntsecuritycon as con
- import win32security
+ import ntsecuritycon as con # noqa: PLC0415
+ import win32security # noqa: PLC0415
# everyone, _domain, _type = win32security.LookupAccountName("",
"Everyone")
admins =
win32security.CreateWellKnownSid(win32security.WinBuiltinAdministratorsSid)
@@ -646,8 +656,8 @@
fname : unicode
The path to the file to secure
"""
- import ctypes
- from ctypes import wintypes
+ import ctypes # noqa: PLC0415
+ from ctypes import wintypes # noqa: PLC0415
advapi32 = ctypes.WinDLL("advapi32", use_last_error=True) #
type:ignore[attr-defined]
secur32 = ctypes.WinDLL("secur32", use_last_error=True) #
type:ignore[attr-defined]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/jupyter_core/troubleshoot.py
new/jupyter_core-5.9.1/jupyter_core/troubleshoot.py
--- old/jupyter_core-5.8.1/jupyter_core/troubleshoot.py 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/jupyter_core/troubleshoot.py 2020-02-02
01:00:00.000000000 +0100
@@ -10,10 +10,10 @@
import platform
import subprocess
import sys
-from typing import Any, Optional, Union
+from typing import Any, Union
-def subs(cmd: Union[list[str], str]) -> Optional[str]:
+def subs(cmd: Union[list[str], str]) -> str | None:
"""
get data from commands that we need to run outside of python
"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/jupyter_core/utils/__init__.py
new/jupyter_core-5.9.1/jupyter_core/utils/__init__.py
--- old/jupyter_core-5.8.1/jupyter_core/utils/__init__.py 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/jupyter_core/utils/__init__.py 2020-02-02
01:00:00.000000000 +0100
@@ -9,10 +9,11 @@
import sys
import threading
import warnings
+from collections.abc import Awaitable, Callable
from contextvars import ContextVar
from pathlib import Path
from types import FrameType
-from typing import Any, Awaitable, Callable, TypeVar, cast
+from typing import Any, TypeVar, cast
def ensure_dir_exists(path: str | Path, mode: int = 0o777) -> None:
@@ -150,9 +151,15 @@
def wrapped(*args: Any, **kwargs: Any) -> Any:
name = threading.current_thread().name
inner = coro(*args, **kwargs)
+
+ loop_running = False
try:
asyncio.get_running_loop()
+ loop_running = True
except RuntimeError:
+ pass
+
+ if not loop_running:
# No loop running, run the loop for this thread.
loop = ensure_event_loop()
return loop.run_until_complete(inner)
@@ -176,7 +183,17 @@
loop = asyncio.get_running_loop()
except RuntimeError:
if sys.platform == "win32" and prefer_selector_loop:
- loop = asyncio.WindowsSelectorEventLoopPolicy().new_event_loop()
+ if (3, 14) <= sys.version_info < (3, 15):
+ # ignore deprecation only for 3.14 and revisit later.
+ with warnings.catch_warnings():
+ warnings.filterwarnings(
+ "ignore",
+ category=DeprecationWarning,
+ message=".*WindowsSelectorEventLoopPolicy.*",
+ )
+ loop =
asyncio.WindowsSelectorEventLoopPolicy().new_event_loop()
+ else:
+ loop =
asyncio.WindowsSelectorEventLoopPolicy().new_event_loop()
else:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/jupyter_core/version.py
new/jupyter_core-5.9.1/jupyter_core/version.py
--- old/jupyter_core-5.8.1/jupyter_core/version.py 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/jupyter_core/version.py 2020-02-02
01:00:00.000000000 +0100
@@ -7,7 +7,7 @@
import re
# Version string must appear intact for hatch versioning
-__version__ = "5.8.1"
+__version__ = "5.9.1"
# Build up version_info tuple for backwards compatibility
pattern = r"(?P<major>\d+).(?P<minor>\d+).(?P<patch>\d+)(?P<rest>.*)"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/pyproject.toml
new/jupyter_core-5.9.1/pyproject.toml
--- old/jupyter_core-5.8.1/pyproject.toml 2020-02-02 01:00:00.000000000
+0100
+++ new/jupyter_core-5.9.1/pyproject.toml 2020-02-02 01:00:00.000000000
+0100
@@ -15,11 +15,10 @@
"Programming Language :: Python",
"Programming Language :: Python :: 3"
]
-requires-python = ">=3.8"
+requires-python = ">=3.10"
dependencies = [
"platformdirs>=2.5",
"traitlets>=5.3",
- "pywin32>=300 ; sys_platform == 'win32' and platform_python_implementation
!= 'PyPy'"
]
dynamic = ["version"]
@@ -28,7 +27,7 @@
email = "[email protected]"
[project.readme]
-text = "There is no reason to install this package on its own."
+text = "Jupyter core package. A base package on which Jupyter projects rely."
content-type = "text/plain"
[project.urls]
@@ -97,13 +96,13 @@
detached = true
[tool.hatch.envs.lint.scripts]
build = [
- "pre-commit run --all-files ruff",
+ "pre-commit run --all-files ruff-check",
"pre-commit run --all-files ruff-format"
]
[tool.mypy]
files = "jupyter_core"
-python_version = "3.8"
+python_version = "3.14"
strict = true
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
warn_unreachable = true
@@ -111,6 +110,11 @@
disallow_untyped_defs = true
warn_redundant_casts = true
disallow_untyped_calls = true
+# This is a workaround for a mypy bug which is incapable of treating
sys.platform
+# correctly https://github.com/python/mypy/issues/10773
+# With pre-commit running on user platform and linux on CI you can't get the
+# types right, so we pin platform to linux
+platform = "linux"
[tool.pytest.ini_options]
minversion = "7.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/tests/test_application.py
new/jupyter_core-5.9.1/tests/test_application.py
--- old/jupyter_core-5.8.1/tests/test_application.py 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/tests/test_application.py 2020-02-02
01:00:00.000000000 +0100
@@ -3,6 +3,7 @@
import asyncio
import os
import shutil
+import sys
from tempfile import mkdtemp
from unittest.mock import patch
@@ -179,6 +180,7 @@
_prefer_selector_loop = True
[email protected](sys.platform == "win32", reason="does not run on windows")
def test_async_tornado_app():
AsyncTornadoApp.launch_instance([])
app = AsyncApp.instance()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/tests/test_command.py
new/jupyter_core-5.9.1/tests/test_command.py
--- old/jupyter_core-5.8.1/tests/test_command.py 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/tests/test_command.py 2020-02-02
01:00:00.000000000 +0100
@@ -65,7 +65,7 @@
if sys.platform == "win32":
try:
- import importlib.resources
+ import importlib.resources # noqa: PLC0415
if not hasattr(importlib.resources, "files"):
raise ImportError
@@ -152,7 +152,7 @@
assert "Jupyter command `jupyter-nonexistant-subcommand` not found." in
stderr
[email protected](sys, "argv", [__file__] + sys.argv[1:])
[email protected](sys, "argv", [__file__, *sys.argv[1:]])
def test_subcommand_list(tmpdir):
a = tmpdir.mkdir("a")
for cmd in ("jupyter-foo-bar", "jupyter-xyz", "jupyter-babel-fish"):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/tests/test_migrate.py
new/jupyter_core-5.9.1/tests/test_migrate.py
--- old/jupyter_core-5.8.1/tests/test_migrate.py 2020-02-02
01:00:00.000000000 +0100
+++ new/jupyter_core-5.9.1/tests/test_migrate.py 2020-02-02
01:00:00.000000000 +0100
@@ -132,8 +132,9 @@
called["migrate_dir"] = True
return migrate_dir(src, dst)
- with patch.object(migrate_mod, "migrate_file", notice_m_file),
patch.object(
- migrate_mod, "migrate_dir", notice_m_dir
+ with (
+ patch.object(migrate_mod, "migrate_file", notice_m_file),
+ patch.object(migrate_mod, "migrate_dir", notice_m_dir),
):
assert migrate_one(src, dst)
assert called == {"migrate_file": True}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-5.8.1/tests/test_paths.py
new/jupyter_core-5.9.1/tests/test_paths.py
--- old/jupyter_core-5.8.1/tests/test_paths.py 2020-02-02 01:00:00.000000000
+0100
+++ new/jupyter_core-5.9.1/tests/test_paths.py 2020-02-02 01:00:00.000000000
+0100
@@ -301,7 +301,7 @@
]
)
)
- for p, v in zip(path, values):
+ for p, v in zip(path, values, strict=False):
assert p == v
@@ -358,7 +358,7 @@
]
)
)
- for p, v in zip(path, values):
+ for p, v in zip(path, values, strict=False):
assert p == v
@@ -383,7 +383,7 @@
]
)
)
- for p, v in zip(path, values):
+ for p, v in zip(path, values, strict=False):
assert p == v
@@ -473,6 +473,19 @@
assert is_hidden(subdir78, root)
[email protected](
+ ("abs_path", "abs_root"),
+ [
+ ("relative.py", "/absolute"),
+ ("/absolute/path.py", "relative"),
+ ("/absolute/path.py", "/absolute/not/parent"),
+ ],
+)
+def test_is_hidden_invalid(abs_path, abs_root):
+ with pytest.raises(ValueError, match="abs"):
+ is_hidden(abs_path, abs_root)
+
+
@pytest.mark.skipif(
not (
sys.platform == "win32"
@@ -499,7 +512,7 @@
reason="only run on windows/pypy < 7.3.6:
https://foss.heptapod.net/pypy/pypy/-/issues/3469",
)
def test_is_hidden_win32_pypy():
- import ctypes # noqa: F401
+ import ctypes # noqa: F401, PLC0415
with tempfile.TemporaryDirectory() as root:
subdir1 = os.path.join(root, "subdir")