# Copyright 2024-2026 Universidad de Sevilla
# SPDX-License-Identifier: Apache-2.0
"""This module defines the steps class, which is used to manage the steps
and post_steps of the verification process."""
[docs]
class Steps:
"""This class defines a data structure in which to store the steps and
provides functions to manage it (such as adding steps and post_steps)"""
[docs]
def __init__(self):
"""Class constructor"""
# Dictionaries are ordered since python 3.7, so we can just insert the
# steps in the order in which we want it them run. For earlier python
# versions we could use OrderedDict, but FVM doesn't work with python <
# 3.8, so there's no need to support that
self.steps = {}
self.post_steps = {}
[docs]
def add_step(self, framework, step, setup, run):
"""Adds a step to the steps dictionary. Fails if the step already exists"""
if step in self.steps:
framework.logger.error(f'{step=} already exists in {self.steps=}')
self.steps[step] = {}
self.steps[step]["setup"] = setup
self.steps[step]["run"] = run
# Cannot reuse add_step for post_steps because post_steps are never run if
# the relevant step fails, whereas steps may be run even if the previous
# step fails (when using the --continue flag)
[docs]
def add_post_step(self, framework, step, post_step, setup, run):
"""Adds a post_step to the post_steps dictionary. Fails if the step does not exist"""
if step not in self.steps:
framework.logger.error(f'{step=} does not exist in {self.steps=}')
if post_step in self.post_steps:
framework.logger.error(f'{post_step=} already exists in {self.steps[step]=}')
# Initialize the post_steps struct if it doesn't exist
if step not in self.post_steps:
self.post_steps[step] = {}
# Add the specific post_step
self.post_steps[step][post_step] = {}
self.post_steps[step][post_step]["setup"] = setup
self.post_steps[step][post_step]["run"] = run
[docs]
def append_step(self, framework, target, step, setup, run):
"""Appends a step after the target step."""
# Fail if target not in dict
if target not in self.steps:
framework.logger.error(f'{target=} not in {self.steps=}, cannot insert step after it')
# Get position of target in the dict
pos = list(self.steps).index(target)
# Convert dict to list
l = list(self.steps.items())
# Add step after target
l.insert(pos+1, (step, {"setup": setup, "run": run}))
# Convert list to dict
self.steps = dict(l)
[docs]
def prepend_step(self, framework, target, step, setup, run):
"""Prepends a step before the target step."""
# Fail if target not in dict
if target not in self.steps:
framework.logger.error(f'{target=} not in {self.steps=}, cannot insert step before it')
# Get position of target in the dict
pos = list(self.steps).index(target)
# Convert dict to list
l = list(self.steps.items())
# Add step before target
l.insert(pos, (step, {"setup": setup, "run": run}))
# Convert list to dict
self.steps = dict(l)