Download backend/backend_app/api/risk_analysis.py from RishiXD/Datathon: direct link, hf CLI and curl.
- Browser
- Download file 4.11 kB
-
https://huggingface.co/spaces/RishiXD/Datathon/resolve/main/backend/backend_app/api/risk_analysis.py
- Command line
-
hf download hf://spaces/RishiXD/Datathon/backend/backend_app/api/risk_analysis.py
-
curl -L -o risk_analysis.py https://huggingface.co/spaces/RishiXD/Datathon/resolve/main/backend/backend_app/api/risk_analysis.py
4.11 kB
| from fastapi import APIRouter, HTTPException | |
| from typing import Dict, Any | |
| from pydantic import BaseModel | |
| from backend_app.state.store import store | |
| router = APIRouter() | |
| class RiskAnalysisRequest(BaseModel): | |
| org: str | |
| repo: str | |
| def analyze_risk(req: RiskAnalysisRequest): | |
| """ | |
| One-shot API to: | |
| 1. Load Live Data | |
| 2. Compute Metrics | |
| 3. Return 'Bus Factor' Risk Analysis (Feature #1) | |
| PLUS Detailed raw stats: commits, PRs, merges per user. | |
| """ | |
| try: | |
| # 1. Load Data | |
| print(f"Loading data for {req.org}/{req.repo}...") | |
| store.load_live_data(req.org, req.repo) | |
| # 2. Compute | |
| print("Computing metrics...") | |
| store.compute() | |
| # 3. Collect Detailed Stats | |
| # We want: commits, comments (reviews), PRs, Merge counts per user. | |
| stats = {} | |
| # Structure: { "user": { "commits": 0, "prs_opened": 0, "prs_merged": 0, "reviews": 0 } } | |
| def get_stat(u): | |
| if u not in stats: stats[u] = {"commits": 0, "prs_opened": 0, "prs_merged": 0, "reviews": 0} | |
| return stats[u] | |
| # Commits | |
| for c in store.commits: | |
| u = c.author or "unknown" | |
| get_stat(u)["commits"] += 1 | |
| # PRs | |
| for p in store.prs: | |
| u = p.author or "unknown" | |
| get_stat(u)["prs_opened"] += 1 | |
| if p.merged_at: | |
| get_stat(u)["prs_merged"] += 1 | |
| # Reviews | |
| for r in store.reviews: | |
| u = r.reviewer or "unknown" | |
| get_stat(u)["reviews"] += 1 | |
| # Format for response | |
| detailed_stats = [] | |
| for user, data in stats.items(): | |
| detailed_stats.append({ | |
| "user": user, | |
| **data | |
| }) | |
| # Sort by commits desc | |
| detailed_stats.sort(key=lambda x: x["commits"], reverse=True) | |
| modules = store.get_modules() | |
| if not modules: | |
| return { | |
| "headline": "No activity found.", | |
| "overall_repo_risk": 0, | |
| "user_stats": detailed_stats, | |
| "modules_analysis": [] | |
| } | |
| top_risk_module = modules[0] | |
| results = [] | |
| for mod in modules: | |
| if not mod.people: continue | |
| top_person = mod.people[0] | |
| share = top_person.share_pct * 100 | |
| # Bus Factor Check | |
| bus_factor = mod.bus_factor | |
| insight = f"Healthy distribution." | |
| if bus_factor == 1: | |
| insight = f"CRITICAL: {top_person.person_id} is a single point of failure (Bus Factor 1). If they leave, {share:.1f}% of module logic is orphaned." | |
| elif share > 50: | |
| insight = f"HIGH RISK: {top_person.person_id} dominates ({share:.1f}%)." | |
| results.append({ | |
| "module": mod.module_id, | |
| "risk_score": mod.risk_index, | |
| "severity": mod.severity, | |
| "bus_factor": bus_factor, | |
| "key_person": top_person.person_id, | |
| "knowledge_share_pct": round(share, 1), | |
| "insight": insight, | |
| "evidence": mod.evidence | |
| }) | |
| headline = f"Repo Analysis: {top_risk_module.module_id} is at {top_risk_module.severity} risk." | |
| if top_risk_module.bus_factor == 1: | |
| headline += f" {top_risk_module.people[0].person_id} is a Single Point of Failure." | |
| return { | |
| "headline": headline, | |
| "overall_repo_risk": top_risk_module.risk_index, | |
| "user_stats": detailed_stats, | |
| "modules_analysis": results | |
| } | |
| except Exception as e: | |
| import traceback | |
| traceback.print_exc() | |
| raise HTTPException(status_code=500, detail=str(e)) | |