mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-10-31 10:02:38 +00:00
This brings the weather slices of my long-running refactor branch to dev ahead of converging wx and gwx, so the convergence PRs build on one copy of the code instead of rewriting it twice. - `modules/weather_common.py` (WeatherCommandMixin): code wx and gwx shared by copy (MQTT and WXSIM source lookup, multi-day sending, high/low formatting, the forecast-option parser, the Open-Meteo model loader). - `modules/nws_alerts.py`: one NWS alert entry parser for wx and the weather service, keeping each caller's own Special Weather Statement rules. - `modules/http_retry.py`: one retrying session builder for the weather HTTP clients. - wx: get_noaa_weather, the hourly, tomorrow and multi-day formatters, _add_period_details and the extract_* readers broken up or made table-driven; NOAA fetches go through `_noaa_fetch`. - gwx: one fetch path; `_open_meteo_current` and `_open_meteo_daily_tail` split out of get_open_meteo_weather. - solarforecast: `_format_forecast` built from one timestamp parser and one day builder (418 → 155 lines). - aurora, rain, wx, gwx: companion and bot location lookups through `modules.location` (which gains optional logging arguments). The changes outside these files that the refactor branch made (the base command's enabled_attr hook, the service base's run_periodic and _cancel_tasks) stay out: aurora and rain keep their can_execute overrides and the weather service its own loops, exactly as on dev. Tests: characterization goldens over real captured NOAA, NWS, Open-Meteo and forecast.solar responses (tests/characterization, fixtures in tests/fixtures), 50 tests and several hundred cases, all of which also pass against dev's unmodified weather code. Each refactor step was additionally checked on the branch with an old-vs-new differential run (tens of thousands of generated inputs, including log calls and exceptions) and reviewed by codex.
29 lines
953 B
Python
29 lines
953 B
Python
"""Shared ``requests`` session with retry/backoff for the weather and forecast APIs."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import requests
|
|
from requests.adapters import HTTPAdapter
|
|
from urllib3.util.retry import Retry
|
|
|
|
|
|
def make_retry_session() -> requests.Session:
|
|
"""A session that retries GETs on connection errors and 5xx responses.
|
|
|
|
Two retries (three attempts) with 0.3 s / 0.6 s backoff. Status codes are
|
|
not raised; callers inspect the response. Connections are pooled
|
|
(10 pools, up to 20 connections each).
|
|
"""
|
|
session = requests.Session()
|
|
retry_strategy = Retry(
|
|
total=2,
|
|
backoff_factor=0.3,
|
|
status_forcelist=[500, 502, 503, 504],
|
|
allowed_methods=["GET"],
|
|
raise_on_status=False,
|
|
)
|
|
adapter = HTTPAdapter(max_retries=retry_strategy, pool_connections=10, pool_maxsize=20)
|
|
session.mount("https://", adapter)
|
|
session.mount("http://", adapter)
|
|
return session
|