tmt package
Subpackages
- tmt.checks package
- tmt.export package
- tmt.frameworks package
- tmt.libraries package
- tmt.plugins package
- tmt.steps package
- Subpackages
- Module contents
ActionBasePluginBasePlugin.base_command()BasePlugin.cli_invocationBasePlugin.command()BasePlugin.dataBasePlugin.default()BasePlugin.delegate()BasePlugin.enabled_on_guest()BasePlugin.get()BasePlugin.go_prolog()BasePlugin.howBasePlugin.methods()BasePlugin.options()BasePlugin.prune()BasePlugin.requires()BasePlugin.safe_nameBasePlugin.show()BasePlugin.wake()
DefaultNameGeneratorGuestTopologyGuestlessPluginLoginMethodPhasePhaseQueuePluginPullTaskPushTaskQueuedPhaseRebootStepStepDataTopologyWhereableStepDataprovides_method()safe_filename()sync_with_guests()
- tmt.templates package
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, cli_invocation: tmt.cli.CliInvocation | None = None, logger: Logger)
Bases:
CommonA 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() bool
Clean guests of runs
- images() bool
Clean images of provision plugins
- runs() 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,CommonGeneral 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[tmt.base._RawAdjustRule] | None
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- contact: list[str]
- description: str | None = None
- enabled: bool = True
- fmf_sources
- 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
Corein a given tree, encapsulating the mapping between core classes and tree search methods.- Parameters:
tree – tree to search for objects.
- has_link(needle: LinkNeedle) bool
Whether object contains specified link
- id: str | None = None
- lint_summary_exists() Iterator[tuple[tmt.lint.LinterOutcome, str]]
C001: summary key should be set and should be reasonably long
- lint_validate() Iterator[tuple[tmt.lint.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
- web_link() str | None
Return a clickable web link to the fmf metadata location
- 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']
- 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:
strA 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.utils.Path | None = None, git_root: tmt.utils.Path | None = None, default_branch: str | None = None, url: str | None = None, ref: str | None = None, path: tmt.utils.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
- name: str | 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.
- class tmt.base.Link(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, note: str | None = None)
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’],Union[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'], Union[str, tmt.base._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
Linkinstance.[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']
- 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'], Union[str, tmt.base._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: targetone.Output of this method is fully compatible with specification, and when given to
from_spec(), it shall create aLinkinstance 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:
objectA container to use for searching links.
relationandtargetfields hold regular expressions that are to be searched for in the corresponding fields ofLinkinstances.- 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
LinkNeedleinstance.[1] https://tmt.readthedocs.io/en/stable/spec/plans.html#fmf
- relation: str = '.*'
- target: str = '.*'
- class tmt.base.Links(*, data: 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'], Union[str, tmt.base._RawFmfId]] | list[Union[str, tmt.base._RawFmfId, dict[Literal['verifies', 'verified-by', 'implements', 'implemented-by', 'documents', 'documented-by', 'blocks', 'blocked-by', 'duplicates', 'duplicated-by', 'parent', 'child', 'relates', 'test-script', 'note'], Union[str, tmt.base._RawFmfId]]]] | None = None)
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’],Union[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[tmt.base.Link]
Get links with given relation, all by default
- has_link(needle: LinkNeedle | None = None) bool
Check whether this set of links contains a matching link.
If
needleis left unspecified, method would take all links into account, as if theneedlewas match all possible links (.*:.*). Method would then answer the question “are there any links at all?”- Parameters:
needle – if set, only links matching
needleare considered. If not set, method considers all present links.- Returns:
Trueif there are matching links,Falseotherwise.
- 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'], Union[str, tmt.base._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: targetone.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.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
- static edit_template(raw_content: str) str
Edit the default template with custom values
- property environment: dict[str, str]
Return combined environment from plan data and command line
- gate: list[str]
- go() None
Execute the plan
- header() None
Show plan name and summary
Include one blank line to separate plans
- property is_remote_plan_reference: bool
Check whether the plan is a remote plan reference
- lint_discover_unknown_method() Iterator[tuple[tmt.lint.LinterOutcome, str]]
P004: discover step methods must be known
- lint_execute_not_defined() Iterator[tuple[tmt.lint.LinterOutcome, str]]
P002: execute step must be defined with “how”
- lint_execute_unknown_method() Iterator[tuple[tmt.lint.LinterOutcome, str]]
P003: execute step methods must be known
- lint_fmf_remote_ids_valid() Iterator[tuple[tmt.lint.LinterOutcome, str]]
P005: remote fmf ids must be valid
- lint_phases_have_guests() Iterator[tuple[tmt.lint.LinterOutcome, str]]
P007: step phases require existing guests and roles
- lint_unique_names() Iterator[tuple[tmt.lint.LinterOutcome, str]]
P006: phases must have unique names
- lint_unknown_keys() Iterator[tuple[tmt.lint.LinterOutcome, str]]
P001: all keys are known
- plan_environment_file
- 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, logger: Logger)
Bases:
CommonTest run, a container of plans
Initialize tree, workdir and plans
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- property environment: dict[str, str]
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. Doest 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[tmt.base.Plan]
Test plans for execution
- runner
- save() None
Save list of selected plans and enabled steps
- class tmt.base.RunData(root: str | None, plans: list[str] | None, steps: list[str], environment: dict[str, str], remove: bool)
Bases:
SerializableContainer- environment: dict[str, str]
- 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, relative_indent: int = 1, cli_invocation: tmt.cli.CliInvocation | None = None, logger: Logger, **kwargs: Any)
Bases:
CommonStatus 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
- 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
- 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[tmt.base.Link]
Return links to relevant documentation
- example: list[str]
- classmethod from_tree(tree: Tree) list[tmt.base.Story]
Gather list of instances of this class in a given tree.
Helpful when looking for objects of a class derived from
Corein a given tree, encapsulating the mapping between core classes and tree search methods.- Parameters:
tree – tree to search for objects.
- property implemented: list[tmt.base.Link]
Return links to relevant source code
- lint_story() Iterator[tuple[tmt.lint.LinterOutcome, str]]
S002: story key must be defined
- lint_unknown_keys() Iterator[tuple[tmt.lint.LinterOutcome, str]]
S001: all keys are known
- 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[tmt.base.Link]
Return links to relevant test coverage
- class tmt.base.StoryPriority(value, names=None, *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[tmt.checks.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'
- environment: dict[str, str]
- 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[tmt.lint.LinterOutcome, str]]
T003: test directory path must be absolute
- lint_defined_test() Iterator[tuple[tmt.lint.LinterOutcome, str]]
T002: test script must be defined
- lint_legacy_coverage_key() Iterator[tuple[tmt.lint.LinterOutcome, str]]
T006: coverage has been obsoleted by link
- lint_legacy_relevancy_rules() Iterator[tuple[tmt.lint.LinterOutcome, str]]
T005: relevancy has been obsoleted by adjust
- lint_manual_test_path_exists() Iterator[tuple[tmt.lint.LinterOutcome, str]]
T007: manual test path is not an actual path
- lint_manual_valid_markdown() Iterator[tuple[tmt.lint.LinterOutcome, str]]
T008: manual test should be valid markdown
- lint_path_exists() Iterator[tuple[tmt.lint.LinterOutcome, str]]
T004: test directory path must exist
- lint_require_type_field() Iterator[tuple[tmt.lint.LinterOutcome, str]]
T009: require fields should have type field
- lint_unknown_keys() Iterator[tuple[tmt.lint.LinterOutcome, str]]
T001: all keys are known
- manual: bool = False
- recommend: list[Union[tmt.base.DependencySimple, tmt.base.DependencyFmfId, tmt.base.DependencyFile]]
- require: list[Union[tmt.base.DependencySimple, tmt.base.DependencyFmfId, tmt.base.DependencyFile]]
- result: str = 'respect'
- serial_number: int = 0
- show() None
Show test details
- 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, logger: Logger)
Bases:
CommonTest 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[tmt.base.LinkNeedle] | None = None, excludes: list[str] | None = None) list[tmt.base.Plan]
Search available plans
- 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[tmt.base.LinkNeedle] | None = None, excludes: list[str] | None = None) list[tmt.base.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[tmt.base.LinkNeedle] | None = None, excludes: list[str] | None = None) list[tmt.base.Test]
Search available tests
- property tree: Tree
Initialize tree only when accessed
- tmt.base.assert_simple_dependencies(dependencies: list[Union[tmt.base.DependencySimple, tmt.base.DependencyFmfId, tmt.base.DependencyFile]], error_message: str, logger: Logger) list[tmt.base.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
adjustrules 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.normalize_require(key_address: str, raw_require: str | _RawDependencyFmfId | _RawDependencyFile | list[Union[str, tmt.base._RawDependencyFmfId, tmt.base._RawDependencyFile]] | None, logger: Logger) list[Union[tmt.base.DependencySimple, tmt.base.DependencyFmfId, tmt.base.DependencyFile]]
Normalize content of
requirekey.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.normalize_test_environment(key_address: str, value: dict[str, Any] | None, logger: Logger) dict[str, str]
Normalize value of tests’
environmentkey
- 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.cli module
Command line interface for the Test Management Tool
- class tmt.cli.CliInvocation(context: Context | None, options: dict[str, Any])
Bases:
objectA single CLI invocation of a tmt subcommand.
Bundles together the Click context and options derived from it. A context alone might be good enough, but sometimes tmt needs to modify saved options. For custom command line options injected manually ‘sources’ is used to keep the parameter source.
Serves as a clear boundary between invocations of classes representing various tmt subcommands and groups.
- classmethod from_context(context: Context) CliInvocation
- classmethod from_options(options: dict[str, Any]) CliInvocation
Inject custom options coming from the command line
- option_sources
- options: dict[str, Any]
- class tmt.cli.Context(command: Command, parent: Context | None = None, info_name: str | None = None, obj: Any | None = None, auto_envvar_prefix: str | None = None, default_map: MutableMapping[str, Any] | None = None, terminal_width: int | None = None, max_content_width: int | None = None, resilient_parsing: bool = False, allow_extra_args: bool | None = None, allow_interspersed_args: bool | None = None, ignore_unknown_options: bool | None = None, help_option_names: List[str] | None = None, token_normalize_func: Callable[[str], str] | None = None, color: bool | None = None, show_default: bool | None = None)
Bases:
ContextCustom
click.Context-like class for typing purposes.Objects of this class are never instantiated, it serves only as a type stub in commands below, to simplify handling and static analysis of
context.obj. There is no added functionality, the only change is a much narrower type ofobjattribute.This class shall be used instead of the original
click.Context. Click is obviously not aware of our type annotations, andcontextobjects managed by Click would always be of typeclick.Context, we would just convince mypy theirobjattribute is no longerAny.- obj: ContextObject
the user object stored.
- class tmt.cli.ContextObject(cli_context: ~tmt.cli.Context, logger: ~tmt.log.Logger, common: ~tmt.utils.Common, fmf_context: ~tmt.utils.FmfContext, tree: ~tmt.base.Tree, steps: set[str] = <factory>, clean: ~tmt.base.Clean | None = None, clean_logger: ~tmt.log.Logger | None = None, clean_partials: ~collections.defaultdict[str, list[typing.Callable[[], bool]]] = <factory>, run: ~tmt.base.Run | None = None)
Bases:
objectClick Context Object container.
In Click terms, this is “an arbitrary object of user data.” In this container, tmt CLI code stores all structures relevant for the command execution. The container itself is then attached to
click.Contextobject Click manages across commands.- clean_partials: defaultdict[str, list[Callable[[], bool]]]
- fmf_context: FmfContext
- steps: set[str]
- class tmt.cli.CustomGroup(name: str | None = None, commands: MutableMapping[str, Command] | Sequence[Command] | None = None, **attrs: Any)
Bases:
GroupCustom Click Group
- class tmt.cli.TmtExitCode(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
Bases:
IntEnum- ALL_TESTS_SKIPPED = 4
Tests were executed, and all reported the
skipresult.
- ERROR = 2
Errors occured during test execution.
- FAIL = 1
There was a fail or warn identified, but no error.
- NO_RESULTS_FOUND = 3
No test results found.
- SUCCESS = 0
At least one test passed, there was no fail, warn or error.
- tmt.cli.do_lint(context: Context, klasses: list[Union[type[tmt.base.Test], type[tmt.base.Plan], type[tmt.base.Story]]], list_checks: bool, failed_only: bool, enable_checks: list[str], disable_checks: list[str], enforce_checks: list[str], outcomes: list[tmt.lint.LinterOutcome], **kwargs: Any) int
Core of all
lintcommands
- tmt.cli.finito(click_context: Context, commands: Any, *args: Any, **kwargs: Any) None
Run tests if run defined
- tmt.cli.pass_context(fn: Callable[Concatenate[Context, P], R]) Callable[P, R]
Custom
click.pass_context()-like decorator.Complementing the
Context, the goal of this decorator to announce the correct type of thecontextparameter. The original decorator annotates the parameter asclick.Context, but that is not what our command callables accept. So, on this boundary between tmt code andclickAPI, we trick type checkers by isolating the necessarytype: ignore[arg-type].
- tmt.cli.perform_clean(click_context: Context, commands: Any, *args: Any, **kwargs: Any) None
Perform clean actions in the correct order.
We need to ensure that guests are always cleaned before the run workdirs even if the user specified them in reverse order.
- tmt.cli.setup_completion(shell: str, install: bool) None
Setup completion based on the shell
tmt.convert module
Convert metadata into the new format
- tmt.convert.add_link(target: str, data: dict[str, Any], system: int = 1, type_: str = 'relates') None
Add relevant link into data under the ‘link’ key
- 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) 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) 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) 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) 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]) 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) 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]) 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.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/latest/spec/plans.html#hardware
- class tmt.hardware.And(constraints: list[tmt.hardware.BaseConstraint] | None = None)
Bases:
CompoundConstraintRepresents constraints that are grouped in
andfashion.Hold constraints that are grouped in
andfashion.- Parameters:
constraints – list of constraints to group.
- variants(members: list[tmt.hardware.Constraint] | None = None) Iterator[list[tmt.hardware.Constraint]]
Generate all distinct variants of constraints covered by this one.
Since the
andreducer 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/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/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/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[tmt.hardware.Constraint]
Pick one of the available variants of this contraints.
As the contraint 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[tmt.hardware.Constraint] | None = None) Iterator[list[tmt.hardware.Constraint]]
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.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 GiBcpu.processors != 4=>cpu,None,processors,!=,4disk[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,Nonecpu.processors=>cpu,None,processorsdisk[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
valuepart 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,operatorandvalue, 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:
BaseConstraintBase 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 contraints.
- property size: int
- to_spec() Any
Convert to a form suitable for saving in a specification file
See https://tmt.readthedocs.io/en/stable/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:
Trueif the given constraint or its children use given constraint name.
- variants(members: list[tmt.hardware.Constraint] | None = None) Iterator[list[tmt.hardware.Constraint]]
Generate all distinct variants of constraints covered by this one.
Since the
andreducer 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: int | Size | str | bool, raw_value: str, unit: str | None = None, original_constraint: Constraint | None = None)
Bases:
BaseConstraintA 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.
- expand_name() ConstraintNameComponents
Expand constraint name into its components.
- Returns:
tuple consisting of constraint name components: name, optional indices, child properties, etc.
- classmethod from_specification(name: str, raw_value: str, as_quantity: bool = True, as_cast: Callable[[str], int | Size | str | bool] | None = None, original_constraint: Constraint | None = None) T
Parse raw constraint specification into our internal representation.
- Parameters:
name – name of the constraint.
raw_value – raw value of the constraint.
as_quantity – if set, value is treated as a quantity containing also unit, and as such the raw value is converted to :py:class`pint.Quantity` instance.
as_cast – if specified, this callable is used to convert raw value to its final type.
original_constraint – when specified, new constraint logically belongs to
original_constraint, possibly representing one of its aspects.
- Raises:
ParseError – when parsing fails.
- Returns:
a
Constraintrepresenting the given specification.
- name: str
- operator_handler: Callable[[Any, Any], bool]
- original_constraint: Constraint | 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/classes.html#class-conversions for more details.
See
from_spec()for its counterpart.
- unit: str | None = None
- 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:
Trueif the given constraint or its children use given constraint name.
- value: int | Size | str | bool
- variants(members: list[tmt.hardware.Constraint] | None = None) Iterator[list[tmt.hardware.Constraint]]
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:
objectComponents 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:
NamedTupleComponents of a constraint name.
Create new instance of ConstraintNameComponents(name, peer_index, child_name)
- child_name: str | None
sizeofdisk[1].size
- name: str
diskofdisk[1].size
- peer_index: int | None
1ofdisk[1].size
- tmt.hardware.ConstraintValue
A type of constraint values.
alias of
Union[int,Size,str,bool]
- 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/classes.html#class-conversions for more details.
See
to_spec()for its counterpart.
- report_support(*, names: list[str] | None = None, check: Callable[[Constraint], 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
namesandcheckare optional, and both can be used and combined. First, thenameslist is checked, if a constraint is not found,checkis 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_supportcaller. 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_supportcaller.
- spec: Any
- to_minimal_spec() Any
Convert to specification, skip default values
See https://tmt.readthedocs.io/en/stable/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/classes.html#class-conversions for more details.
See
from_spec()for its counterpart.
- class tmt.hardware.Operator(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
Bases:
EnumBinary operators defined by specification.
- CONTAINS = 'contains'
- EQ = '=='
- GT = '>'
- GTE = '>='
- LT = '<'
- LTE = '<='
- MATCH = '~'
- NEQ = '!='
- NOTCONTAINS = 'not contains'
- NOTMATCH = '!~'
- class tmt.hardware.Or(constraints: list[tmt.hardware.BaseConstraint] | None = None)
Bases:
CompoundConstraintRepresents constraints that are grouped in
orfashion.Hold constraints that are grouped in
orfashion.- Parameters:
constraints – list of constraints to group.
- variants(members: list[tmt.hardware.Constraint] | None = None) Iterator[list[tmt.hardware.Constraint]]
Generate all distinct variants of constraints covered by this one.
Since the
anyreducer allows any child constraints to be satisfied for the whole group to evaluate asTrue, 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:
MetadataErrorRaised 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()orall().alias of
Callable[[Iterable[bool]],bool]
- 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:
Trueif 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:
Trueifneedleis not inhaystack.
- 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:
Trueif 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 contraint 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.
memoryorcpu. For indexable constraints, seeungroupify_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 contraint 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.
diskornetwork. For non-indexable constraints, seeungroupify().
tmt.identifier module
- exception tmt.identifier.IdError
Bases:
ExceptionGeneral Identifier Error
- 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 ``[CTPS]\d\d\d`` regular expression:
# ``C``ommon, ``T``est, ``P``lan, ``S``tory, 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-checksoutput.
- 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[tmt.lint.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[tmt.lint.Linter] | None = None) tuple[bool, list[tuple[tmt.lint.Linter, tmt.lint.LinterOutcome, tmt.lint.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
lintersmakesenable_checksanddisable_checksignored.
- Returns:
a tuple of two items: a boolean reporting whether the instance passed the test, and a list of
LinterRulingitems, 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[tmt.lint.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[tmt.lint.LinterOutcome, str]]])
Bases:
objectA single linter
- callback: Callable[[Lintable], Iterator[tuple[tmt.lint.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
- tmt.lint.LinterCallback
A linter itself, a callable method.
alias of
Callable[[Lintable],Iterator[tuple[LinterOutcome,str]]]
- class tmt.lint.LinterOutcome(value, names=None, *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[tmt.lint.Linter, tmt.lint.LinterOutcome, tmt.lint.LinterOutcome, str]], outcomes: list[tmt.lint.LinterOutcome] | None = None) Iterator[tuple[tmt.lint.Linter, tmt.lint.LinterOutcome, tmt.lint.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[tmt.lint.Linter, tmt.lint.LinterOutcome, tmt.lint.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:
_FormatterInitialize 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 orstring.Templateformatting in your format string.Changed in version 3.2: Added the
styleparameter.
- class tmt.log.ConsoleHandler(stream=None)
Bases:
StreamHandlerInitialize the handler.
If stream is not specified, sys.stderr is used.
- class tmt.log.DebugLevelFilter(name='')
Bases:
FilterInitialize 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 | int | bool | float | 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:
objecttmt’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[tmt.log.Topic]
- logger_verbosity_level: int = 0
- message_debug_level: int | None = None
- message_verbosity_level: int | None = None
- shift: int = 0
- value: str | int | bool | float | tmt.utils.Path | tmt.utils.Command | tmt.utils.ShellScript | None = None
- class tmt.log.LogfileFormatter
Bases:
_FormatterInitialize 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 orstring.Templateformatting in your format string.Changed in version 3.2: Added the
styleparameter.
- class tmt.log.LogfileHandler(filepath: tmt.utils.Path)
Bases:
FileHandlerOpen the specified file and use it as the stream for logging.
- 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[tmt.log.Topic] | None = None, apply_colors_output: bool = True, apply_colors_logging: bool = True)
Bases:
objectA 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
Loggerinstance with given verbosity levels.- Parameters:
actual_logger – a
logging.Loggerinstance, 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
-vcommand-line option.debug_level – desired debugging level, usually derived from
-dcommand-line option.quiet – if set, all messages would be supressed, with the exception of warnings (
warn()), errors (fail()) and messages emitted withprint().
- 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
- 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.Loggerinstance to wrap. If not set, a default logger namedtmtis created.
- debug(key: str, value: str | int | bool | float | 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.Loggerinstance is created from our raw logger, forming a parent/child relationship betwen them, and it’s then wrapped withLoggerinstance. Settings of this logger are copied to new one, with the exception ofbase_shiftwhich is increased by one, effectively indenting all messages passing through new logger.- Parameters:
logger_name – optional name for the underlying
logging.Loggerinstance. 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.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 | int | bool | float | 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) None
- verbose(key: str, value: str | int | bool | float | 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 = 0) None
- class tmt.log.LoggingFunction(*args, **kwargs)
Bases:
Protocol
- class tmt.log.QuietnessFilter(name='')
Bases:
FilterInitialize 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=None, *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'
- KEY_NORMALIZATION = 'key-normalization'
- class tmt.log.TopicFilter(name='')
Bases:
FilterInitialize 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:
FilterInitialize 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-colorCLI option,NO_COLORor TMT_NO_COLORenvironment variables are set, colorization would be disabled.
- if either of the
- if either of the
--force-colorCLI option orTMT_FORCE_COLOR environment variable are set, colorization would be forcefully enabled.
- if either of the
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-colororTMT_FORCE_COLORare set, colors will be enabled despite any disabling options or environment variables.Note
All inputs with the exception of
isattyresult control both types of output, regular output and logging, and applies to both of them. Onlyisattyoutcome 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-colorCLI 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 | int | bool | float | 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
keyandvalueare specified,{key}: {value}message is rendered. Otherwise, justkeyis used alone. Ifvaluecontains 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
INDENTspaces.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:
objectVersion information and hint for obsolete options
- hint: str | None = None
- property rendered: str
- since: str
- tmt.options.create_method_class(methods: dict[str, click.core.Command]) type[click.core.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, 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 ofclick.option(), and are passed toclick.option(), with the exception ofdeprecatedparameter.- Parameters:
choices – if set, it sets
typeof the option toclick.Choices, and limits option values to those listed inchoices.deprecated – if set, it is rendered and appended to
help. This parameter is not passed toclick.option().
tmt.queue module
- class tmt.queue.GuestlessTask(guests: list['Guest'], logger: Logger)
Bases:
_TaskA task that does not run on a particular guest.
Note
This may sound unexpected, but there are tasks that need to be part of the queue, but need no specific guest to run on. Usualy, they handle the multihost environment on their own. See
tmt.steps.Loginandtmt.steps.Reboot.- go() Iterator[TaskOutcome[Self]]
Perform the task
- class tmt.queue.Queue(name: str, logger: Logger)
Bases:
list[TaskT]Queue class for running phases on guests
- enqueue_task(task: TaskT) None
Put new task into a queue
- run() Iterator[TaskOutcome[TaskT]]
Start crunching the queued phases.
Queued tasks are executed in the order, for each task/guest combination a
TaskOutcomeinstance is yielded.
- class tmt.queue.Task(guests: list['Guest'], logger: Logger)
Bases:
_TaskA task that should run on multiple guests at the same time
- go() Iterator[TaskOutcome[Self]]
Perform the task
- prepare_loggers(logger: Logger) dict[str, tmt.log.Logger]
Create loggers for a set of guests.
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.
- class tmt.queue.TaskOutcome(task: TaskT, logger: Logger, guest: Guest | None, exc: Exception | None)
Bases:
Generic[TaskT]Outcome of a queued task executed on a guest.
Bundles together interesting objects related to how the task has been executed, where and what was the result.
- exc: Exception | None
If set, an exception was raised by the running task, and the exception is saved in this field.
- guest: Guest | None
Guest on which the phase was executed. May be unset, some tasks may handle multiguest actions on their own.
- task: TaskT
A
_Taskinstace the outcome relates to.
tmt.result module
- class tmt.result.BaseResult(name: str, result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, note: str | None = None, log: list[tmt.utils.Path] = <factory>, start_time: str | None = None, end_time: str | None = None, duration: str | None = None)
Bases:
SerializableContainerDescribes what tmt knows about a result
- duration: str | None = None
- end_time: str | None = None
- log: list[tmt.utils.Path]
- name: str
- note: str | None = None
- 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, note: str | None = None, log: list[tmt.utils.Path] = <factory>, start_time: str | None = None, end_time: str | None = None, duration: str | None = None, event: ~tmt.checks.CheckEvent = CheckEvent.BEFORE_TEST)
Bases:
BaseResultDescribes what tmt knows about a single test check result
- event: CheckEvent = 'before-test'
- class tmt.result.Result(name: str, result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, note: str | None = None, log: list[tmt.utils.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, typing.Optional[str]] = <factory>, guest: ~tmt.result.ResultGuestData = <factory>, check: list[tmt.result.CheckResult] = <factory>, data_path: ~tmt.utils.Path | None = None)
Bases:
BaseResultDescribes what tmt knows about a single test result
- check: list[tmt.result.CheckResult]
- context: FmfContext
- static failures(log: str | None, msg_type: str = 'FAIL') str
Filter stdout and get only messages with certain type
- classmethod from_test_invocation(*, invocation: TestInvocation, result: ResultOutcome, note: str | None = None, ids: dict[str, Optional[str]] | None = None, log: list[tmt.utils.Path] | 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 aTestInvocationinstance.- Parameters:
invocation – a test invocation capturing the test run and results.
result – actual test outcome. It will be interpreted according to
Test.resultkey (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, Optional[str]]
- interpret_result(interpret: ResultInterpret) Result
Interpret result according to a given interpretation instruction.
Inspect and possibly modify
resultandnoteattributes, following theinterpretvalue.- Parameters:
interpret – how to interpret current result.
- Returns:
Resultinstance containing the updated result.
- serial_number: int = 0
- show(display_guest: bool = True) str
Return a nicely colored result with test name (and note)
- static summary(results: list[tmt.result.Result]) str
Prepare a nice human summary of provided results
- static total(results: list[tmt.result.Result]) dict[tmt.result.ResultOutcome, int]
Return dictionary with total stats for given results
- class tmt.result.ResultGuestData(name: str = 'default-0', role: str | None = None)
Bases:
SerializableContainerDescribes what tmt knows about a guest the result was produced on
- name: str = 'default-0'
- role: str | None = None
- tmt.result.ResultIds
A type of collection IDs tracked for a single result.
alias of
dict[str,Optional[str]]
- class tmt.result.ResultInterpret(value, names=None, *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'
- SKIP = 'skip'
- WARN = 'warn'
- XFAIL = 'xfail'
- classmethod is_result_outcome(value: ResultInterpret) bool
- class tmt.result.ResultOutcome(value, names=None, *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
- tmt.result.results_to_exit_code(results: list[tmt.result.Result]) int
Map results to a tmt exit code
tmt.trying module
Easily try tests and experiment with guests
- class tmt.trying.Try(*, tree: Tree, logger: Logger, **kwargs: Any)
Bases:
CommonJust store the tree
- check_tests() None
Check for available tests
- check_tree() None
Make sure there is a sane metadata tree
- choose_action() str
Print menu, get next action
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- get_default_plans(run: Run) list[tmt.base.Plan]
Get default plan from user config or the standard template
- go() None
Run the interactive session
- prompt_debug() None
Choose the right debug level
- prompt_verbose() None
Ask for the desired verbosity level
- welcome() None
Welcome message with summary of what we’re going to try
tmt.utils module
Test Metadata Utilities
- class tmt.utils.CentOSDistGit
Bases:
DistGitHandlerCentOS Handler
- lookaside_server: str = 'https://sources.stream.centos.org/sources'
- re_source: Pattern[str] = re.compile('^(\\w+) \\(([^)]+)\\) = ([0-9a-fA-F]+)$')
- remote_substring: Pattern[str] = re.compile('redhat/centos')
- usage_name: str = 'centos'
- class tmt.utils.Command(*elements: str | Path)
Bases:
objectA command with its arguments.
- run(*, cwd: Path | None, shell: bool = False, env: dict[str, str] | None = None, dry: bool = False, join: bool = False, interactive: bool = False, timeout: int | None = None, message: str | None = None, friendly_command: str | None = None, log: LoggingFunction | None = None, silent: bool = False, caller: Common | None = None, logger: Logger) CommandOutput
Run command, give message, handle errors.
- Parameters:
cwd – if set, command would be executed in the given directory, otherwise the current working directory is used.
shell – if set, the command would be executed in a shell.
env – environment variables to combine with the current environment before running the command.
dry – if set, the command would not be actually executed.
join – if set, stdout and stderr of the command would be merged into a single output text.
interactive – if set, the command would be executed in an interactive manner, i.e. with stdout and stdout connected to terminal for live interaction with user.
timeout – if set, command would be interrupted, if still running, after this many seconds.
message – if set, it would be logged for more friendly logging.
friendly_command – if set, it would be logged instead of the command itself, to improve visibility of the command in logging output.
log – a logging function to use for logging of command output. By default,
logger.debugis used.silent – if set, logging of steps taken by this function would be reduced.
caller – optional “parent” of the command execution, used for better linked exceptions.
logger – logger to use for logging.
- Returns:
command output, bundled in a
CommandOutputtuple.
- to_element() str
Convert a command to a shell command line element.
Use when a command or just a list of command options should become a part of another command. Common examples of such “higher level” commands would be would be
rsync -eoransible-playbook --ssh-common-args.
- to_popen() list[str]
Convert a command to form accepted by
subprocess.Popen
- to_script() ShellScript
Convert a command to a shell script.
Use when a command is supposed to become a part of a shell script.
- class tmt.utils.CommandOutput(stdout: str | None, stderr: str | None)
Bases:
object- stderr: str | None
- stdout: str | None
- class tmt.utils.Common(*, parent: CommonDerivedType | None = None, name: str | None = None, workdir: Literal[True] | Path | None = None, relative_indent: int = 1, cli_invocation: CliInvocation | None = None, logger: Logger, **kwargs: Any)
Bases:
_CommonBaseCommon shared stuff
Takes care of command line context, options and workdir handling. Provides logging functions info(), verbose() and debug(). Implements read() and write() for comfortable file access. Provides the run() method for easy command execution.
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.
- cli_invocation: CliInvocation | None = None
- property clone_dirpath: Path
Path for cloning into
Used internally for picking specific libraries (or anything else) from cloned repos for filtering purposes, it is removed at the end of relevant step.
- debug(key: str, value: str | int | bool | float | Path | Command | ShellScript | None = None, color: str | None = None, shift: int = 0, level: int = 1, topic: Topic | None = None) None
Show message if in requested debug mode level
In quiet mode debug messages are not displayed.
- property debug_level: int
The current debug level applied to this object
- fail(message: str, shift: int = 0) None
Show a red failure message on info level, send to stderr
- ignore_class_options: bool = False
- info(key: str, value: str | int | bool | float | Path | Command | ShellScript | None = None, color: str | None = None, shift: int = 0) None
Show a message unless in quiet mode
- property is_dry_run: bool
Whether the current run is a dry-run
- property is_feeling_safe: bool
Whether the current run is allowed to run unsafe actions
- property is_forced_run: bool
Whether the current run is allowed to overwrite files and data
- property name: str
- opt(option: str, default: Any | None = None) Any
Get an option from the command line options
Checks also parent options. For flags (boolean values) parent’s True wins over child’s False (e.g. run –quiet enables quiet mode for all included plans and steps).
For options that can be used multiple times, the child overrides the parent if it was defined (e.g. run -av provision -vvv runs all steps except for provision in mildly verbose mode, provision is run with the most verbosity).
Environment variables override command line options.
- print(text: str, color: str | None = None, shift: int = 0) None
Print out an output.
This method is supposed to be used for emitting a command output. Not to be mistaken with logging - errors, warnings, general command progress, and so on.
print()emits even when--quietis used, as the option suppresses logging but not the actual command output.
- property quietness: bool
The current quietness level applied to this object
- run(command: Command, friendly_command: str | None = None, silent: bool = False, message: str | None = None, cwd: Path | None = None, ignore_dry: bool = False, shell: bool = False, env: dict[str, str] | None = None, interactive: bool = False, join: bool = False, log: LoggingFunction | None = None, timeout: int | None = None) CommandOutput
Run command, give message, handle errors
Command is run in the workdir be default. In dry mode commands are not executed unless ignore_dry=True. Environment is updated with variables from the ‘env’ dictionary.
Output is logged using self.debug() or custom ‘log’ function. A user friendly command string ‘friendly_command’ will be shown, if provided, at the beginning of the command output.
Returns named tuple CommandOutput.
- safe_name
A safe variant of the name which does not contain special characters.
Spaces and other special characters are removed to prevent problems with tools which do not expect them (e.g. in directory names).
- classmethod store_cli_invocation(context: Context | None, options: dict[str, Any] | None = None) CliInvocation
Record a CLI invocation and options it carries for later use.
Warning
The given context is saved into a class variable, therefore it will function as a “default” context for instances on which
store_cli_invocation()has not been called.- Parameters:
context – CLI context representing the invocation.
options – Optional dictionary with custom options. If provided, context is ignored.
- Raises:
GeneralError – when there was a previously saved invocation already. Multiple invocations are not allowed.
- verbose(key: str, value: str | int | bool | float | Path | Command | ShellScript | None = None, color: str | None = None, shift: int = 0, level: int = 1, topic: Topic | None = None) None
Show message if in requested verbose mode level
In quiet mode verbose messages are not displayed.
- property verbosity_level: int
The current verbosity level applied to this object
- warn(message: str, shift: int = 0) None
Show a yellow warning message on info level, send to stderr
- class tmt.utils.Config
Bases:
objectUser configuration
Initialize config directory path
- fmf_tree
Return the configuration tree
- tmt.utils.ContainerClass
Types for generic “data container” classes and instances. In tmt code, this reduces to data classes and data class instances. Our
DataContainerare perfectly compatible data classes, but some helper methods may be used on raw data classes, not just onDataContainerinstances.alias of
type[DataclassInstance]
- exception tmt.utils.ConvertError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
MetadataErrorMetadata conversion error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- class tmt.utils.DataContainer
Bases:
objectA base class for objects that have keys and values
- property is_bare: bool
Check whether all keys are either unset or have their default value.
- Returns:
Trueif all keys either hold their default value or are not set at all,Falseotherwise.
- items() Iterator[tuple[str, Any]]
Iterate over key/value pairs
- classmethod keys() Iterator[str]
Iterate over key names
- to_dict() dict[str, Any]
Convert to a mapping.
See https://tmt.readthedocs.io/en/stable/classes.html#class-conversions for more details.
- to_minimal_dict() dict[str, Any]
Convert to a mapping with unset keys omitted.
See https://tmt.readthedocs.io/en/stable/classes.html#class-conversions for more details.
- values() Iterator[Any]
Iterate over key values
- exception tmt.utils.DiscoverError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
GeneralErrorDiscover step error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- class tmt.utils.DistGitHandler
Bases:
objectCommon functionality for DistGit handlers
- its_me(remotes: list[str]) bool
True if self can work with remotes
- lookaside_server: str
- re_source: Pattern[str]
- re_supported_extensions: Pattern[str] = re.compile('\\.((tar\\.(gz|Z|bz2|lz|lzma|lzo|xz|zst))|tgz|taz|taZ|tz2|tbz2|tbz|tlz|tzst)$')
- remote_substring: Pattern[str]
- sources_file_name = 'sources'
- uri = '/rpms/{name}/{filename}/{hashtype}/{hash}/{filename}'
- url_and_name(cwd: Path | None = None) list[tuple[str, str]]
Return list of urls and basenames of the used source
The ‘cwd’ parameter has to be a DistGit directory.
- usage_name: str
- exception tmt.utils.ExecuteError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
GeneralErrorExecute step error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- class tmt.utils.FedoraDistGit
Bases:
DistGitHandlerFedora Handler
- lookaside_server: str = 'https://src.fedoraproject.org/repo/pkgs'
- re_source: Pattern[str] = re.compile('^(\\w+) \\(([^)]+)\\) = ([0-9a-fA-F]+)$')
- remote_substring: Pattern[str] = re.compile('fedoraproject\\.org')
- usage_name: str = 'fedora'
- tmt.utils.FieldCLIOption
Type of field’s CLI option specification.
alias of
Union[str,Sequence[str]]
- tmt.utils.FieldExporter
Type of field’s exporter callback.
alias of
Callable[[T],Any]
- class tmt.utils.FieldMetadata(internal: bool = False, help: str | None = None, metavar: str | None = None, default: Any | None = None, default_factory: Callable[[], Any] | None = None, option_args: str | Sequence[str] | None = None, option_kwargs: dict[str, Any] | None = None, option_choices: None | Sequence[str] | Callable[[], Sequence[str]] = None, _option: Callable[[Any], Any] | None = None, normalize_callback: Callable[[str, Any, Logger], T] | None = None, serialize_callback: Callable[[T], Any] | None = None, unserialize_callback: Callable[[T], Any] | None = None, export_callback: Callable[[T], Any] | None = None)
Bases:
Generic[T]A dataclass metadata container used by our custom dataclass field management.
Attached to fields defined with
field()- default: Any | None = None
Field default value.
- default_factory: Callable[[], Any] | None = None
Field default value factory.
- export_callback: Callable[[T], Any] | None = None
An export callback to call when exporting the field (performed by
tmt.export.Exportable).
- help: str | None = None
Help text documenting the field.
- internal: bool = False
- metavar: str | None = None
If field accepts a value, this string would represent it in documentation.
- normalize_callback: Callable[[str, Any, Logger], T] | None = None
A normalization callback to call when loading the value from key source (performed by
NormalizeKeysMixin).
- property option: Callable[[Any], Any] | None
- option_args: str | Sequence[str] | None = None
CLI option parameters, for lazy option creation.
- option_choices: None | Sequence[str] | Callable[[], Sequence[str]] = None
- option_kwargs: dict[str, Any] | None = None
- serialize_callback: Callable[[T], Any] | None = None
- unserialize_callback: Callable[[T], Any] | None = None
- exception tmt.utils.FileError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
GeneralErrorFile operation error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- exception tmt.utils.FinishError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
GeneralErrorFinish step error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- class tmt.utils.FmfContext(data: dict[str, list[str]] | None = None)
Bases:
dict[str,list[str]]Represents an fmf context.
See https://tmt.readthedocs.io/en/latest/spec/context.html and https://fmf.readthedocs.io/en/latest/context.html.
- classmethod from_spec(key_address: str, spec: Any, logger: Logger) FmfContext
Convert from a specification file or from a CLI option.
See https://tmt.readthedocs.io/en/stable/spec/context.html for details on context.
- to_spec() dict[str, Any]
Convert to a form suitable for saving in a specification file
- exception tmt.utils.GeneralError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
ExceptionGeneral error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- exception tmt.utils.GitUrlError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
GeneralErrorRemote git url is not reachable
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- tmt.utils.KeySource
A type representing compatible sources of keys and values.
alias of
Union[dict[str,Any],Tree]
- class tmt.utils.ListFormat(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
Bases:
EnumHow to format lists
- LISTED = 1
Use
fmf.utils.listed().
- LONG = 3
One list item per line.
- SHORT = 2
Produce comma-separated list.
- class tmt.utils.LoadFmfKeysMixin(*, node: Tree, logger: Logger, **kwargs: Any)
Bases:
NormalizeKeysMixin
- exception tmt.utils.MetadataError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
GeneralErrorGeneral metadata error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- class tmt.utils.MultiInvokableCommon(**kwargs: Any)
Bases:
CommonInitialize 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.
- cli_invocation: CliInvocation | None = None
- cli_invocations: list[tmt.cli.CliInvocation] = []
- classmethod store_cli_invocation(context: Context | None, options: dict[str, Any] | None = None) CliInvocation
Save a CLI context and options it carries for later use.
Warning
The given context is saved into a class variable, therefore it will function as a “default” context for instances on which
_save_cli_context_to_instance()has not been called.Warning
The given context will overwrite any previously saved context.
- Parameters:
context – CLI context to save.
options – Optional dictionary with custom options. If provided, context is ignored.
- exception tmt.utils.NormalizationError(key_address: str, raw_value: Any, expected_type: str, *args: Any, **kwargs: Any)
Bases:
SpecificationErrorRaised when a key normalization fails
Raised when a key normalization fails.
A subclass of
SpecificationError, but describing errors that appear in a very specific point of key loading in a unified manner.- Parameters:
key_address – the key in question, preferrably with detailed location, e.g.
/plans/foo:discover[0].tests.raw_value – input value, the one that failed the normalization.
expected_type – string description of expected, allowed types, as a hint in the error message.
- tmt.utils.NormalizeCallback
Type of field’s normalization callback.
alias of
Callable[[str,Any,Logger],T]
- class tmt.utils.NormalizeKeysMixin(**kwargs: Any)
Bases:
_CommonBaseMixin adding support for loading fmf keys into object attributes.
When invoked, annotated class-level variables are searched for in a given source container - a mapping, an fmf node, etc. - and if the key of the same name as the variable exists, its value is “promoted” to instance variable.
If a method named
_normalize_<variable name>exists, it is called with the fmf key value as its single argument, and its return value is assigned to instance variable. This gives class chance to modify or transform the original value when needed, e.g. to convert the original value to a type more suitable for internal processing.- items() Iterator[tuple[str, Any]]
Iterate over keys and their values.
Keys are yielded in the order: keys declared by parent classes first, then keys declared by the class itself, all following the order in which keys were defined in their respective classes.
- Yields:
pairs of key name and its value.
- classmethod keys() Iterator[str]
Iterate over key names.
Keys are yielded in the order: keys declared by parent classes first, then keys declared by the class itself, all following the order in which keys were defined in their respective classes.
- Yields:
key names.
- class tmt.utils.Path(*args, **kwargs)
Bases:
PosixPathConstruct a PurePath from one or several strings and or existing PurePath objects. The strings and path objects are combined so as to yield a canonicalized path, which is incorporated into the new PurePath object.
- exception tmt.utils.PrepareError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
GeneralErrorPrepare step error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- class tmt.utils.ProcessExitCodes(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
Bases:
IntEnum- TEST_PIDFILE_LOCK_FAILED = 122
- TEST_PIDFILE_UNLOCK_FAILED = 123
- TIMEOUT = 124
- classmethod is_pidfile(exit_code: int | None) bool
- exception tmt.utils.ProvisionError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
GeneralErrorProvision step error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- tmt.utils.RawCommandElement
A single element of raw command line in its
listform.alias of
Union[str,Path]
- exception tmt.utils.RebootTimeoutError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
ExecuteErrorReboot failed due to a timeout
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- class tmt.utils.RedHatGitlab
Bases:
DistGitHandlerRed Hat on Gitlab
- lookaside_server: str = 'http://pkgs.devel.redhat.com/repo'
- re_source: Pattern[str] = re.compile('^(\\w+) \\(([^)]+)\\) = ([0-9a-fA-F]+)$')
- remote_substring: Pattern[str] = re.compile('redhat/rhel/')
- usage_name: str = 'redhatgitlab'
- exception tmt.utils.ReportError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
GeneralErrorReport step error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- exception tmt.utils.RetryError(label: str, causes: list[Exception])
Bases:
GeneralErrorRetries unsuccessful
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- class tmt.utils.RetryStrategy(total=10, connect=None, read=None, redirect=None, status=None, other=None, allowed_methods=<object object>, status_forcelist=None, backoff_factor=0, raise_on_redirect=True, raise_on_status=True, history=None, respect_retry_after_header=True, remove_headers_on_redirect=<object object>, method_whitelist=<object object>)
Bases:
Retry- increment(*args: Any, **kwargs: Any) Retry
Return a new Retry object with incremented retry counters.
- Parameters:
response (
HTTPResponse) – A response object, or None, if the server did not return a response.error (Exception) – An error encountered during the request, or None if the response was received successfully.
- Returns:
A new
Retryobject.
- exception tmt.utils.RunError(message: str, command: Command, returncode: int, stdout: str | None = None, stderr: str | None = None, caller: Common | None = None, *args: Any, **kwargs: Any)
Bases:
GeneralErrorCommand execution error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- class tmt.utils.SerializableContainer
Bases:
DataContainerA mixin class for saving and loading objects
- classmethod default(key: str, default: Any = None) Any
- classmethod extract_from(obj: Any) SerializableContainerDerivedType
Extract keys from given object, and save them in a container
- classmethod from_serialized(serialized: dict[str, Any]) SerializableContainerDerivedType
Convert from a serialized form loaded from a file.
See https://tmt.readthedocs.io/en/stable/classes.html#class-conversions for more details.
See
to_serialized()for its counterpart.
- inject_to(obj: Any) None
Inject keys from this container into attributes of a given object
- to_serialized() dict[str, Any]
Convert to a form suitable for saving in a file.
See https://tmt.readthedocs.io/en/stable/classes.html#class-conversions for more details.
See
from_serialized()for its counterpart.
- static unserialize(serialized: dict[str, Any], logger: Logger) SerializableContainerDerivedType
Convert from a serialized form loaded from a file.
Similar to
from_serialized(), but this method knows nothing about container’s class, and will locate the correct module and class by inspecting serialized data. Discovered class’from_serialized()is then used to create the container.Used to transform data read from a YAML file into original containers when their classes are not know to the code. Restoring such containers requires inspection of serialized data and dynamic imports of modules as needed.
See https://tmt.readthedocs.io/en/stable/classes.html#class-conversions for more details.
See
to_serialized()for its counterpart.
- tmt.utils.SerializeCallback
Type of field’s serialization callback.
alias of
Callable[[T],Any]
- class tmt.utils.ShellScript(script: str)
Bases:
objectA shell script, a free-form blob of text understood by a shell.
A shell script, a free-form blob of text understood by a shell.
- Parameters:
script – the actual script to be encapsulated by
ShellScriptwrapper.
- classmethod from_scripts(scripts: list[tmt.utils.ShellScript]) ShellScript
Create a single script from many shorter ones.
Scripts are merged into a single
ShellScriptinstance, joined together with;character.- Parameters:
scripts – scripts to merge into one.
- to_element() str
Convert a shell script to a command element
- class tmt.utils.SpecBasedContainer
Bases:
Generic[SpecInT,SpecOutT],DataContainer- classmethod from_spec(spec: SpecInT) SpecBasedContainerT
Convert from a specification file or from a CLI option
See https://tmt.readthedocs.io/en/stable/classes.html#class-conversions for more details.
See
to_spec()for its counterpart.
- to_minimal_spec() SpecOutT
Convert to specification, skip default values
See https://tmt.readthedocs.io/en/stable/classes.html#class-conversions for more details.
See
from_spec()for its counterpart.
- to_spec() SpecOutT
Convert to a form suitable for saving in a specification file
See https://tmt.readthedocs.io/en/stable/classes.html#class-conversions for more details.
See
from_spec()for its counterpart.
- class tmt.utils.SpecBasedContainerT
A typevar bound to spec-based container base class. A stand-in for all classes derived from
SpecBasedContainer.alias of TypeVar(‘SpecBasedContainerT’, bound=
SpecBasedContainer)
- class tmt.utils.SpecInT
A typevar representing an input specification consumed by
SpecBasedContainer.alias of TypeVar(‘SpecInT’)
- class tmt.utils.SpecOutT
A typevar representing an output specification produced by
SpecBasedContainer.alias of TypeVar(‘SpecOutT’)
- exception tmt.utils.SpecificationError(message: str, validation_errors: list[tuple[jsonschema.exceptions.ValidationError, str]] | None = None, *args: Any, **kwargs: Any)
Bases:
MetadataErrorMetadata specification error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- class tmt.utils.Stopwatch
Bases:
AbstractContextManager[Stopwatch]- property duration: timedelta
- end_time: datetime
- start_time: datetime
- class tmt.utils.StreamLogger(log_header: str, *, stream: IO[bytes] | None = None, logger: LoggingFunction | None = None, click_context: Context | None = None)
Bases:
ThreadReading pipes of running process in threads.
Code based on: https://github.com/packit/packit/blob/main/packit/utils/logging.py#L10
This constructor should always be called with keyword arguments. Arguments are:
group should be None; reserved for future extension when a ThreadGroup class is implemented.
target is the callable object to be invoked by the run() method. Defaults to None, meaning nothing is called.
name is the thread name. By default, a unique name is constructed of the form “Thread-N” where N is a small decimal number.
args is a list or tuple of arguments for the target invocation. Defaults to ().
kwargs is a dictionary of keyword arguments for the target invocation. Defaults to {}.
If a subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing anything else to the thread.
- get_output() str | None
- run() None
Method representing the thread’s activity.
You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.
- class tmt.utils.StructuredField(text: str | None = None, version: int = 1, multi: bool = False)
Bases:
objectHandling multiple text data in a single text field
The StructuredField allows you to easily store and extract several sections of text data to/from a single text field. The sections are separated by section names in square brackets and can be hosted in other text as well.
The section names have to be provided on a separate line and there must be no leading/trailing white space before/after the brackets. The StructuredField supports two versions of the format:
Version 0: Simple, concise, useful when neither the surrounding text or the section data can contain lines which could resemble section names. Here’s an example of a simple StructuredField:
Note written by human. [section-one] Section one content. [section-two] Section two content. [section-three] Section three content. [end] Another note written by human.
Version 1: Includes unique header to prevent collisions with the surrounding text and escapes any section-like lines in the content:
Note written by human. [structured-field-start] This is StructuredField version 1. Please, edit with care. [section-one] Section one content. [section-two] Section two content. [structured-field-escape][something-resembling-section-name] [section-three] Section three content. [structured-field-end] Another note written by human.
Note that an additional empty line is added at the end of each section to improve the readability. This line is not considered to be part of the section content.
Besides handling the whole section content it’s also possible to store several key-value pairs in a single section, similarly as in the ini config format:
[section] key1 = value1 key2 = value2 key3 = value3
Provide the key name as the optional argument ‘item’ when accessing these single-line items. Note that the section cannot contain both plain text data and key-value pairs.
Example:
field = qe.StructuredField() field.set("project", "Project Name") field.set("details", "somebody", "owner") field.set("details", "2013-05-27", "started") field.set("description", "This is a description.\n" "It spans across multiple lines.\n") print field.save() [structured-field-start] This is StructuredField version 1. Please, edit with care. [project] Project Name [details] owner = somebody started = 2013-05-27 [description] This is a description. It spans across multiple lines. [structured-field-end] field.version(0) print field.save() [project] Project Name [details] owner = somebody started = 2013-05-27 [description] This is a description. It spans across multiple lines. [end]
Multiple values for the same key are supported as well. Enable this feature with ‘multi=True’ when initializing the structured field. If multiple values are present their list will be returned instead of a single string. Similarly use list for setting multiple values:
field = qe.StructuredField(multi=True) requirements = ['hypervisor=', 'labcontroller=lab.example.com'] field.set("hardware", requirements, "hostrequire") print field.save() [structured-field-start] This is StructuredField version 1. Please, edit with care. [hardware] hostrequire = hypervisor= hostrequire = labcontroller=lab.example.com [structured-field-end] print field.get("hardware", "hostrequire") ['hypervisor=', 'labcontroller=lab.example.com']
Initialize the structured field
Get or set the footer content
- get(section: str, item: str | None = None) str | list[str]
Return content of given section or section item
- header(content: str | None = None) str
Get or set the header content
- iterate() Iterator[tuple[str, str]]
Return (section, content) tuples for all sections
- load(text: str, version: int | None = None) None
Load the StructuredField from a string
- remove(section: str, item: str | None = None) None
Remove given section or section item
- save() str
Convert the StructuredField into a string
- sections() list[str]
Get the list of available sections
- set(section: str, content: Any, item: str | None = None) None
Update content of given section or section item
- version(version: int | None = None) int
Get or set the StructuredField version
- exception tmt.utils.StructuredFieldError(message: str, causes: list[Exception] | None = None, *args: Any, **kwargs: Any)
Bases:
GeneralErrorStructuredField parsing error
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- class tmt.utils.TimeoutHTTPAdapter(*args: Any, **kwargs: Any)
Bases:
HTTPAdapterSpice up request’s session with custom timeout.
- send(request: PreparedRequest, **kwargs: Any) Response
Send request.
All arguments are passed to superclass after enforcing the timeout.
- Parameters:
request – the request to send.
- tmt.utils.UnserializeCallback
Type of field’s unserialization callback.
alias of
Callable[[Any],T]
- class tmt.utils.UnusedStreamLogger(log_header: str)
Bases:
StreamLoggerSpecial variant of
StreamLoggerthat records no data.It is designed to make the implementation of merged streams easier in
Command.run(). Instance of this class is created to logstderrwhen, in fact,stderris merged intostdout. This class returns values compatible withCommandOutputnotion of “no output”.This constructor should always be called with keyword arguments. Arguments are:
group should be None; reserved for future extension when a ThreadGroup class is implemented.
target is the callable object to be invoked by the run() method. Defaults to None, meaning nothing is called.
name is the thread name. By default, a unique name is constructed of the form “Thread-N” where N is a small decimal number.
args is a list or tuple of arguments for the target invocation. Defaults to ().
kwargs is a dictionary of keyword arguments for the target invocation. Defaults to {}.
If a subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing anything else to the thread.
- get_output() str | None
- run() None
Method representing the thread’s activity.
You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.
- class tmt.utils.UpdatableMessage(key: str, enabled: bool = True, indent_level: int = 0, key_color: str | None = None, default_value_color: str | None = None, clear_on_exit: bool = False)
Bases:
AbstractContextManagerUpdatable message suitable for progress-bar-like reporting
Updatable message suitable for progress-bar-like reporting.
with UpdatableMessage('foo') as message: while ...: ... # check state of remote request, and update message state = remote_api.check() message.update(state)
- Parameters:
key – a string to use as the left-hand part of logged message.
enabled – if unset, no output would be performed.
indent_level – desired indentation level.
key_color – optional color to apply to
key.default_color – optional color to apply to value when
update()is called withcolorleft out.clear_on_exit – if set, the message area would be cleared when leaving the progress bar when used as a context manager.
- clear() None
Clear the message area
- update(value: str, color: str | None = None) None
Update progress message.
- Parameters:
value – new message to update message area with.
color – optional message color.
- class tmt.utils.ValidateFmfMixin(*, node: Tree, skip_validation: bool = False, raise_on_validation_error: bool = False, logger: Logger, **kwargs: Any)
Bases:
_CommonBaseMixin adding validation of an fmf node.
Loads a schema whose name is derived from class name, and uses fmf’s validate() method to perform the validation.
- tmt.utils.ValueFormatter
A type describing a per-type formatting helper.
alias of
Callable[[Any,Optional[int],Optional[str],ListFormat,Literal[True, False, ‘auto’]],Iterator[str]]
- exception tmt.utils.WaitingIncompleteError
Bases:
GeneralErrorWaiting incomplete
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- exception tmt.utils.WaitingTimedOutError(check: Callable[[], T], timeout: timedelta, check_success: bool = False)
Bases:
GeneralErrorWaiting ran out of time
General error.
- Parameters:
message – error message.
causes – optional list of exceptions that caused this one. Since
raise ... from ...allows only for a single cause, and some of our workflows may raise exceptions triggered by more than one exception, we need a mechanism for storing them. Our reporting will honor this field, and report causes the same way as__cause__.
- tmt.utils.ascii(text: Any) bytes
Transliterate special unicode characters into pure ascii
- tmt.utils.assert_window_size(window_size: int | None) None
Raise an exception if window size is zero or a negative integer.
Protects possible underflows in formatters employed by
format_value().
- class tmt.utils.cached_property(fn: Callable[[Any], T])
Bases:
Generic[T]
- tmt.utils.check_git_url(url: str) str
Check that a remote git url is accessible
- tmt.utils.clonable_git_url(url: str) str
Modify the git repo url so it can be cloned
- tmt.utils.container_field(container: ContainerClass, key: str) tuple[str, str, dataclasses.Field[Any], tmt.utils.FieldMetadata[Any]]
- tmt.utils.container_field(container: ContainerInstance, key: str) tuple[str, str, Any, dataclasses.Field[Any], tmt.utils.FieldMetadata[Any]]
Return a dataclass/data container field info by the field’s name.
Surprisingly,
dataclassespackage does not have a helper for this. One can iterate over fields, but there’s no public API for retrieving a field when one knows its name.- Parameters:
cls – a dataclass/data container class whose fields to search.
key – field name to retrieve.
- Raises:
GeneralError – when the field does not exist.
- tmt.utils.container_fields(container: type['DataclassInstance'] | DataclassInstance) Iterator[Field[Any]]
- tmt.utils.container_items(container: DataclassInstance) Iterator[tuple[str, Any]]
Iterate over key/value pairs in a container
- tmt.utils.container_keys(container: type['DataclassInstance'] | DataclassInstance) Iterator[str]
Iterate over key names in a container
- tmt.utils.container_values(container: DataclassInstance) Iterator[Any]
Iterate over values in a container
- tmt.utils.copytree(src: Path, dst: Path, symlinks: bool = False, dirs_exist_ok: bool = False) Path
Similar to shutil.copytree but with dirs_exist_ok for Python < 3.8
- tmt.utils.create_directory(*, path: Path, name: str, dry: bool = False, quiet: bool = False, logger: Logger) None
Create a new directory.
Before creating the directory, function checks whether it exists already - the existing directory is not removed and re-created.
The outcome of the operation will be logged in a debug log, but may also be sent to console with
quiet=False.- Parameters:
path – a path to be created.
name – a “label” of the path, used for logging.
dry – if set, directory would not be created. Still, the existence check will happen.
quiet – if set, an outcome of the operation would be logged to console.
logger – logger to use for logging.
- Raises:
FileError – when function tried to create the directory, but failed.
- tmt.utils.create_file(path: Path, content: str, name: str, dry: bool = False, force: bool = False, mode: int = 436, quiet: bool = False) None
Create a new file, handle errors
- tmt.utils.dataclass_normalize_field(container: Any, key_address: str, keyname: str, raw_value: Any, logger: Logger) Any
Normalize and assign a value to container field.
If there is a normalization callback defined for the field via
normalizeparameter offield(), the callback is called to coerceraw_value, and the return value is assigned to container field instead ofvalue.
- tmt.utils.default_branch(*, repository: Path, remote: str = 'origin', logger: Logger) str | None
Detect default branch from given local git repository
- tmt.utils.default_template_environment() Environment
Create a Jinja2 environment with default settings.
Adds common filters, and enables block trimming and left strip.
- tmt.utils.dict_to_yaml(data: dict[str, Any] | list[Any] | _RawFmfId, width: int | None = None, sort: bool = False, start: bool = False) str
Convert dictionary into yaml
- tmt.utils.distgit_download(*, distgit_dir: Path, target_dir: Path, handler_name: str | None = None, download_only: bool = False, caller: Common | None = None, logger: Logger) None
Download sources to the target_dir and possibly extract tarballs
distgit_dir is path to the DistGit repository
- tmt.utils.duplicates(values: Iterable[T | None]) Iterator[T]
Iterate over all duplicate values in
values
- tmt.utils.duration_to_seconds(duration: str) int
Convert sleep time format into seconds
- tmt.utils.effective_workdir_root() Path
Find out what the actual workdir root is.
If
TMT_WORKDIR_ROOTvariable is set, it is used as the workdir root. Otherwise, the default ofWORKDIR_ROOTis used.
- tmt.utils.environment_file_to_dict(*, filename: str, root: Path | None = None, logger: Logger) dict[str, str]
Read environment variables from the given file.
File should be in YAML format (
.yamlor.ymlsuffixes), or in dotenv format.dotenv file exampleA=B C=D
YAML file exampleA: B C: D
Path to each file should be relative to the metadata tree root.
Note
For loading environment variables from multiple files, see
environment_files_to_dict().
- tmt.utils.environment_files_to_dict(*, filenames: Iterable[str], root: Path | None = None, logger: Logger) dict[str, str]
Read environment variables from the given list of files.
Files should be in YAML format (
.yamlor.ymlsuffixes), or in dotenv format.dotenv file exampleA=B C=D
YAML file exampleA: B C: D
Path to each file should be relative to the metadata tree root.
Note
For loading environment variables from a single file, see
environment_file_to_dict(), which is a functionenvironment_files_to_dict()calls for each file, accumulating data from all input files.
- tmt.utils.environment_from_spec(*, raw_fmf_environment: Any = None, raw_fmf_environment_files: Any = None, raw_cli_environment: Any = None, raw_cli_environment_files: Any = None, file_root: Path | None = None, key_address: str | None = None, logger: Logger) dict[str, str]
Extract environment variables from various sources.
Combines various raw sources into a set of environment variables. Calls necessary functions to process environment files, dictionaries and CLI inputs.
All inputs are optional, and there is a clear order of preference, which is, from the most prefered:
--environmentCLI option (raw_cli_environment)--environment-fileCLI option (raw_cli_environment_files)environmentfmf key (raw_fmf_environment)environment-filefmf key (raw_fmf_environment_files)
- Parameters:
raw_fmf_environment – content of
environmentfmf key.Noneand a dictionary are accepted.raw_fmf_environment_files – content of
environment-filefmf key.Noneand a list of paths are accepted.raw_cli_environment – content of
--environmentCLI option.None, a tuple or a list are accepted.raw_cli_environment_files – content of –environment-file` CLI option.
None, a tuple or a list are accepted.
- Raises:
NormalizationError – when an input is of a type which is not allowed for that particular source.
- tmt.utils.environment_to_dict(*, variables: str | list[str], logger: Logger) dict[str, str]
Convert environment variables into a dictionary
Variables may be specified in the following two ways:
NAME=VALUE pairs
@foo.yaml
If “variable” starts with “@” character, it is treated as a path to a YAML file that contains “key: value” pairs which are then transparently loaded and added to the final dictionary.
In general, allowed inputs are the same as in “shell_to_dict” function, with the addition of “@foo.yaml” form: ‘X=1’ ‘X=1 Y=2 Z=3’ [‘X=1’, ‘Y=2’, ‘Z=3’] [‘X=1 Y=2 Z=3’, ‘A=1 B=2 C=3’] ‘TXT=”Some text with spaces in it”’ @foo.yaml @../../bar.yaml
- tmt.utils.field(*, default: bool, option: str | Sequence[str] | None = None, is_flag: bool = True, choices: None | Sequence[str] | Callable[[], Sequence[str]] = None, multiple: bool = False, metavar: str | None = None, envvar: str | None = None, deprecated: Deprecated | None = None, help: str | None = None, show_default: bool = False, internal: bool = False) bool
- tmt.utils.field(*, default: T, option: str | Sequence[str] | None = None, is_flag: bool = False, choices: None | Sequence[str] | Callable[[], Sequence[str]] = None, multiple: bool = False, metavar: str | None = None, envvar: str | None = None, deprecated: Deprecated | None = None, help: str | None = None, show_default: bool = False, internal: bool = False, normalize: Callable[[str, Any, Logger], T] | None = None, serialize: Callable[[T], Any] | None = None, unserialize: Callable[[Any], T] | None = None, exporter: Callable[[T], Any] | None = None) T
- tmt.utils.field(*, default_factory: Callable[[], T], option: str | Sequence[str] | None = None, is_flag: bool = False, choices: None | Sequence[str] | Callable[[], Sequence[str]] = None, multiple: bool = False, metavar: str | None = None, envvar: str | None = None, deprecated: Deprecated | None = None, help: str | None = None, show_default: bool = False, internal: bool = False, normalize: Callable[[str, Any, Logger], T] | None = None, serialize: Callable[[T], Any] | None = None, unserialize: Callable[[Any], T] | None = None, exporter: Callable[[T], Any] | None = None) T
Define a
DataContainerfield.Effectively a fancy wrapper over
dataclasses.field(), tailored for tmt code needs and simplification of various common tasks.- Parameters:
default – if provided, this will be the default value for this field. Passed directly to
dataclass.field(). It is an error to specify bothdefaultanddefault_factory.default_factory – if provided, it must be a zero-argument callable that will be called when a default value is needed for this field. Passed directly to
dataclass.field(). It is an error to specify bothdefaultanddefault_factory.option – one or more command-line option names. Passed directly to
click.option().is_flag – marks this option as a flag. Passed directly to
click.option().choices – if provided, the command-line option would accept only the listed input values. Passed to
click.option()as aclick.Choiceinstance.multiple – accept multiple arguments of the same name. Passed directly to
click.option().metavar – how the input value is represented in the help page. Passed directly to
click.option().envvar – environment variable used for this option. Passed directly to
click.option().deprecated – mark the option as deprecated Provide an instance of Deprecated() with version in which the option was obsoleted and an optional hint with the recommended alternative. A warning message will be added to the option help.
help – the help string for the command-line option. Multiline strings can be used,
textwrap.dedent()is applied before passinghelptoclick.option().show_default – show default value Passed directly to
click.option().internal – if set, the field is treated as internal-only, and will not appear when showing objects via
show()method, or in export created byCore._export().normalize – a callback for normalizing the input value. Consumed by
NormalizeKeysMixin.serialize – a callback for custom serialization of the field value. Consumed by
SerializableKeysMixin.unserialize – a callback for custom unserialization of the field value. Consumed by
SerializableKeysMixin.exporter – a callback for custom export of the field value. Consumed by
tmt.export.Exportable.
- tmt.utils.filter_paths(directory: Path, searching: list[str], files_only: bool = False) list[tmt.utils.Path]
Filter files for specific paths we are searching for inside a directory
Returns list of matching paths.
- tmt.utils.find_fmf_root(path: Path) list[tmt.utils.Path]
Search trough path and return all fmf roots that exist there
Returned list is ordered by path length, shortest one first.
Raise MetadataError if no fmf root is found.
- tmt.utils.flatten(lists: Iterable[list[T]], unique: bool = False) list[T]
“Flatten” a list of lists into a single-level list.
- Parameters:
lists – an iterable of lists to flatten.
unique – if set, duplicate items would be removed, leaving only a single instance in the final list.
- Returns:
list of items from all given lists.
- tmt.utils.fmf_id(*, name: str, fmf_root: Path, always_get_ref: bool = False, logger: Logger) FmfId
Return full fmf identifier of the node
- tmt.utils.format(key: str, value: None | bool | str | list[Any] | dict[Any, Any] = None, indent: int = 24, window_size: int = 79, wrap: Literal[True, False, 'auto'] = 'auto', key_color: str | None = 'green', value_color: str | None = 'black', list_format: ListFormat = ListFormat.LISTED) str
Nicely format and indent a key-value pair
- Parameters:
key – a key introducing the value.
value – an object to format.
indent – the key would be right-justified to this column.
window_size – rendering will try to fit produce lines whose length would exceed
window_size. A window not wide enough may result into not usingfmf.utils.listed()for lists, or wrapping lines in a text paragraph.wrap – if set to
True, always reformat text and wrap long lines; if set toFalse, preserve text formatting and make no changes; the default,auto, tries to rewrap lines as needed to obeywindow_size.key_color – if set, dictionary keys would be colorized by this color.
list_format – preferred list formatting. It may be ignored if
window_sizeis set and not wide enough to hold the desired formatting;ListFormat.LONGwould be the fallback choice.
- Returns:
a formatted string representation of
value.
- tmt.utils.format_value(value: Any, window_size: int | None = None, key_color: str | None = None, list_format: ListFormat = ListFormat.LISTED, wrap: Literal[True, False, 'auto'] = 'auto') str
Render a nicely-formatted string representation of a value.
- Parameters:
value – an object to format.
window_size – if set, rendering will try to produce lines whose length would not exceed
window_size. A window not wide enough may result into not usingfmf.utils.listed(), or wrapping lines in a text paragraph.key_color – if set, dictionary keys would be colorized by this color.
list_format – preferred list formatting. It may be ignored if
window_sizeis set and not wide enough to hold the desired formatting;ListFormat.LONGwould be the fallback choice.
- Returns:
a formatted string representation of
value.
- tmt.utils.generate_runs(path: Path, id_: str | None = None) Iterator[Path]
Generate absolute paths to runs from path
- tmt.utils.get_distgit_handler(remotes: list[str] | None = None, usage_name: str | None = None) DistGitHandler
Return the right DistGitHandler
Pick the DistGitHandler class which understands specified remotes or by usage_name.
- tmt.utils.get_distgit_handler_names() list[str]
All known distgit handlers
- tmt.utils.get_full_metadata(fmf_tree_path: Path, node_path: str) Any
Get full metadata for a node in any fmf tree
Go through fmf tree nodes using given relative node path and return full data as dictionary.
- tmt.utils.get_url_content(url: str) str
Get content of a given URL as a string.
- tmt.utils.git_add(*, path: Path, logger: Logger) None
Add path to the git index.
- Parameters:
path – path to add to the git index.
logger – used for logging.
- tmt.utils.git_clone(url: str, destination: Path, common: Common, env: dict[str, str] | None = None, shallow: bool = False, can_change: bool = True) CommandOutput
Git clone url to destination, retry without shallow if necessary
For shallow=True attempt to clone repository using –depth=1 option first. If not successful attempt to clone whole repo.
Common instance is used to run the command for appropriate logging. Environment is updated by ‘env’ dictionary.
Url can be modified with hardcode rules unless can_change=False is set.
- tmt.utils.git_root(*, fmf_root: Path, logger: Logger) Path | None
Find a path to the root of git repository containing an fmf root.
- Parameters:
fmf_root – path to an fmf root that is supposedly in a git repository.
logger – used for logging.
- Returns:
path to the git repository root, if fmf root lies in one, or
None.
- tmt.utils.inject_auth_git_url(url: str) str
Inject username or token to the git url
- Parameters:
url – original git repo url
- Returns:
URL with injected authentification based on pattern from the environment or unmodified URL
- tmt.utils.is_key_origin(node: Tree, key: str) bool
Find out whether the given key is defined in the given node.
- Parameters:
node – node to check.
key – key to check.
- Returns:
Trueif the key is defined innode, not by one of its parents,Falseotherwise.
- tmt.utils.is_selinux_supported() bool
Returns
trueif SELinux filesystem is supported by the kernel,falseotherwise.For detection
/proc/filesystemsis used, seeman 5 filesystemsfor details.
- tmt.utils.is_url(url: str) bool
Check if the given string is a valid URL.
- tmt.utils.json_to_list(data: Any) list[Any]
Convert json into list
- tmt.utils.key_to_option(key: str) str
Convert a key name to corresponding option name
- tmt.utils.listify(data: tuple[Any, ...] | list[Any] | str | dict[Any, Any], split: bool = False, keys: list[str] | None = None) list[Any] | dict[Any, Any]
Ensure that variable is a list, convert if necessary For dictionaries check all items or only those with provided keys. Also split strings on white-space/comma if split=True.
- tmt.utils.load_run(run: Run) tuple[bool, Optional[Exception]]
Load a run and its steps from the workdir
- tmt.utils.load_schema(schema_filepath: Path) dict[str, Any]
Load a JSON schema from a given filepath.
Recommended for general use, the method may apply some post-loading touches to the given schema, and unless caller is interested in the raw content of the file, this functions should be used instead of the real workhorse of schema loading,
_load_schema().
- tmt.utils.load_schema_store() dict[str, dict[str, Any]]
Load all available JSON schemas, and put them into a “store”.
Schema store is a simple mapping between schema IDs and schemas.
- tmt.utils.locate_key_origin(node: Tree, key: str) Tree | None
Find an fmf node where the given key is defined.
- Parameters:
node – node to begin with.
key – key to look for.
- Returns:
first node in which the key is defined,
Noneifnodenor any of its parents define it.
- tmt.utils.markdown_to_html(filename: Path) str
Convert markdown to html
Expects: Markdown document as a file. Returns: An HTML document as a string.
- tmt.utils.modify_environ(new_elements: dict[str, str]) Iterator[None]
A context manager for os.environ that restores the initial state
- tmt.utils.normalize_int(key_address: str, value: Any, logger: Logger) int
Normalize an integer.
For a field that takes an integer input. The field might be also left out, but it does have a default value.
- tmt.utils.normalize_optional_int(key_address: str, value: Any, logger: Logger) int | None
Normalize an integer that may be unset as well.
For a field that takes an integer input, but might be also left out, and has no default value.
- tmt.utils.normalize_path(key_address: str, value: Any, logger: Logger) Path | None
Normalize content of the test path key
- tmt.utils.normalize_path_list(key_address: str, value: None | str | list[str], logger: Logger) list[tmt.utils.Path]
Normalize a path-or-list-of-paths input value.
This is a fairly common input format present mostly in fmf nodes where tmt, to make things easier for humans, allows this:
foo: /foo/bar foo: - /foo/bar - /baz
Internally, we should stick to one type only, and make sure whatever we get on the input, a list of strings would be the output.
- Parameters:
value – input value from key source.
- tmt.utils.normalize_shell_script(key_address: str, value: None | str, logger: Logger) ShellScript | None
Normalize a single shell script input that may be unset.
- Parameters:
value – input value from key source.
- tmt.utils.normalize_shell_script_list(key_address: str, value: None | str | list[str], logger: Logger) list[tmt.utils.ShellScript]
Normalize a string-or-list-of-strings input value.
This is a fairly common input format present mostly in fmf nodes where tmt, to make things easier for humans, allows this:
foo: bar foo: - bar - baz
Internally, we should stick to one type only, and make sure whatever we get on the input, a list of strings would be the output.
- Parameters:
value – input value from key source.
- tmt.utils.normalize_storage_size(key_address: str, value: Any, logger: Logger) int
Normalize a storage size.
As of now, it’s just a simple integer with units interpreted by the owning plugin. In the future, we want this function to switch to proper units and return
pint.Quantityinstead.
- tmt.utils.normalize_string_list(key_address: str, value: None | str | list[str], logger: Logger) list[str]
Normalize a string-or-list-of-strings input value.
This is a fairly common input format present mostly in fmf nodes where tmt, to make things easier for humans, allows this:
foo: bar foo: - bar - baz
Internally, we should stick to one type only, and make sure whatever we get on the input, a list of strings would be the output.
- Parameters:
value – input value from key source.
- tmt.utils.option_to_key(option: str) str
Convert an option name to corresponding key name
- tmt.utils.parse_dotenv(content: str) dict[str, str]
Parse dotenv (shell) format of variables
- tmt.utils.parse_yaml(content: str) dict[str, str]
Parse variables from yaml, ensure flat dictionary format
- tmt.utils.public_git_url(url: str) str
Convert a git url into a public format.
- Parameters:
url – an URL to convert.
- Returns:
URL that is publicly accessible without authentication, or the original URL if no applicable conversion was found.
- tmt.utils.quote(string: str) str
Surround a string with double quotes
- tmt.utils.remove_color(text: str) str
Remove ansi color sequences from the string
- tmt.utils.render_exception(exception: BaseException) Iterator[str]
Render the exception and its causes for printing
- tmt.utils.render_run_exception(exception: RunError) Iterator[str]
Render detailed output upon command execution errors for printing
- tmt.utils.render_run_exception_streams(stdout: str | None, stderr: str | None, verbose: int = 0) Iterator[str]
Render run exception output streams for printing
- tmt.utils.render_template(template: str, template_filepath: Path | None = None, environment: Environment | None = None, **variables: Any) str
Render a template.
- Parameters:
template – template to render.
template_filepath – path to the template file, if any.
environment – Jinja2 environment to use.
variables – variables to pass to the template.
- tmt.utils.render_template_file(template_filepath: Path, environment: Environment | None = None, **variables: Any) str
Render a template from a file.
- Parameters:
template_filepath – path to the template file.
environment – Jinja2 environment to use.
variables – variables to pass to the template.
- tmt.utils.resource_files(path: str | Path, package: str | module = 'tmt') Path
Helper function to get path of package file or directory.
A thin wrapper for
importlib.resources.files():files()returnsTraversableobject, though in our use-case it should always produce apathlib.PosixPathobject. Converting it totmt.utils.Pathinstance should be safe and stick to the “Pathonly!” rule in tmt’s code base.- Parameters:
path – file or directory path to retrieve, relative to the
packageroot.package – package in which to search for the file/directory.
- Returns:
an absolute path to the requested file or directory.
- tmt.utils.retry(func: Callable[[...], T], attempts: int, interval: int, label: str, logger: Logger, *args: Any, **kwargs: Any) T
Retry functionality to be used elsewhere in the code.
- Parameters:
func – function to be called with all unclaimed positional and keyword arguments.
attempts – number of tries to call the function
interval – amount of seconds to wait before a new try
label – action to retry
- Returns:
propagates return value of
func.
- class tmt.utils.retry_session(retries: int = 3, backoff_factor: float = 0.1, allowed_methods: tuple[str, ...] | None = None, status_forcelist: tuple[int, ...] | None = None, timeout: int | None = None)
Bases:
AbstractContextManagerContext manager for requests.Session() with retries and timeout
- static create(retries: int = 3, backoff_factor: float = 0.1, allowed_methods: tuple[str, ...] | None = None, status_forcelist: tuple[int, ...] | None = None, timeout: int | None = None) Session
- tmt.utils.rewrite_git_url(url: str, patterns: list[tuple[str, str]]) str
Rewrite git url based on supplied patterns
- Parameters:
url – an URL to modify
patterns – List of patterns to try in order
- Returns:
Modified url or the original one if no pattern was be applied.
- tmt.utils.sanitize_name(name: str, allow_slash: bool = True) str
Create a safe variant of a name that does not contain special characters.
Spaces and other special characters are removed to prevent problems with tools which do not expect them (e.g. in directory names).
- Parameters:
name – a name to sanitize.
allow_slash – if set, even a slash character,
/, would be replaced.
- tmt.utils.shell_to_dict(variables: str | list[str]) dict[str, str]
Convert shell-like variables into a dictionary
Accepts single string or list of strings. Allowed forms are: ‘X=1’ ‘X=1 Y=2 Z=3’ [‘X=1’, ‘Y=2’, ‘Z=3’] [‘X=1 Y=2 Z=3’, ‘A=1 B=2 C=3’] ‘TXT=”Some text with spaces in it”’
- tmt.utils.shell_variables(data: list[str] | tuple[str, ...] | dict[str, Any]) list[str]
Prepare variables to be consumed by shell
Convert dictionary or list/tuple of key=value pairs to list of key=value pairs where value is quoted with shlex.quote().
- tmt.utils.show_exception(exception: BaseException) None
Display the exception and its causes
- tmt.utils.uniq(values: list[T]) list[T]
Return a list of all unique items from
values
- tmt.utils.validate_fmf_node(node: Tree, schema_name: str, logger: Logger) list[tuple[jsonschema.exceptions.ValidationError, str]]
Validate a given fmf node
- tmt.utils.validate_git_status(test: Test) tuple[bool, str]
Validate that test has current metadata on fmf_id
Return a tuple (boolean, message) as the result of validation.
Checks that sources: - all local changes are committed - up to date on remote repository - .fmf/version marking fmf root is committed as well
When all checks pass returns (True, ‘’).
- tmt.utils.verdict(decision: bool, comment: str | None = None, good: str = 'pass', bad: str = 'fail', problem: str = 'warn', **kwargs: Any) bool
- tmt.utils.verdict(decision: None, comment: str | None = None, good: str = 'pass', bad: str = 'fail', problem: str = 'warn', **kwargs: Any) None
Print verdict in green, red or yellow based on the decision
The supported decision values are:
True …. good (green) False … bad (red) None …. problem (yellow)
Anything else raises an exception. Additional arguments are passed to the echo function. Returns back the decision.
- tmt.utils.wait(parent: Common, check: Callable[[], T], timeout: timedelta, tick: float = 30.0, tick_increase: float = 1.0) T
Wait for a condition to become true.
To test the condition state, a
checkcallback is called everytickseconds untilcheckreports a success. The callback may:decide the condition has been fulfilled. This is a successfull outcome,
checkshall then simply return, and waiting ends. Or,decide more time is needed. This is not a successfull outcome,
checkshall then raiseWaitingIncompleteexception, andwait()will try again later.
- Parameters:
parent – “owner” of the wait process. Used for its logging capability.
check – a callable responsible for testing the condition. Accepts no arguments. To indicate more time and attempts are needed, the callable shall raise
WaitingIncomplete, otherwise it shall return without exception. Its return value will be propagated bywait()up towait()’s. All other exceptions raised bycheckwill propagate towait()’s caller as well, terminating the wait.timeout – amount of time
wait()is alowed to spend waiting for successfull outcome ofcheckcall.tick – how many seconds to wait between two consecutive calls of
check.tick_increase – a multiplier applied to
tickafter every attempt.
- Returns:
value returned by
checkreporting success.- Raises:
GeneralError – when
tickis not a positive integer.WaitingTimedOutError – when time quota has been consumed.
- tmt.utils.web_git_url(url: str, ref: str, path: Path | None = None) str
Convert a public git url into a clickable web url format
Compose a clickable link from git url, ref and path to file for the most common git servers.
- tmt.utils.yaml_to_dict(data: Any, yaml_type: Literal['rt', 'safe', 'unsafe', 'base'] | None = None) dict[Any, Any]
Convert yaml into dictionary
- tmt.utils.yaml_to_list(data: Any, yaml_type: Literal['rt', 'safe', 'unsafe', 'base'] | None = 'safe') list[Any]
Convert yaml into list
Module contents
Test Management Tool