Git Product home page Git Product logo

Comments (5)

Zethson avatar Zethson commented on June 7, 2024
#!/usr/bin/env python

import click


@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx):
    if ctx.invoked_subcommand is None:
        click.echo('I was invoked without subcommand')
    else:
        click.echo('I am about to invoke %s' % ctx.invoked_subcommand)


@cli.command()
@click.option('--test',
              prompt='SYNC ME BABY ONE MORE TIME')
@click.pass_context
def sync(ctx, test):
    click.echo(test)
    ctx.invoke(second_level)


@click.command()
def second_level():
    print("wtf")


if __name__ == '__main__':
    cli()

from cookietemple.

Zethson avatar Zethson commented on June 7, 2024
import click


@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx):
    if ctx.invoked_subcommand is None:
        click.echo('I was invoked without subcommand')
    else:
        click.echo('I am about to invoke %s' % ctx.invoked_subcommand)


@cli.command()
@click.option('--second',
              prompt='do it')
@click.pass_context
def second_level(ctx, second):
    click.echo(second)
    ctx.invoke(third_level)


@click.command()
@click.option('--test',
              prompt='test me')
def third_level(test):
    click.echo(test)


if __name__ == '__main__':
    cli()

Unfortunately ctx.invoke invokes the method directly NOT opening the third level prompt.

from cookietemple.

Zethson avatar Zethson commented on June 7, 2024

Instead of delegating using decorators we could also ask for input manually. Certainly not as pretty, but may work:

https://click.palletsprojects.com/en/7.x/prompts/#input-prompts

from cookietemple.

Zethson avatar Zethson commented on June 7, 2024

carc1n0genToday at 9:42 PM
@Zeth my answer remains the same.  Manually call click.prompt.  You will not find a solution using decorator based prompt
ZethToday at 9:43 PM
Are you sure that it is not possible using decorators?
Maybe a solution without 

ctx.invoke?

carc1n0genToday at 9:47 PM
Pretty sure if you don't use ctx.invoke you will get a bunch of errors when calling the function
ZethToday at 9:48 PM
Yup.
:frowning:
carc1n0genToday at 9:55 PM
Best way to think about it is like this:  The click arg parsing, and other decorator magic is done before your function is called.  Once your function has been hit, click is done doing magic for you.
ckdiscordvoiceToday at 9:57 PM
Hey guys, does Flask still use Werkzeug for wsgi - making it difficult to log stdout directly from gunicorn + flask?
ZethToday at 9:58 PM
@carc1n0gen I understand. I was just hoping that with some context passing or whatever I could delegate the calls without ctx.invoke and therefore make this possible.
The thing is, it works if you use prompts everywhere. I have a working example like that. But if you start splitting the prompts into commands and then into a main click group, things start falling apart.
carc1n0genToday at 10:01 PM
Well that's because from a cli design point of view, (IMO) commands calling other commands is a hack.  One command should define everything it is supposed to do.
ZethToday at 10:01 PM
Yup. I get that. I have a very complex application with a complex structure and therefore need this kind of behavior.
If you want I can also show you the code and then you will better understand what I'm trying to achieve and maybe have an idea?
carc1n0genToday at 10:02 PM
and according to the docs, invoke is supposed to pass along kwargs for required parameters to the next command.  like this: https://quickpaste.net/82.py -- But this is probably not what you were hoping for
ZethToday at 10:03 PM
As long as the next functions can again prompt it's fine with me.
carc1n0genToday at 10:04 PM
Sure, but not with a decorator
ZethToday at 10:05 PM
All right. I will discuss this with my collaborator.
carc1n0genToday at 10:05 PM
Is your goal to have one command that calls another, but have the other also callable on its own from the cli?
ZethToday at 10:05 PM
It might be our only option, but since I love decorators and would like to keep things consistent I was hoping for such a solution.
My goal is to have the following: 
Say our program is called 'housing' and it has two commands: flat and house
Then I want to able to call housing like:

housing house


or

housing flat



Say we're calling it with the flat option. Then for code structure reasons another function needs to be called.
The next function is called 'get_general_flat_info'.
This function will prompt the user for things like price, location etc.
Then the 'get_general_flat_info' will call another function, let's call it 'get_tenant_info', which will prompt the user for things like name, age, [...]

Basically, I need this sort of chain behavior.
Currently it works, but only when 'housing' is itself a prompt and asks for the options 'house' and 'flat'. It does not work when 'housing' is a  group and 'house' and 'flat' are commands.

