是否可以为基于 Click 的界面中的所有子命令添加全局参数?

2023-12-22

我正在 virtualenv 下使用 Click 并使用entry_pointsetuptools 中的指令将根映射到名为调度的函数。

我的工具公开了两个子命令serve and config,我在顶级组上使用一个选项来确保用户始终通过--path指示。然而用法如下:

mycommand --path=/tmp serve

这俩serve and config子命令需要确保用户始终传递路径,理想情况下我希望将 cli 呈现为:

mycommand serve /tmp` or `mycommand config validate /tmp

当前基于 Click 的实现如下:

# cli root

@click.group()
@click.option('--path', type=click.Path(writable=True))
@click.version_option(__version__)
@click.pass_context
def dispatch(ctx, path):
    """My project description"""
    ctx.obj = Project(path="config.yaml")

# serve

@dispatch.command()
@pass_project
def serve(project):
    """Starts WSGI server using the configuration"""
    print "hello"

# config

@dispatch.group()
@pass_project
def config(project):
    """Validate or initalise a configuration file"""
    pass

@config.command("validate")
@pass_project
def config_validate(project):
    """Reports on the validity of a configuration file"""
    pass

@config.command("init")
@pass_project
def config_init(project):
    """Initialises a skeleton configuration file"""
    pass

如果不向每个子命令添加路径参数,这可能吗?


如果有一个特定的参数,您只想装饰到组上,但根据需要适用于所有命令,您可以通过一些额外的管道来做到这一点,例如:

定制类:

import click

class GroupArgForCommands(click.Group):
    """Add special argument on group to front of command list"""

    def __init__(self, *args, **kwargs):
        super(GroupArgForCommands, self).__init__(*args, **kwargs)
        cls = GroupArgForCommands.CommandArgument

        # gather the special arguments
        self._cmd_args = {
            a.name: a for a in self.params if isinstance(a, cls)}

        # strip out the special arguments
        self.params = [a for a in self.params if not isinstance(a, cls)]

        # hook the original add_command method
        self._orig_add_command = click.Group.add_command.__get__(self)

    class CommandArgument(click.Argument):
        """class to allow us to find our special arguments"""

    @staticmethod
    def command_argument(*param_decls, **attrs):
        """turn argument type into type we can find later"""

        assert 'cls' not in attrs, "Not designed for custom arguments"
        attrs['cls'] = GroupArgForCommands.CommandArgument

        def decorator(f):
            click.argument(*param_decls, **attrs)(f)
            return f

        return decorator

    def add_command(self, cmd, name=None):

        # hook add_command for any sub groups
        if hasattr(cmd, 'add_command'):
            cmd._orig_add_command = cmd.add_command
            cmd.add_command = GroupArgForCommands.add_command.__get__(cmd)
            cmd.cmd_args = self._cmd_args

        # call original add_command
        self._orig_add_command(cmd, name)

        # if this command's callback has desired parameters add them
        import inspect
        args = inspect.signature(cmd.callback)
        for arg_name in reversed(list(args.parameters)):
            if arg_name in self._cmd_args:
                cmd.params[:] = [self._cmd_args[arg_name]] + cmd.params

使用自定义类:

要使用自定义类,请传递cls参数到click.group()装饰器,使用@GroupArgForCommands.command_argument特殊参数的装饰器,然后根据需要向任何命令添加与特殊参数同名的参数。

@click.group(cls=GroupArgForCommands)
@GroupArgForCommands.command_argument('special')
def a_group():
    """My project description"""

@a_group.command()
def a_command(special):
    """a command under the group"""

这是如何运作的?

这有效是因为click是一个设计良好的OO框架。这@click.group()装饰器通常会实例化一个click.Group对象,但允许此行为被覆盖cls范围。所以继承是一件比较容易的事情click.Group在我们自己的班级中并超越所需的方法。

在这种情况下我们重写click.Group.add_command()这样,当添加命令时,我们可以检查命令回调参数,看看它们是否与我们的任何特殊参数具有相同的名称。如果它们匹配,则参数将添加到命令的参数中,就像直接对其进行修饰一样。

此外GroupArgForCommands实现了一个command_argument()方法。当添加特殊参数而不是使用时,此方法用作装饰器click.argument()

测试代码:

def process_path_to_project(ctx, cmd, value):
    """param callback example to convert path to project"""
    # Use 'path' to construct a project.
    # For this example we will just annotate and pass through
    return 'converted {}'.format(value)


@click.group(cls=GroupArgForCommands)
@GroupArgForCommands.command_argument('path',
                                      callback=process_path_to_project)
def dispatch():
    """My project description"""


@dispatch.command()
def serve(path):
    """Starts WSGI server using the configuration"""
    click.echo('serve {}'.format(path))

