1
donnees_meteo/meteo/config.py
2025-11-18 09:01:34 +01:00

118 lines
3.3 KiB
Python

# meteo/config.py
from __future__ import annotations
from dataclasses import dataclass
from typing import Self
import os
from dotenv import load_dotenv
@dataclass(frozen=True)
class InfluxSettings:
"""
Configuration nécessaire pour communiquer avec un serveur InfluxDB 2.x.
Les valeurs sont généralement chargées depuis des variables d'environnement,
éventuellement via un fichier `.env` à la racine du projet.
"""
url: str
token: str
org: str
bucket: str
@classmethod
def from_env(cls) -> Self:
"""
Construit un objet `InfluxSettings` à partir des variables d'environnement.
Variables attendues :
- INFLUXDB_URL
- INFLUXDB_TOKEN
- INFLUXDB_ORG
- INFLUXDB_BUCKET
Lève une RuntimeError si une variable obligatoire est manquante.
"""
# Charge un éventuel fichier .env (idempotent)
load_dotenv()
url = os.getenv("INFLUXDB_URL")
token = os.getenv("INFLUXDB_TOKEN")
org = os.getenv("INFLUXDB_ORG")
bucket = os.getenv("INFLUXDB_BUCKET")
values = {
"INFLUXDB_URL": url,
"INFLUXDB_TOKEN": token,
"INFLUXDB_ORG": org,
"INFLUXDB_BUCKET": bucket,
}
missing = [name for name, value in values.items() if not value]
if missing:
missing_str = ", ".join(missing)
raise RuntimeError(
f"Les variables d'environnement suivantes sont manquantes : {missing_str}. "
"Définissez-les dans votre environnement ou dans un fichier .env."
)
return cls(
url=url, # type: ignore[arg-type]
token=token, # type: ignore[arg-type]
org=org, # type: ignore[arg-type]
bucket=bucket, # type: ignore[arg-type]
)
@dataclass(frozen=True)
class StationLocation:
"""
Décrit la position géographique de la station météo.
Utilisée pour les calculs astronomiques (ex: élévation du soleil).
"""
latitude: float
longitude: float
elevation_m: float = 0.0
@classmethod
def from_env(cls, *, optional: bool = False) -> Self | None:
"""
Charge les coordonnées GPS depuis les variables d'environnement :
- STATION_LATITUDE (obligatoire)
- STATION_LONGITUDE (obligatoire)
- STATION_ELEVATION (optionnelle, en mètres)
"""
load_dotenv()
lat = os.getenv("STATION_LATITUDE")
lon = os.getenv("STATION_LONGITUDE")
elev = os.getenv("STATION_ELEVATION")
if not lat or not lon:
if optional:
return None
raise RuntimeError(
"Les variables STATION_LATITUDE et STATION_LONGITUDE doivent être définies "
"pour calculer l'élévation solaire."
)
latitude = float(lat)
longitude = float(lon)
elevation = float(elev) if elev else 0.0
return cls(latitude=latitude, longitude=longitude, elevation_m=elevation)
def to_astral_observer_kwargs(self) -> dict[str, float]:
"""
Prépare les arguments attendus par astral.Observer.
"""
return {
"latitude": self.latitude,
"longitude": self.longitude,
"elevation": self.elevation_m,
}