Hope my explanation is clear?
If not, as I said I can offer you to take a look at the project and you will see immediately what I'm trying to do.
carc1n0genToday at 10:15 PM
Can you show me the whole command you whish to invoke your desired behaviour? Like python cli.py <command> --option foo etc
ZethToday at 10:16 PM
The real command or the one for the synthetic example that I wrote  above?
carc1n0genToday at 10:16 PM
Pretend the python script isnt executable, what would you have to type
is housing the script name, or is it itself a command with two sub commands?
ZethToday at 10:18 PM
Ah, I see. All of my python scripts are executable and 
'housing' would also be the entry point for the script (or complex program).
carc1n0genToday at 10:18 PM
okay nvm, was just checking
ZethToday at 10:18 PM
So housing IS currently only a command with a prompt asking for 'flat' or 'housing' BUT SHOULD be a group with the 2 commands.
carc1n0genToday at 10:19 PM
That is possible if you like
you can create groups within groups
ZethToday at 10:19 PM
I tried that already, but may not have done it correctly with my lack of deeper click experience?
Do you have a minimal working example for my suggested behavior from above?
(I appreciate your help and time!)
carc1n0genToday at 10:22 PM
https://quickpaste.net/8e.py
groups inside groups! its turtles all the way down
ZethToday at 10:22 PM
yeah
But can they prompt?
I think I had an issue with that then.
carc1n0genToday at 10:23 PM
Im going to come back to that now
ZethToday at 10:23 PM
All right. Thanks!
carc1n0genToday at 10:24 PM
short answer is no and now I will try to explain from a cli design point of view some feedback to how you described your cli
ZethToday at 10:25 PM
All right
carc1n0genToday at 10:26 PM
@click.command is used to expose a function to the cli.  If you have no intention of exposing a function, lets say the get_general_flat_info than it bu design should not get the @click.command (or @group.command) decorator.  You're sort of over complicating things for yourself. It's just a regular function you want to call so that the command function doesnt grow to far.  That isnt what ctx.invoke is for.  Just make it a normal function and call it like a normal function.  You'll have to use click.prompt wherever you want to prompt.
ZethToday at 10:27 PM
The advantage of the decorators is that I can nicely add help, default values etc and then just prompt for a value.
If I use click.prompt I will lose default values and help and such stuff, no?
Oh and I would not mind if the user were able to call it like

housing flat get_general_flat_info


that would be acceptable to me
carc1n0genToday at 10:30 PM
You can do that.  That would make get_general_flat_info your entry point, and a prompt decorator will work
I can amend my example
ZethToday at 10:31 PM
Would that allow for BOTH options?
I need the user to be able to enter via 

housing flat



OR

 
housing flat get_general_flat_info

carc1n0genToday at 10:32 PM
And you want housing flat to also call get_general_flat_info ?
ZethToday at 10:32 PM
yes
carc1n0genToday at 10:33 PM
in your first one, flat would have to itself collect all the prompts and pass the values to get_general_flat_info when using ctx.invoke.  You would have to duplicate the prompt decorators that exist on get_general_flat_info on to flat
https://quickpaste.net/8c
ZethToday at 10:34 PM
I just saw that click.prompt seem to support default values and types
That's good.
I'll play around with your paste real quick
carc1n0genToday at 10:35 PM
Ya I was in the middle of typing that when I found out you do in fact want get_general_flat_info exposed to the cli
ZethToday at 10:36 PM
I would not mind if it is, yes
Yeah, your paste now is basically what I had earlier above as the starting point of my issue :slight_smile:
invoking the function does not prompt anymore
I really think that I need to say goodbye to the later decorators and work with click.prompt
carc1n0genToday at 10:39 PM
In my last example it prompts ahead of time with the first function call, and passes it to the second
but if the second is called directly, it prompts there
ZethToday at 10:39 PM
Ah, I see.
Yup.
carc1n0genToday at 10:40 PM
thats the closest you can get with only decorators
ZethToday at 10:40 PM
You re right
Another question
Some of my current decorator prompts are click.Choice
Can I use them in click.prompt ?
-> Can I only allow certain values for click.prompt?
(without some ugly while loop hacks)?
carc1n0genToday at 10:41 PM
here;s the full click.prompt signature https://click.palletsprojects.com/en/7.x/api/#click.prompt
looks to have some choice capability by just looking
ZethToday at 10:42 PM
type – the type to use to check the value against.
carc1n0genToday at 10:42 PM

    show_choices – Show or hide choices if the passed type is a Choice. For example if type is a Choice of either day or week, show_choices is true and text is “Group by” then the prompt will be “Group by (day, week): “.


Sounds like you can pass a Choice object to it somehow, but I don't see exactly how it works there
oh ya
ZethToday at 10:42 PM
So I need type=click.Choice[bla] ?
carc1n0genToday at 10:43 PM
I've never done it so its time to experiment
ZethToday at 10:43 PM
all right :slight_smile:
let's go
I will try as well
carc1n0genToday at 10:44 PM
https://quickpaste.net/80.py
ZethToday at 10:45 PM
yup
that works
All right then
carc1n0genToday at 10:45 PM

$ pipenv run python cli.py
Gender:  (male, female, other): other
other

ZethToday at 10:45 PM
I'll kill the decorators
and use click.prompt
carc1n0genToday at 10:45 PM
:knife:
ZethToday at 10:45 PM
Thank you very much for your time and patience
I do not forget such things :slight_smile:
carc1n0genToday at 10:46 PM
np, and goodluck

from cookietemple.

Zethson avatar Zethson commented on June 7, 2024

We will need to get rid of all not top level command decorators and replace them with click.prompt

@Imipenem

from cookietemple.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.