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 2023-12-25 19:05:32 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-jupyter-core (Old) and /work/SRC/openSUSE:Factory/.python-jupyter-core.new.28375 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-jupyter-core" Mon Dec 25 19:05:32 2023 rev:22 rq:1134926 version:5.5.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-jupyter-core/python-jupyter-core.changes 2023-11-27 22:43:30.594133525 +0100 +++ /work/SRC/openSUSE:Factory/.python-jupyter-core.new.28375/python-jupyter-core.changes 2023-12-25 19:05:46.622526147 +0100 @@ -1,0 +2,7 @@ +Sat Dec 23 19:23:58 UTC 2023 - Ben Greiner <c...@bnavigator.de> + +- Update to 5.5.1 + * Account for read only file systems in migration #379 + (@blink1073) + +------------------------------------------------------------------- Old: ---- jupyter_core-5.5.0.tar.gz New: ---- jupyter_core-5.5.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-jupyter-core.spec ++++++ --- /var/tmp/diff_new_pack.oxcSN8/_old 2023-12-25 19:05:47.278550087 +0100 +++ /var/tmp/diff_new_pack.oxcSN8/_new 2023-12-25 19:05:47.278550087 +0100 @@ -32,7 +32,7 @@ %endif Name: python-jupyter-core%{psuffix} -Version: 5.5.0 +Version: 5.5.1 Release: 0 Summary: Base package on which Jupyter projects rely License: BSD-3-Clause ++++++ jupyter_core-5.5.0.tar.gz -> jupyter_core-5.5.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/.github/workflows/downstream.yml new/jupyter_core-5.5.1/.github/workflows/downstream.yml --- old/jupyter_core-5.5.0/.github/workflows/downstream.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/.github/workflows/downstream.yml 2020-02-02 01:00:00.000000000 +0100 @@ -0,0 +1,82 @@ +name: Test downstream projects + +on: + push: + branches: ["main"] + pull_request: + +concurrency: + group: downstream-${{ github.ref }} + cancel-in-progress: true + +jobs: + ipykernel: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 + with: + package_name: ipykernel + + nbclient: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - 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=\<IPY-INPUT\> + + nbconvert: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 + with: + package_name: nbconvert + package_spec: pip install -e ".[test]" + + jupyter_server: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 + with: + package_name: jupyter_server + + jupyter_client: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Base Setup + uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + + - name: Run Test + uses: jupyterlab/maintainer-tools/.github/actions/downstream-test@v1 + with: + package_name: jupyter_client + + downstreams_check: # This job does nothing and is only used for the branch protection + if: always() + needs: + - ipykernel + - nbclient + - nbconvert + - jupyter_server + - jupyter_client + runs-on: ubuntu-latest + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/.github/workflows/test.yml new/jupyter_core-5.5.1/.github/workflows/test.yml --- old/jupyter_core-5.5.0/.github/workflows/test.yml 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/.github/workflows/test.yml 2020-02-02 01:00:00.000000000 +0100 @@ -112,7 +112,7 @@ - name: Run Linters run: | hatch run typing:test - hatch run lint:style + hatch run lint:build pipx run interrogate -v . pipx run doc8 --max-line-length=200 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/.pre-commit-config.yaml new/jupyter_core-5.5.1/.pre-commit-config.yaml --- old/jupyter_core-5.5.0/.pre-commit-config.yaml 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.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.27.0 + rev: 0.27.1 hooks: - id: check-github-workflows @@ -33,7 +33,7 @@ [mdformat-gfm, mdformat-frontmatter, mdformat-footnote] - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v3.0.3" + rev: "v3.1.0" hooks: - id: prettier types_or: [yaml, html, json] @@ -44,6 +44,15 @@ - id: blacken-docs additional_dependencies: [black==23.7.0] + - repo: https://github.com/pre-commit/mirrors-mypy + rev: "v1.7.1" + hooks: + - id: mypy + files: jupyter_core + stages: [manual] + args: ["--install-types", "--non-interactive"] + additional_dependencies: ["traitlets>=5.13", "platformdirs>=3.11"] + - repo: https://github.com/codespell-project/codespell rev: "v2.2.6" hooks: @@ -58,14 +67,16 @@ - id: rst-inline-touching-normal - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.3 + rev: v0.1.6 hooks: - id: ruff + types_or: [python, jupyter] args: ["--fix", "--show-fixes"] - id: ruff-format + types_or: [python, jupyter] - repo: https://github.com/scientific-python/cookie - rev: "2023.10.27" + rev: "2023.11.17" hooks: - id: sp-repo-review additional_dependencies: ["repo-review[cli]"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/CHANGELOG.md new/jupyter_core-5.5.1/CHANGELOG.md --- old/jupyter_core-5.5.0/CHANGELOG.md 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/CHANGELOG.md 2020-02-02 01:00:00.000000000 +0100 @@ -2,6 +2,28 @@ <!-- <START NEW CHANGELOG ENTRY> --> +## 5.5.1 + +([Full Changelog](https://github.com/jupyter/jupyter_core/compare/v5.5.0...4e387a4e95b1064cca4a97dd7324b29d14b6e3b7)) + +### Bugs fixed + +- Account for read only file systems in migration [#379](https://github.com/jupyter/jupyter_core/pull/379) ([@blink1073](https://github.com/blink1073)) + +### Maintenance and upkeep improvements + +- Update ruff and typings [#376](https://github.com/jupyter/jupyter_core/pull/376) ([@blink1073](https://github.com/blink1073)) +- chore: update pre-commit hooks [#374](https://github.com/jupyter/jupyter_core/pull/374) ([@pre-commit-ci](https://github.com/pre-commit-ci)) +- Clean up lint and add downstream checks [#373](https://github.com/jupyter/jupyter_core/pull/373) ([@blink1073](https://github.com/blink1073)) + +### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyter/jupyter_core/graphs/contributors?from=2023-10-30&to=2023-12-18&type=c)) + +[@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3Ablink1073+updated%3A2023-10-30..2023-12-18&type=Issues) | [@mtelka](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3Amtelka+updated%3A2023-10-30..2023-12-18&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3Apre-commit-ci+updated%3A2023-10-30..2023-12-18&type=Issues) + +<!-- <END NEW CHANGELOG ENTRY> --> + ## 5.5.0 ([Full Changelog](https://github.com/jupyter/jupyter_core/compare/v5.4.0...df0e9e709ebe208df799ec08030b7d7eb15c9cf9)) @@ -20,8 +42,6 @@ [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3Ablink1073+updated%3A2023-10-10..2023-10-30&type=Issues) | [@singingwolfboy](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_core+involves%3Asingingwolfboy+updated%3A2023-10-10..2023-10-30&type=Issues) -<!-- <END NEW CHANGELOG ENTRY> --> - ## 5.4.0 ([Full Changelog](https://github.com/jupyter/jupyter_core/compare/v5.3.2...d6a748262a44334f27008e8c90d2557f46481f5b)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/PKG-INFO new/jupyter_core-5.5.1/PKG-INFO --- old/jupyter_core-5.5.0/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: jupyter_core -Version: 5.5.0 +Version: 5.5.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/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/docs/conf.py new/jupyter_core-5.5.1/docs/conf.py --- old/jupyter_core-5.5.0/docs/conf.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/docs/conf.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 -# # jupyter_core documentation build configuration file, created by # sphinx-quickstart on Wed Jun 24 11:51:36 2015. # @@ -11,9 +9,10 @@ # # All configuration values have a default; values that are commented out # serve to show the default. +from __future__ import annotations -import os import shutil +from pathlib import Path from jupyter_core.version import __version__, version_info @@ -39,7 +38,7 @@ ] try: - import enchant # type:ignore # noqa + import enchant # noqa: F401 extensions += ["sphinxcontrib.spelling"] except ImportError: @@ -63,7 +62,7 @@ # General information about the project. project = "jupyter_core" -copyright = "2015, Jupyter Development Team" # noqa +copyright = "2015, Jupyter Development Team" author = "Jupyter Development Team" # The version info for the project you're documenting, acts as replacement for @@ -300,6 +299,6 @@ intersphinx_mapping = {"https://docs.python.org/3/": None} -def setup(app): - here = os.path.dirname(os.path.abspath(__file__)) - shutil.copy(os.path.join(here, "..", "CHANGELOG.md"), "changelog.md") +def setup(_): + here = Path(__file__).parent.resolve() + shutil.copy(Path(here, "..", "CHANGELOG.md"), "changelog.md") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/jupyter.py new/jupyter_core-5.5.1/jupyter.py --- old/jupyter_core-5.5.0/jupyter.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/jupyter.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,6 @@ """Launch the root jupyter command""" +from __future__ import annotations + if __name__ == "__main__": from jupyter_core.command import main diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/jupyter_core/__init__.py new/jupyter_core-5.5.1/jupyter_core/__init__.py --- old/jupyter_core-5.5.0/jupyter_core/__init__.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/jupyter_core/__init__.py 2020-02-02 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -from .version import __version__, version_info # noqa diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/jupyter_core/__main__.py new/jupyter_core-5.5.1/jupyter_core/__main__.py --- old/jupyter_core-5.5.0/jupyter_core/__main__.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/jupyter_core/__main__.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,6 @@ """Launch the root jupyter command""" +from __future__ import annotations + from .command import main main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/jupyter_core/application.py new/jupyter_core-5.5.1/jupyter_core/application.py --- old/jupyter_core-5.5.0/jupyter_core/application.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/jupyter_core/application.py 2020-02-02 01:00:00.000000000 +0100 @@ -13,6 +13,7 @@ import sys import typing as t from copy import deepcopy +from pathlib import Path from shutil import which from traitlets import Bool, List, Unicode, observe @@ -62,7 +63,7 @@ base_flags.update(_jupyter_flags) -class NoStart(Exception): # noqa +class NoStart(Exception): """Exception to raise when an application shouldn't start""" @@ -135,9 +136,9 @@ if self.config_file: config_file = self.config_file else: - config_file = os.path.join(self.config_dir, self.config_file_name + ".py") + config_file = str(Path(self.config_dir, self.config_file_name + ".py")) - if os.path.exists(config_file) and not self.answer_yes: + if Path(config_file).exists() and not self.answer_yes: answer = "" def ask() -> str: @@ -157,19 +158,19 @@ config_text = self.generate_config_file() print("Writing default config to: %s" % config_file) - ensure_dir_exists(os.path.abspath(os.path.dirname(config_file)), 0o700) - with open(config_file, mode="w", encoding="utf-8") as f: + 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) def migrate_config(self) -> None: """Migrate config/data from IPython 3""" try: # let's see if we can open the marker file # for reading and updating (writing) - f_marker = open(os.path.join(self.config_dir, "migrated"), "r+") # noqa - except PermissionError: # not readable and/or writable - return # so let's give up migration in such an environment + f_marker = Path.open(Path(self.config_dir, "migrated"), "r+") except FileNotFoundError: # cannot find the marker file pass # that means we have not migrated yet, so continue + except OSError: # not readable and/or writable + return # so let's give up migration in such an environment else: # if we got here without raising anything, # that means the file exists f_marker.close() @@ -178,7 +179,7 @@ from .migrate import get_ipython_dir, migrate # No IPython dir, nothing to migrate - if not os.path.exists(get_ipython_dir()): + if not Path(get_ipython_dir()).exists(): return migrate() @@ -262,7 +263,7 @@ def start(self) -> None: """Start the whole thing""" if self.subcommand: - os.execv(self.subcommand, [self.subcommand] + self.argv[1:]) # noqa + 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.5.0/jupyter_core/command.py new/jupyter_core-5.5.1/jupyter_core/command.py --- old/jupyter_core-5.5.0/jupyter_core/command.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/jupyter_core/command.py 2020-02-02 01:00:00.000000000 +0100 @@ -15,6 +15,7 @@ import site import sys import sysconfig +from pathlib import Path from shutil import which from subprocess import Popen from typing import Any @@ -37,7 +38,6 @@ @epilog.setter def epilog(self, x: Any) -> None: """Ignore epilog set in Parser.__init__""" - pass def argcomplete(self) -> None: """Trigger auto-completion, if enabled""" @@ -63,7 +63,7 @@ "subcommand", type=str, nargs="?", help="the subcommand to launch" ) # For argcomplete, supply all known subcommands - subcommand_action.completer = lambda *args, **kwargs: list_subcommands() # type: ignore[attr-defined] + subcommand_action.completer = lambda *args, **kwargs: list_subcommands() # type: ignore[attr-defined] # noqa: ARG005 group.add_argument("--config-dir", action="store_true", help="show Jupyter config dir") group.add_argument("--data-dir", action="store_true", help="show Jupyter data dir") @@ -98,7 +98,7 @@ if name.startswith("jupyter-"): if sys.platform.startswith("win"): # remove file-extension on Windows - name = os.path.splitext(name)[0] # noqa + name = os.path.splitext(name)[0] # noqa: PTH122, PLW2901 subcommand_tuples.add(tuple(name.split("-")[1:])) # build a set of subcommand strings, excluding subcommands whose parents are defined subcommands = set() @@ -120,7 +120,7 @@ cmd_path = which(cmd) if cmd_path is None: raise OSError("%r not found" % cmd, errno.ENOENT) - p = Popen([cmd_path] + argv[1:]) # noqa + 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 @@ -129,7 +129,7 @@ p.wait() sys.exit(p.returncode) else: - os.execvp(cmd, argv) # noqa + os.execvp(cmd, argv) # noqa: S606 def _jupyter_abspath(subcommand: str) -> str: @@ -177,13 +177,13 @@ path_list.append(bindir) scripts = [sys.argv[0]] - if os.path.islink(scripts[0]): + if Path(scripts[0]).is_symlink(): # include realpath, if `jupyter` is a symlink scripts.append(os.path.realpath(scripts[0])) for script in scripts: - bindir = os.path.dirname(script) - if os.path.isdir(bindir) and os.access(script, os.X_OK): # only if it's a script + bindir = str(Path(script).parent) + if Path(bindir).is_dir() and os.access(script, os.X_OK): # only if it's a script # ensure executable's dir is on PATH # avoids missing subcommands when jupyter is run via absolute path path_list.insert(0, bindir) @@ -211,9 +211,8 @@ # increment word from which to start handling arguments increment_argcomplete_index() return cwords - else: - # Otherwise no subcommand, directly autocomplete and exit - parser.argcomplete() + # Otherwise no subcommand, directly autocomplete and exit + parser.argcomplete() except ImportError: # traitlets >= 5.8 not available, just try to complete this without # worrying about subcommands @@ -222,7 +221,7 @@ raise AssertionError(msg) -def main() -> None: # noqa +def main() -> None: """The command entry point.""" parser = jupyter_parser() argv = sys.argv diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/jupyter_core/migrate.py new/jupyter_core-5.5.1/jupyter_core/migrate.py --- old/jupyter_core-5.5.0/jupyter_core/migrate.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/jupyter_core/migrate.py 2020-02-02 01:00:00.000000000 +0100 @@ -29,6 +29,7 @@ import re import shutil from datetime import datetime, timezone +from pathlib import Path from typing import Any from traitlets.config.loader import JSONFileConfigLoader, PyFileConfigLoader @@ -41,20 +42,18 @@ # mypy: disable-error-code="no-untyped-call" -pjoin = os.path.join - migrations = { - pjoin("{ipython_dir}", "nbextensions"): pjoin("{jupyter_data}", "nbextensions"), - pjoin("{ipython_dir}", "kernels"): pjoin("{jupyter_data}", "kernels"), - pjoin("{profile}", "nbconfig"): pjoin("{jupyter_config}", "nbconfig"), + str(Path("{ipython_dir}", "nbextensions")): str(Path("{jupyter_data}", "nbextensions")), + str(Path("{ipython_dir}", "kernels")): str(Path("{jupyter_data}", "kernels")), + str(Path("{profile}", "nbconfig")): str(Path("{jupyter_config}", "nbconfig")), } -custom_src_t = pjoin("{profile}", "static", "custom") -custom_dst_t = pjoin("{jupyter_config}", "custom") +custom_src_t = str(Path("{profile}", "static", "custom")) +custom_dst_t = str(Path("{jupyter_config}", "custom")) for security_file in ("notebook_secret", "notebook_cookie_secret", "nbsignatures.db"): - src = pjoin("{profile}", "security", security_file) - dst = pjoin("{jupyter_data}", security_file) + src = str(Path("{profile}", "security", security_file)) + dst = str(Path("{jupyter_data}", security_file)) migrations[src] = dst config_migrations = ["notebook", "nbconvert", "qtconsole"] @@ -81,7 +80,7 @@ We only need to support the IPython < 4 behavior for migration, so importing for forward-compatibility and edge cases is not important. """ - return os.environ.get("IPYTHONDIR", os.path.expanduser("~/.ipython")) + return os.environ.get("IPYTHONDIR", str(Path("~/.ipython").expanduser())) def migrate_dir(src: str, dst: str) -> bool: @@ -90,38 +89,37 @@ if not os.listdir(src): log.debug("No files in %s", src) return False - if os.path.exists(dst): + if Path(dst).exists(): if os.listdir(dst): # already exists, non-empty log.debug("%s already exists", dst) return False - else: - os.rmdir(dst) + Path(dst).rmdir() log.info("Copying %s -> %s", src, dst) - ensure_dir_exists(os.path.dirname(dst)) + ensure_dir_exists(Path(dst).parent) shutil.copytree(src, dst, symlinks=True) return True -def migrate_file(src: str, dst: str, substitutions: Any = None) -> bool: +def migrate_file(src: str | Path, dst: str | Path, substitutions: Any = None) -> bool: """Migrate a single file from src to dst substitutions is an optional dict of {regex: replacement} for performing replacements on the file. """ log = get_logger() - if os.path.exists(dst): + if Path(dst).exists(): # already exists log.debug("%s already exists", dst) return False log.info("Copying %s -> %s", src, dst) - ensure_dir_exists(os.path.dirname(dst)) + ensure_dir_exists(Path(dst).parent) shutil.copy(src, dst) if substitutions: - with open(dst, encoding="utf-8") as f: + with Path.open(Path(dst), encoding="utf-8") as f: text = f.read() for pat, replacement in substitutions.items(): text = pat.sub(replacement, text) - with open(dst, "w", encoding="utf-8") as f: + with Path.open(Path(dst), "w", encoding="utf-8") as f: f.write(text) return True @@ -132,13 +130,12 @@ dispatches to migrate_dir/_file """ log = get_logger() - if os.path.isfile(src): + if Path(src).is_file(): return migrate_file(src, dst) - elif os.path.isdir(src): + if Path(src).is_dir(): return migrate_dir(src, dst) - else: - log.debug("Nothing to migrate for %s", src) - return False + log.debug("Nothing to migrate for %s", src) + return False def migrate_static_custom(src: str, dst: str) -> bool: @@ -149,12 +146,12 @@ log = get_logger() migrated = False - custom_js = pjoin(src, "custom.js") - custom_css = pjoin(src, "custom.css") + custom_js = Path(src, "custom.js") + custom_css = Path(src, "custom.css") # check if custom_js is empty: custom_js_empty = True - if os.path.isfile(custom_js): - with open(custom_js, encoding="utf-8") as f: + if Path(custom_js).is_file(): + with Path.open(custom_js, encoding="utf-8") as f: js = f.read().strip() for line in js.splitlines(): if not (line.isspace() or line.strip().startswith(("/*", "*", "//"))): @@ -163,8 +160,8 @@ # check if custom_css is empty: custom_css_empty = True - if os.path.isfile(custom_css): - with open(custom_css, encoding="utf-8") as f: + if Path(custom_css).is_file(): + with Path.open(custom_css, encoding="utf-8") as f: css = f.read().strip() custom_css_empty = css.startswith("/*") and css.endswith("*/") @@ -181,9 +178,9 @@ if not custom_js_empty or not custom_css_empty: ensure_dir_exists(dst) - if not custom_js_empty and migrate_file(custom_js, pjoin(dst, "custom.js")): + if not custom_js_empty and migrate_file(custom_js, Path(dst, "custom.js")): migrated = True - if not custom_css_empty and migrate_file(custom_css, pjoin(dst, "custom.css")): + if not custom_css_empty and migrate_file(custom_css, Path(dst, "custom.css")): migrated = True return migrated @@ -195,8 +192,8 @@ Includes substitutions for updated configurable names. """ log = get_logger() - src_base = pjoin("{profile}", "ipython_{name}_config").format(name=name, **env) - dst_base = pjoin("{jupyter_config}", "jupyter_{name}_config").format(name=name, **env) + src_base = str(Path(f"{env['profile']}", f"ipython_{name}_config")) + dst_base = str(Path(f"{env['jupyter_config']}", f"jupyter_{name}_config")) loaders = { ".py": PyFileConfigLoader, ".json": JSONFileConfigLoader, @@ -205,7 +202,7 @@ for ext in (".py", ".json"): src = src_base + ext dst = dst_base + ext - if os.path.exists(src): + if Path(src).exists(): cfg = loaders[ext](src).load_config() if cfg: if migrate_file(src, dst, substitutions=config_substitutions): @@ -222,13 +219,13 @@ "jupyter_data": jupyter_data_dir(), "jupyter_config": jupyter_config_dir(), "ipython_dir": get_ipython_dir(), - "profile": os.path.join(get_ipython_dir(), "profile_default"), + "profile": str(Path(get_ipython_dir(), "profile_default")), } migrated = False for src_t, dst_t in migrations.items(): src = src_t.format(**env) dst = dst_t.format(**env) - if os.path.exists(src) and migrate_one(src, dst): + if Path(src).exists() and migrate_one(src, dst): migrated = True for name in config_migrations: @@ -238,12 +235,12 @@ custom_src = custom_src_t.format(**env) custom_dst = custom_dst_t.format(**env) - if os.path.exists(custom_src) and migrate_static_custom(custom_src, custom_dst): + if Path(custom_src).exists() and migrate_static_custom(custom_src, custom_dst): migrated = True # write a marker to avoid re-running migration checks ensure_dir_exists(env["jupyter_config"]) - with open(os.path.join(env["jupyter_config"], "migrated"), "w", encoding="utf-8") as f: + with Path.open(Path(env["jupyter_config"], "migrated"), "w", encoding="utf-8") as f: f.write(datetime.now(tz=timezone.utc).isoformat()) return migrated diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/jupyter_core/paths.py new/jupyter_core-5.5.1/jupyter_core/paths.py --- old/jupyter_core-5.5.0/jupyter_core/paths.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/jupyter_core/paths.py 2020-02-02 01:00:00.000000000 +0100 @@ -6,7 +6,7 @@ # Derived from IPython.utils.path, which is # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. - +from __future__ import annotations import errno import os @@ -17,7 +17,7 @@ import warnings from contextlib import contextmanager from pathlib import Path -from typing import Any, Dict, Iterator, List, Optional +from typing import Any, Iterator, Optional import platformdirs @@ -63,14 +63,13 @@ def get_home_dir() -> str: """Get the real path of the home directory""" - homedir = os.path.expanduser("~") + homedir = Path("~").expanduser() # Next line will make things work even when /home/ is a symlink to # /usr/home as it is on FreeBSD, for example - homedir = str(Path(homedir).resolve()) - return homedir + return str(Path(homedir).resolve()) -_dtemps: Dict[str, str] = {} +_dtemps: dict[str, str] = {} def _do_i_own(path: str) -> bool: @@ -85,7 +84,7 @@ # not always implemented or available try: return p.owner() == os.getlogin() - except Exception: # noqa + except Exception: # noqa: S110 pass if hasattr(os, "geteuid"): @@ -174,19 +173,17 @@ home = get_home_dir() if sys.platform == "darwin": - return os.path.join(home, "Library", "Jupyter") - elif os.name == "nt": + return str(Path(home, "Library", "Jupyter")) + if sys.platform == "win32": appdata = os.environ.get("APPDATA", None) if appdata: return str(Path(appdata, "jupyter").resolve()) - else: - return pjoin(jupyter_config_dir(), "data") - else: - # Linux, non-OS X Unix, AIX, etc. - xdg = env.get("XDG_DATA_HOME", None) - if not xdg: - xdg = pjoin(home, ".local", "share") - return pjoin(xdg, "jupyter") + return pjoin(jupyter_config_dir(), "data") + # Linux, non-OS X Unix, AIX, etc. + xdg = env.get("XDG_DATA_HOME", None) + if not xdg: + xdg = pjoin(home, ".local", "share") + return pjoin(xdg, "jupyter") def jupyter_runtime_dir() -> str: @@ -222,17 +219,17 @@ if programdata: SYSTEM_JUPYTER_PATH = [pjoin(programdata, "jupyter")] else: # PROGRAMDATA is not defined by default on XP. - SYSTEM_JUPYTER_PATH = [os.path.join(sys.prefix, "share", "jupyter")] + SYSTEM_JUPYTER_PATH = [str(Path(sys.prefix, "share", "jupyter"))] else: SYSTEM_JUPYTER_PATH = [ "/usr/local/share/jupyter", "/usr/share/jupyter", ] -ENV_JUPYTER_PATH: List[str] = [os.path.join(sys.prefix, "share", "jupyter")] +ENV_JUPYTER_PATH: list[str] = [str(Path(sys.prefix, "share", "jupyter"))] -def jupyter_path(*subdirs: str) -> List[str]: +def jupyter_path(*subdirs: str) -> list[str]: """Return a list of directories to search for data files JUPYTER_PATH environment variable has highest priority. @@ -254,7 +251,7 @@ ['~/.local/jupyter/kernels', '/usr/local/share/jupyter/kernels'] """ - paths: List[str] = [] + paths: list[str] = [] # highest priority is explicit environment variable if os.environ.get("JUPYTER_PATH"): @@ -269,7 +266,7 @@ userbase = site.getuserbase() if hasattr(site, "getuserbase") else site.USER_BASE if userbase: - userdir = os.path.join(userbase, "share", "jupyter") + userdir = str(Path(userbase, "share", "jupyter")) if userdir not in user: user.append(userdir) @@ -295,11 +292,11 @@ SYSTEM_CONFIG_PATH = platformdirs.site_config_dir( APPNAME, appauthor=False, multipath=True ).split(os.pathsep) -else: # noqa: PLR5501 +else: if os.name == "nt": programdata = os.environ.get("PROGRAMDATA", None) - if programdata: # noqa - SYSTEM_CONFIG_PATH = [os.path.join(programdata, "jupyter")] + if programdata: # noqa: SIM108 + SYSTEM_CONFIG_PATH = [str(Path(programdata, "jupyter"))] else: # PROGRAMDATA is not defined by default on XP. SYSTEM_CONFIG_PATH = [] else: @@ -307,10 +304,10 @@ "/usr/local/etc/jupyter", "/etc/jupyter", ] -ENV_CONFIG_PATH: List[str] = [os.path.join(sys.prefix, "etc", "jupyter")] +ENV_CONFIG_PATH: list[str] = [str(Path(sys.prefix, "etc", "jupyter"))] -def jupyter_config_path() -> List[str]: +def jupyter_config_path() -> list[str]: """Return the search path for Jupyter config files as a list. If the JUPYTER_PREFER_ENV_PATH environment variable is set, the @@ -324,7 +321,7 @@ # jupyter_config_dir makes a blank config when JUPYTER_NO_CONFIG is set. return [jupyter_config_dir()] - paths: List[str] = [] + paths: list[str] = [] # highest priority is explicit environment variable if os.environ.get("JUPYTER_CONFIG_PATH"): @@ -339,7 +336,7 @@ userbase = site.getuserbase() if hasattr(site, "getuserbase") else site.USER_BASE if userbase: - userdir = os.path.join(userbase, "etc", "jupyter") + userdir = str(Path(userbase, "etc", "jupyter")) if userdir not in user: user.append(userdir) @@ -384,12 +381,12 @@ The result of calling stat() on abs_path. If not passed, this function will call stat() internally. """ - if os.path.basename(abs_path).startswith("."): + if Path(abs_path).name.startswith("."): return True if stat_res is None: try: - stat_res = os.stat(abs_path) + stat_res = Path(abs_path).stat() except OSError as e: if e.errno == errno.ENOENT: return False @@ -409,7 +406,6 @@ "hidden files are not detectable on this system, so no file will be marked as hidden.", stacklevel=2, ) - pass return False @@ -430,19 +426,19 @@ The result of calling stat() on abs_path. If not passed, this function will call stat() internally. """ - if os.path.basename(abs_path).startswith("."): + if Path(abs_path).name.startswith("."): return True if stat_res is None or stat.S_ISLNK(stat_res.st_mode): try: - stat_res = os.stat(abs_path) + stat_res = Path(abs_path).stat() except OSError as e: if e.errno == errno.ENOENT: return False raise # check that dirs can be listed - if stat.S_ISDIR(stat_res.st_mode): # type:ignore[misc] # noqa + if stat.S_ISDIR(stat_res.st_mode): # noqa: SIM102 # use x-access, not actual listing, in case of slow/large listings if not os.access(abs_path, os.X_OK | os.R_OK): return True @@ -492,15 +488,15 @@ 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 inside_root.split(os.sep)): + if any(part.startswith(".") for part in Path(inside_root).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 = os.path.dirname(abs_path) + path = str(Path(abs_path).parent) while path and path.startswith(abs_root) and path != abs_root: - if not exists(path): - path = os.path.dirname(path) + if not Path(path).exists(): + path = str(Path(path).parent) continue try: # may fail on Windows junctions @@ -509,7 +505,7 @@ return True if getattr(st, "st_flags", 0) & UF_HIDDEN: return True - path = os.path.dirname(path) + path = str(Path(path).parent) return False @@ -555,9 +551,10 @@ sd.SetSecurityDescriptorDacl(1, dacl, 0) win32security.SetFileSecurity(fname, win32security.DACL_SECURITY_INFORMATION, sd) + return None -def _win32_restrict_file_to_user_ctypes(fname: str) -> None: # noqa +def _win32_restrict_file_to_user_ctypes(fname: str) -> None: """Secure a windows file to read-only access for the user. Follows guidance from win32 library creator: @@ -611,7 +608,7 @@ ) class ACL(ctypes.Structure): - _fields_ = [ # noqa + _fields_ = [ ("AclRevision", wintypes.BYTE), ("Sbz1", wintypes.BYTE), ("AclSize", wintypes.WORD), @@ -623,7 +620,7 @@ PACL = ctypes.POINTER(ACL) PSECURITY_DESCRIPTOR = ctypes.POINTER(wintypes.BYTE) - def _nonzero_success(result: int, func: Any, args: Any) -> Any: + def _nonzero_success(result: int, func: Any, args: Any) -> Any: # noqa: ARG001 if not result: raise ctypes.WinError(ctypes.get_last_error()) # type:ignore[attr-defined] return args @@ -950,7 +947,7 @@ # the missing least significant bit on the third octal digit. In addition, we also tolerate # the sticky bit being set, so the lsb from the fourth octal digit is also removed. return ( - stat.S_IMODE(os.stat(fname).st_mode) & 0o6677 + stat.S_IMODE(Path(fname).stat().st_mode) & 0o6677 ) # Use 4 octal digits since S_IMODE does the same @@ -976,7 +973,7 @@ encoding = None if binary else "utf-8" open_flag = os.O_CREAT | os.O_WRONLY | os.O_TRUNC try: - os.remove(fname) + Path(fname).unlink() except OSError: # Skip any issues with the file not existing pass @@ -999,7 +996,7 @@ if os.name != "nt": # Enforce that the file got the requested permissions before writing file_mode = get_file_mode(fname) - if file_mode != 0o0600: # noqa + if file_mode != 0o0600: if allow_insecure_writes: issue_insecure_write_warning() else: @@ -1014,7 +1011,7 @@ def issue_insecure_write_warning() -> None: """Issue an insecure write warning.""" - def format_warning(msg: str, *args: Any, **kwargs: Any) -> str: + def format_warning(msg: str, *args: Any, **kwargs: Any) -> str: # noqa: ARG001 return str(msg) + "\n" warnings.formatwarning = format_warning # type:ignore[assignment] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/jupyter_core/troubleshoot.py new/jupyter_core-5.5.1/jupyter_core/troubleshoot.py --- old/jupyter_core-5.5.0/jupyter_core/troubleshoot.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/jupyter_core/troubleshoot.py 2020-02-02 01:00:00.000000000 +0100 @@ -3,30 +3,31 @@ display environment information that is frequently used to troubleshoot installations of Jupyter or IPython """ +from __future__ import annotations import os import platform import subprocess import sys -from typing import Any, Dict, List, Optional, Union +from typing import Any, Optional, Union -def subs(cmd: Union[List[str], str]) -> Optional[str]: +def subs(cmd: Union[list[str], str]) -> Optional[str]: """ get data from commands that we need to run outside of python """ try: - stdout = subprocess.check_output(cmd) # noqa + stdout = subprocess.check_output(cmd) # noqa: S603 return stdout.decode("utf-8", "replace").strip() except (OSError, subprocess.CalledProcessError): return None -def get_data() -> Dict[str, Any]: +def get_data() -> dict[str, Any]: """ returns a dict of various user environment data """ - env: Dict[str, Any] = {} + env: dict[str, Any] = {} env["path"] = os.environ.get("PATH") env["sys_path"] = sys.path env["sys_exe"] = sys.executable @@ -45,7 +46,7 @@ return env -def main() -> None: # noqa +def main() -> None: """ print out useful info """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/jupyter_core/utils/__init__.py new/jupyter_core-5.5.1/jupyter_core/utils/__init__.py --- old/jupyter_core-5.5.0/jupyter_core/utils/__init__.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/jupyter_core/utils/__init__.py 2020-02-02 01:00:00.000000000 +0100 @@ -6,7 +6,6 @@ import atexit import errno import inspect -import os import sys import threading import warnings @@ -15,7 +14,7 @@ from typing import Any, Awaitable, Callable, TypeVar, cast -def ensure_dir_exists(path: str, mode: int = 0o777) -> None: +def ensure_dir_exists(path: str | Path, mode: int = 0o777) -> None: """Ensure that a directory exists If it doesn't exist, try to create it, protecting against a race condition @@ -23,11 +22,11 @@ The default permissions are determined by the current umask. """ try: - os.makedirs(path, mode=mode) + Path(path).mkdir(parents=True, mode=mode) except OSError as e: if e.errno != errno.EEXIST: raise - if not os.path.isdir(path): + if not Path(path).is_dir(): raise OSError("%r exists but is not a directory" % path) @@ -108,7 +107,7 @@ def _runner(self) -> None: loop = self.__io_loop - assert loop is not None # noqa + assert loop is not None try: loop.run_forever() finally: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/jupyter_core/version.py new/jupyter_core-5.5.1/jupyter_core/version.py --- old/jupyter_core-5.5.0/jupyter_core/version.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/jupyter_core/version.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,17 +1,18 @@ """ store the current version info of the jupyter_core. """ +from __future__ import annotations + import re -from typing import List # Version string must appear intact for hatch versioning -__version__ = "5.5.0" +__version__ = "5.5.1" # Build up version_info tuple for backwards compatibility pattern = r"(?P<major>\d+).(?P<minor>\d+).(?P<patch>\d+)(?P<rest>.*)" match = re.match(pattern, __version__) -assert match is not None # noqa -parts: List[object] = [int(match[part]) for part in ["major", "minor", "patch"]] +assert match is not None +parts: list[object] = [int(match[part]) for part in ["major", "minor", "patch"]] if match["rest"]: parts.append(match["rest"]) version_info = tuple(parts) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/pyproject.toml new/jupyter_core-5.5.1/pyproject.toml --- old/jupyter_core-5.5.0/pyproject.toml 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/pyproject.toml 2020-02-02 01:00:00.000000000 +0100 @@ -88,31 +88,24 @@ nowarn = "test -W default {args}" [tool.hatch.envs.typing] -features = ["test"] -dependencies = ["mypy~=1.6.0", "traitlets>=5.13.0"] +dependencies = ["pre-commit"] +detached = true [tool.hatch.envs.typing.scripts] -test = "mypy --install-types --non-interactive {args}" +test = "pre-commit run --all-files --hook-stage manual mypy" [tool.hatch.envs.lint] -dependencies = ["mdformat>0.7", "ruff==0.1.3"] +dependencies = ["pre-commit"] detached = true [tool.hatch.envs.lint.scripts] -style = [ - "ruff {args:.}", - "ruff format {args:.}", - "mdformat --check {args:*.md}" -] -fmt = [ - "ruff --fix {args:.}", - "ruff format {args:.}", - "mdformat {args:*.md}" +build = [ + "pre-commit run --all-files ruff", + "pre-commit run --all-files ruff-format" ] [tool.mypy] files = "jupyter_core" python_version = "3.8" strict = true -show_error_codes = true enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] warn_unreachable = true @@ -154,24 +147,42 @@ ] [tool.ruff] -target-version = "py38" line-length = 100 [tool.ruff.lint] -select = [ - "A", "B", "C", "DTZ", "E", "EM", "F", "FBT", "I", "ICN", "N", - "PLC", "PLE", "PLR", "PLW", "Q", "RUF", "S", "SIM", "T", "TID", "UP", - "W", "YTT", +extend-select = [ + "B", # flake8-bugbear + "I", # isort + "ARG", # flake8-unused-arguments + "C4", # flake8-comprehensions + "EM", # flake8-errmsg + "ICN", # flake8-import-conventions + "G", # flake8-logging-format + "PGH", # pygrep-hooks + "PIE", # flake8-pie + "PL", # pylint + "PT", # flake8-pytest-style + "PTH", # flake8-use-pathlib + "RET", # flake8-return + "RUF", # Ruff-specific + "SIM", # flake8-simplify + "T20", # flake8-print + "UP", # pyupgrade + "YTT", # flake8-2020 + "EXE", # flake8-executable + "NPY", # NumPy specific rules + "PD", # pandas-vet + "PYI", # flake8-pyi + "S", # flake8-bandit ] ignore = [ - # Q000 Single quotes found but double quotes preferred - "Q000", - # FBT001 Boolean positional arg in function definition - "FBT001", "FBT002", "FBT003", - # E501 Line too long (158 > 100 characters) - "E501", - # SIM105 Use `contextlib.suppress(...)` - "SIM105", + "PLR", # Design related pylint codes + "Q000", # Single quotes found but double quotes preferred + "E501", # Line too long (158 > 100 characters) + "UP007", # Use `X | Y` for type annotations" + "SIM105", # Use `contextlib.suppress(...)` + "S101", # Use of assert + "RUF012" # Mutable class attributes should be annotated ] unfixable = [ # Don't touch print statements @@ -179,6 +190,7 @@ # Don't touch noqa lines "RUF100", ] +isort.required-imports = ["from __future__ import annotations"] [tool.ruff.lint.per-file-ignores] # B011 Do not call assert False since python -O removes these calls @@ -188,11 +200,9 @@ # T201 `print` found # B007 Loop control variable `i` not used within the loop body. # N802 Function name `assertIn` should be lowercase -# S101 Use of `assert` detected -# S108 Probable insecure usage of temporary file or directory: "/tmp" # PLR2004 Magic value used in comparison, consider replacing b'WITNESS A' with a constant variable # S603 `subprocess` call: check for execution of untrusted input -"tests/*" = ["B011", "F841", "C408", "E402", "T201", "B007", "N802", "S101", "S108", "PLR2004", "S603"] +"tests/*" = ["B011", "F841", "C408", "E402", "T201", "B007", "N802", "S", "PTH", "ARG0"] # F821 Undefined name `get_config` "tests/**/profile_default/*_config.py" = ["F821"] # T201 `print` found @@ -217,6 +227,3 @@ [tool.check-wheel-contents] toplevel = ["jupyter_core/", "jupyter.py"] ignore = ["W002"] - -[tool.repo-review] -ignore = ["PY007", "PP308", "GH102", "PC140"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/scripts/jupyter new/jupyter_core-5.5.1/scripts/jupyter --- old/jupyter_core-5.5.0/scripts/jupyter 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/scripts/jupyter 2020-02-02 01:00:00.000000000 +0100 @@ -1,5 +1,6 @@ #!/usr/bin/env python """Launch the root jupyter command""" +from __future__ import annotations from jupyter_core.command import main diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/scripts/jupyter-migrate new/jupyter_core-5.5.1/scripts/jupyter-migrate --- old/jupyter_core-5.5.0/scripts/jupyter-migrate 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/scripts/jupyter-migrate 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,7 @@ #!/usr/bin/env python # PYTHON_ARGCOMPLETE_OK """Migrate Jupyter config from IPython < 4.0""" +from __future__ import annotations from jupyter_core.migrate import main diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/dotipython/profile_default/ipython_config.py new/jupyter_core-5.5.1/tests/dotipython/profile_default/ipython_config.py --- old/jupyter_core-5.5.0/tests/dotipython/profile_default/ipython_config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/dotipython/profile_default/ipython_config.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,5 @@ # Configuration file for ipython. +from __future__ import annotations c = get_config() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/dotipython/profile_default/ipython_console_config.py new/jupyter_core-5.5.1/tests/dotipython/profile_default/ipython_console_config.py --- old/jupyter_core-5.5.0/tests/dotipython/profile_default/ipython_console_config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/dotipython/profile_default/ipython_console_config.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,5 @@ # Configuration file for ipython-console. +from __future__ import annotations c = get_config() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/dotipython/profile_default/ipython_kernel_config.py new/jupyter_core-5.5.1/tests/dotipython/profile_default/ipython_kernel_config.py --- old/jupyter_core-5.5.0/tests/dotipython/profile_default/ipython_kernel_config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/dotipython/profile_default/ipython_kernel_config.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,5 @@ # Configuration file for ipython-kernel. +from __future__ import annotations c = get_config() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/dotipython/profile_default/ipython_nbconvert_config.py new/jupyter_core-5.5.1/tests/dotipython/profile_default/ipython_nbconvert_config.py --- old/jupyter_core-5.5.0/tests/dotipython/profile_default/ipython_nbconvert_config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/dotipython/profile_default/ipython_nbconvert_config.py 2020-02-02 01:00:00.000000000 +0100 @@ -1 +1,3 @@ +from __future__ import annotations + c.NbConvertApp.post_processors = [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/dotipython/profile_default/ipython_notebook_config.py new/jupyter_core-5.5.1/tests/dotipython/profile_default/ipython_notebook_config.py --- old/jupyter_core-5.5.0/tests/dotipython/profile_default/ipython_notebook_config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/dotipython/profile_default/ipython_notebook_config.py 2020-02-02 01:00:00.000000000 +0100 @@ -1 +1,3 @@ +from __future__ import annotations + c.NotebookApp.open_browser = False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/dotipython_empty/profile_default/ipython_config.py new/jupyter_core-5.5.1/tests/dotipython_empty/profile_default/ipython_config.py --- old/jupyter_core-5.5.0/tests/dotipython_empty/profile_default/ipython_config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/dotipython_empty/profile_default/ipython_config.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,5 @@ # Configuration file for ipython. +from __future__ import annotations c = get_config() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/dotipython_empty/profile_default/ipython_console_config.py new/jupyter_core-5.5.1/tests/dotipython_empty/profile_default/ipython_console_config.py --- old/jupyter_core-5.5.0/tests/dotipython_empty/profile_default/ipython_console_config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/dotipython_empty/profile_default/ipython_console_config.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,5 @@ # Configuration file for ipython-console. +from __future__ import annotations c = get_config() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/dotipython_empty/profile_default/ipython_kernel_config.py new/jupyter_core-5.5.1/tests/dotipython_empty/profile_default/ipython_kernel_config.py --- old/jupyter_core-5.5.0/tests/dotipython_empty/profile_default/ipython_kernel_config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/dotipython_empty/profile_default/ipython_kernel_config.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,5 @@ # Configuration file for ipython-kernel. +from __future__ import annotations c = get_config() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/dotipython_empty/profile_default/ipython_nbconvert_config.py new/jupyter_core-5.5.1/tests/dotipython_empty/profile_default/ipython_nbconvert_config.py --- old/jupyter_core-5.5.0/tests/dotipython_empty/profile_default/ipython_nbconvert_config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/dotipython_empty/profile_default/ipython_nbconvert_config.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,5 @@ # Configuration file for ipython-nbconvert. +from __future__ import annotations c = get_config() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/dotipython_empty/profile_default/ipython_notebook_config.py new/jupyter_core-5.5.1/tests/dotipython_empty/profile_default/ipython_notebook_config.py --- old/jupyter_core-5.5.0/tests/dotipython_empty/profile_default/ipython_notebook_config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/dotipython_empty/profile_default/ipython_notebook_config.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,5 @@ # Configuration file for ipython-notebook. +from __future__ import annotations c = get_config() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/mocking.py new/jupyter_core-5.5.1/tests/mocking.py --- old/jupyter_core-5.5.0/tests/mocking.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/mocking.py 2020-02-02 01:00:00.000000000 +0100 @@ -2,6 +2,7 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. +from __future__ import annotations import os import sys diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/test_application.py new/jupyter_core-5.5.1/tests/test_application.py --- old/jupyter_core-5.5.0/tests/test_application.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/test_application.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,3 +1,5 @@ +from __future__ import annotations + import os import shutil from tempfile import mkdtemp @@ -107,7 +109,7 @@ with open(pjoin(config_dir, "dummy_app_config.py"), "w", encoding="utf-8") as f: f.write('c.DummyApp.m = "a\n') # Syntax error - with pytest.raises(SyntaxError): + with pytest.raises(SyntaxError): # noqa: PT012 app = DummyApp(config_dir=config_dir) app.raise_config_file_errors = True app.initialize([]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/test_command.py new/jupyter_core-5.5.1/tests/test_command.py --- old/jupyter_core-5.5.0/tests/test_command.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/test_command.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,5 @@ """Test the Jupyter command-line""" +from __future__ import annotations import json import os diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/test_migrate.py new/jupyter_core-5.5.1/tests/test_migrate.py --- old/jupyter_core-5.5.0/tests/test_migrate.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/test_migrate.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,7 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. """Test config file migration""" +from __future__ import annotations import os import re @@ -28,15 +29,15 @@ dotipython_empty = pjoin(here, "dotipython_empty") -@pytest.fixture +@pytest.fixture() def td(request): """Fixture for a temporary directory""" td = mkdtemp("μnïcøâe") - request.addfinalizer(lambda: shutil.rmtree(td)) - return td + yield td + shutil.rmtree(td) -@pytest.fixture +@pytest.fixture() def env(request): """Fixture for a full testing environment""" td = mkdtemp() @@ -51,14 +52,10 @@ env_patch = patch.dict(os.environ, env) env_patch.start() - def fin(): - """Cleanup test env""" - env_patch.stop() - shutil.rmtree(td, ignore_errors=os.name == "nt") + yield env - request.addfinalizer(fin) - - return env + env_patch.stop() + shutil.rmtree(td, ignore_errors=os.name == "nt") def touch(path, content=""): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/test_paths.py new/jupyter_core-5.5.1/tests/test_paths.py --- old/jupyter_core-5.5.0/tests/test_paths.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/test_paths.py 2020-02-02 01:00:00.000000000 +0100 @@ -2,6 +2,7 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. +from __future__ import annotations import os import re @@ -468,13 +469,11 @@ reason="only run on windows/cpython or pypy >= 7.3.6: https://foss.heptapod.net/pypy/pypy/-/issues/3469", ) def test_is_hidden_win32_cpython(): - import ctypes # noqa - with tempfile.TemporaryDirectory() as root: subdir1 = os.path.join(root, "subdir") os.makedirs(subdir1) assert not is_hidden(subdir1, root) - subprocess.check_call(["attrib", "+h", subdir1]) # noqa + subprocess.check_call(["attrib", "+h", subdir1]) assert is_hidden(subdir1, root) assert is_file_hidden(subdir1) @@ -488,13 +487,13 @@ 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 + import ctypes # noqa: F401 with tempfile.TemporaryDirectory() as root: subdir1 = os.path.join(root, "subdir") os.makedirs(subdir1) assert not is_hidden(subdir1, root) - subprocess.check_call(["attrib", "+h", subdir1]) # noqa + subprocess.check_call(["attrib", "+h", subdir1]) with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. @@ -527,12 +526,12 @@ def fetch_win32_permissions(filename): """Extracts file permissions on windows using icacls""" role_permissions = {} - proc = os.popen("icacls %s" % filename) # noqa + proc = os.popen("icacls %s" % filename) lines = proc.read().splitlines() proc.close() for index, line in enumerate(lines): if index == 0: - line = line.split(filename)[-1].strip().lower() # noqa + line = line.split(filename)[-1].strip().lower() # noqa: PLW2901 match = re.match(r"\s*([^:]+):\(([^\)]*)\)", line) if match: usergroup, permissions = match.groups() @@ -575,16 +574,16 @@ with secure_write(fname) as f: f.write("test 1") mode = os.stat(fname).st_mode - assert 0o0600 == (stat.S_IMODE(mode) & 0o7677) # noqa # tolerate owner-execute bit + assert (stat.S_IMODE(mode) & 0o7677) == 0o0600 # tolerate owner-execute bit with open(fname, encoding="utf-8") as f: assert f.read() == "test 1" # Try changing file permissions ahead of time - os.chmod(fname, 0o755) # noqa + os.chmod(fname, 0o755) with secure_write(fname) as f: f.write("test 2") mode = os.stat(fname).st_mode - assert 0o0600 == (stat.S_IMODE(mode) & 0o7677) # noqa # tolerate owner-execute bit + assert (stat.S_IMODE(mode) & 0o7677) == 0o0600 # tolerate owner-execute bit with open(fname, encoding="utf-8") as f: assert f.read() == "test 2" finally: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/test_troubleshoot.py new/jupyter_core-5.5.1/tests/test_troubleshoot.py --- old/jupyter_core-5.5.0/tests/test_troubleshoot.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/test_troubleshoot.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,3 +1,5 @@ +from __future__ import annotations + from jupyter_core.troubleshoot import main diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyter_core-5.5.0/tests/test_utils.py new/jupyter_core-5.5.1/tests/test_utils.py --- old/jupyter_core-5.5.0/tests/test_utils.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyter_core-5.5.1/tests/test_utils.py 2020-02-02 01:00:00.000000000 +0100 @@ -2,6 +2,7 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. +from __future__ import annotations import asyncio import os @@ -41,9 +42,11 @@ foo_sync = run_sync(foo) assert foo_sync() == 1 assert foo_sync() == 1 + asyncio.get_event_loop().close() asyncio.set_event_loop(None) assert foo_sync() == 1 + asyncio.get_event_loop().close() asyncio.run(foo()) ++++++ use_rpms_paths.patch ++++++ --- /var/tmp/diff_new_pack.oxcSN8/_old 2023-12-25 19:05:47.382553882 +0100 +++ /var/tmp/diff_new_pack.oxcSN8/_new 2023-12-25 19:05:47.382553882 +0100 @@ -7,13 +7,13 @@ --- -Index: jupyter_core-5.3.2/jupyter_core/paths.py +Index: jupyter_core-5.5.1/jupyter_core/paths.py =================================================================== ---- jupyter_core-5.3.2.orig/jupyter_core/paths.py -+++ jupyter_core-5.3.2/jupyter_core/paths.py -@@ -219,10 +219,7 @@ else: +--- jupyter_core-5.5.1.orig/jupyter_core/paths.py ++++ jupyter_core-5.5.1/jupyter_core/paths.py +@@ -221,10 +221,7 @@ else: else: # PROGRAMDATA is not defined by default on XP. - SYSTEM_JUPYTER_PATH = [os.path.join(sys.prefix, "share", "jupyter")] + SYSTEM_JUPYTER_PATH = [str(Path(sys.prefix, "share", "jupyter"))] else: - SYSTEM_JUPYTER_PATH = [ - "/usr/local/share/jupyter", @@ -21,9 +21,9 @@ - ] + SYSTEM_JUPYTER_PATH = [ "@_datadir_jupyter_@" ] - ENV_JUPYTER_PATH: List[str] = [os.path.join(sys.prefix, "share", "jupyter")] + ENV_JUPYTER_PATH: list[str] = [str(Path(sys.prefix, "share", "jupyter"))] -@@ -243,10 +240,10 @@ def jupyter_path(*subdirs: str) -> List[ +@@ -245,10 +242,10 @@ def jupyter_path(*subdirs: str) -> list[ Examples: @@ -37,17 +37,15 @@ + ['~/.local/share/jupyter/kernels', '@_datadir_jupyter_@/kernels'] """ - paths: List[str] = [] -@@ -298,10 +295,7 @@ else: # noqa: PLR5501 - else: # PROGRAMDATA is not defined by default on XP. + paths: list[str] = [] +@@ -301,8 +298,7 @@ else: SYSTEM_CONFIG_PATH = [] else: -- SYSTEM_CONFIG_PATH = [ + SYSTEM_CONFIG_PATH = [ - "/usr/local/etc/jupyter", - "/etc/jupyter", -- ] -+ SYSTEM_CONFIG_PATH = [ "@_distconfdir_jupyter_@" ] - ENV_CONFIG_PATH: List[str] = [os.path.join(sys.prefix, "etc", "jupyter")] - ++ "@_distconfdir_jupyter_@" + ] + ENV_CONFIG_PATH: list[str] = [str(Path(sys.prefix, "etc", "jupyter"))]