1from __future__ import absolute_import 2 3import locale 4import logging 5import sys 6 7from pip._internal.cli import cmdoptions 8from pip._internal.cli.base_command import Command 9from pip._internal.cli.cmdoptions import make_target_python 10from pip._internal.cli.status_codes import SUCCESS 11from pip._internal.utils.logging import indent_log 12from pip._internal.utils.misc import get_pip_version 13from pip._internal.utils.typing import MYPY_CHECK_RUNNING 14from pip._internal.wheel import format_tag 15 16if MYPY_CHECK_RUNNING: 17 from typing import Any, List 18 from optparse import Values 19 20logger = logging.getLogger(__name__) 21 22 23def show_value(name, value): 24 # type: (str, str) -> None 25 logger.info('{}: {}'.format(name, value)) 26 27 28def show_sys_implementation(): 29 # type: () -> None 30 logger.info('sys.implementation:') 31 if hasattr(sys, 'implementation'): 32 implementation = sys.implementation # type: ignore 33 implementation_name = implementation.name 34 else: 35 implementation_name = '' 36 37 with indent_log(): 38 show_value('name', implementation_name) 39 40 41def show_tags(options): 42 # type: (Values) -> None 43 tag_limit = 10 44 45 target_python = make_target_python(options) 46 tags = target_python.get_tags() 47 48 # Display the target options that were explicitly provided. 49 formatted_target = target_python.format_given() 50 suffix = '' 51 if formatted_target: 52 suffix = ' (target: {})'.format(formatted_target) 53 54 msg = 'Compatible tags: {}{}'.format(len(tags), suffix) 55 logger.info(msg) 56 57 if options.verbose < 1 and len(tags) > tag_limit: 58 tags_limited = True 59 tags = tags[:tag_limit] 60 else: 61 tags_limited = False 62 63 with indent_log(): 64 for tag in tags: 65 logger.info(format_tag(tag)) 66 67 if tags_limited: 68 msg = ( 69 '...\n' 70 '[First {tag_limit} tags shown. Pass --verbose to show all.]' 71 ).format(tag_limit=tag_limit) 72 logger.info(msg) 73 74 75class DebugCommand(Command): 76 """ 77 Display debug information. 78 """ 79 80 name = 'debug' 81 usage = """ 82 %prog <options>""" 83 summary = 'Show information useful for debugging.' 84 ignore_require_venv = True 85 86 def __init__(self, *args, **kw): 87 super(DebugCommand, self).__init__(*args, **kw) 88 89 cmd_opts = self.cmd_opts 90 cmdoptions.add_target_python_options(cmd_opts) 91 self.parser.insert_option_group(0, cmd_opts) 92 93 def run(self, options, args): 94 # type: (Values, List[Any]) -> int 95 logger.warning( 96 "This command is only meant for debugging. " 97 "Do not use this with automation for parsing and getting these " 98 "details, since the output and options of this command may " 99 "change without notice." 100 ) 101 show_value('pip version', get_pip_version()) 102 show_value('sys.version', sys.version) 103 show_value('sys.executable', sys.executable) 104 show_value('sys.getdefaultencoding', sys.getdefaultencoding()) 105 show_value('sys.getfilesystemencoding', sys.getfilesystemencoding()) 106 show_value( 107 'locale.getpreferredencoding', locale.getpreferredencoding(), 108 ) 109 show_value('sys.platform', sys.platform) 110 show_sys_implementation() 111 112 show_tags(options) 113 114 return SUCCESS 115