mirror of
https://github.com/pre-commit/pre-commit-hooks.git
synced 2026-04-16 00:20:13 +00:00
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
This commit is contained in:
parent
72ad6dc953
commit
f4cd1ba0d6
813 changed files with 66015 additions and 58839 deletions
|
|
@ -1,14 +1,17 @@
|
|||
"""
|
||||
Package containing all pip commands
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
from collections import namedtuple
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import Optional
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
|
||||
CommandInfo = namedtuple("CommandInfo", "module_path, class_name, summary")
|
||||
CommandInfo = namedtuple('CommandInfo', 'module_path, class_name, summary')
|
||||
|
||||
# This dictionary does a bunch of heavy lifting for help output:
|
||||
# - Enables avoiding additional (costly) imports for presenting `--help`.
|
||||
|
|
@ -17,86 +20,86 @@ CommandInfo = namedtuple("CommandInfo", "module_path, class_name, summary")
|
|||
# Even though the module path starts with the same "pip._internal.commands"
|
||||
# prefix, the full path makes testing easier (specifically when modifying
|
||||
# `commands_dict` in test setup / teardown).
|
||||
commands_dict: Dict[str, CommandInfo] = {
|
||||
"install": CommandInfo(
|
||||
"pip._internal.commands.install",
|
||||
"InstallCommand",
|
||||
"Install packages.",
|
||||
commands_dict: dict[str, CommandInfo] = {
|
||||
'install': CommandInfo(
|
||||
'pip._internal.commands.install',
|
||||
'InstallCommand',
|
||||
'Install packages.',
|
||||
),
|
||||
"download": CommandInfo(
|
||||
"pip._internal.commands.download",
|
||||
"DownloadCommand",
|
||||
"Download packages.",
|
||||
'download': CommandInfo(
|
||||
'pip._internal.commands.download',
|
||||
'DownloadCommand',
|
||||
'Download packages.',
|
||||
),
|
||||
"uninstall": CommandInfo(
|
||||
"pip._internal.commands.uninstall",
|
||||
"UninstallCommand",
|
||||
"Uninstall packages.",
|
||||
'uninstall': CommandInfo(
|
||||
'pip._internal.commands.uninstall',
|
||||
'UninstallCommand',
|
||||
'Uninstall packages.',
|
||||
),
|
||||
"freeze": CommandInfo(
|
||||
"pip._internal.commands.freeze",
|
||||
"FreezeCommand",
|
||||
"Output installed packages in requirements format.",
|
||||
'freeze': CommandInfo(
|
||||
'pip._internal.commands.freeze',
|
||||
'FreezeCommand',
|
||||
'Output installed packages in requirements format.',
|
||||
),
|
||||
"list": CommandInfo(
|
||||
"pip._internal.commands.list",
|
||||
"ListCommand",
|
||||
"List installed packages.",
|
||||
'list': CommandInfo(
|
||||
'pip._internal.commands.list',
|
||||
'ListCommand',
|
||||
'List installed packages.',
|
||||
),
|
||||
"show": CommandInfo(
|
||||
"pip._internal.commands.show",
|
||||
"ShowCommand",
|
||||
"Show information about 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.",
|
||||
'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.",
|
||||
'config': CommandInfo(
|
||||
'pip._internal.commands.configuration',
|
||||
'ConfigurationCommand',
|
||||
'Manage local and global configuration.',
|
||||
),
|
||||
"search": CommandInfo(
|
||||
"pip._internal.commands.search",
|
||||
"SearchCommand",
|
||||
"Search PyPI for packages.",
|
||||
'search': CommandInfo(
|
||||
'pip._internal.commands.search',
|
||||
'SearchCommand',
|
||||
'Search PyPI for packages.',
|
||||
),
|
||||
"cache": CommandInfo(
|
||||
"pip._internal.commands.cache",
|
||||
"CacheCommand",
|
||||
'cache': CommandInfo(
|
||||
'pip._internal.commands.cache',
|
||||
'CacheCommand',
|
||||
"Inspect and manage pip's wheel cache.",
|
||||
),
|
||||
"index": CommandInfo(
|
||||
"pip._internal.commands.index",
|
||||
"IndexCommand",
|
||||
"Inspect information available from package indexes.",
|
||||
'index': CommandInfo(
|
||||
'pip._internal.commands.index',
|
||||
'IndexCommand',
|
||||
'Inspect information available from package indexes.',
|
||||
),
|
||||
"wheel": CommandInfo(
|
||||
"pip._internal.commands.wheel",
|
||||
"WheelCommand",
|
||||
"Build wheels from your requirements.",
|
||||
'wheel': CommandInfo(
|
||||
'pip._internal.commands.wheel',
|
||||
'WheelCommand',
|
||||
'Build wheels from your requirements.',
|
||||
),
|
||||
"hash": CommandInfo(
|
||||
"pip._internal.commands.hash",
|
||||
"HashCommand",
|
||||
"Compute hashes of package archives.",
|
||||
'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.",
|
||||
'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.",
|
||||
'debug': CommandInfo(
|
||||
'pip._internal.commands.debug',
|
||||
'DebugCommand',
|
||||
'Show information useful for debugging.',
|
||||
),
|
||||
"help": CommandInfo(
|
||||
"pip._internal.commands.help",
|
||||
"HelpCommand",
|
||||
"Show help for commands.",
|
||||
'help': CommandInfo(
|
||||
'pip._internal.commands.help',
|
||||
'HelpCommand',
|
||||
'Show help for commands.',
|
||||
),
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +116,7 @@ def create_command(name: str, **kwargs: Any) -> Command:
|
|||
return command
|
||||
|
||||
|
||||
def get_similar_commands(name: str) -> Optional[str]:
|
||||
def get_similar_commands(name: str) -> str | None:
|
||||
"""Command name auto-correct."""
|
||||
from difflib import get_close_matches
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import textwrap
|
||||
from optparse import Values
|
||||
from typing import Any, List
|
||||
from typing import Any
|
||||
from typing import List
|
||||
|
||||
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.cli.status_codes import ERROR
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.exceptions import CommandError
|
||||
from pip._internal.exceptions import PipError
|
||||
from pip._internal.utils.logging import getLogger
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
|
@ -39,34 +44,34 @@ class CacheCommand(Command):
|
|||
def add_options(self) -> None:
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"--format",
|
||||
action="store",
|
||||
dest="list_format",
|
||||
default="human",
|
||||
choices=("human", "abspath"),
|
||||
help="Select the output format among: human (default) or abspath",
|
||||
'--format',
|
||||
action='store',
|
||||
dest='list_format',
|
||||
default='human',
|
||||
choices=('human', 'abspath'),
|
||||
help='Select the output format among: human (default) or abspath',
|
||||
)
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> 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,
|
||||
'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.")
|
||||
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)),
|
||||
'Need an action (%s) to perform.',
|
||||
', '.join(sorted(handlers)),
|
||||
)
|
||||
return ERROR
|
||||
|
||||
|
|
@ -81,21 +86,21 @@ class CacheCommand(Command):
|
|||
|
||||
return SUCCESS
|
||||
|
||||
def get_cache_dir(self, options: Values, args: List[Any]) -> None:
|
||||
def get_cache_dir(self, options: Values, args: list[Any]) -> None:
|
||||
if args:
|
||||
raise CommandError("Too many arguments")
|
||||
raise CommandError('Too many arguments')
|
||||
|
||||
logger.info(options.cache_dir)
|
||||
|
||||
def get_cache_info(self, options: Values, args: List[Any]) -> None:
|
||||
def get_cache_info(self, options: Values, args: list[Any]) -> None:
|
||||
if args:
|
||||
raise CommandError("Too many arguments")
|
||||
raise CommandError('Too many arguments')
|
||||
|
||||
num_http_files = len(self._find_http_files(options))
|
||||
num_packages = len(self._find_wheels(options, "*"))
|
||||
num_packages = len(self._find_wheels(options, '*'))
|
||||
|
||||
http_cache_location = self._cache_dir(options, "http")
|
||||
wheels_cache_location = self._cache_dir(options, "wheels")
|
||||
http_cache_location = self._cache_dir(options, 'http')
|
||||
wheels_cache_location = self._cache_dir(options, 'wheels')
|
||||
http_cache_size = filesystem.format_directory_size(http_cache_location)
|
||||
wheels_cache_size = filesystem.format_directory_size(wheels_cache_location)
|
||||
|
||||
|
|
@ -108,7 +113,7 @@ class CacheCommand(Command):
|
|||
Wheels location: {wheels_cache_location}
|
||||
Wheels size: {wheels_cache_size}
|
||||
Number of wheels: {package_count}
|
||||
"""
|
||||
""",
|
||||
)
|
||||
.format(
|
||||
http_cache_location=http_cache_location,
|
||||
|
|
@ -123,35 +128,35 @@ class CacheCommand(Command):
|
|||
|
||||
logger.info(message)
|
||||
|
||||
def list_cache_items(self, options: Values, args: List[Any]) -> None:
|
||||
def list_cache_items(self, options: Values, args: list[Any]) -> None:
|
||||
if len(args) > 1:
|
||||
raise CommandError("Too many arguments")
|
||||
raise CommandError('Too many arguments')
|
||||
|
||||
if args:
|
||||
pattern = args[0]
|
||||
else:
|
||||
pattern = "*"
|
||||
pattern = '*'
|
||||
|
||||
files = self._find_wheels(options, pattern)
|
||||
if options.list_format == "human":
|
||||
if options.list_format == 'human':
|
||||
self.format_for_human(files)
|
||||
else:
|
||||
self.format_for_abspath(files)
|
||||
|
||||
def format_for_human(self, files: List[str]) -> None:
|
||||
def format_for_human(self, files: list[str]) -> None:
|
||||
if not files:
|
||||
logger.info("Nothing cached.")
|
||||
logger.info('Nothing cached.')
|
||||
return
|
||||
|
||||
results = []
|
||||
for filename in files:
|
||||
wheel = os.path.basename(filename)
|
||||
size = filesystem.format_file_size(filename)
|
||||
results.append(f" - {wheel} ({size})")
|
||||
logger.info("Cache contents:\n")
|
||||
logger.info("\n".join(sorted(results)))
|
||||
results.append(f' - {wheel} ({size})')
|
||||
logger.info('Cache contents:\n')
|
||||
logger.info('\n'.join(sorted(results)))
|
||||
|
||||
def format_for_abspath(self, files: List[str]) -> None:
|
||||
def format_for_abspath(self, files: list[str]) -> None:
|
||||
if not files:
|
||||
return
|
||||
|
||||
|
|
@ -159,48 +164,48 @@ class CacheCommand(Command):
|
|||
for filename in files:
|
||||
results.append(filename)
|
||||
|
||||
logger.info("\n".join(sorted(results)))
|
||||
logger.info('\n'.join(sorted(results)))
|
||||
|
||||
def remove_cache_items(self, options: Values, args: List[Any]) -> None:
|
||||
def remove_cache_items(self, options: Values, args: list[Any]) -> None:
|
||||
if len(args) > 1:
|
||||
raise CommandError("Too many arguments")
|
||||
raise CommandError('Too many arguments')
|
||||
|
||||
if not args:
|
||||
raise CommandError("Please provide a pattern")
|
||||
raise CommandError('Please provide a pattern')
|
||||
|
||||
files = self._find_wheels(options, args[0])
|
||||
|
||||
no_matching_msg = "No matching packages"
|
||||
if args[0] == "*":
|
||||
no_matching_msg = 'No matching packages'
|
||||
if args[0] == '*':
|
||||
# Only fetch http files if no specific pattern given
|
||||
files += self._find_http_files(options)
|
||||
else:
|
||||
# Add the pattern to the log message
|
||||
no_matching_msg += ' for pattern "{}"'.format(args[0])
|
||||
no_matching_msg += f' for pattern "{args[0]}"'
|
||||
|
||||
if not files:
|
||||
logger.warning(no_matching_msg)
|
||||
|
||||
for filename in files:
|
||||
os.unlink(filename)
|
||||
logger.verbose("Removed %s", filename)
|
||||
logger.info("Files removed: %s", len(files))
|
||||
logger.verbose('Removed %s', filename)
|
||||
logger.info('Files removed: %s', len(files))
|
||||
|
||||
def purge_cache(self, options: Values, args: List[Any]) -> None:
|
||||
def purge_cache(self, options: Values, args: list[Any]) -> None:
|
||||
if args:
|
||||
raise CommandError("Too many arguments")
|
||||
raise CommandError('Too many arguments')
|
||||
|
||||
return self.remove_cache_items(options, ["*"])
|
||||
return self.remove_cache_items(options, ['*'])
|
||||
|
||||
def _cache_dir(self, options: Values, subdir: str) -> str:
|
||||
return os.path.join(options.cache_dir, subdir)
|
||||
|
||||
def _find_http_files(self, options: Values) -> List[str]:
|
||||
http_dir = self._cache_dir(options, "http")
|
||||
return filesystem.find_files(http_dir, "*")
|
||||
def _find_http_files(self, options: Values) -> list[str]:
|
||||
http_dir = self._cache_dir(options, 'http')
|
||||
return filesystem.find_files(http_dir, '*')
|
||||
|
||||
def _find_wheels(self, options: Values, pattern: str) -> List[str]:
|
||||
wheel_dir = self._cache_dir(options, "wheels")
|
||||
def _find_wheels(self, options: Values, pattern: str) -> list[str]:
|
||||
wheel_dir = self._cache_dir(options, 'wheels')
|
||||
|
||||
# The wheel filename format, as specified in PEP 427, is:
|
||||
# {distribution}-{version}(-{build})?-{python}-{abi}-{platform}.whl
|
||||
|
|
@ -218,6 +223,6 @@ class CacheCommand(Command):
|
|||
# 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")
|
||||
pattern = pattern + ('*.whl' if '-' in pattern else '-*.whl')
|
||||
|
||||
return filesystem.find_files(wheel_dir, pattern)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from optparse import Values
|
||||
from typing import List
|
||||
|
||||
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.cli.status_codes import ERROR
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.operations.check import check_package_set
|
||||
from pip._internal.operations.check import create_package_set_from_installed
|
||||
from pip._internal.utils.misc import write_output
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -19,7 +20,7 @@ class CheckCommand(Command):
|
|||
usage = """
|
||||
%prog [options]"""
|
||||
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
|
||||
package_set, parsing_probs = create_package_set_from_installed()
|
||||
missing, conflicting = check_package_set(package_set)
|
||||
|
|
@ -28,7 +29,7 @@ class CheckCommand(Command):
|
|||
version = package_set[project_name].version
|
||||
for dependency in missing[project_name]:
|
||||
write_output(
|
||||
"%s %s requires %s, which is not installed.",
|
||||
'%s %s requires %s, which is not installed.',
|
||||
project_name,
|
||||
version,
|
||||
dependency[0],
|
||||
|
|
@ -38,7 +39,7 @@ class CheckCommand(Command):
|
|||
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.",
|
||||
'%s %s has requirement %s, but you have %s %s.',
|
||||
project_name,
|
||||
version,
|
||||
req,
|
||||
|
|
@ -49,5 +50,5 @@ class CheckCommand(Command):
|
|||
if missing or conflicting or parsing_probs:
|
||||
return ERROR
|
||||
else:
|
||||
write_output("No broken requirements found.")
|
||||
write_output('No broken requirements found.')
|
||||
return SUCCESS
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import textwrap
|
||||
from optparse import Values
|
||||
|
|
@ -12,7 +14,7 @@ BASE_COMPLETION = """
|
|||
"""
|
||||
|
||||
COMPLETION_SCRIPTS = {
|
||||
"bash": """
|
||||
'bash': """
|
||||
_pip_completion()
|
||||
{{
|
||||
COMPREPLY=( $( COMP_WORDS="${{COMP_WORDS[*]}}" \\
|
||||
|
|
@ -21,7 +23,7 @@ COMPLETION_SCRIPTS = {
|
|||
}}
|
||||
complete -o default -F _pip_completion {prog}
|
||||
""",
|
||||
"zsh": """
|
||||
'zsh': """
|
||||
function _pip_completion {{
|
||||
local words cword
|
||||
read -Ac words
|
||||
|
|
@ -32,7 +34,7 @@ COMPLETION_SCRIPTS = {
|
|||
}}
|
||||
compctl -K _pip_completion {prog}
|
||||
""",
|
||||
"fish": """
|
||||
'fish': """
|
||||
function __fish_complete_pip
|
||||
set -lx COMP_WORDS (commandline -o) ""
|
||||
set -lx COMP_CWORD ( \\
|
||||
|
|
@ -53,44 +55,44 @@ class CompletionCommand(Command):
|
|||
|
||||
def add_options(self) -> None:
|
||||
self.cmd_opts.add_option(
|
||||
"--bash",
|
||||
"-b",
|
||||
action="store_const",
|
||||
const="bash",
|
||||
dest="shell",
|
||||
help="Emit completion code for bash",
|
||||
'--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",
|
||||
'--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",
|
||||
'--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: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
"""Prints the completion code of the given shell"""
|
||||
shells = COMPLETION_SCRIPTS.keys()
|
||||
shell_options = ["--" + shell for shell in sorted(shells)]
|
||||
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())
|
||||
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))
|
||||
'ERROR: You must pass {}\n'.format(' or '.join(shell_options)),
|
||||
)
|
||||
return SUCCESS
|
||||
|
|
|
|||
|
|
@ -1,20 +1,24 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
from optparse import Values
|
||||
from typing import Any, List, Optional
|
||||
from typing import Any
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.status_codes import ERROR, SUCCESS
|
||||
from pip._internal.configuration import (
|
||||
Configuration,
|
||||
Kind,
|
||||
get_configuration_files,
|
||||
kinds,
|
||||
)
|
||||
from pip._internal.cli.status_codes import ERROR
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.configuration import Configuration
|
||||
from pip._internal.configuration import get_configuration_files
|
||||
from pip._internal.configuration import Kind
|
||||
from pip._internal.configuration import 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.misc import get_prog
|
||||
from pip._internal.utils.misc import write_output
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -51,57 +55,57 @@ class ConfigurationCommand(Command):
|
|||
|
||||
def add_options(self) -> None:
|
||||
self.cmd_opts.add_option(
|
||||
"--editor",
|
||||
dest="editor",
|
||||
action="store",
|
||||
'--editor',
|
||||
dest='editor',
|
||||
action='store',
|
||||
default=None,
|
||||
help=(
|
||||
"Editor to use to edit the file. Uses VISUAL or EDITOR "
|
||||
"environment variables if not provided."
|
||||
'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",
|
||||
'--global',
|
||||
dest='global_file',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="Use the system-wide configuration file only",
|
||||
help='Use the system-wide configuration file only',
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"--user",
|
||||
dest="user_file",
|
||||
action="store_true",
|
||||
'--user',
|
||||
dest='user_file',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="Use the user configuration file only",
|
||||
help='Use the user configuration file only',
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"--site",
|
||||
dest="site_file",
|
||||
action="store_true",
|
||||
'--site',
|
||||
dest='site_file',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="Use the current environment configuration file only",
|
||||
help='Use the current environment configuration file only',
|
||||
)
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: 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,
|
||||
'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)),
|
||||
'Need an action (%s) to perform.',
|
||||
', '.join(sorted(handlers)),
|
||||
)
|
||||
return ERROR
|
||||
|
||||
|
|
@ -111,7 +115,7 @@ class ConfigurationCommand(Command):
|
|||
# Depends on whether the command is modifying.
|
||||
try:
|
||||
load_only = self._determine_file(
|
||||
options, need_value=(action in ["get", "set", "unset", "edit"])
|
||||
options, need_value=(action in ['get', 'set', 'unset', 'edit']),
|
||||
)
|
||||
except PipError as e:
|
||||
logger.error(e.args[0])
|
||||
|
|
@ -119,7 +123,7 @@ class ConfigurationCommand(Command):
|
|||
|
||||
# Load a new configuration
|
||||
self.configuration = Configuration(
|
||||
isolated=options.isolated_mode, load_only=load_only
|
||||
isolated=options.isolated_mode, load_only=load_only,
|
||||
)
|
||||
self.configuration.load()
|
||||
|
||||
|
|
@ -132,7 +136,7 @@ class ConfigurationCommand(Command):
|
|||
|
||||
return SUCCESS
|
||||
|
||||
def _determine_file(self, options: Values, need_value: bool) -> Optional[Kind]:
|
||||
def _determine_file(self, options: Values, need_value: bool) -> Kind | None:
|
||||
file_options = [
|
||||
key
|
||||
for key, value in (
|
||||
|
|
@ -158,47 +162,47 @@ class ConfigurationCommand(Command):
|
|||
return file_options[0]
|
||||
|
||||
raise PipError(
|
||||
"Need exactly one file to operate upon "
|
||||
"(--user, --site, --global) to perform."
|
||||
'Need exactly one file to operate upon '
|
||||
'(--user, --site, --global) to perform.',
|
||||
)
|
||||
|
||||
def list_values(self, options: Values, args: List[str]) -> None:
|
||||
self._get_n_args(args, "list", n=0)
|
||||
def list_values(self, options: Values, args: 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)
|
||||
write_output('%s=%r', key, value)
|
||||
|
||||
def get_name(self, options: Values, args: List[str]) -> None:
|
||||
key = self._get_n_args(args, "get [name]", n=1)
|
||||
def get_name(self, options: Values, args: list[str]) -> None:
|
||||
key = self._get_n_args(args, 'get [name]', n=1)
|
||||
value = self.configuration.get_value(key)
|
||||
|
||||
write_output("%s", value)
|
||||
write_output('%s', value)
|
||||
|
||||
def set_name_value(self, options: Values, args: List[str]) -> None:
|
||||
key, value = self._get_n_args(args, "set [name] [value]", n=2)
|
||||
def set_name_value(self, options: Values, args: 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: Values, args: List[str]) -> None:
|
||||
key = self._get_n_args(args, "unset [name]", n=1)
|
||||
def unset_name(self, options: Values, args: 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: Values, args: List[str]) -> None:
|
||||
def list_config_values(self, options: Values, args: list[str]) -> None:
|
||||
"""List config key-value pairs across different config files"""
|
||||
self._get_n_args(args, "debug", n=0)
|
||||
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)
|
||||
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)
|
||||
write_output('%s, exists: %r', fname, file_exists)
|
||||
if file_exists:
|
||||
self.print_config_file_values(variant)
|
||||
|
||||
|
|
@ -206,35 +210,35 @@ class ConfigurationCommand(Command):
|
|||
"""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)
|
||||
write_output('%s: %s', name, value)
|
||||
|
||||
def print_env_var_values(self) -> None:
|
||||
"""Get key-values pairs present as environment variables"""
|
||||
write_output("%s:", "env_var")
|
||||
write_output('%s:', 'env_var')
|
||||
with indent_log():
|
||||
for key, value in sorted(self.configuration.get_environ_vars()):
|
||||
env_var = f"PIP_{key.upper()}"
|
||||
write_output("%s=%r", env_var, value)
|
||||
env_var = f'PIP_{key.upper()}'
|
||||
write_output('%s=%r', env_var, value)
|
||||
|
||||
def open_in_editor(self, options: Values, args: List[str]) -> None:
|
||||
def open_in_editor(self, options: Values, args: 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.")
|
||||
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)
|
||||
f'Editor Subprocess exited with exit code {e.returncode}',
|
||||
)
|
||||
|
||||
def _get_n_args(self, args: List[str], example: str, n: int) -> Any:
|
||||
def _get_n_args(self, args: list[str], example: str, n: 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 {}. "
|
||||
'Got unexpected number of arguments, expected {}. '
|
||||
'(example: "{} config {}")'
|
||||
).format(n, get_prog(), example)
|
||||
raise PipError(msg)
|
||||
|
|
@ -251,16 +255,16 @@ class ConfigurationCommand(Command):
|
|||
self.configuration.save()
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"Unable to save configuration. Please report this as a bug."
|
||||
'Unable to save configuration. Please report this as a bug.',
|
||||
)
|
||||
raise PipError("Internal Error.")
|
||||
raise PipError('Internal Error.')
|
||||
|
||||
def _determine_editor(self, options: 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"]
|
||||
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.")
|
||||
raise PipError('Could not determine editor to use.')
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import locale
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from optparse import Values
|
||||
from types import ModuleType
|
||||
from typing import Any, Dict, List, Optional
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
import pip._vendor
|
||||
from pip._vendor.certifi import where
|
||||
from pip._vendor.packaging.version import parse as parse_version
|
||||
|
||||
from pip import __file__ as pip_location
|
||||
from pip._internal.cli import cmdoptions
|
||||
from pip._internal.cli.base_command import Command
|
||||
|
|
@ -19,51 +21,53 @@ from pip._internal.configuration import Configuration
|
|||
from pip._internal.metadata import get_environment
|
||||
from pip._internal.utils.logging import indent_log
|
||||
from pip._internal.utils.misc import get_pip_version
|
||||
from pip._vendor.certifi import where
|
||||
from pip._vendor.packaging.version import parse as parse_version
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def show_value(name: str, value: Any) -> None:
|
||||
logger.info("%s: %s", name, value)
|
||||
logger.info('%s: %s', name, value)
|
||||
|
||||
|
||||
def show_sys_implementation() -> None:
|
||||
logger.info("sys.implementation:")
|
||||
logger.info('sys.implementation:')
|
||||
implementation_name = sys.implementation.name
|
||||
with indent_log():
|
||||
show_value("name", implementation_name)
|
||||
show_value('name', implementation_name)
|
||||
|
||||
|
||||
def create_vendor_txt_map() -> Dict[str, str]:
|
||||
def create_vendor_txt_map() -> dict[str, str]:
|
||||
vendor_txt_path = os.path.join(
|
||||
os.path.dirname(pip_location), "_vendor", "vendor.txt"
|
||||
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
|
||||
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
|
||||
return dict(line.split('==', 1) for line in lines) # type: ignore
|
||||
|
||||
|
||||
def get_module_from_module_name(module_name: 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"
|
||||
if module_name == 'setuptools':
|
||||
module_name = 'pkg_resources'
|
||||
|
||||
__import__(f"pip._vendor.{module_name}", globals(), locals(), level=0)
|
||||
__import__(f'pip._vendor.{module_name}', globals(), locals(), level=0)
|
||||
return getattr(pip._vendor, module_name)
|
||||
|
||||
|
||||
def get_vendor_version_from_module(module_name: str) -> Optional[str]:
|
||||
def get_vendor_version_from_module(module_name: str) -> str | None:
|
||||
module = get_module_from_module_name(module_name)
|
||||
version = getattr(module, "__version__", None)
|
||||
version = getattr(module, '__version__', None)
|
||||
|
||||
if not version:
|
||||
# Try to find version in debundled module info.
|
||||
|
|
@ -75,29 +79,29 @@ def get_vendor_version_from_module(module_name: str) -> Optional[str]:
|
|||
return version
|
||||
|
||||
|
||||
def show_actual_vendor_versions(vendor_txt_versions: Dict[str, str]) -> None:
|
||||
def show_actual_vendor_versions(vendor_txt_versions: 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 = ""
|
||||
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)"
|
||||
' (Unable to locate actual module version, using'
|
||||
' vendor.txt specified version)'
|
||||
)
|
||||
actual_version = expected_version
|
||||
elif parse_version(actual_version) != parse_version(expected_version):
|
||||
extra_message = (
|
||||
" (CONFLICT: vendor.txt suggests version should"
|
||||
" be {})".format(expected_version)
|
||||
' (CONFLICT: vendor.txt suggests version should'
|
||||
' be {})'.format(expected_version)
|
||||
)
|
||||
logger.info("%s==%s%s", module_name, actual_version, extra_message)
|
||||
logger.info('%s==%s%s', module_name, actual_version, extra_message)
|
||||
|
||||
|
||||
def show_vendor_versions() -> None:
|
||||
logger.info("vendored library versions:")
|
||||
logger.info('vendored library versions:')
|
||||
|
||||
vendor_txt_versions = create_vendor_txt_map()
|
||||
with indent_log():
|
||||
|
|
@ -112,11 +116,11 @@ def show_tags(options: Values) -> None:
|
|||
|
||||
# Display the target options that were explicitly provided.
|
||||
formatted_target = target_python.format_given()
|
||||
suffix = ""
|
||||
suffix = ''
|
||||
if formatted_target:
|
||||
suffix = f" (target: {formatted_target})"
|
||||
suffix = f' (target: {formatted_target})'
|
||||
|
||||
msg = "Compatible tags: {}{}".format(len(tags), suffix)
|
||||
msg = f'Compatible tags: {len(tags)}{suffix}'
|
||||
logger.info(msg)
|
||||
|
||||
if options.verbose < 1 and len(tags) > tag_limit:
|
||||
|
|
@ -131,7 +135,7 @@ def show_tags(options: Values) -> None:
|
|||
|
||||
if tags_limited:
|
||||
msg = (
|
||||
"...\n[First {tag_limit} tags shown. Pass --verbose to show all.]"
|
||||
'...\n[First {tag_limit} tags shown. Pass --verbose to show all.]'
|
||||
).format(tag_limit=tag_limit)
|
||||
logger.info(msg)
|
||||
|
||||
|
|
@ -139,21 +143,21 @@ def show_tags(options: Values) -> None:
|
|||
def ca_bundle_info(config: Configuration) -> str:
|
||||
levels = set()
|
||||
for key, _ in config.items():
|
||||
levels.add(key.split(".")[0])
|
||||
levels.add(key.split('.')[0])
|
||||
|
||||
if not levels:
|
||||
return "Not specified"
|
||||
return 'Not specified'
|
||||
|
||||
levels_that_override_global = ["install", "wheel", "download"]
|
||||
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"
|
||||
return 'global'
|
||||
|
||||
if "global" in levels:
|
||||
levels.remove("global")
|
||||
return ", ".join(levels)
|
||||
if 'global' in levels:
|
||||
levels.remove('global')
|
||||
return ', '.join(levels)
|
||||
|
||||
|
||||
class DebugCommand(Command):
|
||||
|
|
@ -170,30 +174,30 @@ class DebugCommand(Command):
|
|||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
self.parser.config.load()
|
||||
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: 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."
|
||||
'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('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',
|
||||
locale.getpreferredencoding(),
|
||||
)
|
||||
show_value("sys.platform", sys.platform)
|
||||
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_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()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
from optparse import Values
|
||||
|
|
@ -5,10 +7,13 @@ from typing import List
|
|||
|
||||
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.req_command import RequirementCommand
|
||||
from pip._internal.cli.req_command import 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.misc import ensure_dir
|
||||
from pip._internal.utils.misc import normalize_path
|
||||
from pip._internal.utils.misc import write_output
|
||||
from pip._internal.utils.temp_dir import TempDirectory
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -52,14 +57,14 @@ class DownloadCommand(RequirementCommand):
|
|||
self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"-d",
|
||||
"--dest",
|
||||
"--destination-dir",
|
||||
"--destination-directory",
|
||||
dest="download_dir",
|
||||
metavar="dir",
|
||||
'-d',
|
||||
'--dest',
|
||||
'--destination-dir',
|
||||
'--destination-directory',
|
||||
dest='download_dir',
|
||||
metavar='dir',
|
||||
default=os.curdir,
|
||||
help="Download packages into <dir>.",
|
||||
help='Download packages into <dir>.',
|
||||
)
|
||||
|
||||
cmdoptions.add_target_python_options(self.cmd_opts)
|
||||
|
|
@ -73,7 +78,7 @@ class DownloadCommand(RequirementCommand):
|
|||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
@with_cleanup
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
|
||||
options.ignore_installed = True
|
||||
# editable doesn't really make sense for `pip download`, but the bowels
|
||||
|
|
@ -99,7 +104,7 @@ class DownloadCommand(RequirementCommand):
|
|||
|
||||
directory = TempDirectory(
|
||||
delete=not options.no_clean,
|
||||
kind="download",
|
||||
kind='download',
|
||||
globally_managed=True,
|
||||
)
|
||||
|
||||
|
|
@ -128,13 +133,13 @@ class DownloadCommand(RequirementCommand):
|
|||
|
||||
requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
|
||||
|
||||
downloaded: List[str] = []
|
||||
downloaded: list[str] = []
|
||||
for req in requirement_set.requirements.values():
|
||||
if req.satisfied_by is None:
|
||||
assert req.name is not None
|
||||
preparer.save_linked_requirement(req)
|
||||
downloaded.append(req.name)
|
||||
if downloaded:
|
||||
write_output("Successfully downloaded %s", " ".join(downloaded))
|
||||
write_output('Successfully downloaded %s', ' '.join(downloaded))
|
||||
|
||||
return SUCCESS
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from optparse import Values
|
||||
from typing import List
|
||||
|
|
@ -8,7 +10,7 @@ from pip._internal.cli.status_codes import SUCCESS
|
|||
from pip._internal.operations.freeze import freeze
|
||||
from pip._internal.utils.compat import stdlib_pkgs
|
||||
|
||||
DEV_PKGS = {"pip", "setuptools", "distribute", "wheel"}
|
||||
DEV_PKGS = {'pip', 'setuptools', 'distribute', 'wheel'}
|
||||
|
||||
|
||||
class FreezeCommand(Command):
|
||||
|
|
@ -20,61 +22,61 @@ class FreezeCommand(Command):
|
|||
|
||||
usage = """
|
||||
%prog [options]"""
|
||||
log_streams = ("ext://sys.stderr", "ext://sys.stderr")
|
||||
log_streams = ('ext://sys.stderr', 'ext://sys.stderr')
|
||||
|
||||
def add_options(self) -> None:
|
||||
self.cmd_opts.add_option(
|
||||
"-r",
|
||||
"--requirement",
|
||||
dest="requirements",
|
||||
action="append",
|
||||
'-r',
|
||||
'--requirement',
|
||||
dest='requirements',
|
||||
action='append',
|
||||
default=[],
|
||||
metavar="file",
|
||||
metavar='file',
|
||||
help=(
|
||||
"Use the order in the given requirements file and its "
|
||||
"comments when generating output. This option can be "
|
||||
"used multiple times."
|
||||
'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(
|
||||
"-l",
|
||||
"--local",
|
||||
dest="local",
|
||||
action="store_true",
|
||||
'-l',
|
||||
'--local',
|
||||
dest='local',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=(
|
||||
"If in a virtualenv that has global access, do not output "
|
||||
"globally-installed packages."
|
||||
'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",
|
||||
'--user',
|
||||
dest='user',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="Only output packages installed in user-site.",
|
||||
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",
|
||||
'--all',
|
||||
dest='freeze_all',
|
||||
action='store_true',
|
||||
help=(
|
||||
"Do not skip these packages in the output:"
|
||||
" {}".format(", ".join(DEV_PKGS))
|
||||
'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.",
|
||||
'--exclude-editable',
|
||||
dest='exclude_editable',
|
||||
action='store_true',
|
||||
help='Exclude editable package from output.',
|
||||
)
|
||||
self.cmd_opts.add_option(cmdoptions.list_exclude())
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
skip = set(stdlib_pkgs)
|
||||
if not options.freeze_all:
|
||||
skip.update(DEV_PKGS)
|
||||
|
|
@ -93,5 +95,5 @@ class FreezeCommand(Command):
|
|||
skip=skip,
|
||||
exclude_editable=options.exclude_editable,
|
||||
):
|
||||
sys.stdout.write(line + "\n")
|
||||
sys.stdout.write(line + '\n')
|
||||
return SUCCESS
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
import sys
|
||||
|
|
@ -5,9 +7,12 @@ from optparse import Values
|
|||
from typing import List
|
||||
|
||||
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.cli.status_codes import ERROR
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.utils.hashes import FAVORITE_HASH
|
||||
from pip._internal.utils.hashes import STRONG_HASHES
|
||||
from pip._internal.utils.misc import read_chunks
|
||||
from pip._internal.utils.misc import write_output
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -20,24 +25,24 @@ class HashCommand(Command):
|
|||
installs.
|
||||
"""
|
||||
|
||||
usage = "%prog [options] <file> ..."
|
||||
usage = '%prog [options] <file> ...'
|
||||
ignore_require_venv = True
|
||||
|
||||
def add_options(self) -> None:
|
||||
self.cmd_opts.add_option(
|
||||
"-a",
|
||||
"--algorithm",
|
||||
dest="algorithm",
|
||||
'-a',
|
||||
'--algorithm',
|
||||
dest='algorithm',
|
||||
choices=STRONG_HASHES,
|
||||
action="store",
|
||||
action='store',
|
||||
default=FAVORITE_HASH,
|
||||
help="The hash algorithm to use: one of {}".format(
|
||||
", ".join(STRONG_HASHES)
|
||||
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: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
if not args:
|
||||
self.parser.print_usage(sys.stderr)
|
||||
return ERROR
|
||||
|
|
@ -45,14 +50,14 @@ class HashCommand(Command):
|
|||
algorithm = options.algorithm
|
||||
for path in args:
|
||||
write_output(
|
||||
"%s:\n--hash=%s:%s", path, algorithm, _hash_of_file(path, algorithm)
|
||||
'%s:\n--hash=%s:%s', path, algorithm, _hash_of_file(path, algorithm),
|
||||
)
|
||||
return SUCCESS
|
||||
|
||||
|
||||
def _hash_of_file(path: str, algorithm: str) -> str:
|
||||
"""Return the hash digest of a file."""
|
||||
with open(path, "rb") as archive:
|
||||
with open(path, 'rb') as archive:
|
||||
hash = hashlib.new(algorithm)
|
||||
for chunk in read_chunks(archive):
|
||||
hash.update(chunk)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from optparse import Values
|
||||
from typing import List
|
||||
|
||||
|
|
@ -13,7 +15,7 @@ class HelpCommand(Command):
|
|||
%prog <command>"""
|
||||
ignore_require_venv = True
|
||||
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
from pip._internal.commands import (
|
||||
commands_dict,
|
||||
create_command,
|
||||
|
|
@ -33,7 +35,7 @@ class HelpCommand(Command):
|
|||
if guess:
|
||||
msg.append(f'maybe you meant "{guess}"')
|
||||
|
||||
raise CommandError(" - ".join(msg))
|
||||
raise CommandError(' - '.join(msg))
|
||||
|
||||
command = create_command(cmd_name)
|
||||
command.parser.print_help()
|
||||
|
|
|
|||
|
|
@ -1,20 +1,29 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from optparse import Values
|
||||
from typing import Any, Iterable, List, Optional, Union
|
||||
|
||||
from pip._vendor.packaging.version import LegacyVersion, Version
|
||||
from typing import Any
|
||||
from typing import Iterable
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import Union
|
||||
|
||||
from pip._internal.cli import cmdoptions
|
||||
from pip._internal.cli.req_command import IndexGroupCommand
|
||||
from pip._internal.cli.status_codes import ERROR, SUCCESS
|
||||
from pip._internal.cli.status_codes import ERROR
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.commands.search import print_dist_installation_info
|
||||
from pip._internal.exceptions import CommandError, DistributionNotFound, PipError
|
||||
from pip._internal.exceptions import CommandError
|
||||
from pip._internal.exceptions import DistributionNotFound
|
||||
from pip._internal.exceptions import PipError
|
||||
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.models.target_python import TargetPython
|
||||
from pip._internal.network.session import PipSession
|
||||
from pip._internal.utils.misc import write_output
|
||||
from pip._vendor.packaging.version import LegacyVersion
|
||||
from pip._vendor.packaging.version import Version
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -44,22 +53,22 @@ class IndexCommand(IndexGroupCommand):
|
|||
self.parser.insert_option_group(0, index_opts)
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
handlers = {
|
||||
"versions": self.get_available_package_versions,
|
||||
'versions': self.get_available_package_versions,
|
||||
}
|
||||
|
||||
logger.warning(
|
||||
"pip index is currently an experimental command. "
|
||||
"It may be removed/changed in a future release "
|
||||
"without prior warning."
|
||||
'pip index is currently an experimental command. '
|
||||
'It may be removed/changed in a future release '
|
||||
'without prior warning.',
|
||||
)
|
||||
|
||||
# Determine action
|
||||
if not args or args[0] not in handlers:
|
||||
logger.error(
|
||||
"Need an action (%s) to perform.",
|
||||
", ".join(sorted(handlers)),
|
||||
'Need an action (%s) to perform.',
|
||||
', '.join(sorted(handlers)),
|
||||
)
|
||||
return ERROR
|
||||
|
||||
|
|
@ -78,8 +87,8 @@ class IndexCommand(IndexGroupCommand):
|
|||
self,
|
||||
options: Values,
|
||||
session: PipSession,
|
||||
target_python: Optional[TargetPython] = None,
|
||||
ignore_requires_python: Optional[bool] = None,
|
||||
target_python: TargetPython | None = None,
|
||||
ignore_requires_python: bool | None = None,
|
||||
) -> PackageFinder:
|
||||
"""
|
||||
Create a package finder appropriate to the index command.
|
||||
|
|
@ -97,12 +106,12 @@ class IndexCommand(IndexGroupCommand):
|
|||
link_collector=link_collector,
|
||||
selection_prefs=selection_prefs,
|
||||
target_python=target_python,
|
||||
use_deprecated_html5lib="html5lib" in options.deprecated_features_enabled,
|
||||
use_deprecated_html5lib='html5lib' in options.deprecated_features_enabled,
|
||||
)
|
||||
|
||||
def get_available_package_versions(self, options: Values, args: List[Any]) -> None:
|
||||
def get_available_package_versions(self, options: Values, args: list[Any]) -> None:
|
||||
if len(args) != 1:
|
||||
raise CommandError("You need to specify exactly one argument")
|
||||
raise CommandError('You need to specify exactly one argument')
|
||||
|
||||
target_python = cmdoptions.make_target_python(options)
|
||||
query = args[0]
|
||||
|
|
@ -115,7 +124,7 @@ class IndexCommand(IndexGroupCommand):
|
|||
ignore_requires_python=options.ignore_requires_python,
|
||||
)
|
||||
|
||||
versions: Iterable[Union[LegacyVersion, Version]] = (
|
||||
versions: Iterable[LegacyVersion | Version] = (
|
||||
candidate.version for candidate in finder.find_all_candidates(query)
|
||||
)
|
||||
|
||||
|
|
@ -128,12 +137,12 @@ class IndexCommand(IndexGroupCommand):
|
|||
|
||||
if not versions:
|
||||
raise DistributionNotFound(
|
||||
"No matching distribution found for {}".format(query)
|
||||
f'No matching distribution found for {query}',
|
||||
)
|
||||
|
||||
formatted_versions = [str(ver) for ver in sorted(versions, reverse=True)]
|
||||
latest = formatted_versions[0]
|
||||
|
||||
write_output("{} ({})".format(query, latest))
|
||||
write_output("Available versions: {}".format(", ".join(formatted_versions)))
|
||||
write_output(f'{query} ({latest})')
|
||||
write_output('Available versions: {}'.format(', '.join(formatted_versions)))
|
||||
print_dist_installation_info(query, latest)
|
||||
|
|
|
|||
|
|
@ -1,27 +1,31 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import errno
|
||||
import operator
|
||||
import os
|
||||
import shutil
|
||||
import site
|
||||
from optparse import SUPPRESS_HELP, Values
|
||||
from typing import Iterable, List, Optional
|
||||
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
from optparse import SUPPRESS_HELP
|
||||
from optparse import Values
|
||||
from typing import Iterable
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
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,
|
||||
warn_if_run_as_root,
|
||||
with_cleanup,
|
||||
)
|
||||
from pip._internal.cli.status_codes import ERROR, SUCCESS
|
||||
from pip._internal.exceptions import CommandError, InstallationError
|
||||
from pip._internal.cli.req_command import RequirementCommand
|
||||
from pip._internal.cli.req_command import warn_if_run_as_root
|
||||
from pip._internal.cli.req_command import with_cleanup
|
||||
from pip._internal.cli.status_codes import ERROR
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.exceptions import CommandError
|
||||
from pip._internal.exceptions import InstallationError
|
||||
from pip._internal.locations import get_scheme
|
||||
from pip._internal.metadata import get_environment
|
||||
from pip._internal.models.format_control import FormatControl
|
||||
from pip._internal.operations.check import ConflictDetails, check_install_conflicts
|
||||
from pip._internal.operations.check import check_install_conflicts
|
||||
from pip._internal.operations.check import ConflictDetails
|
||||
from pip._internal.req import install_given_reqs
|
||||
from pip._internal.req.req_install import InstallRequirement
|
||||
from pip._internal.req.req_tracker import get_requirement_tracker
|
||||
|
|
@ -29,31 +33,26 @@ from pip._internal.utils.compat import WINDOWS
|
|||
from pip._internal.utils.distutils_args import parse_distutils_args
|
||||
from pip._internal.utils.filesystem import test_writable_dir
|
||||
from pip._internal.utils.logging import getLogger
|
||||
from pip._internal.utils.misc import (
|
||||
ensure_dir,
|
||||
get_pip_version,
|
||||
protect_pip_from_modification_on_windows,
|
||||
write_output,
|
||||
)
|
||||
from pip._internal.utils.misc import ensure_dir
|
||||
from pip._internal.utils.misc import get_pip_version
|
||||
from pip._internal.utils.misc import protect_pip_from_modification_on_windows
|
||||
from pip._internal.utils.misc import write_output
|
||||
from pip._internal.utils.temp_dir import TempDirectory
|
||||
from pip._internal.utils.virtualenv import (
|
||||
running_under_virtualenv,
|
||||
virtualenv_no_global,
|
||||
)
|
||||
from pip._internal.wheel_builder import (
|
||||
BinaryAllowedPredicate,
|
||||
build,
|
||||
should_build_for_install_command,
|
||||
)
|
||||
from pip._internal.utils.virtualenv import running_under_virtualenv
|
||||
from pip._internal.utils.virtualenv import virtualenv_no_global
|
||||
from pip._internal.wheel_builder import BinaryAllowedPredicate
|
||||
from pip._internal.wheel_builder import build
|
||||
from pip._internal.wheel_builder import should_build_for_install_command
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
def get_check_binary_allowed(format_control: FormatControl) -> BinaryAllowedPredicate:
|
||||
def check_binary_allowed(req: InstallRequirement) -> bool:
|
||||
canonical_name = canonicalize_name(req.name or "")
|
||||
canonical_name = canonicalize_name(req.name or '')
|
||||
allowed_formats = format_control.get_allowed_formats(canonical_name)
|
||||
return "binary" in allowed_formats
|
||||
return 'binary' in allowed_formats
|
||||
|
||||
return check_binary_allowed
|
||||
|
||||
|
|
@ -86,102 +85,102 @@ class InstallCommand(RequirementCommand):
|
|||
|
||||
self.cmd_opts.add_option(cmdoptions.editable())
|
||||
self.cmd_opts.add_option(
|
||||
"-t",
|
||||
"--target",
|
||||
dest="target_dir",
|
||||
metavar="dir",
|
||||
'-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."
|
||||
'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",
|
||||
'--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.)"
|
||||
'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",
|
||||
'--no-user',
|
||||
dest='use_user_site',
|
||||
action='store_false',
|
||||
help=SUPPRESS_HELP,
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
"--root",
|
||||
dest="root_path",
|
||||
metavar="dir",
|
||||
'--root',
|
||||
dest='root_path',
|
||||
metavar='dir',
|
||||
default=None,
|
||||
help="Install everything relative to this alternate root directory.",
|
||||
help='Install everything relative to this alternate root directory.',
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
"--prefix",
|
||||
dest="prefix_path",
|
||||
metavar="dir",
|
||||
'--prefix',
|
||||
dest='prefix_path',
|
||||
metavar='dir',
|
||||
default=None,
|
||||
help=(
|
||||
"Installation prefix where lib, bin and other top-level "
|
||||
"folders are placed"
|
||||
'Installation prefix where lib, bin and other top-level '
|
||||
'folders are placed'
|
||||
),
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(cmdoptions.src())
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"-U",
|
||||
"--upgrade",
|
||||
dest="upgrade",
|
||||
action="store_true",
|
||||
'-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."
|
||||
'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"],
|
||||
'--upgrade-strategy',
|
||||
dest='upgrade_strategy',
|
||||
default='only-if-needed',
|
||||
choices=['only-if-needed', 'eager'],
|
||||
help=(
|
||||
"Determines how dependency upgrading should be handled "
|
||||
"[default: %default]. "
|
||||
'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). "
|
||||
'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)."
|
||||
'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.",
|
||||
'--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",
|
||||
'-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!"
|
||||
'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!'
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -194,33 +193,33 @@ class InstallCommand(RequirementCommand):
|
|||
self.cmd_opts.add_option(cmdoptions.global_options())
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"--compile",
|
||||
action="store_true",
|
||||
dest="compile",
|
||||
'--compile',
|
||||
action='store_true',
|
||||
dest='compile',
|
||||
default=True,
|
||||
help="Compile Python source files to bytecode",
|
||||
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",
|
||||
'--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",
|
||||
'--no-warn-script-location',
|
||||
action='store_false',
|
||||
dest='warn_script_location',
|
||||
default=True,
|
||||
help="Do not warn when installing scripts outside PATH",
|
||||
help='Do not warn when installing scripts outside PATH',
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
"--no-warn-conflicts",
|
||||
action="store_false",
|
||||
dest="warn_about_conflicts",
|
||||
'--no-warn-conflicts',
|
||||
action='store_false',
|
||||
dest='warn_about_conflicts',
|
||||
default=True,
|
||||
help="Do not warn about broken dependencies",
|
||||
help='Do not warn about broken dependencies',
|
||||
)
|
||||
|
||||
self.cmd_opts.add_option(cmdoptions.no_binary())
|
||||
|
|
@ -238,12 +237,12 @@ class InstallCommand(RequirementCommand):
|
|||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
@with_cleanup
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: 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"
|
||||
upgrade_strategy = 'to-satisfy-only'
|
||||
if options.upgrade:
|
||||
upgrade_strategy = options.upgrade_strategy
|
||||
|
||||
|
|
@ -251,7 +250,7 @@ class InstallCommand(RequirementCommand):
|
|||
|
||||
install_options = options.install_options or []
|
||||
|
||||
logger.verbose("Using %s", get_pip_version())
|
||||
logger.verbose('Using %s', get_pip_version())
|
||||
options.use_user_site = decide_user_install(
|
||||
options.use_user_site,
|
||||
prefix_path=options.prefix_path,
|
||||
|
|
@ -260,8 +259,8 @@ class InstallCommand(RequirementCommand):
|
|||
isolated_mode=options.isolated_mode,
|
||||
)
|
||||
|
||||
target_temp_dir: Optional[TempDirectory] = None
|
||||
target_temp_dir_path: Optional[str] = None
|
||||
target_temp_dir: TempDirectory | None = None
|
||||
target_temp_dir_path: str | None = None
|
||||
if options.target_dir:
|
||||
options.ignore_installed = True
|
||||
options.target_dir = os.path.abspath(options.target_dir)
|
||||
|
|
@ -272,11 +271,11 @@ class InstallCommand(RequirementCommand):
|
|||
# fmt: on
|
||||
):
|
||||
raise CommandError(
|
||||
"Target path exists but is not a directory, will not continue."
|
||||
'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 = TempDirectory(kind='target')
|
||||
target_temp_dir_path = target_temp_dir.path
|
||||
self.enter_context(target_temp_dir)
|
||||
|
||||
|
|
@ -297,7 +296,7 @@ class InstallCommand(RequirementCommand):
|
|||
|
||||
directory = TempDirectory(
|
||||
delete=not options.no_clean,
|
||||
kind="install",
|
||||
kind='install',
|
||||
globally_managed=True,
|
||||
)
|
||||
|
||||
|
|
@ -337,11 +336,11 @@ class InstallCommand(RequirementCommand):
|
|||
self.trace_basic_info(finder)
|
||||
|
||||
requirement_set = resolver.resolve(
|
||||
reqs, check_supported_wheels=not options.target_dir
|
||||
reqs, check_supported_wheels=not options.target_dir,
|
||||
)
|
||||
|
||||
try:
|
||||
pip_req = requirement_set.get_requirement("pip")
|
||||
pip_req = requirement_set.get_requirement('pip')
|
||||
except KeyError:
|
||||
modifying_pip = False
|
||||
else:
|
||||
|
|
@ -368,15 +367,15 @@ class InstallCommand(RequirementCommand):
|
|||
|
||||
# If we're using PEP 517, we cannot do a legacy setup.py install
|
||||
# so we fail here.
|
||||
pep517_build_failure_names: List[str] = [
|
||||
pep517_build_failure_names: list[str] = [
|
||||
r.name for r in build_failures if r.use_pep517 # type: ignore
|
||||
]
|
||||
if pep517_build_failure_names:
|
||||
raise InstallationError(
|
||||
"Could not build wheels for {}, which is required to "
|
||||
"install pyproject.toml-based projects".format(
|
||||
", ".join(pep517_build_failure_names)
|
||||
)
|
||||
'Could not build wheels for {}, which is required to '
|
||||
'install pyproject.toml-based projects'.format(
|
||||
', '.join(pep517_build_failure_names),
|
||||
),
|
||||
)
|
||||
|
||||
# For now, we just warn about failures building legacy
|
||||
|
|
@ -389,7 +388,7 @@ class InstallCommand(RequirementCommand):
|
|||
to_install = resolver.get_installation_order(requirement_set)
|
||||
|
||||
# Check for conflicts in the package set we're installing.
|
||||
conflicts: Optional[ConflictDetails] = None
|
||||
conflicts: ConflictDetails | None = None
|
||||
should_warn_about_conflicts = (
|
||||
not options.ignore_dependencies and options.warn_about_conflicts
|
||||
)
|
||||
|
|
@ -423,14 +422,14 @@ class InstallCommand(RequirementCommand):
|
|||
)
|
||||
env = get_environment(lib_locations)
|
||||
|
||||
installed.sort(key=operator.attrgetter("name"))
|
||||
installed.sort(key=operator.attrgetter('name'))
|
||||
items = []
|
||||
for result in installed:
|
||||
item = result.name
|
||||
try:
|
||||
installed_dist = env.get_distribution(item)
|
||||
if installed_dist is not None:
|
||||
item = f"{item}-{installed_dist.version}"
|
||||
item = f'{item}-{installed_dist.version}'
|
||||
except Exception:
|
||||
pass
|
||||
items.append(item)
|
||||
|
|
@ -441,10 +440,10 @@ class InstallCommand(RequirementCommand):
|
|||
resolver_variant=self.determine_resolver_variant(options),
|
||||
)
|
||||
|
||||
installed_desc = " ".join(items)
|
||||
installed_desc = ' '.join(items)
|
||||
if installed_desc:
|
||||
write_output(
|
||||
"Successfully installed %s",
|
||||
'Successfully installed %s',
|
||||
installed_desc,
|
||||
)
|
||||
except OSError as error:
|
||||
|
|
@ -462,14 +461,14 @@ class InstallCommand(RequirementCommand):
|
|||
if options.target_dir:
|
||||
assert target_temp_dir
|
||||
self._handle_target_dir(
|
||||
options.target_dir, target_temp_dir, options.upgrade
|
||||
options.target_dir, target_temp_dir, options.upgrade,
|
||||
)
|
||||
|
||||
warn_if_run_as_root()
|
||||
return SUCCESS
|
||||
|
||||
def _handle_target_dir(
|
||||
self, target_dir: str, target_temp_dir: TempDirectory, upgrade: bool
|
||||
self, target_dir: str, target_temp_dir: TempDirectory, upgrade: bool,
|
||||
) -> None:
|
||||
ensure_dir(target_dir)
|
||||
|
||||
|
|
@ -479,7 +478,7 @@ class InstallCommand(RequirementCommand):
|
|||
|
||||
# Checking both purelib and platlib directories for installed
|
||||
# packages to be moved to target directory
|
||||
scheme = get_scheme("", home=target_temp_dir.path)
|
||||
scheme = get_scheme('', home=target_temp_dir.path)
|
||||
purelib_dir = scheme.purelib
|
||||
platlib_dir = scheme.platlib
|
||||
data_dir = scheme.data
|
||||
|
|
@ -501,17 +500,17 @@ class InstallCommand(RequirementCommand):
|
|||
if os.path.exists(target_item_dir):
|
||||
if not upgrade:
|
||||
logger.warning(
|
||||
"Target directory %s already exists. Specify "
|
||||
"--upgrade to force replacement.",
|
||||
'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 directory %s already exists and is '
|
||||
'a link. pip will not automatically replace '
|
||||
'links, please remove if replacement is '
|
||||
'desired.',
|
||||
target_item_dir,
|
||||
)
|
||||
continue
|
||||
|
|
@ -523,37 +522,37 @@ class InstallCommand(RequirementCommand):
|
|||
shutil.move(os.path.join(lib_dir, item), target_item_dir)
|
||||
|
||||
def _determine_conflicts(
|
||||
self, to_install: List[InstallRequirement]
|
||||
) -> Optional[ConflictDetails]:
|
||||
self, to_install: list[InstallRequirement],
|
||||
) -> ConflictDetails | None:
|
||||
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"
|
||||
'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: ConflictDetails, resolver_variant: str
|
||||
self, conflict_details: ConflictDetails, resolver_variant: str,
|
||||
) -> None:
|
||||
package_set, (missing, conflicting) = conflict_details
|
||||
if not missing and not conflicting:
|
||||
return
|
||||
|
||||
parts: List[str] = []
|
||||
if resolver_variant == "legacy":
|
||||
parts: list[str] = []
|
||||
if resolver_variant == 'legacy':
|
||||
parts.append(
|
||||
"pip's legacy dependency resolver does not consider dependency "
|
||||
"conflicts when selecting packages. This behaviour is the "
|
||||
"source of the following dependency conflicts."
|
||||
'conflicts when selecting packages. This behaviour is the '
|
||||
'source of the following dependency conflicts.',
|
||||
)
|
||||
else:
|
||||
assert resolver_variant == "2020-resolver"
|
||||
assert resolver_variant == '2020-resolver'
|
||||
parts.append(
|
||||
"pip's dependency resolver does not currently take into account "
|
||||
"all the packages that are installed. This behaviour is the "
|
||||
"source of the following dependency conflicts."
|
||||
'all the packages that are installed. This behaviour is the '
|
||||
'source of the following dependency conflicts.',
|
||||
)
|
||||
|
||||
# NOTE: There is some duplication here, with commands/check.py
|
||||
|
|
@ -561,8 +560,8 @@ class InstallCommand(RequirementCommand):
|
|||
version = package_set[project_name][0]
|
||||
for dependency in missing[project_name]:
|
||||
message = (
|
||||
"{name} {version} requires {requirement}, "
|
||||
"which is not installed."
|
||||
'{name} {version} requires {requirement}, '
|
||||
'which is not installed.'
|
||||
).format(
|
||||
name=project_name,
|
||||
version=version,
|
||||
|
|
@ -574,30 +573,30 @@ class InstallCommand(RequirementCommand):
|
|||
version = package_set[project_name][0]
|
||||
for dep_name, dep_version, req in conflicting[project_name]:
|
||||
message = (
|
||||
"{name} {version} requires {requirement}, but {you} have "
|
||||
"{dep_name} {dep_version} which is incompatible."
|
||||
'{name} {version} requires {requirement}, but {you} have '
|
||||
'{dep_name} {dep_version} which is incompatible.'
|
||||
).format(
|
||||
name=project_name,
|
||||
version=version,
|
||||
requirement=req,
|
||||
dep_name=dep_name,
|
||||
dep_version=dep_version,
|
||||
you=("you" if resolver_variant == "2020-resolver" else "you'll"),
|
||||
you=('you' if resolver_variant == '2020-resolver' else "you'll"),
|
||||
)
|
||||
parts.append(message)
|
||||
|
||||
logger.critical("\n".join(parts))
|
||||
logger.critical('\n'.join(parts))
|
||||
|
||||
|
||||
def get_lib_location_guesses(
|
||||
user: bool = False,
|
||||
home: Optional[str] = None,
|
||||
root: Optional[str] = None,
|
||||
home: str | None = None,
|
||||
root: str | None = None,
|
||||
isolated: bool = False,
|
||||
prefix: Optional[str] = None,
|
||||
) -> List[str]:
|
||||
prefix: str | None = None,
|
||||
) -> list[str]:
|
||||
scheme = get_scheme(
|
||||
"",
|
||||
'',
|
||||
user=user,
|
||||
home=home,
|
||||
root=root,
|
||||
|
|
@ -607,7 +606,7 @@ def get_lib_location_guesses(
|
|||
return [scheme.purelib, scheme.platlib]
|
||||
|
||||
|
||||
def site_packages_writable(root: Optional[str], isolated: bool) -> bool:
|
||||
def site_packages_writable(root: str | None, isolated: bool) -> bool:
|
||||
return all(
|
||||
test_writable_dir(d)
|
||||
for d in set(get_lib_location_guesses(root=root, isolated=isolated))
|
||||
|
|
@ -615,10 +614,10 @@ def site_packages_writable(root: Optional[str], isolated: bool) -> bool:
|
|||
|
||||
|
||||
def decide_user_install(
|
||||
use_user_site: Optional[bool],
|
||||
prefix_path: Optional[str] = None,
|
||||
target_dir: Optional[str] = None,
|
||||
root_path: Optional[str] = None,
|
||||
use_user_site: bool | None,
|
||||
prefix_path: str | None = None,
|
||||
target_dir: str | None = None,
|
||||
root_path: str | None = None,
|
||||
isolated_mode: bool = False,
|
||||
) -> bool:
|
||||
"""Determine whether to do a user install based on the input options.
|
||||
|
|
@ -632,21 +631,21 @@ def decide_user_install(
|
|||
# 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")
|
||||
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"
|
||||
'different installation locations',
|
||||
)
|
||||
if virtualenv_no_global():
|
||||
raise InstallationError(
|
||||
"Can not perform a '--user' install. User site-packages "
|
||||
"are not visible in this virtualenv."
|
||||
'are not visible in this virtualenv.',
|
||||
)
|
||||
logger.debug("User install by explicit request")
|
||||
logger.debug('User install by explicit request')
|
||||
return True
|
||||
|
||||
# If we are here, user installs have not been explicitly requested/avoided
|
||||
|
|
@ -654,36 +653,36 @@ def decide_user_install(
|
|||
|
||||
# user install incompatible with --prefix/--target
|
||||
if prefix_path or target_dir:
|
||||
logger.debug("Non-user install due to --prefix or --target option")
|
||||
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")
|
||||
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")
|
||||
logger.debug('Non-user install because site-packages writeable')
|
||||
return False
|
||||
|
||||
logger.info(
|
||||
"Defaulting to user installation because normal site-packages "
|
||||
"is not writeable"
|
||||
'Defaulting to user installation because normal site-packages '
|
||||
'is not writeable',
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def reject_location_related_install_options(
|
||||
requirements: List[InstallRequirement], options: Optional[List[str]]
|
||||
requirements: list[InstallRequirement], options: list[str] | None,
|
||||
) -> 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: Iterable[str]) -> List[str]:
|
||||
return ["--{}".format(name.replace("_", "-")) for name in option_names]
|
||||
def format_options(option_names: Iterable[str]) -> list[str]:
|
||||
return ['--{}'.format(name.replace('_', '-')) for name in option_names]
|
||||
|
||||
offenders = []
|
||||
|
||||
|
|
@ -692,30 +691,30 @@ def reject_location_related_install_options(
|
|||
location_options = parse_distutils_args(install_options)
|
||||
if location_options:
|
||||
offenders.append(
|
||||
"{!r} from {}".format(
|
||||
format_options(location_options.keys()), requirement
|
||||
)
|
||||
'{!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()))
|
||||
f'{format_options(location_options.keys())!r} from command line',
|
||||
)
|
||||
|
||||
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))
|
||||
'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_os_error_message(
|
||||
error: OSError, show_traceback: bool, using_user_site: bool
|
||||
error: OSError, show_traceback: bool, using_user_site: bool,
|
||||
) -> str:
|
||||
"""Format an error message for an OSError
|
||||
|
||||
|
|
@ -724,48 +723,48 @@ def create_os_error_message(
|
|||
parts = []
|
||||
|
||||
# Mention the error if we are not going to show a traceback
|
||||
parts.append("Could not install packages due to an OSError")
|
||||
parts.append('Could not install packages due to an OSError')
|
||||
if not show_traceback:
|
||||
parts.append(": ")
|
||||
parts.append(': ')
|
||||
parts.append(str(error))
|
||||
else:
|
||||
parts.append(".")
|
||||
parts.append('.')
|
||||
|
||||
# Spilt the error indication from a helper message (if any)
|
||||
parts[-1] += "\n"
|
||||
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"
|
||||
user_option_part = 'Consider using the `--user` option'
|
||||
permissions_part = 'Check the permissions'
|
||||
|
||||
if not running_under_virtualenv() and not using_user_site:
|
||||
parts.extend(
|
||||
[
|
||||
user_option_part,
|
||||
" or ",
|
||||
' or ',
|
||||
permissions_part.lower(),
|
||||
]
|
||||
],
|
||||
)
|
||||
else:
|
||||
parts.append(permissions_part)
|
||||
parts.append(".\n")
|
||||
parts.append('.\n')
|
||||
|
||||
# Suggest the user to enable Long Paths if path length is
|
||||
# more than 260
|
||||
if (
|
||||
WINDOWS
|
||||
and error.errno == errno.ENOENT
|
||||
and error.filename
|
||||
and len(error.filename) > 260
|
||||
WINDOWS and
|
||||
error.errno == errno.ENOENT and
|
||||
error.filename and
|
||||
len(error.filename) > 260
|
||||
):
|
||||
parts.append(
|
||||
"HINT: This error might have occurred since "
|
||||
"this system does not have Windows Long Path "
|
||||
"support enabled. You can find information on "
|
||||
"how to enable this at "
|
||||
"https://pip.pypa.io/warnings/enable-long-paths\n"
|
||||
'HINT: This error might have occurred since '
|
||||
'this system does not have Windows Long Path '
|
||||
'support enabled. You can find information on '
|
||||
'how to enable this at '
|
||||
'https://pip.pypa.io/warnings/enable-long-paths\n',
|
||||
)
|
||||
|
||||
return "".join(parts).strip() + "\n"
|
||||
return ''.join(parts).strip() + '\n'
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
from optparse import Values
|
||||
from typing import TYPE_CHECKING, Iterator, List, Optional, Sequence, Tuple, cast
|
||||
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
from typing import cast
|
||||
from typing import Iterator
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import Sequence
|
||||
from typing import Tuple
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from pip._internal.cli import cmdoptions
|
||||
from pip._internal.cli.req_command import IndexGroupCommand
|
||||
|
|
@ -11,11 +17,14 @@ 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.metadata import BaseDistribution, get_environment
|
||||
from pip._internal.metadata import BaseDistribution
|
||||
from pip._internal.metadata import get_environment
|
||||
from pip._internal.models.selection_prefs import SelectionPreferences
|
||||
from pip._internal.network.session import PipSession
|
||||
from pip._internal.utils.compat import stdlib_pkgs
|
||||
from pip._internal.utils.misc import tabulate, write_output
|
||||
from pip._internal.utils.misc import tabulate
|
||||
from pip._internal.utils.misc import write_output
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pip._internal.metadata.base import DistributionVersion
|
||||
|
|
@ -49,81 +58,81 @@ class ListCommand(IndexGroupCommand):
|
|||
|
||||
def add_options(self) -> None:
|
||||
self.cmd_opts.add_option(
|
||||
"-o",
|
||||
"--outdated",
|
||||
action="store_true",
|
||||
'-o',
|
||||
'--outdated',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="List outdated packages",
|
||||
help='List outdated packages',
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
"-u",
|
||||
"--uptodate",
|
||||
action="store_true",
|
||||
'-u',
|
||||
'--uptodate',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="List uptodate packages",
|
||||
help='List uptodate packages',
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
"-e",
|
||||
"--editable",
|
||||
action="store_true",
|
||||
'-e',
|
||||
'--editable',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="List editable projects.",
|
||||
help='List editable projects.',
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
"-l",
|
||||
"--local",
|
||||
action="store_true",
|
||||
'-l',
|
||||
'--local',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=(
|
||||
"If in a virtualenv that has global access, do not list "
|
||||
"globally-installed packages."
|
||||
'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",
|
||||
'--user',
|
||||
dest='user',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="Only output packages installed in user-site.",
|
||||
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",
|
||||
'--pre',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=(
|
||||
"Include pre-release and development versions. By default, "
|
||||
"pip only finds stable versions."
|
||||
'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",
|
||||
'--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.",
|
||||
'--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.",
|
||||
'--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.",
|
||||
'--include-editable',
|
||||
action='store_true',
|
||||
dest='include_editable',
|
||||
help='Include editable package from output.',
|
||||
default=True,
|
||||
)
|
||||
self.cmd_opts.add_option(cmdoptions.list_exclude())
|
||||
|
|
@ -133,7 +142,7 @@ class ListCommand(IndexGroupCommand):
|
|||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def _build_package_finder(
|
||||
self, options: Values, session: PipSession
|
||||
self, options: Values, session: PipSession,
|
||||
) -> PackageFinder:
|
||||
"""
|
||||
Create a package finder appropriate to this list command.
|
||||
|
|
@ -149,12 +158,12 @@ class ListCommand(IndexGroupCommand):
|
|||
return PackageFinder.create(
|
||||
link_collector=link_collector,
|
||||
selection_prefs=selection_prefs,
|
||||
use_deprecated_html5lib="html5lib" in options.deprecated_features_enabled,
|
||||
use_deprecated_html5lib='html5lib' in options.deprecated_features_enabled,
|
||||
)
|
||||
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
if options.outdated and options.uptodate:
|
||||
raise CommandError("Options --outdated and --uptodate cannot be combined.")
|
||||
raise CommandError('Options --outdated and --uptodate cannot be combined.')
|
||||
|
||||
cmdoptions.check_list_path_option(options)
|
||||
|
||||
|
|
@ -162,8 +171,8 @@ class ListCommand(IndexGroupCommand):
|
|||
if options.excludes:
|
||||
skip.update(canonicalize_name(n) for n in options.excludes)
|
||||
|
||||
packages: "_ProcessedDists" = [
|
||||
cast("_DistWithLatestInfo", d)
|
||||
packages: _ProcessedDists = [
|
||||
cast('_DistWithLatestInfo', d)
|
||||
for d in get_environment(options.path).iter_installed_distributions(
|
||||
local_only=options.local,
|
||||
user_only=options.user,
|
||||
|
|
@ -189,8 +198,8 @@ class ListCommand(IndexGroupCommand):
|
|||
return SUCCESS
|
||||
|
||||
def get_outdated(
|
||||
self, packages: "_ProcessedDists", options: Values
|
||||
) -> "_ProcessedDists":
|
||||
self, packages: _ProcessedDists, options: Values,
|
||||
) -> _ProcessedDists:
|
||||
return [
|
||||
dist
|
||||
for dist in self.iter_packages_latest_infos(packages, options)
|
||||
|
|
@ -198,8 +207,8 @@ class ListCommand(IndexGroupCommand):
|
|||
]
|
||||
|
||||
def get_uptodate(
|
||||
self, packages: "_ProcessedDists", options: Values
|
||||
) -> "_ProcessedDists":
|
||||
self, packages: _ProcessedDists, options: Values,
|
||||
) -> _ProcessedDists:
|
||||
return [
|
||||
dist
|
||||
for dist in self.iter_packages_latest_infos(packages, options)
|
||||
|
|
@ -207,8 +216,8 @@ class ListCommand(IndexGroupCommand):
|
|||
]
|
||||
|
||||
def get_not_required(
|
||||
self, packages: "_ProcessedDists", options: Values
|
||||
) -> "_ProcessedDists":
|
||||
self, packages: _ProcessedDists, options: Values,
|
||||
) -> _ProcessedDists:
|
||||
dep_keys = {
|
||||
canonicalize_name(dep.name)
|
||||
for dist in packages
|
||||
|
|
@ -221,14 +230,14 @@ class ListCommand(IndexGroupCommand):
|
|||
return list({pkg for pkg in packages if pkg.canonical_name not in dep_keys})
|
||||
|
||||
def iter_packages_latest_infos(
|
||||
self, packages: "_ProcessedDists", options: Values
|
||||
) -> Iterator["_DistWithLatestInfo"]:
|
||||
self, packages: _ProcessedDists, options: Values,
|
||||
) -> Iterator[_DistWithLatestInfo]:
|
||||
with self._build_session(options) as session:
|
||||
finder = self._build_package_finder(options, session)
|
||||
|
||||
def latest_info(
|
||||
dist: "_DistWithLatestInfo",
|
||||
) -> Optional["_DistWithLatestInfo"]:
|
||||
dist: _DistWithLatestInfo,
|
||||
) -> _DistWithLatestInfo | None:
|
||||
all_candidates = finder.find_all_candidates(dist.canonical_name)
|
||||
if not options.pre:
|
||||
# Remove prereleases
|
||||
|
|
@ -247,9 +256,9 @@ class ListCommand(IndexGroupCommand):
|
|||
|
||||
remote_version = best_candidate.version
|
||||
if best_candidate.link.is_wheel:
|
||||
typ = "wheel"
|
||||
typ = 'wheel'
|
||||
else:
|
||||
typ = "sdist"
|
||||
typ = 'sdist'
|
||||
dist.latest_version = remote_version
|
||||
dist.latest_filetype = typ
|
||||
return dist
|
||||
|
|
@ -259,28 +268,28 @@ class ListCommand(IndexGroupCommand):
|
|||
yield dist
|
||||
|
||||
def output_package_listing(
|
||||
self, packages: "_ProcessedDists", options: Values
|
||||
self, packages: _ProcessedDists, options: Values,
|
||||
) -> None:
|
||||
packages = sorted(
|
||||
packages,
|
||||
key=lambda dist: dist.canonical_name,
|
||||
)
|
||||
if options.list_format == "columns" and packages:
|
||||
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":
|
||||
elif options.list_format == 'freeze':
|
||||
for dist in packages:
|
||||
if options.verbose >= 1:
|
||||
write_output(
|
||||
"%s==%s (%s)", dist.raw_name, dist.version, dist.location
|
||||
'%s==%s (%s)', dist.raw_name, dist.version, dist.location,
|
||||
)
|
||||
else:
|
||||
write_output("%s==%s", dist.raw_name, dist.version)
|
||||
elif options.list_format == "json":
|
||||
write_output('%s==%s', dist.raw_name, dist.version)
|
||||
elif options.list_format == 'json':
|
||||
write_output(format_for_json(packages, options))
|
||||
|
||||
def output_package_listing_columns(
|
||||
self, data: List[List[str]], header: List[str]
|
||||
self, data: list[list[str]], header: list[str],
|
||||
) -> None:
|
||||
# insert the header first: we need to know the size of column names
|
||||
if len(data) > 0:
|
||||
|
|
@ -290,33 +299,33 @@ class ListCommand(IndexGroupCommand):
|
|||
|
||||
# Create and add a separator.
|
||||
if len(data) > 0:
|
||||
pkg_strings.insert(1, " ".join(map(lambda x: "-" * x, sizes)))
|
||||
pkg_strings.insert(1, ' '.join(map(lambda x: '-' * x, sizes)))
|
||||
|
||||
for val in pkg_strings:
|
||||
write_output(val)
|
||||
|
||||
|
||||
def format_for_columns(
|
||||
pkgs: "_ProcessedDists", options: Values
|
||||
) -> Tuple[List[List[str]], List[str]]:
|
||||
pkgs: _ProcessedDists, options: Values,
|
||||
) -> tuple[list[list[str]], list[str]]:
|
||||
"""
|
||||
Convert the package data into something usable
|
||||
by output_package_listing_columns.
|
||||
"""
|
||||
header = ["Package", "Version"]
|
||||
header = ['Package', 'Version']
|
||||
|
||||
running_outdated = options.outdated
|
||||
if running_outdated:
|
||||
header.extend(["Latest", "Type"])
|
||||
header.extend(['Latest', 'Type'])
|
||||
|
||||
has_editables = any(x.editable for x in pkgs)
|
||||
if has_editables:
|
||||
header.append("Editable project location")
|
||||
header.append('Editable project location')
|
||||
|
||||
if options.verbose >= 1:
|
||||
header.append("Location")
|
||||
header.append('Location')
|
||||
if options.verbose >= 1:
|
||||
header.append("Installer")
|
||||
header.append('Installer')
|
||||
|
||||
data = []
|
||||
for proj in pkgs:
|
||||
|
|
@ -329,10 +338,10 @@ def format_for_columns(
|
|||
row.append(proj.latest_filetype)
|
||||
|
||||
if has_editables:
|
||||
row.append(proj.editable_project_location or "")
|
||||
row.append(proj.editable_project_location or '')
|
||||
|
||||
if options.verbose >= 1:
|
||||
row.append(proj.location or "")
|
||||
row.append(proj.location or '')
|
||||
if options.verbose >= 1:
|
||||
row.append(proj.installer)
|
||||
|
||||
|
|
@ -341,21 +350,21 @@ def format_for_columns(
|
|||
return data, header
|
||||
|
||||
|
||||
def format_for_json(packages: "_ProcessedDists", options: Values) -> str:
|
||||
def format_for_json(packages: _ProcessedDists, options: Values) -> str:
|
||||
data = []
|
||||
for dist in packages:
|
||||
info = {
|
||||
"name": dist.raw_name,
|
||||
"version": str(dist.version),
|
||||
'name': dist.raw_name,
|
||||
'version': str(dist.version),
|
||||
}
|
||||
if options.verbose >= 1:
|
||||
info["location"] = dist.location or ""
|
||||
info["installer"] = dist.installer
|
||||
info['location'] = dist.location or ''
|
||||
info['installer'] = dist.installer
|
||||
if options.outdated:
|
||||
info["latest_version"] = str(dist.latest_version)
|
||||
info["latest_filetype"] = dist.latest_filetype
|
||||
info['latest_version'] = str(dist.latest_version)
|
||||
info['latest_filetype'] = dist.latest_filetype
|
||||
editable_project_location = dist.editable_project_location
|
||||
if editable_project_location:
|
||||
info["editable_project_location"] = editable_project_location
|
||||
info['editable_project_location'] = editable_project_location
|
||||
data.append(info)
|
||||
return json.dumps(data)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import shutil
|
||||
import sys
|
||||
|
|
@ -5,19 +7,22 @@ import textwrap
|
|||
import xmlrpc.client
|
||||
from collections import OrderedDict
|
||||
from optparse import Values
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional
|
||||
|
||||
from pip._vendor.packaging.version import parse as parse_version
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
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.cli.status_codes import NO_MATCHES_FOUND
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.exceptions import CommandError
|
||||
from pip._internal.metadata import get_default_environment
|
||||
from pip._internal.models.index import PyPI
|
||||
from pip._internal.network.xmlrpc import PipXmlrpcTransport
|
||||
from pip._internal.utils.logging import indent_log
|
||||
from pip._internal.utils.misc import write_output
|
||||
from pip._vendor.packaging.version import parse as parse_version
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import TypedDict
|
||||
|
|
@ -25,7 +30,7 @@ if TYPE_CHECKING:
|
|||
class TransformedHit(TypedDict):
|
||||
name: str
|
||||
summary: str
|
||||
versions: List[str]
|
||||
versions: list[str]
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -40,19 +45,19 @@ class SearchCommand(Command, SessionCommandMixin):
|
|||
|
||||
def add_options(self) -> None:
|
||||
self.cmd_opts.add_option(
|
||||
"-i",
|
||||
"--index",
|
||||
dest="index",
|
||||
metavar="URL",
|
||||
'-i',
|
||||
'--index',
|
||||
dest='index',
|
||||
metavar='URL',
|
||||
default=PyPI.pypi_url,
|
||||
help="Base URL of Python Package Index (default %default)",
|
||||
help='Base URL of Python Package Index (default %default)',
|
||||
)
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
if not args:
|
||||
raise CommandError("Missing required argument (search query).")
|
||||
raise CommandError('Missing required argument (search query).')
|
||||
query = args
|
||||
pypi_hits = self.search(query, options)
|
||||
hits = transform_hits(pypi_hits)
|
||||
|
|
@ -66,7 +71,7 @@ class SearchCommand(Command, SessionCommandMixin):
|
|||
return SUCCESS
|
||||
return NO_MATCHES_FOUND
|
||||
|
||||
def search(self, query: List[str], options: Values) -> List[Dict[str, str]]:
|
||||
def search(self, query: list[str], options: Values) -> list[dict[str, str]]:
|
||||
index_url = options.index
|
||||
|
||||
session = self.get_default_session(options)
|
||||
|
|
@ -74,9 +79,9 @@ class SearchCommand(Command, SessionCommandMixin):
|
|||
transport = PipXmlrpcTransport(index_url, session)
|
||||
pypi = xmlrpc.client.ServerProxy(index_url, transport)
|
||||
try:
|
||||
hits = pypi.search({"name": query, "summary": query}, "or")
|
||||
hits = pypi.search({'name': query, 'summary': query}, 'or')
|
||||
except xmlrpc.client.Fault as fault:
|
||||
message = "XMLRPC request failed [code: {code}]\n{string}".format(
|
||||
message = 'XMLRPC request failed [code: {code}]\n{string}'.format(
|
||||
code=fault.faultCode,
|
||||
string=fault.faultString,
|
||||
)
|
||||
|
|
@ -85,30 +90,30 @@ class SearchCommand(Command, SessionCommandMixin):
|
|||
return hits
|
||||
|
||||
|
||||
def transform_hits(hits: List[Dict[str, str]]) -> List["TransformedHit"]:
|
||||
def transform_hits(hits: 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: Dict[str, "TransformedHit"] = OrderedDict()
|
||||
packages: dict[str, TransformedHit] = OrderedDict()
|
||||
for hit in hits:
|
||||
name = hit["name"]
|
||||
summary = hit["summary"]
|
||||
version = hit["version"]
|
||||
name = hit['name']
|
||||
summary = hit['summary']
|
||||
version = hit['version']
|
||||
|
||||
if name not in packages.keys():
|
||||
packages[name] = {
|
||||
"name": name,
|
||||
"summary": summary,
|
||||
"versions": [version],
|
||||
'name': name,
|
||||
'summary': summary,
|
||||
'versions': [version],
|
||||
}
|
||||
else:
|
||||
packages[name]["versions"].append(version)
|
||||
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
|
||||
if version == highest_version(packages[name]['versions']):
|
||||
packages[name]['summary'] = summary
|
||||
|
||||
return list(packages.values())
|
||||
|
||||
|
|
@ -119,23 +124,23 @@ def print_dist_installation_info(name: str, latest: str) -> None:
|
|||
if dist is not None:
|
||||
with indent_log():
|
||||
if dist.version == latest:
|
||||
write_output("INSTALLED: %s (latest)", dist.version)
|
||||
write_output('INSTALLED: %s (latest)', dist.version)
|
||||
else:
|
||||
write_output("INSTALLED: %s", dist.version)
|
||||
write_output('INSTALLED: %s', dist.version)
|
||||
if parse_version(latest).pre:
|
||||
write_output(
|
||||
"LATEST: %s (pre-release; install"
|
||||
" with `pip install --pre`)",
|
||||
'LATEST: %s (pre-release; install'
|
||||
' with `pip install --pre`)',
|
||||
latest,
|
||||
)
|
||||
else:
|
||||
write_output("LATEST: %s", latest)
|
||||
write_output('LATEST: %s', latest)
|
||||
|
||||
|
||||
def print_results(
|
||||
hits: List["TransformedHit"],
|
||||
name_column_width: Optional[int] = None,
|
||||
terminal_width: Optional[int] = None,
|
||||
hits: list[TransformedHit],
|
||||
name_column_width: int | None = None,
|
||||
terminal_width: int | None = None,
|
||||
) -> None:
|
||||
if not hits:
|
||||
return
|
||||
|
|
@ -143,26 +148,26 @@ def print_results(
|
|||
name_column_width = (
|
||||
max(
|
||||
[
|
||||
len(hit["name"]) + len(highest_version(hit.get("versions", ["-"])))
|
||||
len(hit['name']) + len(highest_version(hit.get('versions', ['-'])))
|
||||
for hit in hits
|
||||
]
|
||||
)
|
||||
+ 4
|
||||
],
|
||||
) +
|
||||
4
|
||||
)
|
||||
|
||||
for hit in hits:
|
||||
name = hit["name"]
|
||||
summary = hit["summary"] or ""
|
||||
latest = highest_version(hit.get("versions", ["-"]))
|
||||
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)
|
||||
summary = ('\n' + ' ' * (name_column_width + 3)).join(summary_lines)
|
||||
|
||||
name_latest = f"{name} ({latest})"
|
||||
line = f"{name_latest:{name_column_width}} - {summary}"
|
||||
name_latest = f'{name} ({latest})'
|
||||
line = f'{name_latest:{name_column_width}} - {summary}'
|
||||
try:
|
||||
write_output(line)
|
||||
print_dist_installation_info(name, latest)
|
||||
|
|
@ -170,5 +175,5 @@ def print_results(
|
|||
pass
|
||||
|
||||
|
||||
def highest_version(versions: List[str]) -> str:
|
||||
def highest_version(versions: list[str]) -> str:
|
||||
return max(versions, key=parse_version)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from optparse import Values
|
||||
from typing import Iterator, List, NamedTuple, Optional
|
||||
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
from typing import Iterator
|
||||
from typing import List
|
||||
from typing import NamedTuple
|
||||
from typing import Optional
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.status_codes import ERROR, SUCCESS
|
||||
from pip._internal.metadata import BaseDistribution, get_default_environment
|
||||
from pip._internal.cli.status_codes import ERROR
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.metadata import BaseDistribution
|
||||
from pip._internal.metadata import get_default_environment
|
||||
from pip._internal.utils.misc import write_output
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -25,25 +31,25 @@ class ShowCommand(Command):
|
|||
|
||||
def add_options(self) -> None:
|
||||
self.cmd_opts.add_option(
|
||||
"-f",
|
||||
"--files",
|
||||
dest="files",
|
||||
action="store_true",
|
||||
'-f',
|
||||
'--files',
|
||||
dest='files',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="Show the full list of installed files for each package.",
|
||||
help='Show the full list of installed files for each package.',
|
||||
)
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
if not args:
|
||||
logger.warning("ERROR: Please provide a package name or names.")
|
||||
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
|
||||
results, list_files=options.files, verbose=options.verbose,
|
||||
):
|
||||
return ERROR
|
||||
return SUCCESS
|
||||
|
|
@ -53,21 +59,21 @@ class _PackageInfo(NamedTuple):
|
|||
name: str
|
||||
version: str
|
||||
location: str
|
||||
requires: List[str]
|
||||
required_by: List[str]
|
||||
requires: list[str]
|
||||
required_by: list[str]
|
||||
installer: str
|
||||
metadata_version: str
|
||||
classifiers: List[str]
|
||||
classifiers: list[str]
|
||||
summary: str
|
||||
homepage: str
|
||||
author: str
|
||||
author_email: str
|
||||
license: str
|
||||
entry_points: List[str]
|
||||
files: Optional[List[str]]
|
||||
entry_points: list[str]
|
||||
files: list[str] | None
|
||||
|
||||
|
||||
def search_packages_info(query: List[str]) -> Iterator[_PackageInfo]:
|
||||
def search_packages_info(query: list[str]) -> Iterator[_PackageInfo]:
|
||||
"""
|
||||
Gather details from installed distributions. Print distribution name,
|
||||
version, location, and installed files. Installed files requires a
|
||||
|
|
@ -79,14 +85,14 @@ def search_packages_info(query: List[str]) -> Iterator[_PackageInfo]:
|
|||
installed = {dist.canonical_name: dist for dist in env.iter_distributions()}
|
||||
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]
|
||||
[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))
|
||||
logger.warning('Package(s) not found: %s', ', '.join(missing))
|
||||
|
||||
def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]:
|
||||
return (
|
||||
dist.metadata["Name"] or "UNKNOWN"
|
||||
dist.metadata['Name'] or 'UNKNOWN'
|
||||
for dist in installed.values()
|
||||
if current_dist.canonical_name
|
||||
in {canonicalize_name(d.name) for d in dist.iter_dependencies()}
|
||||
|
|
@ -102,14 +108,14 @@ def search_packages_info(query: List[str]) -> Iterator[_PackageInfo]:
|
|||
required_by = sorted(_get_requiring_packages(dist), key=str.lower)
|
||||
|
||||
try:
|
||||
entry_points_text = dist.read_text("entry_points.txt")
|
||||
entry_points_text = dist.read_text('entry_points.txt')
|
||||
entry_points = entry_points_text.splitlines(keepends=False)
|
||||
except FileNotFoundError:
|
||||
entry_points = []
|
||||
|
||||
files_iter = dist.iter_declared_entries()
|
||||
if files_iter is None:
|
||||
files: Optional[List[str]] = None
|
||||
files: list[str] | None = None
|
||||
else:
|
||||
files = sorted(files_iter)
|
||||
|
||||
|
|
@ -118,17 +124,17 @@ def search_packages_info(query: List[str]) -> Iterator[_PackageInfo]:
|
|||
yield _PackageInfo(
|
||||
name=dist.raw_name,
|
||||
version=str(dist.version),
|
||||
location=dist.location or "",
|
||||
location=dist.location or '',
|
||||
requires=requires,
|
||||
required_by=required_by,
|
||||
installer=dist.installer,
|
||||
metadata_version=dist.metadata_version or "",
|
||||
classifiers=metadata.get_all("Classifier", []),
|
||||
summary=metadata.get("Summary", ""),
|
||||
homepage=metadata.get("Home-page", ""),
|
||||
author=metadata.get("Author", ""),
|
||||
author_email=metadata.get("Author-email", ""),
|
||||
license=metadata.get("License", ""),
|
||||
metadata_version=dist.metadata_version or '',
|
||||
classifiers=metadata.get_all('Classifier', []),
|
||||
summary=metadata.get('Summary', ''),
|
||||
homepage=metadata.get('Home-page', ''),
|
||||
author=metadata.get('Author', ''),
|
||||
author_email=metadata.get('Author-email', ''),
|
||||
license=metadata.get('License', ''),
|
||||
entry_points=entry_points,
|
||||
files=files,
|
||||
)
|
||||
|
|
@ -146,33 +152,33 @@ def print_results(
|
|||
for i, dist in enumerate(distributions):
|
||||
results_printed = True
|
||||
if i > 0:
|
||||
write_output("---")
|
||||
write_output('---')
|
||||
|
||||
write_output("Name: %s", dist.name)
|
||||
write_output("Version: %s", dist.version)
|
||||
write_output("Summary: %s", dist.summary)
|
||||
write_output("Home-page: %s", dist.homepage)
|
||||
write_output("Author: %s", dist.author)
|
||||
write_output("Author-email: %s", dist.author_email)
|
||||
write_output("License: %s", dist.license)
|
||||
write_output("Location: %s", dist.location)
|
||||
write_output("Requires: %s", ", ".join(dist.requires))
|
||||
write_output("Required-by: %s", ", ".join(dist.required_by))
|
||||
write_output('Name: %s', dist.name)
|
||||
write_output('Version: %s', dist.version)
|
||||
write_output('Summary: %s', dist.summary)
|
||||
write_output('Home-page: %s', dist.homepage)
|
||||
write_output('Author: %s', dist.author)
|
||||
write_output('Author-email: %s', dist.author_email)
|
||||
write_output('License: %s', dist.license)
|
||||
write_output('Location: %s', dist.location)
|
||||
write_output('Requires: %s', ', '.join(dist.requires))
|
||||
write_output('Required-by: %s', ', '.join(dist.required_by))
|
||||
|
||||
if verbose:
|
||||
write_output("Metadata-Version: %s", dist.metadata_version)
|
||||
write_output("Installer: %s", dist.installer)
|
||||
write_output("Classifiers:")
|
||||
write_output('Metadata-Version: %s', dist.metadata_version)
|
||||
write_output('Installer: %s', dist.installer)
|
||||
write_output('Classifiers:')
|
||||
for classifier in dist.classifiers:
|
||||
write_output(" %s", classifier)
|
||||
write_output("Entry-points:")
|
||||
write_output(' %s', classifier)
|
||||
write_output('Entry-points:')
|
||||
for entry in dist.entry_points:
|
||||
write_output(" %s", entry.strip())
|
||||
write_output(' %s', entry.strip())
|
||||
if list_files:
|
||||
write_output("Files:")
|
||||
write_output('Files:')
|
||||
if dist.files is None:
|
||||
write_output("Cannot locate RECORD or installed-files.txt")
|
||||
write_output('Cannot locate RECORD or installed-files.txt')
|
||||
else:
|
||||
for line in dist.files:
|
||||
write_output(" %s", line.strip())
|
||||
write_output(' %s', line.strip())
|
||||
return results_printed
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from optparse import Values
|
||||
from typing import List
|
||||
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
|
||||
from pip._internal.cli.base_command import Command
|
||||
from pip._internal.cli.req_command import SessionCommandMixin, warn_if_run_as_root
|
||||
from pip._internal.cli.req_command import SessionCommandMixin
|
||||
from pip._internal.cli.req_command import warn_if_run_as_root
|
||||
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.req.constructors import install_req_from_line
|
||||
from pip._internal.req.constructors import install_req_from_parsed_requirement
|
||||
from pip._internal.utils.misc import protect_pip_from_modification_on_windows
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -35,28 +35,28 @@ class UninstallCommand(Command, SessionCommandMixin):
|
|||
|
||||
def add_options(self) -> None:
|
||||
self.cmd_opts.add_option(
|
||||
"-r",
|
||||
"--requirement",
|
||||
dest="requirements",
|
||||
action="append",
|
||||
'-r',
|
||||
'--requirement',
|
||||
dest='requirements',
|
||||
action='append',
|
||||
default=[],
|
||||
metavar="file",
|
||||
metavar='file',
|
||||
help=(
|
||||
"Uninstall all the packages listed in the given requirements "
|
||||
"file. This option can be used multiple times."
|
||||
'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",
|
||||
'-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: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
session = self.get_default_session(options)
|
||||
|
||||
reqs_to_uninstall = {}
|
||||
|
|
@ -69,28 +69,28 @@ class UninstallCommand(Command, SessionCommandMixin):
|
|||
reqs_to_uninstall[canonicalize_name(req.name)] = req
|
||||
else:
|
||||
logger.warning(
|
||||
"Invalid requirement: %r ignored -"
|
||||
" the uninstall command expects named"
|
||||
" requirements.",
|
||||
'Invalid requirement: %r ignored -'
|
||||
' the uninstall command expects named'
|
||||
' requirements.',
|
||||
name,
|
||||
)
|
||||
for filename in options.requirements:
|
||||
for parsed_req in parse_requirements(
|
||||
filename, options=options, session=session
|
||||
filename, options=options, session=session,
|
||||
):
|
||||
req = install_req_from_parsed_requirement(
|
||||
parsed_req, isolated=options.isolated_mode
|
||||
parsed_req, isolated=options.isolated_mode,
|
||||
)
|
||||
if req.name:
|
||||
reqs_to_uninstall[canonicalize_name(req.name)] = req
|
||||
if not reqs_to_uninstall:
|
||||
raise InstallationError(
|
||||
f"You must give at least one requirement to {self.name} (see "
|
||||
f'"pip help {self.name}")'
|
||||
f'You must give at least one requirement to {self.name} (see '
|
||||
f'"pip help {self.name}")',
|
||||
)
|
||||
|
||||
protect_pip_from_modification_on_windows(
|
||||
modifying_pip="pip" in reqs_to_uninstall
|
||||
modifying_pip='pip' in reqs_to_uninstall,
|
||||
)
|
||||
|
||||
for req in reqs_to_uninstall.values():
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
|
|
@ -6,14 +8,17 @@ from typing import List
|
|||
|
||||
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.req_command import RequirementCommand
|
||||
from pip._internal.cli.req_command import with_cleanup
|
||||
from pip._internal.cli.status_codes import SUCCESS
|
||||
from pip._internal.exceptions import CommandError
|
||||
from pip._internal.req.req_install import InstallRequirement
|
||||
from pip._internal.req.req_tracker import get_requirement_tracker
|
||||
from pip._internal.utils.misc import ensure_dir, normalize_path
|
||||
from pip._internal.utils.misc import ensure_dir
|
||||
from pip._internal.utils.misc import normalize_path
|
||||
from pip._internal.utils.temp_dir import TempDirectory
|
||||
from pip._internal.wheel_builder import build, should_build_for_wheel_command
|
||||
from pip._internal.wheel_builder import build
|
||||
from pip._internal.wheel_builder import should_build_for_wheel_command
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -43,14 +48,14 @@ class WheelCommand(RequirementCommand):
|
|||
def add_options(self) -> None:
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"-w",
|
||||
"--wheel-dir",
|
||||
dest="wheel_dir",
|
||||
metavar="dir",
|
||||
'-w',
|
||||
'--wheel-dir',
|
||||
dest='wheel_dir',
|
||||
metavar='dir',
|
||||
default=os.curdir,
|
||||
help=(
|
||||
"Build wheels into <dir>, where the default is the "
|
||||
"current working directory."
|
||||
'Build wheels into <dir>, where the default is the '
|
||||
'current working directory.'
|
||||
),
|
||||
)
|
||||
self.cmd_opts.add_option(cmdoptions.no_binary())
|
||||
|
|
@ -68,9 +73,9 @@ class WheelCommand(RequirementCommand):
|
|||
self.cmd_opts.add_option(cmdoptions.progress_bar())
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"--no-verify",
|
||||
dest="no_verify",
|
||||
action="store_true",
|
||||
'--no-verify',
|
||||
dest='no_verify',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="Don't verify if built wheel is valid.",
|
||||
)
|
||||
|
|
@ -79,12 +84,12 @@ class WheelCommand(RequirementCommand):
|
|||
self.cmd_opts.add_option(cmdoptions.global_options())
|
||||
|
||||
self.cmd_opts.add_option(
|
||||
"--pre",
|
||||
action="store_true",
|
||||
'--pre',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=(
|
||||
"Include pre-release and development versions. By default, "
|
||||
"pip only finds stable versions."
|
||||
'Include pre-release and development versions. By default, '
|
||||
'pip only finds stable versions.'
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -99,7 +104,7 @@ class WheelCommand(RequirementCommand):
|
|||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
@with_cleanup
|
||||
def run(self, options: Values, args: List[str]) -> int:
|
||||
def run(self, options: Values, args: list[str]) -> int:
|
||||
cmdoptions.check_install_build_global(options)
|
||||
|
||||
session = self.get_default_session(options)
|
||||
|
|
@ -114,7 +119,7 @@ class WheelCommand(RequirementCommand):
|
|||
|
||||
directory = TempDirectory(
|
||||
delete=not options.no_clean,
|
||||
kind="wheel",
|
||||
kind='wheel',
|
||||
globally_managed=True,
|
||||
)
|
||||
|
||||
|
|
@ -144,7 +149,7 @@ class WheelCommand(RequirementCommand):
|
|||
|
||||
requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
|
||||
|
||||
reqs_to_build: List[InstallRequirement] = []
|
||||
reqs_to_build: list[InstallRequirement] = []
|
||||
for req in requirement_set.requirements.values():
|
||||
if req.is_wheel:
|
||||
preparer.save_linked_requirement(req)
|
||||
|
|
@ -167,12 +172,12 @@ class WheelCommand(RequirementCommand):
|
|||
shutil.copy(req.local_file_path, options.wheel_dir)
|
||||
except OSError as e:
|
||||
logger.warning(
|
||||
"Building wheel for %s failed: %s",
|
||||
'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")
|
||||
raise CommandError('Failed to build one or more wheels')
|
||||
|
||||
return SUCCESS
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue