tbot.machine.shell
¶
Shells are one of the three parts of a machine: The shell defines the methods
to interact with the machine. For Linux, the shell will usually be
tbot.machine.linux.Bash
, a shell implementation for interacting
with bash.
tbot does not impose any restrictions on how a shell interface is supposed to
look like. It does make sense to keep it close to existing implementations
though, as long as that is feasible. Look at the
LinuxShell
class for inspiration.
All shells inherit from tbot.machine.shell.Shell
, the base-class
for shells. For very bare-bones usecases, tbot provides the
RawShell
class.
Interactive Access¶
A lot of shells have an .interactive()
method which allows accessing the
machine’s console directly. This works similar to a terminal-emulator like
picocom or screen. The default testcases interactive_lab
,
interactive_board
, interactive_uboot
, and interactive_linux
are
using this mechanism, for example.
Base-Class¶
- class tbot.machine.shell.Shell[source]¶
Bases:
Machine
- abstract _init_shell() AbstractContextManager [source]¶
Initialize this shell.
An implementation of this method should return a context manager that, when entered, waits for the shell to appear on the channel and sets up any necessary options. This might include deactivating line-editing, disabling the history, etc.
The most comfortable way to implement this is using
contextlib.contextmanager()
:class Shell(tbot.machine.shell.Shell): @contextlib.contextmanager def _init_shell(self): try: # Wait for shell to appear ... # Setup options ... yield None finally: # Optionally destruct shell ...
- abstract exec(*args: Any) Any [source]¶
Run a command using this shell.
This is the only “common” interface tbot expects shells to implement. The exact semantics of running commands are up to the implementor. This especially includes the return value.
- Parameters:
*args –
.exec()
should take the command as one argument per command-line token. For example:mach.exec("echo", "Hello", "World")
- Returns:
The return value should in some way be related to the “output” of the command. For
LinuxShell
,exec
returns a tuple of the return code and console output:Tuple[int, str]
.
- ch: Channel¶
Channel to communicate with this machine.
Warning
Please refrain from interacting with the channel directly. Instead, write a
Shell
that wraps around the channel interaction. That way, the state of the channel is only managed in a single place and you won’t have to deal with nasty bugs when multiple parties make assumptions about the state of the channel.
Raw-Shell¶
- class tbot.machine.shell.RawShell[source]¶
Bases:
Machine
Absolute minimum shell implementation.
RawShell
attempts to be a minimal shell implementation. It does not make any assumptions about the other end. It is used, for example, for raw board-console access which allows debugging before U-Boot is fully working.- exec(*args: str) None [source]¶
Just send
" ".join(args)
to the machine’s channel.This minimal
exec()
implementation has no way of reading back the command output.
- interactive() None [source]¶
Connect tbot’s stdio to this machine’s channel. This will allow interactive access to the machine.
- ch: Channel¶
Channel to communicate with this machine.
Warning
Please refrain from interacting with the channel directly. Instead, write a
Shell
that wraps around the channel interaction. That way, the state of the channel is only managed in a single place and you won’t have to deal with nasty bugs when multiple parties make assumptions about the state of the channel.