简体   繁体   English

如何在“--help”中定义单击子命令的顺序

[英]How can I define the order of click sub-commands in "--help"

I have code like this:我有这样的代码:

import click

@click.group()
def entry_point():
    pass

entry_point.add_command(lidtk.data.download_documents.main)
entry_point.add_command(lidtk.data.create_ml_dataset.main)
entry_point.add_command(lidtk.classifiers.text_cat.textcat_ngram.cli)

which gives the help text:这给出了帮助文本:

lidtk --help
Usage: lidtk [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  create-dataset  Create sharable dataset from downloaded...
  download        Download 1000 documents of each language.
  textcat

which is over all pretty close to what I want.一切都非常接近我想要的。 But I would like to change the order to:但我想将顺序更改为:

Commands:
  download        Download 1000 documents of each language.
  create-dataset  Create sharable dataset from downloaded...
  textcat

How can this be done using click?如何使用单击来完成此操作?

It's a nice description at the top, but we can achieve it more easily这是顶部的一个很好的描述,但我们可以更轻松地实现它

import click
import collections


from .aws import aws_group
from .db import db_group
from .front import front_group
from .celery import celery_group
from .i18n import i18n_group
from .deprecated import add_deprecated


class OrderedGroup(click.Group):
    def __init__(self, name=None, commands=None, **attrs):
        super(OrderedGroup, self).__init__(name, commands, **attrs)
        #: the registered subcommands by their exported names.
        self.commands = commands or collections.OrderedDict()

    def list_commands(self, ctx):
        return self.commands


@click.group(cls=OrderedGroup)
def entire_group():
    """Entire Group"""


entire_group.add_command(aws_group)
entire_group.add_command(db_group)
entire_group.add_command(front_group)
entire_group.add_command(celery_group)
entire_group.add_command(i18n_group)
add_deprecated(entire_group)

Just change self.commands from Dict to OrderedDict .只需将self.commandsDict更改为OrderedDict As a result, my deprecated commands at a bottom of list.因此,我已弃用的​​命令位于列表底部。

The order of the commands listed by help is set by the list_commands() method of the click.Group class. help列出的命令顺序由click.Group类的list_commands()方法设置。 So, one way to approach the desire to change the help listing order is to inherit for click.Group and override list_commands to give the desired order. 因此,一种满足更改帮助列表顺序要求的方法是继承click.Group并覆盖list_commands以给出所需的顺序。

Custom Class 自定义类

This class overrides the click.Group.command() method which is used to decorate command functions. 此类重写用于装饰命令功能的click.Group.command()方法。 It adds the ability to specify a help_priority , which allows the sort order to be modified as desired: 它增加了指定help_priority ,该功能允许根据需要修改排序顺序:

class SpecialHelpOrder(click.Group):

    def __init__(self, *args, **kwargs):
        self.help_priorities = {}
        super(SpecialHelpOrder, self).__init__(*args, **kwargs)

    def get_help(self, ctx):
        self.list_commands = self.list_commands_for_help
        return super(SpecialHelpOrder, self).get_help(ctx)

    def list_commands_for_help(self, ctx):
        """reorder the list of commands when listing the help"""
        commands = super(SpecialHelpOrder, self).list_commands(ctx)
        return (c[1] for c in sorted(
            (self.help_priorities.get(command, 1), command)
            for command in commands))

    def command(self, *args, **kwargs):
        """Behaves the same as `click.Group.command()` except capture
        a priority for listing command names in help.
        """
        help_priority = kwargs.pop('help_priority', 1)
        help_priorities = self.help_priorities

        def decorator(f):
            cmd = super(SpecialHelpOrder, self).command(*args, **kwargs)(f)
            help_priorities[cmd.name] = help_priority
            return cmd

        return decorator

Using the Custom Class 使用自定义类

By passing the cls parameter to the click.group() decorator, any commands added to the group via the the group.command() can be passed a help_priority . 由经过的cls参数到click.group()装饰,任何命令经由所述添加到组group.command()可以传递一个help_priority The priorities default to 1, and lower numbers are printed first. 优先级默认为1,并且较低的数字首先打印。

@click.group(cls=SpecialHelpOrder)
def cli():
    """My Excellent CLI"""

@cli.command(help_priority=5)
def my_command():
    ....

How does this work? 这是如何运作的?

This works because click is a well designed OO framework. 之所以可行,是因为click是一个设计良好的OO框架。 The @click.group() decorator usually instantiates a click.Group object but allows this behavior to be over ridden with the cls parameter. @click.group()装饰器通常会实例化click.Group对象,但允许使用cls参数覆盖此行为。 So it is a relatively easy matter to inherit from click.Group in our own class and over ride the desired methods. 因此,在我们自己的类中从click.Group继承并覆盖所需的方法是相对容易的事情。

Steps here: 步骤如下:

  1. Override Group.command() so that decorated commands can be passed a help_priority . 重写Group.command()以便可以将装饰后的命令传递给help_priority In the over ridden decorator, capture the desired priority for later 在重写的装饰器中,捕获所需的优先级以备后用
  2. Override Group.get_help() . 覆盖Group.get_help() In the over ridden method, substitute Group.list_commands with a list_commands which will order the commands as desired. Group.list_commands方法中,将Group.list_commands替换为list_commands ,它将按需要对命令进行排序。

Test Code: 测试代码:

import click

@click.group(cls=SpecialHelpOrder)
def cli():
    pass

@cli.command()
def command1():
    '''Command #1'''

@cli.command(help_priority=5)
def command2():
    '''Command #2'''

@cli.command()
def command3():
    '''Command #3'''

if __name__ == '__main__':
    cli('--help'.split())

Test Results: 检测结果:

Usage: test.py [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  command1  Command #1
  command3  Command #3
  command2  Command #2

The answer by Максим Стукало helped me a lot. Максим Стукало回答对我帮助很大。 However, it was missing some typing info.但是,它缺少一些打字信息。 Given, we always do strict typing and given I can't edit the post, I figured I'd create another post, maybe it helps someone:鉴于我们总是严格打字并且我无法编辑帖子,我想我会创建另一个帖子,也许它可以帮助某人:

import collections
from typing import Optional, Mapping

import click


class OrderedGroup(click.Group):
    def __init__(self, name: Optional[str] = None, commands: Optional[Mapping[str, click.Command]] = None, **kwargs):
        super(OrderedGroup, self).__init__(name, commands, **kwargs)
        #: the registered subcommands by their exported names.
        self.commands = commands or collections.OrderedDict()

    def list_commands(self, ctx: click.Context) -> Mapping[str, click.Command]:
        return self.commands

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将我的 Click 命令(每个命令都有一组子命令)拆分为多个文件? - How can I split my Click commands, each with a set of sub-commands, into multiple files? 如何将 typer 命令放在单独的模块中而不成为子命令? - How can I put typer commands in seperate modules without becoming sub-commands? 我可以有一个main()Click函数来调用所有其他子命令吗? - Can I have a main() Click function that invokes all other sub-commands? 如何构建子命令来捆绑也应该独立运行的脚本? - How can I build sub-commands to bundle scripts that should also work independently? 如何在 argparse 的帮助消息中包含所有子命令帮助消息? - How to include all sub-commands help message in argparse's help messages? 如何使用 python argparse 解析多个嵌套的子命令? - How to parse multiple nested sub-commands using python argparse? 如何在 argparse 中使用子命令以及可选的位置 arguments - How to use sub-commands along with optional positional arguments in argparse Python argparse 位置参数和子命令 - Python argparse positional arguments and sub-commands 使用plac定义子命令的常用选项 - Defining common options for sub-commands with plac argparse 子命令和组:在子命令中在自己的组中设置帮助对话框而不隐藏在顶级帮助对话框中 - argparse sub-commands and groups: Setting help-dialog in sub-command on its own group without being hidden in top-level help-dialog
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM