Change VCS tooling verbosity along with pip's verbosity (#9639)

Co-authored-by: Tzu-ping Chung <uranusjr@gmail.com>
Co-authored-by: Pradyun Gedam <pradyunsg@users.noreply.github.com>
This commit is contained in:
James Gerity 2022-01-25 03:54:02 -05:00 committed by GitHub
parent 78ef0b216f
commit 5c24a798b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 105 additions and 33 deletions

1
news/8819.feature.rst Normal file
View File

@ -0,0 +1 @@
Forward pip's verbosity configuration to VCS tools to control their output accordingly.

View File

@ -237,6 +237,7 @@ class RequirementCommand(IndexGroupCommand):
finder: PackageFinder,
use_user_site: bool,
download_dir: Optional[str] = None,
verbosity: int = 0,
) -> RequirementPreparer:
"""
Create a RequirementPreparer instance for the given parameters.
@ -295,6 +296,7 @@ class RequirementCommand(IndexGroupCommand):
require_hashes=options.require_hashes,
use_user_site=use_user_site,
lazy_wheel=lazy_wheel,
verbosity=verbosity,
in_tree_build=in_tree_build,
)

View File

@ -113,6 +113,7 @@ class DownloadCommand(RequirementCommand):
finder=finder,
download_dir=options.download_dir,
use_user_site=False,
verbosity=self.verbosity,
)
resolver = self.make_resolver(

View File

@ -319,6 +319,7 @@ class InstallCommand(RequirementCommand):
session=session,
finder=finder,
use_user_site=options.use_user_site,
verbosity=self.verbosity,
)
resolver = self.make_resolver(
preparer=preparer,

View File

@ -128,6 +128,7 @@ class WheelCommand(RequirementCommand):
finder=finder,
download_dir=options.wheel_dir,
use_user_site=False,
verbosity=self.verbosity,
)
resolver = self.make_resolver(

View File

@ -59,10 +59,10 @@ def _get_prepared_distribution(
return abstract_dist.get_metadata_distribution()
def unpack_vcs_link(link: Link, location: str) -> None:
def unpack_vcs_link(link: Link, location: str, verbosity: int) -> None:
vcs_backend = vcs.get_backend_for_scheme(link.scheme)
assert vcs_backend is not None
vcs_backend.unpack(location, url=hide_url(link.url))
vcs_backend.unpack(location, url=hide_url(link.url), verbosity=verbosity)
class File:
@ -175,6 +175,7 @@ def unpack_url(
link: Link,
location: str,
download: Downloader,
verbosity: int,
download_dir: Optional[str] = None,
hashes: Optional[Hashes] = None,
) -> Optional[File]:
@ -187,7 +188,7 @@ def unpack_url(
"""
# non-editable vcs urls
if link.is_vcs:
unpack_vcs_link(link, location)
unpack_vcs_link(link, location, verbosity=verbosity)
return None
# Once out-of-tree-builds are no longer supported, could potentially
@ -267,6 +268,7 @@ class RequirementPreparer:
require_hashes: bool,
use_user_site: bool,
lazy_wheel: bool,
verbosity: int,
in_tree_build: bool,
) -> None:
super().__init__()
@ -295,6 +297,9 @@ class RequirementPreparer:
# Should wheels be downloaded lazily?
self.use_lazy_wheel = lazy_wheel
# How verbose should underlying tooling be?
self.verbosity = verbosity
# Should in-tree builds be used for local paths?
self.in_tree_build = in_tree_build
@ -525,7 +530,12 @@ class RequirementPreparer:
elif link.url not in self._downloaded:
try:
local_file = unpack_url(
link, req.source_dir, self._download, self.download_dir, hashes
link,
req.source_dir,
self._download,
self.verbosity,
self.download_dir,
hashes,
)
except NetworkConnectionError as exc:
raise InstallationError(

View File

@ -607,7 +607,7 @@ class InstallRequirement:
# So here, if it's neither a path nor a valid VCS URL, it's a bug.
assert vcs_backend, f"Unsupported VCS URL {self.link.url}"
hidden_url = hide_url(self.link.url)
vcs_backend.obtain(self.source_dir, url=hidden_url)
vcs_backend.obtain(self.source_dir, url=hidden_url, verbosity=0)
# Top-level Actions
def uninstall(

View File

@ -33,7 +33,9 @@ class Bazaar(VersionControl):
def get_base_rev_args(rev: str) -> List[str]:
return ["-r", rev]
def fetch_new(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None:
def fetch_new(
self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int
) -> None:
rev_display = rev_options.to_display()
logger.info(
"Checking out %s%s to %s",
@ -41,7 +43,13 @@ class Bazaar(VersionControl):
rev_display,
display_path(dest),
)
cmd_args = make_command("branch", "-q", rev_options.to_args(), url, dest)
if verbosity <= 0:
flag = "--quiet"
elif verbosity == 1:
flag = ""
else:
flag = f"-{'v'*verbosity}"
cmd_args = make_command("branch", flag, rev_options.to_args(), url, dest)
self.run_command(cmd_args)
def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None:

View File

@ -253,9 +253,17 @@ class Git(VersionControl):
return cls.get_revision(dest) == name
def fetch_new(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None:
def fetch_new(
self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int
) -> None:
rev_display = rev_options.to_display()
logger.info("Cloning %s%s to %s", url, rev_display, display_path(dest))
if verbosity <= 0:
flags: Tuple[str, ...] = ("--quiet",)
elif verbosity == 1:
flags = ()
else:
flags = ("--verbose", "--progress")
if self.get_git_version() >= (2, 17):
# Git added support for partial clone in 2.17
# https://git-scm.com/docs/partial-clone
@ -264,13 +272,13 @@ class Git(VersionControl):
make_command(
"clone",
"--filter=blob:none",
"-q",
*flags,
url,
dest,
)
)
else:
self.run_command(make_command("clone", "-q", url, dest))
self.run_command(make_command("clone", *flags, url, dest))
if rev_options.rev:
# Then a specific revision was requested.

View File

@ -1,7 +1,7 @@
import configparser
import logging
import os
from typing import List, Optional
from typing import List, Optional, Tuple
from pip._internal.exceptions import BadCommand, InstallationError
from pip._internal.utils.misc import HiddenText, display_path
@ -33,7 +33,9 @@ class Mercurial(VersionControl):
def get_base_rev_args(rev: str) -> List[str]:
return [rev]
def fetch_new(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None:
def fetch_new(
self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int
) -> None:
rev_display = rev_options.to_display()
logger.info(
"Cloning hg %s%s to %s",
@ -41,9 +43,17 @@ class Mercurial(VersionControl):
rev_display,
display_path(dest),
)
self.run_command(make_command("clone", "--noupdate", "-q", url, dest))
if verbosity <= 0:
flags: Tuple[str, ...] = ("--quiet",)
elif verbosity == 1:
flags = ()
elif verbosity == 2:
flags = ("--verbose",)
else:
flags = ("--verbose", "--debug")
self.run_command(make_command("clone", "--noupdate", *flags, url, dest))
self.run_command(
make_command("update", "-q", rev_options.to_args()),
make_command("update", *flags, rev_options.to_args()),
cwd=dest,
)

View File

@ -277,7 +277,9 @@ class Subversion(VersionControl):
return []
def fetch_new(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None:
def fetch_new(
self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int
) -> None:
rev_display = rev_options.to_display()
logger.info(
"Checking out %s%s to %s",
@ -285,9 +287,13 @@ class Subversion(VersionControl):
rev_display,
display_path(dest),
)
if verbosity <= 0:
flag = "--quiet"
else:
flag = ""
cmd_args = make_command(
"checkout",
"-q",
flag,
self.get_remote_call_options(),
rev_options.to_args(),
url,

View File

@ -458,7 +458,9 @@ class VersionControl:
"""
return cls.normalize_url(url1) == cls.normalize_url(url2)
def fetch_new(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None:
def fetch_new(
self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int
) -> None:
"""
Fetch a revision from a repository, in the case that this is the
first fetch from the repository.
@ -466,6 +468,7 @@ class VersionControl:
Args:
dest: the directory to fetch the repository to.
rev_options: a RevOptions object.
verbosity: verbosity level.
"""
raise NotImplementedError
@ -498,18 +501,19 @@ class VersionControl:
"""
raise NotImplementedError
def obtain(self, dest: str, url: HiddenText) -> None:
def obtain(self, dest: str, url: HiddenText, verbosity: int) -> None:
"""
Install or update in editable mode the package represented by this
VersionControl object.
:param dest: the repository directory in which to install or update.
:param url: the repository URL starting with a vcs prefix.
:param verbosity: verbosity level.
"""
url, rev_options = self.get_url_rev_options(url)
if not os.path.exists(dest):
self.fetch_new(dest, url, rev_options)
self.fetch_new(dest, url, rev_options, verbosity=verbosity)
return
rev_display = rev_options.to_display()
@ -565,14 +569,14 @@ class VersionControl:
if response == "w":
logger.warning("Deleting %s", display_path(dest))
rmtree(dest)
self.fetch_new(dest, url, rev_options)
self.fetch_new(dest, url, rev_options, verbosity=verbosity)
return
if response == "b":
dest_dir = backup_dir(dest)
logger.warning("Backing up %s to %s", display_path(dest), dest_dir)
shutil.move(dest, dest_dir)
self.fetch_new(dest, url, rev_options)
self.fetch_new(dest, url, rev_options, verbosity=verbosity)
return
# Do nothing if the response is "i".
@ -586,16 +590,17 @@ class VersionControl:
)
self.switch(dest, url, rev_options)
def unpack(self, location: str, url: HiddenText) -> None:
def unpack(self, location: str, url: HiddenText, verbosity: int) -> None:
"""
Clean up current location and download the url repository
(and vcs infos) into location
:param url: the repository URL starting with a vcs prefix.
:param verbosity: verbosity level.
"""
if os.path.exists(location):
rmtree(location)
self.obtain(location, url=url)
self.obtain(location, url=url, verbosity=verbosity)
@classmethod
def get_remote_url(cls, location: str) -> str:

View File

@ -292,7 +292,10 @@ def test_resolve_commit_not_on_branch(
# check we can fetch our commit
rev_options = Git.make_rev_options(commit)
Git().fetch_new(
str(clone_path), HiddenText(repo_path.as_uri(), redacted="*"), rev_options
str(clone_path),
HiddenText(repo_path.as_uri(), redacted="*"),
rev_options,
verbosity=0,
)
@ -333,12 +336,14 @@ def test_partial_clone(script: PipTestEnvironment, tmp_path: pathlib.Path) -> No
str(clone_path1),
HiddenText(repo_path.as_uri(), redacted="*"),
Git.make_rev_options(),
verbosity=0,
)
# Check that we can clone to commit
Git().fetch_new(
str(clone_path2),
HiddenText(repo_path.as_uri(), redacted="*"),
Git.make_rev_options(commit),
verbosity=0,
)
# Write some additional stuff to git pull
@ -375,12 +380,14 @@ def test_partial_clone_without_server_support(
str(clone_path1),
HiddenText(repo_path.as_uri(), redacted="*"),
Git.make_rev_options(),
verbosity=0,
)
# Check that we can clone to commit
Git().fetch_new(
str(clone_path2),
HiddenText(repo_path.as_uri(), redacted="*"),
Git.make_rev_options(commit),
verbosity=0,
)
# Write some additional stuff to git pull
@ -414,6 +421,7 @@ def test_clone_without_partial_clone_support(
str(clone_path),
HiddenText(repo_path.as_uri(), redacted="*"),
Git.make_rev_options(),
verbosity=0,
)
repo_file.write_text(u"...")

View File

@ -55,7 +55,7 @@ def local_checkout(
else:
vcs_backend = vcs.get_backend(vcs_name)
assert vcs_backend is not None
vcs_backend.obtain(repo_url_path, url=hide_url(remote_repo))
vcs_backend.obtain(repo_url_path, url=hide_url(remote_repo), verbosity=0)
return "{}+{}".format(vcs_name, path_to_url(repo_url_path))

View File

@ -46,6 +46,7 @@ def preparer(finder: PackageFinder) -> Iterator[RequirementPreparer]:
session=session,
finder=finder,
use_user_site=False,
verbosity=0,
)
yield preparer

View File

@ -44,6 +44,7 @@ def test_unpack_url_with_urllib_response_without_content_type(data: TestData) ->
temp_dir,
download=download,
download_dir=None,
verbosity=0,
)
assert set(os.listdir(temp_dir)) == {
"PKG-INFO",
@ -188,7 +189,7 @@ class Test_unpack_url:
def test_unpack_url_no_download(self, tmpdir: Path, data: TestData) -> None:
self.prep(tmpdir, data)
unpack_url(self.dist_url, self.build_dir, self.no_download)
unpack_url(self.dist_url, self.build_dir, self.no_download, verbosity=0)
assert os.path.isdir(os.path.join(self.build_dir, "simple"))
assert not os.path.isfile(os.path.join(self.download_dir, self.dist_file))
@ -205,6 +206,7 @@ class Test_unpack_url:
self.build_dir,
download=self.no_download,
hashes=Hashes({"md5": ["bogus"]}),
verbosity=0,
)
def test_unpack_url_thats_a_dir(self, tmpdir: Path, data: TestData) -> None:
@ -216,6 +218,7 @@ class Test_unpack_url:
self.build_dir,
download=self.no_download,
download_dir=self.download_dir,
verbosity=0,
)
assert os.path.isdir(os.path.join(self.build_dir, "fspkg"))
@ -241,7 +244,13 @@ def test_unpack_url_excludes_expected_dirs(tmpdir: Path, exclude_dir: str) -> No
dst_included_dir = dst_dir.joinpath("subdir", exclude_dir)
src_link = Link(path_to_url(src_dir))
unpack_url(src_link, dst_dir, Mock(side_effect=AssertionError), download_dir=None)
unpack_url(
src_link,
dst_dir,
Mock(side_effect=AssertionError),
download_dir=None,
verbosity=0,
)
assert not os.path.isdir(dst_excluded_dir)
assert not os.path.isfile(dst_excluded_file)
assert os.path.isfile(dst_included_file)

View File

@ -98,6 +98,7 @@ class TestRequirementSet:
require_hashes=require_hashes,
use_user_site=False,
lazy_wheel=False,
verbosity=0,
in_tree_build=False,
)
yield Resolver(

View File

@ -764,12 +764,12 @@ class TestSubversionArgs(TestCase):
assert self.call_subprocess_mock.call_args[0][0] == args
def test_obtain(self) -> None:
self.svn.obtain(self.dest, hide_url(self.url))
self.svn.obtain(self.dest, hide_url(self.url), verbosity=0)
self.assert_call_args(
[
"svn",
"checkout",
"-q",
"--quiet",
"--non-interactive",
"--username",
"username",
@ -781,12 +781,12 @@ class TestSubversionArgs(TestCase):
)
def test_fetch_new(self) -> None:
self.svn.fetch_new(self.dest, hide_url(self.url), self.rev_options)
self.svn.fetch_new(self.dest, hide_url(self.url), self.rev_options, verbosity=0)
self.assert_call_args(
[
"svn",
"checkout",
"-q",
"--quiet",
"--non-interactive",
hide_url("svn+http://username:password@svn.example.com/"),
"/tmp/test",
@ -795,12 +795,12 @@ class TestSubversionArgs(TestCase):
def test_fetch_new_revision(self) -> None:
rev_options = RevOptions(Subversion, "123")
self.svn.fetch_new(self.dest, hide_url(self.url), rev_options)
self.svn.fetch_new(self.dest, hide_url(self.url), rev_options, verbosity=0)
self.assert_call_args(
[
"svn",
"checkout",
"-q",
"--quiet",
"--non-interactive",
"-r",
"123",