fix: add models and utils modules
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled

This commit is contained in:
2026-02-01 08:21:31 +00:00
parent 1c7a26b93e
commit dd8a7e46ca

View File

@@ -1,6 +1,6 @@
from dataclasses import dataclass, field
from datetime import datetime
from typing import Any, Dict, List, Optional
from typing import List, Optional
from dataclasses_json import dataclass_json
@@ -8,7 +8,7 @@ from dataclasses_json import dataclass_json
@dataclass_json
@dataclass
class Author:
"""Author information."""
"""Represents a git author."""
name: str
email: str
commit_count: int = 0
@@ -19,134 +19,84 @@ class Author:
@dataclass_json
@dataclass
class Commit:
"""Git commit information."""
"""Represents a git commit."""
sha: str
message: str
author_name: str
author_email: str
committed_datetime: datetime
author_datetime: datetime
parents: List[str] = field(default_factory=list)
additions: int = 0
deletions: int = 0
files_changed: List[str] = field(default_factory=list)
parents: List[str] = field(default_factory=list)
file_changes: List["FileChange"] = field(default_factory=list)
is_merge: bool = False
is_revert: bool = False
@property
def lines_changed_count(self) -> int:
"""Get total lines changed."""
return self.additions + self.deletions
def timestamp(self) -> datetime:
return self.committed_datetime
@dataclass_json
@dataclass
class FileChange:
"""File change information."""
"""Represents changes to a file in a commit."""
filepath: str
lines_added: int = 0
lines_deleted: int = 0
change_type: str = "M"
additions: int
deletions: int
changes: int = 0
@dataclass_json
@dataclass
class CommitAnalysis:
"""Commit pattern analysis results."""
total_commits: int = 0
unique_authors: int = 0
commits_by_hour: Dict[str, int] = field(default_factory=dict)
commits_by_day: Dict[str, int] = field(default_factory=dict)
commits_by_week: Dict[str, int] = field(default_factory=dict)
commits_by_month: Dict[str, int] = field(default_factory=dict)
top_authors: List[Author] = field(default_factory=list)
average_commits_per_day: float = 0.0
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary."""
return {
"total_commits": self.total_commits,
"unique_authors": self.unique_authors,
"commits_by_hour": self.commits_by_hour,
"commits_by_day": self.commits_by_day,
"commits_by_week": self.commits_by_week,
"commits_by_month": self.commits_by_month,
"top_authors": [a.to_dict() for a in self.top_authors],
"average_commits_per_day": self.average_commits_per_day,
}
"""Analysis of commit patterns."""
total_commits: int
unique_authors: int
commits_by_hour: dict
commits_by_day: dict
commits_by_week: dict
top_authors: List[Author]
average_commits_per_day: float
@dataclass_json
@dataclass
class CodeChurnAnalysis:
"""Code churn analysis results."""
total_lines_added: int = 0
total_lines_deleted: int = 0
net_change: int = 0
churn_by_file: Dict[str, int] = field(default_factory=dict)
churn_by_author: Dict[str, int] = field(default_factory=dict)
high_churn_files: List[FileChange] = field(default_factory=list)
high_churn_commits: List[Commit] = field(default_factory=list)
average_churn_per_commit: float = 0.0
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary."""
return {
"total_lines_added": self.total_lines_added,
"total_lines_deleted": self.total_lines_deleted,
"net_change": self.net_change,
"churn_by_file": self.churn_by_file,
"churn_by_author": self.churn_by_author,
"high_churn_files": [f.to_dict() for f in self.high_churn_files],
"high_churn_commits": [c.to_dict() for c in self.high_churn_commits],
"average_churn_per_commit": self.average_churn_per_commit,
}
"""Analysis of code churn."""
total_lines_added: int
total_lines_deleted: int
net_change: int
churn_by_file: dict
churn_by_author: dict
high_churn_commits: List[Commit]
average_churn_per_commit: float
@dataclass_json
@dataclass
class RiskyCommitAnalysis:
"""Risky commit detection results."""
large_commits: List[Commit] = field(default_factory=list)
merge_commits: List[Commit] = field(default_factory=list)
revert_commits: List[Commit] = field(default_factory=list)
total_risky: int = 0
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary."""
return {
"large_commits": [c.to_dict() for c in self.large_commits],
"merge_commits": [c.to_dict() for c in self.merge_commits],
"revert_commits": [c.to_dict() for c in self.revert_commits],
"total_risky": self.total_risky,
}
"""Analysis of risky commits."""
total_risky_commits: int
large_change_commits: List[Commit]
merge_commits: List[Commit]
revert_commits: List[Commit]
risk_score: float
@dataclass_json
@dataclass
class VelocityAnalysis:
"""Velocity analysis results."""
total_commits: int = 0
commits_per_day: float = 0.0
commits_per_week: float = 0.0
velocity_trend: str = "stable"
most_active_day: str = ""
most_active_hour: str = ""
weekly_totals: Dict[str, int] = field(default_factory=dict)
daily_totals: Dict[str, int] = field(default_factory=dict)
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary."""
return {
"total_commits": self.total_commits,
"commits_per_day": self.commits_per_day,
"commits_per_week": self.commits_per_week,
"velocity_trend": self.velocity_trend,
"most_active_day": self.most_active_day,
"most_active_hour": self.most_active_hour,
"weekly_totals": self.weekly_totals,
"daily_totals": self.daily_totals,
}
"""Analysis of team velocity."""
commits_per_day: float
commits_per_week: float
commits_per_month: float
velocity_trend: str
top_contributors: List[Author]
most_active_day: str
most_active_hour: str
@dataclass_json
@@ -155,8 +105,7 @@ class ProductivityReport:
"""Comprehensive productivity report."""
repository_path: str
analysis_days: int
commit_analysis: Optional[CommitAnalysis] = None
code_churn_analysis: Optional[CodeChurnAnalysis] = None
risky_commit_analysis: Optional[RiskyCommitAnalysis] = None
velocity_analysis: Optional[VelocityAnalysis] = None
generated_at: datetime = field(default_factory=datetime.now)
commit_analysis: Optional[CommitAnalysis]
code_churn_analysis: Optional[CodeChurnAnalysis]
risky_commit_analysis: Optional[RiskyCommitAnalysis]
velocity_analysis: Optional[VelocityAnalysis]