From 69a1e956dae1d6ced4bc6e66883b271f1f7a10e9 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 26 Aug 2023 10:20:40 +0200 Subject: [PATCH 1/4] Ruff rules C4,C90,PERF --- .pre-commit-config.yaml | 2 +- ...FF-ABE1-48C7-954C-7C3EB229135F.feature.rst | 1 + pyproject.toml | 30 +++++++++++++---- src/pip/_internal/cache.py | 6 ++-- src/pip/_internal/cli/autocompletion.py | 5 +-- src/pip/_internal/commands/cache.py | 12 ++----- src/pip/_internal/commands/debug.py | 2 +- src/pip/_internal/commands/list.py | 2 +- src/pip/_internal/locations/_distutils.py | 2 +- .../_internal/models/installation_report.py | 2 +- src/pip/_internal/operations/install/wheel.py | 6 ++-- src/pip/_internal/req/req_uninstall.py | 2 +- tests/functional/test_cache.py | 20 ++++-------- tests/functional/test_help.py | 4 +-- tests/functional/test_list.py | 32 ++++++++----------- tests/lib/__init__.py | 18 +++++------ tests/unit/test_finder.py | 6 ++-- tests/unit/test_logging.py | 14 ++++---- tests/unit/test_req_uninstall.py | 7 ++-- tests/unit/test_self_check_outdated.py | 2 +- tests/unit/test_target_python.py | 16 +++++----- tests/unit/test_vcs.py | 2 +- 22 files changed, 93 insertions(+), 100 deletions(-) create mode 100644 news/4A0C40FF-ABE1-48C7-954C-7C3EB229135F.feature.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b0aef0d60..1c497c294 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,7 +23,7 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.0.270 + rev: v0.0.286 hooks: - id: ruff diff --git a/news/4A0C40FF-ABE1-48C7-954C-7C3EB229135F.feature.rst b/news/4A0C40FF-ABE1-48C7-954C-7C3EB229135F.feature.rst new file mode 100644 index 000000000..7f6c1d561 --- /dev/null +++ b/news/4A0C40FF-ABE1-48C7-954C-7C3EB229135F.feature.rst @@ -0,0 +1 @@ +Add ruff rules ASYNC,C4,C90,PERF,PLE,PLR for minor optimizations and to set upper limits on code complexity. diff --git a/pyproject.toml b/pyproject.toml index b7c0d1545..c3c21802f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,9 +74,9 @@ webencodings = "https://github.com/SimonSapin/python-webencodings/raw/master/LIC [tool.ruff] extend-exclude = [ + "_vendor", "./build", ".scratch", - "_vendor", "data", ] ignore = [ @@ -88,21 +88,37 @@ ignore = [ ] line-length = 88 select = [ + "ASYNC", "B", + "C4", + "C90", "E", "F", - "W", "G", - "ISC", "I", + "ISC", + "PERF", + "PLE", + "PLR0", + "W", ] -[tool.ruff.per-file-ignores] -"noxfile.py" = ["G"] -"tests/*" = ["B011"] - [tool.ruff.isort] # We need to explicitly make pip "first party" as it's imported by code in # the docs and tests directories. known-first-party = ["pip"] known-third-party = ["pip._vendor"] + +[tool.ruff.mccabe] +max-complexity = 33 # default is 10 + +[tool.ruff.per-file-ignores] +"noxfile.py" = ["G"] +"src/pip/_internal/*" = ["PERF203"] +"tests/*" = ["B011"] + +[tool.ruff.pylint] +max-args = 15 # default is 5 +max-branches = 28 # default is 12 +max-returns = 13 # default is 6 +max-statements = 134 # default is 50 diff --git a/src/pip/_internal/cache.py b/src/pip/_internal/cache.py index 8d3a664c7..f45ac23e9 100644 --- a/src/pip/_internal/cache.py +++ b/src/pip/_internal/cache.py @@ -78,12 +78,10 @@ class Cache: if can_not_cache: return [] - candidates = [] path = self.get_path_for_link(link) if os.path.isdir(path): - for candidate in os.listdir(path): - candidates.append((candidate, path)) - return candidates + return [(candidate, path) for candidate in os.listdir(path)] + return [] def get_path_for_link(self, link: Link) -> str: """Return a directory to store cached items in for link.""" diff --git a/src/pip/_internal/cli/autocompletion.py b/src/pip/_internal/cli/autocompletion.py index 226fe84dc..e5950b906 100644 --- a/src/pip/_internal/cli/autocompletion.py +++ b/src/pip/_internal/cli/autocompletion.py @@ -71,8 +71,9 @@ def autocomplete() -> None: for opt in subcommand.parser.option_list_all: if opt.help != optparse.SUPPRESS_HELP: - for opt_str in opt._long_opts + opt._short_opts: - options.append((opt_str, opt.nargs)) + options += [ + (opt_str, opt.nargs) for opt_str in opt._long_opts + opt._short_opts + ] # filter out previously specified options from available options prev_opts = [x.split("=")[0] for x in cwords[1 : cword - 1]] diff --git a/src/pip/_internal/commands/cache.py b/src/pip/_internal/commands/cache.py index e96d2b492..f6430980c 100644 --- a/src/pip/_internal/commands/cache.py +++ b/src/pip/_internal/commands/cache.py @@ -3,10 +3,10 @@ import textwrap from optparse import Values from typing import Any, List -import pip._internal.utils.filesystem as filesystem from pip._internal.cli.base_command import Command from pip._internal.cli.status_codes import ERROR, SUCCESS from pip._internal.exceptions import CommandError, PipError +from pip._internal.utils import filesystem from pip._internal.utils.logging import getLogger logger = getLogger(__name__) @@ -151,14 +151,8 @@ class CacheCommand(Command): logger.info("\n".join(sorted(results))) def format_for_abspath(self, files: List[str]) -> None: - if not files: - return - - results = [] - for filename in files: - results.append(filename) - - logger.info("\n".join(sorted(results))) + if files: + logger.info("\n".join(sorted(files))) def remove_cache_items(self, options: Values, args: List[Any]) -> None: if len(args) > 1: diff --git a/src/pip/_internal/commands/debug.py b/src/pip/_internal/commands/debug.py index 88a4f798d..564409c68 100644 --- a/src/pip/_internal/commands/debug.py +++ b/src/pip/_internal/commands/debug.py @@ -135,7 +135,7 @@ def show_tags(options: Values) -> None: def ca_bundle_info(config: Configuration) -> str: levels = set() - for key, _ in config.items(): + for key, _ in config.items(): # noqa: PERF102 Configuration has no keys() method. levels.add(key.split(".")[0]) if not levels: diff --git a/src/pip/_internal/commands/list.py b/src/pip/_internal/commands/list.py index ac1035319..2ec456b95 100644 --- a/src/pip/_internal/commands/list.py +++ b/src/pip/_internal/commands/list.py @@ -297,7 +297,7 @@ class ListCommand(IndexGroupCommand): # Create and add a separator. if len(data) > 0: - pkg_strings.insert(1, " ".join(map(lambda x: "-" * x, sizes))) + pkg_strings.insert(1, " ".join(("-" * x for x in sizes))) for val in pkg_strings: write_output(val) diff --git a/src/pip/_internal/locations/_distutils.py b/src/pip/_internal/locations/_distutils.py index 92bd93179..48689f5fb 100644 --- a/src/pip/_internal/locations/_distutils.py +++ b/src/pip/_internal/locations/_distutils.py @@ -89,7 +89,7 @@ def distutils_scheme( # finalize_options(); we only want to override here if the user # has explicitly requested it hence going back to the config if "install_lib" in d.get_option_dict("install"): - scheme.update(dict(purelib=i.install_lib, platlib=i.install_lib)) + scheme.update({"purelib": i.install_lib, "platlib": i.install_lib}) if running_under_virtualenv(): if home: diff --git a/src/pip/_internal/models/installation_report.py b/src/pip/_internal/models/installation_report.py index 7f001f35e..da0334bd5 100644 --- a/src/pip/_internal/models/installation_report.py +++ b/src/pip/_internal/models/installation_report.py @@ -33,7 +33,7 @@ class InstallationReport: } if ireq.user_supplied and ireq.extras: # For top level requirements, the list of requested extras, if any. - res["requested_extras"] = list(sorted(ireq.extras)) + res["requested_extras"] = sorted(ireq.extras) return res def to_dict(self) -> Dict[str, Any]: diff --git a/src/pip/_internal/operations/install/wheel.py b/src/pip/_internal/operations/install/wheel.py index a8cd1330f..58a773059 100644 --- a/src/pip/_internal/operations/install/wheel.py +++ b/src/pip/_internal/operations/install/wheel.py @@ -267,9 +267,9 @@ def get_csv_rows_for_installed( path = _fs_to_record_path(f, lib_dir) digest, length = rehash(f) installed_rows.append((path, digest, length)) - for installed_record_path in installed.values(): - installed_rows.append((installed_record_path, "", "")) - return installed_rows + return installed_rows + [ + (installed_record_path, "", "") for installed_record_path in installed.values() + ] def get_console_script_specs(console: Dict[str, str]) -> List[str]: diff --git a/src/pip/_internal/req/req_uninstall.py b/src/pip/_internal/req/req_uninstall.py index ad5178e76..861aa4f22 100644 --- a/src/pip/_internal/req/req_uninstall.py +++ b/src/pip/_internal/req/req_uninstall.py @@ -274,7 +274,7 @@ class StashedUninstallPathSet: def commit(self) -> None: """Commits the uninstall by removing stashed files.""" - for _, save_dir in self._save_dirs.items(): + for save_dir in self._save_dirs.values(): save_dir.cleanup() self._moves = [] self._save_dirs = {} diff --git a/tests/functional/test_cache.py b/tests/functional/test_cache.py index 788abdd2b..a6640cbbf 100644 --- a/tests/functional/test_cache.py +++ b/tests/functional/test_cache.py @@ -36,10 +36,7 @@ def http_cache_files(http_cache_dir: str) -> List[str]: return [] filenames = glob(os.path.join(destination, "*")) - files = [] - for filename in filenames: - files.append(os.path.join(destination, filename)) - return files + return [os.path.join(destination, filename) for filename in filenames] @pytest.fixture @@ -50,10 +47,7 @@ def wheel_cache_files(wheel_cache_dir: str) -> List[str]: return [] filenames = glob(os.path.join(destination, "*.whl")) - files = [] - for filename in filenames: - files.append(os.path.join(destination, filename)) - return files + return [os.path.join(destination, filename) for filename in filenames] @pytest.fixture @@ -107,7 +101,7 @@ def list_matches_wheel(wheel_name: str, result: TestPipResult) -> bool: `- foo-1.2.3-py3-none-any.whl `.""" lines = result.stdout.splitlines() expected = f" - {wheel_name}-py3-none-any.whl " - return any(map(lambda line: line.startswith(expected), lines)) + return any((line.startswith(expected) for line in lines)) def list_matches_wheel_abspath(wheel_name: str, result: TestPipResult) -> bool: @@ -120,11 +114,9 @@ def list_matches_wheel_abspath(wheel_name: str, result: TestPipResult) -> bool: lines = result.stdout.splitlines() expected = f"{wheel_name}-py3-none-any.whl" return any( - map( - lambda line: ( - os.path.basename(line).startswith(expected) and os.path.exists(line) - ), - lines, + ( + (os.path.basename(line).startswith(expected) and os.path.exists(line)) + for line in lines ) ) diff --git a/tests/functional/test_help.py b/tests/functional/test_help.py index dba41af5f..9627a1215 100644 --- a/tests/functional/test_help.py +++ b/tests/functional/test_help.py @@ -102,8 +102,8 @@ def test_help_commands_equally_functional(in_memory_pip: InMemoryPip) -> None: results = list(map(in_memory_pip.pip, ("help", "--help"))) results.append(in_memory_pip.pip()) - out = map(lambda x: x.stdout, results) - ret = map(lambda x: x.returncode, results) + out = (x.stdout for x in results) + ret = (x.returncode for x in results) msg = '"pip --help" != "pip help" != "pip"' assert len(set(out)) == 1, "output of: " + msg diff --git a/tests/functional/test_list.py b/tests/functional/test_list.py index 4f2be8387..cf8900a32 100644 --- a/tests/functional/test_list.py +++ b/tests/functional/test_list.py @@ -273,25 +273,19 @@ def test_outdated_flag(script: PipTestEnvironment, data: TestData) -> None: "latest_version": "3.0", "latest_filetype": "sdist", } in json_output - assert ( - dict( - name="simplewheel", - version="1.0", - latest_version="2.0", - latest_filetype="wheel", - ) - in json_output - ) - assert ( - dict( - name="pip-test-package", - version="0.1", - latest_version="0.1.1", - latest_filetype="sdist", - editable_project_location="", - ) - in json_output - ) + assert { + "name": "simplewheel", + "version": "1.0", + "latest_version": "2.0", + "latest_filetype": "wheel", + } in json_output + assert { + "name": "pip-test-package", + "version": "0.1", + "latest_version": "0.1.1", + "latest_filetype": "sdist", + "editable_project_location": "", + } in json_output assert "simple2" not in {p["name"] for p in json_output} diff --git a/tests/lib/__init__.py b/tests/lib/__init__.py index b827f88ba..3c8ca98f7 100644 --- a/tests/lib/__init__.py +++ b/tests/lib/__init__.py @@ -740,21 +740,19 @@ class PipTestEnvironment(TestFileEnvironment): def assert_installed(self, **kwargs: str) -> None: ret = self.pip("list", "--format=json") - installed = set( + installed = { (canonicalize_name(val["name"]), val["version"]) for val in json.loads(ret.stdout) - ) - expected = set((canonicalize_name(k), v) for k, v in kwargs.items()) + } + expected = {(canonicalize_name(k), v) for k, v in kwargs.items()} assert expected <= installed, "{!r} not all in {!r}".format(expected, installed) def assert_not_installed(self, *args: str) -> None: ret = self.pip("list", "--format=json") - installed = set( - canonicalize_name(val["name"]) for val in json.loads(ret.stdout) - ) + installed = {canonicalize_name(val["name"]) for val in json.loads(ret.stdout)} # None of the given names should be listed as installed, i.e. their # intersection should be empty. - expected = set(canonicalize_name(k) for k in args) + expected = {canonicalize_name(k) for k in args} assert not (expected & installed), "{!r} contained in {!r}".format( expected, installed ) @@ -798,16 +796,16 @@ def diff_states( return path.startswith(prefix) start_keys = { - k for k in start.keys() if not any([prefix_match(k, i) for i in ignore]) + k for k in start.keys() if not any(prefix_match(k, i) for i in ignore) } - end_keys = {k for k in end.keys() if not any([prefix_match(k, i) for i in ignore])} + end_keys = {k for k in end.keys() if not any(prefix_match(k, i) for i in ignore)} deleted = {k: start[k] for k in start_keys.difference(end_keys)} created = {k: end[k] for k in end_keys.difference(start_keys)} updated = {} for k in start_keys.intersection(end_keys): if start[k].size != end[k].size: updated[k] = end[k] - return dict(deleted=deleted, created=created, updated=updated) + return {"deleted": deleted, "created": created, "updated": updated} def assert_all_changes( diff --git a/tests/unit/test_finder.py b/tests/unit/test_finder.py index 3404d1498..393e83d5a 100644 --- a/tests/unit/test_finder.py +++ b/tests/unit/test_finder.py @@ -234,7 +234,7 @@ class TestCandidateEvaluator: ) sort_key = evaluator._sort_key results = sorted(links, key=sort_key, reverse=True) - results2 = sorted(reversed(links), key=sort_key, reverse=True) + results2 = sorted(links, key=sort_key, reverse=True) assert links == results, results assert links == results2, results2 @@ -261,7 +261,7 @@ class TestCandidateEvaluator: candidate_evaluator = CandidateEvaluator.create("my-project") sort_key = candidate_evaluator._sort_key results = sorted(links, key=sort_key, reverse=True) - results2 = sorted(reversed(links), key=sort_key, reverse=True) + results2 = sorted(links, key=sort_key, reverse=True) assert links == results, results assert links == results2, results2 @@ -301,7 +301,7 @@ class TestCandidateEvaluator: ) sort_key = evaluator._sort_key results = sorted(links, key=sort_key, reverse=True) - results2 = sorted(reversed(links), key=sort_key, reverse=True) + results2 = sorted(links, key=sort_key, reverse=True) assert links == results, results assert links == results2, results2 diff --git a/tests/unit/test_logging.py b/tests/unit/test_logging.py index 3ba6ed57c..9d507d742 100644 --- a/tests/unit/test_logging.py +++ b/tests/unit/test_logging.py @@ -21,13 +21,13 @@ class TestIndentingFormatter: def make_record(self, msg: str, level_name: str) -> logging.LogRecord: level_number = getattr(logging, level_name) - attrs = dict( - msg=msg, - created=1547704837.040001 + time.timezone, - msecs=40, - levelname=level_name, - levelno=level_number, - ) + attrs = { + "msg": msg, + "created": 1547704837.040001 + time.timezone, + "msecs": 40, + "levelname": level_name, + "levelno": level_number, + } record = logging.makeLogRecord(attrs) return record diff --git a/tests/unit/test_req_uninstall.py b/tests/unit/test_req_uninstall.py index b4ae97350..6a846e202 100644 --- a/tests/unit/test_req_uninstall.py +++ b/tests/unit/test_req_uninstall.py @@ -59,10 +59,9 @@ def test_uninstallation_paths() -> None: def test_compressed_listing(tmpdir: Path) -> None: def in_tmpdir(paths: List[str]) -> List[str]: - li = [] - for path in paths: - li.append(str(os.path.join(tmpdir, path.replace("/", os.path.sep)))) - return li + return [ + str(os.path.join(tmpdir, path.replace("/", os.path.sep))) for path in paths + ] sample = in_tmpdir( [ diff --git a/tests/unit/test_self_check_outdated.py b/tests/unit/test_self_check_outdated.py index c025ff302..6b2333f18 100644 --- a/tests/unit/test_self_check_outdated.py +++ b/tests/unit/test_self_check_outdated.py @@ -40,7 +40,7 @@ def test_pip_self_version_check_calls_underlying_implementation( ) -> None: # GIVEN mock_session = Mock() - fake_options = Values(dict(cache_dir=str(tmpdir))) + fake_options = Values({"cache_dir": str(tmpdir)}) # WHEN self_outdated_check.pip_self_version_check(mock_session, fake_options) diff --git a/tests/unit/test_target_python.py b/tests/unit/test_target_python.py index b659c61fe..bc1713769 100644 --- a/tests/unit/test_target_python.py +++ b/tests/unit/test_target_python.py @@ -54,18 +54,18 @@ class TestTargetPython: "kwargs, expected", [ ({}, ""), - (dict(py_version_info=(3, 6)), "version_info='3.6'"), + ({"py_version_info": (3, 6)}, "version_info='3.6'"), ( - dict(platforms=["darwin"], py_version_info=(3, 6)), + {"platforms": ["darwin"], "py_version_info": (3, 6)}, "platforms=['darwin'] version_info='3.6'", ), ( - dict( - platforms=["darwin"], - py_version_info=(3, 6), - abis=["cp36m"], - implementation="cp", - ), + { + "platforms": ["darwin"], + "py_version_info": (3, 6), + "abis": ["cp36m"], + "implementation": "cp", + }, ( "platforms=['darwin'] version_info='3.6' abis=['cp36m'] " "implementation='cp'" diff --git a/tests/unit/test_vcs.py b/tests/unit/test_vcs.py index 38daaa0f2..3ecc69abf 100644 --- a/tests/unit/test_vcs.py +++ b/tests/unit/test_vcs.py @@ -73,7 +73,7 @@ def test_rev_options_repr() -> None: Git, ["HEAD", "opt1", "opt2"], ["123", "opt1", "opt2"], - dict(extra_args=["opt1", "opt2"]), + {"extra_args": ["opt1", "opt2"]}, ), ], ) From 0a24a001fbe451aa399063555634f8d971776a21 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 28 Aug 2023 15:04:54 +0200 Subject: [PATCH 2/4] Fix issues raised in code review --- ...rst => 4A0C40FF-ABE1-48C7-954C-7C3EB229135F.trivial.rst} | 0 pyproject.toml | 1 + src/pip/_internal/commands/debug.py | 5 +---- src/pip/_internal/commands/list.py | 2 +- tests/functional/test_cache.py | 2 +- tests/lib/__init__.py | 6 ++---- tests/unit/test_finder.py | 6 +++--- 7 files changed, 9 insertions(+), 13 deletions(-) rename news/{4A0C40FF-ABE1-48C7-954C-7C3EB229135F.feature.rst => 4A0C40FF-ABE1-48C7-954C-7C3EB229135F.trivial.rst} (100%) diff --git a/news/4A0C40FF-ABE1-48C7-954C-7C3EB229135F.feature.rst b/news/4A0C40FF-ABE1-48C7-954C-7C3EB229135F.trivial.rst similarity index 100% rename from news/4A0C40FF-ABE1-48C7-954C-7C3EB229135F.feature.rst rename to news/4A0C40FF-ABE1-48C7-954C-7C3EB229135F.trivial.rst diff --git a/pyproject.toml b/pyproject.toml index c3c21802f..7a4fe6246 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -116,6 +116,7 @@ max-complexity = 33 # default is 10 "noxfile.py" = ["G"] "src/pip/_internal/*" = ["PERF203"] "tests/*" = ["B011"] +"tests/unit/test_finder.py" = ["C414"] [tool.ruff.pylint] max-args = 15 # default is 5 diff --git a/src/pip/_internal/commands/debug.py b/src/pip/_internal/commands/debug.py index 564409c68..3d6416023 100644 --- a/src/pip/_internal/commands/debug.py +++ b/src/pip/_internal/commands/debug.py @@ -134,10 +134,7 @@ def show_tags(options: Values) -> None: def ca_bundle_info(config: Configuration) -> str: - levels = set() - for key, _ in config.items(): # noqa: PERF102 Configuration has no keys() method. - levels.add(key.split(".")[0]) - + levels = {key.split(".")[0] for key, _ in config.items()} # noqa: PERF102 if not levels: return "Not specified" diff --git a/src/pip/_internal/commands/list.py b/src/pip/_internal/commands/list.py index 2ec456b95..e551dda9a 100644 --- a/src/pip/_internal/commands/list.py +++ b/src/pip/_internal/commands/list.py @@ -297,7 +297,7 @@ class ListCommand(IndexGroupCommand): # Create and add a separator. if len(data) > 0: - pkg_strings.insert(1, " ".join(("-" * x for x in sizes))) + pkg_strings.insert(1, " ".join("-" * x for x in sizes)) for val in pkg_strings: write_output(val) diff --git a/tests/functional/test_cache.py b/tests/functional/test_cache.py index a6640cbbf..8bee7e4fc 100644 --- a/tests/functional/test_cache.py +++ b/tests/functional/test_cache.py @@ -101,7 +101,7 @@ def list_matches_wheel(wheel_name: str, result: TestPipResult) -> bool: `- foo-1.2.3-py3-none-any.whl `.""" lines = result.stdout.splitlines() expected = f" - {wheel_name}-py3-none-any.whl " - return any((line.startswith(expected) for line in lines)) + return any(line.startswith(expected) for line in lines) def list_matches_wheel_abspath(wheel_name: str, result: TestPipResult) -> bool: diff --git a/tests/lib/__init__.py b/tests/lib/__init__.py index 3c8ca98f7..a48423570 100644 --- a/tests/lib/__init__.py +++ b/tests/lib/__init__.py @@ -795,10 +795,8 @@ def diff_states( prefix = prefix.rstrip(os.path.sep) + os.path.sep return path.startswith(prefix) - start_keys = { - k for k in start.keys() if not any(prefix_match(k, i) for i in ignore) - } - end_keys = {k for k in end.keys() if not any(prefix_match(k, i) for i in ignore)} + start_keys = {k for k in start if not any(prefix_match(k, i) for i in ignore)} + end_keys = {k for k in end if not any(prefix_match(k, i) for i in ignore)} deleted = {k: start[k] for k in start_keys.difference(end_keys)} created = {k: end[k] for k in end_keys.difference(start_keys)} updated = {} diff --git a/tests/unit/test_finder.py b/tests/unit/test_finder.py index 393e83d5a..3404d1498 100644 --- a/tests/unit/test_finder.py +++ b/tests/unit/test_finder.py @@ -234,7 +234,7 @@ class TestCandidateEvaluator: ) sort_key = evaluator._sort_key results = sorted(links, key=sort_key, reverse=True) - results2 = sorted(links, key=sort_key, reverse=True) + results2 = sorted(reversed(links), key=sort_key, reverse=True) assert links == results, results assert links == results2, results2 @@ -261,7 +261,7 @@ class TestCandidateEvaluator: candidate_evaluator = CandidateEvaluator.create("my-project") sort_key = candidate_evaluator._sort_key results = sorted(links, key=sort_key, reverse=True) - results2 = sorted(links, key=sort_key, reverse=True) + results2 = sorted(reversed(links), key=sort_key, reverse=True) assert links == results, results assert links == results2, results2 @@ -301,7 +301,7 @@ class TestCandidateEvaluator: ) sort_key = evaluator._sort_key results = sorted(links, key=sort_key, reverse=True) - results2 = sorted(links, key=sort_key, reverse=True) + results2 = sorted(reversed(links), key=sort_key, reverse=True) assert links == results, results assert links == results2, results2 From 0c0099b23b1109cd26c66def926ffab4c99f73cd Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 29 Aug 2023 11:31:42 +0200 Subject: [PATCH 3/4] Ruff misidentifies config as a dict Co-authored-by: Tzu-ping Chung --- src/pip/_internal/commands/debug.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pip/_internal/commands/debug.py b/src/pip/_internal/commands/debug.py index 3d6416023..f76e033df 100644 --- a/src/pip/_internal/commands/debug.py +++ b/src/pip/_internal/commands/debug.py @@ -134,6 +134,8 @@ def show_tags(options: Values) -> None: def ca_bundle_info(config: Configuration) -> str: + # Ruff misidentifies config as a dict. + # Configuration does not have support the mapping interface. levels = {key.split(".")[0] for key, _ in config.items()} # noqa: PERF102 if not levels: return "Not specified" From af43e139b626ab67e5bccae5fa1645b1dbb68fec Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Wed, 6 Sep 2023 15:39:11 +0800 Subject: [PATCH 4/4] Drive by split() limit to improve performance --- src/pip/_internal/commands/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pip/_internal/commands/debug.py b/src/pip/_internal/commands/debug.py index f76e033df..1b1fd3ea5 100644 --- a/src/pip/_internal/commands/debug.py +++ b/src/pip/_internal/commands/debug.py @@ -136,7 +136,7 @@ def show_tags(options: Values) -> None: def ca_bundle_info(config: Configuration) -> str: # Ruff misidentifies config as a dict. # Configuration does not have support the mapping interface. - levels = {key.split(".")[0] for key, _ in config.items()} # noqa: PERF102 + levels = {key.split(".", 1)[0] for key, _ in config.items()} # noqa: PERF102 if not levels: return "Not specified"