User’s Manual¶
Introduction¶
“Rituals” is a task library for Invoke
that keeps the most common tasks you always need out of your project,
and makes them centrally maintained. This leaves your tasks.py
small
and to the point, with only things specific to the project at hand.
The following lists the common task implementations that the
rituals.easy
module offers. See below
on how to integrate them into your tasks.py
.
help
– Default task, when invoked with no task names.clean
– Perform house-cleaning.build
– Build the project.docs
– Build the documentation.test
– Perform standard unittests.check
– Perform source code checks.release.bump
– Bump a development version.release.dist
– Distribute the project.release.prep
– Prepare for a release.- … and many more, see
inv -l
for a complete list.
The guiding principle for these tasks is to strictly separate low-level
tasks for building and installing (via setup.py
) from high-level
convenience tasks a developer uses (via invoke
). Invoke tasks can
use Setuptools ones as building blocks, but never the other way ‘round –
this avoids any bootstrapping headaches during package installations.
Use inv -h ‹task›
as usual to get details on the options of these
tasks.
The Tasks Reference explains them in more detail.
Look at the modules in
rituals.acts
if you want to know every nuance of what these tasks do.
Note
The easiest way to get a working project using rituals
is the
py-generic-project cookiecutter archetype, which is tightly
integrated with the tasks defined here.
That way you have a working project skeleton within minutes that is fully equipped, with all aspects of building, testing, quality checks, continuous integration, documentation, and releasing covered.
Adding Rituals to Your Project¶
First of all, include rituals
as a dependency in your dev-requirements.txt
or a similar file, to get a release from PyPI.
To refer to the current GitHub master
branch instead, use a pip
requirement like this:
-e git+https://github.com/jhermann/rituals.git#egg=rituals
Then at the start of your tasks.py
, use the following statement to define
all tasks that are considered standard:
from rituals.easy import *
This works by defining the namespace
identifier containing Ritual’s default tasks.
Note that it also defines Invoke’s Collection
and task
identifiers,
and some other common helpers assembled in rituals.easy
.
Rituals’ own tasks.py can serve as an example.
Of course, you may also do more selective imports, or build your own Invoke namespaces with the specific tasks you need.
Warning
These tasks expect an importable setup.py
that defines
a project
dict with the setup parameters, see
rudiments and
py-generic-project for examples. The needed changes are minimal:
project = dict( # this would usually be a setup(…) call
name='…',
…
)
if __name__ == '__main__':
setup(**project)
Task Namespaces¶
The Root Namespace¶
The tasks useful for any (Python) project are organized in a root namespace.
When you use the from rituals.easy import *
statement, that also imports
this root namespace. By convention of Invoke, when the identifier namespace
is defined, that one is taken instead of constructing one automatically from
all defined tasks.
It contains some fundamentals like clean
, and nested namespaces handling
specific topics. Examples of nested namespaces are test
, check
,
docs
, and release
. See Tasks Reference for a complete list.
The root namespace has help
as the default task, and
most nested namespaces also have a default with the most commonly performed
action. These default tasks are automatically aliased to the name of the
namespace, so for example docs.sphinx
can also be called as docs
.
Adding Local Task Definitions¶
Having an explicit root namespace
means that within tasks.py
, you need to register your own tasks
using its add_task
method, if you want them to be
available as top-level names:
@task
def my_own_task(ctx):
"""Something project-specific."""
…
namespace.add_task(my_own_task)
Rituals’ own tasks.py uses this to add some local tasks.
Another strategy is to add them in bulk, so when you write a new task you cannot forget to make it visible:
# Register local tasks in root namespace
from invoke import Task
for _task in globals().values():
if isinstance(_task, Task) and _task.body.__module__ == __name__:
namespace.add_task(_task)
Add the above snippet to the end of your tasks.py
,
and every local task definition gets added to the root namespace.
Constructing Your Own Namespace¶
When you want to have more control, you can exclude the namespace
identifier from the import and instead define your own.
This example taken from the
tasks.py of py-generic-project
shows how it’s done:
from rituals.easy import task, Collection
from rituals.acts.documentation import namespace as _docs
…
namespace = Collection.from_module(sys.modules[__name__], name='')
namespace.add_collection(_docs)
Note that the name=''
makes this a root namespace.
If you need to be even more selective, import individual tasks from modules
in rituals.acts
and add them to your namespaces.
How-Tos¶
Change default project layout¶
By default, sources are expected in src/‹packagename›
and tests in
src/tests
.
You can change this by calling one of the following functions, directly
after the import from rituals.invoke_tasks
.
config.set_maven_layout()
– Changes locations tosrc/main/python/‹packagename›
andsrc/test/python
.config.set_flat_layout()
– Changes locations to‹packagename›
andtests
.
Change default project configuration¶
If you want to override the configuration defaults of various tasks,
without using environment variables, add an invoke.yaml
file in
the same directory where your tasks.py
is located
– usually the project root directory.
This example makes Sphinx (as called by the default docs
task)
place generated files in the top-level build
directory instead
of a sub-directory in docs
.
rituals:
docs:
build: ../build/_html
See Configuration Reference for a list of possible options.