I want to use some useful functions as commands. For that I am testing the click
library. I defined my three original functions then decorated as click.command
:
import click
import os, sys
@click.command()
@click.argument('content', required=False)
@click.option('--to_stdout', default=True)
def add_name(content, to_stdout=False):
if not content:
content = ''.join(sys.stdin.readlines())
result = content + "\n\tadded name"
if to_stdout is True:
sys.stdout.writelines(result)
return result
@click.command()
@click.argument('content', required=False)
@click.option('--to_stdout', default=True)
def add_surname(content, to_stdout=False):
if not content:
content = ''.join(sys.stdin.readlines())
result = content + "\n\tadded surname"
if to_stdout is True:
sys.stdout.writelines(result)
return result
@click.command()
@click.argument('content', required=False)
@click.option('--to_stdout', default=False)
def add_name_and_surname(content, to_stdout=False):
result = add_surname(add_name(content))
if to_stdout is True:
sys.stdout.writelines(result)
return result
This way I am able to generate the three commands add_name
, add_surname
and add_name_and_surname
using a setup.py
file and pip install --editable .
Then I am able to pipe:
$ echo "original content" | add_name | add_surname
original content
added name
added surname
However there is one slight problem I need to solve, when composing with different click commands as functions:
$echo "original content" | add_name_and_surname
Usage: add_name_and_surname [OPTIONS] [CONTENT]
Error: Got unexpected extra arguments (r i g i n a l c o n t e n t
)
I have no clue why it does not work, I need this add_name_and_surname
command to call add_name
and add_surname
not as command but as functions, else it defeats my original purpose of using functions as both library functions and commands.
Due to the click decorators the functions can no longer be called just by specifying the arguments. The Context class is your friend here, specifically:
So your code for add_name_and_surname should look like:
@click.command()
@click.argument('content', required=False)
@click.option('--to_stdout', default=False)
@click.pass_context
def add_name_and_surname(ctx, content, to_stdout=False):
result = ctx.invoke(add_surname, content=ctx.forward(add_name))
if to_stdout is True:
sys.stdout.writelines(result)
return result
Reference: http://click.pocoo.org/6/advanced/#invoking-other-commands