簡體   English   中英

如何在“--help”中定義單擊子命令的順序

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

我有這樣的代碼:

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)

這給出了幫助文本:

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

一切都非常接近我想要的。 但我想將順序更改為:

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

如何使用單擊來完成此操作?

這是頂部的一個很好的描述,但我們可以更輕松地實現它

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)

只需將self.commandsDict更改為OrderedDict 因此,我已棄用的​​命令位於列表底部。

help列出的命令順序由click.Group類的list_commands()方法設置。 因此,一種滿足更改幫助列表順序要求的方法是繼承click.Group並覆蓋list_commands以給出所需的順序。

自定義類

此類重寫用於裝飾命令功能的click.Group.command()方法。 它增加了指定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

使用自定義類

由經過的cls參數到click.group()裝飾,任何命令經由所述添加到組group.command()可以傳遞一個help_priority 優先級默認為1,並且較低的數字首先打印。

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

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

這是如何運作的?

之所以可行,是因為click是一個設計良好的OO框架。 @click.group()裝飾器通常會實例化click.Group對象,但允許使用cls參數覆蓋此行為。 因此,在我們自己的類中從click.Group繼承並覆蓋所需的方法是相對容易的事情。

步驟如下:

  1. 重寫Group.command()以便可以將裝飾后的命令傳遞給help_priority 在重寫的裝飾器中,捕獲所需的優先級以備后用
  2. 覆蓋Group.get_help() Group.list_commands方法中,將Group.list_commands替換為list_commands ,它將按需要對命令進行排序。

測試代碼:

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())

檢測結果:

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

Options:
  --help  Show this message and exit.

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

Максим Стукало回答對我幫助很大。 但是,它缺少一些打字信息。 鑒於我們總是嚴格打字並且我無法編輯帖子,我想我會創建另一個帖子,也許它可以幫助某人:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM