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