iripau.executable module

Execute Command-Line Interfaces (CLI) as Python functions.

Call an instance of Executable, or any of its attributes, passing positional arguments as *args and optional arguments as **kwargs. All of the quoting is handled automatically, so there is no need to handle spaces nor any special characters such as single and double quotes. The attributes of the object will be instances of Command. The return value is an instance of subprocess.CompletedProcess.

Example

Make a docker wrapper:

docker = Executable("docker")

# docker --version
output = docker(version=True)

# docker run ubuntu:24.04 --volume=/tmp/data:/data:Z --name=test-container
output = docker.run("ubuntu:24.04", volume="/tmp/data:/data:Z", name="test-container")

# docker container rename test-container renamed-container
output = docker.container.rename("test-container", "renamed-container")

Note

All values for positional and optional arguments are converted to string with str(value) before creating the final subproces command.

class iripau.executable.Command(parent, command)[source]

Bases: object

Run a command or sub-command of a CLI as a Python function.

The attributes of Executable will be instances of this class, as well as any other sub-attribute.

Parameters:
  • parent (Executable | Command) – Object to call so the subprocess can actually be executed.

  • command (str) – Python identifier for a given command or cub-command.

iripau.executable.make_command(command)[source]

Replace underscore with dash.

Suitable for a CLI that uses dashes as word-separator in their positional arguments.

Parameters:

command (str) – Python identifier referring to a CLI command or sub-command.

Return type:

str

Returns:

Final token to be used as a CLI positional argument.

iripau.executable.make_option(option)[source]

Replace underscore with dash and prepend two more dashes.

Suitable for a CLI that uses dashes as word-separator in their positional arguments.

Parameters:

option (str) – Python identifier referring to a CLI optional argument.

Return type:

Tuple[str]

Returns:

The tokens that could be used as a CLI positional argument.

class iripau.executable.Executable(executable, make_command=<function make_command>, make_option=<function make_option>, alias=None, run_args_prefix='_', run_function=None, **kwargs)[source]

Bases: object

Run an executable as a Python callable.

Parameters:
  • executable (Union[Iterable[str], str]) – Path to an executable file or just the name if it exists in the PATH. Or tokens that refer to a command.

  • make_command (Callable[[str], str]) – Function to convert a Python identifier to the corresponding command positional argument for the CLI.

  • make_option (Callable[[str], Tuple[str]]) – Function to convert a Python identifier into the corresponding optional argument for the CLI.

  • alias (Union[Iterable[str], str]) – Alias for executable. See alias in iripau.subprocess.Popen.

  • run_args_prefix (str) – When calling an instance of this class, all of the **kwargs starting with this prefix will be passed to run_function after removing the prefix.

  • run_function (Callable[[Iterable[str], Any], Any]) – The function that will actually run the process, wait for it and return a subprocess.CompletedProcess, preferably. If None, the default will be iripau.command.host_run().

  • **kwargs – Keyword arguments to be passed to run_function every time this object is called. The run_args_prefix is not needed here.

Regarding optional arguments:

Most of the CLIs have a long and short version for the same option, for example docker run -m 128m and docker run --memory=128m. By default only one of those option can be used:

# docker run ubuntu:24.04 -m 128m
docker.run("ubuntu:24.04", m="128m")

# docker run ubuntu:24.04 --memory=128m
docker.run("ubuntu:24.04", memory="128m")

But using the name of a short option in a Python function might reduce readability. To solve that issue, the get method of a dictionary can be used as make_option. The keys of the dictionaries would be the Python identifiers used when calling the object:

options_map = {
    "config": ("-c",),
    "memory": ("-m"),
    "quiet": ("-q",)
}

docker = Executable("docker", make_option=options_map.get)

# docker run ubuntu:24.04 -m 128m
output = docker.run("ubuntu:24.04", memory="128m")

Also, the dictionary can be used in combination with the default function, make_option(), or any other function to avoid having all of the options supported by the CLI in the dictionary:

option_map = {...}

def make_option(option):
    tokens = options_map.get(option)
    if tokens is None:
        tokens = make_option(option)
    return tokens

docker = Executable("docker", make_option=make_option)

Tip

Using a dictionary can help on make_command as well.

As you might have already noted, the values of the dictionary are tuples. If that tuple has more that one item, one of those will be chosen randomly. If the chosen option starts with --, there will be a single token with the option and the value: --memory=128m. If not, there will be two tokens: -m 128m.

Regarding the values that the optional arguments can have:

If True, the option will be treated as a flag, with no value:
From: help=True
To: --help
If False or None, the option will be ignored:
From: help=False or help=None
To: Nothing, not even an empty string
If an iterable and not a string, the option will be repeated for each item:
From: env=["DB_PASS=0123", "DB_PORT=3210"]
To: -e DB_PASS=0123 -e DB_PORT=3210