[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
This commit is contained in:
pre-commit-ci[bot] 2024-04-13 00:00:18 +00:00
parent 72ad6dc953
commit f4cd1ba0d6
813 changed files with 66015 additions and 58839 deletions

View file

@ -1,42 +1,38 @@
"""Handles all VCS (version control) support"""
from __future__ import annotations
import logging
import os
import shutil
import sys
import urllib.parse
from typing import (
TYPE_CHECKING,
Any,
Dict,
Iterable,
Iterator,
List,
Mapping,
Optional,
Tuple,
Type,
Union,
)
from typing import Any
from typing import Dict
from typing import Iterable
from typing import Iterator
from typing import List
from typing import Mapping
from typing import Optional
from typing import Tuple
from typing import Type
from typing import TYPE_CHECKING
from typing import Union
from pip._internal.cli.spinners import SpinnerInterface
from pip._internal.exceptions import BadCommand, InstallationError
from pip._internal.utils.misc import (
HiddenText,
ask_path_exists,
backup_dir,
display_path,
hide_url,
hide_value,
is_installable_dir,
rmtree,
)
from pip._internal.utils.subprocess import (
CommandArgs,
call_subprocess,
format_command_args,
make_command,
)
from pip._internal.exceptions import BadCommand
from pip._internal.exceptions import InstallationError
from pip._internal.utils.misc import ask_path_exists
from pip._internal.utils.misc import backup_dir
from pip._internal.utils.misc import display_path
from pip._internal.utils.misc import HiddenText
from pip._internal.utils.misc import hide_url
from pip._internal.utils.misc import hide_value
from pip._internal.utils.misc import is_installable_dir
from pip._internal.utils.misc import rmtree
from pip._internal.utils.subprocess import call_subprocess
from pip._internal.utils.subprocess import CommandArgs
from pip._internal.utils.subprocess import format_command_args
from pip._internal.utils.subprocess import make_command
from pip._internal.utils.urls import get_url_scheme
if TYPE_CHECKING:
@ -46,7 +42,7 @@ if TYPE_CHECKING:
from typing import Literal
__all__ = ["vcs"]
__all__ = ['vcs']
logger = logging.getLogger(__name__)
@ -61,11 +57,11 @@ def is_url(name: str) -> bool:
scheme = get_url_scheme(name)
if scheme is None:
return False
return scheme in ["http", "https", "file", "ftp"] + vcs.all_schemes
return scheme in ['http', 'https', 'file', 'ftp'] + vcs.all_schemes
def make_vcs_requirement_url(
repo_url: str, rev: str, project_name: str, subdir: Optional[str] = None
repo_url: str, rev: str, project_name: str, subdir: str | None = None,
) -> str:
"""
Return the URL for a VCS requirement.
@ -74,17 +70,17 @@ def make_vcs_requirement_url(
repo_url: the remote VCS url, with any needed VCS prefix (e.g. "git+").
project_name: the (unescaped) project name.
"""
egg_project_name = project_name.replace("-", "_")
req = f"{repo_url}@{rev}#egg={egg_project_name}"
egg_project_name = project_name.replace('-', '_')
req = f'{repo_url}@{rev}#egg={egg_project_name}'
if subdir:
req += f"&subdirectory={subdir}"
req += f'&subdirectory={subdir}'
return req
def find_path_to_project_root_from_repo_root(
location: str, repo_root: str
) -> Optional[str]:
location: str, repo_root: str,
) -> str | None:
"""
Find the the Python project's root by searching up the filesystem from
`location`. Return the path to project root relative to `repo_root`.
@ -99,8 +95,8 @@ def find_path_to_project_root_from_repo_root(
# We've traversed up to the root of the filesystem without
# finding a Python project.
logger.warning(
"Could not find a Python project for directory %s (tried all "
"parent directories)",
'Could not find a Python project for directory %s (tried all '
'parent directories)',
orig_location,
)
return None
@ -132,9 +128,9 @@ class RevOptions:
def __init__(
self,
vc_class: Type["VersionControl"],
rev: Optional[str] = None,
extra_args: Optional[CommandArgs] = None,
vc_class: type[VersionControl],
rev: str | None = None,
extra_args: CommandArgs | None = None,
) -> None:
"""
Args:
@ -148,13 +144,13 @@ class RevOptions:
self.extra_args = extra_args
self.rev = rev
self.vc_class = vc_class
self.branch_name: Optional[str] = None
self.branch_name: str | None = None
def __repr__(self) -> str:
return f"<RevOptions {self.vc_class.name}: rev={self.rev!r}>"
return f'<RevOptions {self.vc_class.name}: rev={self.rev!r}>'
@property
def arg_rev(self) -> Optional[str]:
def arg_rev(self) -> str | None:
if self.rev is None:
return self.vc_class.default_arg_rev
@ -174,11 +170,11 @@ class RevOptions:
def to_display(self) -> str:
if not self.rev:
return ""
return ''
return f" (to revision {self.rev})"
return f' (to revision {self.rev})'
def make_new(self, rev: str) -> "RevOptions":
def make_new(self, rev: str) -> RevOptions:
"""
Make a copy of the current instance, but with a new rev.
@ -189,8 +185,8 @@ class RevOptions:
class VcsSupport:
_registry: Dict[str, "VersionControl"] = {}
schemes = ["ssh", "git", "hg", "bzr", "sftp", "svn"]
_registry: dict[str, VersionControl] = {}
schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp', 'svn']
def __init__(self) -> None:
# Register more schemes with urlparse for various version control
@ -202,33 +198,33 @@ class VcsSupport:
return self._registry.__iter__()
@property
def backends(self) -> List["VersionControl"]:
def backends(self) -> list[VersionControl]:
return list(self._registry.values())
@property
def dirnames(self) -> List[str]:
def dirnames(self) -> list[str]:
return [backend.dirname for backend in self.backends]
@property
def all_schemes(self) -> List[str]:
schemes: List[str] = []
def all_schemes(self) -> list[str]:
schemes: list[str] = []
for backend in self.backends:
schemes.extend(backend.schemes)
return schemes
def register(self, cls: Type["VersionControl"]) -> None:
if not hasattr(cls, "name"):
logger.warning("Cannot register VCS %s", cls.__name__)
def register(self, cls: type[VersionControl]) -> None:
if not hasattr(cls, 'name'):
logger.warning('Cannot register VCS %s', cls.__name__)
return
if cls.name not in self._registry:
self._registry[cls.name] = cls()
logger.debug("Registered VCS backend: %s", cls.name)
logger.debug('Registered VCS backend: %s', cls.name)
def unregister(self, name: str) -> None:
if name in self._registry:
del self._registry[name]
def get_backend_for_dir(self, location: str) -> Optional["VersionControl"]:
def get_backend_for_dir(self, location: str) -> VersionControl | None:
"""
Return a VersionControl object if a repository of that type is found
at the given directory.
@ -238,7 +234,7 @@ class VcsSupport:
repo_path = vcs_backend.get_repository_root(location)
if not repo_path:
continue
logger.debug("Determine that %s uses VCS: %s", location, vcs_backend.name)
logger.debug('Determine that %s uses VCS: %s', location, vcs_backend.name)
vcs_backends[repo_path] = vcs_backend
if not vcs_backends:
@ -251,7 +247,7 @@ class VcsSupport:
inner_most_repo_path = max(vcs_backends, key=len)
return vcs_backends[inner_most_repo_path]
def get_backend_for_scheme(self, scheme: str) -> Optional["VersionControl"]:
def get_backend_for_scheme(self, scheme: str) -> VersionControl | None:
"""
Return a VersionControl object or None.
"""
@ -260,7 +256,7 @@ class VcsSupport:
return vcs_backend
return None
def get_backend(self, name: str) -> Optional["VersionControl"]:
def get_backend(self, name: str) -> VersionControl | None:
"""
Return a VersionControl object or None.
"""
@ -272,14 +268,14 @@ vcs = VcsSupport()
class VersionControl:
name = ""
dirname = ""
repo_name = ""
name = ''
dirname = ''
repo_name = ''
# List of supported schemes for this Version Control
schemes: Tuple[str, ...] = ()
schemes: tuple[str, ...] = ()
# Iterable of environment variable names to pass to call_subprocess().
unset_environ: Tuple[str, ...] = ()
default_arg_rev: Optional[str] = None
unset_environ: tuple[str, ...] = ()
default_arg_rev: str | None = None
@classmethod
def should_add_vcs_url_prefix(cls, remote_url: str) -> bool:
@ -287,10 +283,10 @@ class VersionControl:
Return whether the vcs prefix (e.g. "git+") should be added to a
repository's remote url when used in a requirement.
"""
return not remote_url.lower().startswith(f"{cls.name}:")
return not remote_url.lower().startswith(f'{cls.name}:')
@classmethod
def get_subdirectory(cls, location: str) -> Optional[str]:
def get_subdirectory(cls, location: str) -> str | None:
"""
Return the path to Python project root, relative to the repo root.
Return None if the project root is in the repo root.
@ -320,7 +316,7 @@ class VersionControl:
repo_url = cls.get_remote_url(repo_dir)
if cls.should_add_vcs_url_prefix(repo_url):
repo_url = f"{cls.name}+{repo_url}"
repo_url = f'{cls.name}+{repo_url}'
revision = cls.get_requirement_revision(repo_dir)
subdir = cls.get_subdirectory(repo_dir)
@ -329,7 +325,7 @@ class VersionControl:
return req
@staticmethod
def get_base_rev_args(rev: str) -> List[str]:
def get_base_rev_args(rev: str) -> list[str]:
"""
Return the base revision arguments for a vcs command.
@ -353,7 +349,7 @@ class VersionControl:
@classmethod
def make_rev_options(
cls, rev: Optional[str] = None, extra_args: Optional[CommandArgs] = None
cls, rev: str | None = None, extra_args: CommandArgs | None = None,
) -> RevOptions:
"""
Return a RevOptions object.
@ -375,8 +371,8 @@ class VersionControl:
@classmethod
def get_netloc_and_auth(
cls, netloc: str, scheme: str
) -> Tuple[str, Tuple[Optional[str], Optional[str]]]:
cls, netloc: str, scheme: str,
) -> tuple[str, tuple[str | None, str | None]]:
"""
Parse the repository URL's netloc, and return the new netloc to use
along with auth information.
@ -395,7 +391,7 @@ class VersionControl:
return netloc, (None, None)
@classmethod
def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]:
def get_url_rev_and_auth(cls, url: str) -> tuple[str, str | None, AuthInfo]:
"""
Parse the repository URL to use, and return the URL, revision,
and auth info to use.
@ -403,44 +399,44 @@ class VersionControl:
Returns: (url, rev, (username, password)).
"""
scheme, netloc, path, query, frag = urllib.parse.urlsplit(url)
if "+" not in scheme:
if '+' not in scheme:
raise ValueError(
"Sorry, {!r} is a malformed VCS url. "
"The format is <vcs>+<protocol>://<url>, "
"e.g. svn+http://myrepo/svn/MyApp#egg=MyApp".format(url)
'Sorry, {!r} is a malformed VCS url. '
'The format is <vcs>+<protocol>://<url>, '
'e.g. svn+http://myrepo/svn/MyApp#egg=MyApp'.format(url),
)
# Remove the vcs prefix.
scheme = scheme.split("+", 1)[1]
scheme = scheme.split('+', 1)[1]
netloc, user_pass = cls.get_netloc_and_auth(netloc, scheme)
rev = None
if "@" in path:
path, rev = path.rsplit("@", 1)
if '@' in path:
path, rev = path.rsplit('@', 1)
if not rev:
raise InstallationError(
"The URL {!r} has an empty revision (after @) "
"which is not supported. Include a revision after @ "
"or remove @ from the URL.".format(url)
'The URL {!r} has an empty revision (after @) '
'which is not supported. Include a revision after @ '
'or remove @ from the URL.'.format(url),
)
url = urllib.parse.urlunsplit((scheme, netloc, path, query, ""))
url = urllib.parse.urlunsplit((scheme, netloc, path, query, ''))
return url, rev, user_pass
@staticmethod
def make_rev_args(
username: Optional[str], password: Optional[HiddenText]
username: str | None, password: HiddenText | None,
) -> CommandArgs:
"""
Return the RevOptions "extra arguments" to use in obtain().
"""
return []
def get_url_rev_options(self, url: HiddenText) -> Tuple[HiddenText, RevOptions]:
def get_url_rev_options(self, url: HiddenText) -> tuple[HiddenText, RevOptions]:
"""
Return the URL and RevOptions object to use in obtain(),
as a tuple (url, rev_options).
"""
secret_url, rev, user_pass = self.get_url_rev_and_auth(url.secret)
username, secret_password = user_pass
password: Optional[HiddenText] = None
password: HiddenText | None = None
if secret_password is not None:
password = hide_value(secret_password)
extra_args = self.make_rev_args(username, password)
@ -454,7 +450,7 @@ class VersionControl:
Normalize a URL for comparison by unquoting it and removing any
trailing slash.
"""
return urllib.parse.unquote(url).rstrip("/")
return urllib.parse.unquote(url).rstrip('/')
@classmethod
def compare_urls(cls, url1: str, url2: str) -> bool:
@ -464,7 +460,7 @@ class VersionControl:
return cls.normalize_url(url1) == cls.normalize_url(url2)
def fetch_new(
self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int
self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int,
) -> None:
"""
Fetch a revision from a repository, in the case that this is the
@ -496,7 +492,7 @@ class VersionControl:
raise NotImplementedError
@classmethod
def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool:
def is_commit_id_equal(cls, dest: str, name: str | None) -> bool:
"""
Return whether the id of the current commit equals the given name.
@ -526,68 +522,68 @@ class VersionControl:
existing_url = self.get_remote_url(dest)
if self.compare_urls(existing_url, url.secret):
logger.debug(
"%s in %s exists, and has correct URL (%s)",
'%s in %s exists, and has correct URL (%s)',
self.repo_name.title(),
display_path(dest),
url,
)
if not self.is_commit_id_equal(dest, rev_options.rev):
logger.info(
"Updating %s %s%s",
'Updating %s %s%s',
display_path(dest),
self.repo_name,
rev_display,
)
self.update(dest, url, rev_options)
else:
logger.info("Skipping because already up-to-date.")
logger.info('Skipping because already up-to-date.')
return
logger.warning(
"%s %s in %s exists with URL %s",
'%s %s in %s exists with URL %s',
self.name,
self.repo_name,
display_path(dest),
existing_url,
)
prompt = ("(s)witch, (i)gnore, (w)ipe, (b)ackup ", ("s", "i", "w", "b"))
prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ', ('s', 'i', 'w', 'b'))
else:
logger.warning(
"Directory %s already exists, and is not a %s %s.",
'Directory %s already exists, and is not a %s %s.',
dest,
self.name,
self.repo_name,
)
# https://github.com/python/mypy/issues/1174
prompt = ("(i)gnore, (w)ipe, (b)ackup ", ("i", "w", "b")) # type: ignore
prompt = ('(i)gnore, (w)ipe, (b)ackup ', ('i', 'w', 'b')) # type: ignore
logger.warning(
"The plan is to install the %s repository %s",
'The plan is to install the %s repository %s',
self.name,
url,
)
response = ask_path_exists("What to do? {}".format(prompt[0]), prompt[1])
response = ask_path_exists(f'What to do? {prompt[0]}', prompt[1])
if response == "a":
if response == 'a':
sys.exit(-1)
if response == "w":
logger.warning("Deleting %s", display_path(dest))
if response == 'w':
logger.warning('Deleting %s', display_path(dest))
rmtree(dest)
self.fetch_new(dest, url, rev_options, verbosity=verbosity)
return
if response == "b":
if response == 'b':
dest_dir = backup_dir(dest)
logger.warning("Backing up %s to %s", display_path(dest), dest_dir)
logger.warning('Backing up %s to %s', display_path(dest), dest_dir)
shutil.move(dest, dest_dir)
self.fetch_new(dest, url, rev_options, verbosity=verbosity)
return
# Do nothing if the response is "i".
if response == "s":
if response == 's':
logger.info(
"Switching %s %s to %s%s",
'Switching %s %s to %s%s',
self.repo_name,
display_path(dest),
url,
@ -627,14 +623,14 @@ class VersionControl:
@classmethod
def run_command(
cls,
cmd: Union[List[str], CommandArgs],
cmd: list[str] | CommandArgs,
show_stdout: bool = True,
cwd: Optional[str] = None,
on_returncode: 'Literal["raise", "warn", "ignore"]' = "raise",
extra_ok_returncodes: Optional[Iterable[int]] = None,
command_desc: Optional[str] = None,
extra_environ: Optional[Mapping[str, Any]] = None,
spinner: Optional[SpinnerInterface] = None,
cwd: str | None = None,
on_returncode: Literal["raise", "warn", "ignore"] = 'raise',
extra_ok_returncodes: Iterable[int] | None = None,
command_desc: str | None = None,
extra_environ: Mapping[str, Any] | None = None,
spinner: SpinnerInterface | None = None,
log_failed_cmd: bool = True,
stdout_only: bool = False,
) -> str:
@ -664,8 +660,8 @@ class VersionControl:
# errno.ENOENT = no such file or directory
# In other words, the VCS executable isn't available
raise BadCommand(
f"Cannot find command {cls.name!r} - do you have "
f"{cls.name!r} installed and in your PATH?"
f'Cannot find command {cls.name!r} - do you have '
f'{cls.name!r} installed and in your PATH?',
)
except PermissionError:
# errno.EACCES = Permission denied
@ -673,11 +669,11 @@ class VersionControl:
# only for another user. So, the current user don't have
# permission to call the other user command.
raise BadCommand(
f"No permission to execute {cls.name!r} - install it "
f"locally, globally (ask admin), or check your PATH. "
f"See possible solutions at "
f"https://pip.pypa.io/en/latest/reference/pip_freeze/"
f"#fixing-permission-denied."
f'No permission to execute {cls.name!r} - install it '
f'locally, globally (ask admin), or check your PATH. '
f'See possible solutions at '
f'https://pip.pypa.io/en/latest/reference/pip_freeze/'
f'#fixing-permission-denied.',
)
@classmethod
@ -685,11 +681,11 @@ class VersionControl:
"""
Return whether a directory path is a repository directory.
"""
logger.debug("Checking in %s for %s (%s)...", path, cls.dirname, cls.name)
logger.debug('Checking in %s for %s (%s)...', path, cls.dirname, cls.name)
return os.path.exists(os.path.join(path, cls.dirname))
@classmethod
def get_repository_root(cls, location: str) -> Optional[str]:
def get_repository_root(cls, location: str) -> str | None:
"""
Return the "root" (top-level) directory controlled by the vcs,
or `None` if the directory is not in any.