TBot Module

TBot

class tbot.TBot(config: tbot.config.Config, testcases: dict, new: bool = True, interactive: bool = False) → None[source]

Main class of TBot, you usually do not need to instanciate this yourself

Parameters:
  • config (tbot.config.Config) – A configuration to be used
  • testcases (dict) – Testcases available to this instance
  • new (bool) – Whether this is a new instance that should create a noenv machine. Always True unless you know what you are doing.
Variables:
boardshell

The default board machine

call(tcs: typing.Union[str, typing.Callable], *, fail_ok: bool = False, doc: bool = True, **kwargs: typing.Any) → typing.Any[source]

Call a testcase

Parameters:
  • tcs (str or typing.Callable) – The testcase to be called. Can either be a string or a callable
  • fail_ok (bool) – Whether a failure in this testcase is tolerable
  • doc (bool) – Whether documentation should be generated in this testcase
  • kwargs (dict) – Additional arguments for the testcase
Returns:

The return value from the testcase

call_then(tcs: typing.Union[str, typing.Callable], **kwargs: typing.Any) → typing.Callable[source]

Decorator to call a testcase with a function as a payload (“and_then” argument)

Parameters:
  • tcs (str or typing.Callable) – The testcase to call
  • kwargs (dict) – Additional arguments for the testcase
Returns:

The decorated function

Return type:

typing.Callable

destruct() → None[source]

Destruct this TBot instance and all associated machines. This method will be called automatically when exiting a with statement.

machine(mach: tbot.machine.machine.Machine) → tbot.TBot[source]

Create a new TBot instance with a new machine

Parameters:mach (tbot.machine.machine.Machine) – The machine to be added in the new instance
Returns:The new TBot instance, which has to be used inside a with statement
Return type:TBot
shell

The default host machine

with_board_linux() → tbot.TBot[source]

Shortcut to create a new TBot instance with a Linux boardmachine

Returns:The new TBot instance, which has to be used inside a with statement
Return type:TBot
with_board_uboot() → tbot.TBot[source]

Shortcut to create a new TBot instance with a U-Boot boardmachine

Returns:The new TBot instance, which has to be used inside a with statement
Return type:TBot

Machines

Machine Base Class

class tbot.machine.machine.Machine[source]

Abstract base class for machines

common_machine_name

Common name of this machine, eg "board" or "labhost"

exec(command: str, log_show: bool = True, log_show_stdout: bool = True) → typing.Tuple[int, str][source]

Execute a command on this machine

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • log_show (bool) – Whether documentation backends should include this command
  • log_show_stdout (bool) – Whether documentation backends should include the stdout of this command
Returns:

A tuple of the return code and the output (stdout and stderr are merged)

Return type:

tuple[int, str]

exec0(command: str, **kwargs: bool) → str[source]

Execute a command and expect it to return with 0

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • kwargs – Passed through to Machine.exec
Returns:

The output (stdout and stderr are merged)

Return type:

str

unique_machine_name

Unique name of this machine, eg "labhost-noenv"

workdir

Workdir where testcases can safely store data

Board Machine Base Class

class tbot.machine.board.MachineBoard → None[source]

Abstract base class for board machines

common_machine_name

Common name of this machine, for boards this will always be "board"

exec(command: str, log_show: bool = True, log_show_stdout: bool = True) → typing.Tuple[int, str]

Execute a command on this machine

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • log_show (bool) – Whether documentation backends should include this command
  • log_show_stdout (bool) – Whether documentation backends should include the stdout of this command
Returns:

A tuple of the return code and the output (stdout and stderr are merged)

Return type:

tuple[int, str]

exec0(command: str, **kwargs: bool) → str

Execute a command and expect it to return with 0

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • kwargs – Passed through to Machine.exec
Returns:

The output (stdout and stderr are merged)

Return type:

str

powercycle() → None[source]

Powercycle the board

unique_machine_name

Unique name of this machine, eg "labhost-noenv"

workdir

Workdir where testcases can safely store data

Labhost Machine Without Environment

