diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b932b146f18..e29e1fcf0af 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: - id: black - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.2.0 + rev: v0.3.6 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] diff --git a/news/12595.trivial.rst b/news/12595.trivial.rst new file mode 100644 index 00000000000..3aad5da6745 --- /dev/null +++ b/news/12595.trivial.rst @@ -0,0 +1 @@ +Update ruff pre-commit to v0.3.6 diff --git a/pyproject.toml b/pyproject.toml index bbdbc792d30..74a7f71ca59 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -201,6 +201,7 @@ max-complexity = 33 # default is 10 "src/pip/_internal/*" = ["PERF203"] "tests/*" = ["B011"] "tests/unit/test_finder.py" = ["C414"] +"src/pip/__pip-runner__.py" = ["UP"] # Must be compatible with Python 2.7 [tool.ruff.lint.pylint] max-args = 15 # default is 5 diff --git a/src/pip/_internal/commands/search.py b/src/pip/_internal/commands/search.py index 55880a155e5..e0d329d58ad 100644 --- a/src/pip/_internal/commands/search.py +++ b/src/pip/_internal/commands/search.py @@ -75,9 +75,8 @@ def search(self, query: List[str], options: Values) -> List[Dict[str, str]]: try: hits = pypi.search({"name": query, "summary": query}, "or") except xmlrpc.client.Fault as fault: - message = "XMLRPC request failed [code: {code}]\n{string}".format( - code=fault.faultCode, - string=fault.faultString, + message = ( + f"XMLRPC request failed [code: {fault.faultCode}]\n{fault.faultString}" ) raise CommandError(message) assert isinstance(hits, list) diff --git a/src/pip/_internal/models/candidate.py b/src/pip/_internal/models/candidate.py index 9184a902aef..b12ffeeac4a 100644 --- a/src/pip/_internal/models/candidate.py +++ b/src/pip/_internal/models/candidate.py @@ -20,10 +20,8 @@ def __init__(self, name: str, version: str, link: Link) -> None: ) def __repr__(self) -> str: - return "".format( - self.name, - self.version, - self.link, + return ( + f"" ) def __str__(self) -> str: diff --git a/src/pip/_internal/operations/build/build_tracker.py b/src/pip/_internal/operations/build/build_tracker.py index 85adc1d711a..0ed8dd23596 100644 --- a/src/pip/_internal/operations/build/build_tracker.py +++ b/src/pip/_internal/operations/build/build_tracker.py @@ -3,9 +3,8 @@ import logging import os from types import TracebackType -from typing import Dict, Generator, Optional, Set, Type, Union +from typing import Dict, Generator, Optional, Type, Union -from pip._internal.models.link import Link from pip._internal.req.req_install import InstallRequirement from pip._internal.utils.temp_dir import TempDirectory diff --git a/src/pip/_internal/operations/build/wheel_legacy.py b/src/pip/_internal/operations/build/wheel_legacy.py index c5f0492ccbe..3ee2a7058d3 100644 --- a/src/pip/_internal/operations/build/wheel_legacy.py +++ b/src/pip/_internal/operations/build/wheel_legacy.py @@ -40,16 +40,16 @@ def get_legacy_build_wheel_path( # Sort for determinism. names = sorted(names) if not names: - msg = ("Legacy build of wheel for {!r} created no files.\n").format(name) + msg = f"Legacy build of wheel for {name!r} created no files.\n" msg += format_command_result(command_args, command_output) logger.warning(msg) return None if len(names) > 1: msg = ( - "Legacy build of wheel for {!r} created more than one file.\n" - "Filenames (choosing first): {}\n" - ).format(name, names) + f"Legacy build of wheel for {name!r} created more than one file.\n" + f"Filenames (choosing first): {names}\n" + ) msg += format_command_result(command_args, command_output) logger.warning(msg) diff --git a/src/pip/_internal/operations/install/wheel.py b/src/pip/_internal/operations/install/wheel.py index 1a93f3557ca..f64c3e9c443 100644 --- a/src/pip/_internal/operations/install/wheel.py +++ b/src/pip/_internal/operations/install/wheel.py @@ -505,9 +505,9 @@ def make_data_scheme_file(record_path: RecordPath) -> "File": _, scheme_key, dest_subpath = normed_path.split(os.path.sep, 2) except ValueError: message = ( - "Unexpected file in {}: {!r}. .data directory contents" - " should be named like: '/'." - ).format(wheel_path, record_path) + f"Unexpected file in {wheel_path}: {record_path!r}. .data directory" + " contents should be named like: '/'." + ) raise InstallationError(message) try: @@ -515,10 +515,11 @@ def make_data_scheme_file(record_path: RecordPath) -> "File": except KeyError: valid_scheme_keys = ", ".join(sorted(scheme_paths)) message = ( - "Unknown scheme key used in {}: {} (for file {!r}). .data" - " directory contents should be in subdirectories named" - " with a valid scheme key ({})" - ).format(wheel_path, scheme_key, record_path, valid_scheme_keys) + f"Unknown scheme key used in {wheel_path}: {scheme_key} " + f"(for file {record_path!r}). .data directory contents " + f"should be in subdirectories named with a valid scheme " + f"key ({valid_scheme_keys})" + ) raise InstallationError(message) dest_path = os.path.join(scheme_path, dest_subpath) diff --git a/src/pip/_internal/req/constructors.py b/src/pip/_internal/req/constructors.py index 7e2d0e5b879..74296345620 100644 --- a/src/pip/_internal/req/constructors.py +++ b/src/pip/_internal/req/constructors.py @@ -132,8 +132,8 @@ def parse_editable(editable_req: str) -> Tuple[Optional[str], str, Set[str]]: package_name = link.egg_fragment if not package_name: raise InstallationError( - "Could not detect requirement name for '{}', please specify one " - "with #egg=your_package_name".format(editable_req) + f"Could not detect requirement name for '{editable_req}', " + "please specify one with #egg=your_package_name" ) return package_name, url, set() diff --git a/src/pip/_internal/req/req_install.py b/src/pip/_internal/req/req_install.py index 49c88fca187..7d527959e81 100644 --- a/src/pip/_internal/req/req_install.py +++ b/src/pip/_internal/req/req_install.py @@ -222,8 +222,9 @@ def __str__(self) -> str: return s def __repr__(self) -> str: - return "<{} object: {} editable={!r}>".format( - self.__class__.__name__, str(self), self.editable + return ( + f"<{self.__class__.__name__} object: " + f"{str(self)} editable={self.editable!r}>" ) def format_debug(self) -> str: diff --git a/src/pip/_internal/req/req_uninstall.py b/src/pip/_internal/req/req_uninstall.py index eec9bd8edcd..3a9ae2b1097 100644 --- a/src/pip/_internal/req/req_uninstall.py +++ b/src/pip/_internal/req/req_uninstall.py @@ -510,11 +510,9 @@ def from_dist(cls, dist: BaseDistribution) -> "UninstallPathSet": elif dist.installed_by_distutils: raise UninstallationError( - "Cannot uninstall {!r}. It is a distutils installed project " - "and thus we cannot accurately determine which files belong " - "to it which would lead to only a partial uninstall.".format( - dist.raw_name, - ) + f"Cannot uninstall {dist.raw_name!r}. It is a distutils installed " + "project and thus we cannot accurately determine which files belong " + "to it which would lead to only a partial uninstall." ) elif dist.installed_as_egg: diff --git a/src/pip/_internal/resolution/legacy/resolver.py b/src/pip/_internal/resolution/legacy/resolver.py index 5ddb848a9bc..74581a84de6 100644 --- a/src/pip/_internal/resolution/legacy/resolver.py +++ b/src/pip/_internal/resolution/legacy/resolver.py @@ -104,9 +104,8 @@ def _check_dist_requires_python( return raise UnsupportedPythonVersion( - "Package {!r} requires a different Python: {} not in {!r}".format( - dist.raw_name, version, requires_python - ) + f"Package {dist.raw_name!r} requires a different Python: " + f"{version} not in {requires_python!r}" ) @@ -263,9 +262,8 @@ def _add_requirement_to_set( ) if has_conflicting_requirement: raise InstallationError( - "Double requirement given: {} (already in {}, name={!r})".format( - install_req, existing_req, install_req.name - ) + f"Double requirement given: {install_req} " + f"(already in {existing_req}, name={install_req.name!r})" ) # When no existing requirement exists, add the requirement as a diff --git a/src/pip/_internal/resolution/resolvelib/candidates.py b/src/pip/_internal/resolution/resolvelib/candidates.py index 4125cda2b7c..49a1f660ca6 100644 --- a/src/pip/_internal/resolution/resolvelib/candidates.py +++ b/src/pip/_internal/resolution/resolvelib/candidates.py @@ -191,10 +191,9 @@ def version(self) -> CandidateVersion: return self._version def format_for_error(self) -> str: - return "{} {} (from {})".format( - self.name, - self.version, - self._link.file_path if self._link.is_file else self._link, + return ( + f"{self.name} {self.version} " + f"(from {self._link.file_path if self._link.is_file else self._link})" ) def _prepare_distribution(self) -> BaseDistribution: @@ -269,9 +268,9 @@ def __init__( # Version may not be present for PEP 508 direct URLs if version is not None: wheel_version = Version(wheel.version) - assert version == wheel_version, "{!r} != {!r} for wheel {}".format( - version, wheel_version, name - ) + assert ( + version == wheel_version + ), f"{version!r} != {wheel_version!r} for wheel {name}" if cache_entry is not None: assert ireq.link.is_wheel diff --git a/src/pip/_internal/utils/direct_url_helpers.py b/src/pip/_internal/utils/direct_url_helpers.py index 0e8e5e1608b..66020d3964a 100644 --- a/src/pip/_internal/utils/direct_url_helpers.py +++ b/src/pip/_internal/utils/direct_url_helpers.py @@ -12,8 +12,8 @@ def direct_url_as_pep440_direct_reference(direct_url: DirectUrl, name: str) -> s requirement = name + " @ " fragments = [] if isinstance(direct_url.info, VcsInfo): - requirement += "{}+{}@{}".format( - direct_url.info.vcs, direct_url.url, direct_url.info.commit_id + requirement += ( + f"{direct_url.info.vcs}+{direct_url.url}@{direct_url.info.commit_id}" ) elif isinstance(direct_url.info, ArchiveInfo): requirement += direct_url.url diff --git a/tests/functional/test_build_env.py b/tests/functional/test_build_env.py index 20cd181be07..11164be0500 100644 --- a/tests/functional/test_build_env.py +++ b/tests/functional/test_build_env.py @@ -24,9 +24,10 @@ def run_with_build_env( test_script_contents: Optional[str] = None, ) -> TestPipResult: build_env_script = script.scratch_path / "build_env.py" + scratch_path = str(script.scratch_path) build_env_script.write_text( dedent( - """ + f""" import subprocess import sys @@ -42,7 +43,7 @@ def run_with_build_env( link_collector = LinkCollector( session=PipSession(), - search_scope=SearchScope.create([{scratch!r}], [], False), + search_scope=SearchScope.create([{scratch_path!r}], [], False), ) selection_prefs = SelectionPreferences( allow_yanked=True, @@ -54,9 +55,7 @@ def run_with_build_env( with global_tempdir_manager(): build_env = BuildEnvironment() - """.format( - scratch=str(script.scratch_path) - ) + """ ) + indent(dedent(setup_script_contents), " ") + indent( diff --git a/tests/functional/test_new_resolver_hashes.py b/tests/functional/test_new_resolver_hashes.py index d26def14ae9..5fb1f2bf799 100644 --- a/tests/functional/test_new_resolver_hashes.py +++ b/tests/functional/test_new_resolver_hashes.py @@ -89,19 +89,15 @@ def test_new_resolver_hash_intersect_from_constraint( script: PipTestEnvironment, ) -> None: find_links = _create_find_links(script) + sdist_hash = find_links.sdist_hash constraints_txt = script.scratch_path / "constraints.txt" - constraints_txt.write_text( - f"base==0.1.0 --hash=sha256:{find_links.sdist_hash}", - ) + constraints_txt.write_text(f"base==0.1.0 --hash=sha256:{sdist_hash}") requirements_txt = script.scratch_path / "requirements.txt" requirements_txt.write_text( - """ - base==0.1.0 --hash=sha256:{sdist_hash} --hash=sha256:{wheel_hash} - """.format( - sdist_hash=find_links.sdist_hash, - wheel_hash=find_links.wheel_hash, - ), + f""" + base==0.1.0 --hash=sha256:{sdist_hash} --hash=sha256:{find_links.wheel_hash} + """, ) result = script.pip( diff --git a/tests/unit/test_collector.py b/tests/unit/test_collector.py index 90064776ef3..b786454e04d 100644 --- a/tests/unit/test_collector.py +++ b/tests/unit/test_collector.py @@ -802,9 +802,9 @@ def test_get_index_content_invalid_content_type( assert ( "pip._internal.index.collector", logging.WARNING, - "Skipping page {} because the GET request got Content-Type: {}. " - "The only supported Content-Types are application/vnd.pypi.simple.v1+json, " - "application/vnd.pypi.simple.v1+html, and text/html".format(url, content_type), + f"Skipping page {url} because the GET request got Content-Type: {content_type}." + " The only supported Content-Types are application/vnd.pypi.simple.v1+json, " + "application/vnd.pypi.simple.v1+html, and text/html", ) in caplog.record_tuples