From 6fef3eda62cac0fca2cb3544e86963165479dcd8 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Fri, 28 Jun 2024 19:00:10 +0200 Subject: [PATCH 01/11] Enforce ruff/refurb rule FURB118 FURB118 Use `operator.itemgetter(0)` instead of defining a lambda --- setuptools/command/build_ext.py | 3 ++- setuptools/command/build_py.py | 3 ++- setuptools/command/editable_wheel.py | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/setuptools/command/build_ext.py b/setuptools/command/build_ext.py index af73fff7a5..e944683aaa 100644 --- a/setuptools/command/build_ext.py +++ b/setuptools/command/build_ext.py @@ -1,6 +1,7 @@ from __future__ import annotations import itertools +import operator import os import sys import textwrap @@ -323,7 +324,7 @@ def get_outputs(self) -> list[str]: def get_output_mapping(self) -> dict[str, str]: """See :class:`setuptools.commands.build.SubCommand`""" mapping = self._get_output_mapping() - return dict(sorted(mapping, key=lambda x: x[0])) + return dict(sorted(mapping, key=operator.itemgetter(0))) def __get_stubs_outputs(self): # assemble the base name for each extension that needs a stub diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 2f6fcb7cdc..e4d35305e1 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -2,6 +2,7 @@ import fnmatch import itertools +import operator import os import stat import textwrap @@ -147,7 +148,7 @@ def get_output_mapping(self) -> dict[str, str]: self._get_package_data_output_mapping(), self._get_module_mapping(), ) - return dict(sorted(mapping, key=lambda x: x[0])) + return dict(sorted(mapping, key=operator.itemgetter(0))) def _get_module_mapping(self) -> Iterator[tuple[str, str]]: """Iterate over all modules producing (dest, src) pairs.""" diff --git a/setuptools/command/editable_wheel.py b/setuptools/command/editable_wheel.py index c772570817..fa0823cddc 100644 --- a/setuptools/command/editable_wheel.py +++ b/setuptools/command/editable_wheel.py @@ -14,6 +14,7 @@ import io import logging +import operator import os import shutil import traceback @@ -900,7 +901,7 @@ def _finder_template( """Create a string containing the code for the``MetaPathFinder`` and ``PathEntryFinder``. """ - mapping = dict(sorted(mapping.items(), key=lambda p: p[0])) + mapping = dict(sorted(mapping.items(), key=operator.itemgetter(0))) return _FINDER_TEMPLATE.format(name=name, mapping=mapping, namespaces=namespaces) From 690c5e403129848d2ce901a7d9b117ef6fa1cd38 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Fri, 28 Jun 2024 19:01:02 +0200 Subject: [PATCH 02/11] Enforce ruff/refurb rule FURB142 FURB142 Use of `set.add()` in a for loop --- setuptools/tests/test_wheel.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setuptools/tests/test_wheel.py b/setuptools/tests/test_wheel.py index f91465084a..50a650d1c1 100644 --- a/setuptools/tests/test_wheel.py +++ b/setuptools/tests/test_wheel.py @@ -116,8 +116,7 @@ def build_wheel(extra_file_defs=None, **kwargs): def tree_set(root): contents = set() for dirpath, dirnames, filenames in os.walk(root): - for filename in filenames: - contents.add(os.path.join(os.path.relpath(dirpath, root), filename)) + contents.update(os.path.join(os.path.relpath(dirpath, root), filename) for filename in filenames) return contents From 0cc2edff1f3a6f43229394eecb6299e8e0615c9e Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Fri, 28 Jun 2024 19:03:12 +0200 Subject: [PATCH 03/11] A round of `ruff format` after `ruff check --fix` --- setuptools/tests/test_wheel.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setuptools/tests/test_wheel.py b/setuptools/tests/test_wheel.py index 50a650d1c1..2f3e8ba5a0 100644 --- a/setuptools/tests/test_wheel.py +++ b/setuptools/tests/test_wheel.py @@ -116,7 +116,10 @@ def build_wheel(extra_file_defs=None, **kwargs): def tree_set(root): contents = set() for dirpath, dirnames, filenames in os.walk(root): - contents.update(os.path.join(os.path.relpath(dirpath, root), filename) for filename in filenames) + contents.update( + os.path.join(os.path.relpath(dirpath, root), filename) + for filename in filenames + ) return contents From d05ff4c850c53b44d2960571a11174bd0c8e1d97 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Fri, 28 Jun 2024 20:03:33 +0200 Subject: [PATCH 04/11] Manual improvment --- setuptools/tests/test_wheel.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/setuptools/tests/test_wheel.py b/setuptools/tests/test_wheel.py index 2f3e8ba5a0..caa3ac5aa1 100644 --- a/setuptools/tests/test_wheel.py +++ b/setuptools/tests/test_wheel.py @@ -114,13 +114,11 @@ def build_wheel(extra_file_defs=None, **kwargs): def tree_set(root): - contents = set() - for dirpath, dirnames, filenames in os.walk(root): - contents.update( - os.path.join(os.path.relpath(dirpath, root), filename) - for filename in filenames - ) - return contents + return set( + os.path.join(os.path.relpath(dirpath, root), filename) + for dirpath, dirnames, filenames in os.walk(root) + for filename in filenames + ) def flatten_tree(tree): From f428f1201b9add97133e5032f090621d8bf13dda Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Fri, 28 Jun 2024 19:06:38 +0200 Subject: [PATCH 05/11] Enforce ruff/refurb rule FURB167 FURB167 Use of regular expression alias `re.I` FURB167 Use of regular expression alias `re.M` FURB167 Use of regular expression alias `re.S` FURB167 Use of regular expression alias `re.X` --- pkg_resources/__init__.py | 2 +- setuptools/_normalization.py | 8 ++++---- setuptools/tests/config/test_apply_pyprojecttoml.py | 4 ++-- setuptools/tests/config/test_pyprojecttoml.py | 4 ++-- setuptools/tests/test_dist_info.py | 2 +- tools/finalize.py | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 630aaa9a42..b0c7896f74 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -128,7 +128,7 @@ class _ZipLoaderModule(Protocol): __loader__: zipimport.zipimporter -_PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.I) +_PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.IGNORECASE) class PEP440Warning(RuntimeWarning): diff --git a/setuptools/_normalization.py b/setuptools/_normalization.py index fb89323c9d..ce119d0fdc 100644 --- a/setuptools/_normalization.py +++ b/setuptools/_normalization.py @@ -9,10 +9,10 @@ import packaging # https://packaging.python.org/en/latest/specifications/core-metadata/#name -_VALID_NAME = re.compile(r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.I) -_UNSAFE_NAME_CHARS = re.compile(r"[^A-Z0-9._-]+", re.I) -_NON_ALPHANUMERIC = re.compile(r"[^A-Z0-9]+", re.I) -_PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.I) +_VALID_NAME = re.compile(r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE) +_UNSAFE_NAME_CHARS = re.compile(r"[^A-Z0-9._-]+", re.IGNORECASE) +_NON_ALPHANUMERIC = re.compile(r"[^A-Z0-9]+", re.IGNORECASE) +_PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.IGNORECASE) def safe_identifier(name: str) -> str: diff --git a/setuptools/tests/config/test_apply_pyprojecttoml.py b/setuptools/tests/config/test_apply_pyprojecttoml.py index 489fd98e26..caeaf48c38 100644 --- a/setuptools/tests/config/test_apply_pyprojecttoml.py +++ b/setuptools/tests/config/test_apply_pyprojecttoml.py @@ -41,7 +41,7 @@ def _mock_expand_patterns(patterns, *_, **__): Allow comparing the given patterns for 2 dist objects. We need to strip special chars to avoid errors when validating. """ - return [re.sub("[^a-z0-9]+", "", p, flags=re.I) or "empty" for p in patterns] + return [re.sub("[^a-z0-9]+", "", p, flags=re.IGNORECASE) or "empty" for p in patterns] @pytest.mark.parametrize("url", urls_from_file(HERE / EXAMPLES_FILE)) @@ -600,7 +600,7 @@ def test_not_listed_in_dynamic(self, tmp_path, attr, field, value): """Setuptools cannot set a field if not listed in ``dynamic``""" pyproject = self.pyproject(tmp_path, []) dist = makedist(tmp_path, **{attr: value}) - msg = re.compile(f"defined outside of `pyproject.toml`:.*{field}", re.S) + msg = re.compile(f"defined outside of `pyproject.toml`:.*{field}", re.DOTALL) with pytest.warns(_MissingDynamic, match=msg): dist = pyprojecttoml.apply_configuration(dist, pyproject) diff --git a/setuptools/tests/config/test_pyprojecttoml.py b/setuptools/tests/config/test_pyprojecttoml.py index db40fcd23d..fa63580603 100644 --- a/setuptools/tests/config/test_pyprojecttoml.py +++ b/setuptools/tests/config/test_pyprojecttoml.py @@ -207,7 +207,7 @@ def test_scripts_not_listed_in_dynamic(self, tmp_path, missing_dynamic): dynamic = {"scripts", "gui-scripts", "entry-points"} - {missing_dynamic} msg = f"defined outside of `pyproject.toml`:.*{missing_dynamic}" - with pytest.raises(OptionError, match=re.compile(msg, re.S)): + with pytest.raises(OptionError, match=re.compile(msg, re.DOTALL)): expand_configuration(self.pyproject(dynamic), tmp_path) @@ -325,7 +325,7 @@ def test_invalid_example(tmp_path, example, error_msg): pyproject = tmp_path / "pyproject.toml" pyproject.write_text(cleandoc(example), encoding="utf-8") - pattern = re.compile(f"invalid pyproject.toml.*{error_msg}.*", re.M | re.S) + pattern = re.compile(f"invalid pyproject.toml.*{error_msg}.*", re.MULTILINE | re.DOTALL) with pytest.raises(ValueError, match=pattern): read_configuration(pyproject) diff --git a/setuptools/tests/test_dist_info.py b/setuptools/tests/test_dist_info.py index 010018d1e6..f65d0afbe4 100644 --- a/setuptools/tests/test_dist_info.py +++ b/setuptools/tests/test_dist_info.py @@ -23,7 +23,7 @@ def test_invalid_version(self, tmp_path): """ config = "[metadata]\nname=proj\nversion=42\n[egg_info]\ntag_build=invalid!!!\n" (tmp_path / "setup.cfg").write_text(config, encoding="utf-8") - msg = re.compile("invalid version", re.M | re.I) + msg = re.compile("invalid version", re.MULTILINE | re.IGNORECASE) proc = run_command_inner("dist_info", cwd=tmp_path, check=False) assert proc.returncode assert msg.search(proc.stdout) diff --git a/tools/finalize.py b/tools/finalize.py index d646e67cd0..27471c7e25 100644 --- a/tools/finalize.py +++ b/tools/finalize.py @@ -37,7 +37,7 @@ def _repair_changelog(): """ changelog_fn = pathlib.Path('NEWS.rst') changelog = changelog_fn.read_text(encoding='utf-8') - fixed = re.sub(r'^(v[0-9.]+)v[0-9.]+$', r'\1', changelog, flags=re.M) + fixed = re.sub(r'^(v[0-9.]+)v[0-9.]+$', r'\1', changelog, flags=re.MULTILINE) changelog_fn.write_text(fixed, encoding='utf-8') subprocess.check_output(['git', 'add', changelog_fn]) From 608cf49373ad5324b9d7dab50da6db3bfa04a064 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Fri, 28 Jun 2024 19:07:13 +0200 Subject: [PATCH 06/11] A round of `ruff format` after `ruff check --fix` --- pkg_resources/__init__.py | 4 +++- setuptools/_normalization.py | 4 +++- setuptools/tests/config/test_apply_pyprojecttoml.py | 4 +++- setuptools/tests/config/test_pyprojecttoml.py | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index b0c7896f74..1718e2aba6 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -128,7 +128,9 @@ class _ZipLoaderModule(Protocol): __loader__: zipimport.zipimporter -_PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.IGNORECASE) +_PEP440_FALLBACK = re.compile( + r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.IGNORECASE +) class PEP440Warning(RuntimeWarning): diff --git a/setuptools/_normalization.py b/setuptools/_normalization.py index ce119d0fdc..9268d21d84 100644 --- a/setuptools/_normalization.py +++ b/setuptools/_normalization.py @@ -12,7 +12,9 @@ _VALID_NAME = re.compile(r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE) _UNSAFE_NAME_CHARS = re.compile(r"[^A-Z0-9._-]+", re.IGNORECASE) _NON_ALPHANUMERIC = re.compile(r"[^A-Z0-9]+", re.IGNORECASE) -_PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.IGNORECASE) +_PEP440_FALLBACK = re.compile( + r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.IGNORECASE +) def safe_identifier(name: str) -> str: diff --git a/setuptools/tests/config/test_apply_pyprojecttoml.py b/setuptools/tests/config/test_apply_pyprojecttoml.py index caeaf48c38..71408734cc 100644 --- a/setuptools/tests/config/test_apply_pyprojecttoml.py +++ b/setuptools/tests/config/test_apply_pyprojecttoml.py @@ -41,7 +41,9 @@ def _mock_expand_patterns(patterns, *_, **__): Allow comparing the given patterns for 2 dist objects. We need to strip special chars to avoid errors when validating. """ - return [re.sub("[^a-z0-9]+", "", p, flags=re.IGNORECASE) or "empty" for p in patterns] + return [ + re.sub("[^a-z0-9]+", "", p, flags=re.IGNORECASE) or "empty" for p in patterns + ] @pytest.mark.parametrize("url", urls_from_file(HERE / EXAMPLES_FILE)) diff --git a/setuptools/tests/config/test_pyprojecttoml.py b/setuptools/tests/config/test_pyprojecttoml.py index fa63580603..6d995d23af 100644 --- a/setuptools/tests/config/test_pyprojecttoml.py +++ b/setuptools/tests/config/test_pyprojecttoml.py @@ -325,7 +325,9 @@ def test_invalid_example(tmp_path, example, error_msg): pyproject = tmp_path / "pyproject.toml" pyproject.write_text(cleandoc(example), encoding="utf-8") - pattern = re.compile(f"invalid pyproject.toml.*{error_msg}.*", re.MULTILINE | re.DOTALL) + pattern = re.compile( + f"invalid pyproject.toml.*{error_msg}.*", re.MULTILINE | re.DOTALL + ) with pytest.raises(ValueError, match=pattern): read_configuration(pyproject) From f2c7c6379c49ee92cebadeb51d3d086d8a242f25 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Tue, 31 Dec 2024 12:05:18 +0100 Subject: [PATCH 07/11] Apply ruff/refurb rule FURB188 FURB188 Prefer `removesuffix` over conditionally replacing with slice. --- setuptools/command/bdist_egg.py | 3 +-- setuptools/command/editable_wheel.py | 2 +- setuptools/command/egg_info.py | 3 +-- setuptools/dist.py | 3 +-- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/setuptools/command/bdist_egg.py b/setuptools/command/bdist_egg.py index b66020c863..957b88f3a3 100644 --- a/setuptools/command/bdist_egg.py +++ b/setuptools/command/bdist_egg.py @@ -35,8 +35,7 @@ def _get_purelib(): def strip_module(filename): if '.' in filename: filename = os.path.splitext(filename)[0] - if filename.endswith('module'): - filename = filename[:-6] + filename = filename.removesuffix('module') return filename diff --git a/setuptools/command/editable_wheel.py b/setuptools/command/editable_wheel.py index fa0823cddc..c04861c616 100644 --- a/setuptools/command/editable_wheel.py +++ b/setuptools/command/editable_wheel.py @@ -660,7 +660,7 @@ def _parent_path(pkg, pkg_path): >>> _parent_path("b", "src/c") 'src/c' """ - parent = pkg_path[: -len(pkg)] if pkg_path.endswith(pkg) else pkg_path + parent = pkg_path.removesuffix(pkg) return parent.rstrip("/" + os.sep) diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 7e00ae2cea..e8a26cd3a7 100644 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -475,8 +475,7 @@ def global_exclude(self, pattern): return self._remove_files(match.match) def append(self, item) -> None: - if item.endswith('\r'): # Fix older sdists built on Windows - item = item[:-1] + item = item.removesuffix('\r') path = convert_path(item) if self._safe_path(path): diff --git a/setuptools/dist.py b/setuptools/dist.py index f06298c868..5eab94e333 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -1062,8 +1062,7 @@ def iter_distribution_names(self): name, _buildinfo = ext else: name = ext.name - if name.endswith('module'): - name = name[:-6] + name = name.removesuffix('module') yield name def handle_display_options(self, option_order): From 43b5ffbc20f272063f275b0939ea3ebf43ff6915 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Fri, 28 Jun 2024 19:07:44 +0200 Subject: [PATCH 08/11] Enforce ruff/refurb rule FURB192 FURB192 Prefer `max` over `sorted()` to compute the maximum value in a sequence --- setuptools/msvc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/msvc.py b/setuptools/msvc.py index 313a781ae0..e9b7d1b2af 100644 --- a/setuptools/msvc.py +++ b/setuptools/msvc.py @@ -393,7 +393,7 @@ def _find_latest_available_vs_ver(self): vc_vers = set(reg_vc_vers) vc_vers.update(self.known_vs_paths) - return sorted(vc_vers)[-1] + return max(vc_vers) def find_reg_vs_vers(self): """ From ec52299314b37316fb31c6bcab06ee50cadccac5 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos Orfanos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Wed, 1 Jan 2025 13:47:04 +0100 Subject: [PATCH 09/11] Manual improvment Co-authored-by: Avasam --- setuptools/tests/test_wheel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/tests/test_wheel.py b/setuptools/tests/test_wheel.py index caa3ac5aa1..a7a71c8fc3 100644 --- a/setuptools/tests/test_wheel.py +++ b/setuptools/tests/test_wheel.py @@ -114,11 +114,11 @@ def build_wheel(extra_file_defs=None, **kwargs): def tree_set(root): - return set( + return { os.path.join(os.path.relpath(dirpath, root), filename) for dirpath, dirnames, filenames in os.walk(root) for filename in filenames - ) + } def flatten_tree(tree): From bf7a50a7ff09303ac44ccc183899be3af3bde4f7 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Fri, 3 Jan 2025 20:17:11 +0100 Subject: [PATCH 10/11] Enforce ruff/refurb rules (FURB) --- ruff.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/ruff.toml b/ruff.toml index 349d22cebd..2d69c33894 100644 --- a/ruff.toml +++ b/ruff.toml @@ -26,6 +26,7 @@ extend-select = [ # local "ANN2", # missing-return-type-* + "FURB", # refurb "PERF", # Perflint "PGH", # pygrep-hooks (blanket-* rules) "PT", # flake8-pytest-style From bea8c1c05a1ed9210f1ad995e40aa26df54795ca Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos Orfanos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sun, 25 May 2025 10:49:35 +0200 Subject: [PATCH 11/11] Add comment back. Co-authored-by: Avasam --- setuptools/command/egg_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index e8a26cd3a7..99171f373d 100644 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -475,7 +475,7 @@ def global_exclude(self, pattern): return self._remove_files(match.match) def append(self, item) -> None: - item = item.removesuffix('\r') + item = item.removesuffix('\r') # Fix older sdists built on Windows path = convert_path(item) if self._safe_path(path):