@dispatch.group()
def config():
    """Validate or initalise a configuration file"""
    pass

@config.command("validate")
def config_validate():
    """Reports on the validity of a configuration file"""
    click.echo('config_validate')


@config.command("init")
def config_init(path):
    """Initialises a skeleton configuration file"""
    click.echo('config_init {}'.format(path))



if __name__ == "__main__":
    commands = (
        'config init a_path',
        'config init',
        'config validate a_path',
        'config validate',
        'config a_path',
        'config',
        'serve a_path',
        'serve',
        'config init --help',
        'config validate --help',
        '',
    )

    import sys, time

    time.sleep(1)
    print('Click Version: {}'.format(click.__version__))
    print('Python Version: {}'.format(sys.version))
    for command in commands:
        try:
            time.sleep(0.1)
            print('-----------')
            print('> ' + command)
            time.sleep(0.1)
            dispatch(command.split())

        except BaseException as exc:
            if str(exc) != '0' and \
                    not isinstance(exc, (click.ClickException, SystemExit)):
                raise

Results:

Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> config init a_path
config_init converted a_path
-----------
> config init
Usage: test.py config init [OPTIONS] PATH

Error: Missing argument "path".
-----------
> config validate a_path
Usage: test.py config validate [OPTIONS]

Error: Got unexpected extra argument (a_path)
-----------
> config validate
config_validate
-----------
> config a_path
Usage: test.py config [OPTIONS] COMMAND [ARGS]...

Error: No such command "a_path".
-----------
> config
Usage: test.py config [OPTIONS] COMMAND [ARGS]...

  Validate or initalise a configuration file

Options:
  --help  Show this message and exit.

Commands:
  init      Initialises a skeleton configuration file
  validate  Reports on the validity of a configuration...
-----------
> serve a_path
serve converted a_path
-----------
> serve
Usage: test.py serve [OPTIONS] PATH

Error: Missing argument "path".
-----------
> config init --help
Usage: test.py config init [OPTIONS] PATH

  Initialises a skeleton configuration file

Options:
  --help  Show this message and exit.
-----------
> config validate --help
Usage: test.py config validate [OPTIONS]

  Reports on the validity of a configuration file

Options:
  --help  Show this message and exit.
-----------
> 
Usage: test.py [OPTIONS] COMMAND [ARGS]...

  My project description

Options:
  --help  Show this message and exit.

