SPB Git

spb/qwhpi Public

QHPI — Quebec Housing Price Index: quality-adjusted, hierarchically pooled housing price indexes.

Python 63.9% TypeScript 25.4% CSS 5.5% TeX 3.5% SQL 0.8% Makefile 0.5% Dockerfile 0.5%
1.6 KB · 45 lines python
Raw Blame History
1# =============================================================================2# QWHPI — Quebec Weekly Housing Price Index3# Author  : Simon-Pierre Boucher4# Contact : contact@spboucher.ai5# File    : api/app/deps.py6# Purpose : Shared dependencies — series validation, ETag and CSV helpers.7# =============================================================================8"""Shared FastAPI dependencies and response helpers."""910from __future__ import annotations1112import hashlib1314import polars as pl15from fastapi import HTTPException, Request, Response1617from app.services import data1819VALID_TYPES = {"all", "unifamilial", "condo", "plex"}202122def validate_series(geography: str, property_type: str) -> None:23    if property_type not in VALID_TYPES:24        raise HTTPException(422, f"property_type must be one of {sorted(VALID_TYPES)}")25    if geography not in data.geography_ids():26        raise HTTPException(404, f"unknown geography '{geography}' — see /v1/geographies")272829def etag_for(request: Request, response: Response, *parts: str) -> bool:30    """Set the ETag; return True when the client's copy is fresh (304)."""31    raw = "|".join([data.data_vintage(), data.model_version(),32                    str(request.url), *parts])33    tag = '"' + hashlib.sha256(raw.encode()).hexdigest()[:32] + '"'34    response.headers["ETag"] = tag35    response.headers["Cache-Control"] = "public, max-age=300"36    return request.headers.get("if-none-match") == tag373839def csv_response(df: pl.DataFrame) -> Response:40    return Response(41        content=df.write_csv(),42        media_type="text/csv",43        headers={"X-Author": "Simon-Pierre Boucher <contact@spboucher.ai>"},44    )45