nat-n / poethepoet

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

KeyError thrown when switch tasks are invoked in dry-run mode #115

Closed fdaguin closed 1 year ago

fdaguin commented 1 year ago

Expected Behavior

When invoking a task of type switch in --dry-run mode, no error is thrown.

Actual Behavior

A KeyError: ('task_name[control]',) is thrown.

Steps to Reproduce the Problem

  1. Define the following tasks:

    [tool.poe.tasks.check_number]
    control.script = "sys:stdout.write(str(int(environ['BEST_NUMBER']) % 2))"
    
    [[tool.poe.tasks.check_number.switch]]
    case = "0"
    shell = "import sys, os; print(os.environ['BEST_NUMBER'], 'is even')"
    interpreter = "python"
    
    [[tool.poe.tasks.check_number.switch]]
    case = "1"
    shell = "import sys, os; print(os.environ['BEST_NUMBER'], 'is odd')"
    interpreter = "python"
  2. Run BEST_NUMBER=12 poe check_number and expect no error:
    Poe <= check_number[control]
    Poe => import sys, os; print(os.environ['BEST_NUMBER'], 'is even')
    12 is even
  3. Run BEST_NUMBER=12 poe --dry-run check_number and expect an error:
    Poe <= check_number[control]
    Traceback (most recent call last):
      File "/home/fdaguin/workspace/personal/poethepoet-test/.venv/bin/poe", line 8, in <module>
        sys.exit(main())
      File "/home/fdaguin/workspace/personal/poethepoet-test/.venv/lib/python3.9/site-packages/poethepoet/__init__.py", line 33, in main
        result = app(cli_args=sys.argv[1:])
      File "/home/fdaguin/workspace/personal/poethepoet-test/.venv/lib/python3.9/site-packages/poethepoet/app.py", line 67, in __call__
        return self.run_task() or 0
      File "/home/fdaguin/workspace/personal/poethepoet-test/.venv/lib/python3.9/site-packages/poethepoet/app.py", line 98, in run_task
        return self.task.run(context=context, extra_args=self.ui["task"][1:])
      File "/home/fdaguin/workspace/personal/poethepoet-test/.venv/lib/python3.9/site-packages/poethepoet/task/base.py", line 232, in run
        return self._handle_run(
      File "/home/fdaguin/workspace/personal/poethepoet-test/.venv/lib/python3.9/site-packages/poethepoet/task/switch.py", line 115, in _handle_run
        control_task_output = context.get_task_output(self.control_task.invocation)
      File "/home/fdaguin/workspace/personal/poethepoet-test/.venv/lib/python3.9/site-packages/poethepoet/context.py", line 97, in get_task_output
        return re.sub(r"\s+", " ", self.captured_stdout[invocation].strip("\r\n"))
    KeyError: ('check_number[control]',)

Specifications

nat-n commented 1 year ago

Hi @fdaguin, thanks for the feedback! Nice to see someone using the new feature already.

This is an interesting problem actually... what exactly should happen when running a switch task as a dry run? Normally dry run means no tasks are actually executed, but if the control task is not executed then we can't know which case would be executed...

My feeling is that the in this case we should make an exception and execute the control task, with the assumption that it isn't meant to have any side effects.

Alternatively it could result in something like:

Poe <= check_number[control]
Poe => <unresolved case>

What do you think?

fdaguin commented 1 year ago

Thanks a lot for this neat feature! ✌️ I will use it to launch different commands between a dev workstation and a CI system!

As for your suggestions, both points are completely valid and I'm also in favor for the control task being executed. What about a boolean option like control.check_mode to switch between the two, like Ansible check mode?

nat-n commented 1 year ago

This issue is fixed in v0.18.1. I went with not running the control task in the end because I figured running any tasks in dry-mode could be surprising, and for consistency with handling the similar issue with tasks that define the "uses" option to depend on the output of other tasks.

fdaguin commented 1 year ago

Thanks @nat-n!