命令行界面

The pip._internal.cli 包负责处理和提供 pip 的命令行界面。此包处理

  • CLI 选项定义和解析

  • 自动完成

  • 分派到各种命令

  • 实用程序,如进度条和旋转器

注意

本节文档目前正在编写中。pip 开发人员欢迎您帮助完成本节文档。如果您有兴趣帮忙,请在 跟踪问题 中告诉我们。

概述

一个 ConfigOptionParser 实例用作“主解析器”,用于解析顶级参数。

Command 然后使用另一个 ConfigOptionParser 实例来解析命令特定的参数。

命令结构

本节显示了每个命令类将继承的类层次结构。

base_command.py 定义了基类 Command,每个其他命令将直接或间接地继承自它(参见本节末尾的命令树)。

使用 ConfigOptionParser(参见 配置和 CLI “混合”),此类添加了常规选项并实例化了cmd_opts 组,如果需要,每个其他特定选项都将添加到每个命令类的cmd_opts 中(参见本节末尾的命令树)。对于那些定义特定选项的命令,例如 pip install 命令上的 --dry-run,必须将选项添加到cmd_opts(这是add_options 方法的工作),该方法将在 Command 初始化时自动调用。

基类 Command 具有以下方法

class Command
main()

类的主要方法,它始终被调用(如 main.py 中的 main 所示)。它负责调用类的特定 run 方法并处理可能的错误。

run()

定义命令实际操作的抽象方法。

add_options()

在类上插入额外选项的可选方法,在 Command 初始化时调用。

一些命令具有更专门的行为(例如,参见 pip index)。这些命令将继承自 IndexGroupCommand,它继承自 CommandSessionCommandMixin,以构建相应的请求的 pip 会话。

最后,RequirementCommand 继承自 IndexGroupCommand,是那些以任何形式使用需求的命令的基类,例如 pip install

除了之前的类之外,还有一个最后需要提到的混入类,CommandSessionCommandMixin 都是从它继承的:CommandContextMixIn,负责命令的上下文。

在以下命令树中,我们可以看到为不同的 pip 命令定义的层次结构,其中每个命令都定义在它继承的基类下

命令
├─ cache, check, completion, configuration, debug, freeze, hash, help, inspect, show, search, uninstall
└─ IndexGroupCommand
├─ index, list
└─ RequirementCommand
└─ wheel, download, install

选项定义

共享选项集在 cmdoptions.py 模块中定义,以及我们在调用命令的帮助或 pip index 的帮助消息时看到的常规选项软件包索引选项组。所有选项都是根据函数定义的,这些函数在调用时会返回 optparse.Option 实例,而特定选项组,例如 pip config配置选项,在每个特定命令文件中定义(例如,参见 configuration.py)。

参数解析

应用程序的主要入口点在 main.py 模块中的 main 函数中定义。此函数负责 自动完成,调用 parse_command 函数并通过 create_command 创建和运行子程序,在该子程序上调用 main 方法。

parse_commandmain_parser.py 模块中定义,该模块定义了以下两个函数

parse_command()

负责 pip 程序的初始解析的函数。创建主解析器(参见下一个函数 create_main_parser)以提取常规选项和剩余参数。例如,运行 pip --timeout=5 install --user INITools['--timeout=5'] 拆分为常规选项,并将 ['install', '--user', 'INITools'] 作为其余部分。

在此步骤中,程序处理选项 --python--versionpippip help。如果未找到上述任何选项,则尝试提取命令名称和参数。

create_main_parser()

创建主解析器(在控制台中键入 pip 以查看程序的描述)。内部解析器 (ConfigOptionParser) 在此添加了常规选项组和来自 cmdoptions.py 的命令列表。

在完成初始解析后,create_command 负责使用存储在 commands_dict 变量中的信息创建相应的命令,并调用其 main 方法(参见 命令结构)。

每个特定命令(在基本 Command 类中定义)都会进行第二次参数解析,再次使用 ConfigOptionParser

参数访问

要访问所有选项和参数,Command.run() 将选项作为 optparse.Values 以及参数的字符串列表(在 Command.main() 中解析)传入。基本 Command 类的内部方法负责在对特定命令调用 parse_args 后传递这些变量。

配置和 CLI “融合”

基本 Command 实例化 ConfigOptionParser 类,该类负责解析过程(通过其父类 optparse.OptionParser)。其主要添加部分包括以下函数

class ConfigOptionParser(OptionParser)
get_default_values()

覆盖原始方法以允许在实例化选项解析器后更新默认值。

它允许使用 Configuration 类(有关更多信息,请参阅 配置)覆盖默认选项和参数,以包含环境变量和来自配置文件的设置。

进度条和旋转器

cli 子包中还有另外两个模块负责显示程序的状态。

  • progress_bars.py

    此模块包含以下函数

    get_download_progress_renderer()

    它使用 rich 功能来渲染下载进度。

    此函数(用于 download.py,在 Downloader 类中),允许在运行 pip install 时观察大型包的下载过程。

  • spinner.py

    此模块的主要功能是

    open_spinner()

    它生成适当类型的旋转器,该旋转器在 subprocess.py 模块中的 call_subprocess 函数中使用,以便用户可以看到正在运行的程序。

  • TODO:奇特之处/标准做法/广泛的想法。(避免在选项定义中使用列表,特殊情况下对选项值类型的处理,)

未来的重构想法

  • 将选项定义更改为更具声明性的、一致的、静态的数据结构,替换当前的 partial(Option, ...) 形式

  • 将进度条和旋转器移到 cli.ui 子包中

  • 将所有 Command 类移到 cli.commands 子包中(包括基类)