Scenario: using project-specific sets of aliases¶
We will again continue where we left off in part 2 (Scenario: local development with Docker). This time we will see how commands that were created in one Dodo Commands environment can be reused in a different environemnt. If you haven’t done the steps of the previous scenario, run this to get started:
cd /tmp
git clone git@github.com:mnieber/dodo_commands_tutorial.git
# Copy the end state of part 2 of the tutorial
cp -rf ./dodo_commands_tutorial/part2/after ./tutorial
# Create and activate a dodo environment for our project
cd ./tutorial
$(dodo env --init tutorial)
Activating the default Dodo Commands environment¶
Let’s start by deactivating the current tutorial
environment. You do this by activating
the default
environment:
# activate default environment
$(dodo env default)
dodo which
default
The default environment is similar to all other environment. Let’s check it out:
# Print the Dodo Commands environment directory
dodo which --env-dir
~/.dodo_commands/envs/default
# Print the project directory
dodo which --project-dir
~/.dodo_commands/default_project
# Print the configuration
dodo print-config
ROOT:
env_name: default
version: 1.0.0
config_dir: ~/.dodo_commands/default_project
command_path:
- ~/.dodo_commands/default_project/commands/*
- /some/path/to/dodo_commands/dodo_system_commands
project_dir: ~/.dodo_commands/default_project
Tip
In the output of dodo print-config we see that all command directories in ~/.dodo_commands/default_project/commands/*
are in the command path. This is true for all Dodo Commands environments (unless if you explitly remove this path from the command path).
Installing more commands¶
We will now see how additional default commands can be installed.
# If you haven't activated the default environment yet, do so now
$(dodo env default)
# Install the dodo-git-commands pip package
dodo install-commands --pip dodo-git-commands --to-defaults --confirm
(/) python3.5 -m pip install --upgrade --target ~/.dodo_commands/commands dodo_git_commands
confirm? [Y/n]
Collecting dodo-git-commands
Successfully installed dodo-git-commands-0.3.0
(/) ln -s \
~/.dodo_commands/commands/dodo_git_commands \
~/.dodo_commands/default_project/commands/dodo_git_commands
confirm? [Y/n]
We see that the commands are installed into the ~/.dodo_commands/commands
directory.
Because we passed the to-default
flag, a symlink to dodo_git_commands is created in
~/.dodo_commands/default_project/commands
:
# Print the command path
dodo print-config /ROOT/command_path
- ~/.dodo_commands/default_project/commands/*
- /some/path/to/dodo_commands/dodo_system_commands
dodo which git-multi-status
~/.dodo_commands/commands/dodo_git_commands/git-multi-status.py
Creating a new environment¶
Now we’ll create a new project in the ~/projects
directory. The new project will have
a python virtual environment.
# create a new project with python virtual environment
$(dodo env --create --create-python-env foo)
Creating project directory ~/projects/foo ... done
# check that we've switched to the foo environment
dodo which
foo
# check that we're using the new python virtual environment
which python
~/projects/foo/.env/bin/python
Tip
You can change the standard location for creating new projects in the
~/.dodo_commands/config
file. You can edit this file or call
dodo global-config settings.projects_dir /path/to/projects
Using the mk.py script in the new environment¶
To use the mk
command script that we created in the tutorial
environment, we need to have
/tmp/tutorial/commands
in our command_path. Surely, we can simply add this path to
${/ROOT/command_path}
. The problem with this approach is that we may move the
tutorial
project to a new location, and then the hard-coded path will no longer
be correct. In the steps below, we will use an alternative option that is a bit more robust.
In this step, we use dodo install-commands
to create a symlink in the global commands directory
that points to /tmp/tutorial/commands
. Note that we use the --as
option to give a more
recognizable name (dodo_tutorial_commands
) to the new command path.
dodo install-commands /tmp/tutorial/commands --as dodo_tutorial_commands --confirm
(/tmp) ln -s \
/tmp/tutorial/commands \
~/.dodo_commands/commands/dodo_tutorial_commands
confirm? [Y/n]
Now, if we add ~/.dodo_commands/commands/dodo_tutorial_commands
to ${/ROOT/command_path}
then the mk
command will be found.
ROOT:
# other stuff
command_path:
- ~/.dodo_commands/default_project/commands/*
- ~/.dodo_commands/commands/dodo_tutorial_commands
Note
Of course, if the original location of /tmp/tutorial/commands changes, then you still need to update the symlink in the global commands directory, but you won’t have to update the command path in every project.
Before we can successfully call mk
, we should add a MAKE
section to config.yaml
,
otherwise the command will fail (it expects to find a MAKE
configuration key):
# ~/projects/foo/.dodo_commands/config.yaml
MAKE:
cwd: /tmp/tutorial/writer
Importing symbols from a command script¶
So far, we’ve kept our mk
script deliberately very simple. Let’s refactor it by extracting a function
for running make
. We can then use this function in our mk-greet
script.
# In: /tmp/tutorial/commands/mk.py
from dodo_commands import Dodo
def run_make(*what):
Dodo.run(["make", *what], cwd=Dodo.get("/MAKE/cwd"))
if Dodo.is_main(__name__):
Dodo.parser.add_argument("what")
run_make(Dodo.args.what)
# In: /tmp/tutorial/commands/mk-greet.py
from dodo_commands import Dodo
from dodo_tutorial_commands.mk import run_make
if Dodo.is_main(__name__):
Dodo.parser.add_argument("greeting")
run_make("greeting", "GREETING=%s" % Dodo.args.greeting)
Note
The import of run_make
from the dodo_tutorial_commands
package will succeed because all
packages in the ${/ROOT/command_path}
are added to sys.path
during execution of the
command.
Note
You see that we added a line that says if Dodo.is_main(__name__)
. This replaces the standard line
if __name__ == "__main__"
which doesn’t work when executing the script with dodo mk
. The reason
is that during the execution of dodo `` ``mk.py
is not the main module.
Note
If the caller of the script uses the -confirm
flag then they expect to be notified of any
action before it’s taken. If your script violates this assumption, then you should use
Dodo.is_main(__name__, safe=False)
. This has the effect that the script will not run in combination
with --confirm
(instead, it will stop with an error message).
dodo mk-greet stranger
echo "Hello stranger"
Hello stranger
Detail sections¶
Open the adjacent tabs for more detail sections
In some cases we may want to call a command in a different environment without switching
to that environment. For example, we may only want to print its configuration. We can
do this by calling its entry-point in ~/.dodo_commands/bin
:
# Directly call the entry point of the tutorial environment
~/.dodo_commands/bin/dodo-tutorial which
tutorial
# We can extend the path to make this easier
export PATH=$PATH:~/.dodo_commands/bin
# Directly call the dodo entry point in the foo environment
dodo-tutorial which
tutorial
Each Dodo command should ideally run out-of-the-box. If the mk
command needs additional Python packages,
you can describe them in a mk.meta
file:
# /tmp/tutorial/commands/mk.meta
requirements:
- dominate==2.2.0
We can try this out by importing dominate
in mk.py
:
# /tmp/tutorial/commands/mk.py
import dominate
from dodo_commands import Dodo
# ... rest of the script stays the same
Calling the mk
command will ask the user for confirmation to install the dominate
package into the current Python environment:
dodo mk greeting
This command wants to install dominate==2.2.0:
Install (yes), or abort (no)? [Y/n]
Collecting dominate==2.2.0
Successfully installed dominate-2.2.0
--- Done ---
(/tmp) make runserver
confirm? [Y/n]