mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Merge pull request #9635 from jdufresne/blacken-cli
Blacken src/pip/_internal/cli directory
This commit is contained in:
commit
d37fdf27d3
12 changed files with 518 additions and 471 deletions
|
@ -23,7 +23,6 @@ repos:
|
|||
exclude: |
|
||||
(?x)
|
||||
^docs/|
|
||||
^src/pip/_internal/cli|
|
||||
^src/pip/_internal/commands|
|
||||
^src/pip/_internal/distributions|
|
||||
^src/pip/_internal/index|
|
||||
|
|
0
news/917ab6ff-72ea-4db5-846a-30273dac1c0c.trivial.rst
Normal file
0
news/917ab6ff-72ea-4db5-846a-30273dac1c0c.trivial.rst
Normal file
|
@ -14,17 +14,16 @@ from pip._internal.utils.misc import get_installed_distributions
|
|||
|
||||
def autocomplete():
|
||||
# type: () -> None
|
||||
"""Entry Point for completion of main and subcommand options.
|
||||
"""
|
||||
"""Entry Point for completion of main and subcommand options."""
|
||||
# Don't complete if user hasn't sourced bash_completion file.
|
||||
if 'PIP_AUTO_COMPLETE' not in os.environ:
|
||||
if "PIP_AUTO_COMPLETE" not in os.environ:
|
||||
return
|
||||
cwords = os.environ['COMP_WORDS'].split()[1:]
|
||||
cword = int(os.environ['COMP_CWORD'])
|
||||
cwords = os.environ["COMP_WORDS"].split()[1:]
|
||||
cword = int(os.environ["COMP_CWORD"])
|
||||
try:
|
||||
current = cwords[cword - 1]
|
||||
except IndexError:
|
||||
current = ''
|
||||
current = ""
|
||||
|
||||
parser = create_main_parser()
|
||||
subcommands = list(commands_dict)
|
||||
|
@ -39,13 +38,13 @@ def autocomplete():
|
|||
# subcommand options
|
||||
if subcommand_name is not None:
|
||||
# special case: 'help' subcommand has no options
|
||||
if subcommand_name == 'help':
|
||||
if subcommand_name == "help":
|
||||
sys.exit(1)
|
||||
# special case: list locally installed dists for show and uninstall
|
||||
should_list_installed = (
|
||||
subcommand_name in ['show', 'uninstall'] and
|
||||
not current.startswith('-')
|
||||
)
|
||||
should_list_installed = not current.startswith("-") and subcommand_name in [
|
||||
"show",
|
||||
"uninstall",
|
||||
]
|
||||
if should_list_installed:
|
||||
lc = current.lower()
|
||||
installed = [
|
||||
|
@ -67,13 +66,15 @@ def autocomplete():
|
|||
options.append((opt_str, opt.nargs))
|
||||
|
||||
# filter out previously specified options from available options
|
||||
prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]]
|
||||
prev_opts = [x.split("=")[0] for x in cwords[1 : cword - 1]]
|
||||
options = [(x, v) for (x, v) in options if x not in prev_opts]
|
||||
# filter options by current input
|
||||
options = [(k, v) for k, v in options if k.startswith(current)]
|
||||
# get completion type given cwords and available subcommand options
|
||||
completion_type = get_path_completion_type(
|
||||
cwords, cword, subcommand.parser.option_list_all,
|
||||
cwords,
|
||||
cword,
|
||||
subcommand.parser.option_list_all,
|
||||
)
|
||||
# get completion files and directories if ``completion_type`` is
|
||||
# ``<file>``, ``<dir>`` or ``<path>``
|
||||
|
@ -84,7 +85,7 @@ def autocomplete():
|
|||
opt_label = option[0]
|
||||
# append '=' to options which require args
|
||||
if option[1] and option[0][:2] == "--":
|
||||
opt_label += '='
|
||||
opt_label += "="
|
||||
print(opt_label)
|
||||
else:
|
||||
# show main parser options only when necessary
|
||||
|
@ -92,19 +93,17 @@ def autocomplete():
|
|||
opts = [i.option_list for i in parser.option_groups]
|
||||
opts.append(parser.option_list)
|
||||
flattened_opts = chain.from_iterable(opts)
|
||||
if current.startswith('-'):
|
||||
if current.startswith("-"):
|
||||
for opt in flattened_opts:
|
||||
if opt.help != optparse.SUPPRESS_HELP:
|
||||
subcommands += opt._long_opts + opt._short_opts
|
||||
else:
|
||||
# get completion type given cwords and all available options
|
||||
completion_type = get_path_completion_type(cwords, cword,
|
||||
flattened_opts)
|
||||
completion_type = get_path_completion_type(cwords, cword, flattened_opts)
|
||||
if completion_type:
|
||||
subcommands = list(auto_complete_paths(current,
|
||||
completion_type))
|
||||
subcommands = list(auto_complete_paths(current, completion_type))
|
||||
|
||||
print(' '.join([x for x in subcommands if x.startswith(current)]))
|
||||
print(" ".join([x for x in subcommands if x.startswith(current)]))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
@ -117,16 +116,16 @@ def get_path_completion_type(cwords, cword, opts):
|
|||
:param opts: The available options to check
|
||||
:return: path completion type (``file``, ``dir``, ``path`` or None)
|
||||
"""
|
||||
if cword < 2 or not cwords[cword - 2].startswith('-'):
|
||||
if cword < 2 or not cwords[cword - 2].startswith("-"):
|
||||
return None
|
||||
for opt in opts:
|
||||
if opt.help == optparse.SUPPRESS_HELP:
|
||||
continue
|
||||
for o in str(opt).split('/'):
|
||||
if cwords[cword - 2].split('=')[0] == o:
|
||||
for o in str(opt).split("/"):
|
||||
if cwords[cword - 2].split("=")[0] == o:
|
||||
if not opt.metavar or any(
|
||||
x in ('path', 'file', 'dir')
|
||||
for x in opt.metavar.split('/')):
|
||||
x in ("path", "file", "dir") for x in opt.metavar.split("/")
|
||||
):
|
||||
return opt.metavar
|
||||
return None
|
||||
|
||||
|
@ -148,15 +147,16 @@ def auto_complete_paths(current, completion_type):
|
|||
return
|
||||
filename = os.path.normcase(filename)
|
||||
# list all files that start with ``filename``
|
||||
file_list = (x for x in os.listdir(current_path)
|
||||
if os.path.normcase(x).startswith(filename))
|
||||
file_list = (
|
||||
x for x in os.listdir(current_path) if os.path.normcase(x).startswith(filename)
|
||||
)
|
||||
for f in file_list:
|
||||
opt = os.path.join(current_path, f)
|
||||
comp_file = os.path.normcase(os.path.join(directory, f))
|
||||
# complete regular files when there is not ``<dir>`` after option
|
||||
# complete directories when there is ``<file>``, ``<path>`` or
|
||||
# ``<dir>``after option
|
||||
if completion_type != 'dir' and os.path.isfile(opt):
|
||||
if completion_type != "dir" and os.path.isfile(opt):
|
||||
yield comp_file
|
||||
elif os.path.isdir(opt):
|
||||
yield os.path.join(comp_file, '')
|
||||
yield os.path.join(comp_file, "")
|
||||
|
|
|
@ -34,7 +34,7 @@ from pip._internal.utils.temp_dir import TempDirectoryTypeRegistry as TempDirReg
|
|||
from pip._internal.utils.temp_dir import global_tempdir_manager, tempdir_registry
|
||||
from pip._internal.utils.virtualenv import running_under_virtualenv
|
||||
|
||||
__all__ = ['Command']
|
||||
__all__ = ["Command"]
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -51,7 +51,7 @@ class Command(CommandContextMixIn):
|
|||
self.summary = summary
|
||||
self.parser = ConfigOptionParser(
|
||||
usage=self.usage,
|
||||
prog=f'{get_prog()} {name}',
|
||||
prog=f"{get_prog()} {name}",
|
||||
formatter=UpdatingDefaultsHelpFormatter(),
|
||||
add_help_option=False,
|
||||
name=name,
|
||||
|
@ -62,7 +62,7 @@ class Command(CommandContextMixIn):
|
|||
self.tempdir_registry = None # type: Optional[TempDirRegistry]
|
||||
|
||||
# Commands should add options to this option group
|
||||
optgroup_name = f'{self.name.capitalize()} Options'
|
||||
optgroup_name = f"{self.name.capitalize()} Options"
|
||||
self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name)
|
||||
|
||||
# Add the general options
|
||||
|
@ -86,7 +86,7 @@ class Command(CommandContextMixIn):
|
|||
"""
|
||||
# Make sure we do the pip version check if the index_group options
|
||||
# are present.
|
||||
assert not hasattr(options, 'no_index')
|
||||
assert not hasattr(options, "no_index")
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[Any]) -> int
|
||||
|
@ -131,17 +131,15 @@ class Command(CommandContextMixIn):
|
|||
# This also affects isolated builds and it should.
|
||||
|
||||
if options.no_input:
|
||||
os.environ['PIP_NO_INPUT'] = '1'
|
||||
os.environ["PIP_NO_INPUT"] = "1"
|
||||
|
||||
if options.exists_action:
|
||||
os.environ['PIP_EXISTS_ACTION'] = ' '.join(options.exists_action)
|
||||
os.environ["PIP_EXISTS_ACTION"] = " ".join(options.exists_action)
|
||||
|
||||
if options.require_venv and not self.ignore_require_venv:
|
||||
# If a venv is required check if it can really be found
|
||||
if not running_under_virtualenv():
|
||||
logger.critical(
|
||||
'Could not find an activated virtualenv (required).'
|
||||
)
|
||||
logger.critical("Could not find an activated virtualenv (required).")
|
||||
sys.exit(VIRTUALENV_NOT_FOUND)
|
||||
|
||||
if options.cache_dir:
|
||||
|
@ -171,7 +169,7 @@ class Command(CommandContextMixIn):
|
|||
issue=8333,
|
||||
)
|
||||
|
||||
if '2020-resolver' in options.features_enabled:
|
||||
if "2020-resolver" in options.features_enabled:
|
||||
logger.warning(
|
||||
"--use-feature=2020-resolver no longer has any effect, "
|
||||
"since it is now the default dependency resolver in pip. "
|
||||
|
@ -184,35 +182,39 @@ class Command(CommandContextMixIn):
|
|||
return status
|
||||
except PreviousBuildDirError as exc:
|
||||
logger.critical(str(exc))
|
||||
logger.debug('Exception information:', exc_info=True)
|
||||
logger.debug("Exception information:", exc_info=True)
|
||||
|
||||
return PREVIOUS_BUILD_DIR_ERROR
|
||||
except (InstallationError, UninstallationError, BadCommand,
|
||||
NetworkConnectionError) as exc:
|
||||
except (
|
||||
InstallationError,
|
||||
UninstallationError,
|
||||
BadCommand,
|
||||
NetworkConnectionError,
|
||||
) as exc:
|
||||
logger.critical(str(exc))
|
||||
logger.debug('Exception information:', exc_info=True)
|
||||
logger.debug("Exception information:", exc_info=True)
|
||||
|
||||
return ERROR
|
||||
except CommandError as exc:
|
||||
logger.critical('%s', exc)
|
||||
logger.debug('Exception information:', exc_info=True)
|
||||
logger.critical("%s", exc)
|
||||
logger.debug("Exception information:", exc_info=True)
|
||||
|
||||
return ERROR
|
||||
except BrokenStdoutLoggingError:
|
||||
# Bypass our logger and write any remaining messages to stderr
|
||||
# because stdout no longer works.
|
||||
print('ERROR: Pipe to stdout was broken', file=sys.stderr)
|
||||
print("ERROR: Pipe to stdout was broken", file=sys.stderr)
|
||||
if level_number <= logging.DEBUG:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
|
||||
return ERROR
|
||||
except KeyboardInterrupt:
|
||||
logger.critical('Operation cancelled by user')
|
||||
logger.debug('Exception information:', exc_info=True)
|
||||
logger.critical("Operation cancelled by user")
|
||||
logger.debug("Exception information:", exc_info=True)
|
||||
|
||||
return ERROR
|
||||
except BaseException:
|
||||
logger.critical('Exception:', exc_info=True)
|
||||
logger.critical("Exception:", exc_info=True)
|
||||
|
||||
return UNKNOWN_ERROR
|
||||
finally:
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
|||
from contextlib import ExitStack, contextmanager
|
||||
from typing import ContextManager, Iterator, TypeVar
|
||||
|
||||
_T = TypeVar('_T', covariant=True)
|
||||
_T = TypeVar("_T", covariant=True)
|
||||
|
||||
|
||||
class CommandContextMixIn:
|
||||
|
|
|
@ -41,6 +41,7 @@ logger = logging.getLogger(__name__)
|
|||
# call to main. As it is not safe to do any processing after calling
|
||||
# main, this should not be an issue in practice.
|
||||
|
||||
|
||||
def main(args=None):
|
||||
# type: (Optional[List[str]]) -> int
|
||||
if args is None:
|
||||
|
@ -61,7 +62,7 @@ def main(args=None):
|
|||
# Needed for locale.getpreferredencoding(False) to work
|
||||
# in pip._internal.utils.encoding.auto_decode
|
||||
try:
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
locale.setlocale(locale.LC_ALL, "")
|
||||
except locale.Error as e:
|
||||
# setlocale can apparently crash if locale are uninitialized
|
||||
logger.debug("Ignoring error %s when setting locale", e)
|
||||
|
|
|
@ -16,14 +16,13 @@ __all__ = ["create_main_parser", "parse_command"]
|
|||
|
||||
def create_main_parser():
|
||||
# type: () -> ConfigOptionParser
|
||||
"""Creates and returns the main parser for pip's CLI
|
||||
"""
|
||||
"""Creates and returns the main parser for pip's CLI"""
|
||||
|
||||
parser = ConfigOptionParser(
|
||||
usage='\n%prog <command> [options]',
|
||||
usage="\n%prog <command> [options]",
|
||||
add_help_option=False,
|
||||
formatter=UpdatingDefaultsHelpFormatter(),
|
||||
name='global',
|
||||
name="global",
|
||||
prog=get_prog(),
|
||||
)
|
||||
parser.disable_interspersed_args()
|
||||
|
@ -38,11 +37,11 @@ def create_main_parser():
|
|||
parser.main = True # type: ignore
|
||||
|
||||
# create command listing for description
|
||||
description = [''] + [
|
||||
f'{name:27} {command_info.summary}'
|
||||
description = [""] + [
|
||||
f"{name:27} {command_info.summary}"
|
||||
for name, command_info in commands_dict.items()
|
||||
]
|
||||
parser.description = '\n'.join(description)
|
||||
parser.description = "\n".join(description)
|
||||
|
||||
return parser
|
||||
|
||||
|
@ -67,7 +66,7 @@ def parse_command(args):
|
|||
sys.exit()
|
||||
|
||||
# pip || pip help -> print_help()
|
||||
if not args_else or (args_else[0] == 'help' and len(args_else) == 1):
|
||||
if not args_else or (args_else[0] == "help" and len(args_else) == 1):
|
||||
parser.print_help()
|
||||
sys.exit()
|
||||
|
||||
|
@ -81,7 +80,7 @@ def parse_command(args):
|
|||
if guess:
|
||||
msg.append(f'maybe you meant "{guess}"')
|
||||
|
||||
raise CommandError(' - '.join(msg))
|
||||
raise CommandError(" - ".join(msg))
|
||||
|
||||
# all the args without the subcommand
|
||||
cmd_args = args[:]
|
||||
|
|
|
@ -23,15 +23,15 @@ class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# help position must be aligned with __init__.parseopts.description
|
||||
kwargs['max_help_position'] = 30
|
||||
kwargs['indent_increment'] = 1
|
||||
kwargs['width'] = shutil.get_terminal_size()[0] - 2
|
||||
kwargs["max_help_position"] = 30
|
||||
kwargs["indent_increment"] = 1
|
||||
kwargs["width"] = shutil.get_terminal_size()[0] - 2
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def format_option_strings(self, option):
|
||||
return self._format_option_strings(option)
|
||||
|
||||
def _format_option_strings(self, option, mvarfmt=' <{}>', optsep=', '):
|
||||
def _format_option_strings(self, option, mvarfmt=" <{}>", optsep=", "):
|
||||
"""
|
||||
Return a comma-separated list of option strings and metavars.
|
||||
|
||||
|
@ -52,49 +52,48 @@ class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
|
|||
metavar = option.metavar or option.dest.lower()
|
||||
opts.append(mvarfmt.format(metavar.lower()))
|
||||
|
||||
return ''.join(opts)
|
||||
return "".join(opts)
|
||||
|
||||
def format_heading(self, heading):
|
||||
if heading == 'Options':
|
||||
return ''
|
||||
return heading + ':\n'
|
||||
if heading == "Options":
|
||||
return ""
|
||||
return heading + ":\n"
|
||||
|
||||
def format_usage(self, usage):
|
||||
"""
|
||||
Ensure there is only one newline between usage and the first heading
|
||||
if there is no description.
|
||||
"""
|
||||
msg = '\nUsage: {}\n'.format(
|
||||
self.indent_lines(textwrap.dedent(usage), " "))
|
||||
msg = "\nUsage: {}\n".format(self.indent_lines(textwrap.dedent(usage), " "))
|
||||
return msg
|
||||
|
||||
def format_description(self, description):
|
||||
# leave full control over description to us
|
||||
if description:
|
||||
if hasattr(self.parser, 'main'):
|
||||
label = 'Commands'
|
||||
if hasattr(self.parser, "main"):
|
||||
label = "Commands"
|
||||
else:
|
||||
label = 'Description'
|
||||
label = "Description"
|
||||
# some doc strings have initial newlines, some don't
|
||||
description = description.lstrip('\n')
|
||||
description = description.lstrip("\n")
|
||||
# some doc strings have final newlines and spaces, some don't
|
||||
description = description.rstrip()
|
||||
# dedent, then reindent
|
||||
description = self.indent_lines(textwrap.dedent(description), " ")
|
||||
description = f'{label}:\n{description}\n'
|
||||
description = f"{label}:\n{description}\n"
|
||||
return description
|
||||
else:
|
||||
return ''
|
||||
return ""
|
||||
|
||||
def format_epilog(self, epilog):
|
||||
# leave full control over epilog to us
|
||||
if epilog:
|
||||
return epilog
|
||||
else:
|
||||
return ''
|
||||
return ""
|
||||
|
||||
def indent_lines(self, text, indent):
|
||||
new_lines = [indent + line for line in text.split('\n')]
|
||||
new_lines = [indent + line for line in text.split("\n")]
|
||||
return "\n".join(new_lines)
|
||||
|
||||
|
||||
|
@ -114,7 +113,7 @@ class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter):
|
|||
default_values = self.parser.defaults.get(option.dest)
|
||||
help_text = super().expand_default(option)
|
||||
|
||||
if default_values and option.metavar == 'URL':
|
||||
if default_values and option.metavar == "URL":
|
||||
if isinstance(default_values, str):
|
||||
default_values = [default_values]
|
||||
|
||||
|
@ -123,14 +122,12 @@ class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter):
|
|||
default_values = []
|
||||
|
||||
for val in default_values:
|
||||
help_text = help_text.replace(
|
||||
val, redact_auth_from_url(val))
|
||||
help_text = help_text.replace(val, redact_auth_from_url(val))
|
||||
|
||||
return help_text
|
||||
|
||||
|
||||
class CustomOptionParser(optparse.OptionParser):
|
||||
|
||||
def insert_option_group(self, idx, *args, **kwargs):
|
||||
"""Insert an OptionGroup at a given position."""
|
||||
group = self.add_option_group(*args, **kwargs)
|
||||
|
@ -186,7 +183,7 @@ class ConfigOptionParser(CustomOptionParser):
|
|||
if not val:
|
||||
logger.debug(
|
||||
"Ignoring configuration key '%s' as it's value is empty.",
|
||||
section_key
|
||||
section_key,
|
||||
)
|
||||
continue
|
||||
|
||||
|
@ -210,7 +207,7 @@ class ConfigOptionParser(CustomOptionParser):
|
|||
# Then set the options with those values
|
||||
for key, val in self._get_ordered_configuration_items():
|
||||
# '--' because configuration supports only long names
|
||||
option = self.get_option('--' + key)
|
||||
option = self.get_option("--" + key)
|
||||
|
||||
# Ignore options not present in this parser. E.g. non-globals put
|
||||
# in [global] by users that want them to apply to all applicable
|
||||
|
@ -218,31 +215,31 @@ class ConfigOptionParser(CustomOptionParser):
|
|||
if option is None:
|
||||
continue
|
||||
|
||||
if option.action in ('store_true', 'store_false'):
|
||||
if option.action in ("store_true", "store_false"):
|
||||
try:
|
||||
val = strtobool(val)
|
||||
except ValueError:
|
||||
self.error(
|
||||
'{} is not a valid value for {} option, ' # noqa
|
||||
'please specify a boolean value like yes/no, '
|
||||
'true/false or 1/0 instead.'.format(val, key)
|
||||
"{} is not a valid value for {} option, " # noqa
|
||||
"please specify a boolean value like yes/no, "
|
||||
"true/false or 1/0 instead.".format(val, key)
|
||||
)
|
||||
elif option.action == 'count':
|
||||
elif option.action == "count":
|
||||
with suppress(ValueError):
|
||||
val = strtobool(val)
|
||||
with suppress(ValueError):
|
||||
val = int(val)
|
||||
if not isinstance(val, int) or val < 0:
|
||||
self.error(
|
||||
'{} is not a valid value for {} option, ' # noqa
|
||||
'please instead specify either a non-negative integer '
|
||||
'or a boolean value like yes/no or false/true '
|
||||
'which is equivalent to 1/0.'.format(val, key)
|
||||
"{} is not a valid value for {} option, " # noqa
|
||||
"please instead specify either a non-negative integer "
|
||||
"or a boolean value like yes/no or false/true "
|
||||
"which is equivalent to 1/0.".format(val, key)
|
||||
)
|
||||
elif option.action == 'append':
|
||||
elif option.action == "append":
|
||||
val = val.split()
|
||||
val = [self.check_default(option, key, v) for v in val]
|
||||
elif option.action == 'callback':
|
||||
elif option.action == "callback":
|
||||
late_eval.add(option.dest)
|
||||
opt_str = option.get_opt_string()
|
||||
val = option.convert_value(opt_str, val)
|
||||
|
|
|
@ -108,7 +108,6 @@ class InterruptibleMixin:
|
|||
|
||||
|
||||
class SilentBar(Bar):
|
||||
|
||||
def update(self):
|
||||
# type: () -> None
|
||||
pass
|
||||
|
@ -123,14 +122,11 @@ class BlueEmojiBar(IncrementalBar):
|
|||
|
||||
|
||||
class DownloadProgressMixin:
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# type: (List[Any], Dict[Any, Any]) -> None
|
||||
# https://github.com/python/mypy/issues/5887
|
||||
super().__init__(*args, **kwargs) # type: ignore
|
||||
self.message = (" " * (
|
||||
get_indentation() + 2
|
||||
)) + self.message # type: str
|
||||
self.message = (" " * (get_indentation() + 2)) + self.message # type: str
|
||||
|
||||
@property
|
||||
def downloaded(self):
|
||||
|
@ -162,7 +158,6 @@ class DownloadProgressMixin:
|
|||
|
||||
|
||||
class WindowsMixin:
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# type: (List[Any], Dict[Any, Any]) -> None
|
||||
# The Windows terminal does not support the hide/show cursor ANSI codes
|
||||
|
@ -192,16 +187,14 @@ class WindowsMixin:
|
|||
self.file.flush = lambda: self.file.wrapped.flush()
|
||||
|
||||
|
||||
class BaseDownloadProgressBar(WindowsMixin, InterruptibleMixin,
|
||||
DownloadProgressMixin):
|
||||
class BaseDownloadProgressBar(WindowsMixin, InterruptibleMixin, DownloadProgressMixin):
|
||||
|
||||
file = sys.stdout
|
||||
message = "%(percent)d%%"
|
||||
suffix = "%(downloaded)s %(download_speed)s %(pretty_eta)s"
|
||||
|
||||
|
||||
class DefaultDownloadProgressBar(BaseDownloadProgressBar,
|
||||
_BaseBar):
|
||||
class DefaultDownloadProgressBar(BaseDownloadProgressBar, _BaseBar):
|
||||
pass
|
||||
|
||||
|
||||
|
@ -209,23 +202,21 @@ class DownloadSilentBar(BaseDownloadProgressBar, SilentBar):
|
|||
pass
|
||||
|
||||
|
||||
class DownloadBar(BaseDownloadProgressBar,
|
||||
Bar):
|
||||
class DownloadBar(BaseDownloadProgressBar, Bar):
|
||||
pass
|
||||
|
||||
|
||||
class DownloadFillingCirclesBar(BaseDownloadProgressBar,
|
||||
FillingCirclesBar):
|
||||
class DownloadFillingCirclesBar(BaseDownloadProgressBar, FillingCirclesBar):
|
||||
pass
|
||||
|
||||
|
||||
class DownloadBlueEmojiProgressBar(BaseDownloadProgressBar,
|
||||
BlueEmojiBar):
|
||||
class DownloadBlueEmojiProgressBar(BaseDownloadProgressBar, BlueEmojiBar):
|
||||
pass
|
||||
|
||||
|
||||
class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin,
|
||||
DownloadProgressMixin, Spinner):
|
||||
class DownloadProgressSpinner(
|
||||
WindowsMixin, InterruptibleMixin, DownloadProgressMixin, Spinner
|
||||
):
|
||||
|
||||
file = sys.stdout
|
||||
suffix = "%(downloaded)s %(download_speed)s"
|
||||
|
@ -241,13 +232,15 @@ class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin,
|
|||
message = self.message % self
|
||||
phase = self.next_phase()
|
||||
suffix = self.suffix % self
|
||||
line = ''.join([
|
||||
message,
|
||||
" " if message else "",
|
||||
phase,
|
||||
" " if suffix else "",
|
||||
suffix,
|
||||
])
|
||||
line = "".join(
|
||||
[
|
||||
message,
|
||||
" " if message else "",
|
||||
phase,
|
||||
" " if suffix else "",
|
||||
suffix,
|
||||
]
|
||||
)
|
||||
|
||||
self.writeln(line)
|
||||
|
||||
|
@ -257,7 +250,7 @@ BAR_TYPES = {
|
|||
"on": (DefaultDownloadProgressBar, DownloadProgressSpinner),
|
||||
"ascii": (DownloadBar, DownloadProgressSpinner),
|
||||
"pretty": (DownloadFillingCirclesBar, DownloadProgressSpinner),
|
||||
"emoji": (DownloadBlueEmojiProgressBar, DownloadProgressSpinner)
|
||||
"emoji": (DownloadBlueEmojiProgressBar, DownloadProgressSpinner),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ class SessionCommandMixin(CommandContextMixIn):
|
|||
"""
|
||||
A class mixin for command classes needing _build_session().
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# type: () -> None
|
||||
super().__init__()
|
||||
|
@ -83,8 +84,7 @@ class SessionCommandMixin(CommandContextMixIn):
|
|||
assert not options.cache_dir or os.path.isabs(options.cache_dir)
|
||||
session = PipSession(
|
||||
cache=(
|
||||
os.path.join(options.cache_dir, "http")
|
||||
if options.cache_dir else None
|
||||
os.path.join(options.cache_dir, "http") if options.cache_dir else None
|
||||
),
|
||||
retries=retries if retries is not None else options.retries,
|
||||
trusted_hosts=options.trusted_hosts,
|
||||
|
@ -101,9 +101,7 @@ class SessionCommandMixin(CommandContextMixIn):
|
|||
|
||||
# Handle timeouts
|
||||
if options.timeout or timeout:
|
||||
session.timeout = (
|
||||
timeout if timeout is not None else options.timeout
|
||||
)
|
||||
session.timeout = timeout if timeout is not None else options.timeout
|
||||
|
||||
# Handle configured proxies
|
||||
if options.proxy:
|
||||
|
@ -134,16 +132,14 @@ class IndexGroupCommand(Command, SessionCommandMixin):
|
|||
This overrides the default behavior of not doing the check.
|
||||
"""
|
||||
# Make sure the index_group options are present.
|
||||
assert hasattr(options, 'no_index')
|
||||
assert hasattr(options, "no_index")
|
||||
|
||||
if options.disable_pip_version_check or options.no_index:
|
||||
return
|
||||
|
||||
# Otherwise, check if we're using the latest version of pip available.
|
||||
session = self._build_session(
|
||||
options,
|
||||
retries=0,
|
||||
timeout=min(5, options.timeout)
|
||||
options, retries=0, timeout=min(5, options.timeout)
|
||||
)
|
||||
with session:
|
||||
pip_self_version_check(session, options)
|
||||
|
@ -161,6 +157,7 @@ def with_cleanup(func):
|
|||
"""Decorator for common logic related to managing temporary
|
||||
directories.
|
||||
"""
|
||||
|
||||
def configure_tempdir_registry(registry):
|
||||
# type: (TempDirectoryTypeRegistry) -> None
|
||||
for t in KEEPABLE_TEMPDIR_TYPES:
|
||||
|
@ -185,7 +182,6 @@ def with_cleanup(func):
|
|||
|
||||
|
||||
class RequirementCommand(IndexGroupCommand):
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
# type: (Any, Any) -> None
|
||||
super().__init__(*args, **kw)
|
||||
|
@ -204,13 +200,13 @@ class RequirementCommand(IndexGroupCommand):
|
|||
@classmethod
|
||||
def make_requirement_preparer(
|
||||
cls,
|
||||
temp_build_dir, # type: TempDirectory
|
||||
options, # type: Values
|
||||
req_tracker, # type: RequirementTracker
|
||||
session, # type: PipSession
|
||||
finder, # type: PackageFinder
|
||||
use_user_site, # type: bool
|
||||
download_dir=None, # type: str
|
||||
temp_build_dir, # type: TempDirectory
|
||||
options, # type: Values
|
||||
req_tracker, # type: RequirementTracker
|
||||
session, # type: PipSession
|
||||
finder, # type: PackageFinder
|
||||
use_user_site, # type: bool
|
||||
download_dir=None, # type: str
|
||||
):
|
||||
# type: (...) -> RequirementPreparer
|
||||
"""
|
||||
|
@ -221,20 +217,20 @@ class RequirementCommand(IndexGroupCommand):
|
|||
|
||||
resolver_variant = cls.determine_resolver_variant(options)
|
||||
if resolver_variant == "2020-resolver":
|
||||
lazy_wheel = 'fast-deps' in options.features_enabled
|
||||
lazy_wheel = "fast-deps" in options.features_enabled
|
||||
if lazy_wheel:
|
||||
logger.warning(
|
||||
'pip is using lazily downloaded wheels using HTTP '
|
||||
'range requests to obtain dependency information. '
|
||||
'This experimental feature is enabled through '
|
||||
'--use-feature=fast-deps and it is not ready for '
|
||||
'production.'
|
||||
"pip is using lazily downloaded wheels using HTTP "
|
||||
"range requests to obtain dependency information. "
|
||||
"This experimental feature is enabled through "
|
||||
"--use-feature=fast-deps and it is not ready for "
|
||||
"production."
|
||||
)
|
||||
else:
|
||||
lazy_wheel = False
|
||||
if 'fast-deps' in options.features_enabled:
|
||||
if "fast-deps" in options.features_enabled:
|
||||
logger.warning(
|
||||
'fast-deps has no effect when used with the legacy resolver.'
|
||||
"fast-deps has no effect when used with the legacy resolver."
|
||||
)
|
||||
|
||||
return RequirementPreparer(
|
||||
|
@ -254,17 +250,17 @@ class RequirementCommand(IndexGroupCommand):
|
|||
@classmethod
|
||||
def make_resolver(
|
||||
cls,
|
||||
preparer, # type: RequirementPreparer
|
||||
finder, # type: PackageFinder
|
||||
options, # type: Values
|
||||
wheel_cache=None, # type: Optional[WheelCache]
|
||||
use_user_site=False, # type: bool
|
||||
ignore_installed=True, # type: bool
|
||||
ignore_requires_python=False, # type: bool
|
||||
force_reinstall=False, # type: bool
|
||||
preparer, # type: RequirementPreparer
|
||||
finder, # type: PackageFinder
|
||||
options, # type: Values
|
||||
wheel_cache=None, # type: Optional[WheelCache]
|
||||
use_user_site=False, # type: bool
|
||||
ignore_installed=True, # type: bool
|
||||
ignore_requires_python=False, # type: bool
|
||||
force_reinstall=False, # type: bool
|
||||
upgrade_strategy="to-satisfy-only", # type: str
|
||||
use_pep517=None, # type: Optional[bool]
|
||||
py_version_info=None, # type: Optional[Tuple[int, ...]]
|
||||
use_pep517=None, # type: Optional[bool]
|
||||
py_version_info=None, # type: Optional[Tuple[int, ...]]
|
||||
):
|
||||
# type: (...) -> BaseResolver
|
||||
"""
|
||||
|
@ -296,6 +292,7 @@ class RequirementCommand(IndexGroupCommand):
|
|||
py_version_info=py_version_info,
|
||||
)
|
||||
import pip._internal.resolution.legacy.resolver
|
||||
|
||||
return pip._internal.resolution.legacy.resolver.Resolver(
|
||||
preparer=preparer,
|
||||
finder=finder,
|
||||
|
@ -312,10 +309,10 @@ class RequirementCommand(IndexGroupCommand):
|
|||
|
||||
def get_requirements(
|
||||
self,
|
||||
args, # type: List[str]
|
||||
options, # type: Values
|
||||
finder, # type: PackageFinder
|
||||
session, # type: PipSession
|
||||
args, # type: List[str]
|
||||
options, # type: Values
|
||||
finder, # type: PackageFinder
|
||||
session, # type: PipSession
|
||||
):
|
||||
# type: (...) -> List[InstallRequirement]
|
||||
"""
|
||||
|
@ -324,9 +321,12 @@ class RequirementCommand(IndexGroupCommand):
|
|||
requirements = [] # type: List[InstallRequirement]
|
||||
for filename in options.constraints:
|
||||
for parsed_req in parse_requirements(
|
||||
filename,
|
||||
constraint=True, finder=finder, options=options,
|
||||
session=session):
|
||||
filename,
|
||||
constraint=True,
|
||||
finder=finder,
|
||||
options=options,
|
||||
session=session,
|
||||
):
|
||||
req_to_add = install_req_from_parsed_requirement(
|
||||
parsed_req,
|
||||
isolated=options.isolated_mode,
|
||||
|
@ -336,7 +336,9 @@ class RequirementCommand(IndexGroupCommand):
|
|||
|
||||
for req in args:
|
||||
req_to_add = install_req_from_line(
|
||||
req, None, isolated=options.isolated_mode,
|
||||
req,
|
||||
None,
|
||||
isolated=options.isolated_mode,
|
||||
use_pep517=options.use_pep517,
|
||||
user_supplied=True,
|
||||
)
|
||||
|
@ -354,8 +356,8 @@ class RequirementCommand(IndexGroupCommand):
|
|||
# NOTE: options.require_hashes may be set if --require-hashes is True
|
||||
for filename in options.requirements:
|
||||
for parsed_req in parse_requirements(
|
||||
filename,
|
||||
finder=finder, options=options, session=session):
|
||||
filename, finder=finder, options=options, session=session
|
||||
):
|
||||
req_to_add = install_req_from_parsed_requirement(
|
||||
parsed_req,
|
||||
isolated=options.isolated_mode,
|
||||
|
@ -369,16 +371,19 @@ class RequirementCommand(IndexGroupCommand):
|
|||
options.require_hashes = True
|
||||
|
||||
if not (args or options.editables or options.requirements):
|
||||
opts = {'name': self.name}
|
||||
opts = {"name": self.name}
|
||||
if options.find_links:
|
||||
raise CommandError(
|
||||
'You must give at least one requirement to {name} '
|
||||
"You must give at least one requirement to {name} "
|
||||
'(maybe you meant "pip {name} {links}"?)'.format(
|
||||
**dict(opts, links=' '.join(options.find_links))))
|
||||
**dict(opts, links=" ".join(options.find_links))
|
||||
)
|
||||
)
|
||||
else:
|
||||
raise CommandError(
|
||||
'You must give at least one requirement to {name} '
|
||||
'(see "pip help {name}")'.format(**opts))
|
||||
"You must give at least one requirement to {name} "
|
||||
'(see "pip help {name}")'.format(**opts)
|
||||
)
|
||||
|
||||
return requirements
|
||||
|
||||
|
@ -396,9 +401,9 @@ class RequirementCommand(IndexGroupCommand):
|
|||
|
||||
def _build_package_finder(
|
||||
self,
|
||||
options, # type: Values
|
||||
session, # type: PipSession
|
||||
target_python=None, # type: Optional[TargetPython]
|
||||
options, # type: Values
|
||||
session, # type: PipSession
|
||||
target_python=None, # type: Optional[TargetPython]
|
||||
ignore_requires_python=None, # type: Optional[bool]
|
||||
):
|
||||
# type: (...) -> PackageFinder
|
||||
|
|
|
@ -24,9 +24,14 @@ class SpinnerInterface:
|
|||
|
||||
|
||||
class InteractiveSpinner(SpinnerInterface):
|
||||
def __init__(self, message, file=None, spin_chars="-\\|/",
|
||||
# Empirically, 8 updates/second looks nice
|
||||
min_update_interval_seconds=0.125):
|
||||
def __init__(
|
||||
self,
|
||||
message,
|
||||
file=None,
|
||||
spin_chars="-\\|/",
|
||||
# Empirically, 8 updates/second looks nice
|
||||
min_update_interval_seconds=0.125,
|
||||
):
|
||||
# type: (str, IO[str], str, float) -> None
|
||||
self._message = message
|
||||
if file is None:
|
||||
|
|
Loading…
Reference in a new issue