class tbot.machine.lab_noenv.MachineLabNoEnv → None[source]

Labhost machine without environment

common_machine_name

Common name of this machine, always "host"

exec(command: str, log_show: bool = True, log_show_stdout: bool = True) → typing.Tuple[int, str]

Execute a command on this machine

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • log_show (bool) – Whether documentation backends should include this command
  • log_show_stdout (bool) – Whether documentation backends should include the stdout of this command
Returns:

A tuple of the return code and the output (stdout and stderr are merged)

Return type:

tuple[int, str]

exec0(command: str, **kwargs: bool) → str

Execute a command and expect it to return with 0

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • kwargs – Passed through to Machine.exec
Returns:

The output (stdout and stderr are merged)

Return type:

str

unique_machine_name

Unique name of this machine, always "labhost-noenv"

Labhost Machine With Environment

class tbot.machine.lab_env.MachineLabEnv(prompt: typing.Union[str, NoneType] = None) → None[source]

Labhost machine with environment

common_machine_name

Common name of this machine, always "host"

exec(command: str, log_show: bool = True, log_show_stdout: bool = True) → typing.Tuple[int, str]

Execute a command on this machine

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • log_show (bool) – Whether documentation backends should include this command
  • log_show_stdout (bool) – Whether documentation backends should include the stdout of this command
Returns:

A tuple of the return code and the output (stdout and stderr are merged)

Return type:

tuple[int, str]

exec0(command: str, **kwargs: bool) → str

Execute a command and expect it to return with 0

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • kwargs – Passed through to Machine.exec
Returns:

The output (stdout and stderr are merged)

Return type:

str

unique_machine_name

Unique name of this machine, always "labhost-env"

Buildhost Machine

class tbot.machine.build.MachineBuild(*, name: typing.Union[str, NoneType] = None, username: typing.Union[str, NoneType] = None, password: typing.Union[str, NoneType] = None, hostname: typing.Union[str, NoneType] = None, ssh_flags: typing.Union[str, NoneType] = None) → None[source]

Buildhost machine

Parameters:
  • name (str) – Name of the buildhost, as found in the config. Defaults to the value of tb.config["build.default"]
  • username (str) – Username on the buildhost, defaults to tb.config["build.<name>.username"]
  • password (str) –

    Password on the buildhost, if passwordless login is not available, defaults to tb.config["build.<name>.password"]

    Todo

    Not implemented yet, you have to use passwordless login

  • hostname (str) – Hostname of the buildhost, defaults to tb.config["build.<name>.hostname"]
  • ssh_flags (str) – Flags to be passed to ssh. This allows for custom ssh options like using a different key. Defaults to tb.config["build.<name>.ssh_flags"]
common_machine_name

Common name of this machine, always "host"

exec(command: str, log_show: bool = True, log_show_stdout: bool = True) → typing.Tuple[int, str]

Execute a command on this machine

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • log_show (bool) – Whether documentation backends should include this command
  • log_show_stdout (bool) – Whether documentation backends should include the stdout of this command
Returns:

A tuple of the return code and the output (stdout and stderr are merged)

Return type:

tuple[int, str]

exec0(command: str, **kwargs: bool) → str

Execute a command and expect it to return with 0

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • kwargs – Passed through to Machine.exec
Returns:

The output (stdout and stderr are merged)

Return type:

str

unique_machine_name

Unique name of this machine, "buildhost-<name>"

Board Machine For U-Boot Interaction

class tbot.machine.board_uboot.MachineBoardUBoot(*, name: typing.Union[str, NoneType] = None, boardname: typing.Union[str, NoneType] = None, power_cmd_on: typing.Union[str, NoneType] = None, power_cmd_off: typing.Union[str, NoneType] = None, connect_command: typing.Union[str, NoneType] = None, autoboot_prompt: typing.Union[str, NoneType] = None, autoboot_keys: typing.Union[str, NoneType] = None, prompt: typing.Union[str, NoneType] = None) → None[source]

Board machine for U-Boot interaction

