Skip to content
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

Sequences can't handle arguments :( #37

Closed
rjurney opened this issue Sep 28, 2021 · 8 comments
Closed

Sequences can't handle arguments :( #37

rjurney opened this issue Sep 28, 2021 · 8 comments

Comments

@rjurney
Copy link

rjurney commented Sep 28, 2021

I've read the code and I can't find any way to make a sequence accept an argument. The code actually says to throw an exception if any extra arguments are given :(

I need to run the task setup-artifacts before I run the task poetry add. Since poetry add takes an argument I need to feed it to the last command in the list. This seems unsupported. I read the code and I get lost but this tells me SequenceTasks don't accept arguments:

def _handle_run(
self,
context: "RunContext",
extra_args: Iterable[str],
env: MutableMapping[str, str],
) -> int:
if any(arg.strip() for arg in extra_args):
raise PoeException(f"Sequence task {self.name!r} does not accept arguments")
if len(self.subtasks) > 1:
# Indicate on the global context that there are multiple stages
context.multistage = True
for subtask in self.subtasks:
task_result = subtask.run(context=context, extra_args=tuple(), env=env)
if task_result and not self.options.get("ignore_fail"):
raise ExecutionError(
f"Sequence aborted after failed subtask {subtask.name!r}"
)
return 0

My pyproject.toml reads:

[tool.poe.tasks]
setup-artifacts = "scripts/setup_artifacts.sh setup-poetry"
add = [{ref="setup-artifacts"}, { cmd = "poetry add" }]

I run poe add moto and I get:

poe add moto
Poe the Poet - A task runner that works well with poetry.
version 0.10.0

Error: Sequence task 'add' does not accept arguments

USAGE
  poe [-h] [-v | -q] [--root PATH] [--ansi | --no-ansi] task [task arguments]

GLOBAL OPTIONS
  -h, --help     Show this help page and exit
  --version      Print the version and exit
  -v, --verbose  More console spam
  -q, --quiet    Less console spam
  -d, --dry-run  Print the task contents but don't actaully run it
  --root PATH    Specify where to find the pyproject.toml
  --ansi         Force enable ANSI output
  --no-ansi      Force disable ANSI output

CONFIGURED TASKS
  setup-artifacts
  add

This makes me a sad panda :( What would I need to do to make poe take arguments to sequences? Maybe put an argument for them like args_to=2 to reference the command in the sequence?

@nat-n
Copy link
Owner

nat-n commented Sep 28, 2021

Hi @rjurney, thanks for the feedback!

Yes, I skipped on supporting arguments for sequences the first time round for lack of clarity on how it could work without inelegance. I have a couple of ideas though.

One way to achieve this would be to instead use the task graph feature discussed in #26, for which there is already an experimental implementation in pre-release. I say experimental because it's not really documented or well tested yet.

So with the pre-release version of poethepoet I think you could do something like the following:

[tool.poe.tasks]
setup-artifacts = "scripts/setup_artifacts.sh setup-poetry"
add = { cmd = "poetry add", "deps" = ["setup-artifacts"] }

This example defines a minimalist task graph, with add being the sink node, that requires setup-artifacts to be run first. Let me know if this already works for you?

The other way is something I thought of recently but haven't yet tried would to build upon the named arguments feature (also in pre-release) and make ref tasks support passing arguments (in the same way as "deps" or "uses" references do for task graphs), so it would look something like:

[tool.poe.tasks]
setup-artifacts = "scripts/setup_artifacts.sh setup-poetry"
_poetry_add = "poetry add"

  [tool.poe.tasks.add]
  sequence = ["setup-artifacts", "_poetry_add $target"]
  args = ["target"]

Which would then be invoked as poe add --target moto. Probably the task graph solution is better.

@Haffi921
Copy link

Haffi921 commented Oct 6, 2021

I have a similar issue. For simplicity, let's say I'd like to chain-run isort and black both on a specific file or folder under a rule format.

What I can do already is a general task for the whole project, like this:

[tool.poe.tasks]
isort = "isort ."
black = "black ."
format = ["isort", "black"]

OR statically specify files or folders

[tool.poe.tasks]
format_this_specific_file_why_would_I_ever_do_this = [
    {cmd = "isort ./src/util/error.py"},
    {cmd = "black ./src/util/error.py"}
]

But I cannot dynamically give a file or folder for both task to run on, like this: poe format specific/file.py. I imagine in your proposal this would be the solution?

[tool.poe.tasks]
....

    [tool.poe.tasks.format]
    sequence = ["isort $target", "black $target"]
    args = ["target"]

Is there already a method I can use to get these desired results that I am missing?


I can also imagine another solution for simple cases. Something like this:

[tool.poe.tasks]
format = ["isort $1", "black $1"]

Where $N where N is a number from [1, 2, 3,... ] of order of arguments given. I don't know the specifics if this would clash with any other poe features. But if not, maybe these two solutions could be implemented. One for dead-simple cases and the other one for when you need a bit more control/explicitness.

@nat-n
Copy link
Owner

nat-n commented Oct 6, 2021

Hello @Haffi921, I previously looked into supporting positional arguments (see #17), but haven't found a satisfactory way to do it that generalises well across use cases. The key difficulty is that shells don't let you arbitrarily set envvars like $1. I'm open to suggestions on that.

The example you gave with args should work on the latest pre-release, though I understand how it could be less convenient.

@Haffi921
Copy link

Haffi921 commented Oct 8, 2021

Hey @nat-n, thanks for the reply. That's a shame, it would be a really nice feature. However, I also feel as the args solution is still powerful, if a bit verbose. I'd love to lend a hand at some point.

Still I tried it and it doesn't seem to work. It literally says "Sequence task 'format' does not accept arguments 😁

Here is my pyproject.toml:

[tool.poe.tasks]
test = "pytest ."
retest = "pytest . --lf"

[tool.poe.tasks.format]
sequence = ["isort $target", "black $target"]
args = ["target"]

Here's the output:

PS C:\...> poe format --target .
Poe the Poet - A task runner that works well with poetry.
version 0.11.0b5

Error: Sequence task 'format' does not accept arguments

USAGE
  poe [-h] [-v | -q] [--root PATH] [--ansi | --no-ansi] task [task arguments]

GLOBAL OPTIONS
  -h, --help     Show this help page and exit
  --version      Print the version and exit
  -v, --verbose  Increase command output (repeatable)
  -q, --quiet    Decrease command output (repeatable)
  -d, --dry-run  Print the task contents but don't actaully run it
  --root PATH    Specify where to find the pyproject.toml
  --ansi         Force enable ANSI output
  --no-ansi      Force disable ANSI output

CONFIGURED TASKS
  test
  retest
  format
    --target

Again tho, not a big issue. It's not like I need isort and black on specific files. It was just something I thought might be fun to try and see if works.

More so that I just wanted you to know it didn't work. And I definitely think it would be a nice feature!

@nat-n
Copy link
Owner

nat-n commented Oct 11, 2021

Still I tried it and it doesn't seem to work. It literally says "Sequence task 'format' does not accept arguments 😁

My bad! it's not there yet... 😣

I'm in the middle of refactoring some related code at the moment, I'll see if I can get to work while I'm at it.

@Haffi921
Copy link

Ahh makes sense, yeah no worries

@nat-n
Copy link
Owner

nat-n commented Nov 14, 2021

@rjurney As of v0.11.0 (just released) you can now do something like:

[tool.poe.tasks]
setup-artifacts = "scripts/setup_artifacts.sh setup-poetry"

[tool.poe.tasks.add]
sequence = [{ref="setup-artifacts"}, { cmd = "poetry add $package" }]
args = [{ name = "package", positional = true }]

which could be invoked like:

poe add moto

I hope this works for you :)

@Haffi921 Your example should work now too

@nat-n nat-n closed this as completed Nov 14, 2021
@Haffi921
Copy link

@nat-n Great! Well done, this is a cool feature!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants