From 9d51a631830d0529ab177e5d15368329c4dde5ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20Prchl=C3=ADk?= Date: Mon, 12 Aug 2024 09:08:27 +0200 Subject: [PATCH] Add primitives for loading and saving step results (#2978) --- tmt/steps/__init__.py | 40 ++++++++++++++++++++++++++++++++++- tmt/steps/execute/__init__.py | 11 ++++------ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/tmt/steps/__init__.py b/tmt/steps/__init__.py index 46f5518d63..d004894242 100644 --- a/tmt/steps/__init__.py +++ b/tmt/steps/__init__.py @@ -8,7 +8,7 @@ import re import shutil import textwrap -from collections.abc import Iterable, Iterator +from collections.abc import Iterable, Iterator, Sequence from re import Pattern from typing import ( TYPE_CHECKING, @@ -60,6 +60,7 @@ import tmt.steps.discover import tmt.steps.execute from tmt.base import Plan + from tmt.result import BaseResult from tmt.steps.provision import Guest @@ -252,6 +253,9 @@ class _RawStepData(TypedDict, total=False): #: A type variable representing a return value of plugin's ``go()`` method. PluginReturnValueT = TypeVar('PluginReturnValueT') +#: A type variable representing a result type. +ResultT = TypeVar('ResultT', bound='BaseResult') + @dataclasses.dataclass class StepData( @@ -687,6 +691,40 @@ def save(self) -> None: } self.write(Path('step.yaml'), tmt.utils.dict_to_yaml(content)) + def _load_results( + self, + result_class: type[ResultT], + allow_missing: bool = False) -> list[ResultT]: + """ Load results of this step from the workdir """ + + try: + raw_results: list[Any] = tmt.utils.yaml_to_list(self.read(Path('results.yaml'))) + + return [ + result_class.from_serialized(raw_result) for raw_result in raw_results + ] + + except tmt.utils.FileError as exc: + if allow_missing: + self.debug(f'{self.__class__.__name__} results not found.', level=2) + return [] + + raise GeneralError('Cannot load step results.') from exc + + except Exception as exc: + raise GeneralError('Cannot load step results.') from exc + + def _save_results(self, results: Sequence['BaseResult']) -> None: + """ Save results of this step to the workdir """ + + try: + raw_results = [result.to_serialized() for result in results] + + self.write(Path('results.yaml'), tmt.utils.dict_to_yaml(raw_results)) + + except Exception as exc: + raise GeneralError('Cannot save step results.') from exc + def wake(self) -> None: """ Wake up the step (process workdir and command line) """ # Cleanup possible old workdir if called with --force, but not diff --git a/tmt/steps/execute/__init__.py b/tmt/steps/execute/__init__.py index 91f67734ee..1fd9468cea 100644 --- a/tmt/steps/execute/__init__.py +++ b/tmt/steps/execute/__init__.py @@ -986,17 +986,14 @@ def __init__( def load(self) -> None: """ Load test results """ super().load() - try: - results = tmt.utils.yaml_to_list(self.read(Path('results.yaml'))) - self._results = [Result.from_serialized(data) for data in results] - except tmt.utils.FileError: - self.debug('Test results not found.', level=2) + + self._results = self._load_results(Result, allow_missing=True) def save(self) -> None: """ Save test results to the workdir """ super().save() - results = [result.to_serialized() for result in self.results()] - self.write(Path('results.yaml'), tmt.utils.dict_to_yaml(results)) + + self._save_results(self.results()) def wake(self) -> None: """ Wake up the step (process workdir and command line) """