Parameters:
  • name (str) – Name of the shell (eg someboard-uboot), defaults to tb.config["board.serial.name"]
  • boardname (str) – Name of the board, defaults to tb.config["board.name"]
  • power_cmd_on (str) – Command to poweron the board, defaults to tb.config["board.power.on_command"]
  • power_cmd_off (str) – Command to poweroff the board, defaults to tb.config["board.power.off_command"]
  • connect_command (str) – Command to connect to the board with a tool that behaves similar to rlogin, defaults to tb.config["board.serial.command"]
  • autoboot_prompt (str) – The U-Boot autoboot prompt that is expected on the board, defaults to tb.config["uboot.shell.autoboot-prompt"] or "Hit any key to stop autoboot: <x> " (interpreted as a regular expression)
  • autoboot_keys (str) – The key sequence to stop autoboot, defaults to tb.config["uboot.shell.autoboot-keys"] or "\n"
  • prompt (str) – The U-Boot prompt that is expected on the board, defaults to tb.config["uboot.shell.prompt"] or "U-Boot> "
common_machine_name

Common name of this machine, for boards this will always be "board"

exec(command: str, log_show: bool = True, log_show_stdout: bool = True) → typing.Tuple[int, str]

Execute a command on this machine

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • log_show (bool) – Whether documentation backends should include this command
  • log_show_stdout (bool) – Whether documentation backends should include the stdout of this command
Returns:

A tuple of the return code and the output (stdout and stderr are merged)

Return type:

tuple[int, str]

exec0(command: str, **kwargs: bool) → str

Execute a command and expect it to return with 0

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • kwargs – Passed through to Machine.exec
Returns:

The output (stdout and stderr are merged)

Return type:

str

powercycle() → None

Powercycle the board

unique_machine_name

Unique name of this machine, "board-uboot-<boardshell-name>"

Board Machine For Linux Interaction

class tbot.machine.board_linux.MachineBoardLinux(*, name: typing.Union[str, NoneType] = None, boardname: typing.Union[str, NoneType] = None, boot_command: typing.Union[str, NoneType] = None, login_prompt: typing.Union[str, NoneType] = None, login_timeout: typing.Union[float, NoneType] = None, username: typing.Union[str, NoneType] = None, password: typing.Union[str, NoneType] = None) → None[source]

Board machine for Linux interaction

Parameters:
  • name (str) – Name of the shell (eg someboard-bash), defaults to tb.config["linux.shell.name"]
  • boardname (str) – Name of the board, defaults to tb.config["board.name"]
  • boot_command (str) – U-Boot command to boot linux. May be multiple commands separated by newlines, defaults to tb.config["linux.boot_command"]
  • login_prompt (str) – The string to wait for before sending the username, defaults to tb.config["linux.shell.login_prompt"]
  • login_timeout (float) – The time to wait after entering login credentials, defaults to tb.config["linux.shell.login_timeout"]
  • username (str) – Username, defaults to tb.config["linux.shell.username"]
  • password (str) – Password, use "" if no password is required, defaults to tb.config["linux.shell.password"]
common_machine_name

Common name of this machine, for boards this will always be "board"

exec(command: str, log_show: bool = True, log_show_stdout: bool = True) → typing.Tuple[int, str]

Execute a command on this machine

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • log_show (bool) – Whether documentation backends should include this command
  • log_show_stdout (bool) – Whether documentation backends should include the stdout of this command
Returns:

A tuple of the return code and the output (stdout and stderr are merged)

Return type:

tuple[int, str]

exec0(command: str, **kwargs: bool) → str

Execute a command and expect it to return with 0

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • kwargs – Passed through to Machine.exec
Returns:

The output (stdout and stderr are merged)

Return type:

str

powercycle() → None

Powercycle the board

unique_machine_name

Unique name of this machine, "board-linux-<boardshell-name>"

Dummy Board Machine

class tbot.machine.board_dummy.MachineBoardDummy(*, name: typing.Union[str, NoneType] = None, turn_on: bool = True, power_cmd_on: typing.Union[str, NoneType] = None, power_cmd_off: typing.Union[str, NoneType] = None) → None[source]

