From b57403a047f7a0fe4516b35df7f0072bf2e7239b Mon Sep 17 00:00:00 2001 From: agessaman Date: Thu, 1 Oct 2026 20:43:09 -0700 Subject: [PATCH] refactor(wx): fetch NOAA points, forecast and hourly data through _noaa_fetch get_noaa_weather and get_noaa_hourly_weather repeated the same GET / status check / timeout-or-connection-error block four times, each logging the same two warnings with a different noun. `_noaa_fetch(url, what)` returns the response or None after the warning, and the callers keep their own (ERROR_FETCHING_DATA, None) returns. The alerts fetch stays as it is: its error handling differs. Old and new agree, replies and every logger call, on all 25 combinations of success, HTTP error, timeout, connection error and other exceptions for the first two requests of each function; a mutation of the warning text was caught. --- modules/commands/wx_command.py | 50 +++++++++++++++------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/modules/commands/wx_command.py b/modules/commands/wx_command.py index 0915bea..9628802 100644 --- a/modules/commands/wx_command.py +++ b/modules/commands/wx_command.py @@ -1044,6 +1044,20 @@ class WxCommand(WeatherCommandMixin, BaseCommand): async def _city_to_lat_lon_async(self, city: str) -> tuple: return await self._run_sync_provider_async(self.city_to_lat_lon, city) + def _noaa_fetch(self, url: str, what: str): + """GET *url* through the NOAA session; None, after a warning naming *what*, + on an HTTP error status, a timeout or a connection error. + """ + try: + response = self.noaa_session.get(url, timeout=self.url_timeout) + if not response.ok: + self.logger.warning(f"Error fetching {what} from NOAA: HTTP {response.status_code}") + return None + except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: + self.logger.warning(f"Timeout/connection error fetching {what} from NOAA: {e}") + return None + return response + def get_noaa_weather(self, lat: float, lon: float, return_periods: bool = False, max_length: int = 130) -> tuple: """Get weather forecast from NOAA and return both weather string and points data @@ -1065,26 +1079,16 @@ class WxCommand(WeatherCommandMixin, BaseCommand): weather_api = f"https://api.weather.gov/points/{lat_rounded},{lon_rounded}" # Get the forecast URL (with retry logic) - try: - weather_data = self.noaa_session.get(weather_api, timeout=self.url_timeout) - if not weather_data.ok: - self.logger.warning(f"Error fetching weather data from NOAA: HTTP {weather_data.status_code}") - return self.ERROR_FETCHING_DATA, None - except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: - self.logger.warning(f"Timeout/connection error fetching weather data from NOAA: {e}") + weather_data = self._noaa_fetch(weather_api, "weather data") + if weather_data is None: return self.ERROR_FETCHING_DATA, None weather_json = weather_data.json() forecast_url = weather_json['properties']['forecast'] # Get the forecast (with retry logic) - try: - forecast_data = self.noaa_session.get(forecast_url, timeout=self.url_timeout) - if not forecast_data.ok: - self.logger.warning(f"Error fetching weather forecast from NOAA: HTTP {forecast_data.status_code}") - return self.ERROR_FETCHING_DATA, None - except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: - self.logger.warning(f"Timeout/connection error fetching weather forecast from NOAA: {e}") + forecast_data = self._noaa_fetch(forecast_url, "weather forecast") + if forecast_data is None: return self.ERROR_FETCHING_DATA, None forecast_json = forecast_data.json() @@ -1426,13 +1430,8 @@ class WxCommand(WeatherCommandMixin, BaseCommand): weather_api = f"https://api.weather.gov/points/{lat_rounded},{lon_rounded}" # Get the forecast URL (with retry logic) - try: - weather_data = self.noaa_session.get(weather_api, timeout=self.url_timeout) - if not weather_data.ok: - self.logger.warning(f"Error fetching weather data from NOAA: HTTP {weather_data.status_code}") - return self.ERROR_FETCHING_DATA, None - except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: - self.logger.warning(f"Timeout/connection error fetching weather data from NOAA: {e}") + weather_data = self._noaa_fetch(weather_api, "weather data") + if weather_data is None: return self.ERROR_FETCHING_DATA, None weather_json = weather_data.json() @@ -1443,13 +1442,8 @@ class WxCommand(WeatherCommandMixin, BaseCommand): return self.ERROR_FETCHING_DATA, None # Get the hourly forecast (with retry logic) - try: - hourly_data = self.noaa_session.get(hourly_forecast_url, timeout=self.url_timeout) - if not hourly_data.ok: - self.logger.warning(f"Error fetching hourly forecast from NOAA: HTTP {hourly_data.status_code}") - return self.ERROR_FETCHING_DATA, None - except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: - self.logger.warning(f"Timeout/connection error fetching hourly forecast from NOAA: {e}") + hourly_data = self._noaa_fetch(hourly_forecast_url, "hourly forecast") + if hourly_data is None: return self.ERROR_FETCHING_DATA, None hourly_json = hourly_data.json()