web-dev-qa-db-ja.com

それぞれがサブコマンドのセットを持つClickコマンドを複数のファイルに分割するにはどうすればよいですか?

私が開発した1つの大きなクリックアプリケーションがありますが、さまざまなコマンド/サブコマンドをナビゲートするのは困難です。コマンドを個別のファイルに整理するにはどうすればよいですか?コマンドとそのサブコマンドを別々のクラスに整理することは可能ですか?

これをどのように分離したいかの例を示します。

init

import click

@click.group()
@click.version_option()
def cli():
    pass #Entry Point

command_cloudflare.py

@cli.group()
@click.pass_context
def cloudflare(ctx):
    pass

@cloudflare.group('zone')
def cloudflare_zone():
    pass

@cloudflare_zone.command('add')
@click.option('--jumpstart', '-j', default=True)
@click.option('--organization', '-o', default='')
@click.argument('url')
@click.pass_obj
@__cf_error_handler
def cloudflare_zone_add(ctx, url, jumpstart, organization):
    pass

@cloudflare.group('record')
def cloudflare_record():
    pass

@cloudflare_record.command('add')
@click.option('--ttl', '-t')
@click.argument('domain')
@click.argument('name')
@click.argument('type')
@click.argument('content')
@click.pass_obj
@__cf_error_handler
def cloudflare_record_add(ctx, domain, name, type, content, ttl):
    pass

@cloudflare_record.command('edit')
@click.option('--ttl', '-t')
@click.argument('domain')
@click.argument('name')
@click.argument('type')
@click.argument('content')
@click.pass_obj
@__cf_error_handler
def cloudflare_record_edit(ctx, domain):
    pass

command_uptimerobot.py

@cli.group()
@click.pass_context
def uptimerobot(ctx):
    pass

@uptimerobot.command('add')
@click.option('--alert', '-a', default=True)
@click.argument('name')
@click.argument('url')
@click.pass_obj
def uptimerobot_add(ctx, name, url, alert):
    pass

@uptimerobot.command('delete')
@click.argument('names', nargs=-1, required=True)
@click.pass_obj
def uptimerobot_delete(ctx, names):
    pass
55
Brad T

CommandCollectionを使用することの欠点は、コマンドをマージし、コマンドグループでのみ機能することです。より良い代替案は、add_commandを使用して同じ結果を達成することです。

次のツリーを持つプロジェクトがあります。

cli/
├── __init__.py
├── cli.py
├── group1
│   ├── __init__.py
│   ├── commands.py
└── group2
    ├── __init__.py
    └── commands.py

各サブコマンドには独自のモジュールがあります。これにより、さらに多くのヘルパークラスとファイルを使用して、複雑な実装でも非常に簡単に管理できます。各モジュールでは、commands.pyファイルに@click注釈が含まれています。例group2/commands.py

import click


@click.command()
def version():
    """Display the current version."""
    click.echo(_read_version())

必要に応じて、モジュール内にさらにクラスを簡単に作成し、importを使用してここで使用することができます。これにより、CLIにPythonのクラスとモジュールの全機能を提供できます。

私のcli.pyは、CLI全体のエントリポイントです。

import click

from .group1 import commands as group1
from .group2 import commands as group2

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

entry_point.add_command(group1.command_group)
entry_point.add_command(group2.version)

このセットアップを使用すると、懸念事項によってコマンドを分離し、必要な追加機能を構築することも非常に簡単です。これまでのところ非常に役立っています...

リファレンス: http://click.pocoo.org/6/quickstart/#nesting-commands

63
jdno

プロジェクトに次の構造があるとします。

project/
├── __init__.py
├── init.py
└── commands
    ├── __init__.py
    └── cloudflare.py

グループは複数のコマンドに過ぎず、グループはネストできます。グループをモジュールに分割し、それらをインポートできますinit.pyファイルを作成し、add_commandを使用してcliグループに追加します。

がここにあります init.py例:

import click
from .commands.cloudflare import cloudflare


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


cli.add_command(cloudflare)

Cloudflare.pyファイル内にあるcloudflareグループをインポートする必要があります。きみの commands/cloudflare.pyは次のようになります。

import click


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


@cloudflare.command()
def zone():
    click.echo('This is the zone subcommand of the cloudflare command')

その後、次のようにcloudflareコマンドを実行できます。

$ python init.py cloudflare zone

この情報はドキュメント上ではあまり明確ではありませんが、非常によくコメントされているソースコードを見ると、グループがどのようにネストできるかを確認できます。

21
Diego Castro

私は現時点でこのようなものを探しています、あなたの場合は各ファイルにグループがあるので簡単です、 documentation で説明されているようにこの問題を解決できます:

の中に init.pyファイル:

import click

from command_cloudflare import cloudflare
from command_uptimerobot import uptimerobot

cli = click.CommandCollection(sources=[cloudflare, uptimerobot])

if __== '__main__':
    cli()

このソリューションの最良の部分は、使用しないものをインポートする必要がなく、*をどこからでもインポートする必要がないため、pep8およびその他のリンターに完全に準拠していることです。

私はクリックの専門家ではありませんが、ファイルをメインのファイルにインポートするだけで機能するはずです。すべてのコマンドを別々のファイルに移動し、1つのメインファイルに他のファイルをインポートします。そうすれば、あなたにとって重要な場合に正確な順序を簡単に制御できます。したがって、メインファイルは次のようになります。

import commands_main
import commands_cloudflare
import commands_uptimerobot
0
Achim