Models API Reference
Data models for reqtrace requirements and traces.
FileStats
dataclass
Statistics for a single source file.
Source code in reqtrace/models.py
@dataclass
class FileStats:
"""Statistics for a single source file."""
file_path: str
total_lines: int
mapped_lines: int
unmapped_ranges: List[Tuple[int, int]]
is_disabled: bool = False
Requirement
dataclass
A defined project requirement.
Source code in reqtrace/models.py
@dataclass
# pylint: disable=too-many-instance-attributes
class Requirement:
"""A defined project requirement."""
id: str
title: str
description: str = ""
derived_from: List[str] = field(default_factory=list)
# Source location
file_path: Optional[str] = None
line_number: Optional[int] = None
# Git Metadata (optional, filled during analysis)
created: Optional[GitMetadata] = None
last_changed: Optional[GitMetadata] = None
RequirementIndex
An index of all loaded requirements.
Source code in reqtrace/models.py
class RequirementIndex:
"""An index of all loaded requirements."""
def __init__(self):
self.requirements: Dict[str, Requirement] = {}
def add(self, req: Requirement):
"""Adds a requirement to the index."""
if req.id in self.requirements:
raise ValueError(f"Requirement with id '{req.id}' already exists.")
self.requirements[req.id] = req
def get(self, req_id: str) -> Optional[Requirement]:
"""Gets a requirement by its ID."""
return self.requirements.get(req_id)
def validate_graph(self):
"""Validates that all parent IDs exist and there are no cyclic dependencies."""
# 1. Check for missing parents
for req in self.requirements.values():
for parent_id in req.derived_from:
if parent_id not in self.requirements:
raise ValueError(f"Requirement '{req.id}' derives from unknown requirement '{parent_id}'")
# 2. Check for cycles using DFS
visited = set()
recursion_stack = set()
def dfs(req_id: str):
visited.add(req_id)
recursion_stack.add(req_id)
req = self.requirements[req_id]
for parent_id in req.derived_from:
if parent_id not in visited:
dfs(parent_id)
elif parent_id in recursion_stack:
raise ValueError(f"Cyclic dependency detected involving requirement '{parent_id}'")
recursion_stack.remove(req_id)
for req_id in self.requirements:
if req_id not in visited:
dfs(req_id)
add(req)
Adds a requirement to the index.
Source code in reqtrace/models.py
def add(self, req: Requirement):
"""Adds a requirement to the index."""
if req.id in self.requirements:
raise ValueError(f"Requirement with id '{req.id}' already exists.")
self.requirements[req.id] = req
get(req_id)
Gets a requirement by its ID.
Source code in reqtrace/models.py
def get(self, req_id: str) -> Optional[Requirement]:
"""Gets a requirement by its ID."""
return self.requirements.get(req_id)
validate_graph()
Validates that all parent IDs exist and there are no cyclic dependencies.
Source code in reqtrace/models.py
def validate_graph(self):
"""Validates that all parent IDs exist and there are no cyclic dependencies."""
# 1. Check for missing parents
for req in self.requirements.values():
for parent_id in req.derived_from:
if parent_id not in self.requirements:
raise ValueError(f"Requirement '{req.id}' derives from unknown requirement '{parent_id}'")
# 2. Check for cycles using DFS
visited = set()
recursion_stack = set()
def dfs(req_id: str):
visited.add(req_id)
recursion_stack.add(req_id)
req = self.requirements[req_id]
for parent_id in req.derived_from:
if parent_id not in visited:
dfs(parent_id)
elif parent_id in recursion_stack:
raise ValueError(f"Cyclic dependency detected involving requirement '{parent_id}'")
recursion_stack.remove(req_id)
for req_id in self.requirements:
if req_id not in visited:
dfs(req_id)
SourceStats
dataclass
Statistics about the scanned source code.
Source code in reqtrace/models.py
@dataclass
class SourceStats:
"""Statistics about the scanned source code."""
total_files: int
total_lines: int
mapped_lines: int
unmapped_lines: int
disabled_files: int = 0
file_stats: List[FileStats] = field(default_factory=list)
TraceMatch
dataclass
A trace tag block found within the source code.
Source code in reqtrace/models.py
@dataclass
class TraceMatch:
"""A trace tag block found within the source code."""
file_path: str
line_start: int
line_end: int
req_id: str
percentage: Optional[int] = None
hash: Optional[str] = None
# Git Metadata (optional, filled during analysis)
history: List[GitMetadata] = field(default_factory=list)
first_implemented: Optional[GitMetadata] = None
last_changed: Optional[GitMetadata] = None
def __hash__(self):
return hash((self.file_path, self.line_start, self.line_end, self.req_id, self.percentage, self.hash))
def __eq__(self, other):
if not isinstance(other, TraceMatch):
return False
return (
self.file_path == other.file_path
and self.line_start == other.line_start
and self.line_end == other.line_end
and self.req_id == other.req_id
and self.percentage == other.percentage
and self.hash == other.hash
)