Board machine dummy for just turning the board on and off

Parameters:
  • turn_on (bool) – Whether to turn on the board or just turn it off in the end. Useful for example for the U-Boot test suite which expects the board to be off in the beginning but still needs a manual poweroff once it’s done.
  • power_cmd_on (str) – The command for turning on the board, defaults to tb.config["board.power.on_command"]
  • power_cmd_off (str) – The command for turning off the board, defaults to tb.config["board.power.off_command"]
common_machine_name

Common name of this machine, for boards this will always be "board"

exec(command: str, log_show: bool = True, log_show_stdout: bool = True) → typing.Tuple[int, str]

Execute a command on this machine

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • log_show (bool) – Whether documentation backends should include this command
  • log_show_stdout (bool) – Whether documentation backends should include the stdout of this command
Returns:

A tuple of the return code and the output (stdout and stderr are merged)

Return type:

tuple[int, str]

exec0(command: str, **kwargs: bool) → str

Execute a command and expect it to return with 0

Parameters:
  • command (str) – The command to be executed, no newline at the end
  • kwargs – Passed through to Machine.exec
Returns:

The output (stdout and stderr are merged)

Return type:

str

powercycle() → None

Powercycle the board

unique_machine_name

Unique name of this machine, "board-dummy-<boardshell-name>"

Utils

Configuration

class tbot.config.Config[source]

A TBot configuration

Access configuaration items by using a . separated key-path, eg:

hooks = cfg["uboot.test.hooks"]

By default, this raises an exception if the value was not found. You can supply a default value that will be returned if the value was not found instead:

has_venv = cfg["uboot.test.has_venv", True]

The configuration is available as tb.config in all testcases.

exception tbot.config.ConfigAssignException[source]

An error while writing a config value

exception tbot.config.InvalidConfigException[source]

The configuration provided is not valid for this test

TBot logging facilities

class tbot.log.LogStdoutHandler(dct: typing.Dict[str, typing.Any], verbosity: tbot.log.Verbosity, custom_dash: typing.Union[str, NoneType]) → None[source]

Handler for writing to stdout and dealing with a logevent after it’s creation. You should not need to instanciate this object yourself, use tbot.log.event().

Variables:
  • dct – The log event’s dictionary, you can add additional things
  • key – Key in the dictionary that output given to .print() should be appended to.
  • prefix – A custom prefix that will be added in front of continuation lines.
print(msg: str) → None[source]

Print some text to stdout provided the verbosity is high enough. Also, add the text to the dict in case a key was set.

Parameters:msg (str) – The text
reset_verbosity(new_verbosity: tbot.log.Verbosity) → None[source]

Change the verbosity of this log event

Parameters:new_verbosity (Verbosity) – The new verbosity
class tbot.log.Verbosity[source]

Logger verbosity level

tbot.log.check_log() → None[source]

Check whether the log has been initialized and throw an exception otherwise.

tbot.log.debug(msg: str) → tbot.log.LogStdoutHandler[source]

Print a debug message

Parameters:msg (str) – The message
Returns:A handler for the created log event
Return type:LogStdoutHandler
tbot.log.doc(text: str) → tbot.log.LogStdoutHandler[source]

Add a log event that contains text for the documentation generator. text should be formatted in Markdown.

Parameters:text (str) – The documentation fragment
Returns:A handler for the created log event
Return type:LogStdoutHandler
tbot.log.doc_appendix(title: str, text: str) → tbot.log.LogStdoutHandler[source]

Add a log event that contains an appendix for the documentation generator. text should be formatted in Markdown.

Parameters:
  • title (str) – The appendix’s title
  • text (str) – The appendix’s body
Returns:

A handler for the created log event

Return type:

LogStdoutHandler

tbot.log.error(msg: str) → tbot.log.LogStdoutHandler[source]

Print an error message

