pyXcute API reference

A small task runner inspired by npm scripts.

Usage/examples can be founded in README.

Constants

conf = dict()

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

  1. A convenience way to share variables between your cute.py 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 datetime.datetime.now().

  • 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")

Functions

cute(**tasks)

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}/__init__.py or {pkg_name}/__pkginfo__.py. 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}.

f(text)

Format the string with conf.

Parameters:

text (str) – Input string.

Return type:

str

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

cute(
  hello = "echo Current time is {date}"
)
log(*items)

Log the items to the console.

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

Parameters:

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.

Parameters:
  • 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...

cute(
    foo = my_task,
    bar = "echo bar"
)
split_version(text)

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

Parameters:

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

Return type:

tuple(str, str, str)

The regular expression used by this function:

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

Bump the version with semver module.

Parameters:

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:

str

Returns:

new version number.

Classes

class Bump(file, bumper=<function semver_bumper>, cfgs=('setup.cfg', 'pyproject.toml'))

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

Parameters:
  • 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().

  • cfgs (list[str]) – A list of config files. The version number inside these files would be updated to the new version.

__call__(*args)

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 configs and update to the new version. The version number is matched by the regular expression ^version\s*=\s*["']?(\S+?)["']?\s*$.

class Chain(*task_lists)

An executor which runs tasks in sequence.

Parameters:

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

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

cute(
    foo = ["echo foo", "echo bar"]
)
# equals to
cute(
    foo = Chain(["echo foo", "echo bar"])
)
__call__(*args)

It runs all tasks in sequence.

Parameters:

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

class Cmd(*cmds)

Shell command executor.

Parameters:

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:

cute(
    foo = "echo foo"
)
# equals to
cute(
    foo = Cmd("echo foo")
)
__call__(*args)

When called, it executes each commands with subprocess.run().

Parameters:

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

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

An executor which spawns a live-reload server.

Parameters:
  • 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

__call__()

When called, spawn a livereload server.

A live example.

class Log(*items)

A simple printer.

Parameters:

items (list) – Items which would be logged.

__call__()

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

class Skip(task, should_skip=None)

Run task conditionally.

Parameters:
  • task – The task.

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

__call__(*args)

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

Parameters:

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:

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

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

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

Result:

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

An executor which throws errors.

Parameters:

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:

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

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.

Parameters:

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

__call__(*args)

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.

Parameters:

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

Example:

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