11from typing import TYPE_CHECKING , Any , Callable , Optional , TypedDict , cast
22
3- import fmf
3+ from fmf import Tree
44
55import tmt .utils
66from tmt .checks import Check , _RawCheck , normalize_test_checks
1414)
1515from tmt .log import Logger
1616from tmt .result import ResultInterpret
17- from tmt .steps import Step , _RawStepData
17+ from tmt .steps import STEPS , Step , _RawStepData
1818from tmt .steps .discover import Discover , TestOrigin
1919from tmt .utils import Common , Environment , FmfContext , NormalizeKeysMixin , Path , ShellScript
2020
@@ -276,17 +276,18 @@ class _RecipeStep(SpecBasedContainer[_RawRecipeStep, _RawRecipeStep], Serializab
276276
277277 @classmethod
278278 def from_step (cls , step : 'Step' ) -> '_RecipeStep' :
279- enabled = bool (step .enabled )
280279 return _RecipeStep (
281- enabled = enabled ,
282- phases = [phase .to_minimal_spec () for phase in step .data ] if enabled else [] ,
280+ enabled = bool ( step . enabled ) ,
281+ phases = [phase .to_minimal_spec () for phase in step .data ],
283282 )
284283
285284 # ignore[override]: does not match the signature on purpose, we need to pass logger
286285 @classmethod
287286 def from_spec (cls , spec : _RawRecipeStep , logger : Logger ) -> '_RecipeStep' : # type: ignore[override]
288- enabled = bool (spec .get ('enabled' , False ))
289- return _RecipeStep (enabled = enabled , phases = spec .get ('phases' , []) if enabled else [])
287+ return _RecipeStep (
288+ enabled = bool (spec .get ('enabled' , False )),
289+ phases = spec .get ('phases' , []),
290+ )
290291
291292 def to_spec (self ) -> _RawRecipeStep :
292293 return _RawRecipeStep (enabled = self .enabled , phases = self .phases )
@@ -316,10 +317,9 @@ def to_spec(self) -> _RawRecipeStep:
316317 # ignore[override]: does not match the signature on purpose, we need to pass logger
317318 @classmethod
318319 def from_spec (cls , spec : _RawRecipeStep , logger : Logger ) -> '_RecipeDiscoverStep' : # type: ignore[override]
319- enabled = bool (spec .get ('enabled' , False ))
320320 return _RecipeDiscoverStep (
321- enabled = enabled ,
322- phases = spec .get ('phases' , []) if enabled else [] ,
321+ enabled = bool ( spec . get ( ' enabled' , False )) ,
322+ phases = spec .get ('phases' , []),
323323 tests = [
324324 _RecipeTest .from_spec (test , logger )
325325 for test in cast (list [_RawRecipeTest ], spec .get ('tests' , []))
@@ -329,10 +329,9 @@ def from_spec(cls, spec: _RawRecipeStep, logger: Logger) -> '_RecipeDiscoverStep
329329 @classmethod
330330 def from_step (cls , step : 'Step' ) -> '_RecipeDiscoverStep' :
331331 assert isinstance (step , Discover )
332- enabled = bool (step .enabled )
333332 return _RecipeDiscoverStep (
334- enabled = enabled ,
335- phases = [phase .to_minimal_spec () for phase in step .data ] if enabled else [] ,
333+ enabled = bool ( step . enabled ) ,
334+ phases = [phase .to_minimal_spec () for phase in step .data ],
336335 tests = [_RecipeTest .from_test_origin (test_origin ) for test_origin in step .tests ()],
337336 )
338337
@@ -354,20 +353,18 @@ def to_spec(self) -> _RawRecipeStep:
354353 # ignore[override]: does not match the signature on purpose, we need to pass logger
355354 @classmethod
356355 def from_spec (cls , spec : _RawRecipeStep , logger : Logger ) -> '_RecipeExecuteStep' : # type: ignore[override]
357- enabled = bool (spec .get ('enabled' , False ))
358356 results_path = cast (Optional [str ], spec .get ('results-path' , None ))
359357 return _RecipeExecuteStep (
360- enabled = enabled ,
361- phases = spec .get ('phases' , []) if enabled else [] ,
358+ enabled = bool ( spec . get ( ' enabled' , False )) ,
359+ phases = spec .get ('phases' , []),
362360 results_path = Path (results_path ) if results_path else None ,
363361 )
364362
365363 @classmethod
366364 def from_step (cls , step : 'Step' ) -> '_RecipeExecuteStep' :
367- enabled = bool (step .enabled )
368365 return _RecipeExecuteStep (
369- enabled = enabled ,
370- phases = [phase .to_minimal_spec () for phase in step .data ] if enabled else [] ,
366+ enabled = bool ( step . enabled ) ,
367+ phases = [phase .to_minimal_spec () for phase in step .data ],
371368 results_path = (step .step_workdir / 'results.yaml' ).relative_to (step .run_workdir ),
372369 )
373370
@@ -549,23 +546,25 @@ def to_spec(self) -> _RawRecipe:
549546 'plans' : [plan .to_minimal_spec () for plan in self .plans ],
550547 }
551548
552- def get_plan_by_name (self , name : str ) -> _RecipePlan :
553- plans = [plan for plan in self .plans if plan .name == name ]
554- if len (plans ) != 1 :
555- raise tmt .utils .GeneralError (
556- f"Unable to find the correct plan in the recipe: '{ name } '"
557- )
558- return plans [0 ]
559-
560549
561550class RecipeManager (Common ):
562551 def __init__ (self , logger : Logger ):
563552 super ().__init__ (logger = logger )
564553
565- def load (self , path : Path ) -> Recipe :
566- return Recipe .from_spec (
567- cast (_RawRecipe , tmt .utils .yaml_to_dict (self .read (path ))), self ._logger
554+ def load (
555+ self , run : 'Run' , recipe_path : Optional [Path ], fmf_tree : Optional [Tree ]
556+ ) -> Optional [Recipe ]:
557+ if recipe_path is None or fmf_tree is None :
558+ return None
559+
560+ recipe = Recipe .from_spec (
561+ cast (_RawRecipe , tmt .utils .yaml_to_dict (self .read (recipe_path ))), self ._logger
568562 )
563+ self ._update_tree (recipe , fmf_tree )
564+ self ._update_cli_context (recipe )
565+ run .remove = run .remove or recipe .run .remove
566+
567+ return recipe
569568
570569 def save (self , run : 'Run' ) -> None :
571570 recipe = Recipe (
@@ -596,9 +595,21 @@ def tests(self, recipe: Recipe, plan_name: str) -> list[TestOrigin]:
596595 raise tmt .utils .GeneralError (f"Plan '{ plan_name } ' not found in the recipe." )
597596
598597 @staticmethod
599- def update_tree (recipe : Recipe , tree : fmf . Tree ) -> None :
598+ def _update_tree (recipe : Recipe , tree : Tree ) -> None :
600599 """
601600 Load the plans from the recipe and update the given fmf tree with their specifications.
602601 """
603602 tree .children .clear ()
604603 tree .update ({plan .name : plan .to_fmf_spec () for plan in recipe .plans })
604+
605+ def _update_cli_context (self , recipe : Recipe ) -> None :
606+ """
607+ Load the names of enabled steps from the recipe and save them to the CLI context.
608+ """
609+ if self ._cli_context_object is None :
610+ return
611+ for plan in recipe .plans :
612+ for step_name in STEPS :
613+ recipe_step = plan .get_step_by_name (step_name )
614+ if recipe_step .enabled :
615+ self ._cli_context_object .steps .add (step_name )
0 commit comments