Parameters:msg (str) – The message
Returns:A handler for the created log event
Return type:LogStdoutHandler
tbot.log.event(ty: typing.List[str], *, msg: typing.Union[str, NoneType] = None, verbosity: tbot.log.Verbosity = <Verbosity.INFO: 2>, dct: typing.Union[typing.Dict[str, typing.Any], NoneType] = None, custom_dash: typing.Union[str, NoneType] = None, fake: bool = False) → tbot.log.LogStdoutHandler[source]

Create a new log event

Parameters:
  • ty (list[str]) – The type of this log event
  • msg (str) – An optional message intended for being printed on the screen
  • verbosity (Verbosity) – Optional verbosity of this event (defaults to INFO)
  • dct (dict) – A dictionary of payload for this logevent. Can’t contain keys named "type", "time", "message", or "verbosity".
  • custom_dash (str) – Different prefix for the message when printed onscreen
  • fake (bool) – Whether this is just a fake event that won’t be logged
Returns:

A handler for the created log event

Return type:

LogStdoutHandler

tbot.log.flush_log() → None[source]

Write the log file

tbot.log.has_color(seq: str) → str[source]

Check color support and return the escape sequence for this color code if enabled.

Parameters:seq (str) – The color code, eg "1;31"
Return type:str
tbot.log.has_unicode(with_unicode: str, without_unicode: str) → str[source]

Check whether the terminal supports unicode, if it does, returns the with_unicode string, if it doesn’t, returns the without_unicode string.

Parameters:
  • with_unicode (str) – String to be returned, if the terminal does support unicode
  • without_unicode (str) – String to be returned, if the terminal does not support unicode
Return type:

str

tbot.log.init_log(filename: typing.Union[pathlib.Path, str], verbosity: tbot.log.Verbosity = <Verbosity.INFO: 2>) → None[source]

Initialize the logger

Parameters:
  • filename (pathlib.Path or str) – The file the log should be written to (in json format)
  • verbosity (Verbosity) – The minimun verbosity for messages that are printed to stdout
tbot.log.message(msg: str, verbosity: tbot.log.Verbosity = <Verbosity.INFO: 2>) → tbot.log.LogStdoutHandler[source]

Print a message

Parameters:
  • msg (str) – The message
  • verbosity (Verbosity) – Optional verbosity for this message
Returns:

A handler for the created log event

Return type:

LogStdoutHandler

tbot.log.oververbose(msg: str) → tbot.log.LogStdoutHandler[source]

Log a “oververbose” message, this is intended for very rarely needed debug output (just run TBot with this verbosity and see for yourself …)

Will not create a new log event.

Parameters:msg (str) – The message
Returns:A handler for the message
Return type:LogStdoutHandler
tbot.log.set_layer(layer: int) → None[source]

Set the call graph depth. You should never need to call this yourself.

tbot.log.warning(msg: str) → tbot.log.LogStdoutHandler[source]

Print a warning message

Parameters:msg (str) – The message
Returns:A handler for the created log event
Return type:LogStdoutHandler

TBot log events

tbot.log_events.exception(name: str, trace: str) → tbot.log.LogStdoutHandler[source]

Log event for exceptions

Parameters:
  • name (str) – Name of the exception
  • trace (str) – Traceback of the exception
Returns:

A handler for the created log event

Return type:

LogStdoutHandler

tbot.log_events.shell_command(*, machine: typing.List[str], command: str, show: bool, show_stdout: bool) → tbot.log.LogStdoutHandler[source]

Log event for the execution of shell commands

Add output of the command by calling the print method of the event handler. When the command is done, set the exit code.

Example:

handler = tbot.log_events.shell_command(
    machine=["labhost", "env"],
    command="echo Hello World",
    show=True,
    show_stdout=True,
)

# Print the output of the command
handler.print("Hello World\n")

# Set exit code
handler.dct["exit_code"] = 0
Parameters:
  • machine (list[str]) – Unique name of the machine as a list
  • command (str) – The command that was executed itself
  • show (bool) – Whether this command should be shown in documentation
  • show_stdout (bool) – Whether this commands output should be shown in documentation
Returns:

A handler for the created log event

Return type:

LogStdoutHandler

