Skip to content

Easy execution of tasks from within Python itself #170

@bitprophet

Description

@bitprophet

Until now the focus has been mostly on CLI execution, but calling programmatically has always been on the table - couldn't find a good ticket so this must be it :) (#112 is sort of a feature request for this but it's more of a support thread, I'll roll it into here instead.)

Currently there are no great options for calling a task from another task:

  • The "main" way to execute presently is Executor(<Collection obj>).execute('name'), which requires one to have access to the right Collection instance.
    • Especially if that Collection is the one the task is itself a part of, this is basically impossible with the current API.
  • Executing a task that lives in an imported collection is easier, one can simply do that_collection['taskname'](args), however:
    • it's still a little fugly (if not a ton)
    • more importantly, it has annoying edge cases when using contextualized tasks - the context objects are different from each other so you can't just hand yours into the other task (though this feels like it should be allowed!)

Rambling thoughts about how to smooth over the above problems:

  • Having some focus Collection when executing is still a must at some point - Fabric's execute('name') can't work here because it relies on implicit global state.
  • The connection between a task's inner block and the Collection it lives in, must be via the Context handed in (or some other argument, but a single forced argument is plenty...).
    • Feels like more unification of (or smoothing over of access to) Context and Collection might help here.
    • At the very least we need a way to easily call a task with the "right" collection-as-configuration tree - similar to what the CLI mechanisms do now. Which may mean shoving more of that code into Collection or Context.
  • The previous bullet is more fuel for removing non-contextualized tasks (Consider making contextualization the default #114)
    • However, the non-contextualized route just means you can't easily call contextualized tasks from non-contextualized ones (w/o making your own Context - which is doable). You can always just treat everything like a regular module-of-functions and call other nearby task functions straight up.

Brainstorm of use cases/scenarios:

  • Call one top level task from another
  • Call a subtask from a top level task
  • Call a top level task from a subtask (this doesn't actually make any sense, by definition a subtask has no idea that it IS a subtask, at best it can be expected to know about its siblings)
  • Call a subtask from another subtask in the same module (though ideally this is exactly the same as the first bullet)
  • Call a top level task as a library call (eg in the shell)
  • Call a subtask as a library call
  • (Potentially a new ticket) Call one or more top level tasks, handing them the results of the parser - basically, control over the existing hardcoded-ish CLI module.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions