tmt package

Subpackages

Submodules

tmt.base module

Base Metadata Classes

class tmt.base.Clean(*, parent: Common | None = None, name: str | None = None, workdir: Literal[True] | Path | None = None, workdir_root: Path | None = None, cli_invocation: tmt.cli.CliInvocation | None = None, logger: Logger)

Bases: Common

A class for cleaning up workdirs, guests or images

Initialize name and relation with the parent object

Always skip to initialize the work tree.

cli_invocation: 'tmt.cli.CliInvocation' | None = None
guests(run_ids: tuple[str, ...], keep: int | None) bool

Clean guests of runs

images() bool

Clean images of provision plugins

runs(id_: tuple[str, ...], keep: int | None) bool

Clean workdirs of runs

class tmt.base.Core(*, node: Tree, tree: Tree | None = None, parent: Common | None = None, logger: Logger, **kwargs: Any)

Bases: ValidateFmfMixin, LoadFmfKeysMixin, Common

General node object

Corresponds to given fmf.Tree node. Implements common Test, Plan and Story methods. Also defines L0 metadata and its manipulation.

Initialize the node

adjust: list[_RawAdjustRule] | None
property anchor_path: Path
author: list[str]
cli_invocation: 'tmt.cli.CliInvocation' | None = None
contact: list[str]
description: str | None = None
enabled: bool = True
property fmf_id: FmfId

Return full fmf identifier of the node

property fmf_root: Path | None
property fmf_sources: list[Path]
classmethod from_tree(tree: Tree) list[T]

Gather list of instances of this class in a given tree.

Helpful when looking for objects of a class derived from Core in a given tree, encapsulating the mapping between core classes and tree search methods.

Parameters:

tree – tree to search for objects.

property git_root: Path | None

Whether object contains specified link

id: str | None = None
lint_summary_exists() Iterator[tuple[LinterOutcome, str]]

C001: summary key should be set and should be reasonably long

lint_validate() Iterator[tuple[LinterOutcome, str]]

C000: fmf node should pass the schema validation

ls(summary: bool = False) None

List node

name_and_summary() str

Node name and optional summary

order: int = 50
classmethod store_cli_invocation(context: tmt.cli.Context | None, options: dict[str, Any] | None = None) tmt.cli.CliInvocation

Save provided command line context for future use

summary: str | None = None
tag: list[str]
tier: str | None = None

Return a clickable web link to the fmf metadata location

tmt.base.DEFAULT_ORDER = 50

The default order of any object.

class tmt.base.DependencyFile(type: str = 'file', pattern: list[str] = <factory>)

Bases: SpecBasedContainer[_RawDependencyFile, _RawDependencyFile], SerializableContainer, Exportable[DependencyFile]

VALID_KEYS: ClassVar[list[str]] = ['type', 'pattern']
classmethod from_spec(raw: _RawDependencyFile) DependencyFile

Convert from a specification file or from a CLI option

pattern: list[str]
to_dict() _RawDependencyFile

Return keys and values in the form of a dictionary

to_minimal_dict() _RawDependencyFile

Convert to a mapping with unset keys omitted

type: str = 'file'
static validate() tuple[bool, str]

Validate file dependency and return a human readable error

There is no way to check validity of type or pattern string at this time. Return a tuple (boolean, message) as the result of validation. The boolean specifies the validation result and the message the validation error. In case the file dependency is valid, return an empty string as the message.

class tmt.base.DependencyFmfId(fmf_root: Path | None = None, git_root: Path | None = None, default_branch: str | None = None, url: str | None = None, ref: str | None = None, path: Path | None = None, name: str | None = None, destination: Path | None = None, nick: str | None = None, type: str = 'library')

Bases: FmfId, SpecBasedContainer[_RawDependencyFmfId, _RawDependencyFmfId]

A fmf ID as a dependency.

Not a pure fmf ID though, the form accepted by require & co. allows several extra keys.

VALID_KEYS: ClassVar[list[str]] = ['url', 'ref', 'path', 'name', 'destination', 'nick', 'type']
destination: Path | None = None
classmethod from_spec(raw: _RawDependencyFmfId) DependencyFmfId

Convert from a specification file or from a CLI option

nick: str | None = None
to_dict() _RawDependencyFmfId

Return keys and values in the form of a dictionary

to_minimal_dict() _RawDependencyFmfId

Convert to a mapping with unset keys omitted

to_minimal_spec() _RawDependencyFmfId

Convert to specification, skip default values

to_spec() _RawDependencyFmfId

Convert to a form suitable for saving in a specification file

type: str = 'library'
class tmt.base.DependencySimple

Bases: str

A basic, simple dependency, usually a package

classmethod from_spec(spec: str) DependencySimple
to_minimal_spec() str
to_spec() str
class tmt.base.FmfId(fmf_root: tmt._compat.pathlib.Path | None = None, git_root: tmt._compat.pathlib.Path | None = None, default_branch: str | None = None, url: str | None = None, ref: str | None = None, path: tmt._compat.pathlib.Path | None = None, name: str | None = None)

Bases: SpecBasedContainer[_RawFmfId, _RawFmfId], SerializableContainer, Exportable[FmfId]

NONEXPORTABLE_KEYS: ClassVar[list[str]] = ['fmf_root', 'git_root', 'default_branch']

Keys that are present, might be set, but shall not be exported.

VALID_KEYS: ClassVar[list[str]] = ['url', 'ref', 'path', 'name']
default_branch: str | None = None
fmf_root: Path | None = None
classmethod from_spec(raw: _RawFmfId) FmfId

Convert from a specification file or from a CLI option

git_root: Path | None = None
name: str | None = None
path: Path | None = None
ref: str | None = None
to_dict() _RawFmfId

Return keys and values in the form of a dictionary

to_minimal_dict() _RawFmfId

Convert to a mapping with unset keys omitted

to_minimal_spec() _RawFmfId

Convert to specification, skip default values

to_spec() _RawFmfId

Convert to a form suitable for saving in a specification file

url: str | None = None
validate() tuple[bool, str]

Validate fmf id and return a human readable error

Return a tuple (boolean, message) as the result of validation. The boolean specifies the validation result and the message the validation error. In case the FMF id is valid, return an empty string as the message.

Bases: SpecBasedContainer[Any, dict[Literal[‘verifies’, ‘verified-by’, ‘implements’, ‘implemented-by’, ‘documents’, ‘documented-by’, ‘blocks’, ‘blocked-by’, ‘duplicates’, ‘duplicated-by’, ‘parent’, ‘child’, ‘relates’, ‘test-script’, ‘note’], str | _RawFmfId]]

An internal “link” as defined by tmt specification.

All links, after entering tmt internals, are converted from their raw representation into instances of this class.

[1] https://tmt.readthedocs.io/en/stable/spec/core.html#link

DEFAULT_RELATIONSHIP: ClassVar[Literal['verifies', 'verified-by', 'implements', 'implemented-by', 'documents', 'documented-by', 'blocks', 'blocked-by', 'duplicates', 'duplicated-by', 'parent', 'child', 'relates', 'test-script', 'note']] = 'relates'
classmethod from_spec(spec: str | _RawFmfId | dict[Literal['verifies', 'verified-by', 'implements', 'implemented-by', 'documents', 'documented-by', 'blocks', 'blocked-by', 'duplicates', 'duplicated-by', 'parent', 'child', 'relates', 'test-script', 'note'], str | _RawFmfId]) Link

Convert from a specification file or from a CLI option

Specification is described in [1], this constructor takes care of parsing it into a corresponding Link instance.

[1] https://tmt.readthedocs.io/en/stable/spec/core.html#link

note: str | None = None
relation: Literal['verifies', 'verified-by', 'implements', 'implemented-by', 'documents', 'documented-by', 'blocks', 'blocked-by', 'duplicates', 'duplicated-by', 'parent', 'child', 'relates', 'test-script', 'note']
target: str | FmfId
to_spec() dict[Literal['verifies', 'verified-by', 'implements', 'implemented-by', 'documents', 'documented-by', 'blocks', 'blocked-by', 'duplicates', 'duplicated-by', 'parent', 'child', 'relates', 'test-script', 'note'], str | _RawFmfId]

Convert to a form suitable for saving in a specification file

No matter what the original specification was, every link will generate the very same type of specification, the relation: target one.

Output of this method is fully compatible with specification, and when given to from_spec(), it shall create a Link instance with the same properties as the original one.

[1] https://tmt.readthedocs.io/en/stable/spec/core.html#link

class tmt.base.LinkNeedle(relation: str = '.*', target: str = '.*')

Bases: object

A container to use for searching links.

relation and target fields hold regular expressions that are to be searched for in the corresponding fields of Link instances.

classmethod from_spec(value: str) LinkNeedle

Convert from a specification file or from a CLI option

Specification is described in [1], this constructor takes care of parsing it into a corresponding LinkNeedle instance.

[1] https://tmt.readthedocs.io/en/stable/spec/plans.html#fmf

matches(link: Link) bool

Find out whether a given link matches this needle

relation: str = '.*'
target: str = '.*'

Bases: SpecBasedContainer[Any, list[dict[Literal[‘verifies’, ‘verified-by’, ‘implements’, ‘implemented-by’, ‘documents’, ‘documented-by’, ‘blocks’, ‘blocked-by’, ‘duplicates’, ‘duplicated-by’, ‘parent’, ‘child’, ‘relates’, ‘test-script’, ‘note’], str | _RawFmfId]]]

Collection of links in tests, plans and stories.

Provides abstraction over the whole collection of object’s links.

[1] https://tmt.readthedocs.io/en/stable/spec/core.html#link

Create a collection from raw link data

get(relation: Literal['verifies', 'verified-by', 'implements', 'implemented-by', 'documents', 'documented-by', 'blocks', 'blocked-by', 'duplicates', 'duplicated-by', 'parent', 'child', 'relates', 'test-script', 'note'] | None = None) list[Link]

Get links with given relation, all by default

Check whether this set of links contains a matching link.

If needle is left unspecified, method would take all links into account, as if the needle was match all possible links (.*:.*). Method would then answer the question “are there any links at all?”

Parameters:

needle – if set, only links matching needle are considered. If not set, method considers all present links.

Returns:

True if there are matching links, False otherwise.

show() None

Format a list of links with their relations

to_spec() list[dict[Literal['verifies', 'verified-by', 'implements', 'implemented-by', 'documents', 'documented-by', 'blocks', 'blocked-by', 'duplicates', 'duplicated-by', 'parent', 'child', 'relates', 'test-script', 'note'], str | _RawFmfId]]

Convert to a form suitable for saving in a specification file

No matter what the original specification was, every link will generate the very same type of specification, the relation: target one.

Output of this method is fully compatible with specification, and when used to instantiate Link() object, it shall create a collection of links with the same properties as the original one.

[1] https://tmt.readthedocs.io/en/stable/spec/core.html#link

class tmt.base.LintableCollection(objs: list[Core], *args: Any, **kwargs: Any)

Bases: Lintable[LintableCollection]

Linting rules applied to a collection of Tests, Plans or Stories

lint_no_duplicate_ids() Iterator[tuple[LinterOutcome, str]]

G001: no duplicate ids

print_header() None
class tmt.base.Plan(*, node: Tree, tree: Tree | None = None, run: Run | None = None, skip_validation: bool = False, raise_on_validation_error: bool = False, logger: Logger, **kwargs: Any)

Bases: Core, Exportable[Plan], Lintable[Plan]

Plan object (L2 Metadata)

Initialize the plan

cli_invocation: 'tmt.cli.CliInvocation' | None = None
context: FmfContext
static create(*, names: list[str], template: str, path: Path, force: bool = False, dry: bool | None = None, logger: Logger) None

Create a new plan

draw_test_serial_number(test: Test) int
static edit_template(raw_content: str) str

Edit the default template with custom values

property environment: Environment

Return combined environment from plan data, command line and original plan

gate: list[str]
go() None

Execute the plan

header() None

Show plan name and summary

Include one blank line to separate plans

import_plan() Plan | None

Import plan from a remote repository, return a Plan instance

property is_remote_plan_reference: bool

Check whether the plan is a remote plan reference

lint_discover_unknown_method() Iterator[tuple[LinterOutcome, str]]

P004: discover step methods must be known

lint_empty_env_files() Iterator[tuple[LinterOutcome, str]]

P008: environment files are not empty

lint_execute_not_defined() Iterator[tuple[LinterOutcome, str]]

P002: execute step must be defined with “how”

lint_execute_unknown_method() Iterator[tuple[LinterOutcome, str]]

P003: execute step methods must be known

lint_fmf_remote_ids_valid() Iterator[tuple[LinterOutcome, str]]

P005: remote fmf ids must be valid

lint_phases_have_guests() Iterator[tuple[LinterOutcome, str]]

P007: step phases require existing guests and roles

lint_unique_names() Iterator[tuple[LinterOutcome, str]]

P006: phases must have unique names

lint_unknown_keys() Iterator[tuple[LinterOutcome, str]]

P001: all keys are known

login: Login | None = None
static overview(tree: Tree) None

Show overview of available plans

property plan_environment_file: Path
prune() None

Remove all uninteresting files from the plan workdir

show() None

Show plan details

step_names(enabled_only: bool = True, skip: list[str] | None = None) Iterator[str]

Iterate over step names.

Parameters:
  • enabled_only – if set, only enabled steps would be listed.

  • skip – if step name is in this list, it would be skipped.

Yields:

step names.

steps(enabled_only: bool = True, skip: list[str] | None = None) Iterator[Step]

Iterate over steps.

Parameters:
  • enabled_only – if set, only enabled steps would be listed.

  • skip – if step name is in this list, it would be skipped.

Yields:

instance of tmt.step.Step, representing each step.

wake() None

Wake up all steps

class tmt.base.Run(*, id_: Path | None = None, tree: Tree | None = None, cli_invocation: tmt.cli.CliInvocation | None = None, parent: Common | None = None, workdir_root: Path | None = None, logger: Logger)

Bases: Common

Test run, a container of plans

Initialize tree, workdir and plans

cli_invocation: 'tmt.cli.CliInvocation' | None = None
property environment: Environment

Return environment combined from wake up and command line

finish() None

Check overall results, return appropriate exit code

follow() None

Periodically check for new lines in the log.

go() None

Go and do test steps for selected plans

load() None

Load list of selected plans and enabled steps

load_from_workdir() None

Load the run from its workdir, do not require the root in run.yaml to exist. Does not load the fmf tree.

Use only when the data in workdir is sufficient (e.g. tmt clean and status only require the steps to be loaded and their status).

property plans: list[Plan]

Test plans for execution

prepare_for_try(tree: Tree) None

Prepare the run for the try command

property runner: tmt.steps.provision.local.GuestLocal
save() None

Save list of selected plans and enabled steps

show_runner(logger: Logger) None

Log facts about the machine on which tmt runs

tree: Tree | None
class tmt.base.RunData(root: Optional[str], plans: Optional[list[str]], steps: list[str], remove: bool, environment: tmt.utils.Environment = <factory>)

Bases: SerializableContainer

environment: Environment
plans: list[str] | None
remove: bool
root: str | None
steps: list[str]
class tmt.base.Status(*, parent: CommonDerivedType | None = None, name: str | None = None, workdir: Literal[True] | Path | None = None, workdir_root: Path | None = None, relative_indent: int = 1, cli_invocation: tmt.cli.CliInvocation | None = None, logger: Logger, **kwargs: Any)

Bases: Common

Status of tmt work directories.

Initialize name and relation with the parent object

Prepare the workdir for provided id / directory path or generate a new workdir name if workdir=True given. Store command line context and options for future use if context is provided.

FIRST_COL_LEN = 11
LONGEST_STEP = 'provision'
cli_invocation: 'tmt.cli.CliInvocation' | None = None
static colorize_column(content: str) str

Add color to a status column

static get_overall_plan_status(plan: Plan) str

Examines the plan status (find the last done step)

classmethod pad_with_spaces(string: str) str

Append spaces to string to properly align the first column

plan_matches_filters(plan: Plan) bool

Check if the given plan matches filters from the command line

print_header() None

Print the header of the status table based on verbosity

print_plans_status(run: Run) None

Display the status of each plan of the given run

print_run_status(run: Run) None

Display the overall status of the run

print_verbose_status(run: Run) None

Display the status of each step of the given run

process_run(run: Run) None

Display the status of the given run based on verbosity

run_matches_filters(run: Run) bool

Check if the given run matches filters from the command line

show() None

Display the current status

class tmt.base.Story(*, node: Tree, tree: Tree | None = None, skip_validation: bool = False, raise_on_validation_error: bool = False, logger: Logger, **kwargs: Any)

Bases: Core, Exportable[Story], Lintable[Story]

User story object

Initialize the story

cli_invocation: 'tmt.cli.CliInvocation' | None = None
coverage(code: bool, test: bool, docs: bool) tuple[bool, bool, bool]

Show story coverage

static create(*, names: list[str], template: str, path: Path, force: bool = False, dry: bool | None = None, logger: Logger) None

Create a new story

property documented: list[Link]

Return links to relevant documentation

example: list[str]
classmethod from_tree(tree: Tree) list[Story]

Gather list of instances of this class in a given tree.

Helpful when looking for objects of a class derived from Core in a given tree, encapsulating the mapping between core classes and tree search methods.

Parameters:

tree – tree to search for objects.

property implemented: list[Link]

Return links to relevant source code

lint_story() Iterator[tuple[LinterOutcome, str]]

S002: story key must be defined

lint_unknown_keys() Iterator[tuple[LinterOutcome, str]]

S001: all keys are known

static overview(tree: Tree) None

Show overview of available stories

priority: StoryPriority | None = None
show() None

Show story details

property status: list[str]

Aggregate story status from implemented-, verified- and documented-by links

story: str | None = None
title: str | None = None
property verified: list[Link]

Return links to relevant test coverage

class tmt.base.StoryPriority(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

COULD_HAVE = 'could have'
MUST_HAVE = 'must have'
SHOULD_HAVE = 'should have'
WILL_NOT_HAVE = 'will not have'
class tmt.base.Test(*, node: Tree, tree: Tree | None = None, skip_validation: bool = False, raise_on_validation_error: bool = False, logger: Logger, **kwargs: Any)

Bases: Core, Exportable[Test], Lintable[Test]

Test object (L1 Metadata)

Initialize test data from an fmf node or a dictionary

The following two methods are supported:

Test(node)

check: list[Check]
cli_invocation: 'tmt.cli.CliInvocation' | None = None
component: list[str]
static create(*, names: list[str], template: str, path: Path, script: str | None = None, force: bool = False, dry: bool | None = None, logger: Logger) None

Create a new test

duration: str = '5m'
enabled_on_guest(guest: Guest) bool

Check if the test is enabled on the specific guest

environment: Environment
framework: str = 'shell'
classmethod from_dict(*, mapping: dict[str, Any], name: str, skip_validation: bool = False, raise_on_validation_error: bool = False, logger: Logger, **kwargs: Any) Test

Initialize test data from a dictionary.

Useful when data describing a test are stored in a mapping instead of an fmf node.

lint_absolute_path() Iterator[tuple[LinterOutcome, str]]

T003: test directory path must be absolute

lint_defined_test() Iterator[tuple[LinterOutcome, str]]

T002: test script must be defined

lint_legacy_coverage_key() Iterator[tuple[LinterOutcome, str]]

T006: coverage has been obsoleted by link

lint_legacy_relevancy_rules() Iterator[tuple[LinterOutcome, str]]

T005: relevancy has been obsoleted by adjust

lint_manual_test_path_exists() Iterator[tuple[LinterOutcome, str]]

T007: manual test path is not an actual path

lint_manual_valid_markdown() Iterator[tuple[LinterOutcome, str]]

T008: manual test should be valid markdown

lint_path_exists() Iterator[tuple[LinterOutcome, str]]

T004: test directory path must exist

lint_require_type_field() Iterator[tuple[LinterOutcome, str]]

T009: require fields should have type field

lint_unknown_keys() Iterator[tuple[LinterOutcome, str]]

T001: all keys are known

manual: bool = False
property manual_test_path: Path
static overview(tree: Tree) None

Show overview of available tests

path: Path | None = None
recommend: list[DependencySimple | DependencyFmfId | DependencyFile]
require: list[DependencySimple | DependencyFmfId | DependencyFile]
restart_max_count: int = 1
restart_on_exit_code: list[int]
restart_with_reboot: bool = False
result: ResultInterpret = 'respect'
serial_number: int = 0
show() None

Show test details

show_manual() None

Show manual test instructions

test: ShellScript | None = None
property test_framework: type[TestFramework]
tty: bool = False
where: list[str]
class tmt.base.Tree(*, path: Path | None = None, tree: Tree | None = None, fmf_context: FmfContext | None = None, additional_rules: list[_RawAdjustRule] | None = None, logger: Logger)

Bases: Common

Test Metadata Tree

Initialize tmt tree from directory path or given fmf tree

cli_invocation: 'tmt.cli.CliInvocation' | None = None
classmethod grow(*, path: Path | None = None, tree: Tree | None = None, fmf_context: FmfContext | None = None, logger: Logger | None = None) Tree

Initialize tmt tree from directory path or given fmf tree.

This method serves as an entry point for interactive use of tmt-as-a-library, providing sane defaults.

Warning

This method has a very limited use case, i.e. to help bootstrapping interactive tmt sessions. Using it anywhere outside of this scope should be ruled out.

static init(*, path: Path, template: str, force: bool, logger: Logger) None

Initialize a new tmt tree, optionally with a template

plans(logger: Logger | None = None, keys: list[str] | None = None, names: list[str] | None = None, filters: list[str] | None = None, conditions: list[str] | None = None, run: Run | None = None, links: list[LinkNeedle] | None = None, excludes: list[str] | None = None, apply_command_line: bool = True) list[Plan]

Search available plans

property root: Path | None

Metadata root

sanitize_cli_names(names: list[str]) list[str]

Sanitize CLI names in case name includes control character

stories(logger: Logger | None = None, keys: list[str] | None = None, names: list[str] | None = None, filters: list[str] | None = None, conditions: list[str] | None = None, whole: bool = False, links: list[LinkNeedle] | None = None, excludes: list[str] | None = None, apply_command_line: bool | None = True) list[Story]

Search available stories

tests(logger: Logger | None = None, keys: list[str] | None = None, names: list[str] | None = None, filters: list[str] | None = None, conditions: list[str] | None = None, unique: bool = True, links: list[LinkNeedle] | None = None, excludes: list[str] | None = None, apply_command_line: bool = True, sort: bool = True) list[Test]

Search available tests

property tree: Tree

Initialize tree only when accessed

tmt.base.assert_simple_dependencies(dependencies: list[DependencySimple | DependencyFmfId | DependencyFile], error_message: str, logger: Logger) list[DependencySimple]

Make sure the list of dependencies consists of simple ones.

Parameters:
  • dependencies – the list of requires.

  • error_message – used for a raised exception.

  • logger – used for logging.

Raises:

GeneralError – when there is a dependency on the list which is not a subclass of tmt.base.DependencySimple.

tmt.base.create_adjust_callback(logger: Logger) AdjustCallback

Create a custom callback for fmf’s adjust.

Given the adjust rules are applied on many places, for proper logging they need their own specific logger. Create a callback closure with the given logger.

tmt.base.dependency_factory(raw_dependency: str | _RawDependencyFmfId | _RawDependencyFile | None) DependencySimple | DependencyFmfId | DependencyFile

Select the correct require class

tmt.base.expand_node_data(data: T, fmf_context: FmfContext) T

Recursively expand variables in node data

tmt.base.normalize_require(key_address: str, raw_require: str | _RawDependencyFmfId | _RawDependencyFile | list[str | _RawDependencyFmfId | _RawDependencyFile] | None, logger: Logger) list[DependencySimple | DependencyFmfId | DependencyFile]

Normalize content of require key.

The requirements may be defined as either string or a special fmf id flavor, or a mixed list of these types. The goal here is to reduce the space of possibilities to a list, with fmf ids being converted to their internal representation.

tmt.base.resolve_dynamic_ref(*, workdir: Path, ref: str | None, plan: Plan | None = None, logger: Logger) str | None

Get the final value for the dynamic reference

Returns original ref if the dynamic referencing isn’t used. Plan is used for context and environment expansion to process reference. Common instance is used for appropriate logging.

tmt.convert module

Convert metadata into the new format

Add relevant link into data under the ‘link’ key

tmt.convert.adjust_runtest(path: Path) None

Adjust runtest.sh content and permission

tmt.convert.extract_relevancy(notes: str, field: StructuredField) str | list[str] | None

Get relevancy from testcase, respecting sf priority

tmt.convert.filter_common_data(common_data: dict[str, Any], individual_data: list[dict[str, Any]]) None

Filter common data out from individual data

tmt.convert.html_to_markdown(html: str) str

Convert html to markdown

tmt.convert.read(path: Path, makefile: bool, restraint: bool, nitrate: bool, polarion: bool, polarion_case_id: list[str], link_polarion: bool, purpose: bool, disabled: bool, types: list[str], general: bool, dry_run: bool, logger: Logger) tuple[dict[str, Any], list[dict[str, Any]]]

Read old metadata from various sources

Returns tuple (common_data, individual_data) where ‘common_data’ are metadata which belong to main.fmf and ‘individual_data’ contains data for individual testcases (if multiple nitrate testcases found).

tmt.convert.read_datafile(path: Path, filename: str, datafile: str, types: list[str], testinfo: str | None = None) tuple[str, dict[str, Any]]

Read data values from supplied Makefile or metadata file. Returns task name and a dictionary of the collected values.

tmt.convert.read_manual(plan_id: int, case_id: int, disabled: bool, with_script: bool, logger: Logger) None

Reads metadata of manual test cases from Nitrate

tmt.convert.read_manual_data(testcase: TestCase) dict[str, str]

Read test data from manual fields

tmt.convert.read_nitrate(beaker_task: str, common_data: dict[str, Any], disabled: bool, general: bool, dry_run: bool, logger: Logger) tuple[dict[str, Any], list[dict[str, Any]]]

Read old metadata from nitrate test cases

tmt.convert.read_nitrate_case(*, testcase: TestCase, makefile_data: dict[str, Any] | None = None, general: bool = False, logger: Logger) dict[str, Any]

Read old metadata from nitrate test case

tmt.convert.read_polarion(common_data: dict[str, Any], individual_data: list[dict[str, Any]], polarion_case_id: list[str], link_polarion: bool, filenames: list[str], dry_run: bool) None

Read data from Polarion

tmt.convert.read_polarion_case(data: dict[str, Any] | list[dict[str, Any]], polarion_case_id: str | None, link_polarion: bool, dry_run: bool) None

Read data of specific case from Polarion

tmt.convert.read_tier(tag: str, data: dict[str, Any]) None

Extract tier level from tag

Check for the tier attribute, if there are multiple TierX tags, pick the one with the lowest index.

tmt.convert.relevancy_to_adjust(relevancy: str | list[str], logger: Logger) list[dict[str, Any]]

Convert the old test case relevancy into adjust rules

Expects a string or list of strings with relevancy rules. Returns a list of dictionaries with adjust rules.

tmt.convert.write(path: Path, data: dict[str, Any], quiet: bool = False) None

Write gathered metadata in the fmf format

tmt.convert.write_markdown(path: Path, content: dict[str, str]) None

Write gathered metadata in the markdown format

tmt.hardware module

Guest hardware requirements specification and helpers.

tmt metadata allow to describe various HW requirements a guest needs to satisfy. This package provides useful functions and classes for core functionality and shared across provision plugins.

Parsing of HW requirements

Set of HW requirements, as given by test or plan metadata, is represented by Python structures - lists, mappings, primitive types - when loaded from fmf files. Part of the code below converts this representation to a tree of objects that provide helpful operations for easier evaluation and processing of HW requirements.

Each HW requirement “rule” in original metadata is a constraint, a condition the eventual guest HW must satisfy. Each node of the tree created from HW requirements is therefore called “a constraint”, and represents either a single condition (“trivial” constraints), or a set of such conditions plus a function reducing their individual outcomes to one final answer for the whole set (think any() and all() built-in functions) (“compound” constraints). Components of each constraint - dimension, operator, value, units - are decoupled from the rest, and made available for inspection.

[1] https://tmt.readthedocs.io/en/stable/spec/hardware.html

class tmt.hardware.And(constraints: list[BaseConstraint] | None = None)

Bases: CompoundConstraint

Represents constraints that are grouped in and fashion

Hold constraints that are grouped in and fashion.

Parameters:

constraints – list of constraints to group.

variants(members: list[Constraint[Any]] | None = None) Iterator[list[Constraint[Any]]]

Generate all distinct variants of constraints covered by this one.

Since the and reducer demands all child constraints must be satisfied, and some of these constraints can also be compound constraints, we need to construct a cartesian product of variants yielded by child constraints to include all possible combinations.

Parameters:

members – if specified, each variant generated by this method is prepended with this list.

Yields:

iterator over all variants.

class tmt.hardware.BaseConstraint

Bases: SpecBasedContainer[Any, Any]

Base class for all classes representing one or more constraints

classmethod from_spec(spec: Any) BaseConstraint

Convert from a specification file or from a CLI option

See https://tmt.readthedocs.io/en/stable/code/classes.html#class-conversions for more details.

See to_spec() for its counterpart.

to_minimal_spec() Any

Convert to specification, skip default values

See https://tmt.readthedocs.io/en/stable/code/classes.html#class-conversions for more details.

See from_spec() for its counterpart.

to_spec() Any

Convert to a form suitable for saving in a specification file

See https://tmt.readthedocs.io/en/stable/code/classes.html#class-conversions for more details.

See from_spec() for its counterpart.

uses_constraint(constraint_name: str, logger: Logger) bool

Inspect constraint whether the constraint or one of its children use a constraint of a given name.

Parameters:
  • constraint_name – constraint name to look for.

  • logger – logger to use for logging.

Raises:

NotImplementedError – method is left for child classes to implement.

variant() list[Constraint[Any]]

Pick one of the available variants of this constraints.

As the constraint can yield many variants, often there’s an interest in just one. There can be many different ways for picking the best one, whatever that may mean depending on the context, as a starting point this method is provided. In the future, provision plugins would probably use their own guessing to pick the most suitable variant.

variants(members: list[Constraint[Any]] | None = None) Iterator[list[Constraint[Any]]]

Generate all distinct variants of constraints covered by this one.

For a trivial constraint, there is only one variant, and that is the constraint itself. In the case of compound constraints, the number of variants would be bigger, depending on the constraint’s reducer.

Parameters:

members – if specified, each variant generated by this method is prepended with this list.

Yields:

iterator over all variants.

tmt.hardware.CHILDLESS_CONSTRAINTS: tuple[str, ...] = ('arch', 'memory', 'hostname')

A list of constraint names that do not have child properties.

tmt.hardware.CONSTRAINT_COMPONENTS_PATTERN = re.compile('\n    ^                                   # must match the whole string\n    (?P<name>[a-z_+]+)                  # constraint name is mandatory\n    (?:\\[(?P<peer_index>[+-]?\\d+)\\])?   # index is , re.VERBOSE)

Regular expression to match and split a HW constraint into its components. The input consists of a constraint name, (optional) index of the constraint among its peers, (optional) child constraint name, (optional) operator, and value.

  • memory 10 GiB => memory, None, None, None, 10 GiB

  • cpu.processors != 4 => cpu, None, processors, !=, 4

  • disk[1].size <= 1 TiB => disk, 1, size, <=, 1 TiB

tmt.hardware.CONSTRAINT_NAME_PATTERN = re.compile("\n    (?P<name>[a-z_+]+)                   # constraint name is mandatory\n    (?:\\[(?P<peer_index>[+-]?\\d+)\\])?    # index is optional\n    (?:\\.(?P<child_name>[a-z_]+))?       # child constrain, re.VERBOSE)

Regular expression to match and split a HW constraint name into its components. The input consists of a constraint name, (optional) index of the constraint among its peers, and (optional) child constraint name:

  • memory => memory, None, None

  • cpu.processors => cpu, None, processors

  • disk[1].size => disk, 1, size

tmt.hardware.CONSTRAINT_VALUE_PATTERN = re.compile('\n    ^                                   # must match the whole string\n    (?P<operator>==|!=|~|!~|=~|=|>=|>|<=|<)?  # optional operator\n    \\s*                                 # operator might b, re.VERBOSE)

Regular expression to match and split the value part of a key:value pair. The input consists of an (optional) operator, the actual value of the constraint, and (optional) units. As a result, pattern yields two groups, operator and value, the latter containing both the value and units.

class tmt.hardware.CompoundConstraint(reducer: ~typing.Callable[[~collections.abc.Iterable[bool]], bool] = <built-in function any>, constraints: list[~tmt.hardware.BaseConstraint] | None = None)

Bases: BaseConstraint

Base class for all compound constraints

Construct a compound constraint, constraint imposed to more than one dimension.

Parameters:
  • reducer – a callable reducing a list of results from child constraints into the final answer.

  • constraints – child constraints.

property size: int
to_spec() Any

Convert to a form suitable for saving in a specification file

See https://tmt.readthedocs.io/en/stable/code/classes.html#class-conversions for more details.

See from_spec() for its counterpart.

uses_constraint(constraint_name: str, logger: Logger) bool

Inspect constraint whether it or its children use a constraint of a given name.

Parameters:
  • constraint_name – constraint name to look for.

  • logger – logger to use for logging.

Returns:

True if the given constraint or its children use given constraint name.

variants(members: list[Constraint[Any]] | None = None) Iterator[list[Constraint[Any]]]

Generate all distinct variants of constraints covered by this one.

Since the and reducer demands all child constraints must be satisfied, and some of these constraints can also be compound constraints, we need to construct a cartesian product of variants yielded by child constraints to include all possible combinations.

Parameters:

members – if specified, each variant generated by this method is prepended with this list.

Yields:

iterator over all variants.

Raises:

NotImplementedError – default implementation is left undefined for compound constraints.

class tmt.hardware.Constraint(name: str, operator: Operator, operator_handler: Callable[[Any, Any], bool], value: ConstraintValueT, raw_value: str, default_unit: str | None = None, original_constraint: Constraint[Any] | None = None)

Bases: BaseConstraint, Generic[ConstraintValueT]

A constraint imposing a particular limit to one of the guest properties

change_operator(operator: Operator) None

Change operator of this constraint to a given one.

Parameters:

operator – new operator.

default_unit: str | None = None
expand_name() ConstraintNameComponents

Expand constraint name into its components.

Returns:

tuple consisting of constraint name components: name, optional indices, child properties, etc.

name: str
operator: Operator
operator_handler: Callable[[Any, Any], bool]
original_constraint: Constraint[Any] | None = None
property printable_name: str
raw_value: str
to_spec() Any

Convert to a form suitable for saving in a specification file

See https://tmt.readthedocs.io/en/stable/code/classes.html#class-conversions for more details.

See from_spec() for its counterpart.

uses_constraint(constraint_name: str, logger: Logger) bool

Inspect constraint whether it or its children use a constraint of a given name.

Parameters:
  • constraint_name – constraint name to look for.

  • logger – logger to use for logging.

Returns:

True if the given constraint or its children use given constraint name.

value: ConstraintValueT
variants(members: list[Constraint[ConstraintValueT]] | None = None) Iterator[list[Constraint[ConstraintValueT]]]

Generate all distinct variants of constraints covered by this one.

For a trivial constraint, there is only one variant, and that is the constraint itself. In the case of compound constraints, the number of variants would be bigger, depending on the constraint’s reducer.

Parameters:

members – if specified, each variant generated by this method is prepended with this list.

Yields:

iterator over all variants.

class tmt.hardware.ConstraintComponents(name: str, peer_index: int | None, child_name: str | None, operator: str | None, value: str)

Bases: object

Components of a constraint

child_name: str | None
classmethod from_spec(spec: str) ConstraintComponents
name: str
operator: str | None
peer_index: int | None
value: str
class tmt.hardware.ConstraintNameComponents(name: str, peer_index: int | None, child_name: str | None)

Bases: NamedTuple

Components of a constraint name

Create new instance of ConstraintNameComponents(name, peer_index, child_name)

child_name: str | None

size of disk[1].size

name: str

disk of disk[1].size

peer_index: int | None

1 of disk[1].size

tmt.hardware.ConstraintValue

A type of constraint values.

alias of int | Size | str | bool | float

class tmt.hardware.FlagConstraint(name: str, operator: Operator, operator_handler: Callable[[Any, Any], bool], value: ConstraintValueT, raw_value: str, default_unit: str | None = None, original_constraint: Constraint[Any] | None = None)

Bases: Constraint[bool]

A constraint representing a boolean flag, enabled/disabled, has/has not, etc.

classmethod from_specification(name: str, raw_value: bool, original_constraint: Constraint[Any] | None = None, allowed_operators: list[Operator] | None = None) T
class tmt.hardware.Hardware(constraint: tmt.hardware.BaseConstraint | None, spec: Any)

Bases: SpecBasedContainer[Any, Any]

and_(constraint: BaseConstraint) None
constraint: BaseConstraint | None
format_variants() Iterator[str]

Format variants of constraints.

Yields:

for each variant, which is nothing but a list of constraints, method yields a string variant’s serial number and formatted constraints.

classmethod from_spec(spec: Any) Hardware

Convert from a specification file or from a CLI option

See https://tmt.readthedocs.io/en/stable/code/classes.html#class-conversions for more details.

See to_spec() for its counterpart.

report_support(*, names: list[str] | None = None, check: Callable[[Constraint[Any]], bool] | None = None, logger: Logger) None

Report all unsupported constraints.

A helper method for plugins: plugin provides a callback which checks whether a given constraint is or is not supported by the plugin, and method calls the callback for each constraint stored in this container.

Both names and check are optional, and both can be used and combined. First, the names list is checked, if a constraint is not found, check is called if it’s defined.

Parameters:
  • names – a list of constraint names. If a constraint name is on this list, it is considered to be supported by the report_support caller. Caller may list both full constraint name, e.g. cpu.cores, or just the subsystem name, cpu, indicating all child constraints are supported.

  • check – a callback to call for each constraint in this container. Accepts a single parameter, a constraint to check, and if its return value is true-ish, the constraint is considered to be supported by the report_support caller.

spec: Any
to_minimal_spec() Any

Convert to specification, skip default values

See https://tmt.readthedocs.io/en/stable/code/classes.html#class-conversions for more details.

See from_spec() for its counterpart.

to_spec() Any

Convert to a form suitable for saving in a specification file

See https://tmt.readthedocs.io/en/stable/code/classes.html#class-conversions for more details.

See from_spec() for its counterpart.

tmt.hardware.INDEXABLE_CONSTRAINTS: tuple[str, ...] = ('disk', 'network')

A list of constraint names that operate over sequence of entities.

class tmt.hardware.IntegerConstraint(name: str, operator: Operator, operator_handler: Callable[[Any, Any], bool], value: ConstraintValueT, raw_value: str, default_unit: str | None = None, original_constraint: Constraint[Any] | None = None)

Bases: Constraint[int]

A constraint representing a dimension-less int number

classmethod from_specification(name: str, raw_value: str, original_constraint: Constraint[Any] | None = None, allowed_operators: list[Operator] | None = None) T
class tmt.hardware.NumberConstraint(name: str, operator: Operator, operator_handler: Callable[[Any, Any], bool], value: ConstraintValueT, raw_value: str, default_unit: str | None = None, original_constraint: Constraint[Any] | None = None)

Bases: Constraint[Quantity]

A constraint representing a float number

classmethod from_specification(name: str, raw_value: str, original_constraint: Constraint[Any] | None = None, allowed_operators: list[Operator] | None = None, default_unit: Any | None = None) T
class tmt.hardware.Operator(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

Binary operators defined by specification

CONTAINS = 'contains'
EQ = '=='
GT = '>'
GTE = '>='
LT = '<'
LTE = '<='
MATCH = '~'
NEQ = '!='
NOTCONTAINS = 'not contains'
NOTMATCH = '!~'
class tmt.hardware.Or(constraints: list[BaseConstraint] | None = None)

Bases: CompoundConstraint

Represents constraints that are grouped in or fashion

Hold constraints that are grouped in or fashion.

Parameters:

constraints – list of constraints to group.

variants(members: list[Constraint[Any]] | None = None) Iterator[list[Constraint[Any]]]

Generate all distinct variants of constraints covered by this one.

Since the any reducer allows any child constraints to be satisfied for the whole group to evaluate as True, it is trivial to generate variants - each child constraint shall provide its own “branch”, and there is no need for products or joins of any kind.

Parameters:

members – if specified, each variant generated by this method is prepended with this list.

Yields:

iterator over all variants.

exception tmt.hardware.ParseError(constraint_name: str, raw_value: str, message: str | None = None)

Bases: MetadataError

Raised when HW requirement parsing fails

Raise when HW requirement parsing fails.

Parameters:
  • constraint_name – name of the constraint that caused issues.

  • raw_value – original raw value.

  • message – optional error message.

tmt.hardware.ReducerType

A callable reducing a sequence of booleans to a single one. Think any() or all().

alias of Callable[[Iterable[bool]], bool]

class tmt.hardware.SizeConstraint(name: str, operator: Operator, operator_handler: Callable[[Any, Any], bool], value: ConstraintValueT, raw_value: str, default_unit: str | None = None, original_constraint: Constraint[Any] | None = None)

Bases: Constraint[Size]

A constraint representing a size of resource, usually a storage

classmethod from_specification(name: str, raw_value: str, original_constraint: Constraint[Any] | None = None, allowed_operators: list[Operator] | None = None, default_unit: Any | None = 'bytes') T
class tmt.hardware.TextConstraint(name: str, operator: Operator, operator_handler: Callable[[Any, Any], bool], value: ConstraintValueT, raw_value: str, default_unit: str | None = None, original_constraint: Constraint[Any] | None = None)

Bases: Constraint[str]

A constraint representing a string, e.g. a name

classmethod from_specification(name: str, raw_value: str, original_constraint: Constraint[Any] | None = None, allowed_operators: list[Operator] | None = None) T
tmt.hardware.UNITS = <pint.registry.UnitRegistry object>

Unit registry, used and shared by all code.

tmt.hardware.match(text: str, pattern: str) bool

Match a text against a given regular expression.

Parameters:
  • text – string to examine.

  • pattern – regular expression.

Returns:

True if pattern matches the string.

tmt.hardware.not_contains(haystack: list[str], needle: str) bool

Find out whether an item is in the given list.

Note

Opposite of operator.contains().

Parameters:
  • haystack – container to examine.

  • needle – item to look for in haystack.

Returns:

True if needle is not in haystack.

tmt.hardware.not_match(text: str, pattern: str) bool

Match a text against a given regular expression.

Parameters:
  • text – string to examine.

  • pattern – regular expression.

Returns:

True if pattern does not matche the string.

tmt.hardware.parse_hw_requirements(spec: Any) BaseConstraint

Convert raw specification of HW constraints to our internal representation.

Parameters:

spec – raw constraints specification as stored in an environment.

Returns:

root of HW constraints tree.

tmt.hardware.ungroupify(fn: Callable[[Any], BaseConstraint]) Callable[[Any], BaseConstraint]

Swap returned single-child compound constraint and that child.

Helps reduce the number of levels in the constraint tree: if the return value is a compound constraint which contains just a single child, return the child instead of the compound constraint.

Meant for constraints that do not have an index, e.g. memory or cpu. For indexable constraints, see ungroupify_indexed().

tmt.hardware.ungroupify_indexed(fn: Callable[[Any, int], BaseConstraint]) Callable[[Any, int], BaseConstraint]

Swap returned single-child compound constraint and that child.

Helps reduce the number of levels in the constraint tree: if the return value is a compound constraint which contains just a single child, return the child instead of the compound constraint.

Meant for constraints that have an index, e.g. disk or network. For non-indexable constraints, see ungroupify().

tmt.identifier module

exception tmt.identifier.IdError

Bases: Exception

General Identifier Error

exception tmt.identifier.IdLeafError

Bases: IdError

Identifier not stored in a leaf

tmt.identifier.add_uuid_if_not_defined(node: Tree, dry: bool, logger: Logger) str | None

Add UUID into node and return it unless already defined

tmt.identifier.get_id(node: Tree, leaf_only: bool = True) str | None

Get identifier if defined, optionally ensure leaf node

Return identifier for provided node. If ‘leaf_only’ is True, an additional check is performed to ensure that the identifier is defined in the node itself. The ‘IdLeafError’ exception is raised when the key is inherited from parent.

tmt.identifier.id_command(context: tmt.cli.Context, node: Tree, node_type: str, dry: bool) None

Command line interfacing with output to terminal

Show a brief summary when adding UUIDs to nodes.

tmt.lint module

Metadata linting.

Internal APIs, classes, shared functionality and helpers for test, plan and story metadata linting.

A mixin class, Lintable, provides the required functionality for base classes. Namely, it takes care of linter discovery and provides Lintable.lint() method to run them.

Classes spiced with Lintable define their sets of linters. Consider the following examples:

# Methods whose names start with ``lint_*`` prefix are considered *linters*,
# and linters perform one or more *checks* users can enable or disable.
def lint_path_exists(self) -> LinterReturn:
    # A linter must have a docstring which is then used to generate documentation,
    # e.g. when ``lint --list-checks`` is called. The docstring must begin with
    # a linter *id*. The id should match ``[CTPSG]\d\d\d`` regular expression:
    # ``C``ommon, ``T``est, ``P``lan, ``S``tory, ``G``roup, plus a three-digit
    # serial number of the check among its peers.
    ''' T004: test directory path must exist '''

    # Linter implements a generator (see :py:member:`LinterReturn`) yielding
    # two item tuples of :py:class:`LinterOutcome` and string messages.

    if not self.path:
        yield LinterOutcome.FAIL, 'directory path is not set'
        return

    test_path = os.path.join(self.node.root, os.path.relpath(self.path.strip(), '/'))

    if not os.path.exists(test_path):
        yield LinterOutcome.FAIL, f'test path "{test_path}" does not exist'
        return

    yield LinterOutcome.PASS, f'test path "{test_path}" does exist'

def lint_manual_valid_markdown(self) -> LinterReturn:
    ''' T008: manual test should be valid markdown '''

    # Linter should yield `SKIP` outcome when it does not apply, to announce
    # it did inspect the object but realized the object is out of scope of
    # the linter, and checks do not apply.
    if not self.manual:
         yield LinterOutcome.SKIP, 'not a manual test'
         return

    manual_test = os.path.join(self.node.root, self.path.strip())

    warnings = tmt.export.check_md_file_respects_spec(manual_test)

    if warnings:
        # Linter may yield as many tuples as it deems necessary. This allows
        # for linters iterating over more granular aspects of metadata,
        # providing more specific hints.
        for warning in warnings:
           yield LinterOutcome.WARN, warning

    ...
class tmt.lint.Lintable(*args: Any, **kwargs: Any)

Bases: Generic[LintableT]

Mixin class adding support for linting of class instances

classmethod discover_linters() None

Discover and register all linters implemented by this class.

A linter is a method whose name starts with lint_ prefix. It must have a docstring which serves as a hint for --list-checks output.

classmethod format_linters() str

Format registered linters for printing or logging.

Returns:

a string description of registered linters, suitable for logging or help texts.

classmethod get_linter_registry() list[Linter]

Return - or initialize - linter registry

lint(enable_checks: list[str] | None = None, disable_checks: list[str] | None = None, enforce_checks: list[str] | None = None, linters: list[Linter] | None = None) tuple[bool, list[tuple[Linter, LinterOutcome, LinterOutcome, str]]]

Check the instance against a battery of linters and report results.

Parameters:
  • enable_checks – if set, only linters providing the listed checks would be applied.

  • disable_checks – if set, linters providing the listed checks would not be applied.

  • enforce_checks – if set, listed checks would be marked as failed if their outcome is not pass, i.e. even a warning would become a fail.

  • linters – if set, only these linters would be applied. Providing linters makes enable_checks and disable_checks ignored.

Returns:

a tuple of two items: a boolean reporting whether the instance passed the test, and a list of LinterRuling items, each describing one linter outcome. Note that linters may produce none or more than one outcome.

classmethod resolve_enabled_linters(enable_checks: list[str] | None = None, disable_checks: list[str] | None = None) list[Linter]

Produce a list of enabled linters from all registered ones.

Method combines three inputs:

  • registered linters, acquired from the class registry,

  • list of checks to enable, and

  • list of checks to disable

into a single list of linters that are considered as enabled.

Parameters:
  • enable_checks – if set, only linters providing the listed checks would be included in the output.

  • disable_checks – if set, linters providing the listed checks would be removed from the output.

Returns:

list of linters that were registered, and whose checks were enabled and not disabled.

class tmt.lint.Linter(callback: Callable[[Lintable], Iterator[tuple[LinterOutcome, str]]])

Bases: object

A single linter

callback: Callable[[Lintable], Iterator[tuple[LinterOutcome, str]]]
description: str | None = None
format() list[str]

Format the linter for printing or logging.

Returns:

a string description of the linter, suitable for logging or help texts, in the form of lines of text.

help: str
id: str
class tmt.lint.LinterOutcome(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

FAIL = 'fail'
FIXED = 'fixed'
PASS = 'pass'
SKIP = 'skip'
WARN = 'warn'
tmt.lint.LinterReturn

A return value type of a single linter.

alias of Iterator[tuple[LinterOutcome, str]]

tmt.lint.LinterRuling

Info on how a linter decided: linter itself, its outcome & the message.

alias of tuple[Linter, LinterOutcome, LinterOutcome, str]

tmt.lint.filter_allowed_checks(rulings: Iterable[tuple[Linter, LinterOutcome, LinterOutcome, str]], outcomes: list[LinterOutcome] | None = None) Iterator[tuple[Linter, LinterOutcome, LinterOutcome, str]]

Filter only rulings whose outcomes are allowed.

Parameters:
  • rulings – rulings to process.

  • outcomes – a list of allowed ruling outcomes. If not set, all outcomes are allowed.

Yields:

rulings with allowed outcomes.

tmt.lint.format_rulings(rulings: Iterable[tuple[Linter, LinterOutcome, LinterOutcome, str]]) Iterator[str]

Format rulings for printing or logging.

Parameters:

rulings – rulings to format.

Yields:

rulings formatted as separate strings.

tmt.log module

tmt’s logging subsystem.

Adds a layer on top of Python’s own logging subsystem. This layer implements the desired verbosity and debug levels, colorization, formatting, verbosity inheritance and other features used by tmt commands and code.

The main workhorses are Logger instances. Each instance wraps a particular logging.Logger instance - usually there’s a chain of such instances, with the root one having console and logfile handlers attached. tmt’s log verbosity/debug/quiet features are handled on our side, with the use of logging.Filter classes.

Logger instances can be cloned and modified, to match various levels of tmt’s runtime class tree - tmt spawns a “root logger” from which a new one is cloned - and indented by one extra level - for Run instance, and so on. This way, every object in tmt’s hierarchy uses a given logger, which may have its own specific settings, and, in the future, possibly also handlers for special output channels.

While tmt recognizes several levels of verbosity (-v) and debugging (-d), all messages emitted by Logger.verbose() and Logger.debug() use a single logging level, INFO or DEBUG, respectively. The level of verbosity and debugging is then handled by a special logging.Filter` classes. This allows different levels when logging to console but all-capturing log files while keeping implementation simple - the other option would be managing handlers themselves, which would be very messy given the propagation of messages.

class tmt.log.ConsoleFormatter(apply_colors: bool = True, show_timestamps: bool = False)

Bases: _Formatter

Initialize the formatter with specified format strings.

Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with the optional datefmt argument. If datefmt is omitted, you get an ISO8601-like (or RFC 3339-like) format.

Use a style parameter of ‘%’, ‘{’ or ‘$’ to specify that you want to use one of %-formatting, str.format() ({}) formatting or string.Template formatting in your format string.

Changed in version 3.2: Added the style parameter.

class tmt.log.ConsoleHandler(stream=None)

Bases: StreamHandler

Initialize the handler.

If stream is not specified, sys.stderr is used.

class tmt.log.DebugLevelFilter(name='')

Bases: Filter

Initialize a filter.

Initialize with the name of the logger which, together with its children, will have its events allowed through the filter. If no name is specified, allow every event.

filter(record: LogRecord) bool

Determine if the specified record is to be logged.

Returns True if the record should be logged, or False otherwise. If deemed appropriate, the record may be modified in-place.

class tmt.log.LogRecordDetails(key: str, value: str | dict[str, ~typing.Any] | int | bool | float | tmt.utils.Environment | tmt.utils.FmfContext | tmt.utils.Path | tmt.utils.Command | tmt.utils.ShellScript | None = None, color: str | None = None, shift: int = 0, logger_labels: list[str] = <factory>, logger_labels_padding: int = 0, logger_verbosity_level: int = 0, message_verbosity_level: int | None = None, logger_debug_level: int = 0, message_debug_level: int | None = None, logger_quiet: bool = False, ignore_quietness: bool = False, logger_topics: set[~tmt.log.Topic] = <factory>, message_topic: ~tmt.log.Topic | None = None)

Bases: object

tmt’s log message components attached to log records

color: str | None = None
ignore_quietness: bool = False
key: str
logger_debug_level: int = 0
logger_labels: list[str]
logger_labels_padding: int = 0
logger_quiet: bool = False
logger_topics: set[Topic]
logger_verbosity_level: int = 0
message_debug_level: int | None = None
message_topic: Topic | None = None
message_verbosity_level: int | None = None
shift: int = 0
value: str | dict[str, Any] | int | bool | float | tmt.utils.Environment | tmt.utils.FmfContext | tmt.utils.Path | tmt.utils.Command | tmt.utils.ShellScript | None = None
class tmt.log.LogfileFormatter

Bases: _Formatter

Initialize the formatter with specified format strings.

Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with the optional datefmt argument. If datefmt is omitted, you get an ISO8601-like (or RFC 3339-like) format.

Use a style parameter of ‘%’, ‘{’ or ‘$’ to specify that you want to use one of %-formatting, str.format() ({}) formatting or string.Template formatting in your format string.

Changed in version 3.2: Added the style parameter.

class tmt.log.LogfileHandler(filepath: tmt.utils.Path)

Bases: FileHandler

Open the specified file and use it as the stream for logging.

emitting_to: list[Path] = []

Paths of all log files to which LogfileHandler was attached.

class tmt.log.Logger(actual_logger: Logger, base_shift: int = 0, labels: list[str] | None = None, labels_padding: int = 0, verbosity_level: int = 0, debug_level: int = 0, quiet: bool = False, topics: set[Topic] | None = None, apply_colors_output: bool = True, apply_colors_logging: bool = True)

Bases: object

A logging entry point, representing a certain level of verbosity and handlers.

Provides actual logging methods plus methods for managing verbosity levels and handlers.

Create a Logger instance with given verbosity levels.

Parameters:
  • actual_logger – a logging.Logger instance, the raw logger to use for logging.

  • base_shift – shift applied to all messages processed by this logger.

  • labels_padding – if set, rendered labels would be padded to this length.

  • verbosity_level – desired verbosity level, usually derived from -v command-line option.

  • debug_level – desired debugging level, usually derived from -d command-line option.

  • quiet – if set, all messages would be suppressed, with the exception of warnings (warn()), errors (fail()) and messages emitted with print().

add_console_handler(show_timestamps: bool = False) None

Attach console handler to this logger.

Parameters:

show_timestamps – when set, emitted messages would include the time.

add_logfile_handler(filepath: tmt.utils.Path) None

Attach a log file handler to this logger

property apply_colors_output: bool
apply_verbosity_options(cli_invocation: tmt.cli.CliInvocation | None = None, **kwargs: Any) Logger

Update logger’s settings to match given CLI options.

Use this method to update logger’s settings after Logger.descend() call, to reflect options given to a tmt subcommand.

clone() Logger

Create a copy of this logger instance.

All its settings are propagated to new instance. Settings are not shared, and may be freely modified after cloning without affecting the other logger.

classmethod create(actual_logger: Logger | None = None, apply_colors_output: bool = True, apply_colors_logging: bool = True, **verbosity_options: Any) Logger

Create a (root) tmt logger.

This method has a very limited set of use cases:

  • CLI bootstrapping right after tmt started.

  • Unit tests of code that requires logger as one of its inputs.

  • 3rd party apps treating tmt as a library, i.e. when they wish tmt to use their logger instead of tmt’s default one.

Parameters:

actual_logger – a logging.Logger instance to wrap. If not set, a default logger named tmt is created.

debug(key: str, value: str | dict[str, Any] | int | bool | float | tmt.utils.Environment | tmt.utils.FmfContext | tmt.utils.Path | tmt.utils.Command | tmt.utils.ShellScript | None = None, color: str | None = None, shift: int = 0, level: int = 1, topic: Topic | None = None) None
descend(logger_name: str | None = None, extra_shift: int = 1) Logger

Create a copy of this logger instance, but with a new raw logger.

New logging.Logger instance is created from our raw logger, forming a parent/child relationship between them, and it’s then wrapped with Logger instance. Settings of this logger are copied to new one, with the exception of base_shift which is increased by one, effectively indenting all messages passing through new logger.

Parameters:
  • logger_name – optional name for the underlying logging.Logger instance. Useful for debugging. If not set, a generic one is created.

  • extra_shift – by how many extra levels should messages be indented by new logger.

fail(message: str, shift: int = 0) None
classmethod get_bootstrap_logger() Logger

Create a logger designed for tmt startup time.

Warning

This logger has a very limited use case span, i.e. before tmt can digest its command-line options and create a proper logger. This happens inside tmt.cli._root.main() function, but there are some actions taken by tmt code before this function is called by Click, actions that need to emit logging messages. Using it anywhere outside of this brief time in tmt’s runtime should be ruled out.

info(key: str, value: str | dict[str, Any] | int | bool | float | tmt.utils.Environment | tmt.utils.FmfContext | tmt.utils.Path | tmt.utils.Command | tmt.utils.ShellScript | None = None, color: str | None = None, shift: int = 0) None
property labels_span: int

Length of rendered labels

print(text: str, color: str | None = None, shift: int = 0, file: TextIO | None = None) None
print_format(text: str, color: str | None = None, shift: int = 0) str

Format the given text in a way suitable for print()

verbose(key: str, value: str | dict[str, Any] | int | bool | float | tmt.utils.Environment | tmt.utils.FmfContext | tmt.utils.Path | tmt.utils.Command | tmt.utils.ShellScript | None = None, color: str | None = None, shift: int = 0, level: int = 1, topic: Topic | None = None) None
warn(message: str, shift: int) None
warning(message: str, shift: int = 0) None
class tmt.log.LoggingFunction(*args, **kwargs)

Bases: Protocol

class tmt.log.QuietnessFilter(name='')

Bases: Filter

Initialize a filter.

Initialize with the name of the logger which, together with its children, will have its events allowed through the filter. If no name is specified, allow every event.

filter(record: LogRecord) bool

Determine if the specified record is to be logged.

Returns True if the record should be logged, or False otherwise. If deemed appropriate, the record may be modified in-place.

class tmt.log.Topic(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

ADJUST_DECISIONS = 'adjust-decisions'
CLI_INVOCATIONS = 'cli-invocations'
COMMAND_EVENTS = 'command-events'
HELP_RENDERING = 'help-rendering'
KEY_NORMALIZATION = 'key-normalization'
class tmt.log.TopicFilter(name='')

Bases: Filter

Initialize a filter.

Initialize with the name of the logger which, together with its children, will have its events allowed through the filter. If no name is specified, allow every event.

filter(record: LogRecord) bool

Determine if the specified record is to be logged.

Returns True if the record should be logged, or False otherwise. If deemed appropriate, the record may be modified in-place.

class tmt.log.VerbosityLevelFilter(name='')

Bases: Filter

Initialize a filter.

Initialize with the name of the logger which, together with its children, will have its events allowed through the filter. If no name is specified, allow every event.

filter(record: LogRecord) bool

Determine if the specified record is to be logged.

Returns True if the record should be logged, or False otherwise. If deemed appropriate, the record may be modified in-place.

tmt.log.create_decolorizer(apply_colors: bool) Callable[[str], str]
tmt.log.decide_colorization(no_color: bool, force_color: bool) tuple[bool, bool]

Decide whether the output and logging should be colorized.

Based on values of CLI options, environment variables and output stream properties, a colorization setup is decided. The following inputs are evaluated, in this order:

  • if either of the --no-color CLI option, NO_COLOR or

    TMT_NO_COLOR environment variables are set, colorization would be disabled.

  • if either of the --force-color CLI option or TMT_FORCE_COLOR

    environment variable are set, colorization would be forcefully enabled.

If none of the situations above happened, colorization would be enabled for output and logging based on their respective stream TTY status. Output is sent to standard output, logging then to standard error output, colorization would then be the outcome of stream’s file.isatty() method.

Note

Be aware that “forced enable” is stronger than “forced disable”. If --force-color or TMT_FORCE_COLOR are set, colors will be enabled despite any disabling options or environment variables.

Note

All inputs with the exception of isatty result control both types of output, regular output and logging, and applies to both of them. Only isatty outcome is specific for each type, and may result in one output type dropping colors while the other would be colorized.

Parameters:
  • no_color – value of the --no-color CLI option.

  • force_color – value of the –force-color` CLI option.

Returns:

a tuple of two booleans, one for output colorization, the other for logging colorization.

tmt.log.indent(key: str, value: str | dict[str, Any] | int | bool | float | tmt.utils.Environment | tmt.utils.FmfContext | tmt.utils.Path | tmt.utils.Command | tmt.utils.ShellScript | None = None, color: str | None = None, level: int = 0, labels: list[str] | None = None, labels_padding: int = 0) str

Indent a key/value message.

If both key and value are specified, {key}: {value} message is rendered. Otherwise, just key is used alone. If value contains multiple lines, each but the very first line is indented by one extra level.

Parameters:
  • value – optional value to print at right side of key.

  • color – optional color to apply on key.

  • level – number of indentation levels. Each level is indented by INDENT spaces.

  • labels – optional list of strings to prepend to each message. Each item would be wrapped within square brackets ([foo] message...).

  • labels_padding – if set, rendered labels would be padded to this length.

tmt.log.render_labels(labels: list[str]) str

tmt.options module

Common options and the MethodCommand class

class tmt.options.Deprecated(since: str, hint: str | None = None)

Bases: object

Version information and hint for obsolete options

hint: str | None = None
property rendered: str
since: str
class tmt.options.Path

Bases: ParamType

convert(value: Any, param: Parameter | None, ctx: Context | None) Path | None

Convert the value to the correct type. This is not called if the value is None (the missing value).

This must accept string values from the command line, as well as values that are already the correct type. It may also convert other compatible types.

The param and ctx arguments may be None in certain situations, such as when converting prompt input.

If the value cannot be converted, call fail() with a descriptive message.

Parameters:
  • value – The value to convert.

  • param – The parameter that is using this type to convert its value. May be None.

  • ctx – The current context that arrived at this value. May be None.

name: str = 'path'

the descriptive name of this type

tmt.options.create_method_class(methods: dict[str, Command]) type[Command]

Create special class to handle different options for each method

Accepts dictionary with method names and corresponding commands: For example: {‘fmf’, <click.core.Command object at 0x7f3fe04fded0>} Methods should be already sorted according to their priority.

tmt.options.create_options_decorator(options: list[Callable[[Any], Any]]) Callable[[FC], FC]
tmt.options.option(*param_decls: str, show_default: bool = False, is_flag: bool = False, multiple: bool = False, count: bool = False, type: Choice | Any | None = None, help: str | None = None, required: bool = False, default: Any | None = None, nargs: int | None = None, metavar: str | None = None, prompt: str | None = None, envvar: str | None = None, hidden: bool = False, choices: Sequence[str] | None = None, deprecated: Deprecated | None = None) Callable[[Any], Any]

Attaches an option to the command.

This is a wrapper for click.option(), its parameters have the same meaning as those of click.option(), and are passed to click.option(), with the exception of deprecated parameter.

Parameters:
  • choices – if set, it sets type of the option to click.Choices, and limits option values to those listed in choices.

  • deprecated – if set, it is rendered and appended to help. This parameter is not passed to click.option().

tmt.options.show_step_method_hints(step_name: str, how: str, logger: Logger) None

Show hints about available step methods’ installation

The logger will be used to output the hints to the terminal, hence it must be an instance of a subclass of tmt.utils.Common (info method must be available).

tmt.queue module

class tmt.queue.GuestlessTask(logger: Logger, **kwargs: Any)

Bases: Task[TaskResultT]

A task not assigned to a particular set of guests.

An extension of the Task class, provides a quite generic wrapper for the actual task which takes care of catching exceptions and proper reporting.

go() Iterator[Self]

Perform the task.

Called by Queue machinery to accomplish the task. It expects the child class would implement run(), with go taking care of task/queue interaction.

Yields:

since the task is not expected to run on multiple guests, only a single instance of the class is yielded to describe the task and its outcome.

run(logger: Logger) TaskResultT

Perform the task.

Called once from go(). Subclasses of GuestlessTask should implement their logic in this method rather than in go() which is already provided. If your task requires different handling in go, it might be better derived directly from Task.

class tmt.queue.MultiGuestTask(logger: Logger, guests: list[Guest], **kwargs: Any)

Bases: Task[TaskResultT]

A task assigned to a particular set of guests.

An extension of the Task class, provides a quite generic wrapper for the actual task which takes care of catching exceptions and proper reporting.

go() Iterator[Self]

Perform the task.

Called by Queue machinery to accomplish the task. It expects the child class would implement run(), with go taking care of task/queue interaction.

Yields:

instances of the same class, describing invocations of the task and their outcome. For each guest, one instance would be yielded.

property guest_ids: list[str]
guests: list[Guest]
run_on_guest(guest: Guest, logger: Logger) None

Perform the task.

Called from go() once for every guest to run on. Subclasses of GuestlessTask should implement their logic in this method rather than in go() which is already provided. If your task requires different handling in go, it might be better derived directly from Task.

class tmt.queue.Queue(name: str, logger: Logger)

Bases: list[TaskT]

Queue class for running tasks

enqueue_task(task: TaskT) None

Put new task into a queue

run() Iterator[TaskT]

Start crunching the queued tasks.

Tasks are executed in the order, for each task/guest combination a Task instance is yielded.

class tmt.queue.Task(logger: Logger, **kwargs: Any)

Bases: Generic[TaskResultT]

A base class for queueable actions.

The class provides not just the tracking, but the implementation of the said action as well. Child classes must implement their action functionality in go().

Note

This class and its subclasses must provide their own __init__ methods, and cannot rely on dataclasses generating one. This is caused by subclasses often adding fields without default values, and dataclasses module does not allow non-default fields to be specified after those with default values. Therefore initialize fields to their defaults “manually”.

exc: Exception | None

If set, an exception was raised by the running task, and the exception is saved in this field.

go() Iterator[Self]

Perform the task.

Called by Queue machinery to accomplish the task.

Yields:

instances of the same class, describing invocations of the task and their outcome. The task might be executed multiple times, depending on how exactly it was queued, and method would yield corresponding results.

guest: Guest | None

Guest on which the phase was executed. May be unset, some tasks may handle multiguest actions on their own.

logger: Logger

A logger to use for logging events related to the outcome.

property name: str

A name of this task.

Left for child classes to implement, because the name depends on the actual task.

requested_exit: SystemExit | None

If set, the task raised SystemExit exception, and wants to terminate the run completely.

result: TaskResultT | None
tmt.queue.prepare_loggers(logger: Logger, labels: list[str]) dict[str, Logger]

Create loggers for a set of labels.

Guests are assumed to be a group a phase would be executed on, and therefore their labels need to be set, to provide context, plus their labels need to be properly aligned for more readable output.

tmt.result module

class tmt.result.BaseResult(name: str, result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, original_result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, note: list[str] = <factory>, log: list[~tmt._compat.pathlib.Path] = <factory>, start_time: str | None = None, end_time: str | None = None, duration: str | None = None)

Bases: SerializableContainer

Describes what tmt knows about a result

duration: str | None = None
end_time: str | None = None
log: list[Path]
name: str
note: list[str]
original_result: ResultOutcome = 'pass'
property printable_note: str
result: ResultOutcome = 'pass'
show() str

Return a nicely colored result with test name (and note)

start_time: str | None = None
class tmt.result.CheckResult(name: str, result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, original_result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, note: list[str] = <factory>, log: list[~tmt._compat.pathlib.Path] = <factory>, start_time: str | None = None, end_time: str | None = None, duration: str | None = None, event: ~tmt.checks.CheckEvent = CheckEvent.BEFORE_TEST)

Bases: BaseResult

Describes what tmt knows about a single test check result

event: CheckEvent = 'before-test'
to_subcheck() SubCheckResult

Convert check to a tmt SubCheckResult

class tmt.result.PhaseResult(name: str, result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, original_result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, note: list[str] = <factory>, log: list[~tmt._compat.pathlib.Path] = <factory>, start_time: str | None = None, end_time: str | None = None, duration: str | None = None)

Bases: BaseResult

Describes what tmt knows about result of individual phases, e.g. prepare ansible

tmt.result.RawResult

Raw result as written in a YAML file. A dictionary, but for now the actual keys are not important.

class tmt.result.Result(name: str, result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, original_result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, note: list[str] = <factory>, log: list[~tmt._compat.pathlib.Path] = <factory>, start_time: str | None = None, end_time: str | None = None, duration: str | None = None, serial_number: int = 0, fmf_id: ~tmt.base.FmfId | None = None, context: ~tmt.utils.FmfContext = <factory>, ids: dict[str, str | None] = <factory>, guest: ~tmt.result.ResultGuestData = <factory>, subresult: list[~tmt.result.SubResult] = <factory>, check: list[~tmt.result.CheckResult] = <factory>, data_path: ~tmt._compat.pathlib.Path | None = None)

Bases: BaseResult

Describes what tmt knows about a single test result

check: list[CheckResult]
context: FmfContext
data_path: Path | None = None
static failures(log: str | None, msg_type: str = 'FAIL') str

Filter stdout and get only messages with certain type

fmf_id: FmfId | None = None
classmethod from_test_invocation(*, invocation: TestInvocation, result: ResultOutcome, note: list[str] | None = None, ids: dict[str, str | None] | None = None, log: list[Path] | None = None, subresult: list[SubResult] | None = None) Result

Create a result from a test invocation.

A helper for extracting interesting data from a given test invocation. While it’s perfectly possible to go directly through Result(...), most of the time a result stems from a particular test invocation captured by a TestInvocation instance.

Parameters:
  • invocation – a test invocation capturing the test run and results.

  • result – actual test outcome. It will be interpreted according to Test.result key (see https://tmt.readthedocs.io/en/stable/spec/tests.html#result).

  • note – optional result notes.

  • ids – additional test IDs. They will be added to IDs extracted from the test.

  • log – optional list of test logs.

guest: ResultGuestData
ids: dict[str, str | None]
interpret_check_result(check_name: str, interpret_checks: dict[str, CheckResultInterpret]) ResultOutcome

Aggregate all checks of given name and interpret the outcome

Parameters:
  • check_name – name of the check to be aggregated

  • interpret_checks – mapping of check:how and its result interpret

Returns:

ResultOutcome instance with the interpreted result

interpret_result(interpret: ResultInterpret, interpret_checks: dict[str, CheckResultInterpret]) Result

Interpret result according to a given interpretation instruction.

Inspect and possibly modify result and note attributes, following the interpret value.

Parameters:
  • interpret – how to interpret current result.

  • interpret_checks – mapping of check:how and its result interpret

Returns:

Result instance containing the updated result.

serial_number: int = 0
show(display_guest: bool = True) str

Return a nicely colored result with test name (and note)

subresult: list[SubResult]
static summary(results: list[Result]) str

Prepare a nice human summary of provided results

to_subresult() SubResult

Convert result to tmt subresult

static total(results: list[Result]) dict[ResultOutcome, int]

Return dictionary with total stats for given results

class tmt.result.ResultGuestData(name: str = 'default-0', role: str | None = None, primary_address: str | None = None)

Bases: SerializableContainer

Describes what tmt knows about a guest the result was produced on

classmethod from_test_invocation(*, invocation: TestInvocation) ResultGuestData

Create a guest data for a result from a test invocation.

A helper for extracting interesting guest data from a given test invocation.

Parameters:

invocation – a test invocation capturing the test run and results.

name: str = 'default-0'
primary_address: str | None = None
role: str | None = None
tmt.result.ResultIds

A type of collection IDs tracked for a single result.

alias of dict[str, str | None]

class tmt.result.ResultInterpret(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

CUSTOM = 'custom'
ERROR = 'error'
FAIL = 'fail'
INFO = 'info'
PASS = 'pass'
RESPECT = 'respect'
RESTRAINT = 'restraint'
WARN = 'warn'
XFAIL = 'xfail'
classmethod from_spec(spec: str) ResultInterpret
classmethod is_result_outcome(value: ResultInterpret) bool
classmethod normalize(key_address: str, value: Any, logger: Logger) ResultInterpret
class tmt.result.ResultOutcome(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

ERROR = 'error'
FAIL = 'fail'
INFO = 'info'
PASS = 'pass'
SKIP = 'skip'
WARN = 'warn'
classmethod from_spec(spec: str) ResultOutcome
static reduce(outcomes: list[ResultOutcome]) ResultOutcome

Reduce several result outcomes into a single outcome

Convert multiple outcomes into a single one by picking the worst. This is used when aggregating several test or check results to present a single value to the user.

class tmt.result.SubCheckResult(name: str, result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, original_result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, note: list[str] = <factory>, log: list[~tmt._compat.pathlib.Path] = <factory>, start_time: str | None = None, end_time: str | None = None, duration: str | None = None, event: ~tmt.checks.CheckEvent = CheckEvent.BEFORE_TEST)

Bases: CheckResult

Describes what tmt knows about a single subtest check result.

It does not contain any additional fields; it simply defines a type to easily differentiate between a tmt.result.CheckResult and a CheckResult located within a result phase.

class tmt.result.SubResult(name: str, result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, original_result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, note: list[str] = <factory>, log: list[~tmt._compat.pathlib.Path] = <factory>, start_time: str | None = None, end_time: str | None = None, duration: str | None = None, check: list[~tmt.result.SubCheckResult] = <factory>)

Bases: BaseResult

Describes what tmt knows about a single test subresult

check: list[SubCheckResult]
tmt.result.results_to_exit_code(results: list[Result]) int

Map results to a tmt exit code

tmt.trying module

Easily try tests and experiment with guests

class tmt.trying.Action(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

Available actions and their keyboard shortcuts

DEBUG = ('b', 'choose a different debugging level')
DISCOVER = ('d', 'gather information about tests to be executed')
EXECUTE = ('e', 'run tests using the specified executor')
FINISH = ('f', 'perform the finishing tasks, clean up guests')
KEEP = ('k', 'exit the session but keep the run for later use')
LOGIN = ('l', 'log into the guest for experimenting')
PREPARE = ('p', 'prepare the environment for testing')
QUIT = ('q', 'clean up the run and quit the session')
REPORT = ('r', 'provide test results overview and send reports')
START_ASK = ('-', 'do nothing without first asking the user')
START_LOGIN = ('-', 'jump directly to login after start')
START_TEST = ('-', 'start directly with executing detected tests')
TEST = ('t', 'rediscover tests and execute them again')
VERBOSE = ('v', 'set the desired level of verbosity')
property action: str

Action name in lower case

property description: str

Action description

classmethod find(answer: str) Action

Return action for given keyboard input (shortcut or whole word)

property key: str

Keyboard shortcut

property menu: str

Show menu with the keyboard shortcut highlighted

class tmt.trying.Try(*, tree: Tree, logger: Logger, **kwargs: Any)

Bases: Common

Just store the tree

action_debug(plan: Plan) None

Set verbosity level of all loggers in given plan

action_discover(plan: Plan) None

Discover tests

action_execute(plan: Plan) None

Execute tests

action_finish(plan: Plan) None

Clean up guests and finish

action_keep(plan: Plan) None

Keep run and exit the session

action_login(plan: Plan) None

Log into the guest

action_prepare(plan: Plan) None

Prepare the guest

action_quit(plan: Plan) None

Clean up the run and quit the session

action_report(plan: Plan) None

Report results

action_start(plan: Plan) None

Common start actions

action_start_ask(plan: Plan) None

Ask what to do

action_start_login(plan: Plan) None

Start with login

action_start_test(plan: Plan) None

Start with testing

action_test(plan: Plan) None

Test again

action_verbose(plan: Plan) None

Set verbosity level of all loggers in given plan

check_plans(run: Run) None

Check for plans to be used for testing

check_tests() None

Check for available tests

check_tree() None

Make sure there is a sane metadata tree

choose_action() Action

Print menu, get next action

cli_invocation: 'tmt.cli.CliInvocation' | None = None
get_default_plans(run: Run) list[Plan]

Get default plan from user config or the standard template

go() None

Run the interactive session

handle_epel(plan: Plan) None

Enable EPEL repository

handle_install(plan: Plan) None

Install local rpm package on the guest.

handle_options(plan: Plan) None

Choose requested cli option

prompt_debug() None

Choose the right debug level

prompt_verbose() None

Ask for the desired verbosity level

save() None

Save list of selected plans and enabled steps

welcome() None

Welcome message with summary of what we’re going to try

Module contents

Test Management Tool