From ba8b71150cfed0acaa2b4d4bc6ccb4302f9d40d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 May 2024 10:31:18 +0200 Subject: [PATCH] Bump the pip group with 7 updates (#16270) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump the pip group with 7 updates Updates the requirements on [sphinx](https://github.com/sphinx-doc/sphinx), [matplotlib](https://github.com/matplotlib/matplotlib), [pandas](https://github.com/pandas-dev/pandas), [scipy](https://github.com/scipy/scipy), [ruff](https://github.com/astral-sh/ruff), [pyyaml-include](https://github.com/tanbro/pyyaml-include) and [pydantic](https://github.com/pydantic/pydantic) to permit the latest version. Updates `sphinx` to 7.3.7 - [Release notes](https://github.com/sphinx-doc/sphinx/releases) - [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES.rst) - [Commits](https://github.com/sphinx-doc/sphinx/compare/v1.8.0...v7.3.7) Updates `matplotlib` from 3.8.3 to 3.8.4 - [Release notes](https://github.com/matplotlib/matplotlib/releases) - [Commits](https://github.com/matplotlib/matplotlib/compare/v3.8.3...v3.8.4) Updates `pandas` from 2.2.1 to 2.2.2 - [Release notes](https://github.com/pandas-dev/pandas/releases) - [Commits](https://github.com/pandas-dev/pandas/compare/v2.2.1...v2.2.2) Updates `scipy` from 1.12.0 to 1.13.0 - [Release notes](https://github.com/scipy/scipy/releases) - [Commits](https://github.com/scipy/scipy/compare/v1.12.0...v1.13.0) Updates `ruff` from 0.3.5 to 0.4.2 - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/v0.3.5...v0.4.2) Updates `pyyaml-include` to 2.0.2.post1 - [Changelog](https://github.com/tanbro/pyyaml-include/blob/main/CHANGELOG.md) - [Commits](https://github.com/tanbro/pyyaml-include/compare/0.1a1...v2.0.2.post1) Updates `pydantic` to 2.7.1 - [Release notes](https://github.com/pydantic/pydantic/releases) - [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md) - [Commits](https://github.com/pydantic/pydantic/compare/v0.0.2...v2.7.1) --- updated-dependencies: - dependency-name: sphinx dependency-type: direct:production dependency-group: pip - dependency-name: matplotlib dependency-type: direct:production update-type: version-update:semver-patch dependency-group: pip - dependency-name: pandas dependency-type: direct:production update-type: version-update:semver-patch dependency-group: pip - dependency-name: scipy dependency-type: direct:production update-type: version-update:semver-minor dependency-group: pip - dependency-name: ruff dependency-type: direct:production update-type: version-update:semver-minor dependency-group: pip - dependency-name: pyyaml-include dependency-type: direct:production dependency-group: pip - dependency-name: pydantic dependency-type: direct:production dependency-group: pip ... Signed-off-by: dependabot[bot] * Fix ruff UP031 * More lint fixes * Ignore UP031 for milestone_check.py * Format --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Frédéric Collonval Co-authored-by: Frédéric Collonval --- .pre-commit-config.yaml | 2 +- examples/test_examples.py | 8 +- jupyterlab/commands.py | 140 +++++++++++++------------- jupyterlab/extensions/manager.py | 2 +- jupyterlab/federated_labextensions.py | 20 ++-- jupyterlab/handlers/error_handler.py | 6 +- jupyterlab/labapp.py | 26 +++-- jupyterlab/labextensions.py | 4 +- jupyterlab/utils.py | 7 +- pyproject.toml | 16 +-- scripts/ci_script.sh | 2 +- scripts/milestone_check.py | 12 +-- 12 files changed, 119 insertions(+), 126 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 950f52a2f594..93fe72bcbbb1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,7 +33,7 @@ repos: # Check ruff version is aligned with the one in pyproject.toml - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.5 + rev: v0.4.2 hooks: - id: ruff args: ["--fix"] diff --git a/examples/test_examples.py b/examples/test_examples.py index dbf8390d8cd5..817252f1125d 100644 --- a/examples/test_examples.py +++ b/examples/test_examples.py @@ -33,14 +33,14 @@ def main(): parser.add_argument("--testPath", help="paths containing this string are tested") args = parser.parse_args() - paths = [i for i in glob.glob("%s/*" % here) if osp.isdir(i)] + paths = [i for i in glob.glob(f"{here}/*") if osp.isdir(i)] services_dir = osp.abspath(osp.join(here, "../packages/services/examples")) - paths += list(glob.glob("%s/*" % services_dir)) + paths += list(glob.glob(f"{services_dir}/*")) if args.testPath: paths = [p for p in paths if args.testPath in p] - print("Testing %s" % paths) + print(f"Testing {paths}") count = 0 failed = [] for path in sorted(paths): @@ -64,7 +64,7 @@ def main(): msg = "The following examples failed:\n-{}".format("\n-".join(failed)) raise AssertionError(msg) - print("\n\n%s tests complete!" % count) + print(f"\n\n{count} tests complete!") if __name__ == "__main__": diff --git a/jupyterlab/commands.py b/jupyterlab/commands.py index ef0d23a5fc6d..143df3bd8612 100644 --- a/jupyterlab/commands.py +++ b/jupyterlab/commands.py @@ -265,7 +265,7 @@ def ensure_app(app_dir): return msgs = [ - 'JupyterLab application assets not found in "%s"' % app_dir, + f'JupyterLab application assets not found in "{app_dir}"', "Please run `jupyter lab build` or use a different app directory", ] return msgs @@ -467,7 +467,7 @@ def clean(app_options=None): logger = app_options.logger app_dir = app_options.app_dir - logger.info("Cleaning %s...", app_dir) + logger.info(f"Cleaning {app_dir}...") if app_dir == pjoin(HERE, "dev"): msg = "Cannot clean the dev app" raise ValueError(msg) @@ -476,7 +476,7 @@ def clean(app_options=None): raise ValueError(msg) if getattr(app_options, "all", False): - logger.info("Removing everything in %s...", app_dir) + logger.info(f"Removing everything in {app_dir}...") _rmtree_star(app_dir, logger) else: possible_targets = ["extensions", "settings", "staging", "static"] @@ -485,10 +485,10 @@ def clean(app_options=None): for name in targets: target = pjoin(app_dir, name) if osp.exists(target): - logger.info("Removing %s...", name) + logger.info(f"Removing {name}...") _rmtree(target, logger) else: - logger.info("%s not present, skipping...", name) + logger.info(f"{name} not present, skipping...") logger.info("Success!") if getattr(app_options, "all", False) or getattr(app_options, "extensions", False): @@ -671,7 +671,7 @@ def install_extension(self, extension, existing=None, pin=None): config = self._read_build_config() uninstalled = config.get("uninstalled_core_extensions", []) if extension in uninstalled: - self.logger.info("Installing core extension %s" % extension) + self.logger.info(f"Installing core extension {extension}") uninstalled.remove(extension) config["uninstalled_core_extensions"] = uninstalled self._write_build_config(config) @@ -778,8 +778,8 @@ def list_extensions(self): # noqa self._ensure_disabled_info() logger = self.logger info = self.info - - logger.info("JupyterLab v%s" % info["version"]) + version = info["version"] + logger.info(f"JupyterLab v{version}") if info["federated_extensions"] or info["extensions"]: info["compat_errors"] = self._get_extension_compat() @@ -808,7 +808,7 @@ def list_extensions(self): # noqa uninstalled_core = info["uninstalled_core"] if uninstalled_core: logger.info("\nUninstalled core extensions:") - [logger.info(" %s" % item) for item in sorted(uninstalled_core)] + [logger.info(f" {item}") for item in sorted(uninstalled_core)] all_exts = ( list(info["federated_extensions"]) @@ -823,7 +823,7 @@ def list_extensions(self): # noqa # Show that all plugins will be disabled if the whole extension matches if item in all_exts: item += " (all plugins)" # noqa PLW2901 - logger.info(" %s" % item) + logger.info(f" {item}") # Here check if modules are improperly shadowed improper_shadowed = [] @@ -837,12 +837,12 @@ def list_extensions(self): # noqa logger.info( "\nThe following source extensions are overshadowed by older prebuilt extensions:" ) - [logger.info(" %s" % name) for name in sorted(improper_shadowed)] + [logger.info(f" {name}") for name in sorted(improper_shadowed)] messages = self.build_check(fast=True) if messages: logger.info("\nBuild recommended, please run `jupyter lab build`:") - [logger.info(" %s" % item) for item in messages] + [logger.info(f" {item}") for item in messages] def build_check(self, fast=None): # noqa """Determine whether JupyterLab should be built. @@ -870,8 +870,8 @@ def build_check(self, fast=None): # noqa if not static_version.endswith("-spliced"): core_version = old_jlab["version"] if Version(static_version) != Version(core_version): - msg = "Version mismatch: %s (built), %s (current)" - return [msg % (static_version, core_version)] + msg = f"Version mismatch: {static_version} (built), {core_version} (current)" + return [msg] shadowed_exts = self.info["shadowed_exts"] @@ -886,14 +886,14 @@ def build_check(self, fast=None): # noqa if ext in shadowed_exts: continue if ext not in old_jlab[ext_type]: - messages.append("%s needs to be included in build" % ext) + messages.append(f"{ext} needs to be included in build") # Extensions that were removed. for ext in old_jlab[ext_type]: if ext in shadowed_exts: continue if ext not in new_jlab[ext_type]: - messages.append("%s needs to be removed from build" % ext) + messages.append(f"{ext} needs to be removed from build") # Look for mismatched dependencies src_pkg_dir = pjoin(REPO_ROOT, "packages") @@ -906,8 +906,8 @@ def build_check(self, fast=None): # noqa if pkg in local or pkg in linked: continue if old_deps[pkg] != dep: - msg = "%s changed from %s to %s" - messages.append(msg % (pkg, old_deps[pkg], new_deps[pkg])) + msg = f"{pkg} changed from {old_deps[pkg]} to {new_deps[pkg]}" + messages.append(msg) # Look for updated local extensions. for name, source in local.items(): @@ -915,7 +915,7 @@ def build_check(self, fast=None): # noqa continue dname = pjoin(app_dir, "extensions") if self._check_local(name, source, dname): - messages.append("%s content changed" % name) + messages.append(f"{name} content changed") # Look for updated linked packages. for name, item in linked.items(): @@ -923,7 +923,7 @@ def build_check(self, fast=None): # noqa continue dname = pjoin(app_dir, "staging", "linked_packages") if self._check_local(name, item["source"], dname): - messages.append("%s content changed" % name) + messages.append(f"{name} content changed") return messages @@ -941,14 +941,13 @@ def uninstall_extension(self, name): .get("install", {}) .get("uninstallInstructions", None) ): - logger.error( - "JupyterLab cannot uninstall this extension. %s" - % info["federated_extensions"][name]["install"]["uninstallInstructions"] - ) + instructions = info["federated_extensions"][name]["install"][ + "uninstallInstructions" + ] + logger.error(f"JupyterLab cannot uninstall this extension. {instructions}") else: logger.error( - "JupyterLab cannot uninstall %s since it was installed outside of JupyterLab. Use the same method used to install this extension to uninstall this extension." - % name + f"JupyterLab cannot uninstall {name} since it was installed outside of JupyterLab. Use the same method used to install this extension to uninstall this extension." ) return False @@ -957,7 +956,7 @@ def uninstall_extension(self, name): config = self._read_build_config() uninstalled = config.get("uninstalled_core_extensions", []) if name not in uninstalled: - logger.info("Uninstalling core extension %s" % name) + logger.info(f"Uninstalling core extension {name}") uninstalled.append(name) config["uninstalled_core_extensions"] = uninstalled self._write_build_config(config) @@ -980,7 +979,7 @@ def uninstall_extension(self, name): self._write_build_config(config) return True - logger.warning('No labextension named "%s" installed' % name) + logger.warning(f'No labextension named "{name}" installed') return False def uninstall_all_extensions(self): @@ -1014,7 +1013,7 @@ def update_extension(self, name): Returns `True` if a rebuild is recommended, `False` otherwise. """ if name not in self.info["extensions"]: - self.logger.warning('No labextension named "%s" installed' % name) + self.logger.warning(f'No labextension named "{name}" installed') return False return self._update_extension(name) @@ -1025,7 +1024,7 @@ def _update_extension(self, name): """ data = self.info["extensions"][name] if data["alias_package_source"]: - self.logger.warning("Skipping updating pinned extension '%s'." % name) + self.logger.warning(f"Skipping updating pinned extension '{name}'.") return False try: latest = self._latest_compatible_package_version(name) @@ -1035,7 +1034,7 @@ def _update_extension(self, name): self.logger.warning(f"No compatible version found for {name}!") return False if latest == data["version"]: - self.logger.info("Extension %r already up to date" % name) + self.logger.info(f"Extension {name!r} already up to date") return False self.logger.info(f"Updating {name} to version {latest}") return self.install_extension(f"{name}@{latest}") @@ -1047,8 +1046,8 @@ def link_package(self, path): """ path = _normalize_path(path) if not osp.exists(path) or not osp.isdir(path): - msg = 'Cannot install "%s" only link local directories' - raise ValueError(msg % path) + msg = f'Cannot install "{path}" only link local directories' + raise ValueError(msg) with TemporaryDirectory() as tempdir: info = self._extract_package(path, tempdir) @@ -1059,9 +1058,9 @@ def link_package(self, path): # Warn that it is a linked package. self.logger.warning( - "Installing %s as a linked package because it does not have extension metadata:", path + f"Installing {path} as a linked package because it does not have extension metadata:" ) - [self.logger.warning(" %s" % m) for m in messages] + [self.logger.warning(f" {m}") for m in messages] # Add to metadata. config = self._read_build_config() @@ -1100,7 +1099,8 @@ def unlink_package(self, path): os.remove(path) if not found: - raise ValueError("No linked package for %s" % path) + msg = f"No linked package for {path}" + raise ValueError(msg) self._write_build_config(config) return True @@ -1331,7 +1331,7 @@ def _populate_staging(self, name=None, version=None, static_url=None, clean=Fals app_dir = self.app_dir staging = pjoin(app_dir, "staging") if clean and osp.exists(staging): - self.logger.info("Cleaning %s", staging) + self.logger.info(f"Cleaning {staging}") _rmtree(staging, self.logger) self._ensure_app_dirs() @@ -1668,7 +1668,7 @@ def _get_linked_packages(self): data = read_package(path) name = data["name"] if name not in info: - self.logger.warning("Removing orphaned linked package %s" % name) + self.logger.warning(f"Removing orphaned linked package {name}") os.remove(path) continue item = info[name] @@ -1699,11 +1699,11 @@ def _list_extensions(self, info, ext_type): """List the extensions of a given type.""" self._ensure_disabled_info() logger = self.logger - names = info["%s_extensions" % ext_type] + names = info[f"{ext_type}_extensions"] if not names: return - dname = info["%s_dir" % ext_type] + dname = info[f"{ext_type}_dir"] error_accumulator = {} @@ -1769,13 +1769,13 @@ def _list_federated_extensions(self): def _compose_extra_status(self, name: str, info: dict, data: dict, errors) -> str: extra = "" if _is_disabled(name, info["disabled"]): - extra += " %s" % RED_DISABLED + extra += f" {RED_DISABLED}" else: - extra += " %s" % GREEN_ENABLED + extra += f" {GREEN_ENABLED}" if errors: - extra += " %s" % RED_X + extra += f" {RED_X}" else: - extra += " %s" % GREEN_OK + extra += f" {GREEN_OK}" if data["is_local"]: extra += "*" lock_status = _is_locked(name, info["locked"]) @@ -1783,7 +1783,7 @@ def _compose_extra_status(self, name: str, info: dict, data: dict, errors) -> st extra += " 🔒 (all plugins locked)" elif lock_status.locked_plugins: plugin_list = ", ".join(sorted(lock_status.locked_plugins)) - extra += " 🔒 (plugins: %s locked)" % plugin_list + extra += f" 🔒 (plugins: {plugin_list} locked)" return extra def _read_build_config(self): @@ -1838,8 +1838,8 @@ def _install_extension(self, extension, tempdir, pin=None): # Verify that the package is an extension. messages = _validate_extension(data) if messages: - msg = '"%s" is not a valid extension:\n%s' - msg = msg % (extension, "\n".join(messages)) + all_messages = "\n".join(messages) + msg = f'"{extension}" is not a valid extension:\n{all_messages}' if allow_fallback: try: version = self._latest_compatible_package_version(name) @@ -1861,8 +1861,8 @@ def _install_extension(self, extension, tempdir, pin=None): raise ValueError(msg) from None if version and name: - self.logger.debug("Incompatible extension:\n%s", name) - self.logger.debug("Found compatible version: %s", version) + self.logger.debug(f"Incompatible extension:\n{name}") + self.logger.debug(f"Found compatible version: {version}") with TemporaryDirectory() as tempdir2: return self._install_extension(f"{name}@{version}", tempdir2) @@ -1897,14 +1897,14 @@ def _extract_package(self, source, tempdir, pin=None): ret = self._run([which("npm"), "pack", source], cwd=tempdir) if ret != 0: - msg = '"%s" is not a valid npm package' - raise ValueError(msg % source) + msg = f'"{source}" is not a valid npm package' + raise ValueError(msg) path = glob(pjoin(tempdir, "*.tgz"))[0] info["data"] = read_package(path) if is_dir: info["sha"] = sha = _tarsum(path) - target = path.replace(".tgz", "-%s.tgz" % sha) + target = path.replace(".tgz", f"-{sha}.tgz") shutil.move(path, target) info["path"] = target else: @@ -1992,8 +1992,8 @@ def sort_key(key_value): with TemporaryDirectory() as tempdir: ret = self._run([which("npm"), "pack", *keys], cwd=tempdir) if ret != 0: - msg = '"%s" is not a valid npm package' - raise ValueError(msg % keys) + msg = f'"{keys}" is not a valid npm package' + raise ValueError(msg) for key in keys: fname = ( @@ -2043,12 +2043,12 @@ def sort_key(key_value): # All singleton deps in current version of lab are newer than those # in the latest version of the extension return ( - 'The extension "%s" does not yet support the current version of ' - "JupyterLab.\n" % name + f'The extension "{name}" does not yet support the current version of ' + "JupyterLab.\n" ) parts = [ - "No version of {extension} could be found that is compatible with " + f"No version of {name} could be found that is compatible with " "the current version of JupyterLab." ] if latest_newer_than_lab: @@ -2059,7 +2059,7 @@ def sort_key(key_value): ) ) - return " ".join(parts).format(extension=name) + return " ".join(parts) def _run(self, cmd, **kwargs): """Run the command using our logger and abort callback. @@ -2085,10 +2085,7 @@ def _node_check(logger): except Exception: data = CoreConfig()._data ver = data["engines"]["node"] - msg = ( - "Please install nodejs %s before continuing. nodejs may be installed using conda or directly from the nodejs website." - % ver - ) + msg = f"Please install nodejs {ver} before continuing. nodejs may be installed using conda or directly from the nodejs website." raise ValueError(msg) from None @@ -2216,16 +2213,16 @@ def _validate_extension(data): # noqa mime_extension += ".js" if extension and extension not in files: - messages.append('Missing extension module "%s"' % extension) + messages.append(f'Missing extension module "{extension}"') if mime_extension and mime_extension not in files: - messages.append('Missing mimeExtension module "%s"' % mime_extension) + messages.append(f'Missing mimeExtension module "{mime_extension}"') if theme_path and not any(f.startswith(str(Path(theme_path))) for f in files): - messages.append('themePath is empty: "%s"' % theme_path) + messages.append(f'themePath is empty: "{theme_path}"') if schema_dir and not any(f.startswith(str(Path(schema_dir))) for f in files): - messages.append('schemaDir is empty: "%s"' % schema_dir) + messages.append(f'schemaDir is empty: "{schema_dir}"') return messages @@ -2439,8 +2436,7 @@ def _format_compatibility_errors(name, version, errors): l0 = max(l0, len(pkg) + 1) l1 = max(l1, len(jlab) + 1) - msg = '\n"%s@%s" is not compatible with the current JupyterLab' - msg = msg % (name, version) + msg = f'\n"{name}@{version}" is not compatible with the current JupyterLab' msg += "\nConflicting Dependencies:\n" msg += "JupyterLab".ljust(l0) msg += "Extension".ljust(l1) @@ -2492,7 +2488,7 @@ def _log_single_compat_errors(logger, name, version, errors): age = _compat_error_age(errors) if age > 0: - logger.warning('The extension "%s" is outdated.\n', name) + logger.warning(f'The extension "{name}" is outdated.\n') else: msg = _format_compatibility_errors(name, version, errors) logger.warning(f"{msg}\n") @@ -2588,14 +2584,14 @@ def _fetch_package_metadata(registry, name, logger): }, ) try: - logger.debug("Fetching URL: %s" % (req.full_url)) + logger.debug(f"Fetching URL: {req.full_url}") except AttributeError: - logger.debug("Fetching URL: %s" % (req.get_full_url())) + logger.debug(f"Fetching URL: {req.get_full_url()}") try: with contextlib.closing(urlopen(req)) as response: # noqa S310 return json.loads(response.read().decode("utf-8")) except URLError as exc: - logger.warning("Failed to fetch package metadata for %r: %r", name, exc) + logger.warning(f"Failed to fetch package metadata for {name!r}: {exc!r}") raise diff --git a/jupyterlab/extensions/manager.py b/jupyterlab/extensions/manager.py index 98e591a981c5..06dc3a9cdc35 100644 --- a/jupyterlab/extensions/manager.py +++ b/jupyterlab/extensions/manager.py @@ -207,7 +207,7 @@ def __init__( ) -> None: super().__init__(parent=parent) self.log.debug( - "Plugins in %s will managed on the %s level", self.__class__.__name__, self.level + f"Plugins in {self.__class__.__name__} will managed on the {self.level} level" ) self.app_options = _ensure_options(app_options) plugin_options_field = {f.name for f in fields(PluginManagerOptions)} diff --git a/jupyterlab/federated_labextensions.py b/jupyterlab/federated_labextensions.py index 00e7483151e5..c3733a2fe25a 100644 --- a/jupyterlab/federated_labextensions.py +++ b/jupyterlab/federated_labextensions.py @@ -102,7 +102,7 @@ def develop_labextension( # noqa full_dest = normpath(pjoin(labext, destination)) if overwrite and os.path.lexists(full_dest): if logger: - logger.info("Removing: %s" % full_dest) + logger.info(f"Removing: {full_dest}") if os.path.isdir(full_dest) and not os.path.islink(full_dest): shutil.rmtree(full_dest) else: @@ -129,7 +129,8 @@ def develop_labextension( # noqa raise elif not os.path.islink(full_dest): - raise ValueError("%s exists and is not a symlink" % full_dest) + msg = f"{full_dest} exists and is not a symlink" + raise ValueError(msg) elif os.path.isdir(path): path = pjoin(os.path.abspath(path), "") # end in path separator @@ -137,7 +138,7 @@ def develop_labextension( # noqa dest_dir = pjoin(full_dest, parent[len(path) :]) if not os.path.exists(dest_dir): if logger: - logger.info("Making directory: %s" % dest_dir) + logger.info(f"Making directory: {dest_dir}") os.makedirs(dest_dir) for file_name in files: src = pjoin(parent, file_name) @@ -202,7 +203,7 @@ def build_labextension( ext_path = str(Path(path).resolve()) if logger: - logger.info("Building extension in %s" % path) + logger.info(f"Building extension in {path}") builder = _ensure_builder(ext_path, core_path) @@ -225,7 +226,7 @@ def watch_labextension( ext_path = str(Path(path).resolve()) if logger: - logger.info("Building extension in %s" % path) + logger.info(f"Building extension in {path}") # Check to see if we need to create a symlink federated_extensions = get_federated_extensions(labextensions_path) @@ -268,9 +269,8 @@ def _ensure_builder(ext_path, core_path): dep_version2 = ext_data.get("devDependencies", {}).get("@jupyterlab/builder") dep_version2 = dep_version2 or ext_data.get("dependencies", {}).get("@jupyterlab/builder") if dep_version2 is None: - raise ValueError( - "Extensions require a devDependency on @jupyterlab/builder@%s" % dep_version1 - ) + msg = f"Extensions require a devDependency on @jupyterlab/builder@{dep_version1}" + raise ValueError(msg) # if we have installed from disk (version is a path), assume we know what # we are doing and do not check versions. @@ -331,10 +331,10 @@ def _should_copy(src, dest, logger=None): # we add a fudge factor to work around a bug in python 2.x # that was fixed in python 3.x: https://bugs.python.org/issue12904 if logger: - logger.warning("Out of date: %s" % dest) + logger.warning(f"Out of date: {dest}") return True if logger: - logger.info("Up to date: %s" % dest) + logger.info(f"Up to date: {dest}") return False diff --git a/jupyterlab/handlers/error_handler.py b/jupyterlab/handlers/error_handler.py index f2d936ba2bc9..ed6bf9270d7c 100644 --- a/jupyterlab/handlers/error_handler.py +++ b/jupyterlab/handlers/error_handler.py @@ -16,7 +16,7 @@

JupyterLab Error

-%s +{messages} """ @@ -29,5 +29,5 @@ def initialize(self, messages=None, name=None): @web.authenticated @web.removeslash def get(self): - msgs = ["

%s

" % msg for msg in self.messages] - self.write(TEMPLATE % "\n".join(msgs)) + msgs = [f"

{msg}

" for msg in self.messages] + self.write(TEMPLATE.format(messages="\n".join(msgs))) diff --git a/jupyterlab/labapp.py b/jupyterlab/labapp.py index a9aab613cfc9..49a8d1bd8280 100644 --- a/jupyterlab/labapp.py +++ b/jupyterlab/labapp.py @@ -188,12 +188,12 @@ def start(self): core_config=self.core_config, splice_source=self.splice_source, ) - self.log.info("JupyterLab %s", version) + self.log.info(f"JupyterLab {version}") with self.debug_logging(): if self.pre_clean: - self.log.info("Cleaning %s" % app_dir) + self.log.info(f"Cleaning {app_dir}") clean(app_options=app_options) - self.log.info("Building in %s", app_dir) + self.log.info(f"Building in {app_dir}") try: production = None if self.dev_build is None else not self.dev_build build( @@ -216,7 +216,7 @@ def start(self): clean_flags = dict(base_flags) clean_flags["extensions"] = ( {"LabCleanApp": {"extensions": True}}, - "Also delete /extensions.\n%s" % ext_warn_msg, + f"Also delete /extensions.\n{ext_warn_msg}", ) clean_flags["settings"] = ( {"LabCleanApp": {"settings": True}}, @@ -228,7 +228,7 @@ def start(self): ) clean_flags["all"] = ( {"LabCleanApp": {"all": True}}, - "Delete the entire contents of the app directory.\n%s" % ext_warn_msg, + f"Delete the entire contents of the app directory.\n{ext_warn_msg}", ) @@ -257,9 +257,7 @@ class LabCleanApp(JupyterApp): app_dir = Unicode("", config=True, help="The app directory to clean") - extensions = Bool( - False, config=True, help="Also delete /extensions.\n%s" % ext_warn_msg - ) + extensions = Bool(False, config=True, help=f"Also delete /extensions.\n{ext_warn_msg}") settings = Bool(False, config=True, help="Also delete /settings") @@ -268,7 +266,7 @@ class LabCleanApp(JupyterApp): all = Bool( False, config=True, - help="Delete the entire contents of the app directory.\n%s" % ext_warn_msg, + help=f"Delete the entire contents of the app directory.\n{ext_warn_msg}", ) def start(self): @@ -300,9 +298,9 @@ class LabPathApp(JupyterApp): """ def start(self): - print("Application directory: %s" % get_app_dir()) - print("User Settings directory: %s" % get_user_settings_dir()) - print("Workspaces directory: %s" % get_workspaces_dir()) + print(f"Application directory: {get_app_dir()}") + print(f"User Settings directory: {get_user_settings_dir()}") + print(f"Workspaces directory: {get_workspaces_dir()}") class LabWorkspaceExportApp(WorkspaceExportApp): @@ -742,8 +740,8 @@ def initialize_handlers(self): # noqa # Client-side code assumes notebookVersion is a JSON-encoded string page_config["notebookVersion"] = json.dumps(jpserver_version_info) - self.log.info("JupyterLab extension loaded from %s" % HERE) - self.log.info("JupyterLab application directory is %s" % self.app_dir) + self.log.info(f"JupyterLab extension loaded from {HERE!s}") + self.log.info(f"JupyterLab application directory is {self.app_dir!s}") if self.custom_css: handlers.append( diff --git a/jupyterlab/labextensions.py b/jupyterlab/labextensions.py index e6e07c71c1ca..edf34e125510 100644 --- a/jupyterlab/labextensions.py +++ b/jupyterlab/labextensions.py @@ -187,7 +187,7 @@ def run_task(self): def deprecation_warning(self, msg): return self.log.warning( - "\033[33m(Deprecated) %s\n\n%s \033[0m", msg, LABEXTENSION_COMMAND_WARNING + f"\033[33m(Deprecated) {msg}\n\n{LABEXTENSION_COMMAND_WARNING} \033[0m" ) def _log_format_default(self): @@ -589,7 +589,7 @@ def start(self): # The above should have called a subcommand and raised NoStart; if we # get here, it didn't, so we should self.log.info a message. subcmds = ", ".join(sorted(self.subcommands)) - self.exit("Please supply at least one subcommand: %s" % subcmds) + self.exit(f"Please supply at least one subcommand: {subcmds}") main = LabExtensionApp.launch_instance diff --git a/jupyterlab/utils.py b/jupyterlab/utils.py index a2662a2c3c9e..8c9c16202f19 100644 --- a/jupyterlab/utils.py +++ b/jupyterlab/utils.py @@ -36,12 +36,13 @@ def __init__(self, alt_func=None, behavior="warn", removed_version=None): def __call__(self, func): alt_msg = "" if self.alt_func is not None: - alt_msg = " Use ``%s`` instead." % self.alt_func + alt_msg = f" Use ``{self.alt_func}`` instead." rmv_msg = "" if self.removed_version is not None: - rmv_msg = " and will be removed in version %s" % self.removed_version + rmv_msg = f" and will be removed in version {self.removed_version}" - msg = "Function ``%s`` is deprecated" % func.__name__ + rmv_msg + "." + alt_msg + function_description = func.__name__ + rmv_msg + "." + alt_msg + msg = f"Function ``{function_description}`` is deprecated" @functools.wraps(func) def wrapped(*args, **kwargs): diff --git a/pyproject.toml b/pyproject.toml index c2fd8358fdac..e9e6a2e9d4da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,7 +76,7 @@ Pypi = "https://pypi.org/project/jupyterlab" [project.optional-dependencies] docs = [ - "sphinx>=1.8,<7.3.0", + "sphinx>=1.8,<7.4.0", "sphinx-copybutton", "pydata-sphinx-theme>=0.13.0", "pytest", @@ -91,10 +91,10 @@ docs-screenshots = [ "ipywidgets==8.1.2", "jupyterlab-geojson==3.4.0", "jupyterlab-language-pack-zh-CN==4.1.post2", - "matplotlib==3.8.3", + "matplotlib==3.8.4", "nbconvert>=7.0.0", - "pandas==2.2.1", - "scipy==1.12.0", + "pandas==2.2.2", + "scipy==1.13.0", "vega_datasets==0.9.0", ] test = [ @@ -118,13 +118,13 @@ dev = [ "coverage", "hatch", "bump2version", - "ruff==0.3.5", + "ruff==0.4.2", ] upgrade-extension = [ - "pyyaml-include<2.0", + "pyyaml-include<3.0", "copier>=8,<10", "jinja2-time<0.3", - "pydantic<2.0", + "pydantic<3.0", "tomli-w<2.0" ] @@ -303,7 +303,7 @@ lint.ignore = [ # RUF012 Mutable class attributes should be annotated with `typing.ClassVar` "jupyterlab/tests/echo_kernel.py" = ["RUF012"] # T201 `print` found -"scripts/milestone_check.py" = ["T201"] +"scripts/milestone_check.py" = ["T201", "UP031"] # N806 Variable `tM` in function should be lowercase # N816 Variable `comparatorTrimReplace` in global scope should not be mixedCase # PLC1901 test can be simplified as an empty string is falsey diff --git a/scripts/ci_script.sh b/scripts/ci_script.sh index 01f43ebd1ff1..e1cf953e8cef 100755 --- a/scripts/ci_script.sh +++ b/scripts/ci_script.sh @@ -82,7 +82,7 @@ if [[ $GROUP == lint ]]; then # Python checks ruff format . - ruff . + ruff check . pipx run 'validate-pyproject[all]' pyproject.toml fi diff --git a/scripts/milestone_check.py b/scripts/milestone_check.py index 25249d4141f1..d23da5977315 100644 --- a/scripts/milestone_check.py +++ b/scripts/milestone_check.py @@ -95,7 +95,7 @@ } -headers = {"Authorization": "token %s" % api_token} +headers = {"Authorization": f"token {api_token}"} # construct a commit to PR dictionary prs = {} large_prs = [] @@ -170,9 +170,9 @@ prs[prnumber] = {"mergeCommit": pr["mergeCommit"]["oid"], "commits": pr_commits} if total_commits > len(pr_commits): + oid = pr["mergeCommit"]["oid"] print( - "WARNING: PR %d (merge %s) has %d commits, but GitHub is only giving us %d of them" - % (prnumber, pr["mergeCommit"]["oid"], total_commits, len(pr_commits)) + f"WARNING: PR {prnumber} (merge {oid}) has {total_commits} commits, but GitHub is only giving us {len(pr_commits)} of them" ) @@ -197,7 +197,7 @@ prs_not_represented = set(prs.keys()) - good -print("Milestone: %s, %d merged PRs, %d commits in history" % (MILESTONE, total_prs, len(commits))) +print(f"Milestone: {MILESTONE}, {total_prs} merged PRs, {len(commits)} commits in history") print() print("-" * 40) @@ -211,9 +211,7 @@ """ ) print( - "\n".join( - "https://github.com/jupyterlab/jupyterlab/pull/%d" % i for i in prs_not_represented - ) + "\n".join(f"https://github.com/jupyterlab/jupyterlab/pull/{i}" for i in prs_not_represented) ) else: print(