Ekaropolus 0eb2b393f2
All checks were successful
continuous-integration/drone/push Build is passing
SAMI Functionality add
2025-09-16 16:18:45 -06:00

107 lines
3.3 KiB
Python

# pxy_de/api.py
from __future__ import annotations
from pathlib import Path
from typing import List, Dict, Any
import pandas as pd
from django.conf import settings
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .providers.base import get_provider
def _rel(path: Path, base_dir: Path) -> str:
"""
Return a clean relative path like 'data/...'
"""
try:
return str(path.relative_to(settings.BASE_DIR))
except Exception:
# Fallback: show relative to provider base_dir
try:
return str(Path("data") / path.relative_to(base_dir))
except Exception:
return str(path)
def _probe_csv(path: Path) -> Dict[str, Any]:
"""
Lightweight readability probe: existence + sample columns (no full read).
"""
info: Dict[str, Any] = {"exists": path.exists()}
if not info["exists"]:
return info
try:
sample = pd.read_csv(path, nrows=5)
info["columns"] = list(sample.columns)
info["sample_rows"] = int(sample.shape[0]) # up to 5
except Exception as e:
info["error"] = f"{type(e).__name__}: {e}"
return info
@api_view(["GET"])
def de_health(request):
"""
GET /api/de/health?city=CDMX&business=cafe&indicator=imss_wages_2023
Reports:
- provider in use
- base_dir used by the provider
- required/missing files (population.csv always; others if params passed)
- lightweight probes for each checked file (exists, columns, sample_rows)
"""
provider = get_provider()
base_dir: Path = getattr(provider, "base_dir", Path(settings.BASE_DIR) / "data")
checks: List[Dict[str, Any]] = []
missing: List[str] = []
city = (request.query_params.get("city") or "").strip()
business = (request.query_params.get("business") or "").strip()
indicator = (request.query_params.get("indicator") or "").strip()
# Always check SAMI population
pop_path = base_dir / "sami" / "population.csv"
pop_probe = _probe_csv(pop_path)
pop_probe["path"] = _rel(pop_path, base_dir)
checks.append(pop_probe)
if not pop_probe["exists"]:
missing.append(pop_probe["path"])
# Optional: indicator for SAMI
if indicator:
ind_path = base_dir / "sami" / f"{indicator}.csv"
ind_probe = _probe_csv(ind_path)
ind_probe["path"] = _rel(ind_path, base_dir)
checks.append(ind_probe)
if not ind_probe["exists"]:
missing.append(ind_probe["path"])
# Optional: Sites (competition / DENUE)
if city and business:
denue_path = base_dir / "denue" / f"{city}_{business}.csv"
denue_probe = _probe_csv(denue_path)
denue_probe["path"] = _rel(denue_path, base_dir)
checks.append(denue_probe)
if not denue_probe["exists"]:
missing.append(denue_probe["path"])
# Optional: Sites (demand / population grid)
if city:
grid_path = base_dir / "popgrid" / f"{city}_grid.csv"
grid_probe = _probe_csv(grid_path)
grid_probe["path"] = _rel(grid_path, base_dir)
checks.append(grid_probe)
if not grid_probe["exists"]:
missing.append(grid_probe["path"])
ok = len(missing) == 0
return Response({
"provider": "csv-data",
"base_dir": str(base_dir),
"ok": ok,
"missing": missing,
"files": checks,
})