summaryrefslogtreecommitdiff
path: root/cached
diff options
context:
space:
mode:
Diffstat (limited to 'cached')
-rw-r--r--cached/weather_data.py78
-rw-r--r--cached/weather_forecast.py48
2 files changed, 62 insertions, 64 deletions
diff --git a/cached/weather_data.py b/cached/weather_data.py
index 45b6e6e..7b86d02 100644
--- a/cached/weather_data.py
+++ b/cached/weather_data.py
@@ -1,12 +1,12 @@
#!/usr/bin/env python3
-from dataclasses import dataclass
import datetime
import json
import logging
import os
-from typing import Any, List
import urllib.request
+from dataclasses import dataclass
+from typing import Any, List
from overrides import overrides
@@ -27,32 +27,31 @@ cfg.add_argument(
type=str,
default=f'{os.environ["HOME"]}/cache/.weather_summary_cache',
metavar='FILENAME',
- help='File in which to cache weather data'
+ help='File in which to cache weather data',
)
cfg.add_argument(
'--weather_data_stalest_acceptable',
type=argparse_utils.valid_duration,
- default=datetime.timedelta(seconds=7200), # 2 hours
+ default=datetime.timedelta(seconds=7200), # 2 hours
metavar='DURATION',
- help='Maximum acceptable age of cached data. If zero, forces a refetch'
+ help='Maximum acceptable age of cached data. If zero, forces a refetch',
)
@dataclass
class WeatherData:
- date: datetime.date # The date
- high: float # The predicted high in F
- low: float # The predicted low in F
- precipitation_inches: float # Number of inches of precipitation / day
- conditions: List[str] # Conditions per ~3h window
- most_common_condition: str # The most common condition
- icon: str # An icon to represent it
+ date: datetime.date # The date
+ high: float # The predicted high in F
+ low: float # The predicted low in F
+ precipitation_inches: float # Number of inches of precipitation / day
+ conditions: List[str] # Conditions per ~3h window
+ most_common_condition: str # The most common condition
+ icon: str # An icon to represent it
[email protected]_autoloaded_singleton()
[email protected]_autoloaded_singleton() # type: ignore
class CachedWeatherData(persistent.Persistent):
- def __init__(self,
- weather_data = None):
+ def __init__(self, weather_data=None):
if weather_data is not None:
self.weather_data = weather_data
return
@@ -72,7 +71,7 @@ class CachedWeatherData(persistent.Persistent):
"Sand": "🏜️",
"Ash": "🌋",
"Squall": "🌬",
- "Tornado": "🌪️"
+ "Tornado": "🌪️",
}
now = datetime.datetime.now()
dates = set()
@@ -80,7 +79,7 @@ class CachedWeatherData(persistent.Persistent):
lows = {}
conditions = {}
precip = {}
- param = "id=5786882" # Bellevue, WA
+ param = "id=5786882" # Bellevue, WA
key = "c0b160c49743622f62a9cd3cda0270b3"
www = urllib.request.urlopen(
f'http://api.openweathermap.org/data/2.5/weather?zip=98005,us&APPID={key}&units=imperial'
@@ -107,13 +106,13 @@ class CachedWeatherData(persistent.Persistent):
if dt == now.date() and now.hour > 18 and condition == 'Clear':
icon = '🌙'
self.weather_data[dt] = WeatherData(
- date = dt,
- high = float(parsed_json["main"]["temp_max"]),
- low = float(parsed_json["main"]["temp_min"]),
- precipitation_inches = p / 25.4,
- conditions = [condition],
- most_common_condition = condition,
- icon = icon,
+ date=dt,
+ high=float(parsed_json["main"]["temp_max"]),
+ low=float(parsed_json["main"]["temp_min"]),
+ precipitation_inches=p / 25.4,
+ conditions=[condition],
+ most_common_condition=condition,
+ icon=icon,
)
www = urllib.request.urlopen(
@@ -134,9 +133,9 @@ class CachedWeatherData(persistent.Persistent):
lows[dt] = None
conditions[dt] = []
for temp in (
- data["main"]["temp"],
- data['main']['temp_min'],
- data['main']['temp_max'],
+ data["main"]["temp"],
+ data['main']['temp_min'],
+ data['main']['temp_max'],
):
if highs[dt] is None or temp > highs[dt]:
highs[dt] = temp
@@ -160,10 +159,7 @@ class CachedWeatherData(persistent.Persistent):
for dt in sorted(dates):
if dt == today:
high = highs.get(dt, None)
- if (
- high is not None and
- self.weather_data[today].high < high
- ):
+ if high is not None and self.weather_data[today].high < high:
self.weather_data[today].high = high
continue
most_common_condition = list_utils.most_common(conditions[dt])
@@ -171,23 +167,24 @@ class CachedWeatherData(persistent.Persistent):
if dt == now.date() and now.hour > 18 and condition == 'Clear':
icon = '🌙'
self.weather_data[dt] = WeatherData(
- date = dt,
- high = highs[dt],
- low = lows[dt],
- precipitation_inches = precip[dt] / 25.4,
- conditions = conditions[dt],
- most_common_condition = most_common_condition,
- icon = icon
+ date=dt,
+ high=highs[dt],
+ low=lows[dt],
+ precipitation_inches=precip[dt] / 25.4,
+ conditions=conditions[dt],
+ most_common_condition=most_common_condition,
+ icon=icon,
)
@classmethod
@overrides
def load(cls) -> Any:
if persistent.was_file_written_within_n_seconds(
- config.config['weather_data_cachefile'],
- config.config['weather_data_stalest_acceptable'].total_seconds(),
+ config.config['weather_data_cachefile'],
+ config.config['weather_data_stalest_acceptable'].total_seconds(),
):
import pickle
+
with open(config.config['weather_data_cachefile'], 'rb') as rf:
weather_data = pickle.load(rf)
return cls(weather_data)
@@ -196,6 +193,7 @@ class CachedWeatherData(persistent.Persistent):
@overrides
def save(self) -> bool:
import pickle
+
with open(config.config['weather_data_cachefile'], 'wb') as wf:
pickle.dump(
self.weather_data,
diff --git a/cached/weather_forecast.py b/cached/weather_forecast.py
index b343938..58f53c3 100644
--- a/cached/weather_forecast.py
+++ b/cached/weather_forecast.py
@@ -1,60 +1,59 @@
#!/usr/bin/env python3
-from dataclasses import dataclass
import datetime
import logging
import os
-from typing import Any
import urllib.request
+from dataclasses import dataclass
+from typing import Any
import astral # type: ignore
+import pytz
from astral.sun import sun # type: ignore
from bs4 import BeautifulSoup # type: ignore
from overrides import overrides
-import pytz
import argparse_utils
import config
-import datetime_utils
import dateparse.dateparse_utils as dp
+import datetime_utils
import persistent
-import text_utils
import smart_home.thermometers as temps
-
+import text_utils
logger = logging.getLogger(__name__)
cfg = config.add_commandline_args(
f'Cached Weather Forecast ({__file__})',
- 'Arguments controlling detailed weather rendering'
+ 'Arguments controlling detailed weather rendering',
)
cfg.add_argument(
'--weather_forecast_cachefile',
type=str,
default=f'{os.environ["HOME"]}/cache/.weather_forecast_cache',
metavar='FILENAME',
- help='File in which to cache weather data'
+ help='File in which to cache weather data',
)
cfg.add_argument(
'--weather_forecast_stalest_acceptable',
type=argparse_utils.valid_duration,
- default=datetime.timedelta(seconds=7200), # 2 hours
+ default=datetime.timedelta(seconds=7200), # 2 hours
metavar='DURATION',
- help='Maximum acceptable age of cached data. If zero, forces a refetch'
+ help='Maximum acceptable age of cached data. If zero, forces a refetch',
)
@dataclass
class WeatherForecast:
- date: datetime.date # The date
- sunrise: datetime.datetime # Sunrise datetime
- sunset: datetime.datetime # Sunset datetime
- description: str # Textual description of weather
+ date: datetime.date # The date
+ sunrise: datetime.datetime # Sunrise datetime
+ sunset: datetime.datetime # Sunset datetime
+ description: str # Textual description of weather
[email protected]_autoloaded_singleton()
[email protected]_autoloaded_singleton() # type: ignore
class CachedDetailedWeatherForecast(persistent.Persistent):
- def __init__(self, forecasts = None):
+ def __init__(self, forecasts=None):
if forecasts is not None:
self.forecasts = forecasts
return
@@ -82,8 +81,7 @@ class CachedDetailedWeatherForecast(persistent.Persistent):
last_dt = now
dt = now
for (day, txt) in zip(
- forecast.find_all('b'),
- forecast.find_all(class_='col-sm-10 forecast-text')
+ forecast.find_all('b'), forecast.find_all(class_='col-sm-10 forecast-text')
):
last_dt = dt
try:
@@ -112,20 +110,21 @@ class CachedDetailedWeatherForecast(persistent.Persistent):
self.forecasts[dt.date()].description += '\n' + blurb
else:
self.forecasts[dt.date()] = WeatherForecast(
- date = dt,
- sunrise = sunrise,
- sunset = sunset,
- description = blurb,
+ date=dt,
+ sunrise=sunrise,
+ sunset=sunset,
+ description=blurb,
)
@classmethod
@overrides
def load(cls) -> Any:
if persistent.was_file_written_within_n_seconds(
- config.config['weather_forecast_cachefile'],
- config.config['weather_forecast_stalest_acceptable'].total_seconds(),
+ config.config['weather_forecast_cachefile'],
+ config.config['weather_forecast_stalest_acceptable'].total_seconds(),
):
import pickle
+
with open(config.config['weather_forecast_cachefile'], 'rb') as rf:
weather_data = pickle.load(rf)
return cls(weather_data)
@@ -134,6 +133,7 @@ class CachedDetailedWeatherForecast(persistent.Persistent):
@overrides
def save(self) -> bool:
import pickle
+
with open(config.config['weather_forecast_cachefile'], 'wb') as wf:
pickle.dump(
self.forecasts,