Commands:
  config  Validate or initalise a configuration file
  serve   Starts WSGI server using the configuration
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以为基于 Click 的界面中的所有子命令添加全局参数? 的相关文章

  • Python逻辑运算符优先级[重复]

    这个问题在这里已经有答案了 哪个运算符优先4 gt 5 or 3 lt 4 and 9 gt 8 这会被评估为真还是假 我知道该声明3 gt 4 or 2 lt 3 and 9 gt 10 显然应该评估为 false 但我不太确定 pyth
  • 如何使用 imaplib 获取“消息 ID”

    我尝试获取一个在操作期间不会更改的唯一 ID 我觉得UID不好 所以我认为 Message ID 是正确的 但我不知道如何获取它 我只知道 imap fetch uid XXXX 有人有解决方案吗 来自 IMAP 文档本身 IMAP4消息号
  • 将数据帧行转换为字典

    我有像下面的示例数据这样的数据帧 我正在尝试将数据帧中的一行转换为类似于下面所需输出的字典 但是当我使用 to dict 时 我得到了索引和列值 有谁知道如何将行转换为像所需输出那样的字典 任何提示都非常感激 Sample data pri
  • Pandas 中允许重复列

    我将一个大的 CSV 包含股票财务数据 文件分割成更小的块 CSV 文件的格式不同 像 Excel 数据透视表之类的东西 第一列的前几行包含一些标题 公司名称 ID 等在以下列中重复 因为一家公司有多个属性 而不是一家公司只有一栏 在前几行
  • 从零开始的 numpy 形状意味着什么

    好的 我发现数组的形状中可以包含 0 对于将 0 作为唯一维度的情况 这对我来说是有意义的 它是一个空数组 np zeros 0 但如果你有这样的情况 np zeros 0 100 让我很困惑 为什么这么定义呢 据我所知 这只是表达空数组的
  • 忽略 Mercurial hook 中的某些 Mercurial 命令

    我有一个像这样的善变钩子 hooks pretxncommit myhook python path to file myhook 代码如下所示 def myhook ui repo kwargs do some stuff 但在我的例子中
  • 如何计算numpy数组中元素的频率?

    我有一个 3 D numpy 数组 其中包含重复的元素 counterTraj shape 13530 1 1 例如 counterTraj 包含这样的元素 我只显示了几个元素 array 136 129 130 103 102 101 我
  • Pandas 数据帧到 numpy 数组 [重复]

    这个问题在这里已经有答案了 我对 Python 很陌生 经验也很少 我已经设法通过复制 粘贴和替换我拥有的数据来使一些代码正常工作 但是我一直在寻找如何从数据框中选择数据 但无法理解这些示例并替换我自己的数据 总体目标 如果有人真的可以帮助
  • 对图像块进行多重处理

    我有一个函数必须循环遍历图像的各个像素并计算一些几何形状 此函数需要很长时间才能运行 在 24 兆像素图像上大约需要 5 小时 但似乎应该很容易在多个内核上并行运行 然而 我一生都找不到一个有据可查 解释充分的例子来使用 Multiproc
  • 从 python 发起 SSH 隧道时出现问题

    目标是在卫星服务器和集中式注册数据库之间建立 n 个 ssh 隧道 我已经在我的服务器之间设置了公钥身份验证 因此它们只需直接登录而无需密码提示 怎么办 我试过帕拉米科 它看起来不错 但仅仅建立一个基本的隧道就变得相当复杂 尽管代码示例将受
  • 如何使用列表作为pandas数据框中的值?

    我有一个数据框 需要列的子集包含具有多个值的条目 下面是一个带有 运行时 列的数据框 其中包含程序在各种条件下的运行时 df condition a runtimes 1 1 5 2 condition b runtimes 0 5 0 7
  • 将 2D NumPy 数组按元素相乘并求和

    我想知道是否有一种更快的方法 专用 NumPy 函数来执行 2D NumPy 数组的元素乘法 然后对所有元素求和 我目前使用np sum np multiply A B 其中 A B 是相同维度的 NumPy 数组m x n 您可以使用np
  • mac osx 10.8 上的初学者 python

    我正在学习编程 并且一直在使用 Ruby 和 ROR 但我觉得我更喜欢 Python 语言来学习编程 虽然我看到了 Ruby 和 Rails 的优点 但我觉得我需要一种更容易学习编程概念的语言 因此是 Python 但是 我似乎找不到适用于
  • 使用yield 进行字典理解

    作为一个人为的例子 myset set a b c d mydict item yield join item s for item in myset and list mydict gives as cs bs ds a None b N
  • 默认情况下,Keras 自定义层参数是不可训练的吗?

    我在 Keras 中构建了一个简单的自定义层 并惊讶地发现参数默认情况下未设置为可训练 我可以通过显式设置可训练属性来使其工作 我无法通过查看文档或代码来解释为什么会这样 这是应该的样子还是我做错了什么导致默认情况下参数不可训练 代码 im
  • 迭代 my_dict.keys() 并修改字典中的值是否会使迭代器失效?

    我的例子是这样的 for my key in my dict keys my dict my key mutate 上述代码的行为是否已定义 假设my dict是一本字典并且mutate是一个改变其对象的方法 我担心的是 改变字典中的值可能
  • 无法在前端使用 JavaScript Fetch API 将文件上传到 FastAPI 后端

    我正在尝试弄清楚如何将图像发送到我的 API 并验证生成的token那是在header的请求 到目前为止 这就是我所处的位置 app post endreProfilbilde async def endreProfilbilde requ
  • 限制 django 应用程序模型中的单个记录?

    我想使用模型来保存 django 应用程序的系统设置 因此 我想限制该模型 使其只能有一条记录 极限怎么办 尝试这个 class MyModel models Model onefield models CharField The fiel
  • 列表值的意外更改

    这是我的课 class variable object def init self name name alias parents values table name of the variable self name 这是有问题的函数 f
  • Scrapy Spider不存储状态(持久状态)

    您好 有一个基本的蜘蛛 可以运行以获取给定域上的所有链接 我想确保它保持其状态 以便它可以从离开的位置恢复 我已按照给定的网址进行操作http doc scrapy org en latest topics jobs html http d

