2
votes

Comment spécifier une valeur par défaut pour la liste d'arguments traitée par clic?

J'ai cette ligne de code qui devrait récupérer tous les noms de fichiers passés à mon script Python:

@click.argument("logs", nargs=-1, type=click.File('r'), required=1, default="-")

Lorsqu'aucun nom de fichier n'est passé, je veux par défaut - , c'est-à-dire l'entrée standard. Donc, si j'essaye:

@click.argument("logs", nargs=-1, type=click.File('r'), required=1)

le clic devient malheureux et génère cette erreur:

TypeError: nargs = -1 en combinaison avec une valeur par défaut n'est pas pris en charge.

Y a-t-il une solution de contournement pour cela? J'ai essayé de définir nargs = 0 mais cela génère une erreur différente:

IndexError: index de tuple hors de portée


1 commentaires

Pour ce que ça vaut, problème sur github (c'est-à-dire qu'ils ne l'ont pas résolu, ils l'ont interdit explicitement).


3 Réponses :


0
votes

Le code suivant:

$ myhello -l foo.log -l bar.log -l baz.log
foo.log
bar.log
baz.log
$ myhello
-

Produira ce qui suit:

import click


@click.command()
@click.option('--logs', '-l', multiple=True, default='-')
def cli(logs):
    click.echo('\n'.join(logs))

Donc, si vous pouviez simplement appeler votre programme différemment avec des paramètres répétés à la place, ce serait la solution de contournement que vous recherchez.


2 commentaires

Cela change la sémantique de ce que l'OP voulait, donc oui, ce serait juste une solution de contournement qui ne résout pas le problème réel.


dans ce cas, je voudrais simplement ajouter un simple wrapper autour de ce qui précède dans bash.



1
votes

Puisque click avait explicitement déclaré avoir désactivé cette fonctionnalité particulière requise par la question, comme indiqué sur ce problème sur leur projet, une solution de contournement sera nécessaire et qui peut être facilement implémentée dans le cadre de la fonction Python (au lieu d'une pile supplémentaire sur le code bash comme suggéré par le commentaire sur le

La solution de contournement consiste simplement à supprimer l'argument requis et à gérer les journaux manquants à l'aide d'une instruction (similaire à ce que ce commit a fait qui faisait référence au problème lié):

$ python fail.py 
(<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>,)
$ python fail.py -
(<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>,)
$ python fail.py foo bar
(<_io.TextIOWrapper name='foo' mode='r' encoding='UTF-8'>, <_io.TextIOWrapper name='bar' mode='r' encoding='UTF-8'>)

Exemple d'exécution

import sys
import click

@click.command()
@click.argument("logs", nargs=-1, type=click.File('r'))
def main(logs):
    if not logs:
        logs = (sys.stdin,)
    print(logs)
    # do stuff with logs

if __name__ == '__main__': 
    main()

p>


0 commentaires

3
votes

Pour définir par défaut stdin pour une liste de fichiers potentiellement vide, vous pouvez définir une classe d'arguments personnalisée telle que:

Classe personnalisée:

@click.command()
@click.argument("logs", cls=FilesDefaultToStdin)
def main(logs):
    ...

Définir ce comportement en tant que classe permet une réutilisation facile.

Pour utiliser la classe personnalisée:

class FilesDefaultToStdin(click.Argument):
    def __init__(self, *args, **kwargs):
        kwargs['nargs'] = -1
        kwargs['type'] = click.File('r')
        super().__init__(*args, **kwargs)

    def full_process_value(self, ctx, value):
        return super().process_value(ctx, value or ('-', ))

Comment cela fonctionne?

Cela fonctionne car Click est un framework OO bien conçu. Le décorateur @ click.argument () instancie généralement un objet click.Argument mais permet à ce comportement d'être remplacé par le paramètre cls . Il est donc relativement facile d'hériter de click.Argument dans notre propre classe et de remplacer les méthodes souhaitées.

Dans ce cas, nous remplaçons click. Argument.full_process_value () . Dans notre full_process_value () , nous recherchons une liste d'arguments vide, et si elle est vide, nous ajoutons l'argument - (stdin) à la liste.

De plus, nous attribuons automatiquement les arguments nargs = -1 et type = click.File ('r') .


0 commentaires