diff options
author | Jon Dufresne <jon.dufresne@gmail.com> | 2021-08-07 07:53:45 -0700 |
---|---|---|
committer | Jon Dufresne <jon.dufresne@gmail.com> | 2021-08-12 07:45:42 -0700 |
commit | 219def7e105a62444cc067d740506415e2d7d6a9 (patch) | |
tree | 14f9b823391694fa64f9779d56e82ee8ce6d0369 | |
parent | 346bba7a0fca0cd1c39f6b371ea8d0eb8686fd20 (diff) | |
download | pip-219def7e105a62444cc067d740506415e2d7d6a9.tar.gz |
Blacken src/pip/_internal/vcs directory
-rw-r--r-- | .pre-commit-config.yaml | 1 | ||||
-rw-r--r-- | news/26cf7f49-43b0-4a58-97ed-1a4e164c7a9e.trivial.rst | 0 | ||||
-rw-r--r-- | src/pip/_internal/vcs/bazaar.py | 41 | ||||
-rw-r--r-- | src/pip/_internal/vcs/git.py | 143 | ||||
-rw-r--r-- | src/pip/_internal/vcs/mercurial.py | 55 | ||||
-rw-r--r-- | src/pip/_internal/vcs/subversion.py | 89 | ||||
-rw-r--r-- | src/pip/_internal/vcs/versioncontrol.py | 125 |
7 files changed, 235 insertions, 219 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 90b22b9b7..22a1b36ce 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,6 @@ repos: (?x) ^src/pip/_internal/models| ^src/pip/_internal/operations| - ^src/pip/_internal/vcs| ^src/pip/_internal/\w+\.py$| # Tests ^tests/data| diff --git a/news/26cf7f49-43b0-4a58-97ed-1a4e164c7a9e.trivial.rst b/news/26cf7f49-43b0-4a58-97ed-1a4e164c7a9e.trivial.rst new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/news/26cf7f49-43b0-4a58-97ed-1a4e164c7a9e.trivial.rst diff --git a/src/pip/_internal/vcs/bazaar.py b/src/pip/_internal/vcs/bazaar.py index 2abde2cf2..82e75954a 100644 --- a/src/pip/_internal/vcs/bazaar.py +++ b/src/pip/_internal/vcs/bazaar.py @@ -16,55 +16,57 @@ logger = logging.getLogger(__name__) class Bazaar(VersionControl): - name = 'bzr' - dirname = '.bzr' - repo_name = 'branch' + name = "bzr" + dirname = ".bzr" + repo_name = "branch" schemes = ( - 'bzr+http', 'bzr+https', 'bzr+ssh', 'bzr+sftp', 'bzr+ftp', - 'bzr+lp', 'bzr+file' + "bzr+http", + "bzr+https", + "bzr+ssh", + "bzr+sftp", + "bzr+ftp", + "bzr+lp", + "bzr+file", ) @staticmethod def get_base_rev_args(rev: str) -> List[str]: - return ['-r', rev] + return ["-r", rev] def fetch_new(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: rev_display = rev_options.to_display() logger.info( - 'Checking out %s%s to %s', + "Checking out %s%s to %s", url, rev_display, display_path(dest), ) - cmd_args = ( - make_command('branch', '-q', rev_options.to_args(), url, dest) - ) + cmd_args = make_command("branch", "-q", rev_options.to_args(), url, dest) self.run_command(cmd_args) def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: - self.run_command(make_command('switch', url), cwd=dest) + self.run_command(make_command("switch", url), cwd=dest) def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: - cmd_args = make_command('pull', '-q', rev_options.to_args()) + cmd_args = make_command("pull", "-q", rev_options.to_args()) self.run_command(cmd_args, cwd=dest) @classmethod def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: # hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it url, rev, user_pass = super().get_url_rev_and_auth(url) - if url.startswith('ssh://'): - url = 'bzr+' + url + if url.startswith("ssh://"): + url = "bzr+" + url return url, rev, user_pass @classmethod def get_remote_url(cls, location: str) -> str: urls = cls.run_command( - ['info'], show_stdout=False, stdout_only=True, cwd=location + ["info"], show_stdout=False, stdout_only=True, cwd=location ) for line in urls.splitlines(): line = line.strip() - for x in ('checkout of branch: ', - 'parent branch: '): + for x in ("checkout of branch: ", "parent branch: "): if line.startswith(x): repo = line.split(x)[1] if cls._is_local_repository(repo): @@ -75,7 +77,10 @@ class Bazaar(VersionControl): @classmethod def get_revision(cls, location: str) -> str: revision = cls.run_command( - ['revno'], show_stdout=False, stdout_only=True, cwd=location, + ["revno"], + show_stdout=False, + stdout_only=True, + cwd=location, ) return revision.splitlines()[-1] diff --git a/src/pip/_internal/vcs/git.py b/src/pip/_internal/vcs/git.py index 8919aa538..2b9fa8d8b 100644 --- a/src/pip/_internal/vcs/git.py +++ b/src/pip/_internal/vcs/git.py @@ -34,10 +34,11 @@ GIT_VERSION_REGEX = re.compile( r".*$" # Suffix, including any pre- and post-release segments we don't care about. ) -HASH_REGEX = re.compile('^[a-fA-F0-9]{40}$') +HASH_REGEX = re.compile("^[a-fA-F0-9]{40}$") # SCP (Secure copy protocol) shorthand. e.g. 'git@example.com:foo/bar.git' -SCP_REGEX = re.compile(r"""^ +SCP_REGEX = re.compile( + r"""^ # Optional user, e.g. 'git@' (\w+@)? # Server, e.g. 'github.com'. @@ -46,7 +47,9 @@ SCP_REGEX = re.compile(r"""^ # alphanumeric character so as not to be confusable with a Windows paths # like 'C:/foo/bar' or 'C:\foo\bar'. (\w[^:]*) -$""", re.VERBOSE) + $""", + re.VERBOSE, +) def looks_like_hash(sha): @@ -55,16 +58,20 @@ def looks_like_hash(sha): class Git(VersionControl): - name = 'git' - dirname = '.git' - repo_name = 'clone' + name = "git" + dirname = ".git" + repo_name = "clone" schemes = ( - 'git+http', 'git+https', 'git+ssh', 'git+git', 'git+file', + "git+http", + "git+https", + "git+ssh", + "git+git", + "git+file", ) # Prevent the user's environment variables from interfering with pip: # https://github.com/pypa/pip/issues/1130 - unset_environ = ('GIT_DIR', 'GIT_WORK_TREE') - default_arg_rev = 'HEAD' + unset_environ = ("GIT_DIR", "GIT_WORK_TREE") + default_arg_rev = "HEAD" @staticmethod def get_base_rev_args(rev): @@ -83,15 +90,11 @@ class Git(VersionControl): # return False in the rare case rev is both a commit hash # and a tag or a branch; we don't want to cache in that case # because that branch/tag could point to something else in the future - is_tag_or_branch = bool( - self.get_revision_sha(dest, rev_options.rev)[0] - ) + is_tag_or_branch = bool(self.get_revision_sha(dest, rev_options.rev)[0]) return not is_tag_or_branch def get_git_version(self) -> Tuple[int, ...]: - version = self.run_command( - ['version'], show_stdout=False, stdout_only=True - ) + version = self.run_command(["version"], show_stdout=False, stdout_only=True) match = GIT_VERSION_REGEX.match(version) if not match: return () @@ -108,18 +111,18 @@ class Git(VersionControl): # HEAD rather than a symbolic ref. In addition, the -q causes the # command to exit with status code 1 instead of 128 in this case # and to suppress the message to stderr. - args = ['symbolic-ref', '-q', 'HEAD'] + args = ["symbolic-ref", "-q", "HEAD"] output = cls.run_command( args, - extra_ok_returncodes=(1, ), + extra_ok_returncodes=(1,), show_stdout=False, stdout_only=True, cwd=location, ) ref = output.strip() - if ref.startswith('refs/heads/'): - return ref[len('refs/heads/'):] + if ref.startswith("refs/heads/"): + return ref[len("refs/heads/") :] return None @@ -136,11 +139,11 @@ class Git(VersionControl): """ # Pass rev to pre-filter the list. output = cls.run_command( - ['show-ref', rev], + ["show-ref", rev], cwd=dest, show_stdout=False, stdout_only=True, - on_returncode='ignore', + on_returncode="ignore", ) refs = {} # NOTE: We do not use splitlines here since that would split on other @@ -155,12 +158,12 @@ class Git(VersionControl): except ValueError: # Include the offending line to simplify troubleshooting if # this error ever occurs. - raise ValueError(f'unexpected show-ref line: {line!r}') + raise ValueError(f"unexpected show-ref line: {line!r}") refs[ref_name] = ref_sha - branch_ref = f'refs/remotes/origin/{rev}' - tag_ref = f'refs/tags/{rev}' + branch_ref = f"refs/remotes/origin/{rev}" + tag_ref = f"refs/tags/{rev}" sha = refs.get(branch_ref) if sha is not None: @@ -230,11 +233,11 @@ class Git(VersionControl): # fetch the requested revision cls.run_command( - make_command('fetch', '-q', url, rev_options.to_args()), + make_command("fetch", "-q", url, rev_options.to_args()), cwd=dest, ) # Change the revision to the SHA of the ref we fetched - sha = cls.get_revision(dest, rev='FETCH_HEAD') + sha = cls.get_revision(dest, rev="FETCH_HEAD") rev_options = rev_options.make_new(sha) return rev_options @@ -258,27 +261,33 @@ class Git(VersionControl): def fetch_new(self, dest, url, rev_options): # type: (str, HiddenText, RevOptions) -> None rev_display = rev_options.to_display() - logger.info('Cloning %s%s to %s', url, rev_display, display_path(dest)) - self.run_command(make_command('clone', '-q', url, dest)) + logger.info("Cloning %s%s to %s", url, rev_display, display_path(dest)) + self.run_command(make_command("clone", "-q", url, dest)) if rev_options.rev: # Then a specific revision was requested. rev_options = self.resolve_revision(dest, url, rev_options) - branch_name = getattr(rev_options, 'branch_name', None) + branch_name = getattr(rev_options, "branch_name", None) if branch_name is None: # Only do a checkout if the current commit id doesn't match # the requested revision. if not self.is_commit_id_equal(dest, rev_options.rev): cmd_args = make_command( - 'checkout', '-q', rev_options.to_args(), + "checkout", + "-q", + rev_options.to_args(), ) self.run_command(cmd_args, cwd=dest) elif self.get_current_branch(dest) != branch_name: # Then a specific branch was requested, and that branch # is not yet checked out. - track_branch = f'origin/{branch_name}' + track_branch = f"origin/{branch_name}" cmd_args = [ - 'checkout', '-b', branch_name, '--track', track_branch, + "checkout", + "-b", + branch_name, + "--track", + track_branch, ] self.run_command(cmd_args, cwd=dest) else: @@ -293,10 +302,10 @@ class Git(VersionControl): def switch(self, dest, url, rev_options): # type: (str, HiddenText, RevOptions) -> None self.run_command( - make_command('config', 'remote.origin.url', url), + make_command("config", "remote.origin.url", url), cwd=dest, ) - cmd_args = make_command('checkout', '-q', rev_options.to_args()) + cmd_args = make_command("checkout", "-q", rev_options.to_args()) self.run_command(cmd_args, cwd=dest) self.update_submodules(dest) @@ -306,12 +315,12 @@ class Git(VersionControl): # First fetch changes from the default remote if self.get_git_version() >= (1, 9): # fetch tags in addition to everything else - self.run_command(['fetch', '-q', '--tags'], cwd=dest) + self.run_command(["fetch", "-q", "--tags"], cwd=dest) else: - self.run_command(['fetch', '-q'], cwd=dest) + self.run_command(["fetch", "-q"], cwd=dest) # Then reset to wanted revision (maybe even origin/master) rev_options = self.resolve_revision(dest, url, rev_options) - cmd_args = make_command('reset', '--hard', '-q', rev_options.to_args()) + cmd_args = make_command("reset", "--hard", "-q", rev_options.to_args()) self.run_command(cmd_args, cwd=dest) #: update submodules self.update_submodules(dest) @@ -328,8 +337,8 @@ class Git(VersionControl): # We need to pass 1 for extra_ok_returncodes since the command # exits with return code 1 if there are no matching lines. stdout = cls.run_command( - ['config', '--get-regexp', r'remote\..*\.url'], - extra_ok_returncodes=(1, ), + ["config", "--get-regexp", r"remote\..*\.url"], + extra_ok_returncodes=(1,), show_stdout=False, stdout_only=True, cwd=location, @@ -341,10 +350,10 @@ class Git(VersionControl): raise RemoteNotFoundError for remote in remotes: - if remote.startswith('remote.origin.url '): + if remote.startswith("remote.origin.url "): found_remote = remote break - url = found_remote.split(' ')[1] + url = found_remote.split(" ")[1] return cls._git_remote_to_pip_url(url.strip()) @staticmethod @@ -387,7 +396,7 @@ class Git(VersionControl): """ try: cls.run_command( - ['rev-parse', '-q', '--verify', "sha^" + rev], + ["rev-parse", "-q", "--verify", "sha^" + rev], cwd=location, log_failed_cmd=False, ) @@ -400,9 +409,9 @@ class Git(VersionControl): def get_revision(cls, location, rev=None): # type: (str, Optional[str]) -> str if rev is None: - rev = 'HEAD' + rev = "HEAD" current_rev = cls.run_command( - ['rev-parse', rev], + ["rev-parse", rev], show_stdout=False, stdout_only=True, cwd=location, @@ -418,14 +427,14 @@ class Git(VersionControl): """ # find the repo root git_dir = cls.run_command( - ['rev-parse', '--git-dir'], + ["rev-parse", "--git-dir"], show_stdout=False, stdout_only=True, cwd=location, ).strip() if not os.path.isabs(git_dir): git_dir = os.path.join(location, git_dir) - repo_root = os.path.abspath(os.path.join(git_dir, '..')) + repo_root = os.path.abspath(os.path.join(git_dir, "..")) return find_path_to_project_root_from_repo_root(location, repo_root) @classmethod @@ -440,23 +449,21 @@ class Git(VersionControl): # Works around an apparent Git bug # (see https://article.gmane.org/gmane.comp.version-control.git/146500) scheme, netloc, path, query, fragment = urlsplit(url) - if scheme.endswith('file'): - initial_slashes = path[:-len(path.lstrip('/'))] - newpath = ( - initial_slashes + - urllib.request.url2pathname(path) - .replace('\\', '/').lstrip('/') - ) - after_plus = scheme.find('+') + 1 + if scheme.endswith("file"): + initial_slashes = path[: -len(path.lstrip("/"))] + newpath = initial_slashes + urllib.request.url2pathname(path).replace( + "\\", "/" + ).lstrip("/") + after_plus = scheme.find("+") + 1 url = scheme[:after_plus] + urlunsplit( (scheme[after_plus:], netloc, newpath, query, fragment), ) - if '://' not in url: - assert 'file:' not in url - url = url.replace('git+', 'git+ssh://') + if "://" not in url: + assert "file:" not in url + url = url.replace("git+", "git+ssh://") url, rev, user_pass = super().get_url_rev_and_auth(url) - url = url.replace('ssh://', '') + url = url.replace("ssh://", "") else: url, rev, user_pass = super().get_url_rev_and_auth(url) @@ -465,10 +472,10 @@ class Git(VersionControl): @classmethod def update_submodules(cls, location): # type: (str) -> None - if not os.path.exists(os.path.join(location, '.gitmodules')): + if not os.path.exists(os.path.join(location, ".gitmodules")): return cls.run_command( - ['submodule', 'update', '--init', '--recursive', '-q'], + ["submodule", "update", "--init", "--recursive", "-q"], cwd=location, ) @@ -480,26 +487,28 @@ class Git(VersionControl): return loc try: r = cls.run_command( - ['rev-parse', '--show-toplevel'], + ["rev-parse", "--show-toplevel"], cwd=location, show_stdout=False, stdout_only=True, - on_returncode='raise', + on_returncode="raise", log_failed_cmd=False, ) except BadCommand: - logger.debug("could not determine if %s is under git control " - "because git is not available", location) + logger.debug( + "could not determine if %s is under git control " + "because git is not available", + location, + ) return None except InstallationError: return None - return os.path.normpath(r.rstrip('\r\n')) + return os.path.normpath(r.rstrip("\r\n")) @staticmethod def should_add_vcs_url_prefix(repo_url): # type: (str) -> bool - """In either https or ssh form, requirements must be prefixed with git+. - """ + """In either https or ssh form, requirements must be prefixed with git+.""" return True diff --git a/src/pip/_internal/vcs/mercurial.py b/src/pip/_internal/vcs/mercurial.py index bef200bf6..410c79d90 100644 --- a/src/pip/_internal/vcs/mercurial.py +++ b/src/pip/_internal/vcs/mercurial.py @@ -18,11 +18,15 @@ logger = logging.getLogger(__name__) class Mercurial(VersionControl): - name = 'hg' - dirname = '.hg' - repo_name = 'clone' + name = "hg" + dirname = ".hg" + repo_name = "clone" schemes = ( - 'hg+file', 'hg+http', 'hg+https', 'hg+ssh', 'hg+static-http', + "hg+file", + "hg+http", + "hg+https", + "hg+ssh", + "hg+static-http", ) @staticmethod @@ -32,42 +36,40 @@ class Mercurial(VersionControl): def fetch_new(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: rev_display = rev_options.to_display() logger.info( - 'Cloning hg %s%s to %s', + "Cloning hg %s%s to %s", url, rev_display, display_path(dest), ) - self.run_command(make_command('clone', '--noupdate', '-q', url, dest)) + self.run_command(make_command("clone", "--noupdate", "-q", url, dest)) self.run_command( - make_command('update', '-q', rev_options.to_args()), + make_command("update", "-q", rev_options.to_args()), cwd=dest, ) def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: - repo_config = os.path.join(dest, self.dirname, 'hgrc') + repo_config = os.path.join(dest, self.dirname, "hgrc") config = configparser.RawConfigParser() try: config.read(repo_config) - config.set('paths', 'default', url.secret) - with open(repo_config, 'w') as config_file: + config.set("paths", "default", url.secret) + with open(repo_config, "w") as config_file: config.write(config_file) except (OSError, configparser.NoSectionError) as exc: - logger.warning( - 'Could not switch Mercurial repository to %s: %s', url, exc, - ) + logger.warning("Could not switch Mercurial repository to %s: %s", url, exc) else: - cmd_args = make_command('update', '-q', rev_options.to_args()) + cmd_args = make_command("update", "-q", rev_options.to_args()) self.run_command(cmd_args, cwd=dest) def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: - self.run_command(['pull', '-q'], cwd=dest) - cmd_args = make_command('update', '-q', rev_options.to_args()) + self.run_command(["pull", "-q"], cwd=dest) + cmd_args = make_command("update", "-q", rev_options.to_args()) self.run_command(cmd_args, cwd=dest) @classmethod def get_remote_url(cls, location: str) -> str: url = cls.run_command( - ['showconfig', 'paths.default'], + ["showconfig", "paths.default"], show_stdout=False, stdout_only=True, cwd=location, @@ -82,7 +84,7 @@ class Mercurial(VersionControl): Return the repository-local changeset revision number, as an integer. """ current_revision = cls.run_command( - ['parents', '--template={rev}'], + ["parents", "--template={rev}"], show_stdout=False, stdout_only=True, cwd=location, @@ -96,7 +98,7 @@ class Mercurial(VersionControl): hexadecimal string """ current_rev_hash = cls.run_command( - ['parents', '--template={node}'], + ["parents", "--template={node}"], show_stdout=False, stdout_only=True, cwd=location, @@ -116,7 +118,7 @@ class Mercurial(VersionControl): """ # find the repo root repo_root = cls.run_command( - ['root'], show_stdout=False, stdout_only=True, cwd=location + ["root"], show_stdout=False, stdout_only=True, cwd=location ).strip() if not os.path.isabs(repo_root): repo_root = os.path.abspath(os.path.join(location, repo_root)) @@ -129,20 +131,23 @@ class Mercurial(VersionControl): return loc try: r = cls.run_command( - ['root'], + ["root"], cwd=location, show_stdout=False, stdout_only=True, - on_returncode='raise', + on_returncode="raise", log_failed_cmd=False, ) except BadCommand: - logger.debug("could not determine if %s is under hg control " - "because hg is not available", location) + logger.debug( + "could not determine if %s is under hg control " + "because hg is not available", + location, + ) return None except InstallationError: return None - return os.path.normpath(r.rstrip('\r\n')) + return os.path.normpath(r.rstrip("\r\n")) vcs.register(Mercurial) diff --git a/src/pip/_internal/vcs/subversion.py b/src/pip/_internal/vcs/subversion.py index 965e0b425..c95774c76 100644 --- a/src/pip/_internal/vcs/subversion.py +++ b/src/pip/_internal/vcs/subversion.py @@ -24,16 +24,14 @@ logger = logging.getLogger(__name__) _svn_xml_url_re = re.compile('url="([^"]+)"') _svn_rev_re = re.compile(r'committed-rev="(\d+)"') _svn_info_xml_rev_re = re.compile(r'\s*revision="(\d+)"') -_svn_info_xml_url_re = re.compile(r'<url>(.*)</url>') +_svn_info_xml_url_re = re.compile(r"<url>(.*)</url>") class Subversion(VersionControl): - name = 'svn' - dirname = '.svn' - repo_name = 'checkout' - schemes = ( - 'svn+ssh', 'svn+http', 'svn+https', 'svn+svn', 'svn+file' - ) + name = "svn" + dirname = ".svn" + repo_name = "checkout" + schemes = ("svn+ssh", "svn+http", "svn+https", "svn+svn", "svn+file") @classmethod def should_add_vcs_url_prefix(cls, remote_url): @@ -43,7 +41,7 @@ class Subversion(VersionControl): @staticmethod def get_base_rev_args(rev): # type: (str) -> List[str] - return ['-r', rev] + return ["-r", rev] @classmethod def get_revision(cls, location): @@ -57,9 +55,9 @@ class Subversion(VersionControl): for base, dirs, _ in os.walk(location): if cls.dirname not in dirs: dirs[:] = [] - continue # no sense walking uncontrolled subdirs + continue # no sense walking uncontrolled subdirs dirs.remove(cls.dirname) - entries_fn = os.path.join(base, cls.dirname, 'entries') + entries_fn = os.path.join(base, cls.dirname, "entries") if not os.path.exists(entries_fn): # FIXME: should we warn? continue @@ -68,10 +66,10 @@ class Subversion(VersionControl): if base == location: assert dirurl is not None - base = dirurl + '/' # save the root url + base = dirurl + "/" # save the root url elif not dirurl or not dirurl.startswith(base): dirs[:] = [] - continue # not part of the same svn tree, skip it + continue # not part of the same svn tree, skip it revision = max(revision, localrev) return str(revision) @@ -82,7 +80,7 @@ class Subversion(VersionControl): This override allows the auth information to be passed to svn via the --username and --password options instead of via the URL. """ - if scheme == 'ssh': + if scheme == "ssh": # The --username and --password options can't be used for # svn+ssh URLs, so keep the auth information in the URL. return super().get_netloc_and_auth(netloc, scheme) @@ -94,8 +92,8 @@ class Subversion(VersionControl): # type: (str) -> Tuple[str, Optional[str], AuthInfo] # hotfix the URL scheme after removing svn+ from svn+ssh:// readd it url, rev, user_pass = super().get_url_rev_and_auth(url) - if url.startswith('ssh://'): - url = 'svn+' + url + if url.startswith("ssh://"): + url = "svn+" + url return url, rev, user_pass @staticmethod @@ -103,9 +101,9 @@ class Subversion(VersionControl): # type: (Optional[str], Optional[HiddenText]) -> CommandArgs extra_args = [] # type: CommandArgs if username: - extra_args += ['--username', username] + extra_args += ["--username", username] if password: - extra_args += ['--password', password] + extra_args += ["--password", password] return extra_args @@ -139,26 +137,24 @@ class Subversion(VersionControl): # type: (str) -> Tuple[Optional[str], int] from pip._internal.exceptions import InstallationError - entries_path = os.path.join(location, cls.dirname, 'entries') + entries_path = os.path.join(location, cls.dirname, "entries") if os.path.exists(entries_path): with open(entries_path) as f: data = f.read() else: # subversion >= 1.7 does not have the 'entries' file - data = '' + data = "" url = None - if (data.startswith('8') or - data.startswith('9') or - data.startswith('10')): - entries = list(map(str.splitlines, data.split('\n\x0c\n'))) + if data.startswith("8") or data.startswith("9") or data.startswith("10"): + entries = list(map(str.splitlines, data.split("\n\x0c\n"))) del entries[0][0] # get rid of the '8' url = entries[0][3] revs = [int(d[9]) for d in entries if len(d) > 9 and d[9]] + [0] - elif data.startswith('<?xml'): + elif data.startswith("<?xml"): match = _svn_xml_url_re.search(data) if not match: - raise ValueError(f'Badly formatted data: {data!r}') - url = match.group(1) # get repository URL + raise ValueError(f"Badly formatted data: {data!r}") + url = match.group(1) # get repository URL revs = [int(m.group(1)) for m in _svn_rev_re.finditer(data)] + [0] else: try: @@ -169,16 +165,14 @@ class Subversion(VersionControl): # is being used to prompt for passwords, because passwords # are only potentially needed for remote server requests. xml = cls.run_command( - ['info', '--xml', location], + ["info", "--xml", location], show_stdout=False, stdout_only=True, ) match = _svn_info_xml_url_re.search(xml) assert match is not None url = match.group(1) - revs = [ - int(m.group(1)) for m in _svn_info_xml_rev_re.finditer(xml) - ] + revs = [int(m.group(1)) for m in _svn_info_xml_rev_re.finditer(xml)] except InstallationError: url, revs = None, [] @@ -225,15 +219,13 @@ class Subversion(VersionControl): # compiled Mar 28 2018, 08:49:13 on x86_64-pc-linux-gnu # svn, version 1.12.0-SlikSvn (SlikSvn/1.12.0) # compiled May 28 2019, 13:44:56 on x86_64-microsoft-windows6.2 - version_prefix = 'svn, version ' - version = self.run_command( - ['--version'], show_stdout=False, stdout_only=True - ) + version_prefix = "svn, version " + version = self.run_command(["--version"], show_stdout=False, stdout_only=True) if not version.startswith(version_prefix): return () - version = version[len(version_prefix):].split()[0] - version_list = version.partition('-')[0].split('.') + version = version[len(version_prefix) :].split()[0] + version_list = version.partition("-")[0].split(".") try: parsed_version = tuple(map(int, version_list)) except ValueError: @@ -278,7 +270,7 @@ class Subversion(VersionControl): if not self.use_interactive: # --non-interactive switch is available since Subversion 0.14.4. # Subversion < 1.8 runs in interactive mode by default. - return ['--non-interactive'] + return ["--non-interactive"] svn_version = self.get_vcs_version() # By default, Subversion >= 1.8 runs in non-interactive mode if @@ -290,7 +282,7 @@ class Subversion(VersionControl): # SVN 1.7, pip should continue to support SVN 1.7. Therefore, pip # can't safely add the option if the SVN version is < 1.8 (or unknown). if svn_version >= (1, 8): - return ['--force-interactive'] + return ["--force-interactive"] return [] @@ -298,29 +290,38 @@ class Subversion(VersionControl): # type: (str, HiddenText, RevOptions) -> None rev_display = rev_options.to_display() logger.info( - 'Checking out %s%s to %s', + "Checking out %s%s to %s", url, rev_display, display_path(dest), ) cmd_args = make_command( - 'checkout', '-q', self.get_remote_call_options(), - rev_options.to_args(), url, dest, + "checkout", + "-q", + self.get_remote_call_options(), + rev_options.to_args(), + url, + dest, ) self.run_command(cmd_args) def switch(self, dest, url, rev_options): # type: (str, HiddenText, RevOptions) -> None cmd_args = make_command( - 'switch', self.get_remote_call_options(), rev_options.to_args(), - url, dest, + "switch", + self.get_remote_call_options(), + rev_options.to_args(), + url, + dest, ) self.run_command(cmd_args) def update(self, dest, url, rev_options): # type: (str, HiddenText, RevOptions) -> None cmd_args = make_command( - 'update', self.get_remote_call_options(), rev_options.to_args(), + "update", + self.get_remote_call_options(), + rev_options.to_args(), dest, ) self.run_command(cmd_args) diff --git a/src/pip/_internal/vcs/versioncontrol.py b/src/pip/_internal/vcs/versioncontrol.py index 9da5109bf..42a0c21d0 100644 --- a/src/pip/_internal/vcs/versioncontrol.py +++ b/src/pip/_internal/vcs/versioncontrol.py @@ -41,7 +41,7 @@ if TYPE_CHECKING: from typing import Literal -__all__ = ['vcs'] +__all__ = ["vcs"] logger = logging.getLogger(__name__) @@ -57,7 +57,7 @@ def is_url(name): 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, rev, project_name, subdir=None): @@ -70,9 +70,9 @@ def make_vcs_requirement_url(repo_url, rev, project_name, subdir=None): project_name: the (unescaped) project name. """ egg_project_name = project_name.replace("-", "_") - req = f'{repo_url}@{rev}#egg={egg_project_name}' + req = f"{repo_url}@{rev}#egg={egg_project_name}" if subdir: - req += f'&subdirectory={subdir}' + req += f"&subdirectory={subdir}" return req @@ -147,7 +147,7 @@ class RevOptions: def __repr__(self): # type: () -> 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): @@ -173,9 +173,9 @@ class RevOptions: def to_display(self): # type: () -> str if not self.rev: - return '' + return "" - return f' (to revision {self.rev})' + return f" (to revision {self.rev})" def make_new(self, rev): # type: (str) -> RevOptions @@ -190,7 +190,7 @@ class RevOptions: class VcsSupport: _registry = {} # type: Dict[str, VersionControl] - schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp', 'svn'] + schemes = ["ssh", "git", "hg", "bzr", "sftp", "svn"] def __init__(self): # type: () -> None @@ -223,12 +223,12 @@ class VcsSupport: def register(self, cls): # type: (Type[VersionControl]) -> None - if not hasattr(cls, 'name'): - logger.warning('Cannot register VCS %s', cls.__name__) + 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): # type: (str) -> None @@ -246,8 +246,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: @@ -283,9 +282,9 @@ vcs = VcsSupport() class VersionControl: - name = '' - dirname = '' - repo_name = '' + name = "" + dirname = "" + repo_name = "" # List of supported schemes for this Version Control schemes = () # type: Tuple[str, ...] # Iterable of environment variable names to pass to call_subprocess(). @@ -299,7 +298,7 @@ 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): @@ -335,12 +334,11 @@ 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) - req = make_vcs_requirement_url(repo_url, revision, project_name, - subdir=subdir) + req = make_vcs_requirement_url(repo_url, revision, project_name, subdir=subdir) return req @@ -385,8 +383,8 @@ class VersionControl: def _is_local_repository(cls, repo): # type: (str) -> bool """ - posix absolute paths start with os.path.sep, - win32 ones start with drive (like c:\\folder) + posix absolute paths start with os.path.sep, + win32 ones start with drive (like c:\\folder) """ drive, tail = os.path.splitdrive(repo) return repo.startswith(os.path.sep) or bool(drive) @@ -421,25 +419,25 @@ 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) ) # 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) ) - url = urllib.parse.urlunsplit((scheme, netloc, path, query, '')) + url = urllib.parse.urlunsplit((scheme, netloc, path, query, "")) return url, rev, user_pass @staticmethod @@ -473,7 +471,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, url2): @@ -481,7 +479,7 @@ class VersionControl: """ Compare two repo URLs for identity, ignoring incidental differences. """ - return (cls.normalize_url(url1) == cls.normalize_url(url2)) + return cls.normalize_url(url1) == cls.normalize_url(url2) def fetch_new(self, dest, url, rev_options): # type: (str, HiddenText, RevOptions) -> None @@ -547,73 +545,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 ', # type: ignore - ('i', 'w', 'b')) + 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("What to do? {}".format(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) 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) 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, @@ -658,7 +651,7 @@ class VersionControl: cmd, # type: Union[List[str], CommandArgs] show_stdout=True, # type: bool cwd=None, # type: Optional[str] - on_returncode='raise', # type: Literal["raise", "warn", "ignore"] + on_returncode="raise", # type: Literal["raise", "warn", "ignore"] extra_ok_returncodes=None, # type: Optional[Iterable[int]] command_desc=None, # type: Optional[str] extra_environ=None, # type: Optional[Mapping[str, Any]] @@ -674,21 +667,26 @@ class VersionControl: """ cmd = make_command(cls.name, *cmd) try: - return call_subprocess(cmd, show_stdout, cwd, - on_returncode=on_returncode, - extra_ok_returncodes=extra_ok_returncodes, - command_desc=command_desc, - extra_environ=extra_environ, - unset_environ=cls.unset_environ, - spinner=spinner, - log_failed_cmd=log_failed_cmd, - stdout_only=stdout_only) + return call_subprocess( + cmd, + show_stdout, + cwd, + on_returncode=on_returncode, + extra_ok_returncodes=extra_ok_returncodes, + command_desc=command_desc, + extra_environ=extra_environ, + unset_environ=cls.unset_environ, + spinner=spinner, + log_failed_cmd=log_failed_cmd, + stdout_only=stdout_only, + ) except FileNotFoundError: # 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 # This error occurs, for instance, when the command is installed @@ -708,8 +706,7 @@ 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 |