tbot.log_events.tbot_done(success: bool) → tbot.log.LogStdoutHandler[source]

Log event for TBot being done with running testcases

Parameters:success (bool) – Whether this run of TBot was successful
Returns:A handler for the created log event
Return type:LogStdoutHandler
tbot.log_events.testcase_begin(name: str) → tbot.log.LogStdoutHandler[source]

Log event for when a testcase is called

Parameters:name (str) – Name of the testcase
Returns:A handler for the created log event
Return type:LogStdoutHandler
tbot.log_events.testcase_end(name: str, duration: float, success: bool = True, fail_ok: bool = False) → tbot.log.LogStdoutHandler[source]

Log event for when a testcase is done

Parameters:
  • name (str) – Name of the testcase
  • duration (float) – Duration of the testcase’s execution in seconds
  • success (bool) – Whether the testcase was successful
  • fail_ok (bool) – Whether a failure is acceptable for this testcase
Returns:

A handler for the created log event

Return type:

LogStdoutHandler

Tescase collector

tbot.testcase_collector.get_testcases(paths: typing.Union[typing.List[str], typing.List[pathlib.Path], NoneType] = None) → typing.Dict[str, typing.Callable][source]

Collect all testcases from the directories specified in paths

Parameters:paths – List of directories to search
Returns:Collection of testcases
tbot.testcase_collector.testcase(f: F) → F[source]

Decorator for testcases

Utilities for shell interaction

exception tbot.machine.shell_utils.InvalidChannelState[source]

An invalid channel state

exception tbot.machine.shell_utils.InvalidCommand[source]

An invalid channel state

tbot.machine.shell_utils.command_and_retval(chan: paramiko.channel.Channel, prompt: str, command: str, stdout_handler: typing.Union[tbot.log.LogStdoutHandler, NoneType] = None) → typing.Tuple[int, str][source]

Execute a command and return it’s output and return value

Parameters:
Returns:

The return-code and output of the command

Return type:

tuple[int, str]

tbot.machine.shell_utils.exec_command(chan: paramiko.channel.Channel, prompt: str, command: str, stdout_handler: typing.Union[tbot.log.LogStdoutHandler, NoneType] = None) → str[source]

Execute a command and return it’s output

Parameters:
Returns:

The output of the command

Return type:

str

tbot.machine.shell_utils.read_to_prompt(chan: paramiko.channel.Channel, prompt: str, stdout_handler: typing.Union[tbot.log.LogStdoutHandler, NoneType] = None, prompt_regex: bool = False) → str[source]

Read until the shell waits for further input

Parameters:
  • chan (paramiko.channel.Channel) – Channel to read from
  • prompt (str) – Prompt to be waited for
  • stdout_handler (tbot.log.LogStdoutHandler) – Optional stdout handler to write output lines to
  • prompt_regex (bool) – Wether the prompt string is to be interpreted as a regular expression (read_to_prompt will add a $ to the end of your expression to ensure it only matches the end of the output)
Returns:

The read string (including the prompt)

Return type:

str

tbot.machine.shell_utils.setup_channel(chan: paramiko.channel.Channel, prompt: str) → None[source]

Setup a paramiko channel

Parameters:
Returns:

Nothing

Return type:

None

Machine Manager

class tbot.machine.machine.MachineManager(tb: tbot.TBot, conn: typing.Union[paramiko.client.SSHClient, NoneType] = None) → None[source]

A container to manage the list of available machines

clear() → None. Remove all items from D.
copy() → a shallow copy of D
fromkeys()

Returns a new dict with keys from iterable and values equal to value.

get(k[, d]) → D[k] if k in D, else d. d defaults to None.
items() → a set-like object providing a view on D's items
keys() → a set-like object providing a view on D's keys
pop(k[, d]) → v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised

popitem() → (k, v), remove and return some (key, value) pair as a

2-tuple; but raise KeyError if D is empty.

setdefault(k[, d]) → D.get(k,d), also set D[k]=d if k not in D
update([E, ]**F) → None. Update D from dict/iterable E and F.

If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

values() → an object providing a view on D's values