nat-n / poethepoet

A task runner that works well with poetry.
https://poethepoet.natn.io/
MIT License
1.46k stars 59 forks source link

Named arguments for tasks #6

Closed pawamoy closed 2 years ago

pawamoy commented 4 years ago

I see in the TODO section of the README:

support declaring specific arguments for a task

Could you elaborate on what it means 🙂 ?

I'm currently trying to migrate a Makefile to poe tasks, and I'd need to pass named arguments to a task:

.PHONY: do-this
do-this:
ifndef a
    $(error Pass A with 'make do-this a=X.Y.Z')
endif
ifndef b
    $(error Pass B with 'make do-this b=X.Y.Z')
endif
ifndef c
    $(error Pass C with 'make do-this c=X.Y.Z')
endif
    @echo "actual commands..."
    @echo $(a) $(b) $(c)

I guess it gets a bit hard to replicate such features in a declarative way.

Maybe something like this?

[tool.poe.tasks.do-this]
args = [
    { name = "a", help = "Pass A with 'a=X.Y.Z'", required = true },
    { name = "b", help = "Pass B with 'b=X.Y.Z'", required = true },
    { name = "c", help = "Pass C with 'c=X.Y.Z'", required = true },
]
shell = """
    echo "actual commands...";
    echo $a $b $c
"""

...letting us do poe do-this a=hey b=ho c=heyho.

A more verbose equivalent:

[tool.poe.tasks.do-this]
  shell = """
    echo "actual commands...";
    echo $a $b $c
  """

  [[tool.poe.tasks.do-this.args]]
    name = "a"
    help = "Pass A with 'a=X.Y.Z'"
    required = true
  [[tool.poe.tasks.do-this.args]]
    name = "b"
    help = "Pass B with 'b=X.Y.Z'"
    required = true
  [[tool.poe.tasks.do-this.args]]
    name = "c"
    help = "Pass C with 'c=X.Y.Z'"
    required = true
nat-n commented 4 years ago

That's not far off what I had in mind. Thanks for bringing it up.

I'd like to support both named and positional arguments, in a way that translates well to different task types. For shell/cmd tasks what you describe using env variables might be a good way to do it. For script tasks passing as arg/kwargs should work too.

I hadn't thought of providing required/help keys per arg but it makes sense. For more light weight use cases it would be nice to be able to simply provide something like:

args = ["arg1", "arg2"]

or

args = {arg1 = "foo", arg2 = "bar"} # provide defaults

It should be possible to support more than one of these schemes.

As for implementation I was thinking of dynamically translating the arguments into an argparse parser for parsing and validation. Of course it would be cool to support tab completion for task arguments as well :)

nat-n commented 3 years ago

I've published an initial implementation of this feature as a beta-release https://pypi.org/project/poethepoet/0.11.0b1/

It's not thoroughly tested or documented yet (see README on the feature branch ) and there are a few bits missing functionality wise but it'd be great if someone could try it out and provide feedback!

Still to do:

nat-n commented 2 years ago

Named arguments released in v0.11.0.