Path: blob/main/test/lib/python3.9/site-packages/pip/_internal/commands/debug.py
4804 views
import locale1import logging2import os3import sys4from optparse import Values5from types import ModuleType6from typing import Any, Dict, List, Optional78import pip._vendor9from pip._vendor.certifi import where10from pip._vendor.packaging.version import parse as parse_version1112from pip import __file__ as pip_location13from pip._internal.cli import cmdoptions14from pip._internal.cli.base_command import Command15from pip._internal.cli.cmdoptions import make_target_python16from pip._internal.cli.status_codes import SUCCESS17from pip._internal.configuration import Configuration18from pip._internal.metadata import get_environment19from pip._internal.utils.logging import indent_log20from pip._internal.utils.misc import get_pip_version2122logger = logging.getLogger(__name__)232425def show_value(name: str, value: Any) -> None:26logger.info("%s: %s", name, value)272829def show_sys_implementation() -> None:30logger.info("sys.implementation:")31implementation_name = sys.implementation.name32with indent_log():33show_value("name", implementation_name)343536def create_vendor_txt_map() -> Dict[str, str]:37vendor_txt_path = os.path.join(38os.path.dirname(pip_location), "_vendor", "vendor.txt"39)4041with open(vendor_txt_path) as f:42# Purge non version specifying lines.43# Also, remove any space prefix or suffixes (including comments).44lines = [45line.strip().split(" ", 1)[0] for line in f.readlines() if "==" in line46]4748# Transform into "module" -> version dict.49return dict(line.split("==", 1) for line in lines)505152def get_module_from_module_name(module_name: str) -> ModuleType:53# Module name can be uppercase in vendor.txt for some reason...54module_name = module_name.lower()55# PATCH: setuptools is actually only pkg_resources.56if module_name == "setuptools":57module_name = "pkg_resources"5859__import__(f"pip._vendor.{module_name}", globals(), locals(), level=0)60return getattr(pip._vendor, module_name)616263def get_vendor_version_from_module(module_name: str) -> Optional[str]:64module = get_module_from_module_name(module_name)65version = getattr(module, "__version__", None)6667if not version:68# Try to find version in debundled module info.69assert module.__file__ is not None70env = get_environment([os.path.dirname(module.__file__)])71dist = env.get_distribution(module_name)72if dist:73version = str(dist.version)7475return version767778def show_actual_vendor_versions(vendor_txt_versions: Dict[str, str]) -> None:79"""Log the actual version and print extra info if there is80a conflict or if the actual version could not be imported.81"""82for module_name, expected_version in vendor_txt_versions.items():83extra_message = ""84actual_version = get_vendor_version_from_module(module_name)85if not actual_version:86extra_message = (87" (Unable to locate actual module version, using"88" vendor.txt specified version)"89)90actual_version = expected_version91elif parse_version(actual_version) != parse_version(expected_version):92extra_message = (93" (CONFLICT: vendor.txt suggests version should"94" be {})".format(expected_version)95)96logger.info("%s==%s%s", module_name, actual_version, extra_message)979899def show_vendor_versions() -> None:100logger.info("vendored library versions:")101102vendor_txt_versions = create_vendor_txt_map()103with indent_log():104show_actual_vendor_versions(vendor_txt_versions)105106107def show_tags(options: Values) -> None:108tag_limit = 10109110target_python = make_target_python(options)111tags = target_python.get_tags()112113# Display the target options that were explicitly provided.114formatted_target = target_python.format_given()115suffix = ""116if formatted_target:117suffix = f" (target: {formatted_target})"118119msg = "Compatible tags: {}{}".format(len(tags), suffix)120logger.info(msg)121122if options.verbose < 1 and len(tags) > tag_limit:123tags_limited = True124tags = tags[:tag_limit]125else:126tags_limited = False127128with indent_log():129for tag in tags:130logger.info(str(tag))131132if tags_limited:133msg = (134"...\n[First {tag_limit} tags shown. Pass --verbose to show all.]"135).format(tag_limit=tag_limit)136logger.info(msg)137138139def ca_bundle_info(config: Configuration) -> str:140levels = set()141for key, _ in config.items():142levels.add(key.split(".")[0])143144if not levels:145return "Not specified"146147levels_that_override_global = ["install", "wheel", "download"]148global_overriding_level = [149level for level in levels if level in levels_that_override_global150]151if not global_overriding_level:152return "global"153154if "global" in levels:155levels.remove("global")156return ", ".join(levels)157158159class DebugCommand(Command):160"""161Display debug information.162"""163164usage = """165%prog <options>"""166ignore_require_venv = True167168def add_options(self) -> None:169cmdoptions.add_target_python_options(self.cmd_opts)170self.parser.insert_option_group(0, self.cmd_opts)171self.parser.config.load()172173def run(self, options: Values, args: List[str]) -> int:174logger.warning(175"This command is only meant for debugging. "176"Do not use this with automation for parsing and getting these "177"details, since the output and options of this command may "178"change without notice."179)180show_value("pip version", get_pip_version())181show_value("sys.version", sys.version)182show_value("sys.executable", sys.executable)183show_value("sys.getdefaultencoding", sys.getdefaultencoding())184show_value("sys.getfilesystemencoding", sys.getfilesystemencoding())185show_value(186"locale.getpreferredencoding",187locale.getpreferredencoding(),188)189show_value("sys.platform", sys.platform)190show_sys_implementation()191192show_value("'cert' config value", ca_bundle_info(self.parser.config))193show_value("REQUESTS_CA_BUNDLE", os.environ.get("REQUESTS_CA_BUNDLE"))194show_value("CURL_CA_BUNDLE", os.environ.get("CURL_CA_BUNDLE"))195show_value("pip._vendor.certifi.where()", where())196show_value("pip._vendor.DEBUNDLED", pip._vendor.DEBUNDLED)197198show_vendor_versions()199200show_tags(options)201202return SUCCESS203204205