Skip to main content

taskcapsule

A simple framework for running commands or Python functions concrrently using templated commands/functions and dictionaries of arguments.

Warning

This has sharp edges which can only be smoothed as errors are discovered. Expect better guardrails to occur over time as issues are discovered.

CLI/Subprocess Warning

Shells and environments behave in all sorts of ways. When in doubt, use absolute paths for the items that you're calling

Features

  • Support for CLI subshells and Python callables
  • Output filtering, which is the functional equivilent of grep
  • Minimum worker spawning. If you have fewer tasks than defined workers, the worker pool will be reduced to the number of tasks
  • Task validation to ensure that either function or command is set

Future Work

  • Validate function calls and arguments via inspect
  • Tests
  • Result gathering
  • Pipelines

Examples

Subshell and Callable Example

# from examples/cli_or_callable.py
from taskcapsule import Task, TaskRunner


def hello(message: str):
    return f"Hello, {message}!"


my_tasks = []
my_tasks.append(
    Task(
        command="echo {message}",
        kwargs={"message": "Hello, CLI runner!"},
        output_filter="Hello",
    )
)
my_tasks.append(
    Task(
        function=hello,
        kwargs={"message": "callable runner!"},
        output_filter="Hello",
    )
)

runner = TaskRunner(
    tasks=my_tasks,
    workers=4,
)
runner.run()
$ python cli_or_callable.py |jq
INFO:task-runner:spawning 2 workers
{
  "function": "hello",
  "kwargs": {
    "message": "Hello, callable runner!"
  },
  "return_code": 0,
  "output": "Hello, callable runner!!",
  "error": "",
  "duration": 9.5367431640625E-7,
  "success_filter": "Hello"
}
{
  "command": "echo Hello, CLI runner!",
  "kwargs": {
    "message": "Hello, CLI runner!"
  },
  "return_code": 0,
  "output": "Hello, CLI runner!\n",
  "error": "",
  "duration": 0.016596078872680664,
  "success_filter": "Hello"
}
INFO:task-runner:all tasks completed

Nmap Example

from taskcapsule import TaskRunner, Task
# Look to see if the host is running WebLogic T3
template = "nmap -oG - -p {port} --script weblogic-t3-info {addr}"
items = [{"addr":"1.2.3.4","port": "7002"}]
my_tasks = []
for i in items:
    kwargs = items
    my_tasks.append(
        Task(
            command=template,
            kwargs=kwargs,
            target_metadata={"uuid": "fedcba09-1234-1111-bcde-1234567890fe"},
            # This is in the output if, and only if, T3 is running
            output_filter="T3",
        )
    )

tr = TaskRunner(tasks=my_tasks)
tr.run()

Output

python example.py|jq

INFO:taskcapsule:spawning 1 workers
{
  "command": "nmap -oG - -p 7002 --script weblogic-t3-info 1.2.3.4",
  "kwargs": {
    "addr": "1.2.3.4",
    "port": "7002"
  },
  "return_code": 0,
  "stdout": "# Nmap 7.95 scan initiated Thu Apr 17 09:23:50 2025 as: nmap -oG - -p 7002 --script weblogic-t3-info 1.2.3.4\nHost: 1.2.3.4 ()\tStatus: Up\nHost: 45.60.186.97 ()\tPorts: 7002/open/tcp//afs3-prserver//WebLogic application server 12.2.1.4 (T3 enabled)/\n# Nmap done at Thu Apr 17 09:23:51 2025 -- 1 IP address (1 host up) scanned in 0.70 seconds\n",
  "stderr": "",
  "duration": 0.7490861415863037,
  "success_filter": "T3",
  "target_metadata": {
    "uuid": "fedcba09-1234-1111-bcde-1234567890fe"
  }
}
INFO:task-runner:all tasks completed

Error Handling

Code

from taskcapsule import Task, TaskRunner


def hello(message: str):
    return f"Hello, {message}!"


my_tasks = []
my_tasks.append(
    Task(
        command="nosuchcommand {message}",
        kwargs={"message": "Hello, CLI runner!"},
    )
)
my_tasks.append(
    Task(
        function=hello,
        kwargs={"wrong_arg": "callable runner!"},
    )
)
runner = TaskRunner(
    tasks=my_tasks,
    workers=4,
    show_failures=True,
)
runner.run()

Output

$ python show_errors.py|jq
INFO:task-runner:spawning 2 workers
ERROR:task-runner:processing command=None function=<function hello at 0x104ec4220> kwargs={'wrong_arg': 'callable runner!'} output_filter=None target_metadata=None: hello() got an unexpected keyword argument 'wrong_arg'
INFO:task-runner:success filter is None, skipping check
{
  "function": "hello",
  "kwargs": {
    "wrong_arg": "callable runner!"
  },
  "return_code": -1,
  "output": "",
  "error": "hello() got an unexpected keyword argument 'wrong_arg'",
  "duration": 0.00011897087097167969
}
INFO:task-runner:success filter is None, skipping check
{
  "command": "nosuchcommand Hello, CLI runner!",
  "kwargs": {
    "message": "Hello, CLI runner!"
  },
  "return_code": 127,
  "output": "",
  "error": "/bin/sh: nosuchcommand: command not found\n",
  "duration": 0.021525859832763672
}

Release files for taskcapsule 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for taskcapsule 0.2.1
File Size Uploaded
taskcapsule-0.2.1.tar.gz 7.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for taskcapsule 0.2.1
File Interpreter ABI Platform
taskcapsule-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 14.6 kB

Release files / taskcapsule-0.2.1.tar.gz

Download URL taskcapsule-0.2.1.tar.gz
Size 7.2 kB
Tags Source
SHA-256 checksum
How to use checksums
40bebfbd0ab8493ba8d62d97d0d278d00711c637af5750caac7e3c446743e443
BLAKE2b-256 checksum
How to use checksums
9eaec1921031e6653498a9dfeb57cdb2aa130bc85cb0de4f6c9e6b911308e283
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.14

Release files / taskcapsule-0.2.1-py3-none-any.whl

Download URL taskcapsule-0.2.1-py3-none-any.whl
Size 7.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a4737419ffbec009752adeb028e05b64fcabd2ad831686544b47395cbec18d4e
BLAKE2b-256 checksum
How to use checksums
ed5a110abe5e3167cf642aae70df176efb4beef4215950c2053f6a70fecc0d65
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.14

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page