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:
A convenience way to share variables between your
cute.py
file andxcute
module.The context for string formatting. See
f()
.
By default, it has following keys:
curr_task
:str
. The name of the current task.date
: Equals todatetime.datetime.now()
.old_version
:str
. A version number. Only available afterBump
task.pkg_name
: Thepkg_name
specified by the user incute()
.py
: A specialPy
Object. This allows you to usepy
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 tocute()
.tty
:bool
.True
if the output is a terminal.version
:str
. A version number. Also seecute()
.
- 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 toconf
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 runcute version
to log the version of{pkg_name}
module.bump
:Bump("{version_file}")
. You can runcute bump [major|minor|patch]
to bump the version of{version_file}
.
- f(text)¶
Format the string with
conf
.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 withprint(*items)
.
- run_task(task, *args)¶
Run user task. It handles non-callable user task and converts them into
Chain
,Task
, orCmd
.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:
The regular expression used by this function:
match = re.search("__version__ = ['\"]([^'\"]+)", text)
- semver_bumper(old_version, part='patch')¶
Bump the version with
semver
module.
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 tosemver_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:Assign the old version to
conf["old_version"]
Assign the new version to
conf["version"]
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.
When the task is a
list
, it would be converted intoChain
:cute( foo = ["echo foo", "echo bar"] ) # equals to cute( foo = Chain(["echo foo", "echo bar"]) )
- 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 intoCmd
:cute( foo = "echo foo" ) # equals to cute( foo = Cmd("echo foo") )
- __call__(*args)¶
When called, it executes each commands with
subprocess.run()
.
- 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.
- 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
orshould_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 aSkip: ...
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.
When the task is an instance of
Exception
or a subclass ofException
, it would be converted intoThrow
: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
isNone
, re-raises last error.If
err
is an instance ofBaseException
, raiseserr
.If
err
is an instance ofstr
, raisesException(err)
.If
err
is callable, raiseserr()
.
- 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.
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 )