Photo Chris J. Davis in Unsplash
We usually have a fast-start CLI in our COOP packages. It is done with click.
The UX rationale is type the name of the package in the terminal to discover all the implemented commands. It looks like :
>ms_thermo
Usage: ms_thermo [OPTIONS] COMMAND [ARGS]...
Package ms_thermo v0.3.2
--------------- MS_THERMO --------------------
You are now using the Command line interface of MS-Thermo, a Python3
helper for reactive multispecies computation, created at CERFACS
(https://cerfacs.fr).
This is a python package currently installed in your python environement.
See the full documentation at : https://ms-
thermo.readthedocs.io/en/latest/.
Options:
--help Show this message and exit.
Commands:
fresh-gas description of a non-reacted kero-air mixture.
gasout Apply GASOUT actions to a CFD field.
hp-equil HP equilibrium using Cantera.
tadia adiabatic flame temperature for Kerosene.
yk-from-phi Mass fractions of a fuel-air mixture.
Add the entry point
To enable this CLI, ou must open an entry point, i.e. a command that will be added to your terminal at the installation.
In the setup.cfg
this reads:
[options.entry_points]
console_scripts =
ms_thermo = ms_thermo.cli:main_cli
Here, typing the name ms_thermo
is equivalent to call function main_cli
stored in the module cli.py
of the ms_thermo
package.
Create the click dialog cli.py
The module cli.py
is stored at the root of the sources internal to the package (here src/ms-thermo/cli.py
).
Il looks like this
Header
First we keep a light header with the minimal amount of imports. Since these are done at each CLI call, make sure you do not load all the dependencies when you import the package.
This means *keep your __init___.py
as void as possible, no from .core import *
.
The drawback is the need to use only relative explicit imports inside our modules. In the long run we experienced, this is not really a drag, and help ou developers to easily find the source of lower layer codes.
#!/usr/bin/env python
"""
cli.py
Command line interface for tools in ms_thermo
"""
import click
import ms_thermo
Version decorator
We add this small utility function, which will help to decorate our mail CLI with the up-to-date package version.
def add_version(f):
"""
Add the version of the tool to the help heading.
:param f: function to decorate
:return: decorated function
"""
doc = f.__doc__
f.__doc__ = "Package " + ms_thermo.__name__ + " v" + ms_thermo.__version__ + "\n\n" + doc
return f
The main group
Here is the “landing” command, the main group of CLI associated to the package. In click, docstrings are the content printed to the screen, make sure they look good.
@click.group()
@add_version
def main_cli():
"""--------------- MS_THERMO --------------------
You are now using the Command line interface of MS-Thermo,
a Python3 helper for reactive multispecies computation, created at CERFACS (https://cerfacs.fr).
This is a python package currently installed in your python environement.
See the full documentation at : https://ms-thermo.readthedocs.io/en/latest/.
"""
pass
The actual commands
Here, we add two simple command with simple args, read the click documentation for more complex inputs.
@click.command()
@click.argument("temperature", nargs=1)
@click.argument("pressure", nargs=1)
@click.argument("phi", nargs=1)
def tadia(temperature, pressure, phi):
"""adiabatic flame temperature for Kerosene.
The initial TEMPERATURE is in Kelvins.
The initial PRESURE in in Pascals.
The PHI equivalence ratio equals 1 at stoechiometry.
The computation is done by interpolation in a precomputed 2S_KERO_BFER table.
The system considered to build the table was a 1D flame at constant pressure.
"""
from ms_thermo.tadia import tadia_table
burnt_temperature, yk_ = tadia_table(float(temperature), float(pressure), float(phi))
print(
"\nThe adiabatic flame temperature of a mix "
+ f"C10H22-air from tables is : {burnt_temperature:.2f} K."
)
print("\nSpecies | Mass fraction")
print("------------------------------")
for specie in yk_:
print(f"{specie:12s}| {yk_[specie]:.3f}")
main_cli.add_command(tadia)
@click.command()
@click.argument("temperature", nargs=1, type=float)
@click.argument("pressure", nargs=1, type=float)
@click.argument("phi", nargs=1, type=float)
def fresh_gas(temperature, pressure, phi):
"""description of a non-reacted kero-air mixture.
The initial TEMPERATURE is in Kelvins.
The initial PRESURE in in Pascals.
The PHI equivalence ratio equals 1 at stoechiometry.
The computation is done using a 100K piecewise linear table of enthalpies.
"""
from ms_thermo.fresh_gas import fresh_gas
rho, rhoE, rhoyk = fresh_gas(temperature, pressure, phi)
print(f"\nrho | {rho:.3f} kg/m3")
print(f"rhoE | {rhoE:.3f} J.kg/m3")
print("rhoYk |")
for specie in rhoyk:
print(f" {specie:9s}| {rhoyk[specie]:.3f} mol.kg/m3")
print("------------------------------")
print("Yk |")
for specie in rhoyk:
print(f" {specie:9s}| {rhoyk[specie]/rho:.3f} [-]")
main_cli.add_command(fresh_gas)
Deprecated commands
At the end, we keep some deprecations messages to help people find the new equivalent to a deprecated command:
DPCTD = "Deprecated command from python package ms-thermo..."
def redirect_yk_from_phi():
"""redicrection of former command"""
print(DPCTD)
print(" ? Did you mean : > ms_thermo yk_from_phi")
def redirect_gasout():
"""redicrection of former command"""
print(DPCTD)
print(" ? Did you mean : > ms_thermo gasout")