Source code for validate_actions.globals.problems

"""Handles problem management for validate-actions."""
from dataclasses import dataclass, field
from enum import Enum
from typing import List

from validate_actions.domain_model.primitives import Pos


[docs] class ProblemLevel(Enum): """Enumeration of problem severity levels for workflow validation. This enum defines the different levels of issues that can be found during workflow validation, ordered by severity. Attributes: NON (int): No problem or informational level (severity 0) WAR (int): Warning level - potential issues that don't break functionality (severity 1) ERR (int): Error level - critical issues that need to be fixed (severity 2) """ NON = 0 # No problem/informational WAR = 1 # Warning level ERR = 2 # Error level
[docs] @dataclass class Problem: """Represents a single validation problem found in a workflow file. This class encapsulates all information about a specific issue discovered during workflow validation, including its location, severity, description, and the rule that detected it. Attributes: pos (Pos): Position information (line, column, character index) where the problem occurs level (ProblemLevel): Severity level of the problem (NON, WAR, or ERR) desc (str): Human-readable description of the problem rule (str): Name/identifier of the validation rule that detected this problem """ pos: Pos level: ProblemLevel desc: str rule: str
[docs] @dataclass class Problems: """Collection and management of validation problems. This class manages a collection of Problem instances, maintains counts by severity level, and tracks the highest severity level encountered. It provides methods for adding, removing, sorting, and merging problems. Attributes: problems (List[Problem]): List of all problems found during validation max_level (ProblemLevel): Highest severity level among all problems n_error (int): Count of problems with ERROR level n_warning (int): Count of problems with WARNING level """ problems: List[Problem] = field(default_factory=list) max_level: ProblemLevel = ProblemLevel.NON n_error: int = 0 n_warning: int = 0
[docs] def append(self, problem: Problem) -> None: """Add a new problem to the collection and update counts. Appends the problem to the internal list, increments the appropriate severity counter, and updates the maximum severity level if necessary. Args: problem (Problem): The problem instance to add to the collection """ self.problems.append(problem) match problem.level: case ProblemLevel.WAR: self.n_warning += 1 case ProblemLevel.ERR: self.n_error += 1 case ProblemLevel.NON: # Non-problem, do not count pass self.max_level = ProblemLevel(max(self.max_level.value, problem.level.value))
[docs] def sort(self) -> None: """Sort problems by their position in the file. Sorts the problems list in-place by line number first, then by column number. This ensures problems are presented in the order they appear in the source file. """ self.problems.sort(key=lambda x: (x.pos.line, x.pos.col))
[docs] def extend(self, problems: "Problems") -> None: """Merge another Problems collection into this one. Extends the current problems list with all problems from another collection, updates all counters, and adjusts the maximum severity level. Args: problems (Problems): Another Problems instance to merge into this one """ self.problems.extend(problems.problems) self.n_error += problems.n_error self.n_warning += problems.n_warning self.max_level = ProblemLevel(max(self.max_level.value, problems.max_level.value))
[docs] def remove(self, problem: Problem) -> None: """Remove a specific problem from the collection. Removes the problem from the list, decrements the appropriate severity counter, and resets max_level to NON if no problems remain. Args: problem (Problem): The specific problem instance to remove Raises: ValueError: If the problem is not found in the collection """ self.problems.remove(problem) match problem.level: case ProblemLevel.WAR: self.n_warning -= 1 case ProblemLevel.ERR: self.n_error -= 1 case ProblemLevel.NON: # Non-problem, do not count pass if not self.problems: self.max_level = ProblemLevel.NON