-
Notifications
You must be signed in to change notification settings - Fork 367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
*args and **kwds support in tasks #378
Comments
I feel like there's an open ticket for this already, but I can't find it. Semi-related issues that are not duplicates: #174, #9, #159. Is it possible? Not at the moment, since it makes multi-task CLI parsing quite ambiguous; there's no obvious "one right way" to implement it. I.e.:
You probably want that to act like: mytask(*['a', 'bunch', 'of', 'etc']) But what if your task collection has another task called Hopefully there's a way to square these two concerns; offhand:
|
Since I could usefully use an *args for a project I'm working on, I'd like to add my vote for this feature. If this feature were to come at the cost of being able to have multiple tasks in one invocation, then I personally wouldn't mind. There are many ways in which you can chain tasks, but there is no other way to have an arbitrary amount of arguments for a task. Otherwise, one other option is that, if the parser knows about splat-args, then it will accept multiple instances of the same argument. Ie. you would call this as In my own use case, f.ex. I need to specify multiple recipients. I know in advance which argument I might need to repeat, which I do assume is the most likely use case anyway... |
Thanks for the input, @SwampFalc. (FYI - the |
It would be great to have this feature, I would like to use invoke as a entrypoint to pass arguments to other commands |
Hi, Just chiming in to give my support for this feature. I was just wondering what you think about throwing an exception in the case of ambiguity, but allowing the user to wrap an argument in "quotes" if it has the same name as a task and using that or something similar as a marker that it should always be treated as an argument not a task name. |
Noting that the word 'kwargs' does not appear in here so searching for the term doesn't find this ticket. Kind of important. (This bump courtesy of a soon to be closed duplicate :)) Yes, having this is still something I'd like. Also, I note the discussion so far has been about just args/varargs, and not kwargs/keyword arguments. Not sure how we'd handle actual kwargs...brainstorm:
|
We have a bunch of tasks that rely on Here are a few concrete examples in our task collection: @task
def scale(*args, **kwargs):
"""
Update desired count for services.
Usage:
fab ecs.scale:app-nginx=4,api-nginx=4
""" @task
def set(pattern, **kwargs):
"""
Set ENV vars for a service.
Usage:
fab ecs.config.set:"app-.*",FOO=bar,BAZ=nie
""" @task
def put(service_name, **kwargs):
"""
Set parameters in SSM Parameter Store.
Usage:
fab ssm.params.put:<service>,[key_filter=value],[key_filter2=value],[type=SecureString],...
fab ssm.params.put:prod_app,one=1
fab ssm.params.put:prod_app,one=1,two=2,type=String
""" @task
def rollback(env="prod", **kwargs):
"""
Rollback ecs images / lambda functions to specified or previous versions
and trigger an ops ci build.
Usage:
fab app.rollback:prod,app_image_ref=codeclimate/example:b100
""" |
Got it working! In python 3 at least. Won't be able to test or tinker for a bit, let me know if y'all have any ideas or fixes or issues!
Btw thank you @bitprophet and friends for such clean, easy to read and extend code! I was very pleasantly surprised with how easy it was to at least get kwargs working. Varargs took about 2x the time 😄 |
First step towards pyinvoke#378. See (#TODO 378)s.
Realized I forgot to note -- This patch is about half the size and appears to work flawlessly with no function signature compromises if you only do **kwargs support. *args caused the function signature compromise, because I can't figure out how to place *args where they belong instead of in positional_params[1:], which causes two values to be supplied for required params (because required params are in the kwargs dict that gets unpacked in |
@dblandin Try https://magicinvoke.readthedocs.io/en/latest/examples/args-kwargs/README.html#args-kwargs |
Hey @haydenflinner, I no longer have access to the same fabric/invoke-based command suite so I might not be able to test this without spinning up something new. I'm going to mention a former colleague who might be interested. cc/ @wfleming |
I would be interested in being able to optin for this behavior too, @bitprophet / @haydenflinner what can be done to make this move further? |
@johnraz You could try out my patch by doing |
Rethinking this after a night of sleep I realise that my need is slightly different. What I'd like to achieve is the following:
and in my tasks
Where I know I can achieve this by wrapping everything but the command name within quotes, but getting rid of the quotes is exactly what I'd like to do. I'm not really sure how this could be achieved by the parser nor if it fits in this issue. Also please let me know if you find my use case can be better solved another way 😉 |
You might try only using |
@johnraz I have the same use case as you (and which I think also aligns with OP's desire, though they were hoping to achieve this through *args/**kwargs) of wanting to wrap another script with an invoke task and be able to pass the commands through. I just made a few changes in a fork that allow this (see here; probably <10 lines changed). Basically, each task has a flag @invoke.task(allow_unknown=True)
def test(ctx) -> None:
pytest_args = sys.argv[sys.argv.index("test") + 1:]
cmd = "poetry run pytest " + " ".join(pytest_args)
ctx.run(cmd) Before my changes, trying to add coverage to pytest would give the following: $ invoke test --cov=.
No idea what '--cov' is! After, it works =) You could still call, e.g. |
I have been playing with magicinvoke that has
In the above examples, I have to re-combine I would recommend the following strategy:
P.S. The reason I think |
Re: P.S. I'm not sure that that's accurate, I use the *args / **kwargs on a work project in the same way that they're often used on regular Python functions: Wrapping another inv task without knowing/copying its signature, just by passing in *args, **kwargs. But I think you're perfectly right with 2), I'm surprised I didn't try that case when implementing this feature. If you want to give implementing it a stab, I'd merge it pretty quickly after verifying that it worked. I think it should be relatively easy:
This is the if statement in parser.py which catches flags on a function which takes args or kwargs. Below on line 287 is the line which we fall through to if we fail to accept an argv value as a flag. If you changed eat_all from a boolean to a [None, 'args', 'args_and_kwargs'] enum (representing cases 1-3 of your comment) you should be able to get the behavior that you want by just wiring up that value to the appropriate property of the wrapped task. Though I understand if you'd rather not 😃 Good luck and thanks for giving the library a shot! |
@haydenflinner thanks for the post. Is there a way to create a small PR with these changes to merge into the main project? This issue is marked with a |
That label was added in 2016, maybe things were still being merged back then, but not now. You could likely cherry-pick / flatten the two or three commits that have been done on this topic from magicinvoke and submit a PR, but if you need it in the next ~6 months (or maybe ever), make sure to submit it to magicinvoke too 😛 Even things like this or this aren't being merged. |
I was running into the issue described here and took a look at the MR here: #582 and managed to get that working with the 1.6.0 release mostly as is. I had to make a small change which I noted on the ticket. Is there any way we could get some movement on this? |
One last thing to note here in case anyone would like it. I started with @neighthan The function signature for the above snippet:
and the output would be: And running with multiple tasks:
(Note these commands are a bit shorthand)
|
Any proposal has been merged? |
I ended up switching to just |
Is it possible to have support for args and/or kwds in tasks? I need it sometimes to pass all argument commands, as is, to another script.
The text was updated successfully, but these errors were encountered: