web-dev-qa-db-fra.com

Comment diviser mes commandes Click, chacune avec un ensemble de sous-commandes, en plusieurs fichiers?

J'ai développé une application grand clic, mais la navigation dans les différentes commandes/sous-commandes devient difficile. Comment organiser mes commandes dans des fichiers séparés? Est-il possible d'organiser les commandes et leurs sous-commandes dans des classes séparées?

Voici un exemple de la façon dont je voudrais le séparer:

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

L’inconvénient d’utiliser CommandCollection pour cela est qu’il fusionne vos commandes et fonctionne uniquement avec des groupes de commandes. La meilleure solution consiste à utiliser add_command pour obtenir le même résultat.

J'ai un projet avec l'arbre suivant:

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

Chaque sous-commande a son propre module, ce qui facilite incroyablement la gestion d'implémentations même complexes avec beaucoup plus de classes et de fichiers d'assistance. Dans chaque module, le fichier commands.py contient les annotations @click. Exemple group2/commands.py:

import click


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

Si nécessaire, vous pouvez facilement créer plus de classes dans le module et import et les utiliser ici, donnant ainsi à votre CLI toute la puissance des classes et des modules de Python.

Mon cli.py est le point d’entrée pour l’ensemble de la 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)

Avec cette configuration, il est très facile de séparer vos commandes par préoccupations et de créer autour de celles-ci des fonctionnalités supplémentaires dont elles pourraient avoir besoin. Cela m'a très bien servi jusqu'à présent ...

Référence: http://click.pocoo.org/6/quickstart/#nesting-commands

48
jdno

Supposons que votre projet ait la structure suivante:

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

Les groupes ne sont rien d'autre que plusieurs commandes et les groupes peuvent être imbriqués. Vous pouvez séparer vos groupes en modules et les importer dans votre fichier init.py et les ajouter au groupe cli à l'aide de la commande add_command.

Voici un exemple de init.py:

import click
from .commands.cloudflare import cloudflare


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


cli.add_command(cloudflare)

Vous devez importer le groupe cloudflare qui réside dans le fichier cloudflare.py. Votre commands/cloudflare.py ressemblerait à ceci:

import click


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


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

Ensuite, vous pouvez exécuter la commande cloudflare comme ceci:

$ python init.py cloudflare zone

Cette information n’est pas très explicite sur la documentation, mais si vous regardez le code source, qui est très bien commenté, vous pouvez voir comment les groupes peuvent être imbriqués.

13
Diego Castro

Je cherche quelque chose comme ceci pour le moment, dans votre cas, c'est simple parce que vous avez des groupes dans chacun des fichiers, vous pouvez résoudre ce problème comme expliqué dans la documentation :

Dans le fichier init.py:

import click

from command_cloudflare import cloudflare
from command_uptimerobot import uptimerobot

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

if __== '__main__':
    cli()

La meilleure partie de cette solution est qu’elle est totalement conforme à pep8 et aux autres linters car vous n’avez pas besoin d’importer quelque chose que vous n’utiliseriez pas et que vous n’avez pas besoin d’importer * de n’importe où.

J'espère que cela aide et bon look avec votre Cli.

7

Je ne suis pas un expert des clics, mais cela devrait fonctionner en important simplement vos fichiers dans le fichier principal. Je déplacerais toutes les commandes dans des fichiers séparés et un fichier principal importerait les autres. De cette façon, il est plus facile de contrôler l'ordre exact, au cas où cela serait important pour vous. Donc, votre fichier principal ressemblerait à ceci:

import commands_main
import commands_cloudflare
import commands_uptimerobot
0
Achim