Skip to content
Tags give the ability to mark specific points in history as being important
  • v0.10.6
    3b45a7f3 · Prepare 0.10.6 ·
    Version 0.10.6
  • v0.10.5
    35447bad · Prepare 0.10.5 ·
    Version 0.10.5
  • v0.10.4
    bd1f9ffd · Prepare 0.10.4 ·
    Version 0.10.4
  • v0.10.3
    97f81b7c · Prepare 0.10.3 ·
    Version 0.10.3
  • v0.10.2
    843f8351 · Prepare 0.10.2 ·
    Version 0.10.2
  • v0.10.1
    0d4cbadb · Prepare 0.10.1 ·
    Version 0.10.1
  • v0.10.0
    54188b65 · Prepare 0.10.0 ·
    Version 0.10.0
  • v0.9.6
    41fd03e0 · Prepare 0.9.6 ·
    Version 0.9.6
  • v0.9.5
    dd9d2751 · Prepare 0.9.5 ·
    Version 0.9.5
  • v0.9.4
    fef839e3 · Prepare 0.9.4 ·
    Version 0.9.4
  • v0.9.3
    58a22bb4 · Prepare 0.9.3 ·
    Version 0.9.3
  • v0.9.2
    a1c148db · Prepare 0.9.2 ·
    Version 0.9.2
    == Added ==
    - Added a new `strip_ansi_escapes()` utility in `tbot_contrib.utils`
      which can be used to remove e.g. color escape codes from command
    - Added a `hashcmp()` utility in `tbot_contrib.utils` to compare the
      hashsum of two files (which may be located on different machines).
    - Added the `py.typed` marker for type-checkers (see PEP 561).
    == Fixed ==
    - Fixed the order of instance teardown in `keep_alive` contexts.  This
      fixes any kinds of problems due to wrong teardown order of dependent
      machines (e.g.  lab-host torn down before a board machine).
    - Fixed selftests failing due to deprecation of `ssh-rsa` algorithm.
    - Fixed `find_ip_address()` not working when a local address is passed
      as the `route_target`.
  • v0.9.1
    3a3269b3 · Prepare 0.9.1 ·
    Version 0.9.1
    == Added ==
    - Added a mechanism for "locking" connections to certain machines.  This can be
      used, for example, to ensure exlusive access to a certain board.  See
      `tbot_contrib.locking` for details.
    - `Path.rmdir()` and `Path.unlink()`: Methods to conveniently delete an empty
      directory, a symlink, or a file from a host's filesystem.
    - `Path.mkdir()`: Method to conveniently create a directory on the respective
    - `Path.at_host(host)`:  A method to safely convert a tbot-path into a plain
      string.  The `host` parameter is used to check that the `Path` is actually
      meant for the expected host.  Any uses of the (unofficial) `_local_str()`
      method should be replaced by `at_host()` as the former will be removed soon.
    - New classes `AppendStdout`, `AppendStderr`, and `AppendBoth` in
      `machine.linux` allow to append command output to files in `exec()` and
      `exec0()` methods.
    - Added a feature to the `Context` to allow reconfiguring a context temporarily
      (`Context.reconfigure()`).  This is useful to e.g. enable `keep_alive` mode
      for certain tests.
    == Changed ==
    - Warnings emitted due to problems when parsing the SSH config now include
      hints about the actual problem.
    - `linux.Path` no longer inherits from `pathlib.PurePosixPath`.  This fixes
      a number of long standing oddities where certain methods would not function
      correctly.  All API from `PurePosixPath` has been reimplemented in
      `linux.Path` explictly, now with the proper behavior.
    == Fixed ==
    - Fixed the `PyserialConnector` not working properly with tbot contexts.
    - Fixed `linux.Background` not properly redirecting stderr output.
  • v0.9.0
    6484dc62 · Prepare 0.9.0 ·
    Version 0.9.0
    == Added ==
    - Added the **Context** API for much easier and more flexible machine
      management.  Please read the [Context API][context-api] documentation for an
      introduction and migration guide.  **Note**: For now the old `tbot.selectable`
      API still exists and will be compatible both ways with the new API.  It will,
      however, slowly be phased out in the future.
    - Warning about incorrect build-host configuration when running `uboot_testpy`
    - Added support for SSH connection multiplexing to `SSHConnector`.  You can
      enable it by adding `use_multiplexing = True` to your host config.
      Multiplexing can drastically speed up testcases which open many connections to
      the same host (see `ControlMaster` in `sshd_config(5)` for details).
    - Added two more types of machine initializers:
      - `PreConnectInitializer`: Runs before the connection is established.
      - `PostShellInitializer`: Runs after the shell is available (and thus can
        interact with it).
    == Changed ==
    - `LinuxShell.env()` can now be used to query `$!` (last background job PID) and
      `$$` (current shell PID) special environment  variables (using `m.env("!")`
      and `m.env("$")`).
    - Added some more specific exception types and started using them where
      appropriate.  This effort is by far not over yet, though ...
    - The `linux.Background` special token is now more safe to use as it prevents
      console clobbering as good as it can.  You can manually redirect command
      output to files using a new call syntax.  See `Background` documentation
      for details.
    - `paramiko` is now an optional dependency.  tbot works just fine without
      paramiko, but if it is installed, the `ParamikoConnector` becomes available.
    - Switched to `pytest` for tbot's selftests.
    == Fixed ==
    - Call `olddefconfig` before attempting to build U-Boot.  This prevents kconfig
      from attempting to interactively query new config settings.
    - Fixed a rare timing-dependent bash/ash initialization deadlock.
    - Fixed `selftest_tc` failing if user has no git identity set up.
    - Fixed documentation silently building without version information if
      `git describe` fails.
    - Fixed tbot configuring an overly narrow terminal in some cases, leading to
      weird looking output (now the minimum is 80 chars wide).
    - Fixed `Path.write_text()`/`Path.write_bytes()` hanging when an error occurs
      and the channel receives data very slowly.
  • v0.8.3
    1e4eea44 · Prepare 0.8.3 ·
    Version 0.8.3
    == Added ==
    - Added `ensure_sd_unit()` testcase/util-function which starts systemd
      services if not yet running.
    - `tbot.error` module as a central place for defining all exception types.
    - Added a `PyserialConnector` to connect to a serial port using PySerial.
    - super-verbose mode (`-vvv`) now prefixes each output line with a channel
      identifier to help separate what data came from which channel.
    - Added a `Channel.read_until_timeout()` method for reading all data until
      a timeout is reached (or an Exception is thrown).
    - Added `find_ip_address()` testcase/util-function to discover the IP
      address of a machine.
    - One can now pass a custom line-ending to `Channel.readline()` incase the
      remote does not behave properly and send `\r\n` for every line.
    - Added a `Channel.add_death_string()` method which is like
      `.with_death_string()` but not a context-manager.  The death string is
      added for the entire lifetime of the channel with this new method.
    == Changed ==
    - tbot now prints all passed flags on start (and thus also stores this
      info in the log-file).
    - The `\e[K` is passed through to make output from programs like
      ninja-build prettier.
    == Fixed ==
    - Fixed an issue where the path returned by `mach.workdir` would be
      associated with a wrong host machine.
    - Fixed bash completions for `@args` not properly dealing with
    - Fixed `login_delay` for board-linux not behaving as documented and in
      some circumstances leading to a login without waiting.
  • v0.8.2
    4a628227 · Release 0.8.2 ·
    Version 0.8.2
    == Added ==
    - Added `` to run a command and interact with its stdio.
    - `Path.write_text()`, `Path.read_text()`, `Path.write_bytes()`, and
      `Path.read_bytes()`: Methods to easily manipulate remote files.
    - Added integration for U-Boot's test/py test-framework.  See the
      ``uboot_testpy`` testcase fore more.
    - A connector for connection to a [conserver](
      based serial console: `tbot_contrib.connector.conserver`
    - Testcases for timing the duration of an operation (`tbot_contrib.timing`).
    - A testcase to deploy an `swu`-file to
      [SWUpdate]( (`tbot_contrib.swupdate`).
    - Machines now implement `==` and `hash()`.  A machine which was cloned
      from another machine has the same hash, i.e. they can be treated as equal.
    - Added a U-Boot smoke-test: `` or `uboot_smoke_test`
    - Added a `DistroToolchain` class to easily allow using pre-installed
      toolchains with tbot.
    - Added a Workdir which lives in ``$XDG_DATA_HOME`` and one living in
      ``$XDG_RUNTIME_DIR`` (``Workdir.xdg_home()`` and ``Workdir.xdg_runtime()``).
    - You can now specify the U-Boot revision to checkout:
      ``tbot uboot_checkout -prev=\"v2020.01\"``
    - A ``boot_timeout`` parameter was added to U-Boot machines to limit the maximum
      time, U-Boot is allowed to take during boot.
    - Testcases for interacting with GPIOs (`tbot_contrib.gpio`).
    - ``tbot.Re``: A convenience wrapper around ``re.compile``.  Whereever
      regex-patterns are needed (e.g. in channel-interaction), you can now use
      `tbot.Re` instead of `re.compile("...".encode())`.
    - A `Channel.readline()` and a `Channel.expect()` method to mimic pexpect.
    == Changed ==
    - The default workdir for Linux shells is no longer `/tmp/tbot-wd`.  It is
      now `$XDG_DATA_HOME/tbot` (usually `~/.local/share/tbot`).
    - `UBootBuilder` now points to the new U-Boot upstream
      (<>) by default.
    - Fixed `linux.Bash`'s `.env()` implementation unnecessarily querying the
      variable after setting it.
    - ``selftest`` now uses a dedicated machine class which does not clobber
      the default workdir and instead stores data in a temporary directory.
    == Fixed ==
    - Fixed tbot sometimes not displaying a message before entering
      interactive mode, thus leaving the user clueless what escape-sequence to
      use to exit.
    - Fixed `linux.Bash`, `linux.Ash`, and `board.UBootShell` allowing some
      bad characters in command invocations which would mess up the shell's
    - Fixed `tbot.flags` only being set _after_ loading the testcases which
      could lead to weird inconsistency errors.
    - Fixed ``Channel.sendcontrol()`` not actually allowing all C0 control
  • v0.8.1
    5b0378fd · Release 0.8.1 ·
    Version 0.8.1
    == Added ==
    - Added `LinuxShell.glob()` method for easily using shell globs.
    - Added parameters to `LinuxShell.subshell()` which can be used to spawn
      custom subshells.
    - Added `linux.RedirBoth` to redirect both stdout and stderr to the same
    - Added `UBootShell.ram_base` property to learn the RAM base address in
    - Added a write blacklist to channels.  This feature can be used to
      disallow tests sending certain control characters.
    - Added a `do_build()` step to `UBootBuilder` which can be used to
      customize the command used for building U-Boot.
    - Empty `tbot_contrib` module for the future :)
    == Changed ==
    - Made `SSHConnector` based machine cloneable (if the underlying host is
    - Made `tbot.testcase` also work as a context-manager.  This can be used
      to define 'sub-tests' in a function.  Example:
      with tbot.testcase("my_sub_testcase"):
    == Fixed ==
    - Fixed U-Boot and board-Linux not saving the bootlog to the log-event.
    - Fixed tbot happily printing special characters as part of a command which was
      sent (in the log).
    - Fixed selftests failing in some rare circumstances because a subprocess
      is not properly terminated or when bash is slow.
    - Removed use of the deprecated `time.clock()` function.
    - Properly check stdout encoding.
    - Fixed `read_iter` sometimes passing negative timeout values to the
      underlying channel IO.
    - Fixed tbot hanging on zero-byte `Channel.send()` call.
    - Fixed `lnx.env()` behaving incorrectly when an environment variable has
      a value which looks like an `echo`-option.
    - Fixed a bug caused by passing `"\n^"` as a parameter (bash interprets this as
      a kind of history expansion).
    - Fixed `UBootShell` not properly escaping `\` and `'`.
    - Fixed `ub.env()` failing on environment variables with weird values.
  • v0.8.0
    c3e0a012 · Release 0.8.0 ·
    Version 0.8.0
    The machine interface was completely overhauled.  Please read the [migration
    guide]( for more info.
    == Added ==
    - `@tbot.with_lab`, `@tbot.with_uboot`, and `@tbot.with_linux` decorators to
      make writing testcase much simpler
    - `linux.RedirStdout(f)` & `linux.RedirStderr(f)`: Redirect stdout and stderr symbols
    - `Machine.init()` hook to call custom code after the machine was initialized.
      This can be used, for example, to init network manually in U-Boot.
    - `` testcase
    - `tbot.skip()`: Skip a testcase
    - `Machine.clone()`: Attempt creating a copy of a machine.  The two copies
      allow parallel interaction with the same host.
    == Changed ==
    - `linux.BuildMachine` is now a mixin called `linux.Builder`
    - `linux.LabHost` is now a mixin called `linux.Lab`
    - `linux.LinuxMachine` should be replaced by `linux.LinuxShell`
    - `LabHost.new_channel()` was removed in favor of `LinuxShell.open_channel()`.
      `open_channel()` consumes the machine it is called on which means the
      equivalent to `new_channel()` now is:
          with mach.clone() as cl:
              chan = cl.open_channel("telnet", "")
    == Removed ==
    - `exec0(stdout=f)`: Redirection should be done using `RedirStdout`.
    - `linux.Env(var)`: Environment-Variable substitution is hard to control.  It
      is much easier to just use `mach.env(var)`.
    == Fixed ==
    - `Path.__fspath__()` erroneously returning a result, even though the contract
      that is assumed with this method cannot be upheld by tbot.
  • v0.7.1
    cb0af554 · Release 0.7.1 ·
    Version 0.7.1
    == Added ==
    - `tbot.acquire_local()`: Quick access to a localhost machine
    - `LinuxMachine.home`: Path to the current user's home
    - `LocalLabHost.tbotdir`: tbot's current working directory on the localhost (either
      from where you ran `tbot` or the path given with `-C`)
    - ``:  Testcases for modifying a kernel config file
    - `login_delay`: Time to wait before logging in on the board.  This should
      allow working with boards that clobber the console a lot during boot.
    == Changed ==
    - Unknown parameters are now ignored if running multiple testcases so
      you can specify parameters that are just relevant to a single one.
    - `SSHMachine`s now use `NoneAuthenticator` by default.
    == Fixed ==
    - `selftest`s sometimes failing if dropbear does not start fast enough
    - `SSHMachine`s using the local user's home dir instead of the one on the
    - Local channels now correctly end the session which fixes weird bugs like
      picocom not being able to reaquire the shell.
  • v0.7.0
    04c95dec · Release 0.7.0 ·
    Version 0.7.0
    == Added ==
    - Read commandline arguments from files:  You can now specify a file using
      @filename and each line from that file will be interpreted as a commandline
    - A man-page: doc/tbot.1!
    - tbot.named_testcase: Define testcases with a different name in log-files
      than the function name.  The motivation is to reduce name ambiguity
      (e.g. `` and `` would both be called `build` in the
      log).  This also affects the testcases name when calling it from the
      commandline (you have to use the new name).
    == Changed ==
    - The U-Boot build testcase has been completely rewritten.  You will need to
      adapt you board config to work with the new version:
      * The build-info no longer exists, instead you define a `UBootBuilder`.  Take
        a look at the docs to see available options.
      * The build attribute of your U-Boot machine must now be an **instance** of
        your `UBootBuilder`, **not** the class itself.
          Example of the new config:
          from tbot.machine import board
          from import uboot
          class MyUBootBuilder(uboot.UBootBuilder):
              name = "my-builder"
              defconfig = "my_defconfig"
              toolchain = "generic-armv7a-hf"
          class MyUBootMachine(board.UBootMachine):
              build = MyUBootBuilder()
    == Fixed ==
    - `boot_to_shell` is no longer a public method of BoardLinux machines.