Skip to content

Commit

Permalink
Merge pull request #949 from atugushev/downloading-progress-bar
Browse files Browse the repository at this point in the history
Show progress bar when downloading package in verbose mode
  • Loading branch information
atugushev authored Apr 22, 2020
2 parents 93454b7 + 31fe23c commit 0d84a4c
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 5 deletions.
2 changes: 1 addition & 1 deletion piptools/_compat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import six

from .pip_compat import PIP_VERSION, parse_requirements
from .pip_compat import BAR_TYPES, PIP_VERSION, parse_requirements

if six.PY2:
from .tempfile import TemporaryDirectory
Expand Down
2 changes: 2 additions & 0 deletions piptools/_compat/pip_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
def install_req_from_parsed_requirement(req, **kwargs):
return req

from pip._internal.utils.ui import BAR_TYPES

else:
from pip._internal.req.constructors import install_req_from_parsed_requirement
from pip._internal.cli.progress_bars import BAR_TYPES


def parse_requirements(
Expand Down
3 changes: 3 additions & 0 deletions piptools/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import contextlib
import logging
import sys

from . import click

Expand All @@ -12,6 +13,8 @@


class LogContext(object):
stream = sys.stderr

def __init__(self, verbosity=0, indent_width=2):
self.verbosity = verbosity
self.current_indent = 0
Expand Down
48 changes: 44 additions & 4 deletions piptools/repositories/pypi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import collections
import hashlib
import itertools
import logging
import os
from contextlib import contextmanager
from shutil import rmtree
Expand All @@ -15,12 +17,13 @@
from pip._internal.req import RequirementSet
from pip._internal.req.req_tracker import get_requirement_tracker
from pip._internal.utils.hashes import FAVORITE_HASH
from pip._internal.utils.logging import indent_log, setup_logging
from pip._internal.utils.misc import normalize_path
from pip._internal.utils.temp_dir import TempDirectory, global_tempdir_manager
from pip._internal.utils.urls import path_to_url, url_to_path
from pip._vendor.requests import RequestException

from .._compat import PIP_VERSION, TemporaryDirectory, contextlib
from .._compat import BAR_TYPES, PIP_VERSION, TemporaryDirectory, contextlib
from ..click import progressbar
from ..exceptions import NoCandidateFound
from ..logging import log
Expand Down Expand Up @@ -82,6 +85,8 @@ def __init__(self, pip_args, cache_dir):
self._download_dir = fs_str(os.path.join(self._cache_dir, "pkgs"))
self._wheel_download_dir = fs_str(os.path.join(self._cache_dir, "wheels"))

self._setup_logging()

def freshen_build_caches(self):
"""
Start with fresh build/source caches. Will remove any old build
Expand Down Expand Up @@ -144,7 +149,7 @@ def find_best_match(self, ireq, prereleases=None):
def resolve_reqs(self, download_dir, ireq, wheel_cache):
with get_requirement_tracker() as req_tracker, TempDirectory(
kind="resolver"
) as temp_dir:
) as temp_dir, indent_log():
preparer = self.command.make_requirement_preparer(
temp_build_dir=temp_dir,
options=self.options,
Expand Down Expand Up @@ -368,11 +373,17 @@ def _get_file_hash(self, link):
# Choose a context manager depending on verbosity
if log.verbosity >= 1:
iter_length = f.size / FILE_CHUNK_SIZE if f.size else None
bar_template = "{prefix}[%(bar)s] %(info)s".format(
bar_template = "{prefix} |%(bar)s| %(info)s".format(
prefix=" " * log.current_indent
)
context_manager = progressbar(
chunks, length=iter_length, bar_template=bar_template
chunks,
length=iter_length,
# Make it look like default pip progress bar
fill_char="█",
empty_char=" ",
bar_template=bar_template,
width=32,
)
else:
context_manager = contextlib.nullcontext(chunks)
Expand Down Expand Up @@ -415,6 +426,35 @@ def _wheel_support_index_min(self, tags=None):
Wheel.support_index_min = original_support_index_min
self._available_candidates_cache = original_cache

def _setup_logging(self):
"""
Setup pip's logger. Ensure pip is verbose same as pip-tools and sync
pip's log stream with LogContext.stream.
"""
# Default pip's logger is noisy, so decrease it's verbosity
setup_logging(
verbosity=log.verbosity - 1,
no_color=self.options.no_color,
user_log_file=self.options.log,
)

# Sync pip's console handler stream with LogContext.stream
logger = logging.getLogger()
console_handlers = [
handler for handler in logger.handlers if handler.name == "console"
]
if console_handlers: # pragma: no branch
console_handlers[0].stream = log.stream
else: # pragma: no cover
# There is always a console handler. This warning would be a signal that
# this block should be removed/revisited, because of pip possibly
# refactored-out logging config.
log.warning("Couldn't find a 'console' logging handler")

# Sync pip's progress bars stream with LogContext.stream
for bar_cls in itertools.chain(*BAR_TYPES.values()):
bar_cls.file = log.stream


@contextmanager
def open_local_or_remote_file(link, session):
Expand Down

0 comments on commit 0d84a4c

Please sign in to comment.