import json import urllib.parse import urllib.request import urllib.error class PeiTariffApiError(Exception): def __init__(self, message, status=None, code="API_ERROR", request_id=None, details=None): super().__init__(message) self.status = status self.code = code self.request_id = request_id self.details = details class PeiTariffApi: def __init__(self, api_key, base_url="https://powerexpertindia.com/v1", timeout=15): if not api_key: raise ValueError("api_key is required") self.api_key = api_key self.base_url = base_url.rstrip("/") self.timeout = timeout def request(self, path, method="GET", query=None, body=None): url = self.base_url + path if query: clean = {k: v for k, v in query.items() if v is not None and v != ""} if clean: url += "?" + urllib.parse.urlencode(clean) headers = { "Accept": "application/json", "X-API-Key": self.api_key, } data = None if body is not None: headers["Content-Type"] = "application/json" data = json.dumps(body).encode("utf-8") req = urllib.request.Request(url, data=data, headers=headers, method=method) try: with urllib.request.urlopen(req, timeout=self.timeout) as response: return json.loads(response.read().decode("utf-8")) except urllib.error.HTTPError as error: raw = error.read().decode("utf-8", errors="replace") try: payload = json.loads(raw) except Exception: payload = {} err = payload.get("error", {}) raise PeiTariffApiError( err.get("message", f"API request failed with HTTP {error.code}"), error.code, err.get("code", "API_ERROR"), payload.get("request_id"), err.get("details"), ) from None def health(self): return self.request("/health") def states(self): return self.request("/states") def categories(self, **params): return self.request("/categories", query=params) def tariffs(self, **params): return self.request("/tariffs", query=params) def sources(self, **params): return self.request("/sources", query=params) def calculate(self, payload): return self.request("/calculate", method="POST", body=payload) def solar_savings(self, payload): return self.request("/solar-savings", method="POST", body=payload)