随机推荐

  • 如何从 e.target.name 更新状态中的对象

    我正在尝试从这样的表单输入数据 h1 Company Position h1
  • 对数刻度(x 轴)直方图

    我需要的是 X 轴以对数刻度显示的直方图 但是 我仍然希望直方图中的每个条形都具有相同的宽度 不管怎样 我想出了 或发现 具有较高值的 显示条与较窄的显示条 它们在普通比例上具有相同的宽度 而不是在对数比例上 这是我现在正在做的事情 edg
  • Python c-api 和 unicode 字符串

    我需要在 python 对象和各种编码的 c 字符串之间进行转换 使用 PyUnicode Decode 从 C 字符串到 unicode 对象相当简单 但是我不知道如何走另一条路 char can be a wchar t or any
  • 基于 Rails 中每个下拉菜单的嵌套下拉框和多选框?

    我有一个要求 但如何开始有点困难 我寻求一些帮助 我有三个表 即服装 类别和材料 考虑服装表包含 男装 童装 我有一个页面来添加服装 在添加服装时 我需要一个下拉菜单 其中应列出类别 选择类别后 属于所选类别的材料应出现在多选框中 我们可以
  • angular-cli如何添加全局样式?

    我使用 Sass 创建了一个全局样式表并将其放在public style styles scss 我只指定背景颜色 在索引中 我添加了一个链接 背景颜色不适用于 body 标记 检查正文标签后 我可以看到背景颜色已应用但被否决scaffol
  • 如何在面板中的另一个 WPF 窗口内加载 WPF (xaml) 窗口?

    这可能吗 我使用了 Frame 控件并且 显示 例如 showwindow xaml 但我收到这个错误 根元素对于导航无效 确保您可以使用以下方式导航 显示 窗口 YourFrame Navigate YourWindow 然而 我不太喜欢
  • 如何使用张量板制作散点图-tensorflow

    现在 我正在研究张量流 但是 我无法使用张量板绘制点图 如果我有训练样本数据 就像那样 train X numpy asarray 3 3 4 4 5 5 6 71 6 93 4 168 9 779 train Y numpy asarra
  • jQuery - 如何按属性名称开头选择值

    我想通过给出属性名称 仅开头 来选择属性值 例如 如果我们有 html 标签 div class slide div 我想从属性中选择以以下开头的值data 先谢谢您的帮助 如果您想要所有 data 属性 您可以迭代 jq 数据对象 sli
  • 如何使用图像作为提交按钮?

    有人可以帮助更改此设置以合并名为的图像BUTTON1 JPG而不是标准submit button
  • python中编译的正则表达式对象的类型

    python中编译后的正则表达式是什么类型 我特别想评价一下 isinstance re compile 是真实的 出于内省的目的 我的一个解决方案是 有一些全局常量REGEX TYPE type re compile 但看起来不太优雅 E
  • 使用 int 与 Integer

    我遇到一个类 它使用整数变量来捕获要在 for 循环中使用的大小 这是好的做法还是我们应该使用 int 原始数据类型 Integer size something getFields size for Integer j 0 j lt si
  • 将自定义对象的数据绑定到MvvmCross中的TextView

    I have one custom object in my ViewModel I want to bind only one of its member to textview in my droid view 我只想将该对象的字符串成
  • jQuery 显示一个 Div 并隐藏其他 Div

    http jsfiddle net yrM3H 2 http jsfiddle net yrM3H 2 我有以下代码 jQuery document ready function jQuery toggle next hidden hide
  • 检查变量是否已设置然后回显而不重复?

    是否有一种简洁的方法来检查变量是否已设置 然后回显它而不重复相同的变量名称 而不是这个 我正在考虑这个 C 风格伪代码中的一些内容 PHP has sprintf http www php net manual en function sp
  • 如何更改@NotNull注释对应返回的响应JSON

    我有一个简单的代码 当 RequestBody 中不存在 customerId 时 它返回错误 json VO 类 public class OrderVO private int orderId NotNull message Custo
  • 如何向 html 5 视频添加嵌入链接

    如果您在 Discord 中链接 YouTube 视频 它会在 Discord 上显示为可播放的视频 而不仅仅是链接 对于我的视频 如果我从我的网站链接它们 不和谐会将它们显示为链接而不是视频 我听说我需要在其中嵌入链接 但我不知道我在寻找
  • 打印机 println:未创建新行

    我正在尝试使用 Apache POI 类将 Outlook MSG 文件解码为文本文件 一切正常 除了println的方法PrintWriter 它不会创建新行 它只是将每个句子直接一个接一个地连接起来 下面代码片段的结果是 De text
  • 正则表达式将数字与逗号和点匹配

    我想使用匹配整数和浮点数re模块 因此 如果有人键入以下输入类型之一 它应该验证它是否是一个数字 1000 1 000 1 000 1 000 98 1 000 1 0 1 0000 现在我正在使用以下内容 0 9 任何帮助表示赞赏 对于给
  • 将 JSON 反序列化为对象

    我正在将 JSON 字符串反序列化为对象 我无法使用Dictionary
  • 是否可以为基于 Click 的界面中的所有子命令添加全局参数?

    我正在 virtualenv 下使用 Click 并使用entry pointsetuptools 中的指令将根映射到名为调度的函数 我的工具公开了两个子命令serve and config 我在顶级组上使用一个选项来确保用户始终通过 pa