summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/pip/_internal/commands
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.11/site-packages/pip/_internal/commands')
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__init__.py132
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-311.pycbin0 -> 4462 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/cache.cpython-311.pycbin0 -> 10882 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/check.cpython-311.pycbin0 -> 2417 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/completion.cpython-311.pycbin0 -> 5632 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-311.pycbin0 -> 14860 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/debug.cpython-311.pycbin0 -> 12205 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/download.cpython-311.pycbin0 -> 7951 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-311.pycbin0 -> 4667 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/hash.cpython-311.pycbin0 -> 3364 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/help.cpython-311.pycbin0 -> 1976 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/index.cpython-311.pycbin0 -> 7730 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-311.pycbin0 -> 4452 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/install.cpython-311.pycbin0 -> 31153 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/list.cpython-311.pycbin0 -> 17256 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/search.cpython-311.pycbin0 -> 8958 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/show.cpython-311.pycbin0 -> 11301 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-311.pycbin0 -> 5152 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-311.pycbin0 -> 9408 bytes
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/cache.py225
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/check.py54
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/completion.py130
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/configuration.py280
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/debug.py201
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/download.py147
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/freeze.py108
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/hash.py59
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/help.py41
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/index.py139
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/inspect.py92
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/install.py774
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/list.py368
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/search.py174
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/show.py189
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/uninstall.py113
-rw-r--r--venv/lib/python3.11/site-packages/pip/_internal/commands/wheel.py183
36 files changed, 3409 insertions, 0 deletions
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__init__.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/__init__.py
new file mode 100644
index 0000000..858a410
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__init__.py
@@ -0,0 +1,132 @@
+"""
+Package containing all pip commands
+"""
+
+import importlib
+from collections import namedtuple
+from typing import Any, Dict, Optional
+
+from pip._internal.cli.base_command import Command
+
+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`.
+# - The ordering matters for help display.
+#
+# 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.",
+ ),
+ "download": CommandInfo(
+ "pip._internal.commands.download",
+ "DownloadCommand",
+ "Download packages.",
+ ),
+ "uninstall": CommandInfo(
+ "pip._internal.commands.uninstall",
+ "UninstallCommand",
+ "Uninstall packages.",
+ ),
+ "freeze": CommandInfo(
+ "pip._internal.commands.freeze",
+ "FreezeCommand",
+ "Output installed packages in requirements format.",
+ ),
+ "inspect": CommandInfo(
+ "pip._internal.commands.inspect",
+ "InspectCommand",
+ "Inspect the python environment.",
+ ),
+ "list": CommandInfo(
+ "pip._internal.commands.list",
+ "ListCommand",
+ "List installed packages.",
+ ),
+ "show": CommandInfo(
+ "pip._internal.commands.show",
+ "ShowCommand",
+ "Show information about installed packages.",
+ ),
+ "check": CommandInfo(
+ "pip._internal.commands.check",
+ "CheckCommand",
+ "Verify installed packages have compatible dependencies.",
+ ),
+ "config": CommandInfo(
+ "pip._internal.commands.configuration",
+ "ConfigurationCommand",
+ "Manage local and global configuration.",
+ ),
+ "search": CommandInfo(
+ "pip._internal.commands.search",
+ "SearchCommand",
+ "Search PyPI for packages.",
+ ),
+ "cache": CommandInfo(
+ "pip._internal.commands.cache",
+ "CacheCommand",
+ "Inspect and manage pip's wheel cache.",
+ ),
+ "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.",
+ ),
+ "hash": CommandInfo(
+ "pip._internal.commands.hash",
+ "HashCommand",
+ "Compute hashes of package archives.",
+ ),
+ "completion": CommandInfo(
+ "pip._internal.commands.completion",
+ "CompletionCommand",
+ "A helper command used for command completion.",
+ ),
+ "debug": CommandInfo(
+ "pip._internal.commands.debug",
+ "DebugCommand",
+ "Show information useful for debugging.",
+ ),
+ "help": CommandInfo(
+ "pip._internal.commands.help",
+ "HelpCommand",
+ "Show help for commands.",
+ ),
+}
+
+
+def create_command(name: str, **kwargs: Any) -> Command:
+ """
+ Create an instance of the Command class with the given name.
+ """
+ module_path, class_name, summary = commands_dict[name]
+ module = importlib.import_module(module_path)
+ command_class = getattr(module, class_name)
+ command = command_class(name=name, summary=summary, **kwargs)
+
+ return command
+
+
+def get_similar_commands(name: str) -> Optional[str]:
+ """Command name auto-correct."""
+ from difflib import get_close_matches
+
+ name = name.lower()
+
+ close_commands = get_close_matches(name, commands_dict.keys())
+
+ if close_commands:
+ return close_commands[0]
+ else:
+ return None
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..a6dc288
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/cache.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/cache.cpython-311.pyc
new file mode 100644
index 0000000..f0a8329
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/cache.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/check.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/check.cpython-311.pyc
new file mode 100644
index 0000000..25a1351
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/check.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/completion.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/completion.cpython-311.pyc
new file mode 100644
index 0000000..bde80a0
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/completion.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-311.pyc
new file mode 100644
index 0000000..ddef073
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/debug.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/debug.cpython-311.pyc
new file mode 100644
index 0000000..cd6954d
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/debug.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/download.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/download.cpython-311.pyc
new file mode 100644
index 0000000..d0a2f02
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/download.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-311.pyc
new file mode 100644
index 0000000..399e976
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/hash.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/hash.cpython-311.pyc
new file mode 100644
index 0000000..6abf8bc
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/hash.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/help.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/help.cpython-311.pyc
new file mode 100644
index 0000000..4d3eb4e
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/help.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/index.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/index.cpython-311.pyc
new file mode 100644
index 0000000..6493e2d
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/index.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-311.pyc
new file mode 100644
index 0000000..5b8c2f9
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/install.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/install.cpython-311.pyc
new file mode 100644
index 0000000..121e229
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/install.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/list.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/list.cpython-311.pyc
new file mode 100644
index 0000000..22c139e
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/list.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/search.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/search.cpython-311.pyc
new file mode 100644
index 0000000..481a62f
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/search.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/show.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/show.cpython-311.pyc
new file mode 100644
index 0000000..a733863
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/show.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-311.pyc
new file mode 100644
index 0000000..a940a04
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-311.pyc
new file mode 100644
index 0000000..cbe067f
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/cache.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/cache.py
new file mode 100644
index 0000000..3283361
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/cache.py
@@ -0,0 +1,225 @@
+import os
+import textwrap
+from optparse import Values
+from typing import Any, List
+
+from pip._internal.cli.base_command import Command
+from pip._internal.cli.status_codes import ERROR, SUCCESS
+from pip._internal.exceptions import CommandError, PipError
+from pip._internal.utils import filesystem
+from pip._internal.utils.logging import getLogger
+
+logger = getLogger(__name__)
+
+
+class CacheCommand(Command):
+ """
+ Inspect and manage pip's wheel cache.
+
+ Subcommands:
+
+ - dir: Show the cache directory.
+ - info: Show information about the cache.
+ - list: List filenames of packages stored in the cache.
+ - remove: Remove one or more package from the cache.
+ - purge: Remove all items from the cache.
+
+ ``<pattern>`` can be a glob expression or a package name.
+ """
+
+ ignore_require_venv = True
+ usage = """
+ %prog dir
+ %prog info
+ %prog list [<pattern>] [--format=[human, abspath]]
+ %prog remove <pattern>
+ %prog purge
+ """
+
+ 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",
+ )
+
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ 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,
+ }
+
+ if not options.cache_dir:
+ logger.error("pip cache commands can not function since cache is disabled.")
+ return ERROR
+
+ # Determine action
+ if not args or args[0] not in handlers:
+ logger.error(
+ "Need an action (%s) to perform.",
+ ", ".join(sorted(handlers)),
+ )
+ return ERROR
+
+ action = args[0]
+
+ # Error handling happens here, not in the action-handlers.
+ try:
+ handlers[action](options, args[1:])
+ except PipError as e:
+ logger.error(e.args[0])
+ return ERROR
+
+ return SUCCESS
+
+ def get_cache_dir(self, options: Values, args: List[Any]) -> None:
+ if args:
+ raise CommandError("Too many arguments")
+
+ logger.info(options.cache_dir)
+
+ def get_cache_info(self, options: Values, args: List[Any]) -> None:
+ if args:
+ raise CommandError("Too many arguments")
+
+ num_http_files = len(self._find_http_files(options))
+ num_packages = len(self._find_wheels(options, "*"))
+
+ http_cache_location = self._cache_dir(options, "http-v2")
+ old_http_cache_location = self._cache_dir(options, "http")
+ wheels_cache_location = self._cache_dir(options, "wheels")
+ http_cache_size = filesystem.format_size(
+ filesystem.directory_size(http_cache_location)
+ + filesystem.directory_size(old_http_cache_location)
+ )
+ wheels_cache_size = filesystem.format_directory_size(wheels_cache_location)
+
+ message = (
+ textwrap.dedent(
+ """
+ Package index page cache location (pip v23.3+): {http_cache_location}
+ Package index page cache location (older pips): {old_http_cache_location}
+ Package index page cache size: {http_cache_size}
+ Number of HTTP files: {num_http_files}
+ Locally built wheels location: {wheels_cache_location}
+ Locally built wheels size: {wheels_cache_size}
+ Number of locally built wheels: {package_count}
+ """ # noqa: E501
+ )
+ .format(
+ http_cache_location=http_cache_location,
+ old_http_cache_location=old_http_cache_location,
+ http_cache_size=http_cache_size,
+ num_http_files=num_http_files,
+ wheels_cache_location=wheels_cache_location,
+ package_count=num_packages,
+ wheels_cache_size=wheels_cache_size,
+ )
+ .strip()
+ )
+
+ logger.info(message)
+
+ def list_cache_items(self, options: Values, args: List[Any]) -> None:
+ if len(args) > 1:
+ raise CommandError("Too many arguments")
+
+ if args:
+ pattern = args[0]
+ else:
+ pattern = "*"
+
+ files = self._find_wheels(options, pattern)
+ if options.list_format == "human":
+ self.format_for_human(files)
+ else:
+ self.format_for_abspath(files)
+
+ def format_for_human(self, files: List[str]) -> None:
+ if not files:
+ logger.info("No locally built wheels 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)))
+
+ def format_for_abspath(self, files: List[str]) -> None:
+ if files:
+ logger.info("\n".join(sorted(files)))
+
+ def remove_cache_items(self, options: Values, args: List[Any]) -> None:
+ if len(args) > 1:
+ raise CommandError("Too many arguments")
+
+ if not args:
+ raise CommandError("Please provide a pattern")
+
+ files = self._find_wheels(options, args[0])
+
+ 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 += 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))
+
+ def purge_cache(self, options: Values, args: List[Any]) -> None:
+ if args:
+ raise CommandError("Too many arguments")
+
+ 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]:
+ old_http_dir = self._cache_dir(options, "http")
+ new_http_dir = self._cache_dir(options, "http-v2")
+ return filesystem.find_files(old_http_dir, "*") + filesystem.find_files(
+ new_http_dir, "*"
+ )
+
+ 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
+ #
+ # Additionally, non-alphanumeric values in the distribution are
+ # normalized to underscores (_), meaning hyphens can never occur
+ # before `-{version}`.
+ #
+ # Given that information:
+ # - If the pattern we're given contains a hyphen (-), the user is
+ # providing at least the version. Thus, we can just append `*.whl`
+ # to match the rest of it.
+ # - If the pattern we're given doesn't contain a hyphen (-), the
+ # user is only providing the name. Thus, we append `-*.whl` to
+ # match the hyphen before the version, followed by anything else.
+ #
+ # PEP 427: https://www.python.org/dev/peps/pep-0427/
+ pattern = pattern + ("*.whl" if "-" in pattern else "-*.whl")
+
+ return filesystem.find_files(wheel_dir, pattern)
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/check.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/check.py
new file mode 100644
index 0000000..5efd0a3
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/check.py
@@ -0,0 +1,54 @@
+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,
+ warn_legacy_versions_and_specifiers,
+)
+from pip._internal.utils.misc import write_output
+
+logger = logging.getLogger(__name__)
+
+
+class CheckCommand(Command):
+ """Verify installed packages have compatible dependencies."""
+
+ usage = """
+ %prog [options]"""
+
+ def run(self, options: Values, args: List[str]) -> int:
+ package_set, parsing_probs = create_package_set_from_installed()
+ warn_legacy_versions_and_specifiers(package_set)
+ missing, conflicting = check_package_set(package_set)
+
+ for project_name in missing:
+ version = package_set[project_name].version
+ for dependency in missing[project_name]:
+ write_output(
+ "%s %s requires %s, which is not installed.",
+ project_name,
+ version,
+ dependency[0],
+ )
+
+ for project_name in conflicting:
+ version = package_set[project_name].version
+ for dep_name, dep_version, req in conflicting[project_name]:
+ write_output(
+ "%s %s has requirement %s, but you have %s %s.",
+ project_name,
+ version,
+ req,
+ dep_name,
+ dep_version,
+ )
+
+ if missing or conflicting or parsing_probs:
+ return ERROR
+ else:
+ write_output("No broken requirements found.")
+ return SUCCESS
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/completion.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/completion.py
new file mode 100644
index 0000000..9e89e27
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/completion.py
@@ -0,0 +1,130 @@
+import sys
+import textwrap
+from optparse import Values
+from typing import List
+
+from pip._internal.cli.base_command import Command
+from pip._internal.cli.status_codes import SUCCESS
+from pip._internal.utils.misc import get_prog
+
+BASE_COMPLETION = """
+# pip {shell} completion start{script}# pip {shell} completion end
+"""
+
+COMPLETION_SCRIPTS = {
+ "bash": """
+ _pip_completion()
+ {{
+ COMPREPLY=( $( COMP_WORDS="${{COMP_WORDS[*]}}" \\
+ COMP_CWORD=$COMP_CWORD \\
+ PIP_AUTO_COMPLETE=1 $1 2>/dev/null ) )
+ }}
+ complete -o default -F _pip_completion {prog}
+ """,
+ "zsh": """
+ #compdef -P pip[0-9.]#
+ __pip() {{
+ compadd $( COMP_WORDS="$words[*]" \\
+ COMP_CWORD=$((CURRENT-1)) \\
+ PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null )
+ }}
+ if [[ $zsh_eval_context[-1] == loadautofunc ]]; then
+ # autoload from fpath, call function directly
+ __pip "$@"
+ else
+ # eval/source/. command, register function for later
+ compdef __pip -P 'pip[0-9.]#'
+ fi
+ """,
+ "fish": """
+ function __fish_complete_pip
+ set -lx COMP_WORDS (commandline -o) ""
+ set -lx COMP_CWORD ( \\
+ math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\
+ )
+ set -lx PIP_AUTO_COMPLETE 1
+ string split \\ -- (eval $COMP_WORDS[1])
+ end
+ complete -fa "(__fish_complete_pip)" -c {prog}
+ """,
+ "powershell": """
+ if ((Test-Path Function:\\TabExpansion) -and -not `
+ (Test-Path Function:\\_pip_completeBackup)) {{
+ Rename-Item Function:\\TabExpansion _pip_completeBackup
+ }}
+ function TabExpansion($line, $lastWord) {{
+ $lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
+ if ($lastBlock.StartsWith("{prog} ")) {{
+ $Env:COMP_WORDS=$lastBlock
+ $Env:COMP_CWORD=$lastBlock.Split().Length - 1
+ $Env:PIP_AUTO_COMPLETE=1
+ (& {prog}).Split()
+ Remove-Item Env:COMP_WORDS
+ Remove-Item Env:COMP_CWORD
+ Remove-Item Env:PIP_AUTO_COMPLETE
+ }}
+ elseif (Test-Path Function:\\_pip_completeBackup) {{
+ # Fall back on existing tab expansion
+ _pip_completeBackup $line $lastWord
+ }}
+ }}
+ """,
+}
+
+
+class CompletionCommand(Command):
+ """A helper command to be used for command completion."""
+
+ ignore_require_venv = True
+
+ 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",
+ )
+ self.cmd_opts.add_option(
+ "--zsh",
+ "-z",
+ action="store_const",
+ const="zsh",
+ dest="shell",
+ help="Emit completion code for zsh",
+ )
+ self.cmd_opts.add_option(
+ "--fish",
+ "-f",
+ action="store_const",
+ const="fish",
+ dest="shell",
+ help="Emit completion code for fish",
+ )
+ self.cmd_opts.add_option(
+ "--powershell",
+ "-p",
+ action="store_const",
+ const="powershell",
+ dest="shell",
+ help="Emit completion code for powershell",
+ )
+
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ 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)]
+ if options.shell in shells:
+ script = textwrap.dedent(
+ COMPLETION_SCRIPTS.get(options.shell, "").format(prog=get_prog())
+ )
+ print(BASE_COMPLETION.format(script=script, shell=options.shell))
+ return SUCCESS
+ else:
+ sys.stderr.write(
+ "ERROR: You must pass {}\n".format(" or ".join(shell_options))
+ )
+ return SUCCESS
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/configuration.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/configuration.py
new file mode 100644
index 0000000..1a1dc6b
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/configuration.py
@@ -0,0 +1,280 @@
+import logging
+import os
+import subprocess
+from optparse import Values
+from typing import Any, List, 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.exceptions import PipError
+from pip._internal.utils.logging import indent_log
+from pip._internal.utils.misc import get_prog, write_output
+
+logger = logging.getLogger(__name__)
+
+
+class ConfigurationCommand(Command):
+ """
+ Manage local and global configuration.
+
+ Subcommands:
+
+ - list: List the active configuration (or from the file specified)
+ - edit: Edit the configuration file in an editor
+ - get: Get the value associated with command.option
+ - set: Set the command.option=value
+ - unset: Unset the value associated with command.option
+ - debug: List the configuration files and values defined under them
+
+ Configuration keys should be dot separated command and option name,
+ with the special prefix "global" affecting any command. For example,
+ "pip config set global.index-url https://example.org/" would configure
+ the index url for all commands, but "pip config set download.timeout 10"
+ would configure a 10 second timeout only for "pip download" commands.
+
+ If none of --user, --global and --site are passed, a virtual
+ environment configuration file is used if one is active and the file
+ exists. Otherwise, all modifications happen to the user file by
+ default.
+ """
+
+ ignore_require_venv = True
+ usage = """
+ %prog [<file-option>] list
+ %prog [<file-option>] [--editor <editor-path>] edit
+
+ %prog [<file-option>] get command.option
+ %prog [<file-option>] set command.option value
+ %prog [<file-option>] unset command.option
+ %prog [<file-option>] debug
+ """
+
+ def add_options(self) -> None:
+ self.cmd_opts.add_option(
+ "--editor",
+ dest="editor",
+ action="store",
+ default=None,
+ help=(
+ "Editor to use to edit the file. Uses VISUAL or EDITOR "
+ "environment variables if not provided."
+ ),
+ )
+
+ self.cmd_opts.add_option(
+ "--global",
+ dest="global_file",
+ action="store_true",
+ default=False,
+ help="Use the system-wide configuration file only",
+ )
+
+ self.cmd_opts.add_option(
+ "--user",
+ dest="user_file",
+ action="store_true",
+ default=False,
+ help="Use the user configuration file only",
+ )
+
+ self.cmd_opts.add_option(
+ "--site",
+ dest="site_file",
+ action="store_true",
+ default=False,
+ help="Use the current environment configuration file only",
+ )
+
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ def run(self, options: 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,
+ }
+
+ # Determine action
+ if not args or args[0] not in handlers:
+ logger.error(
+ "Need an action (%s) to perform.",
+ ", ".join(sorted(handlers)),
+ )
+ return ERROR
+
+ action = args[0]
+
+ # Determine which configuration files are to be loaded
+ # Depends on whether the command is modifying.
+ try:
+ load_only = self._determine_file(
+ options, need_value=(action in ["get", "set", "unset", "edit"])
+ )
+ except PipError as e:
+ logger.error(e.args[0])
+ return ERROR
+
+ # Load a new configuration
+ self.configuration = Configuration(
+ isolated=options.isolated_mode, load_only=load_only
+ )
+ self.configuration.load()
+
+ # Error handling happens here, not in the action-handlers.
+ try:
+ handlers[action](options, args[1:])
+ except PipError as e:
+ logger.error(e.args[0])
+ return ERROR
+
+ return SUCCESS
+
+ def _determine_file(self, options: Values, need_value: bool) -> Optional[Kind]:
+ file_options = [
+ key
+ for key, value in (
+ (kinds.USER, options.user_file),
+ (kinds.GLOBAL, options.global_file),
+ (kinds.SITE, options.site_file),
+ )
+ if value
+ ]
+
+ if not file_options:
+ if not need_value:
+ return None
+ # Default to user, unless there's a site file.
+ elif any(
+ os.path.exists(site_config_file)
+ for site_config_file in get_configuration_files()[kinds.SITE]
+ ):
+ return kinds.SITE
+ else:
+ return kinds.USER
+ elif len(file_options) == 1:
+ return file_options[0]
+
+ raise PipError(
+ "Need exactly one file to operate upon "
+ "(--user, --site, --global) to perform."
+ )
+
+ def list_values(self, options: 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)
+
+ 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)
+
+ 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)
+ self.configuration.unset_value(key)
+
+ self._save_configuration()
+
+ 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.print_env_var_values()
+ # Iterate over config files and print if they exist, and the
+ # key-value pairs present in them if they do
+ for variant, files in sorted(self.configuration.iter_config_files()):
+ write_output("%s:", variant)
+ for fname in files:
+ with indent_log():
+ file_exists = os.path.exists(fname)
+ write_output("%s, exists: %r", fname, file_exists)
+ if file_exists:
+ self.print_config_file_values(variant)
+
+ def print_config_file_values(self, variant: Kind) -> None:
+ """Get key-value pairs from the file of a variant"""
+ for name, value in self.configuration.get_values_in_config(variant).items():
+ with indent_log():
+ write_output("%s: %s", name, value)
+
+ def print_env_var_values(self) -> None:
+ """Get key-values pairs present as environment variables"""
+ write_output("%s:", "env_var")
+ with indent_log():
+ for key, value in sorted(self.configuration.get_environ_vars()):
+ env_var = f"PIP_{key.upper()}"
+ write_output("%s=%r", env_var, value)
+
+ 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.")
+ elif '"' in fname:
+ # This shouldn't happen, unless we see a username like that.
+ # If that happens, we'd appreciate a pull request fixing this.
+ raise PipError(
+ f'Can not open an editor for a file name containing "\n{fname}'
+ )
+
+ try:
+ subprocess.check_call(f'{editor} "{fname}"', shell=True)
+ except FileNotFoundError as e:
+ if not e.filename:
+ e.filename = editor
+ raise
+ except subprocess.CalledProcessError as e:
+ raise PipError(f"Editor Subprocess exited with exit code {e.returncode}")
+
+ 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 = (
+ f"Got unexpected number of arguments, expected {n}. "
+ f'(example: "{get_prog()} config {example}")'
+ )
+ raise PipError(msg)
+
+ if n == 1:
+ return args[0]
+ else:
+ return args
+
+ def _save_configuration(self) -> None:
+ # We successfully ran a modifying command. Need to save the
+ # configuration.
+ try:
+ self.configuration.save()
+ except Exception:
+ logger.exception(
+ "Unable to save configuration. Please report this as a bug."
+ )
+ raise PipError("Internal Error.")
+
+ def _determine_editor(self, options: Values) -> str:
+ if options.editor is not None:
+ return options.editor
+ elif "VISUAL" in os.environ:
+ return os.environ["VISUAL"]
+ elif "EDITOR" in os.environ:
+ return os.environ["EDITOR"]
+ else:
+ raise PipError("Could not determine editor to use.")
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/debug.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/debug.py
new file mode 100644
index 0000000..7e5271c
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/debug.py
@@ -0,0 +1,201 @@
+import importlib.resources
+import locale
+import logging
+import os
+import sys
+from optparse import Values
+from types import ModuleType
+from typing import Any, Dict, List, Optional
+
+import pip._vendor
+from pip._vendor.certifi import where
+from pip._vendor.packaging.version import parse as parse_version
+
+from pip._internal.cli import cmdoptions
+from pip._internal.cli.base_command import Command
+from pip._internal.cli.cmdoptions import make_target_python
+from pip._internal.cli.status_codes import SUCCESS
+from pip._internal.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
+
+logger = logging.getLogger(__name__)
+
+
+def show_value(name: str, value: Any) -> None:
+ logger.info("%s: %s", name, value)
+
+
+def show_sys_implementation() -> None:
+ logger.info("sys.implementation:")
+ implementation_name = sys.implementation.name
+ with indent_log():
+ show_value("name", implementation_name)
+
+
+def create_vendor_txt_map() -> Dict[str, str]:
+ with importlib.resources.open_text("pip._vendor", "vendor.txt") as f:
+ # Purge non version specifying lines.
+ # Also, remove any space prefix or suffixes (including comments).
+ lines = [
+ line.strip().split(" ", 1)[0] for line in f.readlines() if "==" in line
+ ]
+
+ # Transform into "module" -> version dict.
+ return dict(line.split("==", 1) for line in lines)
+
+
+def get_module_from_module_name(module_name: str) -> Optional[ModuleType]:
+ # Module name can be uppercase in vendor.txt for some reason...
+ module_name = module_name.lower().replace("-", "_")
+ # PATCH: setuptools is actually only pkg_resources.
+ if module_name == "setuptools":
+ module_name = "pkg_resources"
+
+ try:
+ __import__(f"pip._vendor.{module_name}", globals(), locals(), level=0)
+ return getattr(pip._vendor, module_name)
+ except ImportError:
+ # We allow 'truststore' to fail to import due
+ # to being unavailable on Python 3.9 and earlier.
+ if module_name == "truststore" and sys.version_info < (3, 10):
+ return None
+ raise
+
+
+def get_vendor_version_from_module(module_name: str) -> Optional[str]:
+ module = get_module_from_module_name(module_name)
+ version = getattr(module, "__version__", None)
+
+ if module and not version:
+ # Try to find version in debundled module info.
+ assert module.__file__ is not None
+ env = get_environment([os.path.dirname(module.__file__)])
+ dist = env.get_distribution(module_name)
+ if dist:
+ version = str(dist.version)
+
+ return version
+
+
+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 = ""
+ actual_version = get_vendor_version_from_module(module_name)
+ if not actual_version:
+ extra_message = (
+ " (Unable to locate actual module version, using"
+ " vendor.txt specified version)"
+ )
+ actual_version = expected_version
+ elif parse_version(actual_version) != parse_version(expected_version):
+ extra_message = (
+ " (CONFLICT: vendor.txt suggests version should"
+ f" be {expected_version})"
+ )
+ logger.info("%s==%s%s", module_name, actual_version, extra_message)
+
+
+def show_vendor_versions() -> None:
+ logger.info("vendored library versions:")
+
+ vendor_txt_versions = create_vendor_txt_map()
+ with indent_log():
+ show_actual_vendor_versions(vendor_txt_versions)
+
+
+def show_tags(options: Values) -> None:
+ tag_limit = 10
+
+ target_python = make_target_python(options)
+ tags = target_python.get_sorted_tags()
+
+ # Display the target options that were explicitly provided.
+ formatted_target = target_python.format_given()
+ suffix = ""
+ if formatted_target:
+ suffix = f" (target: {formatted_target})"
+
+ msg = f"Compatible tags: {len(tags)}{suffix}"
+ logger.info(msg)
+
+ if options.verbose < 1 and len(tags) > tag_limit:
+ tags_limited = True
+ tags = tags[:tag_limit]
+ else:
+ tags_limited = False
+
+ with indent_log():
+ for tag in tags:
+ logger.info(str(tag))
+
+ if tags_limited:
+ msg = f"...\n[First {tag_limit} tags shown. Pass --verbose to show all.]"
+ logger.info(msg)
+
+
+def ca_bundle_info(config: Configuration) -> str:
+ levels = {key.split(".", 1)[0] for key, _ in config.items()}
+ if not levels:
+ return "Not specified"
+
+ levels_that_override_global = ["install", "wheel", "download"]
+ global_overriding_level = [
+ level for level in levels if level in levels_that_override_global
+ ]
+ if not global_overriding_level:
+ return "global"
+
+ if "global" in levels:
+ levels.remove("global")
+ return ", ".join(levels)
+
+
+class DebugCommand(Command):
+ """
+ Display debug information.
+ """
+
+ usage = """
+ %prog <options>"""
+ ignore_require_venv = True
+
+ def add_options(self) -> None:
+ cmdoptions.add_target_python_options(self.cmd_opts)
+ self.parser.insert_option_group(0, self.cmd_opts)
+ self.parser.config.load()
+
+ def run(self, options: 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."
+ )
+ show_value("pip version", get_pip_version())
+ show_value("sys.version", sys.version)
+ show_value("sys.executable", sys.executable)
+ show_value("sys.getdefaultencoding", sys.getdefaultencoding())
+ show_value("sys.getfilesystemencoding", sys.getfilesystemencoding())
+ show_value(
+ "locale.getpreferredencoding",
+ locale.getpreferredencoding(),
+ )
+ show_value("sys.platform", sys.platform)
+ show_sys_implementation()
+
+ show_value("'cert' config value", ca_bundle_info(self.parser.config))
+ show_value("REQUESTS_CA_BUNDLE", os.environ.get("REQUESTS_CA_BUNDLE"))
+ show_value("CURL_CA_BUNDLE", os.environ.get("CURL_CA_BUNDLE"))
+ show_value("pip._vendor.certifi.where()", where())
+ show_value("pip._vendor.DEBUNDLED", pip._vendor.DEBUNDLED)
+
+ show_vendor_versions()
+
+ show_tags(options)
+
+ return SUCCESS
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/download.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/download.py
new file mode 100644
index 0000000..54247a7
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/download.py
@@ -0,0 +1,147 @@
+import logging
+import os
+from optparse import Values
+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.status_codes import SUCCESS
+from pip._internal.operations.build.build_tracker import get_build_tracker
+from pip._internal.req.req_install import check_legacy_setup_py_options
+from pip._internal.utils.misc import ensure_dir, normalize_path, write_output
+from pip._internal.utils.temp_dir import TempDirectory
+
+logger = logging.getLogger(__name__)
+
+
+class DownloadCommand(RequirementCommand):
+ """
+ Download packages from:
+
+ - PyPI (and other indexes) using requirement specifiers.
+ - VCS project urls.
+ - Local project directories.
+ - Local or remote source archives.
+
+ pip also supports downloading from "requirements files", which provide
+ an easy way to specify a whole environment to be downloaded.
+ """
+
+ usage = """
+ %prog [options] <requirement specifier> [package-index-options] ...
+ %prog [options] -r <requirements file> [package-index-options] ...
+ %prog [options] <vcs project url> ...
+ %prog [options] <local project path> ...
+ %prog [options] <archive url/path> ..."""
+
+ def add_options(self) -> None:
+ self.cmd_opts.add_option(cmdoptions.constraints())
+ self.cmd_opts.add_option(cmdoptions.requirements())
+ self.cmd_opts.add_option(cmdoptions.no_deps())
+ self.cmd_opts.add_option(cmdoptions.global_options())
+ self.cmd_opts.add_option(cmdoptions.no_binary())
+ self.cmd_opts.add_option(cmdoptions.only_binary())
+ self.cmd_opts.add_option(cmdoptions.prefer_binary())
+ self.cmd_opts.add_option(cmdoptions.src())
+ self.cmd_opts.add_option(cmdoptions.pre())
+ self.cmd_opts.add_option(cmdoptions.require_hashes())
+ self.cmd_opts.add_option(cmdoptions.progress_bar())
+ self.cmd_opts.add_option(cmdoptions.no_build_isolation())
+ self.cmd_opts.add_option(cmdoptions.use_pep517())
+ self.cmd_opts.add_option(cmdoptions.no_use_pep517())
+ self.cmd_opts.add_option(cmdoptions.check_build_deps())
+ 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",
+ default=os.curdir,
+ help="Download packages into <dir>.",
+ )
+
+ cmdoptions.add_target_python_options(self.cmd_opts)
+
+ index_opts = cmdoptions.make_option_group(
+ cmdoptions.index_group,
+ self.parser,
+ )
+
+ self.parser.insert_option_group(0, index_opts)
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ @with_cleanup
+ def run(self, options: Values, args: List[str]) -> int:
+ options.ignore_installed = True
+ # editable doesn't really make sense for `pip download`, but the bowels
+ # of the RequirementSet code require that property.
+ options.editables = []
+
+ cmdoptions.check_dist_restriction(options)
+
+ options.download_dir = normalize_path(options.download_dir)
+ ensure_dir(options.download_dir)
+
+ session = self.get_default_session(options)
+
+ target_python = make_target_python(options)
+ finder = self._build_package_finder(
+ options=options,
+ session=session,
+ target_python=target_python,
+ ignore_requires_python=options.ignore_requires_python,
+ )
+
+ build_tracker = self.enter_context(get_build_tracker())
+
+ directory = TempDirectory(
+ delete=not options.no_clean,
+ kind="download",
+ globally_managed=True,
+ )
+
+ reqs = self.get_requirements(args, options, finder, session)
+ check_legacy_setup_py_options(options, reqs)
+
+ preparer = self.make_requirement_preparer(
+ temp_build_dir=directory,
+ options=options,
+ build_tracker=build_tracker,
+ session=session,
+ finder=finder,
+ download_dir=options.download_dir,
+ use_user_site=False,
+ verbosity=self.verbosity,
+ )
+
+ resolver = self.make_resolver(
+ preparer=preparer,
+ finder=finder,
+ options=options,
+ ignore_requires_python=options.ignore_requires_python,
+ use_pep517=options.use_pep517,
+ py_version_info=options.python_version,
+ )
+
+ self.trace_basic_info(finder)
+
+ requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
+
+ 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)
+
+ preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
+ requirement_set.warn_legacy_versions_and_specifiers()
+
+ if downloaded:
+ write_output("Successfully downloaded %s", " ".join(downloaded))
+
+ return SUCCESS
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/freeze.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/freeze.py
new file mode 100644
index 0000000..fd9d88a
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/freeze.py
@@ -0,0 +1,108 @@
+import sys
+from optparse import Values
+from typing import AbstractSet, List
+
+from pip._internal.cli import cmdoptions
+from pip._internal.cli.base_command import Command
+from pip._internal.cli.status_codes import SUCCESS
+from pip._internal.operations.freeze import freeze
+from pip._internal.utils.compat import stdlib_pkgs
+
+
+def _should_suppress_build_backends() -> bool:
+ return sys.version_info < (3, 12)
+
+
+def _dev_pkgs() -> AbstractSet[str]:
+ pkgs = {"pip"}
+
+ if _should_suppress_build_backends():
+ pkgs |= {"setuptools", "distribute", "wheel"}
+
+ return pkgs
+
+
+class FreezeCommand(Command):
+ """
+ Output installed packages in requirements format.
+
+ packages are listed in a case-insensitive sorted order.
+ """
+
+ usage = """
+ %prog [options]"""
+ log_streams = ("ext://sys.stderr", "ext://sys.stderr")
+
+ def add_options(self) -> None:
+ self.cmd_opts.add_option(
+ "-r",
+ "--requirement",
+ dest="requirements",
+ action="append",
+ default=[],
+ metavar="file",
+ help=(
+ "Use the order in the given requirements file and its "
+ "comments when generating output. This option can be "
+ "used multiple times."
+ ),
+ )
+ self.cmd_opts.add_option(
+ "-l",
+ "--local",
+ dest="local",
+ action="store_true",
+ default=False,
+ help=(
+ "If in a virtualenv that has global access, do not output "
+ "globally-installed packages."
+ ),
+ )
+ self.cmd_opts.add_option(
+ "--user",
+ dest="user",
+ action="store_true",
+ default=False,
+ help="Only output packages installed in user-site.",
+ )
+ self.cmd_opts.add_option(cmdoptions.list_path())
+ self.cmd_opts.add_option(
+ "--all",
+ dest="freeze_all",
+ action="store_true",
+ help=(
+ "Do not skip these packages in the output:"
+ " {}".format(", ".join(_dev_pkgs()))
+ ),
+ )
+ self.cmd_opts.add_option(
+ "--exclude-editable",
+ dest="exclude_editable",
+ action="store_true",
+ help="Exclude editable package from output.",
+ )
+ self.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:
+ skip = set(stdlib_pkgs)
+ if not options.freeze_all:
+ skip.update(_dev_pkgs())
+
+ if options.excludes:
+ skip.update(options.excludes)
+
+ cmdoptions.check_list_path_option(options)
+
+ for line in freeze(
+ requirement=options.requirements,
+ local_only=options.local,
+ user_only=options.user,
+ paths=options.path,
+ isolated=options.isolated_mode,
+ skip=skip,
+ exclude_editable=options.exclude_editable,
+ ):
+ sys.stdout.write(line + "\n")
+ return SUCCESS
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/hash.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/hash.py
new file mode 100644
index 0000000..042dac8
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/hash.py
@@ -0,0 +1,59 @@
+import hashlib
+import logging
+import sys
+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
+
+logger = logging.getLogger(__name__)
+
+
+class HashCommand(Command):
+ """
+ Compute a hash of a local package archive.
+
+ These can be used with --hash in a requirements file to do repeatable
+ installs.
+ """
+
+ usage = "%prog [options] <file> ..."
+ ignore_require_venv = True
+
+ def add_options(self) -> None:
+ self.cmd_opts.add_option(
+ "-a",
+ "--algorithm",
+ dest="algorithm",
+ choices=STRONG_HASHES,
+ action="store",
+ default=FAVORITE_HASH,
+ help="The hash algorithm to use: one of {}".format(
+ ", ".join(STRONG_HASHES)
+ ),
+ )
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ def run(self, options: Values, args: List[str]) -> int:
+ if not args:
+ self.parser.print_usage(sys.stderr)
+ return ERROR
+
+ algorithm = options.algorithm
+ for path in args:
+ write_output(
+ "%s:\n--hash=%s:%s", path, algorithm, _hash_of_file(path, algorithm)
+ )
+ return SUCCESS
+
+
+def _hash_of_file(path: str, algorithm: str) -> str:
+ """Return the hash digest of a file."""
+ with open(path, "rb") as archive:
+ hash = hashlib.new(algorithm)
+ for chunk in read_chunks(archive):
+ hash.update(chunk)
+ return hash.hexdigest()
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/help.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/help.py
new file mode 100644
index 0000000..6206631
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/help.py
@@ -0,0 +1,41 @@
+from optparse import Values
+from typing import List
+
+from pip._internal.cli.base_command import Command
+from pip._internal.cli.status_codes import SUCCESS
+from pip._internal.exceptions import CommandError
+
+
+class HelpCommand(Command):
+ """Show help for commands"""
+
+ usage = """
+ %prog <command>"""
+ ignore_require_venv = True
+
+ def run(self, options: Values, args: List[str]) -> int:
+ from pip._internal.commands import (
+ commands_dict,
+ create_command,
+ get_similar_commands,
+ )
+
+ try:
+ # 'pip help' with no args is handled by pip.__init__.parseopt()
+ cmd_name = args[0] # the command we need help for
+ except IndexError:
+ return SUCCESS
+
+ if cmd_name not in commands_dict:
+ guess = get_similar_commands(cmd_name)
+
+ msg = [f'unknown command "{cmd_name}"']
+ if guess:
+ msg.append(f'maybe you meant "{guess}"')
+
+ raise CommandError(" - ".join(msg))
+
+ command = create_command(cmd_name)
+ command.parser.print_help()
+
+ return SUCCESS
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/index.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/index.py
new file mode 100644
index 0000000..f55e9e4
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/index.py
@@ -0,0 +1,139 @@
+import logging
+from optparse import Values
+from typing import Any, Iterable, List, Optional, Union
+
+from pip._vendor.packaging.version import LegacyVersion, Version
+
+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.commands.search import print_dist_installation_info
+from pip._internal.exceptions import CommandError, DistributionNotFound, 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
+
+logger = logging.getLogger(__name__)
+
+
+class IndexCommand(IndexGroupCommand):
+ """
+ Inspect information available from package indexes.
+ """
+
+ ignore_require_venv = True
+ usage = """
+ %prog versions <package>
+ """
+
+ def add_options(self) -> None:
+ cmdoptions.add_target_python_options(self.cmd_opts)
+
+ self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
+ self.cmd_opts.add_option(cmdoptions.pre())
+ self.cmd_opts.add_option(cmdoptions.no_binary())
+ self.cmd_opts.add_option(cmdoptions.only_binary())
+
+ index_opts = cmdoptions.make_option_group(
+ cmdoptions.index_group,
+ self.parser,
+ )
+
+ self.parser.insert_option_group(0, index_opts)
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ def run(self, options: Values, args: List[str]) -> int:
+ handlers = {
+ "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."
+ )
+
+ # Determine action
+ if not args or args[0] not in handlers:
+ logger.error(
+ "Need an action (%s) to perform.",
+ ", ".join(sorted(handlers)),
+ )
+ return ERROR
+
+ action = args[0]
+
+ # Error handling happens here, not in the action-handlers.
+ try:
+ handlers[action](options, args[1:])
+ except PipError as e:
+ logger.error(e.args[0])
+ return ERROR
+
+ return SUCCESS
+
+ def _build_package_finder(
+ self,
+ options: Values,
+ session: PipSession,
+ target_python: Optional[TargetPython] = None,
+ ignore_requires_python: Optional[bool] = None,
+ ) -> PackageFinder:
+ """
+ Create a package finder appropriate to the index command.
+ """
+ link_collector = LinkCollector.create(session, options=options)
+
+ # Pass allow_yanked=False to ignore yanked versions.
+ selection_prefs = SelectionPreferences(
+ allow_yanked=False,
+ allow_all_prereleases=options.pre,
+ ignore_requires_python=ignore_requires_python,
+ )
+
+ return PackageFinder.create(
+ link_collector=link_collector,
+ selection_prefs=selection_prefs,
+ target_python=target_python,
+ )
+
+ 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")
+
+ target_python = cmdoptions.make_target_python(options)
+ query = args[0]
+
+ with self._build_session(options) as session:
+ finder = self._build_package_finder(
+ options=options,
+ session=session,
+ target_python=target_python,
+ ignore_requires_python=options.ignore_requires_python,
+ )
+
+ versions: Iterable[Union[LegacyVersion, Version]] = (
+ candidate.version for candidate in finder.find_all_candidates(query)
+ )
+
+ if not options.pre:
+ # Remove prereleases
+ versions = (
+ version for version in versions if not version.is_prerelease
+ )
+ versions = set(versions)
+
+ if not versions:
+ raise DistributionNotFound(
+ f"No matching distribution found for {query}"
+ )
+
+ formatted_versions = [str(ver) for ver in sorted(versions, reverse=True)]
+ latest = formatted_versions[0]
+
+ write_output(f"{query} ({latest})")
+ write_output("Available versions: {}".format(", ".join(formatted_versions)))
+ print_dist_installation_info(query, latest)
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/inspect.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/inspect.py
new file mode 100644
index 0000000..27c8fa3
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/inspect.py
@@ -0,0 +1,92 @@
+import logging
+from optparse import Values
+from typing import Any, Dict, List
+
+from pip._vendor.packaging.markers import default_environment
+from pip._vendor.rich import print_json
+
+from pip import __version__
+from pip._internal.cli import cmdoptions
+from pip._internal.cli.req_command import Command
+from pip._internal.cli.status_codes import SUCCESS
+from pip._internal.metadata import BaseDistribution, get_environment
+from pip._internal.utils.compat import stdlib_pkgs
+from pip._internal.utils.urls import path_to_url
+
+logger = logging.getLogger(__name__)
+
+
+class InspectCommand(Command):
+ """
+ Inspect the content of a Python environment and produce a report in JSON format.
+ """
+
+ ignore_require_venv = True
+ usage = """
+ %prog [options]"""
+
+ def add_options(self) -> None:
+ self.cmd_opts.add_option(
+ "--local",
+ action="store_true",
+ default=False,
+ help=(
+ "If in a virtualenv that has global access, do not list "
+ "globally-installed packages."
+ ),
+ )
+ self.cmd_opts.add_option(
+ "--user",
+ dest="user",
+ action="store_true",
+ default=False,
+ help="Only output packages installed in user-site.",
+ )
+ self.cmd_opts.add_option(cmdoptions.list_path())
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ def run(self, options: Values, args: List[str]) -> int:
+ cmdoptions.check_list_path_option(options)
+ dists = get_environment(options.path).iter_installed_distributions(
+ local_only=options.local,
+ user_only=options.user,
+ skip=set(stdlib_pkgs),
+ )
+ output = {
+ "version": "1",
+ "pip_version": __version__,
+ "installed": [self._dist_to_dict(dist) for dist in dists],
+ "environment": default_environment(),
+ # TODO tags? scheme?
+ }
+ print_json(data=output)
+ return SUCCESS
+
+ def _dist_to_dict(self, dist: BaseDistribution) -> Dict[str, Any]:
+ res: Dict[str, Any] = {
+ "metadata": dist.metadata_dict,
+ "metadata_location": dist.info_location,
+ }
+ # direct_url. Note that we don't have download_info (as in the installation
+ # report) since it is not recorded in installed metadata.
+ direct_url = dist.direct_url
+ if direct_url is not None:
+ res["direct_url"] = direct_url.to_dict()
+ else:
+ # Emulate direct_url for legacy editable installs.
+ editable_project_location = dist.editable_project_location
+ if editable_project_location is not None:
+ res["direct_url"] = {
+ "url": path_to_url(editable_project_location),
+ "dir_info": {
+ "editable": True,
+ },
+ }
+ # installer
+ installer = dist.installer
+ if dist.installer:
+ res["installer"] = installer
+ # requested
+ if dist.installed_with_dist_info:
+ res["requested"] = dist.requested
+ return res
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/install.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/install.py
new file mode 100644
index 0000000..e944bb9
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/install.py
@@ -0,0 +1,774 @@
+import errno
+import json
+import operator
+import os
+import shutil
+import site
+from optparse import SUPPRESS_HELP, Values
+from typing import List, Optional
+
+from pip._vendor.rich import print_json
+
+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.locations import get_scheme
+from pip._internal.metadata import get_environment
+from pip._internal.models.installation_report import InstallationReport
+from pip._internal.operations.build.build_tracker import get_build_tracker
+from pip._internal.operations.check import ConflictDetails, check_install_conflicts
+from pip._internal.req import install_given_reqs
+from pip._internal.req.req_install import (
+ InstallRequirement,
+ check_legacy_setup_py_options,
+)
+from pip._internal.utils.compat import WINDOWS
+from pip._internal.utils.filesystem import test_writable_dir
+from pip._internal.utils.logging import getLogger
+from pip._internal.utils.misc import (
+ check_externally_managed,
+ ensure_dir,
+ get_pip_version,
+ protect_pip_from_modification_on_windows,
+ 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 build, should_build_for_install_command
+
+logger = getLogger(__name__)
+
+
+class InstallCommand(RequirementCommand):
+ """
+ Install packages from:
+
+ - PyPI (and other indexes) using requirement specifiers.
+ - VCS project urls.
+ - Local project directories.
+ - Local or remote source archives.
+
+ pip also supports installing from "requirements files", which provide
+ an easy way to specify a whole environment to be installed.
+ """
+
+ usage = """
+ %prog [options] <requirement specifier> [package-index-options] ...
+ %prog [options] -r <requirements file> [package-index-options] ...
+ %prog [options] [-e] <vcs project url> ...
+ %prog [options] [-e] <local project path> ...
+ %prog [options] <archive url/path> ..."""
+
+ def add_options(self) -> None:
+ self.cmd_opts.add_option(cmdoptions.requirements())
+ self.cmd_opts.add_option(cmdoptions.constraints())
+ self.cmd_opts.add_option(cmdoptions.no_deps())
+ self.cmd_opts.add_option(cmdoptions.pre())
+
+ self.cmd_opts.add_option(cmdoptions.editable())
+ self.cmd_opts.add_option(
+ "--dry-run",
+ action="store_true",
+ dest="dry_run",
+ default=False,
+ help=(
+ "Don't actually install anything, just print what would be. "
+ "Can be used in combination with --ignore-installed "
+ "to 'resolve' the requirements."
+ ),
+ )
+ self.cmd_opts.add_option(
+ "-t",
+ "--target",
+ dest="target_dir",
+ metavar="dir",
+ default=None,
+ help=(
+ "Install packages into <dir>. "
+ "By default this will not replace existing files/folders in "
+ "<dir>. Use --upgrade to replace existing packages in <dir> "
+ "with new versions."
+ ),
+ )
+ cmdoptions.add_target_python_options(self.cmd_opts)
+
+ self.cmd_opts.add_option(
+ "--user",
+ dest="use_user_site",
+ action="store_true",
+ help=(
+ "Install to the Python user install directory for your "
+ "platform. Typically ~/.local/, or %APPDATA%\\Python on "
+ "Windows. (See the Python documentation for site.USER_BASE "
+ "for full details.)"
+ ),
+ )
+ self.cmd_opts.add_option(
+ "--no-user",
+ dest="use_user_site",
+ action="store_false",
+ help=SUPPRESS_HELP,
+ )
+ self.cmd_opts.add_option(
+ "--root",
+ dest="root_path",
+ metavar="dir",
+ default=None,
+ help="Install everything relative to this alternate root directory.",
+ )
+ self.cmd_opts.add_option(
+ "--prefix",
+ dest="prefix_path",
+ metavar="dir",
+ default=None,
+ help=(
+ "Installation prefix where lib, bin and other top-level "
+ "folders are placed. Note that the resulting installation may "
+ "contain scripts and other resources which reference the "
+ "Python interpreter of pip, and not that of ``--prefix``. "
+ "See also the ``--python`` option if the intention is to "
+ "install packages into another (possibly pip-free) "
+ "environment."
+ ),
+ )
+
+ self.cmd_opts.add_option(cmdoptions.src())
+
+ self.cmd_opts.add_option(
+ "-U",
+ "--upgrade",
+ dest="upgrade",
+ action="store_true",
+ help=(
+ "Upgrade all specified packages to the newest available "
+ "version. The handling of dependencies depends on the "
+ "upgrade-strategy used."
+ ),
+ )
+
+ self.cmd_opts.add_option(
+ "--upgrade-strategy",
+ dest="upgrade_strategy",
+ default="only-if-needed",
+ choices=["only-if-needed", "eager"],
+ help=(
+ "Determines how dependency upgrading should be handled "
+ "[default: %default]. "
+ '"eager" - dependencies are upgraded regardless of '
+ "whether the currently installed version satisfies the "
+ "requirements of the upgraded package(s). "
+ '"only-if-needed" - are upgraded only when they do not '
+ "satisfy the requirements of the upgraded package(s)."
+ ),
+ )
+
+ self.cmd_opts.add_option(
+ "--force-reinstall",
+ dest="force_reinstall",
+ action="store_true",
+ help="Reinstall all packages even if they are already up-to-date.",
+ )
+
+ self.cmd_opts.add_option(
+ "-I",
+ "--ignore-installed",
+ dest="ignore_installed",
+ action="store_true",
+ help=(
+ "Ignore the installed packages, overwriting them. "
+ "This can break your system if the existing package "
+ "is of a different version or was installed "
+ "with a different package manager!"
+ ),
+ )
+
+ self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
+ self.cmd_opts.add_option(cmdoptions.no_build_isolation())
+ self.cmd_opts.add_option(cmdoptions.use_pep517())
+ self.cmd_opts.add_option(cmdoptions.no_use_pep517())
+ self.cmd_opts.add_option(cmdoptions.check_build_deps())
+ self.cmd_opts.add_option(cmdoptions.override_externally_managed())
+
+ self.cmd_opts.add_option(cmdoptions.config_settings())
+ self.cmd_opts.add_option(cmdoptions.global_options())
+
+ self.cmd_opts.add_option(
+ "--compile",
+ action="store_true",
+ dest="compile",
+ default=True,
+ help="Compile Python source files to bytecode",
+ )
+
+ self.cmd_opts.add_option(
+ "--no-compile",
+ action="store_false",
+ dest="compile",
+ help="Do not compile Python source files to bytecode",
+ )
+
+ self.cmd_opts.add_option(
+ "--no-warn-script-location",
+ action="store_false",
+ dest="warn_script_location",
+ default=True,
+ help="Do not warn when installing scripts outside PATH",
+ )
+ self.cmd_opts.add_option(
+ "--no-warn-conflicts",
+ action="store_false",
+ dest="warn_about_conflicts",
+ default=True,
+ help="Do not warn about broken dependencies",
+ )
+ self.cmd_opts.add_option(cmdoptions.no_binary())
+ self.cmd_opts.add_option(cmdoptions.only_binary())
+ self.cmd_opts.add_option(cmdoptions.prefer_binary())
+ self.cmd_opts.add_option(cmdoptions.require_hashes())
+ self.cmd_opts.add_option(cmdoptions.progress_bar())
+ self.cmd_opts.add_option(cmdoptions.root_user_action())
+
+ index_opts = cmdoptions.make_option_group(
+ cmdoptions.index_group,
+ self.parser,
+ )
+
+ self.parser.insert_option_group(0, index_opts)
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ self.cmd_opts.add_option(
+ "--report",
+ dest="json_report_file",
+ metavar="file",
+ default=None,
+ help=(
+ "Generate a JSON file describing what pip did to install "
+ "the provided requirements. "
+ "Can be used in combination with --dry-run and --ignore-installed "
+ "to 'resolve' the requirements. "
+ "When - is used as file name it writes to stdout. "
+ "When writing to stdout, please combine with the --quiet option "
+ "to avoid mixing pip logging output with JSON output."
+ ),
+ )
+
+ @with_cleanup
+ 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'")
+
+ # Check whether the environment we're installing into is externally
+ # managed, as specified in PEP 668. Specifying --root, --target, or
+ # --prefix disables the check, since there's no reliable way to locate
+ # the EXTERNALLY-MANAGED file for those cases. An exception is also
+ # made specifically for "--dry-run --report" for convenience.
+ installing_into_current_environment = (
+ not (options.dry_run and options.json_report_file)
+ and options.root_path is None
+ and options.target_dir is None
+ and options.prefix_path is None
+ )
+ if (
+ installing_into_current_environment
+ and not options.override_externally_managed
+ ):
+ check_externally_managed()
+
+ upgrade_strategy = "to-satisfy-only"
+ if options.upgrade:
+ upgrade_strategy = options.upgrade_strategy
+
+ cmdoptions.check_dist_restriction(options, check_target=True)
+
+ logger.verbose("Using %s", get_pip_version())
+ options.use_user_site = decide_user_install(
+ options.use_user_site,
+ prefix_path=options.prefix_path,
+ target_dir=options.target_dir,
+ root_path=options.root_path,
+ isolated_mode=options.isolated_mode,
+ )
+
+ target_temp_dir: Optional[TempDirectory] = None
+ target_temp_dir_path: Optional[str] = None
+ if options.target_dir:
+ options.ignore_installed = True
+ options.target_dir = os.path.abspath(options.target_dir)
+ if (
+ # fmt: off
+ os.path.exists(options.target_dir) and
+ not os.path.isdir(options.target_dir)
+ # fmt: on
+ ):
+ raise CommandError(
+ "Target path exists but is not a directory, will not continue."
+ )
+
+ # Create a target directory for using with the target option
+ target_temp_dir = TempDirectory(kind="target")
+ target_temp_dir_path = target_temp_dir.path
+ self.enter_context(target_temp_dir)
+
+ global_options = options.global_options or []
+
+ session = self.get_default_session(options)
+
+ target_python = make_target_python(options)
+ finder = self._build_package_finder(
+ options=options,
+ session=session,
+ target_python=target_python,
+ ignore_requires_python=options.ignore_requires_python,
+ )
+ build_tracker = self.enter_context(get_build_tracker())
+
+ directory = TempDirectory(
+ delete=not options.no_clean,
+ kind="install",
+ globally_managed=True,
+ )
+
+ try:
+ reqs = self.get_requirements(args, options, finder, session)
+ check_legacy_setup_py_options(options, reqs)
+
+ wheel_cache = WheelCache(options.cache_dir)
+
+ # Only when installing is it permitted to use PEP 660.
+ # In other circumstances (pip wheel, pip download) we generate
+ # regular (i.e. non editable) metadata and wheels.
+ for req in reqs:
+ req.permit_editable_wheels = True
+
+ preparer = self.make_requirement_preparer(
+ temp_build_dir=directory,
+ options=options,
+ build_tracker=build_tracker,
+ session=session,
+ finder=finder,
+ use_user_site=options.use_user_site,
+ verbosity=self.verbosity,
+ )
+ resolver = self.make_resolver(
+ preparer=preparer,
+ finder=finder,
+ options=options,
+ wheel_cache=wheel_cache,
+ use_user_site=options.use_user_site,
+ ignore_installed=options.ignore_installed,
+ ignore_requires_python=options.ignore_requires_python,
+ force_reinstall=options.force_reinstall,
+ upgrade_strategy=upgrade_strategy,
+ use_pep517=options.use_pep517,
+ )
+
+ self.trace_basic_info(finder)
+
+ requirement_set = resolver.resolve(
+ reqs, check_supported_wheels=not options.target_dir
+ )
+
+ if options.json_report_file:
+ report = InstallationReport(requirement_set.requirements_to_install)
+ if options.json_report_file == "-":
+ print_json(data=report.to_dict())
+ else:
+ with open(options.json_report_file, "w", encoding="utf-8") as f:
+ json.dump(report.to_dict(), f, indent=2, ensure_ascii=False)
+
+ if options.dry_run:
+ # In non dry-run mode, the legacy versions and specifiers check
+ # will be done as part of conflict detection.
+ requirement_set.warn_legacy_versions_and_specifiers()
+ would_install_items = sorted(
+ (r.metadata["name"], r.metadata["version"])
+ for r in requirement_set.requirements_to_install
+ )
+ if would_install_items:
+ write_output(
+ "Would install %s",
+ " ".join("-".join(item) for item in would_install_items),
+ )
+ return SUCCESS
+
+ try:
+ pip_req = requirement_set.get_requirement("pip")
+ except KeyError:
+ modifying_pip = False
+ else:
+ # If we're not replacing an already installed pip,
+ # we're not modifying it.
+ modifying_pip = pip_req.satisfied_by is None
+ protect_pip_from_modification_on_windows(modifying_pip=modifying_pip)
+
+ reqs_to_build = [
+ r
+ for r in requirement_set.requirements.values()
+ if should_build_for_install_command(r)
+ ]
+
+ _, build_failures = build(
+ reqs_to_build,
+ wheel_cache=wheel_cache,
+ verify=True,
+ build_options=[],
+ global_options=global_options,
+ )
+
+ if build_failures:
+ raise InstallationError(
+ "Could not build wheels for {}, which is required to "
+ "install pyproject.toml-based projects".format(
+ ", ".join(r.name for r in build_failures) # type: ignore
+ )
+ )
+
+ to_install = resolver.get_installation_order(requirement_set)
+
+ # Check for conflicts in the package set we're installing.
+ conflicts: Optional[ConflictDetails] = None
+ should_warn_about_conflicts = (
+ not options.ignore_dependencies and options.warn_about_conflicts
+ )
+ if should_warn_about_conflicts:
+ conflicts = self._determine_conflicts(to_install)
+
+ # Don't warn about script install locations if
+ # --target or --prefix has been specified
+ warn_script_location = options.warn_script_location
+ if options.target_dir or options.prefix_path:
+ warn_script_location = False
+
+ installed = install_given_reqs(
+ to_install,
+ global_options,
+ root=options.root_path,
+ home=target_temp_dir_path,
+ prefix=options.prefix_path,
+ warn_script_location=warn_script_location,
+ use_user_site=options.use_user_site,
+ pycompile=options.compile,
+ )
+
+ lib_locations = get_lib_location_guesses(
+ user=options.use_user_site,
+ home=target_temp_dir_path,
+ root=options.root_path,
+ prefix=options.prefix_path,
+ isolated=options.isolated_mode,
+ )
+ env = get_environment(lib_locations)
+
+ 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}"
+ except Exception:
+ pass
+ items.append(item)
+
+ if conflicts is not None:
+ self._warn_about_conflicts(
+ conflicts,
+ resolver_variant=self.determine_resolver_variant(options),
+ )
+
+ installed_desc = " ".join(items)
+ if installed_desc:
+ write_output(
+ "Successfully installed %s",
+ installed_desc,
+ )
+ except OSError as error:
+ show_traceback = self.verbosity >= 1
+
+ message = create_os_error_message(
+ error,
+ show_traceback,
+ options.use_user_site,
+ )
+ logger.error(message, exc_info=show_traceback)
+
+ return ERROR
+
+ if options.target_dir:
+ assert target_temp_dir
+ self._handle_target_dir(
+ options.target_dir, target_temp_dir, options.upgrade
+ )
+ if options.root_user_action == "warn":
+ warn_if_run_as_root()
+ return SUCCESS
+
+ def _handle_target_dir(
+ self, target_dir: str, target_temp_dir: TempDirectory, upgrade: bool
+ ) -> None:
+ ensure_dir(target_dir)
+
+ # Checking both purelib and platlib directories for installed
+ # packages to be moved to target directory
+ lib_dir_list = []
+
+ # Checking both purelib and platlib directories for installed
+ # packages to be moved to target directory
+ scheme = get_scheme("", home=target_temp_dir.path)
+ purelib_dir = scheme.purelib
+ platlib_dir = scheme.platlib
+ data_dir = scheme.data
+
+ if os.path.exists(purelib_dir):
+ lib_dir_list.append(purelib_dir)
+ if os.path.exists(platlib_dir) and platlib_dir != purelib_dir:
+ lib_dir_list.append(platlib_dir)
+ if os.path.exists(data_dir):
+ lib_dir_list.append(data_dir)
+
+ for lib_dir in lib_dir_list:
+ for item in os.listdir(lib_dir):
+ if lib_dir == data_dir:
+ ddir = os.path.join(data_dir, item)
+ if any(s.startswith(ddir) for s in lib_dir_list[:-1]):
+ continue
+ target_item_dir = os.path.join(target_dir, item)
+ if os.path.exists(target_item_dir):
+ if not upgrade:
+ logger.warning(
+ "Target directory %s already exists. Specify "
+ "--upgrade to force replacement.",
+ target_item_dir,
+ )
+ continue
+ if os.path.islink(target_item_dir):
+ logger.warning(
+ "Target directory %s already exists and is "
+ "a link. pip will not automatically replace "
+ "links, please remove if replacement is "
+ "desired.",
+ target_item_dir,
+ )
+ continue
+ if os.path.isdir(target_item_dir):
+ shutil.rmtree(target_item_dir)
+ else:
+ os.remove(target_item_dir)
+
+ shutil.move(os.path.join(lib_dir, item), target_item_dir)
+
+ def _determine_conflicts(
+ self, to_install: List[InstallRequirement]
+ ) -> Optional[ConflictDetails]:
+ try:
+ return check_install_conflicts(to_install)
+ except Exception:
+ logger.exception(
+ "Error while checking for conflicts. Please file an issue on "
+ "pip's issue tracker: https://github.com/pypa/pip/issues/new"
+ )
+ return None
+
+ def _warn_about_conflicts(
+ self, conflict_details: 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.append(
+ "pip's legacy dependency resolver does not consider dependency "
+ "conflicts when selecting packages. This behaviour is the "
+ "source of the following dependency conflicts."
+ )
+ else:
+ assert resolver_variant == "resolvelib"
+ 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."
+ )
+
+ # NOTE: There is some duplication here, with commands/check.py
+ for project_name in missing:
+ version = package_set[project_name][0]
+ for dependency in missing[project_name]:
+ message = (
+ f"{project_name} {version} requires {dependency[1]}, "
+ "which is not installed."
+ )
+ parts.append(message)
+
+ for project_name in conflicting:
+ version = package_set[project_name][0]
+ for dep_name, dep_version, req in conflicting[project_name]:
+ message = (
+ "{name} {version} requires {requirement}, but {you} 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 == "resolvelib" else "you'll"),
+ )
+ parts.append(message)
+
+ logger.critical("\n".join(parts))
+
+
+def get_lib_location_guesses(
+ user: bool = False,
+ home: Optional[str] = None,
+ root: Optional[str] = None,
+ isolated: bool = False,
+ prefix: Optional[str] = None,
+) -> List[str]:
+ scheme = get_scheme(
+ "",
+ user=user,
+ home=home,
+ root=root,
+ isolated=isolated,
+ prefix=prefix,
+ )
+ return [scheme.purelib, scheme.platlib]
+
+
+def site_packages_writable(root: Optional[str], isolated: bool) -> bool:
+ return all(
+ test_writable_dir(d)
+ for d in set(get_lib_location_guesses(root=root, isolated=isolated))
+ )
+
+
+def decide_user_install(
+ use_user_site: Optional[bool],
+ prefix_path: Optional[str] = None,
+ target_dir: Optional[str] = None,
+ root_path: Optional[str] = None,
+ isolated_mode: bool = False,
+) -> bool:
+ """Determine whether to do a user install based on the input options.
+
+ If use_user_site is False, no additional checks are done.
+ If use_user_site is True, it is checked for compatibility with other
+ options.
+ If use_user_site is None, the default behaviour depends on the environment,
+ which is provided by the other arguments.
+ """
+ # In some cases (config from tox), use_user_site can be set to an integer
+ # rather than a bool, which 'use_user_site is False' wouldn't catch.
+ if (use_user_site is not None) and (not use_user_site):
+ logger.debug("Non-user install by explicit request")
+ return False
+
+ if use_user_site:
+ if prefix_path:
+ raise CommandError(
+ "Can not combine '--user' and '--prefix' as they imply "
+ "different installation locations"
+ )
+ if virtualenv_no_global():
+ raise InstallationError(
+ "Can not perform a '--user' install. User site-packages "
+ "are not visible in this virtualenv."
+ )
+ logger.debug("User install by explicit request")
+ return True
+
+ # If we are here, user installs have not been explicitly requested/avoided
+ assert use_user_site is None
+
+ # user install incompatible with --prefix/--target
+ if prefix_path or target_dir:
+ logger.debug("Non-user install due to --prefix or --target option")
+ return False
+
+ # If user installs are not enabled, choose a non-user install
+ if not site.ENABLE_USER_SITE:
+ logger.debug("Non-user install because user site-packages disabled")
+ return False
+
+ # If we have permission for a non-user install, do that,
+ # otherwise do a user install.
+ if site_packages_writable(root=root_path, isolated=isolated_mode):
+ logger.debug("Non-user install because site-packages writeable")
+ return False
+
+ logger.info(
+ "Defaulting to user installation because normal site-packages "
+ "is not writeable"
+ )
+ return True
+
+
+def create_os_error_message(
+ error: OSError, show_traceback: bool, using_user_site: bool
+) -> str:
+ """Format an error message for an OSError
+
+ It may occur anytime during the execution of the install command.
+ """
+ parts = []
+
+ # Mention the error if we are not going to show a traceback
+ parts.append("Could not install packages due to an OSError")
+ if not show_traceback:
+ parts.append(": ")
+ parts.append(str(error))
+ else:
+ parts.append(".")
+
+ # Spilt the error indication from a helper message (if any)
+ parts[-1] += "\n"
+
+ # Suggest useful actions to the user:
+ # (1) using user site-packages or (2) verifying the permissions
+ if error.errno == errno.EACCES:
+ user_option_part = "Consider using the `--user` option"
+ permissions_part = "Check the permissions"
+
+ if not running_under_virtualenv() and not using_user_site:
+ parts.extend(
+ [
+ user_option_part,
+ " or ",
+ permissions_part.lower(),
+ ]
+ )
+ else:
+ parts.append(permissions_part)
+ 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
+ ):
+ 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"
+ )
+
+ return "".join(parts).strip() + "\n"
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/list.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/list.py
new file mode 100644
index 0000000..e551dda
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/list.py
@@ -0,0 +1,368 @@
+import json
+import logging
+from optparse import Values
+from typing import TYPE_CHECKING, Generator, List, Optional, Sequence, Tuple, cast
+
+from pip._vendor.packaging.utils import canonicalize_name
+
+from pip._internal.cli import cmdoptions
+from pip._internal.cli.req_command import IndexGroupCommand
+from pip._internal.cli.status_codes import SUCCESS
+from pip._internal.exceptions import CommandError
+from pip._internal.index.collector import LinkCollector
+from pip._internal.index.package_finder import PackageFinder
+from pip._internal.metadata import BaseDistribution, 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
+
+if TYPE_CHECKING:
+ from pip._internal.metadata.base import DistributionVersion
+
+ class _DistWithLatestInfo(BaseDistribution):
+ """Give the distribution object a couple of extra fields.
+
+ These will be populated during ``get_outdated()``. This is dirty but
+ makes the rest of the code much cleaner.
+ """
+
+ latest_version: DistributionVersion
+ latest_filetype: str
+
+ _ProcessedDists = Sequence[_DistWithLatestInfo]
+
+
+logger = logging.getLogger(__name__)
+
+
+class ListCommand(IndexGroupCommand):
+ """
+ List installed packages, including editables.
+
+ Packages are listed in a case-insensitive sorted order.
+ """
+
+ ignore_require_venv = True
+ usage = """
+ %prog [options]"""
+
+ def add_options(self) -> None:
+ self.cmd_opts.add_option(
+ "-o",
+ "--outdated",
+ action="store_true",
+ default=False,
+ help="List outdated packages",
+ )
+ self.cmd_opts.add_option(
+ "-u",
+ "--uptodate",
+ action="store_true",
+ default=False,
+ help="List uptodate packages",
+ )
+ self.cmd_opts.add_option(
+ "-e",
+ "--editable",
+ action="store_true",
+ default=False,
+ help="List editable projects.",
+ )
+ self.cmd_opts.add_option(
+ "-l",
+ "--local",
+ action="store_true",
+ default=False,
+ help=(
+ "If in a virtualenv that has global access, do not list "
+ "globally-installed packages."
+ ),
+ )
+ self.cmd_opts.add_option(
+ "--user",
+ dest="user",
+ action="store_true",
+ default=False,
+ help="Only output packages installed in user-site.",
+ )
+ self.cmd_opts.add_option(cmdoptions.list_path())
+ self.cmd_opts.add_option(
+ "--pre",
+ action="store_true",
+ default=False,
+ help=(
+ "Include pre-release and development versions. By default, "
+ "pip only finds stable versions."
+ ),
+ )
+
+ self.cmd_opts.add_option(
+ "--format",
+ action="store",
+ dest="list_format",
+ default="columns",
+ choices=("columns", "freeze", "json"),
+ help=(
+ "Select the output format among: columns (default), freeze, or json. "
+ "The 'freeze' format cannot be used with the --outdated option."
+ ),
+ )
+
+ self.cmd_opts.add_option(
+ "--not-required",
+ action="store_true",
+ dest="not_required",
+ help="List packages that are not dependencies of installed packages.",
+ )
+
+ self.cmd_opts.add_option(
+ "--exclude-editable",
+ action="store_false",
+ dest="include_editable",
+ help="Exclude editable package from output.",
+ )
+ self.cmd_opts.add_option(
+ "--include-editable",
+ action="store_true",
+ dest="include_editable",
+ help="Include editable package from output.",
+ default=True,
+ )
+ self.cmd_opts.add_option(cmdoptions.list_exclude())
+ index_opts = cmdoptions.make_option_group(cmdoptions.index_group, self.parser)
+
+ self.parser.insert_option_group(0, index_opts)
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ def _build_package_finder(
+ self, options: Values, session: PipSession
+ ) -> PackageFinder:
+ """
+ Create a package finder appropriate to this list command.
+ """
+ link_collector = LinkCollector.create(session, options=options)
+
+ # Pass allow_yanked=False to ignore yanked versions.
+ selection_prefs = SelectionPreferences(
+ allow_yanked=False,
+ allow_all_prereleases=options.pre,
+ )
+
+ return PackageFinder.create(
+ link_collector=link_collector,
+ selection_prefs=selection_prefs,
+ )
+
+ def run(self, options: Values, args: List[str]) -> int:
+ if options.outdated and options.uptodate:
+ raise CommandError("Options --outdated and --uptodate cannot be combined.")
+
+ if options.outdated and options.list_format == "freeze":
+ raise CommandError(
+ "List format 'freeze' cannot be used with the --outdated option."
+ )
+
+ cmdoptions.check_list_path_option(options)
+
+ skip = set(stdlib_pkgs)
+ if options.excludes:
+ skip.update(canonicalize_name(n) for n in options.excludes)
+
+ packages: "_ProcessedDists" = [
+ cast("_DistWithLatestInfo", d)
+ for d in get_environment(options.path).iter_installed_distributions(
+ local_only=options.local,
+ user_only=options.user,
+ editables_only=options.editable,
+ include_editables=options.include_editable,
+ skip=skip,
+ )
+ ]
+
+ # get_not_required must be called firstly in order to find and
+ # filter out all dependencies correctly. Otherwise a package
+ # can't be identified as requirement because some parent packages
+ # could be filtered out before.
+ if options.not_required:
+ packages = self.get_not_required(packages, options)
+
+ if options.outdated:
+ packages = self.get_outdated(packages, options)
+ elif options.uptodate:
+ packages = self.get_uptodate(packages, options)
+
+ self.output_package_listing(packages, options)
+ return SUCCESS
+
+ def get_outdated(
+ self, packages: "_ProcessedDists", options: Values
+ ) -> "_ProcessedDists":
+ return [
+ dist
+ for dist in self.iter_packages_latest_infos(packages, options)
+ if dist.latest_version > dist.version
+ ]
+
+ def get_uptodate(
+ self, packages: "_ProcessedDists", options: Values
+ ) -> "_ProcessedDists":
+ return [
+ dist
+ for dist in self.iter_packages_latest_infos(packages, options)
+ if dist.latest_version == dist.version
+ ]
+
+ def get_not_required(
+ self, packages: "_ProcessedDists", options: Values
+ ) -> "_ProcessedDists":
+ dep_keys = {
+ canonicalize_name(dep.name)
+ for dist in packages
+ for dep in (dist.iter_dependencies() or ())
+ }
+
+ # Create a set to remove duplicate packages, and cast it to a list
+ # to keep the return type consistent with get_outdated and
+ # get_uptodate
+ return list({pkg for pkg in packages if pkg.canonical_name not in dep_keys})
+
+ def iter_packages_latest_infos(
+ self, packages: "_ProcessedDists", options: Values
+ ) -> Generator["_DistWithLatestInfo", None, None]:
+ with self._build_session(options) as session:
+ finder = self._build_package_finder(options, session)
+
+ def latest_info(
+ dist: "_DistWithLatestInfo",
+ ) -> Optional["_DistWithLatestInfo"]:
+ all_candidates = finder.find_all_candidates(dist.canonical_name)
+ if not options.pre:
+ # Remove prereleases
+ all_candidates = [
+ candidate
+ for candidate in all_candidates
+ if not candidate.version.is_prerelease
+ ]
+
+ evaluator = finder.make_candidate_evaluator(
+ project_name=dist.canonical_name,
+ )
+ best_candidate = evaluator.sort_best_candidate(all_candidates)
+ if best_candidate is None:
+ return None
+
+ remote_version = best_candidate.version
+ if best_candidate.link.is_wheel:
+ typ = "wheel"
+ else:
+ typ = "sdist"
+ dist.latest_version = remote_version
+ dist.latest_filetype = typ
+ return dist
+
+ for dist in map(latest_info, packages):
+ if dist is not None:
+ yield dist
+
+ def output_package_listing(
+ self, packages: "_ProcessedDists", options: Values
+ ) -> None:
+ packages = sorted(
+ packages,
+ key=lambda dist: dist.canonical_name,
+ )
+ if options.list_format == "columns" and packages:
+ data, header = format_for_columns(packages, options)
+ self.output_package_listing_columns(data, header)
+ elif options.list_format == "freeze":
+ for dist in packages:
+ if options.verbose >= 1:
+ write_output(
+ "%s==%s (%s)", dist.raw_name, dist.version, dist.location
+ )
+ else:
+ 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]
+ ) -> None:
+ # insert the header first: we need to know the size of column names
+ if len(data) > 0:
+ data.insert(0, header)
+
+ pkg_strings, sizes = tabulate(data)
+
+ # Create and add a separator.
+ if len(data) > 0:
+ pkg_strings.insert(1, " ".join("-" * x for x in sizes))
+
+ for val in pkg_strings:
+ write_output(val)
+
+
+def format_for_columns(
+ 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"]
+
+ running_outdated = options.outdated
+ if running_outdated:
+ header.extend(["Latest", "Type"])
+
+ has_editables = any(x.editable for x in pkgs)
+ if has_editables:
+ header.append("Editable project location")
+
+ if options.verbose >= 1:
+ header.append("Location")
+ if options.verbose >= 1:
+ header.append("Installer")
+
+ data = []
+ for proj in pkgs:
+ # if we're working on the 'outdated' list, separate out the
+ # latest_version and type
+ row = [proj.raw_name, str(proj.version)]
+
+ if running_outdated:
+ row.append(str(proj.latest_version))
+ row.append(proj.latest_filetype)
+
+ if has_editables:
+ row.append(proj.editable_project_location or "")
+
+ if options.verbose >= 1:
+ row.append(proj.location or "")
+ if options.verbose >= 1:
+ row.append(proj.installer)
+
+ data.append(row)
+
+ return data, header
+
+
+def format_for_json(packages: "_ProcessedDists", options: Values) -> str:
+ data = []
+ for dist in packages:
+ info = {
+ "name": dist.raw_name,
+ "version": str(dist.version),
+ }
+ if options.verbose >= 1:
+ 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
+ editable_project_location = dist.editable_project_location
+ if editable_project_location:
+ info["editable_project_location"] = editable_project_location
+ data.append(info)
+ return json.dumps(data)
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/search.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/search.py
new file mode 100644
index 0000000..03ed925
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/search.py
@@ -0,0 +1,174 @@
+import logging
+import shutil
+import sys
+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 pip._internal.cli.base_command import Command
+from pip._internal.cli.req_command import SessionCommandMixin
+from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS
+from pip._internal.exceptions import CommandError
+from pip._internal.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
+
+if TYPE_CHECKING:
+ from typing import TypedDict
+
+ class TransformedHit(TypedDict):
+ name: str
+ summary: str
+ versions: List[str]
+
+
+logger = logging.getLogger(__name__)
+
+
+class SearchCommand(Command, SessionCommandMixin):
+ """Search for PyPI packages whose name or summary contains <query>."""
+
+ usage = """
+ %prog [options] <query>"""
+ ignore_require_venv = True
+
+ def add_options(self) -> None:
+ self.cmd_opts.add_option(
+ "-i",
+ "--index",
+ dest="index",
+ metavar="URL",
+ default=PyPI.pypi_url,
+ help="Base URL of Python Package Index (default %default)",
+ )
+
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ def run(self, options: Values, args: List[str]) -> int:
+ if not args:
+ raise CommandError("Missing required argument (search query).")
+ query = args
+ pypi_hits = self.search(query, options)
+ hits = transform_hits(pypi_hits)
+
+ terminal_width = None
+ if sys.stdout.isatty():
+ terminal_width = shutil.get_terminal_size()[0]
+
+ print_results(hits, terminal_width=terminal_width)
+ if pypi_hits:
+ return SUCCESS
+ return NO_MATCHES_FOUND
+
+ def search(self, query: List[str], options: Values) -> List[Dict[str, str]]:
+ index_url = options.index
+
+ session = self.get_default_session(options)
+
+ transport = PipXmlrpcTransport(index_url, session)
+ pypi = xmlrpc.client.ServerProxy(index_url, transport)
+ try:
+ hits = pypi.search({"name": query, "summary": query}, "or")
+ except xmlrpc.client.Fault as fault:
+ message = "XMLRPC request failed [code: {code}]\n{string}".format(
+ code=fault.faultCode,
+ string=fault.faultString,
+ )
+ raise CommandError(message)
+ assert isinstance(hits, list)
+ return hits
+
+
+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()
+ for hit in hits:
+ name = hit["name"]
+ summary = hit["summary"]
+ version = hit["version"]
+
+ if name not in packages.keys():
+ packages[name] = {
+ "name": name,
+ "summary": summary,
+ "versions": [version],
+ }
+ else:
+ packages[name]["versions"].append(version)
+
+ # if this is the highest version, replace summary and score
+ if version == highest_version(packages[name]["versions"]):
+ packages[name]["summary"] = summary
+
+ return list(packages.values())
+
+
+def print_dist_installation_info(name: str, latest: str) -> None:
+ env = get_default_environment()
+ dist = env.get_distribution(name)
+ if dist is not None:
+ with indent_log():
+ if dist.version == latest:
+ write_output("INSTALLED: %s (latest)", dist.version)
+ else:
+ write_output("INSTALLED: %s", dist.version)
+ if parse_version(latest).pre:
+ write_output(
+ "LATEST: %s (pre-release; install"
+ " with `pip install --pre`)",
+ latest,
+ )
+ else:
+ write_output("LATEST: %s", latest)
+
+
+def print_results(
+ hits: List["TransformedHit"],
+ name_column_width: Optional[int] = None,
+ terminal_width: Optional[int] = None,
+) -> None:
+ if not hits:
+ return
+ if name_column_width is None:
+ name_column_width = (
+ max(
+ [
+ len(hit["name"]) + len(highest_version(hit.get("versions", ["-"])))
+ for hit in hits
+ ]
+ )
+ + 4
+ )
+
+ for hit in hits:
+ name = hit["name"]
+ summary = hit["summary"] or ""
+ latest = highest_version(hit.get("versions", ["-"]))
+ if terminal_width is not None:
+ target_width = terminal_width - name_column_width - 5
+ if target_width > 10:
+ # wrap and indent summary to fit terminal
+ summary_lines = textwrap.wrap(summary, target_width)
+ summary = ("\n" + " " * (name_column_width + 3)).join(summary_lines)
+
+ name_latest = f"{name} ({latest})"
+ line = f"{name_latest:{name_column_width}} - {summary}"
+ try:
+ write_output(line)
+ print_dist_installation_info(name, latest)
+ except UnicodeEncodeError:
+ pass
+
+
+def highest_version(versions: List[str]) -> str:
+ return max(versions, key=parse_version)
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/show.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/show.py
new file mode 100644
index 0000000..3f10701
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/show.py
@@ -0,0 +1,189 @@
+import logging
+from optparse import Values
+from typing import Generator, Iterable, Iterator, List, NamedTuple, Optional
+
+from pip._vendor.packaging.utils import canonicalize_name
+
+from pip._internal.cli.base_command import Command
+from pip._internal.cli.status_codes import ERROR, SUCCESS
+from pip._internal.metadata import BaseDistribution, get_default_environment
+from pip._internal.utils.misc import write_output
+
+logger = logging.getLogger(__name__)
+
+
+class ShowCommand(Command):
+ """
+ Show information about one or more installed packages.
+
+ The output is in RFC-compliant mail header format.
+ """
+
+ usage = """
+ %prog [options] <package> ..."""
+ ignore_require_venv = True
+
+ def add_options(self) -> None:
+ self.cmd_opts.add_option(
+ "-f",
+ "--files",
+ dest="files",
+ action="store_true",
+ default=False,
+ help="Show the full list of installed files for each package.",
+ )
+
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ def run(self, options: Values, args: List[str]) -> int:
+ if not args:
+ logger.warning("ERROR: Please provide a package name or names.")
+ return ERROR
+ query = args
+
+ results = search_packages_info(query)
+ if not print_results(
+ results, list_files=options.files, verbose=options.verbose
+ ):
+ return ERROR
+ return SUCCESS
+
+
+class _PackageInfo(NamedTuple):
+ name: str
+ version: str
+ location: str
+ editable_project_location: Optional[str]
+ requires: List[str]
+ required_by: List[str]
+ installer: str
+ metadata_version: str
+ classifiers: List[str]
+ summary: str
+ homepage: str
+ project_urls: List[str]
+ author: str
+ author_email: str
+ license: str
+ entry_points: List[str]
+ files: Optional[List[str]]
+
+
+def search_packages_info(query: List[str]) -> Generator[_PackageInfo, None, None]:
+ """
+ Gather details from installed distributions. Print distribution name,
+ version, location, and installed files. Installed files requires a
+ pip generated 'installed-files.txt' in the distributions '.egg-info'
+ directory.
+ """
+ env = get_default_environment()
+
+ installed = {dist.canonical_name: dist for dist in env.iter_all_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]
+ )
+ if 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"
+ for dist in installed.values()
+ if current_dist.canonical_name
+ in {canonicalize_name(d.name) for d in dist.iter_dependencies()}
+ )
+
+ for query_name in query_names:
+ try:
+ dist = installed[query_name]
+ except KeyError:
+ continue
+
+ requires = sorted((req.name for req in dist.iter_dependencies()), key=str.lower)
+ required_by = sorted(_get_requiring_packages(dist), key=str.lower)
+
+ try:
+ 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
+ else:
+ files = sorted(files_iter)
+
+ metadata = dist.metadata
+
+ yield _PackageInfo(
+ name=dist.raw_name,
+ version=str(dist.version),
+ location=dist.location or "",
+ editable_project_location=dist.editable_project_location,
+ 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", ""),
+ project_urls=metadata.get_all("Project-URL", []),
+ author=metadata.get("Author", ""),
+ author_email=metadata.get("Author-email", ""),
+ license=metadata.get("License", ""),
+ entry_points=entry_points,
+ files=files,
+ )
+
+
+def print_results(
+ distributions: Iterable[_PackageInfo],
+ list_files: bool,
+ verbose: bool,
+) -> bool:
+ """
+ Print the information from installed distributions found.
+ """
+ results_printed = False
+ for i, dist in enumerate(distributions):
+ results_printed = True
+ if i > 0:
+ write_output("---")
+
+ write_output("Name: %s", dist.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)
+ if dist.editable_project_location is not None:
+ write_output(
+ "Editable project location: %s", dist.editable_project_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:")
+ for classifier in dist.classifiers:
+ write_output(" %s", classifier)
+ write_output("Entry-points:")
+ for entry in dist.entry_points:
+ write_output(" %s", entry.strip())
+ write_output("Project-URLs:")
+ for project_url in dist.project_urls:
+ write_output(" %s", project_url)
+ if list_files:
+ write_output("Files:")
+ if dist.files is None:
+ write_output("Cannot locate RECORD or installed-files.txt")
+ else:
+ for line in dist.files:
+ write_output(" %s", line.strip())
+ return results_printed
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/uninstall.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/uninstall.py
new file mode 100644
index 0000000..f198fc3
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/uninstall.py
@@ -0,0 +1,113 @@
+import logging
+from optparse import Values
+from typing import List
+
+from pip._vendor.packaging.utils import canonicalize_name
+
+from pip._internal.cli import cmdoptions
+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.status_codes import SUCCESS
+from pip._internal.exceptions import InstallationError
+from pip._internal.req import parse_requirements
+from pip._internal.req.constructors import (
+ install_req_from_line,
+ install_req_from_parsed_requirement,
+)
+from pip._internal.utils.misc import (
+ check_externally_managed,
+ protect_pip_from_modification_on_windows,
+)
+
+logger = logging.getLogger(__name__)
+
+
+class UninstallCommand(Command, SessionCommandMixin):
+ """
+ Uninstall packages.
+
+ pip is able to uninstall most installed packages. Known exceptions are:
+
+ - Pure distutils packages installed with ``python setup.py install``, which
+ leave behind no metadata to determine what files were installed.
+ - Script wrappers installed by ``python setup.py develop``.
+ """
+
+ usage = """
+ %prog [options] <package> ...
+ %prog [options] -r <requirements file> ..."""
+
+ def add_options(self) -> None:
+ self.cmd_opts.add_option(
+ "-r",
+ "--requirement",
+ dest="requirements",
+ action="append",
+ default=[],
+ metavar="file",
+ help=(
+ "Uninstall all the packages listed in the given requirements "
+ "file. This option can be used multiple times."
+ ),
+ )
+ self.cmd_opts.add_option(
+ "-y",
+ "--yes",
+ dest="yes",
+ action="store_true",
+ help="Don't ask for confirmation of uninstall deletions.",
+ )
+ self.cmd_opts.add_option(cmdoptions.root_user_action())
+ self.cmd_opts.add_option(cmdoptions.override_externally_managed())
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ def run(self, options: Values, args: List[str]) -> int:
+ session = self.get_default_session(options)
+
+ reqs_to_uninstall = {}
+ for name in args:
+ req = install_req_from_line(
+ name,
+ isolated=options.isolated_mode,
+ )
+ if req.name:
+ reqs_to_uninstall[canonicalize_name(req.name)] = req
+ else:
+ logger.warning(
+ "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
+ ):
+ req = install_req_from_parsed_requirement(
+ parsed_req, isolated=options.isolated_mode
+ )
+ if req.name:
+ reqs_to_uninstall[canonicalize_name(req.name)] = req
+ if not reqs_to_uninstall:
+ raise InstallationError(
+ f"You must give at least one requirement to {self.name} (see "
+ f'"pip help {self.name}")'
+ )
+
+ if not options.override_externally_managed:
+ check_externally_managed()
+
+ protect_pip_from_modification_on_windows(
+ modifying_pip="pip" in reqs_to_uninstall
+ )
+
+ for req in reqs_to_uninstall.values():
+ uninstall_pathset = req.uninstall(
+ auto_confirm=options.yes,
+ verbose=self.verbosity > 0,
+ )
+ if uninstall_pathset:
+ uninstall_pathset.commit()
+ if options.root_user_action == "warn":
+ warn_if_run_as_root()
+ return SUCCESS
diff --git a/venv/lib/python3.11/site-packages/pip/_internal/commands/wheel.py b/venv/lib/python3.11/site-packages/pip/_internal/commands/wheel.py
new file mode 100644
index 0000000..ed578aa
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/pip/_internal/commands/wheel.py
@@ -0,0 +1,183 @@
+import logging
+import os
+import shutil
+from optparse import Values
+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.status_codes import SUCCESS
+from pip._internal.exceptions import CommandError
+from pip._internal.operations.build.build_tracker import get_build_tracker
+from pip._internal.req.req_install import (
+ InstallRequirement,
+ check_legacy_setup_py_options,
+)
+from pip._internal.utils.misc import ensure_dir, normalize_path
+from pip._internal.utils.temp_dir import TempDirectory
+from pip._internal.wheel_builder import build, should_build_for_wheel_command
+
+logger = logging.getLogger(__name__)
+
+
+class WheelCommand(RequirementCommand):
+ """
+ Build Wheel archives for your requirements and dependencies.
+
+ Wheel is a built-package format, and offers the advantage of not
+ recompiling your software during every install. For more details, see the
+ wheel docs: https://wheel.readthedocs.io/en/latest/
+
+ 'pip wheel' uses the build system interface as described here:
+ https://pip.pypa.io/en/stable/reference/build-system/
+
+ """
+
+ usage = """
+ %prog [options] <requirement specifier> ...
+ %prog [options] -r <requirements file> ...
+ %prog [options] [-e] <vcs project url> ...
+ %prog [options] [-e] <local project path> ...
+ %prog [options] <archive url/path> ..."""
+
+ def add_options(self) -> None:
+ self.cmd_opts.add_option(
+ "-w",
+ "--wheel-dir",
+ dest="wheel_dir",
+ metavar="dir",
+ default=os.curdir,
+ help=(
+ "Build wheels into <dir>, where the default is the "
+ "current working directory."
+ ),
+ )
+ self.cmd_opts.add_option(cmdoptions.no_binary())
+ self.cmd_opts.add_option(cmdoptions.only_binary())
+ self.cmd_opts.add_option(cmdoptions.prefer_binary())
+ self.cmd_opts.add_option(cmdoptions.no_build_isolation())
+ self.cmd_opts.add_option(cmdoptions.use_pep517())
+ self.cmd_opts.add_option(cmdoptions.no_use_pep517())
+ self.cmd_opts.add_option(cmdoptions.check_build_deps())
+ self.cmd_opts.add_option(cmdoptions.constraints())
+ self.cmd_opts.add_option(cmdoptions.editable())
+ self.cmd_opts.add_option(cmdoptions.requirements())
+ self.cmd_opts.add_option(cmdoptions.src())
+ self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
+ self.cmd_opts.add_option(cmdoptions.no_deps())
+ self.cmd_opts.add_option(cmdoptions.progress_bar())
+
+ self.cmd_opts.add_option(
+ "--no-verify",
+ dest="no_verify",
+ action="store_true",
+ default=False,
+ help="Don't verify if built wheel is valid.",
+ )
+
+ self.cmd_opts.add_option(cmdoptions.config_settings())
+ self.cmd_opts.add_option(cmdoptions.build_options())
+ self.cmd_opts.add_option(cmdoptions.global_options())
+
+ self.cmd_opts.add_option(
+ "--pre",
+ action="store_true",
+ default=False,
+ help=(
+ "Include pre-release and development versions. By default, "
+ "pip only finds stable versions."
+ ),
+ )
+
+ self.cmd_opts.add_option(cmdoptions.require_hashes())
+
+ index_opts = cmdoptions.make_option_group(
+ cmdoptions.index_group,
+ self.parser,
+ )
+
+ self.parser.insert_option_group(0, index_opts)
+ self.parser.insert_option_group(0, self.cmd_opts)
+
+ @with_cleanup
+ def run(self, options: Values, args: List[str]) -> int:
+ session = self.get_default_session(options)
+
+ finder = self._build_package_finder(options, session)
+
+ options.wheel_dir = normalize_path(options.wheel_dir)
+ ensure_dir(options.wheel_dir)
+
+ build_tracker = self.enter_context(get_build_tracker())
+
+ directory = TempDirectory(
+ delete=not options.no_clean,
+ kind="wheel",
+ globally_managed=True,
+ )
+
+ reqs = self.get_requirements(args, options, finder, session)
+ check_legacy_setup_py_options(options, reqs)
+
+ wheel_cache = WheelCache(options.cache_dir)
+
+ preparer = self.make_requirement_preparer(
+ temp_build_dir=directory,
+ options=options,
+ build_tracker=build_tracker,
+ session=session,
+ finder=finder,
+ download_dir=options.wheel_dir,
+ use_user_site=False,
+ verbosity=self.verbosity,
+ )
+
+ resolver = self.make_resolver(
+ preparer=preparer,
+ finder=finder,
+ options=options,
+ wheel_cache=wheel_cache,
+ ignore_requires_python=options.ignore_requires_python,
+ use_pep517=options.use_pep517,
+ )
+
+ self.trace_basic_info(finder)
+
+ requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
+
+ reqs_to_build: List[InstallRequirement] = []
+ for req in requirement_set.requirements.values():
+ if req.is_wheel:
+ preparer.save_linked_requirement(req)
+ elif should_build_for_wheel_command(req):
+ reqs_to_build.append(req)
+
+ preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
+ requirement_set.warn_legacy_versions_and_specifiers()
+
+ # build wheels
+ build_successes, build_failures = build(
+ reqs_to_build,
+ wheel_cache=wheel_cache,
+ verify=(not options.no_verify),
+ build_options=options.build_options or [],
+ global_options=options.global_options or [],
+ )
+ for req in build_successes:
+ assert req.link and req.link.is_wheel
+ assert req.local_file_path
+ # copy from cache to target directory
+ try:
+ shutil.copy(req.local_file_path, options.wheel_dir)
+ except OSError as e:
+ logger.warning(
+ "Building wheel for %s failed: %s",
+ req.name,
+ e,
+ )
+ build_failures.append(req)
+ if len(build_failures) != 0:
+ raise CommandError("Failed to build one or more wheels")
+
+ return SUCCESS