From 393b66b4cedead9c7ab9795a6a6e85b1d0f69d62 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sat, 24 May 2025 15:13:02 +0200 Subject: [PATCH 1/8] Enforce ruff rule RUF012 RUF012 Mutable class attributes should be annotated with `typing.ClassVar` --- fsspec/gui.py | 17 +++++++++++++---- fsspec/implementations/memory.py | 4 ++-- fsspec/implementations/tests/conftest.py | 2 +- fsspec/implementations/tests/test_archive.py | 4 ++-- fsspec/tests/conftest.py | 5 +++-- pyproject.toml | 1 + 6 files changed, 22 insertions(+), 11 deletions(-) diff --git a/fsspec/gui.py b/fsspec/gui.py index 9d914c8be..da658e884 100644 --- a/fsspec/gui.py +++ b/fsspec/gui.py @@ -170,8 +170,17 @@ def show(self, threads=False): class SingleSelect(SigSlot): """A multiselect which only allows you to select one item for an event""" - signals = ["_selected", "selected"] # the first is internal - slots = ["set_options", "set_selection", "add", "clear", "select"] + signals: ClassVar[Sequence[str]] = [ + "_selected", + "selected", + ] # the first is internal + slots: ClassVar[Sequence[str]] = [ + "set_options", + "set_selection", + "add", + "clear", + "select", + ] def __init__(self, **kwargs): self.kwargs = kwargs @@ -213,7 +222,7 @@ class FileSelector(SigSlot): them as the output of a cell, or in a separate browser tab using ``.show()``. """ - signals = [ + signals: ClassVar[Sequence[str]] = [ "protocol_changed", "selection_changed", "directory_entered", @@ -222,7 +231,7 @@ class FileSelector(SigSlot): "go_clicked", "filters_changed", ] - slots = ["set_filters", "go_home"] + slots: ClassVar[Sequence[str]] = ["set_filters", "go_home"] def __init__(self, url=None, filters=None, ignore=None, kwargs=None): """ diff --git a/fsspec/implementations/memory.py b/fsspec/implementations/memory.py index f6b67bbc8..254d9e8a2 100644 --- a/fsspec/implementations/memory.py +++ b/fsspec/implementations/memory.py @@ -5,7 +5,7 @@ from errno import ENOTEMPTY from io import BytesIO from pathlib import PurePath, PureWindowsPath -from typing import Any, ClassVar +from typing import Any, ClassVar, Sequence from fsspec import AbstractFileSystem from fsspec.implementations.local import LocalFileSystem @@ -22,7 +22,7 @@ class MemoryFileSystem(AbstractFileSystem): """ store: ClassVar[dict[str, Any]] = {} # global, do not overwrite! - pseudo_dirs = [""] # global, do not overwrite! + pseudo_dirs: ClassVar[Sequence[str]] = [""] # global, do not overwrite! protocol = "memory" root_marker = "/" diff --git a/fsspec/implementations/tests/conftest.py b/fsspec/implementations/tests/conftest.py index 7dce3ee4e..d71c31032 100644 --- a/fsspec/implementations/tests/conftest.py +++ b/fsspec/implementations/tests/conftest.py @@ -10,7 +10,7 @@ class MultiProtocolFileSystem(LocalFileSystem): - protocol = ["file", "other"] + protocol = ("file", "other") FILESYSTEMS = { diff --git a/fsspec/implementations/tests/test_archive.py b/fsspec/implementations/tests/test_archive.py index 457714b39..dce41a4f2 100644 --- a/fsspec/implementations/tests/test_archive.py +++ b/fsspec/implementations/tests/test_archive.py @@ -214,14 +214,14 @@ class TestAnyArchive: will adhere to the same specification. """ - scenarios = [ + scenarios = ( scenario_zip, scenario_tar, scenario_targz, scenario_tarbz2, scenario_tarxz, scenario_libarchive, - ] + ) def test_repr(self, scenario: ArchiveTestScenario): with scenario.provider() as archive: diff --git a/fsspec/tests/conftest.py b/fsspec/tests/conftest.py index ccf7bdccf..7daaed062 100644 --- a/fsspec/tests/conftest.py +++ b/fsspec/tests/conftest.py @@ -6,6 +6,7 @@ from collections import ChainMap from http.server import BaseHTTPRequestHandler, HTTPServer from types import SimpleNamespace +from typing import ClassVar import pytest @@ -45,7 +46,7 @@ def reset_files(): class HTTPTestHandler(BaseHTTPRequestHandler): - static_files = { + static_files: ClassVar[dict[str, bytes]] = { "/index/realfile": data, "/index/otherfile": data, "/index": _make_index_listing, @@ -55,7 +56,7 @@ class HTTPTestHandler(BaseHTTPRequestHandler): "/simple/dir/": _make_listing("/simple/dir/file"), "/simple/dir/file": data, } - dynamic_files = {} + dynamic_files: ClassVar[dict[str, bytes]] = {} files = ChainMap(dynamic_files, static_files) diff --git a/pyproject.toml b/pyproject.toml index 80f76a0db..0c1edd0f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -177,6 +177,7 @@ select = [ # "PT", enable in later PR "PYI", "RUF006", + "RUF012", "RUF015", "RUF024", "SIM", From 7801d0088b377c4fa4bd5d457f434446c3a9ae1a Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sat, 24 May 2025 14:54:40 +0200 Subject: [PATCH 2/8] Enforce ruff rule RUF019 RUF019 Unnecessary key check before dictionary access --- fsspec/implementations/gist.py | 8 ++++---- pyproject.toml | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/fsspec/implementations/gist.py b/fsspec/implementations/gist.py index ad9ac0b6a..f2872b335 100644 --- a/fsspec/implementations/gist.py +++ b/fsspec/implementations/gist.py @@ -148,16 +148,16 @@ def _get_kwargs_from_urls(path): """ so = infer_storage_options(path) out = {} - if "username" in so and so["username"]: + if so.get("username"): out["username"] = so["username"] - if "password" in so and so["password"]: + if so.get("password"): out["token"] = so["password"] - if "host" in so and so["host"]: + if so.get("host"): # We interpret 'host' as the gist ID out["gist_id"] = so["host"] # Extract SHA and filename from path - if "path" in so and so["path"]: + if so.get("path"): path_parts = so["path"].rsplit("/", 2)[-2:] if len(path_parts) == 2: if path_parts[0]: # SHA present diff --git a/pyproject.toml b/pyproject.toml index 0c1edd0f3..017a7e725 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -179,6 +179,7 @@ select = [ "RUF006", "RUF012", "RUF015", + "RUF019", "RUF024", "SIM", "SLOT", From c0e9c783be6a2318fdf7634b63d430eb695e91f9 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sat, 12 Oct 2024 20:54:28 +0200 Subject: [PATCH 3/8] Enforce ruff rule RUF022 RUF022 `__all__` is not sorted --- fsspec/__init__.py | 12 ++++++------ fsspec/registry.py | 2 +- pyproject.toml | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/fsspec/__init__.py b/fsspec/__init__.py index 452c78a05..183564af0 100644 --- a/fsspec/__init__.py +++ b/fsspec/__init__.py @@ -16,21 +16,21 @@ __all__ = [ "AbstractFileSystem", - "FSTimeoutError", + "Callback", "FSMap", + "FSTimeoutError", + "available_compressions", + "available_protocols", + "caching", "filesystem", - "register_implementation", "get_filesystem_class", "get_fs_token_paths", "get_mapper", "open", "open_files", "open_local", + "register_implementation", "registry", - "caching", - "Callback", - "available_protocols", - "available_compressions", "url_to_fs", ] diff --git a/fsspec/registry.py b/fsspec/registry.py index 96ffad7f4..d535d1ce3 100644 --- a/fsspec/registry.py +++ b/fsspec/registry.py @@ -4,7 +4,7 @@ import types import warnings -__all__ = ["registry", "get_filesystem_class", "default"] +__all__ = ["default", "get_filesystem_class", "registry"] # internal, mutable _registry: dict[str, type] = {} diff --git a/pyproject.toml b/pyproject.toml index 017a7e725..168f259d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -180,6 +180,7 @@ select = [ "RUF012", "RUF015", "RUF019", + "RUF022", "RUF024", "SIM", "SLOT", From 2108fe058d19f7cb8d6ba592288ea57ee1265dff Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sat, 24 May 2025 14:49:38 +0200 Subject: [PATCH 4/8] Enforce ruff rule RUF046 RUF046 Value being cast to `int` is already an integer --- fsspec/utils.py | 2 +- pyproject.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/fsspec/utils.py b/fsspec/utils.py index 208d0f7d8..f8a2c0c22 100644 --- a/fsspec/utils.py +++ b/fsspec/utils.py @@ -172,7 +172,7 @@ def build_name_function(max_int: float) -> Callable[[int], str]: # handle corner cases max_int is 0 or exact power of 10 max_int += 1e-8 - pad_length = int(math.ceil(math.log10(max_int))) + pad_length = math.ceil(math.log10(max_int)) def name_function(i: int) -> str: return str(i).zfill(pad_length) diff --git a/pyproject.toml b/pyproject.toml index 168f259d0..14cc6c967 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -182,6 +182,7 @@ select = [ "RUF019", "RUF022", "RUF024", + "RUF046", "SIM", "SLOT", "SIM101", From 83dd6410b4a019e32517681b27e7e4f581d6afab Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 3 Nov 2025 23:05:52 +0100 Subject: [PATCH 5/8] Apply ruff rule RUF059 RUF059 Unpacked variable is never used --- fsspec/core.py | 2 +- fsspec/implementations/reference.py | 2 +- fsspec/implementations/tar.py | 2 +- fsspec/implementations/tests/test_cached.py | 4 ++-- fsspec/implementations/tests/test_git.py | 4 ++-- fsspec/tests/conftest.py | 2 +- fsspec/tests/test_api.py | 2 +- fsspec/tests/test_core.py | 10 +++++----- fsspec/tests/test_fuse.py | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/fsspec/core.py b/fsspec/core.py index a7db808ae..1eea74491 100644 --- a/fsspec/core.py +++ b/fsspec/core.py @@ -292,7 +292,7 @@ def open_files( - For implementations in separate packages see https://filesystem-spec.readthedocs.io/en/latest/api.html#other-known-implementations """ - fs, fs_token, paths = get_fs_token_paths( + fs, _fs_token, paths = get_fs_token_paths( urlpath, mode, num=num, diff --git a/fsspec/implementations/reference.py b/fsspec/implementations/reference.py index d33215ad3..e1e188b76 100644 --- a/fsspec/implementations/reference.py +++ b/fsspec/implementations/reference.py @@ -391,7 +391,7 @@ def __getitem__(self, key): def __setitem__(self, key, value): if "/" in key and not self._is_meta(key): - field, chunk = key.rsplit("/", 1) + field, _chunk = key.rsplit("/", 1) record, i, _ = self._key_to_record(key) subdict = self._items.setdefault((field, record), {}) subdict[i] = value diff --git a/fsspec/implementations/tar.py b/fsspec/implementations/tar.py index 412e5ba4d..c6ba33eee 100644 --- a/fsspec/implementations/tar.py +++ b/fsspec/implementations/tar.py @@ -118,7 +118,7 @@ def _get_dirs(self): def _open(self, path, mode="rb", **kwargs): if mode != "rb": raise ValueError("Read-only filesystem implementation") - details, offset = self.index[path] + details, _offset = self.index[path] if details["type"] != "file": raise ValueError("Can only handle regular files") return self.tar.extractfile(path) diff --git a/fsspec/implementations/tests/test_cached.py b/fsspec/implementations/tests/test_cached.py index 814929d8c..64d2cafec 100644 --- a/fsspec/implementations/tests/test_cached.py +++ b/fsspec/implementations/tests/test_cached.py @@ -699,7 +699,7 @@ def test_local_filecache_basic(local_filecache): def test_local_filecache_does_not_change_when_original_data_changed(local_filecache): - old_data, original_file, cache_location, fs = local_filecache + old_data, original_file, _cache_location, fs = local_filecache new_data = b"abc" with fs.open(original_file, "rb") as f: @@ -899,7 +899,7 @@ def test_filecache_serialization(impl, fs): def test_add_file_to_cache_after_save(local_filecache): - (data, original_file, cache_location, fs) = local_filecache + (_data, original_file, cache_location, fs) = local_filecache fs.save_cache() diff --git a/fsspec/implementations/tests/test_git.py b/fsspec/implementations/tests/test_git.py index 2aeb544a1..bd85ff0ba 100644 --- a/fsspec/implementations/tests/test_git.py +++ b/fsspec/implementations/tests/test_git.py @@ -67,7 +67,7 @@ def _check_FileNotFoundError(f, *args, **kwargs): def test_file_existence_checks(repo): - d, sha = repo + d, _sha = repo fs, _ = fsspec.url_to_fs(f"git://{d}:abranch@") @@ -95,7 +95,7 @@ def test_file_existence_checks(repo): def test_url(repo): - d, sha = repo + d, _sha = repo fs, _, paths = fsspec.core.get_fs_token_paths(f"git://file1::file://{d}") assert make_path_posix(d) in make_path_posix(fs.repo.path) assert paths == ["file1"] diff --git a/fsspec/tests/conftest.py b/fsspec/tests/conftest.py index 7daaed062..30589eec6 100644 --- a/fsspec/tests/conftest.py +++ b/fsspec/tests/conftest.py @@ -93,7 +93,7 @@ def do_GET(self): content_range = f"bytes 0-{len(file_data) - 1}/{len(file_data)}" if ("Range" in self.headers) and ("ignore_range" not in self.headers): ran = self.headers["Range"] - b, ran = ran.split("=") + _b, ran = ran.split("=") start, end = ran.split("-") if start: content_range = f"bytes {start}-{end}/{len(file_data)}" diff --git a/fsspec/tests/test_api.py b/fsspec/tests/test_api.py index ce1f239ac..8c3d3ef31 100644 --- a/fsspec/tests/test_api.py +++ b/fsspec/tests/test_api.py @@ -42,7 +42,7 @@ def test_class_methods(): def test_multi(m): m.pipe("/afile", b"data") - fs, token, paths = fsspec.core.get_fs_token_paths(["/afile", "/afile"]) + _fs, _token, paths = fsspec.core.get_fs_token_paths(["/afile", "/afile"]) assert len(paths) == 2 diff --git a/fsspec/tests/test_core.py b/fsspec/tests/test_core.py index 0dacd3830..05a4dd4cd 100644 --- a/fsspec/tests/test_core.py +++ b/fsspec/tests/test_core.py @@ -399,11 +399,11 @@ def test_url_to_fs(ftp_writable): data = b"hello" with fsspec.open(f"ftp://{username}:{password}@{host}:{port}/afile", "wb") as f: f.write(data) - fs, url = fsspec.core.url_to_fs( + _fs, url = fsspec.core.url_to_fs( f"simplecache::ftp://{username}:{password}@{host}:{port}/afile" ) assert url == "/afile" - fs, url = fsspec.core.url_to_fs(f"ftp://{username}:{password}@{host}:{port}/afile") + _fs, url = fsspec.core.url_to_fs(f"ftp://{username}:{password}@{host}:{port}/afile") assert url == "/afile" with fsspec.open(f"ftp://{username}:{password}@{host}:{port}/afile.zip", "wb") as f: @@ -414,11 +414,11 @@ def test_url_to_fs(ftp_writable): f2.write(b"hello") f.write(data) - fs, url = fsspec.core.url_to_fs( + _fs, url = fsspec.core.url_to_fs( f"zip://inner::ftp://{username}:{password}@{host}:{port}/afile.zip" ) assert url == "inner" - fs, url = fsspec.core.url_to_fs( + _fs, url = fsspec.core.url_to_fs( f"simplecache::zip::ftp://{username}:{password}@{host}:{port}/afile.zip" ) assert url == "" @@ -472,7 +472,7 @@ def test_repeated_argument(): pytest.importorskip("adlfs") from fsspec.core import url_to_fs - fs, url = url_to_fs( + fs, _url = url_to_fs( "az://DIR@ACCOUNT.blob.core.windows.net/DATA", anon=False, account_name="ACCOUNT", diff --git a/fsspec/tests/test_fuse.py b/fsspec/tests/test_fuse.py index ef3005367..91a806c8c 100644 --- a/fsspec/tests/test_fuse.py +++ b/fsspec/tests/test_fuse.py @@ -132,7 +132,7 @@ def test_chmod(mount_local): def test_seek_rw(mount_local): - source_dir, mount_dir = mount_local + _source_dir, mount_dir = mount_local fh = open(mount_dir / "text", "w") fh.write("teST") fh.seek(2) From 29c5dca4ff9815c44253d0227bed647e4237f741 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Tue, 11 Mar 2025 22:51:46 +0100 Subject: [PATCH 6/8] Enforce ruff rule RUF100 RUF100 Unused `noqa` directive --- fsspec/implementations/tests/test_smb.py | 2 -- pyproject.toml | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/fsspec/implementations/tests/test_smb.py b/fsspec/implementations/tests/test_smb.py index a4b443528..24b31489d 100644 --- a/fsspec/implementations/tests/test_smb.py +++ b/fsspec/implementations/tests/test_smb.py @@ -20,8 +20,6 @@ def delay_rerun(*args): return True -# ruff: noqa: F821 - if os.environ.get("WSL_INTEROP"): # Running on WSL (Windows) port_test = [9999] diff --git a/pyproject.toml b/pyproject.toml index 14cc6c967..b7c9c4d83 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -179,10 +179,9 @@ select = [ "RUF006", "RUF012", "RUF015", - "RUF019", - "RUF022", "RUF024", "RUF046", + "RUF100", "SIM", "SLOT", "SIM101", From 8749107143aa3de1c37b285851e0478b73f7d9c0 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sat, 24 May 2025 15:18:16 +0200 Subject: [PATCH 7/8] Enforce ruff rules (RUF) --- pyproject.toml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b7c9c4d83..d8d3f7787 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -176,12 +176,7 @@ select = [ "PIE810", # "PT", enable in later PR "PYI", - "RUF006", - "RUF012", - "RUF015", - "RUF024", - "RUF046", - "RUF100", + "RUF", "SIM", "SLOT", "SIM101", @@ -216,6 +211,8 @@ ignore = [ "UP011", "UP015", "UP018", + "RUF001", + "RUF005", "SIM102", "SIM105", "SIM108", From cdfa2e8d775c076b05ecc7833af1f12cab3825e9 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Wed, 6 Aug 2025 20:48:32 +0200 Subject: [PATCH 8/8] Apply ruff/pyupgrade rule UP035 UP035 Import from `collections.abc` instead of `typing` --- fsspec/implementations/memory.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fsspec/implementations/memory.py b/fsspec/implementations/memory.py index 254d9e8a2..017307cf8 100644 --- a/fsspec/implementations/memory.py +++ b/fsspec/implementations/memory.py @@ -1,11 +1,12 @@ from __future__ import annotations import logging +from collections.abc import Sequence from datetime import datetime, timezone from errno import ENOTEMPTY from io import BytesIO from pathlib import PurePath, PureWindowsPath -from typing import Any, ClassVar, Sequence +from typing import Any, ClassVar from fsspec import AbstractFileSystem from fsspec.implementations.local import LocalFileSystem