# Watiba
#### Version: **0.6.33**
#### Date: 2021/08/05
Watiba, pronounced wah-TEE-bah, is a lightweight Python pre-compiler for embedding Linux shell
commands within Python applications. It is similar to other languages' syntactical enhancements where
XML or HTML is integrated into a language such as JavaScript. That is the concept applied here but integrating
BASH shell commands with Python.
As you browse this document, you'll find Watiba is rich with features for shell command integration with Python.
Features:
- Shell command integration with Python code
- In-line access to shell command results
- Current directory context maintained across commands throughout your Python code
- Async/promise support for integrated shell commands
- Remote shell command execution
- Remote shell command chaining and piping
## Table of Contents
1. [Usage](#usage)
2. [Directory Context](#directory-context)
3. [Commands as Variables](#commands-as-variables)
4. [Command Results](#command-results)
5. [Asynchronous Spawning and Promises](#async-spawing-and-promises)
1. [Useful Properties in Promise](#useful-properties-in-promise)
2. [Spawn Controller](#spawn-controller)
3. [Join, Wait or Watch](#join-wait-watch)
4. [The Promise Tree](#promise-tree)
5. [Threads](#threads)
6. [Remote Execution](#remote-execution)
1. [Change SSH port for remote execution](#change-ssh-port)
7. [Command Chaining](#command-chaining)
8. [Command Chain Piping (Experimental)](#piping-output)
9. [Installation](#installation)
10. [Pre-compiling](#pre-compiling)
11. [Code Examples](#code-examples)
<div id="usage"/>
## Usage
Watiba files, suffixed with ".wt", are Python programs containing embedded shell commands.
Shell commands are expressed within backtick characters emulating BASH's original capture syntax.
They can be placed in any Python statement or expression. Watiba keeps track of the current working directory
after the execution of any shell command so that all subsequent shell commands keep context. For example:
Basic example of embedded commands:
```
#!/usr/bin/python3
# Typical Python program
if __name__ == "__main__":
# Change directory context
`cd /tmp`
# Directory context maintained
for file in `ls -lrt`.stdout: # In-line access to command results
print(f"File in /tmp: {file}")
```
This loop will display the file list from /tmp. The `ls -lrt` is run in the
context of previous `cd /tmp`.
<div id="commands-as-variables"/>
#### Commands Expressed as Variables
Commands within backticks can _be_ a variable, but cannot contain snippets of Python code or Python variables.
The statement within the backticks _must_ be either a pure shell command or a Python variable containing a pure
shell command. To execute commands in a Python variable, prefix the variable name between backticks with a dollar sign.
_A command variable is denoted by prepending a dollar sign on the variable name within backticks_:
```
# Set the Python variable to the command
cmdA = 'echo "This is a line of output" > /tmp/blah.txt'
cmdB = 'cat /tmp/blah.txt'
# Execute first command
`$cmdA` # Execute the command within Python variable cmdA
# Execute second command
for line in `$cmdB`.stdout:
print(line)
```
_This example demonstrates keeping dir context and executing a command by variable_:
```
#!/usr/bin/python3
if __name__ == "__main__":
# Change CWD to /tmp
`cd /tmp`
# Set a command string
my_cmd = "tar -zxvf tmp.tar.gz"
# Execute that command and save the command results in variable "w"
w = `$my_cmd`
if w.exit_code == 0:
for l in w.stderr:
print(l)
```
_These constructs are **not** supported_:
```
file_name = "blah.txt"
# Python variable within backticks
`touch file_name` # NOT SUPPORTED!
# Attempting to access Python variable with dollar sign
`touch $file_name` # NOT SUPPORTED!
# Python within backticks is NOT SUPPORTED!
`if x not in l: ls -lrt x`
```
<div id="directory-context"/>
## Directory Context
An important Watiba usage point is directory context is kept for dispersed shell commands.
Any command that changes the shell's CWD is discovered and kept by Watiba. Watiba achieves
this by tagging a `&& echo pwd` to the user's command, locating the result in the command's STDOUT,
and finally setting the Python environment to that CWD with `os.chdir(dir)`. This is automatic and
opaque to the user. The user will not see the results of the generated suffix. If the `echo`
suffix presents a problem for the user, it can be eliminated by prefixing the leading backtick with a
dash. The dash turns off the context track, by not suffixing the command, and so causes Watiba to
lose its context. However, the context is maintained _within_ the set of commands in the backticks just not
when it returns. For example, **out = -\`cd /tmp && ls -lrt\`** honors the ```cd``` within the scope
of that execution line, but not for any backticked commands that follow later in your code.
**_Warning!_** The dash will cause Watiba to lose its directory context should the command
cause a CWD change either explicitly or implicitly.
_Example_:
```
`cd /tmp` # Context will be kept
# This will print from /home/user, but context is NOT kept
for line in -`cd /home/user && ls -lrt`.stdout:
print(line)
# This will print from /tmp, not /home/user
for line in `ls -lrt`.stdout:
print(line)
```
<div id="command-results"/>
## Command Results
The results of the command issued in backticks are available in the properties
of the object returned by Watiba. Following are those properties:
<table>
<th>Property</th><th>Data Type</th><th>Description</th>
<tr></tr>
<td valign="top">stdout</td><td valign="top">List</td><td valign="top">STDOUT lines from the command normalized for display</td>
<tr></tr>
<td valign="top">stderr</td><td valign="top">List</td><td valign="top">STDERR lines from the command normalized for display</td>
<tr></tr>
<td valign="top">exit_code</td><td valign="top">Integer</td><td valign="top">Exit code value from command</td>
<tr></tr>
<td valign="top">cwd</td><td valign="top">String</td><td valign="top">Current working directory <i>after</i> command was executed</td>
</table>
Technically, the returned object for any shell command is defined in the WTOutput class.
<div id="async-spawing-and-promises"/>
## Asynchronous Spawning and Promises
Shell commands can be executed asynchronously with a defined resolver callback block. Each _spawn_ expression creates
and runs a new OS thread. The resolver is a callback block that follows the Watiba _spawn_ expression. The spawn
feature is executed when a ```spawn `cmd` args: resolver block``` code block is encountered. The
resolver is passed the results in the promise object. (The promise structure contains the properties
defined in section ["Results from Spawned Commands"](#spawn-results) The _spawn_ expression also returns a _promise_ object
to the caller of _spawn_. The promise object is passed to the _resolver block_ in argument _promise_. The
outer code can check its state with a call to _resolved()_ on the *returned* promise object. Output from the command
is found in _promise.output_. The examples throughout this README and in the _examples.wt_ file make this clear.
<div id="useful-properties-in-promise"/>
##### Useful properties in promise structure
A promise is either returned in assignment from outermost spawn, or passed to child spawns in argument "promise".
<table>
<th>Property</th>
<th>Data Type</th>
<th>Description</th>
<tr></tr>
<td valign="top">host</td><td valign="top">String</td><td valign="top">Host name on which spawned command ran</td>
<tr></tr>
<td valign="top">children</td><td valign="top">List</td><td valign="top">Children promises for this promise node</td>
<tr></tr>
<td valign="top">parent</td><td val