Automation API: launching and controlling UDB

The Automation API provides the udb_launcher.UdbLauncher class to help with configuring, launching, and managing UDB.

Using the undo automate program

To execute scripts using the UdbLauncher class, you need to use the undo automate program, which makes sure that the Python environment is set up correctly to execute Undo code.

For example, it’s possible to write a my_script.py file like this:

from undodb.udb_launcher import UdbLauncher
print 'UdbLauncher imported successfully!'

And then execute it with:

$ undo automate my_script.py
UdbLauncher imported successfully!

This assumes that undo is in the search path: that is, the installation directory of UDB was added to the $PATH environment variable. If this is not the case, the full path needs to be used:

$ /path/to/undodb/undo automate my_script.py
UdbLauncher imported successfully!

If undo is in the search path, it’s possible to make the script executable (with chmod +x my_script.py) and use a shebang line to execute it directly:

#! /usr/bin/env -S undo automate
from undodb.udb_launcher import UdbLauncher
print 'UdbLauncher imported successfully!'

Then:

$ ./my_script.py
UdbLauncher imported successfully!

Note

This uses the -S option to env, which was added in GNU coreutils version 8.30. On systems with older versions of coreutils, you will need to ensure that udb-automate is in the search path, and execute it via the shebang line instead:

#! /usr/bin/env udb-automate
from undodb.udb_launcher import UdbLauncher
print 'UdbLauncher imported successfully!'

The udb_launcher module

class udb_launcher.PreparedRunInformation(...)

The information (command line, environment, etc.) needed to run UDB from a script.

Usually you only need to use UdbLauncher.run_debugger() which deals with the startup automatically. In cases when you need more control of the UDB process, use UdbLauncher.prepare_run_information().

Do not instantiate this class directly.

close(exc_type: Optional[type[BaseException]] = None, exc_value: Optional[BaseException] = None, traceback: Optional[Any] = None) Any

Clears up the resources related to the UDB run.

If this object is used in a with block, then this method is called automatically when exiting the block.

property env: dict[str, str]

The environment (as a dictionary) to use to run the debugger.

This is based on os.environ plus additions to configure the debugger correctly.

You can use this property only after you have called the prepare method or when using this object in a with block.

Type

dict from str to str

property final_args: list[str]

The arguments to pass to the debugger.

Unlike args, this is the finalized arguments that are going to be used to actually run UDB.

Type

list of str

property result_data: dict[Any, Any]

The dictionary of data passed back from the extensions scripts.

You should call this property only after the debugger finished running or the data won’t be available yet.

Type

dict

udb_launcher.REDIRECTION_COLLECT = REDIRECTION_COLLECT

Value that can be passed to UdbLauncher.run_debugger() to collect the output in a variable.

See UdbLauncher.run_debugger() for more details.

udb_launcher.REDIRECTION_DISABLED = REDIRECTION_DISABLED

Value that can be passed to UdbLauncher.run_debugger() to not redirect the output.

See UdbLauncher.run_debugger() for more details.

udb_launcher.REDIRECTION_DISCARD = REDIRECTION_DISCARD

Value that can be passed to UdbLauncher.run_debugger() to discard the output.

See UdbLauncher.run_debugger() for more details.

udb_launcher.REDIRECTION_SAME_AS_DEBUGGER = REDIRECTION_SAME_AS_DEBUGGER

Value that can be passed as the redirect_program_output argument to UdbLauncher.run_debugger() to make the output of the debugged program be redirected (or not redirected) to the same destination as the output of the debugger itself.

See UdbLauncher.run_debugger() for more details.

class udb_launcher.UdbLauncher

Class used to configure arguments to UDB and launch it.

add_command(command: str) None

Adds a UDB command to run at startup.

This is equivalent to using the -iex option on the udb command line.

For instance, to set a breakpoint on the function my_func and run the program at startup:

launcher.add_command('break my_func')
launcher.add_command('run')
Parameters

command (str) – The command to run.

add_extension(module_name: str) None

Adds an extension script to be loaded inside the running UDB instance.

Parameters

module_name (str) – The name of the module to load in the same form as you would pass it to import.

