wake-up-neo.net

Wie kann ich meine Click-Befehle mit jeweils mehreren Unterbefehlen in mehrere Dateien aufteilen?

Ich habe eine große Klickanwendung, die ich entwickelt habe, aber das Navigieren durch die verschiedenen Befehle/Unterbefehle wird immer schwieriger. Wie organisiere ich meine Befehle in separaten Dateien? Ist es möglich, Befehle und ihre Unterbefehle in separaten Klassen zu organisieren?

Hier ist ein Beispiel, wie ich es trennen möchte:

drin

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
39
Brad T

Der Nachteil der Verwendung von CommandCollection besteht darin, dass Ihre Befehle zusammengeführt werden und nur mit Befehlsgruppen funktioniert. Die bessere Alternative ist, add_command zu verwenden, um das gleiche Ergebnis zu erzielen.

Ich habe ein Projekt mit dem folgenden Baum:

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

Jeder Unterbefehl verfügt über ein eigenes Modul, wodurch die Verwaltung komplexer Implementierungen mit noch mehr Hilfsklassen und -dateien denkbar einfach ist. In jedem Modul enthält die commands.py-Datei die @click-Anmerkungen. Beispiel group2/commands.py:

import click


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

Bei Bedarf können Sie problemlos weitere Klassen im Modul und import erstellen und hier verwenden, um Ihrer CLI die volle Leistungsfähigkeit der Klassen und Module von Python zu geben.

Mein cli.py ist der Einstiegspunkt für die gesamte 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)

Mit diesem Setup ist es sehr einfach, Ihre Befehle nach Bedenken zu trennen und zusätzliche Funktionen um sie herum aufzubauen, die sie möglicherweise benötigen. Es hat mir bisher sehr gut gedient ...

Referenz: http://click.pocoo.org/6/quickstart/#nesting-commands

48
jdno

Angenommen, Ihr Projekt hat die folgende Struktur:

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

Gruppen sind nichts anderes als mehrere Befehle und Gruppen, die verschachtelt werden können. Sie können Ihre Gruppen in Module aufteilen und in Ihre init.py-Datei importieren und sie mit dem add_command der cli-Gruppe hinzufügen.

Hier ist ein init.py Beispiel:

import click
from .commands.cloudflare import cloudflare


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


cli.add_command(cloudflare)

Sie müssen die Cloudflare-Gruppe importieren, die sich in der Datei cloudflare.py befindet. Ihr commands/cloudflare.py würde so aussehen:

import click


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


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

Dann können Sie den Befehl cloudflare wie folgt ausführen:

$ python init.py cloudflare zone

Diese Informationen sind in der Dokumentation nicht sehr explizit. Wenn Sie jedoch den Quellcode betrachten, der sehr gut kommentiert ist, können Sie sehen, wie Gruppen verschachtelt werden können.

13
Diego Castro

Ich suche im Moment nach so etwas wie diesem, in Ihrem Fall ist das einfach, weil Sie in jeder Datei Gruppen haben. Sie können dieses Problem lösen, wie in der Dokumentation beschrieben :

In der init.py-Datei:

import click

from command_cloudflare import cloudflare
from command_uptimerobot import uptimerobot

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

if __== '__main__':
    cli()

Das Beste an dieser Lösung ist, dass sie vollständig mit pep8 und anderen Linters kompatibel ist, da Sie nicht brauchen, etwas zu importieren, das Sie nicht verwenden würden, und Sie müssen * nicht von überall importieren.

Ich hoffe das hilft und sieht gut aus mit deinem cli.

Ich bin kein Click-Experte, aber es sollte funktionieren, indem Sie einfach Ihre Dateien in die Hauptdatei importieren. Ich würde alle Befehle in separaten Dateien verschieben und eine Hauptdatei haben, die die anderen importiert. Auf diese Weise ist es einfacher, die genaue Reihenfolge zu kontrollieren, falls dies für Sie wichtig ist. Ihre Hauptdatei würde also so aussehen:

import commands_main
import commands_cloudflare
import commands_uptimerobot
0
Achim