I spent all that money on a graphical user interface, I bought a Macintosh in 1985, and now the latest version wants me to develop with just the 256 icons of ascii.
The terminal is required. Some employers expect a typing speed test and take exception to those with terminal phobia. I am ok with clis. I read the documentation and become proficient with them as tools. But there are so many and as I move from one to the other I forget the arguments and short cuts.
I have a solution. I have evolved a work practice that includes the package Invoke. Once you have mastered a tool, encapsulate your hard won knowledge in tasks and rule the day. The documentation is excellent, but let me give you a taste.
python3.9 -m venv .
pip install invoke
echo '""" our development tasks """' > tasks.py
echo 'from invoke import task' >> tasks.py
Here we create a directory called
tamed, move to that directory and install a virtual environment, which we activate. Then we ask
pip to install
invoke. Finally, we create a file called
tasks.py and place within a comment and import.
invoke now will result in:
% invoke --list
No tasks found in collection 'tasks'!
So let’s add some tasks.
First we need a
You’ll notice the underscore first parameter, that’s the context and we’ll address it later. But for now, let’s see the
help for this task:
% inv -h hello
Usage: inv[oke] [--core-opts] hello [--options] [other tasks here ...]
-m STRING, --message=STRING
Now, let’s call it:
%inv hello world
Since the terminal is now the window on your world we’ll need an essential tool to know what it’s like in there:
Some things to note here: we have a flag for the short format, we’ve added help to our task and we’re using the context. The context allows us to run subprocesses. Here we’re using curl. I’ve imported
urllib.parse at the top of the file and
quote what is passed in as the location. Short will be a boolean and we can test its
truthiness to append the format argument. Now who remembers that
curl takes the argument
-s for silent mode and not
-q for quiet mode - for that matter who knew you could get rid of the progress information? I called up the
man page to remember how to get rid of it for this article! Now I no longer have to remember as it’s encapsulated in my task! Oh, and the weather here:
% inv weather 'milford haven' -s
milford haven: ⛅ +13°C
the hard part
I recently was asked to build a python package with sub-packages that could be delivered independently, with their own versions. So I immediately went to the documentation and read up on sub-packages: Packaging namespace packages
From this I chose
pkg_resources-style namespace packages as it supports
zip-safe and we’d be using resources within the package such as templates and icons. The resultant directory structure looks like this:
And yet, properly installed, you
import starwars.goongas.main. When asked to add another sub-package… I have a task for that!
First we have to create a subdirectory within a package directory within a subdirectory of the package directory. The
__init__.py of the embedded package directory needs to declare a namespace and our version resides in the subpackage’s
__init__.py . Then we create a config file for bumpversion and a simple
setup.py , add our creation to
dev.txt , make a directory for the new tests and finally instruct the user to run
pip and start testing!
By now you must see that I could not possibly remember all that. But I put it in a task and have used it often on more than one project. It looks like I also use bumpversion.
Another useful parameter to
pre; a chain of tasks to invoke before invoking this task. For example, a
release task might have
pre=[clean, lint, test, build]. If any task or
ctx.run fails the task exits. So if test fails release will never be invoked. Invoke, also, has a concept of
collections that allow you to create groups of tasks, for example: db tasks and documentation tasks. It’s worth a look: Loading collections.
Some do not like the underscore policy of
invoke, as in changing them to hyphens, and so there is an adaptation for that: raft
I just used this subtitle to annoy my brother. In the
Invoke documentation it explains how to write your own command line tool. When you publish it, I will likely have to learn it, and encapsulate my usage of it in my own tasks, but have a look. Using Invoke as a library. I’m afraid
Invoke has not cured my terminal phobia, but the
cli is now my friend.