pyXcute API reference

A small task runner inspired by npm scripts.

Usage/examples can be founded in README.


conf = dict()

A dictionary that is used across all tasks. It has 2 purpoeses:

  1. A convenience way to share variables between your file and xcute module.

  2. The context for string formatting. See f().

By default, it has following keys:

  • curr_task: str. The name of the current task.

  • date: Equals to

  • old_version: str. A version number. Only available after Bump task.

  • pkg_name: The pkg_name specified by the user in cute().

  • py: A special Py Object. This allows you to use py launcher corss-platform. On Windows:

    "{py:2.7}".format(**conf) # -> "py -2.7"

    On Linux:

    "{py:2.7}".format(**conf) # -> "python2.7"
  • tasks: dict. This is what you send to cute().

  • tty: bool. True if the output is a terminal.

  • version: str. A version number. Also see cute().

task_converter = TaskConverter()

The task converter used by pyXcute.

You can extend the converter like this:

# let's say you want to convert tasks that start with ``"my:..."`` into
# ``MyTask``

# create the callable executor
class MyTask:
    def __init__(self, task):
        self.task = task
    def __call__(self):
        # do something to ``task``...
# create a test function
def is_my_task(task):
    return isinstance(task, str) and task.startswith("my:")
# prepend them to ``task_converter.matchers`` so that MyTask converter is
# processed before Cmd converter.
task_converter.matchers.insert(0, (is_my_task, MyTask))

# the task would be converted automatically
task_converter.transform("my:this is a custom task")
# -> MyTask("my:this is a custom task")



Main entry point.

Define your tasks as keyword arguments. Those tasks would be assigned to conf with key "tasks".

There are some tasks having special effects:

  • pkg_name: When this task is defined:

    • The key is removed and inserted into conf. This allows you to specify {pkg_name} variable in other tasks.

    • The module would try to find the version number from {pkg_name}/ or {pkg_name}/ If found, the filename is inserted to conf with key "version_file", and the version is inserted with key "version".

      See split_version() for the regular expression matching __version__.

Some tasks have a default value:

  • version: Log("{version}"). You can run cute version to log the version of {pkg_name} module.

  • bump: Bump("{version_file}"). You can run cute bump [major|minor|patch] to bump the version of {version_file}.


Format the string with conf.


text (str) – Input string.

Return type


This function is used by various task executors. It allows you to interpret variables in your tasks. For example:

  hello = "echo Current time is {date}"

Log the items to the console.

If conf["tty"] is False, this function has no effect.


items (list) – items would be logged with print(*items).

run_task(task, *args)

Run user task. It handles non-callable user task and converts them into Chain, Task, or Cmd.

  • task – The task.

  • args (list[str]) – Additional that would be passed to the task.

Call this function if you have to execute other tasks in your customized executor:

def my_task():
    # do something...
    run_task("bar") # run "bar" task
    # do something...

    foo = my_task,
    bar = "echo bar"

Split the text to (left, version_number, right).


text (str) – Input text. It is usually the source code of or

Return type

tuple(str, str, str)

The regular expression used by this function:

match ="__version__ = ['\"]([^'\"]+)", text)
semver_bumper(old_version, part='patch')

Bump the version with semver module.


part (str) –

Specify which part should be bumped. Possible values are "patch", "minor", or "major".

If part is a valid version number, it would bump the version number to part.

Return type



new version number.


class Bump(file, bumper=<function semver_bumper>)

An executor which can bump the version inside a .py file.

  • file (str) – Input file.

  • bumper (callable) – A callable that would bump a version. The signature is bumper(version: str, *args) -> new_version: str. Default to semver_bumper().


When called, it bumps the version number of the file. Additional arguments are sent to bumper.

It uses split_version() to find the version. After bumping, it would:

  1. Assign the old version to conf["old_version"]

  2. Assign the new version to conf["version"]

  3. Try to find the version number inside setup.cfg and update it to the new version.

class Chain(*task_lists)

An executor which runs tasks in sequence.


task_lists (list[list]) – Multiple list of tasks.

When the task is a list, it would be converted into Chain:

    foo = ["echo foo", "echo bar"]
# equals to
    foo = Chain(["echo foo", "echo bar"])

It runs all tasks in sequence.


args (list[str]) – Other arguments would be passed into each task.

class Cmd(*cmds)

Shell command executor.


cmds (list[str]) – A list of commands. The command may contain variables which could be expanded by f().

If the task is a str, the task would be converted into Cmd:

    foo = "echo foo"
# equals to
    foo = Cmd("echo foo")

When called, it executes each commands with


args (list[str]) – args are appended to each command.

class LiveReload(pattern, task, html_base, **kwargs)

An executor which spawns a live-reload server.

  • pattern (str or list[str]) – Glob pattern, filename, or folder to be watched.

  • task – A task that should be run when the file changes.

  • html_base (str) – Path to the folder containing HTML files.

  • kwargs – Other arguments will be passed to Server.serve


When called, spawn a livereload server.

A live example.

class Log(*items)

A simple printer.


items (list) – Items which would be logged.


When called, it prints the items to the console with log().

class Skip(task, should_skip=None)

Run task conditionally.

  • task – The task.

  • should_skip (bool or callable) – Whether to skip the task.


Skip the test if should_skip or should_skip(*args) is not truthy.


args (list[str]) – Additional arguments are passed to the task and should_skip if it is a function.

Usually, you can just use comparators to run task conditionally:

    foo = sys.version_info >= (3, ) and "echo Python 3+"

Skip would log a Skip: ... information to the console when a task is skipped:

    foo = Skip("echo Python 3+", sys.version_info < (3, ))


$ python2 foo
> Task: foo
> Skip: echo Python 3+
class Throw(err=None)

An executor which throws errors.


err (str or Exception or None or class) – The error.

When the task is an instance of Exception or a subclass of Exception, it would be converted into Throw:

    foo = Exception,
    foo2 = Exception("some message")
# equals to
    foo = Throw(Exception),
    foo2 = Throw(Exception("some message"))

When called, it behaves differently according to the type of err:

  • If err is None, re-raises last error.

  • If err is an instance of BaseException, raises err.

  • If err is an instance of str, raises Exception(err).

  • If err is callable, raises err().

class Try(*tasks)

An executor which suppresses errors.


tasks (list) – The tasks which should be run.


When called, the tasks are executed in sequence. If a task raises an error, the error would be logged and continue to the next task.


args (list[str]) – Other arguments would be sent to each task.


    foo = Try(
        "echo execute and fail && exit 1", # executed
        "echo execute and fail && exit 1" # executed
    foo_err = "echo foo failed" # not executed