For instance:

  • launcher.add_extension('foo') looks for a foo module, e.g. a foo.py file in the current directory.

  • launcher.add_extension('mypackage.foo') looks for a foo module in the mypackage package, e.g. a mypackage/foo.py file.

  • launcher.add_extension('.foo') looks for a foo module in the current package, e.g. a foo.py file in the current directory.

Once UDB is started using the run_debugger() method, it will load all the specified scripts (in the order they were added).

Once the scripts are loaded, UDB will call a run function (accepting no arguments) on each module (if available). For clarity, you should put your logic into the run function rather than at module level.

property args: list[str]

The arguments configured so far for UDB.

Note that these arguments are not enough to successfully run UDB as more need to be added just before running it. If you need to run UDB without using the run_debugger() method, use prepare_run_information() to get the arguments (and other information) to run UDB.

Type

list of str

prepare_run_information() udb_launcher.PreparedRunInformation

Makes a PreparedRunInformation with all the information needed to run UDB.

Note that generally using run_debugger() is easier but, if you need to run the debugger with more control over the way it’s launched, you can do something like this:

launcher = udb_launcher.UdbLauncher()
[...]
with launcher.prepare_run_information() as prepared_info:
    subprocess.call(prepared_info.final_args, env=prepared_info.env)

print('Result data from extensions: {}'.format(prepared_info.result_data))
Returns

An object with the information needed to run UDB (like command line arguments and environment variables).

Return type

PreparedRunInformation

property program_args: list[str] | None

The arguments to use to start a program.

This is equivalent to using --args on the udb command line.

If no arguments were specified, None is returned.

Type

list of str or None

property recording_file: str | None

The recording file to load in UndoDb.

Type

str or None

property run_data: dict[Any, Any]

A dictionary with data that automation scripts can pass to extensions.

Type

dict

run_debugger(redirect_debugger_output=REDIRECTION_DISABLED, redirect_program_output=REDIRECTION_SAME_AS_DEBUGGER) udb_launcher._RunResult

Runs UDB with the previously configured arguments and waits for debugger operations to complete.

Output produced by the debugger and any sub-processes may be redirected; this can be controlled using the redirect_debugger_output and redirect_program_output arguments, see below for more details.

Note that both redirect_debugger_output and redirect_program_output are keyword-only arguments.

While UDB is running, output can come from three different sources:

  • The debugger itself, including your Python code running inside it (see add_extension).

  • The debugged program or recording.

  • Python code, including your extensions, running inside a debugger_io.redirect_to_launcher_output context manager (see later for details).

This function allows powerful redirection of the output coming from different sources, allowing your automation scripts to only display to the user what is useful to display.

redirect_debugger_output controls the output coming from the debugger itself and can be:

  • REDIRECTION_DISABLED (default): No redirection, the output goes to standard output.

  • REDIRECTION_COLLECT: The output is collected in memory and is accessible through the output member of the return value of this function.

  • REDIRECTION_DISCARD: The output is discarded.

  • A file-like object (like a file opened with open() or a io.BytesIO) into which to redirect the output. The file needs to accepts writes of bytes, for instance a file opened with open(..., "wb").

  • A numeric file descriptor to which to redirect the output.

Your Python code running inside UDB can still write to the standard output of the launcher program, if needed, by using debugger_io.redirect_to_launcher_output() which skips any redirection. This is useful, for instance, when you want to discard most debugger’s output but still print some information on standard output.

As with redirect_debugger_output, the redirect_program_output controls the output coming from the program or recording loaded in the debugger. On top of the values already documented above for redirect_debugger_output, this parameter also accepts REDIRECTION_SAME_AS_DEBUGGER (the default) which redirects the program output together with the debugger output.

Parameters
  • redirect_debugger_output – Where to redirect the output of the debugger to. By default, it’s not redirected (REDIRECTION_DISABLED).

  • redirect_program_output – Where to redirect the output of the program to. By default, it’s redirected to go to the same destination as the debugger output (REDIRECTION_SAME_AS_DEBUGGER).

Returns

An object which contains information about the UDB run.

It has the following members:

  • exit_code: The exit code of UDB (0 means success).

  • result_data: A dictionary with data potentially filled by the extension scripts. This is similar to how UdbLauncher.run_data is used to pass data into the extension scripts.

  • output: If redirect_debugger_output or redirect_program_output are set to REDIRECTION_COLLECT, then it contains the collected output; otherwise it’s set to None.