Created starter files for the project.
This commit is contained in:
commit
73f0c0db42
1992 changed files with 769897 additions and 0 deletions
122
venv/Lib/site-packages/pip/_internal/commands/__init__.py
Normal file
122
venv/Lib/site-packages/pip/_internal/commands/__init__.py
Normal file
|
@ -0,0 +1,122 @@
|
|||
"""
|
||||
Package containing all pip commands
|
||||
"""
|
||||
|
||||
# The following comment should be removed at some point in the future.
|
||||
# mypy: disallow-untyped-defs=False
|
||||
# There is currently a bug in python/typeshed mentioned at
|
||||
# https://github.com/python/typeshed/issues/3906 which causes the
|
||||
# return type of difflib.get_close_matches to be reported
|
||||
# as List[Sequence[str]] whereas it should have been List[str]
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import importlib
|
||||
from collections import OrderedDict, namedtuple
|
||||
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from typing import Any
|
||||
from pip._internal.cli.base_command import Command
|
||||
|
||||
|
||||
CommandInfo = namedtuple('CommandInfo', 'module_path, class_name, summary')
|
||||
|
||||
# The ordering matters for help display.
|
||||
# Also, even though the module path starts with the same
|
||||
# "pip._internal.commands" prefix in each case, we include the full path
|
||||
# because it makes testing easier (specifically when modifying commands_dict
|
||||
# in test setup / teardown by adding info for a FakeCommand class defined
|
||||
# in a test-related module).
|
||||
# Finally, we need to pass an iterable of pairs here rather than a dict
|
||||
# so that the ordering won't be lost when using Python 2.7.
|
||||
commands_dict = OrderedDict([
|
||||
('install', CommandInfo(
|
||||
'pip._internal.commands.install', 'InstallCommand',
|
||||
'Install packages.',
|
||||
)),
|
||||
('download', CommandInfo(
|
||||
'pip._internal.commands.download', 'DownloadCommand',
|
||||
'Download packages.',
|
||||
)),
|
||||
('uninstall', CommandInfo(
|
||||
'pip._internal.commands.uninstall', 'UninstallCommand',
|
||||
'Uninstall packages.',
|
||||
)),
|
||||
('freeze', CommandInfo(
|
||||
'pip._internal.commands.freeze', 'FreezeCommand',
|
||||
'Output installed packages in requirements format.',
|
||||
)),
|
||||
('list', CommandInfo(
|
||||
'pip._internal.commands.list', 'ListCommand',
|
||||
'List installed packages.',
|
||||
)),
|
||||
('show', CommandInfo(
|
||||
'pip._internal.commands.show', 'ShowCommand',
|
||||
'Show information about installed packages.',
|
||||
)),
|
||||
('check', CommandInfo(
|
||||
'pip._internal.commands.check', 'CheckCommand',
|
||||
'Verify installed packages have compatible dependencies.',
|
||||
)),
|
||||
('config', CommandInfo(
|
||||
'pip._internal.commands.configuration', 'ConfigurationCommand',
|
||||
'Manage local and global configuration.',
|
||||
)),
|
||||
('search', CommandInfo(
|
||||
'pip._internal.commands.search', 'SearchCommand',
|
||||
'Search PyPI for packages.',
|
||||
)),
|
||||
('cache', CommandInfo(
|
||||
'pip._internal.commands.cache', 'CacheCommand',
|
||||
"Inspect and manage pip's wheel cache.",
|
||||
)),
|
||||
('wheel', CommandInfo(
|
||||
'pip._internal.commands.wheel', 'WheelCommand',
|
||||
'Build wheels from your requirements.',
|
||||
)),
|
||||
('hash', CommandInfo(
|
||||
'pip._internal.commands.hash', 'HashCommand',
|
||||
'Compute hashes of package archives.',
|
||||
)),
|
||||
('completion', CommandInfo(
|
||||
'pip._internal.commands.completion', 'CompletionCommand',
|
||||
'A helper command used for command completion.',
|
||||
)),
|
||||
('debug', CommandInfo(
|
||||
'pip._internal.commands.debug', 'DebugCommand',
|
||||
'Show information useful for debugging.',
|
||||
)),
|
||||
('help', CommandInfo(
|
||||
'pip._internal.commands.help', 'HelpCommand',
|
||||
'Show help for commands.',
|
||||
)),
|
||||
]) # type: OrderedDict[str, CommandInfo]
|
||||
|
||||
|
||||
def create_command(name, **kwargs):
|
||||
# type: (str, **Any) -> Command
|
||||
"""
|
||||
Create an instance of the Command class with the given name.
|
||||
"""
|
||||
module_path, class_name, summary = commands_dict[name]
|
||||
module = importlib.import_module(module_path)
|
||||
command_class = getattr(module, class_name)
|
||||
command = command_class(name=name, summary=summary, **kwargs)
|
||||
|
||||
return command
|
||||
|
||||
|
||||
def get_similar_commands(name):
|
||||
"""Command name auto-correct."""
|
||||
from difflib import get_close_matches
|
||||
|
||||
name = name.lower()
|
||||
|
||||
close_commands = get_close_matches(name, commands_dict.keys())
|
||||
|
||||
if close_commands:
|
||||
return close_commands[0]
|
||||
else:
|
||||
return False
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
182
venv/Lib/site-packages/pip/_internal/commands/cache.py
Normal file
182
venv/Lib/site-packages/pip/_internal/commands/cache.py
Normal file
|
@ -0,0 +1,182 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import os
|
||||
import textwrap
|
||||
|
||||
import pip._internal.utils.filesystem as filesystem
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.status_codes import ERROR, SUCCESS
|
||||
from pip._internal.exceptions import CommandError, PipError
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from optparse import Values
|
||||
from typing import Any, List
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CacheCommand(Command):
|
||||
"""
|
||||
Inspect and manage pip's wheel cache.
|
||||
|
||||
Subcommands:
|
||||
|
||||
- dir: Show the cache directory.
|
||||
- info: Show information about the cache.
|
||||
- list: List filenames of packages stored in the cache.
|
||||
- remove: Remove one or more package from the cache.
|
||||
- purge: Remove all items from the cache.
|
||||
|
||||
``<pattern>`` can be a glob expression or a package name.
|
||||
"""
|
||||
|
||||
ignore_require_venv = True
|
||||
usage = """
|
||||
%prog dir
|
||||
%prog info
|
||||
%prog list [<pattern>]
|
||||
%prog remove <pattern>
|
||||
%prog purge
|
||||
"""
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[Any]) -> int
|
||||
handlers = {
|
||||
"dir": self.get_cache_dir,
|
||||
"info": self.get_cache_info,
|
||||
"list": self.list_cache_items,
|
||||
"remove": self.remove_cache_items,
|
||||
"purge": self.purge_cache,
|
||||
}
|
||||
|
||||
if not options.cache_dir:
|
||||
logger.error("pip cache commands can not "
|
||||
"function since cache is disabled.")
|
||||
return ERROR
|
||||
|
||||
# Determine action
|
||||
if not args or args[0] not in handlers:
|
||||
logger.error(
|
||||
"Need an action (%s) to perform.",
|
||||
", ".join(sorted(handlers)),
|
||||
)
|
||||
return ERROR
|
||||
|
||||
action = args[0]
|
||||
|
||||
# Error handling happens here, not in the action-handlers.
|
||||
try:
|
||||
handlers[action](options, args[1:])
|
||||
except PipError as e:
|
||||
logger.error(e.args[0])
|
||||
return ERROR
|
||||
|
||||
return SUCCESS
|
||||
|
||||
def get_cache_dir(self, options, args):
|
||||
# type: (Values, List[Any]) -> None
|
||||
if args:
|
||||
raise CommandError('Too many arguments')
|
||||
|
||||
logger.info(options.cache_dir)
|
||||
|
||||
def get_cache_info(self, options, args):
|
||||
# type: (Values, List[Any]) -> None
|
||||
if args:
|
||||
raise CommandError('Too many arguments')
|
||||
|
||||
num_packages = len(self._find_wheels(options, '*'))
|
||||
|
||||
cache_location = self._wheels_cache_dir(options)
|
||||
cache_size = filesystem.format_directory_size(cache_location)
|
||||
|
||||
message = textwrap.dedent("""
|
||||
Location: {location}
|
||||
Size: {size}
|
||||
Number of wheels: {package_count}
|
||||
""").format(
|
||||
location=cache_location,
|
||||
package_count=num_packages,
|
||||
size=cache_size,
|
||||
).strip()
|
||||
|
||||
logger.info(message)
|
||||
|
||||
def list_cache_items(self, options, args):
|
||||
# type: (Values, List[Any]) -> None
|
||||
if len(args) > 1:
|
||||
raise CommandError('Too many arguments')
|
||||
|
||||
if args:
|
||||
pattern = args[0]
|
||||
else:
|
||||
pattern = '*'
|
||||
|
||||
files = self._find_wheels(options, pattern)
|
||||
|
||||
if not files:
|
||||
logger.info('Nothing cached.')
|
||||
return
|
||||
|
||||
results = []
|
||||
for filename in files:
|
||||
wheel = os.path.basename(filename)
|
||||
size = filesystem.format_file_size(filename)
|
||||
results.append(' - {} ({})'.format(wheel, size))
|
||||
logger.info('Cache contents:\n')
|
||||
logger.info('\n'.join(sorted(results)))
|
||||
|
||||
def remove_cache_items(self, options, args):
|
||||
# type: (Values, List[Any]) -> None
|
||||
if len(args) > 1:
|
||||
raise CommandError('Too many arguments')
|
||||
|
||||
if not args:
|
||||
raise CommandError('Please provide a pattern')
|
||||
|
||||
files = self._find_wheels(options, args[0])
|
||||
if not files:
|
||||
raise CommandError('No matching packages')
|
||||
|
||||
for filename in files:
|
||||
os.unlink(filename)
|
||||
logger.debug('Removed %s', filename)
|
||||
logger.info('Files removed: %s', len(files))
|
||||
|
||||
def purge_cache(self, options, args):
|
||||
# type: (Values, List[Any]) -> None
|
||||
if args:
|
||||
raise CommandError('Too many arguments')
|
||||
|
||||
return self.remove_cache_items(options, ['*'])
|
||||
|
||||
def _wheels_cache_dir(self, options):
|
||||
# type: (Values) -> str
|
||||
return os.path.join(options.cache_dir, 'wheels')
|
||||
|
||||
def _find_wheels(self, options, pattern):
|
||||
# type: (Values, str) -> List[str]
|
||||
wheel_dir = self._wheels_cache_dir(options)
|
||||
|
||||
# The wheel filename format, as specified in PEP 427, is:
|
||||
# {distribution}-{version}(-{build})?-{python}-{abi}-{platform}.whl
|
||||
#
|
||||
# Additionally, non-alphanumeric values in the distribution are
|
||||
# normalized to underscores (_), meaning hyphens can never occur
|
||||
# before `-{version}`.
|
||||
#
|
||||
# Given that information:
|
||||
# - If the pattern we're given contains a hyphen (-), the user is
|
||||
# providing at least the version. Thus, we can just append `*.whl`
|
||||
# to match the rest of it.
|
||||
# - If the pattern we're given doesn't contain a hyphen (-), the
|
||||
# user is only providing the name. Thus, we append `-*.whl` to
|
||||
# match the hyphen before the version, followed by anything else.
|
||||
#
|
||||
# PEP 427: https://www.python.org/dev/peps/pep-0427/
|
||||
pattern = pattern + ("*.whl" if "-" in pattern else "-*.whl")
|
||||
|
||||
return filesystem.find_files(wheel_dir, pattern)
|
51
venv/Lib/site-packages/pip/_internal/commands/check.py
Normal file
51
venv/Lib/site-packages/pip/_internal/commands/check.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
import logging
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.status_codes import ERROR, SUCCESS
|
||||
from pip._internal.operations.check import (
|
||||
check_package_set,
|
||||
create_package_set_from_installed,
|
||||
)
|
||||
from pip._internal.utils.misc import write_output
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from typing import List, Any
|
||||
from optparse import Values
|
||||
|
||||
|
||||
class CheckCommand(Command):
|
||||
"""Verify installed packages have compatible dependencies."""
|
||||
|
||||
usage = """
|
||||
%prog [options]"""
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[Any]) -> int
|
||||
|
||||
package_set, parsing_probs = create_package_set_from_installed()
|
||||
missing, conflicting = check_package_set(package_set)
|
||||
|
||||
for project_name in missing:
|
||||
version = package_set[project_name].version
|
||||
for dependency in missing[project_name]:
|
||||
write_output(
|
||||
"%s %s requires %s, which is not installed.",
|
||||
project_name, version, dependency[0],
|
||||
)
|
||||
|
||||
for project_name in conflicting:
|
||||
version = package_set[project_name].version
|
||||
for dep_name, dep_version, req in conflicting[project_name]:
|
||||
write_output(
|
||||
"%s %s has requirement %s, but you have %s %s.",
|
||||
project_name, version, req, dep_name, dep_version,
|
||||
)
|
||||
|
||||
if missing or conflicting or parsing_probs:
|
||||
return ERROR
|
||||
else:
|
||||
write_output("No broken requirements found.")
|
||||
return SUCCESS
|
98
venv/Lib/site-packages/pip/_internal/commands/completion.py
Normal file
98
venv/Lib/site-packages/pip/_internal/commands/completion.py
Normal file
|
@ -0,0 +1,98 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.utils.misc import get_prog
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from typing import List
|
||||
from optparse import Values
|
||||
|
||||
BASE_COMPLETION = """
|
||||
# pip {shell} completion start{script}# pip {shell} completion end
|
||||
"""
|
||||
|
||||
COMPLETION_SCRIPTS = {
|
||||
'bash': """
|
||||
_pip_completion()
|
||||
{{
|
||||
COMPREPLY=( $( COMP_WORDS="${{COMP_WORDS[*]}}" \\
|
||||
COMP_CWORD=$COMP_CWORD \\
|
||||
PIP_AUTO_COMPLETE=1 $1 2>/dev/null ) )
|
||||
}}
|
||||
complete -o default -F _pip_completion {prog}
|
||||
""",
|
||||
'zsh': """
|
||||
function _pip_completion {{
|
||||
local words cword
|
||||
read -Ac words
|
||||
read -cn cword
|
||||
reply=( $( COMP_WORDS="$words[*]" \\
|
||||
COMP_CWORD=$(( cword-1 )) \\
|
||||
PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null ))
|
||||
}}
|
||||
compctl -K _pip_completion {prog}
|
||||
""",
|
||||
'fish': """
|
||||
function __fish_complete_pip
|
||||
set -lx COMP_WORDS (commandline -o) ""
|
||||
set -lx COMP_CWORD ( \\
|
||||
math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\
|
||||
)
|
||||
set -lx PIP_AUTO_COMPLETE 1
|
||||
string split \\ -- (eval $COMP_WORDS[1])
|
||||
end
|
||||
complete -fa "(__fish_complete_pip)" -c {prog}
|
||||
""",
|
||||
}
|
||||
|
||||
|
||||
class CompletionCommand(Command):
|
||||
"""A helper command to be used for command completion."""
|
||||
|
||||
ignore_require_venv = True
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
self.cmd_opts.add_option(
|
||||
'--bash', '-b',
|
||||
action='store_const',
|
||||
const='bash',
|
||||
dest='shell',
|
||||
help='Emit completion code for bash')
|
||||
self.cmd_opts.add_option(
|
||||
'--zsh', '-z',
|
||||
action='store_const',
|
||||
const='zsh',
|
||||
dest='shell',
|
||||
help='Emit completion code for zsh')
|
||||
self.cmd_opts.add_option(
|
||||
'--fish', '-f',
|
||||
action='store_const',
|
||||
const='fish',
|
||||
dest='shell',
|
||||
help='Emit completion code for fish')
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
"""Prints the completion code of the given shell"""
|
||||
shells = COMPLETION_SCRIPTS.keys()
|
||||
shell_options = ['--' + shell for shell in sorted(shells)]
|
||||
if options.shell in shells:
|
||||
script = textwrap.dedent(
|
||||
COMPLETION_SCRIPTS.get(options.shell, '').format(
|
||||
prog=get_prog())
|
||||
)
|
||||
print(BASE_COMPLETION.format(script=script, shell=options.shell))
|
||||
return SUCCESS
|
||||
else:
|
||||
sys.stderr.write(
|
||||
'ERROR: You must pass {}\n' .format(' or '.join(shell_options))
|
||||
)
|
||||
return SUCCESS
|
284
venv/Lib/site-packages/pip/_internal/commands/configuration.py
Normal file
284
venv/Lib/site-packages/pip/_internal/commands/configuration.py
Normal file
|
@ -0,0 +1,284 @@
|
|||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.status_codes import ERROR, SUCCESS
|
||||
from pip._internal.configuration import (
|
||||
Configuration,
|
||||
get_configuration_files,
|
||||
kinds,
|
||||
)
|
||||
from pip._internal.exceptions import PipError
|
||||
from pip._internal.utils.logging import indent_log
|
||||
from pip._internal.utils.misc import get_prog, write_output
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from typing import List, Any, Optional
|
||||
from optparse import Values
|
||||
|
||||
from pip._internal.configuration import Kind
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ConfigurationCommand(Command):
|
||||
"""
|
||||
Manage local and global configuration.
|
||||
|
||||
Subcommands:
|
||||
|
||||
- list: List the active configuration (or from the file specified)
|
||||
- edit: Edit the configuration file in an editor
|
||||
- get: Get the value associated with name
|
||||
- set: Set the name=value
|
||||
- unset: Unset the value associated with name
|
||||
- debug: List the configuration files and values defined under them
|
||||
|
||||
If none of --user, --global and --site are passed, a virtual
|
||||
environment configuration file is used if one is active and the file
|
||||
exists. Otherwise, all modifications happen on the to the user file by
|
||||
default.
|
||||
"""
|
||||
|
||||
ignore_require_venv = True
|
||||
usage = """
|
||||
%prog [<file-option>] list
|
||||
%prog [<file-option>] [--editor <editor-path>] edit
|
||||
|
||||
%prog [<file-option>] get name
|
||||
%prog [<file-option>] set name value
|
||||
%prog [<file-option>] unset name
|
||||
%prog [<file-option>] debug
|
||||
"""
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
self.cmd_opts.add_option(
|
||||
'--editor',
|
||||
dest='editor',
|
||||
action='store',
|
||||
default=None,
|
||||
help=(
|
||||
'Editor to use to edit the file. Uses VISUAL or EDITOR '
|
||||
'environment variables if not provided.'
|
||||
)
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'--global',
|
||||
dest='global_file',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Use the system-wide configuration file only'
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'--user',
|
||||
dest='user_file',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Use the user configuration file only'
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'--site',
|
||||
dest='site_file',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Use the current environment configuration file only'
|
||||
)
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
handlers = {
|
||||
"list": self.list_values,
|
||||
"edit": self.open_in_editor,
|
||||
"get": self.get_name,
|
||||
"set": self.set_name_value,
|
||||
"unset": self.unset_name,
|
||||
"debug": self.list_config_values,
|
||||
}
|
||||
|
||||
# Determine action
|
||||
if not args or args[0] not in handlers:
|
||||
logger.error(
|
||||
"Need an action (%s) to perform.",
|
||||
", ".join(sorted(handlers)),
|
||||
)
|
||||
return ERROR
|
||||
|
||||
action = args[0]
|
||||
|
||||
# Determine which configuration files are to be loaded
|
||||
# Depends on whether the command is modifying.
|
||||
try:
|
||||
load_only = self._determine_file(
|
||||
options, need_value=(action in ["get", "set", "unset", "edit"])
|
||||
)
|
||||
except PipError as e:
|
||||
logger.error(e.args[0])
|
||||
return ERROR
|
||||
|
||||
# Load a new configuration
|
||||
self.configuration = Configuration(
|
||||
isolated=options.isolated_mode, load_only=load_only
|
||||
)
|
||||
self.configuration.load()
|
||||
|
||||
# Error handling happens here, not in the action-handlers.
|
||||
try:
|
||||
handlers[action](options, args[1:])
|
||||
except PipError as e:
|
||||
logger.error(e.args[0])
|
||||
return ERROR
|
||||
|
||||
return SUCCESS
|
||||
|
||||
def _determine_file(self, options, need_value):
|
||||
# type: (Values, bool) -> Optional[Kind]
|
||||
file_options = [key for key, value in (
|
||||
(kinds.USER, options.user_file),
|
||||
(kinds.GLOBAL, options.global_file),
|
||||
(kinds.SITE, options.site_file),
|
||||
) if value]
|
||||
|
||||
if not file_options:
|
||||
if not need_value:
|
||||
return None
|
||||
# Default to user, unless there's a site file.
|
||||
elif any(
|
||||
os.path.exists(site_config_file)
|
||||
for site_config_file in get_configuration_files()[kinds.SITE]
|
||||
):
|
||||
return kinds.SITE
|
||||
else:
|
||||
return kinds.USER
|
||||
elif len(file_options) == 1:
|
||||
return file_options[0]
|
||||
|
||||
raise PipError(
|
||||
"Need exactly one file to operate upon "
|
||||
"(--user, --site, --global) to perform."
|
||||
)
|
||||
|
||||
def list_values(self, options, args):
|
||||
# type: (Values, List[str]) -> None
|
||||
self._get_n_args(args, "list", n=0)
|
||||
|
||||
for key, value in sorted(self.configuration.items()):
|
||||
write_output("%s=%r", key, value)
|
||||
|
||||
def get_name(self, options, args):
|
||||
# type: (Values, List[str]) -> None
|
||||
key = self._get_n_args(args, "get [name]", n=1)
|
||||
value = self.configuration.get_value(key)
|
||||
|
||||
write_output("%s", value)
|
||||
|
||||
def set_name_value(self, options, args):
|
||||
# type: (Values, List[str]) -> None
|
||||
key, value = self._get_n_args(args, "set [name] [value]", n=2)
|
||||
self.configuration.set_value(key, value)
|
||||
|
||||
self._save_configuration()
|
||||
|
||||
def unset_name(self, options, args):
|
||||
# type: (Values, List[str]) -> None
|
||||
key = self._get_n_args(args, "unset [name]", n=1)
|
||||
self.configuration.unset_value(key)
|
||||
|
||||
self._save_configuration()
|
||||
|
||||
def list_config_values(self, options, args):
|
||||
# type: (Values, List[str]) -> None
|
||||
"""List config key-value pairs across different config files"""
|
||||
self._get_n_args(args, "debug", n=0)
|
||||
|
||||
self.print_env_var_values()
|
||||
# Iterate over config files and print if they exist, and the
|
||||
# key-value pairs present in them if they do
|
||||
for variant, files in sorted(self.configuration.iter_config_files()):
|
||||
write_output("%s:", variant)
|
||||
for fname in files:
|
||||
with indent_log():
|
||||
file_exists = os.path.exists(fname)
|
||||
write_output("%s, exists: %r",
|
||||
fname, file_exists)
|
||||
if file_exists:
|
||||
self.print_config_file_values(variant)
|
||||
|
||||
def print_config_file_values(self, variant):
|
||||
# type: (Kind) -> None
|
||||
"""Get key-value pairs from the file of a variant"""
|
||||
for name, value in self.configuration.\
|
||||
get_values_in_config(variant).items():
|
||||
with indent_log():
|
||||
write_output("%s: %s", name, value)
|
||||
|
||||
def print_env_var_values(self):
|
||||
# type: () -> None
|
||||
"""Get key-values pairs present as environment variables"""
|
||||
write_output("%s:", 'env_var')
|
||||
with indent_log():
|
||||
for key, value in sorted(self.configuration.get_environ_vars()):
|
||||
env_var = 'PIP_{}'.format(key.upper())
|
||||
write_output("%s=%r", env_var, value)
|
||||
|
||||
def open_in_editor(self, options, args):
|
||||
# type: (Values, List[str]) -> None
|
||||
editor = self._determine_editor(options)
|
||||
|
||||
fname = self.configuration.get_file_to_edit()
|
||||
if fname is None:
|
||||
raise PipError("Could not determine appropriate file.")
|
||||
|
||||
try:
|
||||
subprocess.check_call([editor, fname])
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise PipError(
|
||||
"Editor Subprocess exited with exit code {}"
|
||||
.format(e.returncode)
|
||||
)
|
||||
|
||||
def _get_n_args(self, args, example, n):
|
||||
# type: (List[str], str, int) -> Any
|
||||
"""Helper to make sure the command got the right number of arguments
|
||||
"""
|
||||
if len(args) != n:
|
||||
msg = (
|
||||
'Got unexpected number of arguments, expected {}. '
|
||||
'(example: "{} config {}")'
|
||||
).format(n, get_prog(), example)
|
||||
raise PipError(msg)
|
||||
|
||||
if n == 1:
|
||||
return args[0]
|
||||
else:
|
||||
return args
|
||||
|
||||
def _save_configuration(self):
|
||||
# type: () -> None
|
||||
# We successfully ran a modifying command. Need to save the
|
||||
# configuration.
|
||||
try:
|
||||
self.configuration.save()
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"Unable to save configuration. Please report this as a bug."
|
||||
)
|
||||
raise PipError("Internal Error.")
|
||||
|
||||
def _determine_editor(self, options):
|
||||
# type: (Values) -> str
|
||||
if options.editor is not None:
|
||||
return options.editor
|
||||
elif "VISUAL" in os.environ:
|
||||
return os.environ["VISUAL"]
|
||||
elif "EDITOR" in os.environ:
|
||||
return os.environ["EDITOR"]
|
||||
else:
|
||||
raise PipError("Could not determine editor to use.")
|
229
venv/Lib/site-packages/pip/_internal/commands/debug.py
Normal file
229
venv/Lib/site-packages/pip/_internal/commands/debug.py
Normal file
|
@ -0,0 +1,229 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import locale
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pip._vendor
|
||||
from pip._vendor import pkg_resources
|
||||
from pip._vendor.certifi import where
|
||||
|
||||
from pip import __file__ as pip_location
|
||||
from pip._internal.cli import cmdoptions
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.cmdoptions import make_target_python
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.utils.logging import indent_log
|
||||
from pip._internal.utils.misc import get_pip_version
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from types import ModuleType
|
||||
from typing import List, Optional, Dict
|
||||
from optparse import Values
|
||||
from pip._internal.configuration import Configuration
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def show_value(name, value):
|
||||
# type: (str, Optional[str]) -> None
|
||||
logger.info('%s: %s', name, value)
|
||||
|
||||
|
||||
def show_sys_implementation():
|
||||
# type: () -> None
|
||||
logger.info('sys.implementation:')
|
||||
if hasattr(sys, 'implementation'):
|
||||
implementation = sys.implementation # type: ignore
|
||||
implementation_name = implementation.name
|
||||
else:
|
||||
implementation_name = ''
|
||||
|
||||
with indent_log():
|
||||
show_value('name', implementation_name)
|
||||
|
||||
|
||||
def create_vendor_txt_map():
|
||||
# type: () -> Dict[str, str]
|
||||
vendor_txt_path = os.path.join(
|
||||
os.path.dirname(pip_location),
|
||||
'_vendor',
|
||||
'vendor.txt'
|
||||
)
|
||||
|
||||
with open(vendor_txt_path) as f:
|
||||
# Purge non version specifying lines.
|
||||
# Also, remove any space prefix or suffixes (including comments).
|
||||
lines = [line.strip().split(' ', 1)[0]
|
||||
for line in f.readlines() if '==' in line]
|
||||
|
||||
# Transform into "module" -> version dict.
|
||||
return dict(line.split('==', 1) for line in lines) # type: ignore
|
||||
|
||||
|
||||
def get_module_from_module_name(module_name):
|
||||
# type: (str) -> ModuleType
|
||||
# Module name can be uppercase in vendor.txt for some reason...
|
||||
module_name = module_name.lower()
|
||||
# PATCH: setuptools is actually only pkg_resources.
|
||||
if module_name == 'setuptools':
|
||||
module_name = 'pkg_resources'
|
||||
|
||||
__import__(
|
||||
'pip._vendor.{}'.format(module_name),
|
||||
globals(),
|
||||
locals(),
|
||||
level=0
|
||||
)
|
||||
return getattr(pip._vendor, module_name)
|
||||
|
||||
|
||||
def get_vendor_version_from_module(module_name):
|
||||
# type: (str) -> Optional[str]
|
||||
module = get_module_from_module_name(module_name)
|
||||
version = getattr(module, '__version__', None)
|
||||
|
||||
if not version:
|
||||
# Try to find version in debundled module info
|
||||
# The type for module.__file__ is Optional[str] in
|
||||
# Python 2, and str in Python 3. The type: ignore is
|
||||
# added to account for Python 2, instead of a cast
|
||||
# and should be removed once we drop Python 2 support
|
||||
pkg_set = pkg_resources.WorkingSet(
|
||||
[os.path.dirname(module.__file__)] # type: ignore
|
||||
)
|
||||
package = pkg_set.find(pkg_resources.Requirement.parse(module_name))
|
||||
version = getattr(package, 'version', None)
|
||||
|
||||
return version
|
||||
|
||||
|
||||
def show_actual_vendor_versions(vendor_txt_versions):
|
||||
# type: (Dict[str, str]) -> None
|
||||
"""Log the actual version and print extra info if there is
|
||||
a conflict or if the actual version could not be imported.
|
||||
"""
|
||||
for module_name, expected_version in vendor_txt_versions.items():
|
||||
extra_message = ''
|
||||
actual_version = get_vendor_version_from_module(module_name)
|
||||
if not actual_version:
|
||||
extra_message = ' (Unable to locate actual module version, using'\
|
||||
' vendor.txt specified version)'
|
||||
actual_version = expected_version
|
||||
elif actual_version != expected_version:
|
||||
extra_message = ' (CONFLICT: vendor.txt suggests version should'\
|
||||
' be {})'.format(expected_version)
|
||||
logger.info('%s==%s%s', module_name, actual_version, extra_message)
|
||||
|
||||
|
||||
def show_vendor_versions():
|
||||
# type: () -> None
|
||||
logger.info('vendored library versions:')
|
||||
|
||||
vendor_txt_versions = create_vendor_txt_map()
|
||||
with indent_log():
|
||||
show_actual_vendor_versions(vendor_txt_versions)
|
||||
|
||||
|
||||
def show_tags(options):
|
||||
# type: (Values) -> None
|
||||
tag_limit = 10
|
||||
|
||||
target_python = make_target_python(options)
|
||||
tags = target_python.get_tags()
|
||||
|
||||
# Display the target options that were explicitly provided.
|
||||
formatted_target = target_python.format_given()
|
||||
suffix = ''
|
||||
if formatted_target:
|
||||
suffix = ' (target: {})'.format(formatted_target)
|
||||
|
||||
msg = 'Compatible tags: {}{}'.format(len(tags), suffix)
|
||||
logger.info(msg)
|
||||
|
||||
if options.verbose < 1 and len(tags) > tag_limit:
|
||||
tags_limited = True
|
||||
tags = tags[:tag_limit]
|
||||
else:
|
||||
tags_limited = False
|
||||
|
||||
with indent_log():
|
||||
for tag in tags:
|
||||
logger.info(str(tag))
|
||||
|
||||
if tags_limited:
|
||||
msg = (
|
||||
'...\n'
|
||||
'[First {tag_limit} tags shown. Pass --verbose to show all.]'
|
||||
).format(tag_limit=tag_limit)
|
||||
logger.info(msg)
|
||||
|
||||
|
||||
def ca_bundle_info(config):
|
||||
# type: (Configuration) -> str
|
||||
levels = set()
|
||||
for key, _ in config.items():
|
||||
levels.add(key.split('.')[0])
|
||||
|
||||
if not levels:
|
||||
return "Not specified"
|
||||
|
||||
levels_that_override_global = ['install', 'wheel', 'download']
|
||||
global_overriding_level = [
|
||||
level for level in levels if level in levels_that_override_global
|
||||
]
|
||||
if not global_overriding_level:
|
||||
return 'global'
|
||||
|
||||
if 'global' in levels:
|
||||
levels.remove('global')
|
||||
return ", ".join(levels)
|
||||
|
||||
|
||||
class DebugCommand(Command):
|
||||
"""
|
||||
Display debug information.
|
||||
"""
|
||||
|
||||
usage = """
|
||||
%prog <options>"""
|
||||
ignore_require_venv = True
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
cmdoptions.add_target_python_options(self.cmd_opts)
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
self.parser.config.load()
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
logger.warning(
|
||||
"This command is only meant for debugging. "
|
||||
"Do not use this with automation for parsing and getting these "
|
||||
"details, since the output and options of this command may "
|
||||
"change without notice."
|
||||
)
|
||||
show_value('pip version', get_pip_version())
|
||||
show_value('sys.version', sys.version)
|
||||
show_value('sys.executable', sys.executable)
|
||||
show_value('sys.getdefaultencoding', sys.getdefaultencoding())
|
||||
show_value('sys.getfilesystemencoding', sys.getfilesystemencoding())
|
||||
show_value(
|
||||
'locale.getpreferredencoding', locale.getpreferredencoding(),
|
||||
)
|
||||
show_value('sys.platform', sys.platform)
|
||||
show_sys_implementation()
|
||||
|
||||
show_value("'cert' config value", ca_bundle_info(self.parser.config))
|
||||
show_value("REQUESTS_CA_BUNDLE", os.environ.get('REQUESTS_CA_BUNDLE'))
|
||||
show_value("CURL_CA_BUNDLE", os.environ.get('CURL_CA_BUNDLE'))
|
||||
show_value("pip._vendor.certifi.where()", where())
|
||||
show_value("pip._vendor.DEBUNDLED", pip._vendor.DEBUNDLED)
|
||||
|
||||
show_vendor_versions()
|
||||
|
||||
show_tags(options)
|
||||
|
||||
return SUCCESS
|
143
venv/Lib/site-packages/pip/_internal/commands/download.py
Normal file
143
venv/Lib/site-packages/pip/_internal/commands/download.py
Normal file
|
@ -0,0 +1,143 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from pip._internal.cli import cmdoptions
|
||||
from pip._internal.cli.cmdoptions import make_target_python
|
||||
from pip._internal.cli.req_command import RequirementCommand, with_cleanup
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.req.req_tracker import get_requirement_tracker
|
||||
from pip._internal.utils.misc import ensure_dir, normalize_path, write_output
|
||||
from pip._internal.utils.temp_dir import TempDirectory
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from optparse import Values
|
||||
from typing import List
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DownloadCommand(RequirementCommand):
|
||||
"""
|
||||
Download packages from:
|
||||
|
||||
- PyPI (and other indexes) using requirement specifiers.
|
||||
- VCS project urls.
|
||||
- Local project directories.
|
||||
- Local or remote source archives.
|
||||
|
||||
pip also supports downloading from "requirements files", which provide
|
||||
an easy way to specify a whole environment to be downloaded.
|
||||
"""
|
||||
|
||||
usage = """
|
||||
%prog [options] <requirement specifier> [package-index-options] ...
|
||||
%prog [options] -r <requirements file> [package-index-options] ...
|
||||
%prog [options] <vcs project url> ...
|
||||
%prog [options] <local project path> ...
|
||||
%prog [options] <archive url/path> ..."""
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
self.cmd_opts.add_option(cmdoptions.constraints())
|
||||
self.cmd_opts.add_option(cmdoptions.requirements())
|
||||
self.cmd_opts.add_option(cmdoptions.build_dir())
|
||||
self.cmd_opts.add_option(cmdoptions.no_deps())
|
||||
self.cmd_opts.add_option(cmdoptions.global_options())
|
||||
self.cmd_opts.add_option(cmdoptions.no_binary())
|
||||
self.cmd_opts.add_option(cmdoptions.only_binary())
|
||||
self.cmd_opts.add_option(cmdoptions.prefer_binary())
|
||||
self.cmd_opts.add_option(cmdoptions.src())
|
||||
self.cmd_opts.add_option(cmdoptions.pre())
|
||||
self.cmd_opts.add_option(cmdoptions.require_hashes())
|
||||
self.cmd_opts.add_option(cmdoptions.progress_bar())
|
||||
self.cmd_opts.add_option(cmdoptions.no_build_isolation())
|
||||
self.cmd_opts.add_option(cmdoptions.use_pep517())
|
||||
self.cmd_opts.add_option(cmdoptions.no_use_pep517())
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'-d', '--dest', '--destination-dir', '--destination-directory',
|
||||
dest='download_dir',
|
||||
metavar='dir',
|
||||
default=os.curdir,
|
||||
help=("Download packages into <dir>."),
|
||||
)
|
||||
|
||||
cmdoptions.add_target_python_options(self.cmd_opts)
|
||||
|
||||
index_opts = cmdoptions.make_option_group(
|
||||
cmdoptions.index_group,
|
||||
self.parser,
|
||||
)
|
||||
|
||||
self.parser.insert_option_group(0, index_opts)
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
@with_cleanup
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
|
||||
options.ignore_installed = True
|
||||
# editable doesn't really make sense for `pip download`, but the bowels
|
||||
# of the RequirementSet code require that property.
|
||||
options.editables = []
|
||||
|
||||
cmdoptions.check_dist_restriction(options)
|
||||
|
||||
options.download_dir = normalize_path(options.download_dir)
|
||||
|
||||
ensure_dir(options.download_dir)
|
||||
|
||||
session = self.get_default_session(options)
|
||||
|
||||
target_python = make_target_python(options)
|
||||
finder = self._build_package_finder(
|
||||
options=options,
|
||||
session=session,
|
||||
target_python=target_python,
|
||||
)
|
||||
build_delete = (not (options.no_clean or options.build_dir))
|
||||
|
||||
req_tracker = self.enter_context(get_requirement_tracker())
|
||||
|
||||
directory = TempDirectory(
|
||||
options.build_dir,
|
||||
delete=build_delete,
|
||||
kind="download",
|
||||
globally_managed=True,
|
||||
)
|
||||
|
||||
reqs = self.get_requirements(args, options, finder, session)
|
||||
|
||||
preparer = self.make_requirement_preparer(
|
||||
temp_build_dir=directory,
|
||||
options=options,
|
||||
req_tracker=req_tracker,
|
||||
session=session,
|
||||
finder=finder,
|
||||
download_dir=options.download_dir,
|
||||
use_user_site=False,
|
||||
)
|
||||
|
||||
resolver = self.make_resolver(
|
||||
preparer=preparer,
|
||||
finder=finder,
|
||||
options=options,
|
||||
py_version_info=options.python_version,
|
||||
)
|
||||
|
||||
self.trace_basic_info(finder)
|
||||
|
||||
requirement_set = resolver.resolve(
|
||||
reqs, check_supported_wheels=True
|
||||
)
|
||||
|
||||
downloaded = ' '.join([req.name # type: ignore
|
||||
for req in requirement_set.requirements.values()
|
||||
if req.successfully_downloaded])
|
||||
if downloaded:
|
||||
write_output('Successfully downloaded %s', downloaded)
|
||||
|
||||
return SUCCESS
|
103
venv/Lib/site-packages/pip/_internal/commands/freeze.py
Normal file
103
venv/Lib/site-packages/pip/_internal/commands/freeze.py
Normal file
|
@ -0,0 +1,103 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import sys
|
||||
|
||||
from pip._internal.cache import WheelCache
|
||||
from pip._internal.cli import cmdoptions
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.models.format_control import FormatControl
|
||||
from pip._internal.operations.freeze import freeze
|
||||
from pip._internal.utils.compat import stdlib_pkgs
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
DEV_PKGS = {'pip', 'setuptools', 'distribute', 'wheel'}
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from optparse import Values
|
||||
from typing import List
|
||||
|
||||
|
||||
class FreezeCommand(Command):
|
||||
"""
|
||||
Output installed packages in requirements format.
|
||||
|
||||
packages are listed in a case-insensitive sorted order.
|
||||
"""
|
||||
|
||||
usage = """
|
||||
%prog [options]"""
|
||||
log_streams = ("ext://sys.stderr", "ext://sys.stderr")
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
self.cmd_opts.add_option(
|
||||
'-r', '--requirement',
|
||||
dest='requirements',
|
||||
action='append',
|
||||
default=[],
|
||||
metavar='file',
|
||||
help="Use the order in the given requirements file and its "
|
||||
"comments when generating output. This option can be "
|
||||
"used multiple times.")
|
||||
self.cmd_opts.add_option(
|
||||
'-f', '--find-links',
|
||||
dest='find_links',
|
||||
action='append',
|
||||
default=[],
|
||||
metavar='URL',
|
||||
help='URL for finding packages, which will be added to the '
|
||||
'output.')
|
||||
self.cmd_opts.add_option(
|
||||
'-l', '--local',
|
||||
dest='local',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='If in a virtualenv that has global access, do not output '
|
||||
'globally-installed packages.')
|
||||
self.cmd_opts.add_option(
|
||||
'--user',
|
||||
dest='user',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Only output packages installed in user-site.')
|
||||
self.cmd_opts.add_option(cmdoptions.list_path())
|
||||
self.cmd_opts.add_option(
|
||||
'--all',
|
||||
dest='freeze_all',
|
||||
action='store_true',
|
||||
help='Do not skip these packages in the output:'
|
||||
' {}'.format(', '.join(DEV_PKGS)))
|
||||
self.cmd_opts.add_option(
|
||||
'--exclude-editable',
|
||||
dest='exclude_editable',
|
||||
action='store_true',
|
||||
help='Exclude editable package from output.')
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
format_control = FormatControl(set(), set())
|
||||
wheel_cache = WheelCache(options.cache_dir, format_control)
|
||||
skip = set(stdlib_pkgs)
|
||||
if not options.freeze_all:
|
||||
skip.update(DEV_PKGS)
|
||||
|
||||
cmdoptions.check_list_path_option(options)
|
||||
|
||||
freeze_kwargs = dict(
|
||||
requirement=options.requirements,
|
||||
find_links=options.find_links,
|
||||
local_only=options.local,
|
||||
user_only=options.user,
|
||||
paths=options.path,
|
||||
isolated=options.isolated_mode,
|
||||
wheel_cache=wheel_cache,
|
||||
skip=skip,
|
||||
exclude_editable=options.exclude_editable,
|
||||
)
|
||||
|
||||
for line in freeze(**freeze_kwargs):
|
||||
sys.stdout.write(line + '\n')
|
||||
return SUCCESS
|
63
venv/Lib/site-packages/pip/_internal/commands/hash.py
Normal file
63
venv/Lib/site-packages/pip/_internal/commands/hash.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.status_codes import ERROR, SUCCESS
|
||||
from pip._internal.utils.hashes import FAVORITE_HASH, STRONG_HASHES
|
||||
from pip._internal.utils.misc import read_chunks, write_output
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from optparse import Values
|
||||
from typing import List
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HashCommand(Command):
|
||||
"""
|
||||
Compute a hash of a local package archive.
|
||||
|
||||
These can be used with --hash in a requirements file to do repeatable
|
||||
installs.
|
||||
"""
|
||||
|
||||
usage = '%prog [options] <file> ...'
|
||||
ignore_require_venv = True
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
self.cmd_opts.add_option(
|
||||
'-a', '--algorithm',
|
||||
dest='algorithm',
|
||||
choices=STRONG_HASHES,
|
||||
action='store',
|
||||
default=FAVORITE_HASH,
|
||||
help='The hash algorithm to use: one of {}'.format(
|
||||
', '.join(STRONG_HASHES)))
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
if not args:
|
||||
self.parser.print_usage(sys.stderr)
|
||||
return ERROR
|
||||
|
||||
algorithm = options.algorithm
|
||||
for path in args:
|
||||
write_output('%s:\n--hash=%s:%s',
|
||||
path, algorithm, _hash_of_file(path, algorithm))
|
||||
return SUCCESS
|
||||
|
||||
|
||||
def _hash_of_file(path, algorithm):
|
||||
# type: (str, str) -> str
|
||||
"""Return the hash digest of a file."""
|
||||
with open(path, 'rb') as archive:
|
||||
hash = hashlib.new(algorithm)
|
||||
for chunk in read_chunks(archive):
|
||||
hash.update(chunk)
|
||||
return hash.hexdigest()
|
44
venv/Lib/site-packages/pip/_internal/commands/help.py
Normal file
44
venv/Lib/site-packages/pip/_internal/commands/help.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.exceptions import CommandError
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from typing import List
|
||||
from optparse import Values
|
||||
|
||||
|
||||
class HelpCommand(Command):
|
||||
"""Show help for commands"""
|
||||
|
||||
usage = """
|
||||
%prog <command>"""
|
||||
ignore_require_venv = True
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
from pip._internal.commands import (
|
||||
commands_dict, create_command, get_similar_commands,
|
||||
)
|
||||
|
||||
try:
|
||||
# 'pip help' with no args is handled by pip.__init__.parseopt()
|
||||
cmd_name = args[0] # the command we need help for
|
||||
except IndexError:
|
||||
return SUCCESS
|
||||
|
||||
if cmd_name not in commands_dict:
|
||||
guess = get_similar_commands(cmd_name)
|
||||
|
||||
msg = ['unknown command "{}"'.format(cmd_name)]
|
||||
if guess:
|
||||
msg.append('maybe you meant "{}"'.format(guess))
|
||||
|
||||
raise CommandError(' - '.join(msg))
|
||||
|
||||
command = create_command(cmd_name)
|
||||
command.parser.print_help()
|
||||
|
||||
return SUCCESS
|
749
venv/Lib/site-packages/pip/_internal/commands/install.py
Normal file
749
venv/Lib/site-packages/pip/_internal/commands/install.py
Normal file
|
@ -0,0 +1,749 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import errno
|
||||
import logging
|
||||
import operator
|
||||
import os
|
||||
import shutil
|
||||
import site
|
||||
from optparse import SUPPRESS_HELP
|
||||
|
||||
from pip._vendor import pkg_resources
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
|
||||
from pip._internal.cache import WheelCache
|
||||
from pip._internal.cli import cmdoptions
|
||||
from pip._internal.cli.cmdoptions import make_target_python
|
||||
from pip._internal.cli.req_command import RequirementCommand, with_cleanup
|
||||
from pip._internal.cli.status_codes import ERROR, SUCCESS
|
||||
from pip._internal.exceptions import CommandError, InstallationError
|
||||
from pip._internal.locations import distutils_scheme
|
||||
from pip._internal.operations.check import check_install_conflicts
|
||||
from pip._internal.req import install_given_reqs
|
||||
from pip._internal.req.req_tracker import get_requirement_tracker
|
||||
from pip._internal.utils.datetime import today_is_later_than
|
||||
from pip._internal.utils.distutils_args import parse_distutils_args
|
||||
from pip._internal.utils.filesystem import test_writable_dir
|
||||
from pip._internal.utils.misc import (
|
||||
ensure_dir,
|
||||
get_installed_version,
|
||||
get_pip_version,
|
||||
protect_pip_from_modification_on_windows,
|
||||
write_output,
|
||||
)
|
||||
from pip._internal.utils.temp_dir import TempDirectory
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
from pip._internal.utils.virtualenv import virtualenv_no_global
|
||||
from pip._internal.wheel_builder import build, should_build_for_install_command
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from optparse import Values
|
||||
from typing import Iterable, List, Optional
|
||||
|
||||
from pip._internal.models.format_control import FormatControl
|
||||
from pip._internal.operations.check import ConflictDetails
|
||||
from pip._internal.req.req_install import InstallRequirement
|
||||
from pip._internal.wheel_builder import BinaryAllowedPredicate
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_check_binary_allowed(format_control):
|
||||
# type: (FormatControl) -> BinaryAllowedPredicate
|
||||
def check_binary_allowed(req):
|
||||
# type: (InstallRequirement) -> bool
|
||||
if req.use_pep517:
|
||||
return True
|
||||
canonical_name = canonicalize_name(req.name)
|
||||
allowed_formats = format_control.get_allowed_formats(canonical_name)
|
||||
return "binary" in allowed_formats
|
||||
|
||||
return check_binary_allowed
|
||||
|
||||
|
||||
class InstallCommand(RequirementCommand):
|
||||
"""
|
||||
Install packages from:
|
||||
|
||||
- PyPI (and other indexes) using requirement specifiers.
|
||||
- VCS project urls.
|
||||
- Local project directories.
|
||||
- Local or remote source archives.
|
||||
|
||||
pip also supports installing from "requirements files", which provide
|
||||
an easy way to specify a whole environment to be installed.
|
||||
"""
|
||||
|
||||
usage = """
|
||||
%prog [options] <requirement specifier> [package-index-options] ...
|
||||
%prog [options] -r <requirements file> [package-index-options] ...
|
||||
%prog [options] [-e] <vcs project url> ...
|
||||
%prog [options] [-e] <local project path> ...
|
||||
%prog [options] <archive url/path> ..."""
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
self.cmd_opts.add_option(cmdoptions.requirements())
|
||||
self.cmd_opts.add_option(cmdoptions.constraints())
|
||||
self.cmd_opts.add_option(cmdoptions.no_deps())
|
||||
self.cmd_opts.add_option(cmdoptions.pre())
|
||||
|
||||
self.cmd_opts.add_option(cmdoptions.editable())
|
||||
self.cmd_opts.add_option(
|
||||
'-t', '--target',
|
||||
dest='target_dir',
|
||||
metavar='dir',
|
||||
default=None,
|
||||
help='Install packages into <dir>. '
|
||||
'By default this will not replace existing files/folders in '
|
||||
'<dir>. Use --upgrade to replace existing packages in <dir> '
|
||||
'with new versions.'
|
||||
)
|
||||
cmdoptions.add_target_python_options(self.cmd_opts)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'--user',
|
||||
dest='use_user_site',
|
||||
action='store_true',
|
||||
help="Install to the Python user install directory for your "
|
||||
"platform. Typically ~/.local/, or %APPDATA%\\Python on "
|
||||
"Windows. (See the Python documentation for site.USER_BASE "
|
||||
"for full details.)")
|
||||
self.cmd_opts.add_option(
|
||||
'--no-user',
|
||||
dest='use_user_site',
|
||||
action='store_false',
|
||||
help=SUPPRESS_HELP)
|
||||
self.cmd_opts.add_option(
|
||||
'--root',
|
||||
dest='root_path',
|
||||
metavar='dir',
|
||||
default=None,
|
||||
help="Install everything relative to this alternate root "
|
||||
"directory.")
|
||||
self.cmd_opts.add_option(
|
||||
'--prefix',
|
||||
dest='prefix_path',
|
||||
metavar='dir',
|
||||
default=None,
|
||||
help="Installation prefix where lib, bin and other top-level "
|
||||
"folders are placed")
|
||||
|
||||
self.cmd_opts.add_option(cmdoptions.build_dir())
|
||||
|
||||
self.cmd_opts.add_option(cmdoptions.src())
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'-U', '--upgrade',
|
||||
dest='upgrade',
|
||||
action='store_true',
|
||||
help='Upgrade all specified packages to the newest available '
|
||||
'version. The handling of dependencies depends on the '
|
||||
'upgrade-strategy used.'
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'--upgrade-strategy',
|
||||
dest='upgrade_strategy',
|
||||
default='only-if-needed',
|
||||
choices=['only-if-needed', 'eager'],
|
||||
help='Determines how dependency upgrading should be handled '
|
||||
'[default: %default]. '
|
||||
'"eager" - dependencies are upgraded regardless of '
|
||||
'whether the currently installed version satisfies the '
|
||||
'requirements of the upgraded package(s). '
|
||||
'"only-if-needed" - are upgraded only when they do not '
|
||||
'satisfy the requirements of the upgraded package(s).'
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'--force-reinstall',
|
||||
dest='force_reinstall',
|
||||
action='store_true',
|
||||
help='Reinstall all packages even if they are already '
|
||||
'up-to-date.')
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'-I', '--ignore-installed',
|
||||
dest='ignore_installed',
|
||||
action='store_true',
|
||||
help='Ignore the installed packages, overwriting them. '
|
||||
'This can break your system if the existing package '
|
||||
'is of a different version or was installed '
|
||||
'with a different package manager!'
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
|
||||
self.cmd_opts.add_option(cmdoptions.no_build_isolation())
|
||||
self.cmd_opts.add_option(cmdoptions.use_pep517())
|
||||
self.cmd_opts.add_option(cmdoptions.no_use_pep517())
|
||||
|
||||
self.cmd_opts.add_option(cmdoptions.install_options())
|
||||
self.cmd_opts.add_option(cmdoptions.global_options())
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"--compile",
|
||||
action="store_true",
|
||||
dest="compile",
|
||||
default=True,
|
||||
help="Compile Python source files to bytecode",
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"--no-compile",
|
||||
action="store_false",
|
||||
dest="compile",
|
||||
help="Do not compile Python source files to bytecode",
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"--no-warn-script-location",
|
||||
action="store_false",
|
||||
dest="warn_script_location",
|
||||
default=True,
|
||||
help="Do not warn when installing scripts outside PATH",
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
"--no-warn-conflicts",
|
||||
action="store_false",
|
||||
dest="warn_about_conflicts",
|
||||
default=True,
|
||||
help="Do not warn about broken dependencies",
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(cmdoptions.no_binary())
|
||||
self.cmd_opts.add_option(cmdoptions.only_binary())
|
||||
self.cmd_opts.add_option(cmdoptions.prefer_binary())
|
||||
self.cmd_opts.add_option(cmdoptions.require_hashes())
|
||||
self.cmd_opts.add_option(cmdoptions.progress_bar())
|
||||
|
||||
index_opts = cmdoptions.make_option_group(
|
||||
cmdoptions.index_group,
|
||||
self.parser,
|
||||
)
|
||||
|
||||
self.parser.insert_option_group(0, index_opts)
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
@with_cleanup
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
if options.use_user_site and options.target_dir is not None:
|
||||
raise CommandError("Can not combine '--user' and '--target'")
|
||||
|
||||
cmdoptions.check_install_build_global(options)
|
||||
upgrade_strategy = "to-satisfy-only"
|
||||
if options.upgrade:
|
||||
upgrade_strategy = options.upgrade_strategy
|
||||
|
||||
cmdoptions.check_dist_restriction(options, check_target=True)
|
||||
|
||||
install_options = options.install_options or []
|
||||
|
||||
logger.debug("Using %s", get_pip_version())
|
||||
options.use_user_site = decide_user_install(
|
||||
options.use_user_site,
|
||||
prefix_path=options.prefix_path,
|
||||
target_dir=options.target_dir,
|
||||
root_path=options.root_path,
|
||||
isolated_mode=options.isolated_mode,
|
||||
)
|
||||
|
||||
target_temp_dir = None # type: Optional[TempDirectory]
|
||||
target_temp_dir_path = None # type: Optional[str]
|
||||
if options.target_dir:
|
||||
options.ignore_installed = True
|
||||
options.target_dir = os.path.abspath(options.target_dir)
|
||||
if (os.path.exists(options.target_dir) and not
|
||||
os.path.isdir(options.target_dir)):
|
||||
raise CommandError(
|
||||
"Target path exists but is not a directory, will not "
|
||||
"continue."
|
||||
)
|
||||
|
||||
# Create a target directory for using with the target option
|
||||
target_temp_dir = TempDirectory(kind="target")
|
||||
target_temp_dir_path = target_temp_dir.path
|
||||
self.enter_context(target_temp_dir)
|
||||
|
||||
global_options = options.global_options or []
|
||||
|
||||
session = self.get_default_session(options)
|
||||
|
||||
target_python = make_target_python(options)
|
||||
finder = self._build_package_finder(
|
||||
options=options,
|
||||
session=session,
|
||||
target_python=target_python,
|
||||
ignore_requires_python=options.ignore_requires_python,
|
||||
)
|
||||
build_delete = (not (options.no_clean or options.build_dir))
|
||||
wheel_cache = WheelCache(options.cache_dir, options.format_control)
|
||||
|
||||
req_tracker = self.enter_context(get_requirement_tracker())
|
||||
|
||||
directory = TempDirectory(
|
||||
options.build_dir,
|
||||
delete=build_delete,
|
||||
kind="install",
|
||||
globally_managed=True,
|
||||
)
|
||||
|
||||
try:
|
||||
reqs = self.get_requirements(args, options, finder, session)
|
||||
|
||||
reject_location_related_install_options(
|
||||
reqs, options.install_options
|
||||
)
|
||||
|
||||
preparer = self.make_requirement_preparer(
|
||||
temp_build_dir=directory,
|
||||
options=options,
|
||||
req_tracker=req_tracker,
|
||||
session=session,
|
||||
finder=finder,
|
||||
use_user_site=options.use_user_site,
|
||||
)
|
||||
resolver = self.make_resolver(
|
||||
preparer=preparer,
|
||||
finder=finder,
|
||||
options=options,
|
||||
wheel_cache=wheel_cache,
|
||||
use_user_site=options.use_user_site,
|
||||
ignore_installed=options.ignore_installed,
|
||||
ignore_requires_python=options.ignore_requires_python,
|
||||
force_reinstall=options.force_reinstall,
|
||||
upgrade_strategy=upgrade_strategy,
|
||||
use_pep517=options.use_pep517,
|
||||
)
|
||||
|
||||
self.trace_basic_info(finder)
|
||||
|
||||
requirement_set = resolver.resolve(
|
||||
reqs, check_supported_wheels=not options.target_dir
|
||||
)
|
||||
|
||||
try:
|
||||
pip_req = requirement_set.get_requirement("pip")
|
||||
except KeyError:
|
||||
modifying_pip = False
|
||||
else:
|
||||
# If we're not replacing an already installed pip,
|
||||
# we're not modifying it.
|
||||
modifying_pip = pip_req.satisfied_by is None
|
||||
protect_pip_from_modification_on_windows(
|
||||
modifying_pip=modifying_pip
|
||||
)
|
||||
|
||||
check_binary_allowed = get_check_binary_allowed(
|
||||
finder.format_control
|
||||
)
|
||||
|
||||
reqs_to_build = [
|
||||
r for r in requirement_set.requirements.values()
|
||||
if should_build_for_install_command(
|
||||
r, check_binary_allowed
|
||||
)
|
||||
]
|
||||
|
||||
_, build_failures = build(
|
||||
reqs_to_build,
|
||||
wheel_cache=wheel_cache,
|
||||
build_options=[],
|
||||
global_options=[],
|
||||
)
|
||||
|
||||
# If we're using PEP 517, we cannot do a direct install
|
||||
# so we fail here.
|
||||
pep517_build_failure_names = [
|
||||
r.name # type: ignore
|
||||
for r in build_failures if r.use_pep517
|
||||
] # type: List[str]
|
||||
if pep517_build_failure_names:
|
||||
raise InstallationError(
|
||||
"Could not build wheels for {} which use"
|
||||
" PEP 517 and cannot be installed directly".format(
|
||||
", ".join(pep517_build_failure_names)
|
||||
)
|
||||
)
|
||||
|
||||
# For now, we just warn about failures building legacy
|
||||
# requirements, as we'll fall through to a direct
|
||||
# install for those.
|
||||
for r in build_failures:
|
||||
if not r.use_pep517:
|
||||
r.legacy_install_reason = 8368
|
||||
|
||||
to_install = resolver.get_installation_order(
|
||||
requirement_set
|
||||
)
|
||||
|
||||
# Check for conflicts in the package set we're installing.
|
||||
conflicts = None # type: Optional[ConflictDetails]
|
||||
should_warn_about_conflicts = (
|
||||
not options.ignore_dependencies and
|
||||
options.warn_about_conflicts
|
||||
)
|
||||
if should_warn_about_conflicts:
|
||||
conflicts = self._determine_conflicts(to_install)
|
||||
|
||||
# Don't warn about script install locations if
|
||||
# --target has been specified
|
||||
warn_script_location = options.warn_script_location
|
||||
if options.target_dir:
|
||||
warn_script_location = False
|
||||
|
||||
installed = install_given_reqs(
|
||||
to_install,
|
||||
install_options,
|
||||
global_options,
|
||||
root=options.root_path,
|
||||
home=target_temp_dir_path,
|
||||
prefix=options.prefix_path,
|
||||
warn_script_location=warn_script_location,
|
||||
use_user_site=options.use_user_site,
|
||||
pycompile=options.compile,
|
||||
)
|
||||
|
||||
lib_locations = get_lib_location_guesses(
|
||||
user=options.use_user_site,
|
||||
home=target_temp_dir_path,
|
||||
root=options.root_path,
|
||||
prefix=options.prefix_path,
|
||||
isolated=options.isolated_mode,
|
||||
)
|
||||
working_set = pkg_resources.WorkingSet(lib_locations)
|
||||
|
||||
installed.sort(key=operator.attrgetter('name'))
|
||||
items = []
|
||||
for result in installed:
|
||||
item = result.name
|
||||
try:
|
||||
installed_version = get_installed_version(
|
||||
result.name, working_set=working_set
|
||||
)
|
||||
if installed_version:
|
||||
item += '-' + installed_version
|
||||
except Exception:
|
||||
pass
|
||||
items.append(item)
|
||||
|
||||
if conflicts is not None:
|
||||
self._warn_about_conflicts(
|
||||
conflicts,
|
||||
new_resolver='2020-resolver' in options.features_enabled,
|
||||
)
|
||||
|
||||
installed_desc = ' '.join(items)
|
||||
if installed_desc:
|
||||
write_output(
|
||||
'Successfully installed %s', installed_desc,
|
||||
)
|
||||
except EnvironmentError as error:
|
||||
show_traceback = (self.verbosity >= 1)
|
||||
|
||||
message = create_env_error_message(
|
||||
error, show_traceback, options.use_user_site,
|
||||
)
|
||||
logger.error(message, exc_info=show_traceback) # noqa
|
||||
|
||||
return ERROR
|
||||
|
||||
if options.target_dir:
|
||||
assert target_temp_dir
|
||||
self._handle_target_dir(
|
||||
options.target_dir, target_temp_dir, options.upgrade
|
||||
)
|
||||
|
||||
return SUCCESS
|
||||
|
||||
def _handle_target_dir(self, target_dir, target_temp_dir, upgrade):
|
||||
# type: (str, TempDirectory, bool) -> None
|
||||
ensure_dir(target_dir)
|
||||
|
||||
# Checking both purelib and platlib directories for installed
|
||||
# packages to be moved to target directory
|
||||
lib_dir_list = []
|
||||
|
||||
# Checking both purelib and platlib directories for installed
|
||||
# packages to be moved to target directory
|
||||
scheme = distutils_scheme('', home=target_temp_dir.path)
|
||||
purelib_dir = scheme['purelib']
|
||||
platlib_dir = scheme['platlib']
|
||||
data_dir = scheme['data']
|
||||
|
||||
if os.path.exists(purelib_dir):
|
||||
lib_dir_list.append(purelib_dir)
|
||||
if os.path.exists(platlib_dir) and platlib_dir != purelib_dir:
|
||||
lib_dir_list.append(platlib_dir)
|
||||
if os.path.exists(data_dir):
|
||||
lib_dir_list.append(data_dir)
|
||||
|
||||
for lib_dir in lib_dir_list:
|
||||
for item in os.listdir(lib_dir):
|
||||
if lib_dir == data_dir:
|
||||
ddir = os.path.join(data_dir, item)
|
||||
if any(s.startswith(ddir) for s in lib_dir_list[:-1]):
|
||||
continue
|
||||
target_item_dir = os.path.join(target_dir, item)
|
||||
if os.path.exists(target_item_dir):
|
||||
if not upgrade:
|
||||
logger.warning(
|
||||
'Target directory %s already exists. Specify '
|
||||
'--upgrade to force replacement.',
|
||||
target_item_dir
|
||||
)
|
||||
continue
|
||||
if os.path.islink(target_item_dir):
|
||||
logger.warning(
|
||||
'Target directory %s already exists and is '
|
||||
'a link. pip will not automatically replace '
|
||||
'links, please remove if replacement is '
|
||||
'desired.',
|
||||
target_item_dir
|
||||
)
|
||||
continue
|
||||
if os.path.isdir(target_item_dir):
|
||||
shutil.rmtree(target_item_dir)
|
||||
else:
|
||||
os.remove(target_item_dir)
|
||||
|
||||
shutil.move(
|
||||
os.path.join(lib_dir, item),
|
||||
target_item_dir
|
||||
)
|
||||
|
||||
def _determine_conflicts(self, to_install):
|
||||
# type: (List[InstallRequirement]) -> Optional[ConflictDetails]
|
||||
try:
|
||||
return check_install_conflicts(to_install)
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"Error while checking for conflicts. Please file an issue on "
|
||||
"pip's issue tracker: https://github.com/pypa/pip/issues/new"
|
||||
)
|
||||
return None
|
||||
|
||||
def _warn_about_conflicts(self, conflict_details, new_resolver):
|
||||
# type: (ConflictDetails, bool) -> None
|
||||
package_set, (missing, conflicting) = conflict_details
|
||||
if not missing and not conflicting:
|
||||
return
|
||||
|
||||
parts = [] # type: List[str]
|
||||
if not new_resolver:
|
||||
parts.append(
|
||||
"After October 2020 you may experience errors when installing "
|
||||
"or updating packages. This is because pip will change the "
|
||||
"way that it resolves dependency conflicts.\n"
|
||||
)
|
||||
parts.append(
|
||||
"We recommend you use --use-feature=2020-resolver to test "
|
||||
"your packages with the new resolver before it becomes the "
|
||||
"default.\n"
|
||||
)
|
||||
elif not today_is_later_than(year=2020, month=7, day=31):
|
||||
# NOTE: trailing newlines here are intentional
|
||||
parts.append(
|
||||
"Pip will install or upgrade your package(s) and its "
|
||||
"dependencies without taking into account other packages you "
|
||||
"already have installed. This may cause an uncaught "
|
||||
"dependency conflict.\n"
|
||||
)
|
||||
form_link = "https://forms.gle/cWKMoDs8sUVE29hz9"
|
||||
parts.append(
|
||||
"If you would like pip to take your other packages into "
|
||||
"account, please tell us here: {}\n".format(form_link)
|
||||
)
|
||||
|
||||
# NOTE: There is some duplication here, with commands/check.py
|
||||
for project_name in missing:
|
||||
version = package_set[project_name][0]
|
||||
for dependency in missing[project_name]:
|
||||
message = (
|
||||
"{name} {version} requires {requirement}, "
|
||||
"which is not installed."
|
||||
).format(
|
||||
name=project_name,
|
||||
version=version,
|
||||
requirement=dependency[1],
|
||||
)
|
||||
parts.append(message)
|
||||
|
||||
for project_name in conflicting:
|
||||
version = package_set[project_name][0]
|
||||
for dep_name, dep_version, req in conflicting[project_name]:
|
||||
message = (
|
||||
"{name} {version} requires {requirement}, but you'll have "
|
||||
"{dep_name} {dep_version} which is incompatible."
|
||||
).format(
|
||||
name=project_name,
|
||||
version=version,
|
||||
requirement=req,
|
||||
dep_name=dep_name,
|
||||
dep_version=dep_version,
|
||||
)
|
||||
parts.append(message)
|
||||
|
||||
logger.critical("\n".join(parts))
|
||||
|
||||
|
||||
def get_lib_location_guesses(
|
||||
user=False, # type: bool
|
||||
home=None, # type: Optional[str]
|
||||
root=None, # type: Optional[str]
|
||||
isolated=False, # type: bool
|
||||
prefix=None # type: Optional[str]
|
||||
):
|
||||
# type:(...) -> List[str]
|
||||
scheme = distutils_scheme('', user=user, home=home, root=root,
|
||||
isolated=isolated, prefix=prefix)
|
||||
return [scheme['purelib'], scheme['platlib']]
|
||||
|
||||
|
||||
def site_packages_writable(root, isolated):
|
||||
# type: (Optional[str], bool) -> bool
|
||||
return all(
|
||||
test_writable_dir(d) for d in set(
|
||||
get_lib_location_guesses(root=root, isolated=isolated))
|
||||
)
|
||||
|
||||
|
||||
def decide_user_install(
|
||||
use_user_site, # type: Optional[bool]
|
||||
prefix_path=None, # type: Optional[str]
|
||||
target_dir=None, # type: Optional[str]
|
||||
root_path=None, # type: Optional[str]
|
||||
isolated_mode=False, # type: bool
|
||||
):
|
||||
# type: (...) -> bool
|
||||
"""Determine whether to do a user install based on the input options.
|
||||
|
||||
If use_user_site is False, no additional checks are done.
|
||||
If use_user_site is True, it is checked for compatibility with other
|
||||
options.
|
||||
If use_user_site is None, the default behaviour depends on the environment,
|
||||
which is provided by the other arguments.
|
||||
"""
|
||||
# In some cases (config from tox), use_user_site can be set to an integer
|
||||
# rather than a bool, which 'use_user_site is False' wouldn't catch.
|
||||
if (use_user_site is not None) and (not use_user_site):
|
||||
logger.debug("Non-user install by explicit request")
|
||||
return False
|
||||
|
||||
if use_user_site:
|
||||
if prefix_path:
|
||||
raise CommandError(
|
||||
"Can not combine '--user' and '--prefix' as they imply "
|
||||
"different installation locations"
|
||||
)
|
||||
if virtualenv_no_global():
|
||||
raise InstallationError(
|
||||
"Can not perform a '--user' install. User site-packages "
|
||||
"are not visible in this virtualenv."
|
||||
)
|
||||
logger.debug("User install by explicit request")
|
||||
return True
|
||||
|
||||
# If we are here, user installs have not been explicitly requested/avoided
|
||||
assert use_user_site is None
|
||||
|
||||
# user install incompatible with --prefix/--target
|
||||
if prefix_path or target_dir:
|
||||
logger.debug("Non-user install due to --prefix or --target option")
|
||||
return False
|
||||
|
||||
# If user installs are not enabled, choose a non-user install
|
||||
if not site.ENABLE_USER_SITE:
|
||||
logger.debug("Non-user install because user site-packages disabled")
|
||||
return False
|
||||
|
||||
# If we have permission for a non-user install, do that,
|
||||
# otherwise do a user install.
|
||||
if site_packages_writable(root=root_path, isolated=isolated_mode):
|
||||
logger.debug("Non-user install because site-packages writeable")
|
||||
return False
|
||||
|
||||
logger.info("Defaulting to user installation because normal site-packages "
|
||||
"is not writeable")
|
||||
return True
|
||||
|
||||
|
||||
def reject_location_related_install_options(requirements, options):
|
||||
# type: (List[InstallRequirement], Optional[List[str]]) -> None
|
||||
"""If any location-changing --install-option arguments were passed for
|
||||
requirements or on the command-line, then show a deprecation warning.
|
||||
"""
|
||||
def format_options(option_names):
|
||||
# type: (Iterable[str]) -> List[str]
|
||||
return ["--{}".format(name.replace("_", "-")) for name in option_names]
|
||||
|
||||
offenders = []
|
||||
|
||||
for requirement in requirements:
|
||||
install_options = requirement.install_options
|
||||
location_options = parse_distutils_args(install_options)
|
||||
if location_options:
|
||||
offenders.append(
|
||||
"{!r} from {}".format(
|
||||
format_options(location_options.keys()), requirement
|
||||
)
|
||||
)
|
||||
|
||||
if options:
|
||||
location_options = parse_distutils_args(options)
|
||||
if location_options:
|
||||
offenders.append(
|
||||
"{!r} from command line".format(
|
||||
format_options(location_options.keys())
|
||||
)
|
||||
)
|
||||
|
||||
if not offenders:
|
||||
return
|
||||
|
||||
raise CommandError(
|
||||
"Location-changing options found in --install-option: {}."
|
||||
" This is unsupported, use pip-level options like --user,"
|
||||
" --prefix, --root, and --target instead.".format(
|
||||
"; ".join(offenders)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def create_env_error_message(error, show_traceback, using_user_site):
|
||||
# type: (EnvironmentError, bool, bool) -> str
|
||||
"""Format an error message for an EnvironmentError
|
||||
|
||||
It may occur anytime during the execution of the install command.
|
||||
"""
|
||||
parts = []
|
||||
|
||||
# Mention the error if we are not going to show a traceback
|
||||
parts.append("Could not install packages due to an EnvironmentError")
|
||||
if not show_traceback:
|
||||
parts.append(": ")
|
||||
parts.append(str(error))
|
||||
else:
|
||||
parts.append(".")
|
||||
|
||||
# Spilt the error indication from a helper message (if any)
|
||||
parts[-1] += "\n"
|
||||
|
||||
# Suggest useful actions to the user:
|
||||
# (1) using user site-packages or (2) verifying the permissions
|
||||
if error.errno == errno.EACCES:
|
||||
user_option_part = "Consider using the `--user` option"
|
||||
permissions_part = "Check the permissions"
|
||||
|
||||
if not using_user_site:
|
||||
parts.extend([
|
||||
user_option_part, " or ",
|
||||
permissions_part.lower(),
|
||||
])
|
||||
else:
|
||||
parts.append(permissions_part)
|
||||
parts.append(".\n")
|
||||
|
||||
return "".join(parts).strip() + "\n"
|
320
venv/Lib/site-packages/pip/_internal/commands/list.py
Normal file
320
venv/Lib/site-packages/pip/_internal/commands/list.py
Normal file
|
@ -0,0 +1,320 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
from pip._vendor import six
|
||||
|
||||
from pip._internal.cli import cmdoptions
|
||||
from pip._internal.cli.req_command import IndexGroupCommand
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.exceptions import CommandError
|
||||
from pip._internal.index.collector import LinkCollector
|
||||
from pip._internal.index.package_finder import PackageFinder
|
||||
from pip._internal.models.selection_prefs import SelectionPreferences
|
||||
from pip._internal.utils.misc import (
|
||||
dist_is_editable,
|
||||
get_installed_distributions,
|
||||
tabulate,
|
||||
write_output,
|
||||
)
|
||||
from pip._internal.utils.packaging import get_installer
|
||||
from pip._internal.utils.parallel import map_multithread
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from optparse import Values
|
||||
from typing import List, Set, Tuple, Iterator
|
||||
|
||||
from pip._internal.network.session import PipSession
|
||||
from pip._vendor.pkg_resources import Distribution
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ListCommand(IndexGroupCommand):
|
||||
"""
|
||||
List installed packages, including editables.
|
||||
|
||||
Packages are listed in a case-insensitive sorted order.
|
||||
"""
|
||||
|
||||
ignore_require_venv = True
|
||||
usage = """
|
||||
%prog [options]"""
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
self.cmd_opts.add_option(
|
||||
'-o', '--outdated',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='List outdated packages')
|
||||
self.cmd_opts.add_option(
|
||||
'-u', '--uptodate',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='List uptodate packages')
|
||||
self.cmd_opts.add_option(
|
||||
'-e', '--editable',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='List editable projects.')
|
||||
self.cmd_opts.add_option(
|
||||
'-l', '--local',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=('If in a virtualenv that has global access, do not list '
|
||||
'globally-installed packages.'),
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
'--user',
|
||||
dest='user',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Only output packages installed in user-site.')
|
||||
self.cmd_opts.add_option(cmdoptions.list_path())
|
||||
self.cmd_opts.add_option(
|
||||
'--pre',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=("Include pre-release and development versions. By default, "
|
||||
"pip only finds stable versions."),
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'--format',
|
||||
action='store',
|
||||
dest='list_format',
|
||||
default="columns",
|
||||
choices=('columns', 'freeze', 'json'),
|
||||
help="Select the output format among: columns (default), freeze, "
|
||||
"or json",
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'--not-required',
|
||||
action='store_true',
|
||||
dest='not_required',
|
||||
help="List packages that are not dependencies of "
|
||||
"installed packages.",
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'--exclude-editable',
|
||||
action='store_false',
|
||||
dest='include_editable',
|
||||
help='Exclude editable package from output.',
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
'--include-editable',
|
||||
action='store_true',
|
||||
dest='include_editable',
|
||||
help='Include editable package from output.',
|
||||
default=True,
|
||||
)
|
||||
index_opts = cmdoptions.make_option_group(
|
||||
cmdoptions.index_group, self.parser
|
||||
)
|
||||
|
||||
self.parser.insert_option_group(0, index_opts)
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def _build_package_finder(self, options, session):
|
||||
# type: (Values, PipSession) -> PackageFinder
|
||||
"""
|
||||
Create a package finder appropriate to this list command.
|
||||
"""
|
||||
link_collector = LinkCollector.create(session, options=options)
|
||||
|
||||
# Pass allow_yanked=False to ignore yanked versions.
|
||||
selection_prefs = SelectionPreferences(
|
||||
allow_yanked=False,
|
||||
allow_all_prereleases=options.pre,
|
||||
)
|
||||
|
||||
return PackageFinder.create(
|
||||
link_collector=link_collector,
|
||||
selection_prefs=selection_prefs,
|
||||
)
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
if options.outdated and options.uptodate:
|
||||
raise CommandError(
|
||||
"Options --outdated and --uptodate cannot be combined.")
|
||||
|
||||
cmdoptions.check_list_path_option(options)
|
||||
|
||||
packages = get_installed_distributions(
|
||||
local_only=options.local,
|
||||
user_only=options.user,
|
||||
editables_only=options.editable,
|
||||
include_editables=options.include_editable,
|
||||
paths=options.path,
|
||||
)
|
||||
|
||||
# get_not_required must be called firstly in order to find and
|
||||
# filter out all dependencies correctly. Otherwise a package
|
||||
# can't be identified as requirement because some parent packages
|
||||
# could be filtered out before.
|
||||
if options.not_required:
|
||||
packages = self.get_not_required(packages, options)
|
||||
|
||||
if options.outdated:
|
||||
packages = self.get_outdated(packages, options)
|
||||
elif options.uptodate:
|
||||
packages = self.get_uptodate(packages, options)
|
||||
|
||||
self.output_package_listing(packages, options)
|
||||
return SUCCESS
|
||||
|
||||
def get_outdated(self, packages, options):
|
||||
# type: (List[Distribution], Values) -> List[Distribution]
|
||||
return [
|
||||
dist for dist in self.iter_packages_latest_infos(packages, options)
|
||||
if dist.latest_version > dist.parsed_version
|
||||
]
|
||||
|
||||
def get_uptodate(self, packages, options):
|
||||
# type: (List[Distribution], Values) -> List[Distribution]
|
||||
return [
|
||||
dist for dist in self.iter_packages_latest_infos(packages, options)
|
||||
if dist.latest_version == dist.parsed_version
|
||||
]
|
||||
|
||||
def get_not_required(self, packages, options):
|
||||
# type: (List[Distribution], Values) -> List[Distribution]
|
||||
dep_keys = set() # type: Set[Distribution]
|
||||
for dist in packages:
|
||||
dep_keys.update(requirement.key for requirement in dist.requires())
|
||||
|
||||
# Create a set to remove duplicate packages, and cast it to a list
|
||||
# to keep the return type consistent with get_outdated and
|
||||
# get_uptodate
|
||||
return list({pkg for pkg in packages if pkg.key not in dep_keys})
|
||||
|
||||
def iter_packages_latest_infos(self, packages, options):
|
||||
# type: (List[Distribution], Values) -> Iterator[Distribution]
|
||||
with self._build_session(options) as session:
|
||||
finder = self._build_package_finder(options, session)
|
||||
|
||||
def latest_info(dist):
|
||||
# type: (Distribution) -> Distribution
|
||||
typ = 'unknown'
|
||||
all_candidates = finder.find_all_candidates(dist.key)
|
||||
if not options.pre:
|
||||
# Remove prereleases
|
||||
all_candidates = [candidate for candidate in all_candidates
|
||||
if not candidate.version.is_prerelease]
|
||||
|
||||
evaluator = finder.make_candidate_evaluator(
|
||||
project_name=dist.project_name,
|
||||
)
|
||||
best_candidate = evaluator.sort_best_candidate(all_candidates)
|
||||
if best_candidate is None:
|
||||
return None
|
||||
|
||||
remote_version = best_candidate.version
|
||||
if best_candidate.link.is_wheel:
|
||||
typ = 'wheel'
|
||||
else:
|
||||
typ = 'sdist'
|
||||
# This is dirty but makes the rest of the code much cleaner
|
||||
dist.latest_version = remote_version
|
||||
dist.latest_filetype = typ
|
||||
return dist
|
||||
|
||||
for dist in map_multithread(latest_info, packages):
|
||||
if dist is not None:
|
||||
yield dist
|
||||
|
||||
def output_package_listing(self, packages, options):
|
||||
# type: (List[Distribution], Values) -> None
|
||||
packages = sorted(
|
||||
packages,
|
||||
key=lambda dist: dist.project_name.lower(),
|
||||
)
|
||||
if options.list_format == 'columns' and packages:
|
||||
data, header = format_for_columns(packages, options)
|
||||
self.output_package_listing_columns(data, header)
|
||||
elif options.list_format == 'freeze':
|
||||
for dist in packages:
|
||||
if options.verbose >= 1:
|
||||
write_output("%s==%s (%s)", dist.project_name,
|
||||
dist.version, dist.location)
|
||||
else:
|
||||
write_output("%s==%s", dist.project_name, dist.version)
|
||||
elif options.list_format == 'json':
|
||||
write_output(format_for_json(packages, options))
|
||||
|
||||
def output_package_listing_columns(self, data, header):
|
||||
# type: (List[List[str]], List[str]) -> None
|
||||
# insert the header first: we need to know the size of column names
|
||||
if len(data) > 0:
|
||||
data.insert(0, header)
|
||||
|
||||
pkg_strings, sizes = tabulate(data)
|
||||
|
||||
# Create and add a separator.
|
||||
if len(data) > 0:
|
||||
pkg_strings.insert(1, " ".join(map(lambda x: '-' * x, sizes)))
|
||||
|
||||
for val in pkg_strings:
|
||||
write_output(val)
|
||||
|
||||
|
||||
def format_for_columns(pkgs, options):
|
||||
# type: (List[Distribution], Values) -> Tuple[List[List[str]], List[str]]
|
||||
"""
|
||||
Convert the package data into something usable
|
||||
by output_package_listing_columns.
|
||||
"""
|
||||
running_outdated = options.outdated
|
||||
# Adjust the header for the `pip list --outdated` case.
|
||||
if running_outdated:
|
||||
header = ["Package", "Version", "Latest", "Type"]
|
||||
else:
|
||||
header = ["Package", "Version"]
|
||||
|
||||
data = []
|
||||
if options.verbose >= 1 or any(dist_is_editable(x) for x in pkgs):
|
||||
header.append("Location")
|
||||
if options.verbose >= 1:
|
||||
header.append("Installer")
|
||||
|
||||
for proj in pkgs:
|
||||
# if we're working on the 'outdated' list, separate out the
|
||||
# latest_version and type
|
||||
row = [proj.project_name, proj.version]
|
||||
|
||||
if running_outdated:
|
||||
row.append(proj.latest_version)
|
||||
row.append(proj.latest_filetype)
|
||||
|
||||
if options.verbose >= 1 or dist_is_editable(proj):
|
||||
row.append(proj.location)
|
||||
if options.verbose >= 1:
|
||||
row.append(get_installer(proj))
|
||||
|
||||
data.append(row)
|
||||
|
||||
return data, header
|
||||
|
||||
|
||||
def format_for_json(packages, options):
|
||||
# type: (List[Distribution], Values) -> str
|
||||
data = []
|
||||
for dist in packages:
|
||||
info = {
|
||||
'name': dist.project_name,
|
||||
'version': six.text_type(dist.version),
|
||||
}
|
||||
if options.verbose >= 1:
|
||||
info['location'] = dist.location
|
||||
info['installer'] = get_installer(dist)
|
||||
if options.outdated:
|
||||
info['latest_version'] = six.text_type(dist.latest_version)
|
||||
info['latest_filetype'] = dist.latest_filetype
|
||||
data.append(info)
|
||||
return json.dumps(data)
|
160
venv/Lib/site-packages/pip/_internal/commands/search.py
Normal file
160
venv/Lib/site-packages/pip/_internal/commands/search.py
Normal file
|
@ -0,0 +1,160 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import textwrap
|
||||
from collections import OrderedDict
|
||||
|
||||
from pip._vendor import pkg_resources
|
||||
from pip._vendor.packaging.version import parse as parse_version
|
||||
# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is
|
||||
# why we ignore the type on this import
|
||||
from pip._vendor.six.moves import xmlrpc_client # type: ignore
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.req_command import SessionCommandMixin
|
||||
from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS
|
||||
from pip._internal.exceptions import CommandError
|
||||
from pip._internal.models.index import PyPI
|
||||
from pip._internal.network.xmlrpc import PipXmlrpcTransport
|
||||
from pip._internal.utils.compat import get_terminal_size
|
||||
from pip._internal.utils.logging import indent_log
|
||||
from pip._internal.utils.misc import get_distribution, write_output
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from optparse import Values
|
||||
from typing import List, Dict, Optional
|
||||
from typing_extensions import TypedDict
|
||||
TransformedHit = TypedDict(
|
||||
'TransformedHit',
|
||||
{'name': str, 'summary': str, 'versions': List[str]},
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SearchCommand(Command, SessionCommandMixin):
|
||||
"""Search for PyPI packages whose name or summary contains <query>."""
|
||||
|
||||
usage = """
|
||||
%prog [options] <query>"""
|
||||
ignore_require_venv = True
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
self.cmd_opts.add_option(
|
||||
'-i', '--index',
|
||||
dest='index',
|
||||
metavar='URL',
|
||||
default=PyPI.pypi_url,
|
||||
help='Base URL of Python Package Index (default %default)')
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
if not args:
|
||||
raise CommandError('Missing required argument (search query).')
|
||||
query = args
|
||||
pypi_hits = self.search(query, options)
|
||||
hits = transform_hits(pypi_hits)
|
||||
|
||||
terminal_width = None
|
||||
if sys.stdout.isatty():
|
||||
terminal_width = get_terminal_size()[0]
|
||||
|
||||
print_results(hits, terminal_width=terminal_width)
|
||||
if pypi_hits:
|
||||
return SUCCESS
|
||||
return NO_MATCHES_FOUND
|
||||
|
||||
def search(self, query, options):
|
||||
# type: (List[str], Values) -> List[Dict[str, str]]
|
||||
index_url = options.index
|
||||
|
||||
session = self.get_default_session(options)
|
||||
|
||||
transport = PipXmlrpcTransport(index_url, session)
|
||||
pypi = xmlrpc_client.ServerProxy(index_url, transport)
|
||||
hits = pypi.search({'name': query, 'summary': query}, 'or')
|
||||
return hits
|
||||
|
||||
|
||||
def transform_hits(hits):
|
||||
# type: (List[Dict[str, str]]) -> List[TransformedHit]
|
||||
"""
|
||||
The list from pypi is really a list of versions. We want a list of
|
||||
packages with the list of versions stored inline. This converts the
|
||||
list from pypi into one we can use.
|
||||
"""
|
||||
packages = OrderedDict() # type: OrderedDict[str, TransformedHit]
|
||||
for hit in hits:
|
||||
name = hit['name']
|
||||
summary = hit['summary']
|
||||
version = hit['version']
|
||||
|
||||
if name not in packages.keys():
|
||||
packages[name] = {
|
||||
'name': name,
|
||||
'summary': summary,
|
||||
'versions': [version],
|
||||
}
|
||||
else:
|
||||
packages[name]['versions'].append(version)
|
||||
|
||||
# if this is the highest version, replace summary and score
|
||||
if version == highest_version(packages[name]['versions']):
|
||||
packages[name]['summary'] = summary
|
||||
|
||||
return list(packages.values())
|
||||
|
||||
|
||||
def print_results(hits, name_column_width=None, terminal_width=None):
|
||||
# type: (List[TransformedHit], Optional[int], Optional[int]) -> None
|
||||
if not hits:
|
||||
return
|
||||
if name_column_width is None:
|
||||
name_column_width = max([
|
||||
len(hit['name']) + len(highest_version(hit.get('versions', ['-'])))
|
||||
for hit in hits
|
||||
]) + 4
|
||||
|
||||
installed_packages = [p.project_name for p in pkg_resources.working_set]
|
||||
for hit in hits:
|
||||
name = hit['name']
|
||||
summary = hit['summary'] or ''
|
||||
latest = highest_version(hit.get('versions', ['-']))
|
||||
if terminal_width is not None:
|
||||
target_width = terminal_width - name_column_width - 5
|
||||
if target_width > 10:
|
||||
# wrap and indent summary to fit terminal
|
||||
summary_lines = textwrap.wrap(summary, target_width)
|
||||
summary = ('\n' + ' ' * (name_column_width + 3)).join(
|
||||
summary_lines)
|
||||
|
||||
line = '{name_latest:{name_column_width}} - {summary}'.format(
|
||||
name_latest='{name} ({latest})'.format(**locals()),
|
||||
**locals())
|
||||
try:
|
||||
write_output(line)
|
||||
if name in installed_packages:
|
||||
dist = get_distribution(name)
|
||||
assert dist is not None
|
||||
with indent_log():
|
||||
if dist.version == latest:
|
||||
write_output('INSTALLED: %s (latest)', dist.version)
|
||||
else:
|
||||
write_output('INSTALLED: %s', dist.version)
|
||||
if parse_version(latest).pre:
|
||||
write_output('LATEST: %s (pre-release; install'
|
||||
' with "pip install --pre")', latest)
|
||||
else:
|
||||
write_output('LATEST: %s', latest)
|
||||
except UnicodeEncodeError:
|
||||
pass
|
||||
|
||||
|
||||
def highest_version(versions):
|
||||
# type: (List[str]) -> str
|
||||
return max(versions, key=parse_version)
|
186
venv/Lib/site-packages/pip/_internal/commands/show.py
Normal file
186
venv/Lib/site-packages/pip/_internal/commands/show.py
Normal file
|
@ -0,0 +1,186 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import os
|
||||
from email.parser import FeedParser
|
||||
|
||||
from pip._vendor import pkg_resources
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.status_codes import ERROR, SUCCESS
|
||||
from pip._internal.utils.misc import write_output
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from optparse import Values
|
||||
from typing import List, Dict, Iterator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ShowCommand(Command):
|
||||
"""
|
||||
Show information about one or more installed packages.
|
||||
|
||||
The output is in RFC-compliant mail header format.
|
||||
"""
|
||||
|
||||
usage = """
|
||||
%prog [options] <package> ..."""
|
||||
ignore_require_venv = True
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
self.cmd_opts.add_option(
|
||||
'-f', '--files',
|
||||
dest='files',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Show the full list of installed files for each package.')
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
if not args:
|
||||
logger.warning('ERROR: Please provide a package name or names.')
|
||||
return ERROR
|
||||
query = args
|
||||
|
||||
results = search_packages_info(query)
|
||||
if not print_results(
|
||||
results, list_files=options.files, verbose=options.verbose):
|
||||
return ERROR
|
||||
return SUCCESS
|
||||
|
||||
|
||||
def search_packages_info(query):
|
||||
# type: (List[str]) -> Iterator[Dict[str, str]]
|
||||
"""
|
||||
Gather details from installed distributions. Print distribution name,
|
||||
version, location, and installed files. Installed files requires a
|
||||
pip generated 'installed-files.txt' in the distributions '.egg-info'
|
||||
directory.
|
||||
"""
|
||||
installed = {}
|
||||
for p in pkg_resources.working_set:
|
||||
installed[canonicalize_name(p.project_name)] = p
|
||||
|
||||
query_names = [canonicalize_name(name) for name in query]
|
||||
missing = sorted(
|
||||
[name for name, pkg in zip(query, query_names) if pkg not in installed]
|
||||
)
|
||||
if missing:
|
||||
logger.warning('Package(s) not found: %s', ', '.join(missing))
|
||||
|
||||
def get_requiring_packages(package_name):
|
||||
# type: (str) -> List[str]
|
||||
canonical_name = canonicalize_name(package_name)
|
||||
return [
|
||||
pkg.project_name for pkg in pkg_resources.working_set
|
||||
if canonical_name in
|
||||
[canonicalize_name(required.name) for required in
|
||||
pkg.requires()]
|
||||
]
|
||||
|
||||
for dist in [installed[pkg] for pkg in query_names if pkg in installed]:
|
||||
package = {
|
||||
'name': dist.project_name,
|
||||
'version': dist.version,
|
||||
'location': dist.location,
|
||||
'requires': [dep.project_name for dep in dist.requires()],
|
||||
'required_by': get_requiring_packages(dist.project_name)
|
||||
}
|
||||
file_list = None
|
||||
metadata = ''
|
||||
if isinstance(dist, pkg_resources.DistInfoDistribution):
|
||||
# RECORDs should be part of .dist-info metadatas
|
||||
if dist.has_metadata('RECORD'):
|
||||
lines = dist.get_metadata_lines('RECORD')
|
||||
paths = [line.split(',')[0] for line in lines]
|
||||
paths = [os.path.join(dist.location, p) for p in paths]
|
||||
file_list = [os.path.relpath(p, dist.location) for p in paths]
|
||||
|
||||
if dist.has_metadata('METADATA'):
|
||||
metadata = dist.get_metadata('METADATA')
|
||||
else:
|
||||
# Otherwise use pip's log for .egg-info's
|
||||
if dist.has_metadata('installed-files.txt'):
|
||||
paths = dist.get_metadata_lines('installed-files.txt')
|
||||
paths = [os.path.join(dist.egg_info, p) for p in paths]
|
||||
file_list = [os.path.relpath(p, dist.location) for p in paths]
|
||||
|
||||
if dist.has_metadata('PKG-INFO'):
|
||||
metadata = dist.get_metadata('PKG-INFO')
|
||||
|
||||
if dist.has_metadata('entry_points.txt'):
|
||||
entry_points = dist.get_metadata_lines('entry_points.txt')
|
||||
package['entry_points'] = entry_points
|
||||
|
||||
if dist.has_metadata('INSTALLER'):
|
||||
for line in dist.get_metadata_lines('INSTALLER'):
|
||||
if line.strip():
|
||||
package['installer'] = line.strip()
|
||||
break
|
||||
|
||||
# @todo: Should pkg_resources.Distribution have a
|
||||
# `get_pkg_info` method?
|
||||
feed_parser = FeedParser()
|
||||
feed_parser.feed(metadata)
|
||||
pkg_info_dict = feed_parser.close()
|
||||
for key in ('metadata-version', 'summary',
|
||||
'home-page', 'author', 'author-email', 'license'):
|
||||
package[key] = pkg_info_dict.get(key)
|
||||
|
||||
# It looks like FeedParser cannot deal with repeated headers
|
||||
classifiers = []
|
||||
for line in metadata.splitlines():
|
||||
if line.startswith('Classifier: '):
|
||||
classifiers.append(line[len('Classifier: '):])
|
||||
package['classifiers'] = classifiers
|
||||
|
||||
if file_list:
|
||||
package['files'] = sorted(file_list)
|
||||
yield package
|
||||
|
||||
|
||||
def print_results(distributions, list_files=False, verbose=False):
|
||||
# type: (Iterator[Dict[str, str]], bool, bool) -> bool
|
||||
"""
|
||||
Print the information from installed distributions found.
|
||||
"""
|
||||
results_printed = False
|
||||
for i, dist in enumerate(distributions):
|
||||
results_printed = True
|
||||
if i > 0:
|
||||
write_output("---")
|
||||
|
||||
write_output("Name: %s", dist.get('name', ''))
|
||||
write_output("Version: %s", dist.get('version', ''))
|
||||
write_output("Summary: %s", dist.get('summary', ''))
|
||||
write_output("Home-page: %s", dist.get('home-page', ''))
|
||||
write_output("Author: %s", dist.get('author', ''))
|
||||
write_output("Author-email: %s", dist.get('author-email', ''))
|
||||
write_output("License: %s", dist.get('license', ''))
|
||||
write_output("Location: %s", dist.get('location', ''))
|
||||
write_output("Requires: %s", ', '.join(dist.get('requires', [])))
|
||||
write_output("Required-by: %s", ', '.join(dist.get('required_by', [])))
|
||||
|
||||
if verbose:
|
||||
write_output("Metadata-Version: %s",
|
||||
dist.get('metadata-version', ''))
|
||||
write_output("Installer: %s", dist.get('installer', ''))
|
||||
write_output("Classifiers:")
|
||||
for classifier in dist.get('classifiers', []):
|
||||
write_output(" %s", classifier)
|
||||
write_output("Entry-points:")
|
||||
for entry in dist.get('entry_points', []):
|
||||
write_output(" %s", entry.strip())
|
||||
if list_files:
|
||||
write_output("Files:")
|
||||
for line in dist.get('files', []):
|
||||
write_output(" %s", line.strip())
|
||||
if "files" not in dist:
|
||||
write_output("Cannot locate installed-files.txt")
|
||||
return results_printed
|
95
venv/Lib/site-packages/pip/_internal/commands/uninstall.py
Normal file
95
venv/Lib/site-packages/pip/_internal/commands/uninstall.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.req_command import SessionCommandMixin
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.exceptions import InstallationError
|
||||
from pip._internal.req import parse_requirements
|
||||
from pip._internal.req.constructors import (
|
||||
install_req_from_line,
|
||||
install_req_from_parsed_requirement,
|
||||
)
|
||||
from pip._internal.utils.misc import protect_pip_from_modification_on_windows
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from optparse import Values
|
||||
from typing import List
|
||||
|
||||
|
||||
class UninstallCommand(Command, SessionCommandMixin):
|
||||
"""
|
||||
Uninstall packages.
|
||||
|
||||
pip is able to uninstall most installed packages. Known exceptions are:
|
||||
|
||||
- Pure distutils packages installed with ``python setup.py install``, which
|
||||
leave behind no metadata to determine what files were installed.
|
||||
- Script wrappers installed by ``python setup.py develop``.
|
||||
"""
|
||||
|
||||
usage = """
|
||||
%prog [options] <package> ...
|
||||
%prog [options] -r <requirements file> ..."""
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
self.cmd_opts.add_option(
|
||||
'-r', '--requirement',
|
||||
dest='requirements',
|
||||
action='append',
|
||||
default=[],
|
||||
metavar='file',
|
||||
help='Uninstall all the packages listed in the given requirements '
|
||||
'file. This option can be used multiple times.',
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
'-y', '--yes',
|
||||
dest='yes',
|
||||
action='store_true',
|
||||
help="Don't ask for confirmation of uninstall deletions.")
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
session = self.get_default_session(options)
|
||||
|
||||
reqs_to_uninstall = {}
|
||||
for name in args:
|
||||
req = install_req_from_line(
|
||||
name, isolated=options.isolated_mode,
|
||||
)
|
||||
if req.name:
|
||||
reqs_to_uninstall[canonicalize_name(req.name)] = req
|
||||
for filename in options.requirements:
|
||||
for parsed_req in parse_requirements(
|
||||
filename,
|
||||
options=options,
|
||||
session=session):
|
||||
req = install_req_from_parsed_requirement(
|
||||
parsed_req,
|
||||
isolated=options.isolated_mode
|
||||
)
|
||||
if req.name:
|
||||
reqs_to_uninstall[canonicalize_name(req.name)] = req
|
||||
if not reqs_to_uninstall:
|
||||
raise InstallationError(
|
||||
'You must give at least one requirement to {self.name} (see '
|
||||
'"pip help {self.name}")'.format(**locals())
|
||||
)
|
||||
|
||||
protect_pip_from_modification_on_windows(
|
||||
modifying_pip="pip" in reqs_to_uninstall
|
||||
)
|
||||
|
||||
for req in reqs_to_uninstall.values():
|
||||
uninstall_pathset = req.uninstall(
|
||||
auto_confirm=options.yes, verbose=self.verbosity > 0,
|
||||
)
|
||||
if uninstall_pathset:
|
||||
uninstall_pathset.commit()
|
||||
|
||||
return SUCCESS
|
188
venv/Lib/site-packages/pip/_internal/commands/wheel.py
Normal file
188
venv/Lib/site-packages/pip/_internal/commands/wheel.py
Normal file
|
@ -0,0 +1,188 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from pip._internal.cache import WheelCache
|
||||
from pip._internal.cli import cmdoptions
|
||||
from pip._internal.cli.req_command import RequirementCommand, with_cleanup
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.exceptions import CommandError
|
||||
from pip._internal.req.req_tracker import get_requirement_tracker
|
||||
from pip._internal.utils.misc import ensure_dir, normalize_path
|
||||
from pip._internal.utils.temp_dir import TempDirectory
|
||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||
from pip._internal.wheel_builder import build, should_build_for_wheel_command
|
||||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from optparse import Values
|
||||
from typing import List
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class WheelCommand(RequirementCommand):
|
||||
"""
|
||||
Build Wheel archives for your requirements and dependencies.
|
||||
|
||||
Wheel is a built-package format, and offers the advantage of not
|
||||
recompiling your software during every install. For more details, see the
|
||||
wheel docs: https://wheel.readthedocs.io/en/latest/
|
||||
|
||||
Requirements: setuptools>=0.8, and wheel.
|
||||
|
||||
'pip wheel' uses the bdist_wheel setuptools extension from the wheel
|
||||
package to build individual wheels.
|
||||
|
||||
"""
|
||||
|
||||
usage = """
|
||||
%prog [options] <requirement specifier> ...
|
||||
%prog [options] -r <requirements file> ...
|
||||
%prog [options] [-e] <vcs project url> ...
|
||||
%prog [options] [-e] <local project path> ...
|
||||
%prog [options] <archive url/path> ..."""
|
||||
|
||||
def add_options(self):
|
||||
# type: () -> None
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'-w', '--wheel-dir',
|
||||
dest='wheel_dir',
|
||||
metavar='dir',
|
||||
default=os.curdir,
|
||||
help=("Build wheels into <dir>, where the default is the "
|
||||
"current working directory."),
|
||||
)
|
||||
self.cmd_opts.add_option(cmdoptions.no_binary())
|
||||
self.cmd_opts.add_option(cmdoptions.only_binary())
|
||||
self.cmd_opts.add_option(cmdoptions.prefer_binary())
|
||||
self.cmd_opts.add_option(
|
||||
'--build-option',
|
||||
dest='build_options',
|
||||
metavar='options',
|
||||
action='append',
|
||||
help="Extra arguments to be supplied to 'setup.py bdist_wheel'.",
|
||||
)
|
||||
self.cmd_opts.add_option(cmdoptions.no_build_isolation())
|
||||
self.cmd_opts.add_option(cmdoptions.use_pep517())
|
||||
self.cmd_opts.add_option(cmdoptions.no_use_pep517())
|
||||
self.cmd_opts.add_option(cmdoptions.constraints())
|
||||
self.cmd_opts.add_option(cmdoptions.editable())
|
||||
self.cmd_opts.add_option(cmdoptions.requirements())
|
||||
self.cmd_opts.add_option(cmdoptions.src())
|
||||
self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
|
||||
self.cmd_opts.add_option(cmdoptions.no_deps())
|
||||
self.cmd_opts.add_option(cmdoptions.build_dir())
|
||||
self.cmd_opts.add_option(cmdoptions.progress_bar())
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'--global-option',
|
||||
dest='global_options',
|
||||
action='append',
|
||||
metavar='options',
|
||||
help="Extra global options to be supplied to the setup.py "
|
||||
"call before the 'bdist_wheel' command.")
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
'--pre',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=("Include pre-release and development versions. By default, "
|
||||
"pip only finds stable versions."),
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(cmdoptions.require_hashes())
|
||||
|
||||
index_opts = cmdoptions.make_option_group(
|
||||
cmdoptions.index_group,
|
||||
self.parser,
|
||||
)
|
||||
|
||||
self.parser.insert_option_group(0, index_opts)
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
@with_cleanup
|
||||
def run(self, options, args):
|
||||
# type: (Values, List[str]) -> int
|
||||
cmdoptions.check_install_build_global(options)
|
||||
|
||||
session = self.get_default_session(options)
|
||||
|
||||
finder = self._build_package_finder(options, session)
|
||||
build_delete = (not (options.no_clean or options.build_dir))
|
||||
wheel_cache = WheelCache(options.cache_dir, options.format_control)
|
||||
|
||||
options.wheel_dir = normalize_path(options.wheel_dir)
|
||||
ensure_dir(options.wheel_dir)
|
||||
|
||||
req_tracker = self.enter_context(get_requirement_tracker())
|
||||
|
||||
directory = TempDirectory(
|
||||
options.build_dir,
|
||||
delete=build_delete,
|
||||
kind="wheel",
|
||||
globally_managed=True,
|
||||
)
|
||||
|
||||
reqs = self.get_requirements(args, options, finder, session)
|
||||
|
||||
preparer = self.make_requirement_preparer(
|
||||
temp_build_dir=directory,
|
||||
options=options,
|
||||
req_tracker=req_tracker,
|
||||
session=session,
|
||||
finder=finder,
|
||||
wheel_download_dir=options.wheel_dir,
|
||||
use_user_site=False,
|
||||
)
|
||||
|
||||
resolver = self.make_resolver(
|
||||
preparer=preparer,
|
||||
finder=finder,
|
||||
options=options,
|
||||
wheel_cache=wheel_cache,
|
||||
ignore_requires_python=options.ignore_requires_python,
|
||||
use_pep517=options.use_pep517,
|
||||
)
|
||||
|
||||
self.trace_basic_info(finder)
|
||||
|
||||
requirement_set = resolver.resolve(
|
||||
reqs, check_supported_wheels=True
|
||||
)
|
||||
|
||||
reqs_to_build = [
|
||||
r for r in requirement_set.requirements.values()
|
||||
if should_build_for_wheel_command(r)
|
||||
]
|
||||
|
||||
# build wheels
|
||||
build_successes, build_failures = build(
|
||||
reqs_to_build,
|
||||
wheel_cache=wheel_cache,
|
||||
build_options=options.build_options or [],
|
||||
global_options=options.global_options or [],
|
||||
)
|
||||
for req in build_successes:
|
||||
assert req.link and req.link.is_wheel
|
||||
assert req.local_file_path
|
||||
# copy from cache to target directory
|
||||
try:
|
||||
shutil.copy(req.local_file_path, options.wheel_dir)
|
||||
except OSError as e:
|
||||
logger.warning(
|
||||
"Building wheel for %s failed: %s",
|
||||
req.name, e,
|
||||
)
|
||||
build_failures.append(req)
|
||||
if len(build_failures) != 0:
|
||||
raise CommandError(
|
||||
"Failed to build one or more wheels"
|
||||
)
|
||||
|
||||
return SUCCESS
|
Loading…
Add table
Add a link
Reference in a new issue