Precommit black missed a file?

This commit is contained in:
Flamm, Matthew H
2019-08-03 11:52:55 +01:00
parent 3dc4d8485f
commit 55934905c3

View File

@@ -8,13 +8,29 @@ import aiohttp
import voluptuous as vol import voluptuous as vol
from homeassistant.components.weather import ( from homeassistant.components.weather import (
WeatherEntity, PLATFORM_SCHEMA, ATTR_FORECAST_CONDITION, WeatherEntity,
ATTR_FORECAST_TEMP, ATTR_FORECAST_TIME, PLATFORM_SCHEMA,
ATTR_FORECAST_WIND_SPEED, ATTR_FORECAST_WIND_BEARING) ATTR_FORECAST_CONDITION,
ATTR_FORECAST_TEMP,
ATTR_FORECAST_TIME,
ATTR_FORECAST_WIND_SPEED,
ATTR_FORECAST_WIND_BEARING,
)
from homeassistant.const import ( from homeassistant.const import (
CONF_API_KEY, CONF_NAME, CONF_LATITUDE, CONF_LONGITUDE, CONF_MODE, CONF_API_KEY,
LENGTH_KILOMETERS, LENGTH_METERS, LENGTH_MILES, PRESSURE_HPA, PRESSURE_PA, CONF_NAME,
PRESSURE_INHG, TEMP_CELSIUS, TEMP_FAHRENHEIT) CONF_LATITUDE,
CONF_LONGITUDE,
CONF_MODE,
LENGTH_KILOMETERS,
LENGTH_METERS,
LENGTH_MILES,
PRESSURE_HPA,
PRESSURE_PA,
PRESSURE_INHG,
TEMP_CELSIUS,
TEMP_FAHRENHEIT,
)
from homeassistant.exceptions import PlatformNotReady, ConfigEntryNotReady from homeassistant.exceptions import PlatformNotReady, ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
@@ -25,62 +41,81 @@ from homeassistant.util.temperature import convert as convert_temperature
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
ATTRIBUTION = 'Data from National Weather Service/NOAA' ATTRIBUTION = "Data from National Weather Service/NOAA"
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15) MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15)
CONF_STATION = 'station' CONF_STATION = "station"
ATTR_FORECAST_DETAIL_DESCRIPTION = 'detailed_description' ATTR_FORECAST_DETAIL_DESCRIPTION = "detailed_description"
ATTR_FORECAST_PRECIP_PROB = 'precipitation_probability' ATTR_FORECAST_PRECIP_PROB = "precipitation_probability"
ATTR_FORECAST_DAYTIME = 'daytime' ATTR_FORECAST_DAYTIME = "daytime"
# Ordered so that a single condition can be chosen from multiple weather codes. # Ordered so that a single condition can be chosen from multiple weather codes.
# Catalog of NWS icon weather codes listed at: # Catalog of NWS icon weather codes listed at:
# https://api.weather.gov/icons # https://api.weather.gov/icons
CONDITION_CLASSES = OrderedDict([ CONDITION_CLASSES = OrderedDict(
('snowy', ['Snow', [
'Sleet', ("snowy", ["Snow", "Sleet", "Blizzard"]),
'Blizzard']), (
('snowy-rainy', ['Rain/snow', "snowy-rainy",
'Rain/sleet', [
'Freezing rain/snow', "Rain/snow",
'Freezing rain', "Rain/sleet",
'Rain/freezing rain']), "Freezing rain/snow",
('hail', []), "Freezing rain",
('lightning-rainy', ['Thunderstorm (high cloud cover)', "Rain/freezing rain",
'Thunderstorm (medium cloud cover)', ],
'Thunderstorm (low cloud cover)']), ),
('lightning', []), ("hail", []),
('pouring', []), (
('rainy', ['Rain', "lightning-rainy",
'Rain showers (high cloud cover)', [
'Rain showers (low cloud cover)']), "Thunderstorm (high cloud cover)",
('windy-variant', ['Mostly cloudy and windy', "Thunderstorm (medium cloud cover)",
'Overcast and windy']), "Thunderstorm (low cloud cover)",
('windy', ['Fair/clear and windy', ],
'A few clouds and windy', ),
'Partly cloudy and windy']), ("lightning", []),
('fog', ['Fog/mist']), ("pouring", []),
('clear', ['Fair/clear']), # sunny and clear-night (
('cloudy', ['Mostly cloudy', "rainy",
'Overcast']), [
('partlycloudy', ['A few clouds', "Rain",
'Partly cloudy']), "Rain showers (high cloud cover)",
]) "Rain showers (low cloud cover)",
],
),
("windy-variant", ["Mostly cloudy and windy", "Overcast and windy"]),
(
"windy",
[
"Fair/clear and windy",
"A few clouds and windy",
"Partly cloudy and windy",
],
),
("fog", ["Fog/mist"]),
("clear", ["Fair/clear"]), # sunny and clear-night
("cloudy", ["Mostly cloudy", "Overcast"]),
("partlycloudy", ["A few clouds", "Partly cloudy"]),
]
)
ERRORS = (aiohttp.ClientError, JSONDecodeError) ERRORS = (aiohttp.ClientError, JSONDecodeError)
FORECAST_MODE = ['daynight', 'hourly'] FORECAST_MODE = ["daynight", "hourly"]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
vol.Optional(CONF_NAME): cv.string, {
vol.Optional(CONF_LATITUDE): cv.latitude, vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_LONGITUDE): cv.longitude, vol.Optional(CONF_LATITUDE): cv.latitude,
vol.Optional(CONF_MODE, default='daynight'): vol.In(FORECAST_MODE), vol.Optional(CONF_LONGITUDE): cv.longitude,
vol.Optional(CONF_STATION): cv.string, vol.Optional(CONF_MODE, default="daynight"): vol.In(FORECAST_MODE),
vol.Required(CONF_API_KEY): cv.string, vol.Optional(CONF_STATION): cv.string,
}) vol.Required(CONF_API_KEY): cv.string,
}
)
def convert_condition(time, weather): def convert_condition(time, weather):
@@ -94,22 +129,27 @@ def convert_condition(time, weather):
prec_probs = [w[1] or 0 for w in weather] prec_probs = [w[1] or 0 for w in weather]
# Choose condition with highest priority. # Choose condition with highest priority.
cond = next((key for key, value in CONDITION_CLASSES.items() cond = next(
if any(condition in value for condition in conditions)), (
conditions[0]) key
for key, value in CONDITION_CLASSES.items()
if any(condition in value for condition in conditions)
),
conditions[0],
)
if cond == 'clear': if cond == "clear":
if time == 'day': if time == "day":
return 'sunny', max(prec_probs) return "sunny", max(prec_probs)
if time == 'night': if time == "night":
return 'clear-night', max(prec_probs) return "clear-night", max(prec_probs)
return cond, max(prec_probs) return cond, max(prec_probs)
async def async_setup_platform(hass, config, async_add_entities, async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
discovery_info=None):
"""Set up the NWS weather platform.""" """Set up the NWS weather platform."""
from pynws import SimpleNWS from pynws import SimpleNWS
latitude = config.get(CONF_LATITUDE, hass.config.latitude) latitude = config.get(CONF_LATITUDE, hass.config.latitude)
longitude = config.get(CONF_LONGITUDE, hass.config.longitude) longitude = config.get(CONF_LONGITUDE, hass.config.longitude)
station = config.get(CONF_STATION) station = config.get(CONF_STATION)
@@ -129,17 +169,20 @@ async def async_setup_platform(hass, config, async_add_entities,
try: try:
await nws.set_station(station) await nws.set_station(station)
except ERRORS as status: except ERRORS as status:
_LOGGER.error("Error getting station list for %s: %s", _LOGGER.error(
(latitude, longitude), status) "Error getting station list for %s: %s", (latitude, longitude), status
)
raise PlatformNotReady raise PlatformNotReady
_LOGGER.debug("Station list: %s", nws.stations) _LOGGER.debug("Station list: %s", nws.stations)
_LOGGER.debug("Initialized for coordinates %s, %s -> station %s", _LOGGER.debug(
latitude, longitude, nws.station) "Initialized for coordinates %s, %s -> station %s",
latitude,
longitude,
nws.station,
)
async_add_entities( async_add_entities([NWSWeather(nws, mode, hass.config.units, config)], True)
[NWSWeather(nws, mode, hass.config.units, config)],
True)
class NWSWeather(WeatherEntity): class NWSWeather(WeatherEntity):
@@ -162,16 +205,20 @@ class NWSWeather(WeatherEntity):
try: try:
await self.nws.update_observation() await self.nws.update_observation()
except ERRORS as status: except ERRORS as status:
_LOGGER.error("Error updating observation from station %s: %s", _LOGGER.error(
self.nws.station, status) "Error updating observation from station %s: %s",
self.nws.station,
status,
)
else: else:
self.observation = self.nws.observation self.observation = self.nws.observation
_LOGGER.debug("Updating forecast") _LOGGER.debug("Updating forecast")
try: try:
await self.nws.update_forecast() await self.nws.update_forecast()
except ERRORS as status: except ERRORS as status:
_LOGGER.error("Error updating forecast from station %s: %s", _LOGGER.error(
self.nws.station, status) "Error updating forecast from station %s: %s", self.nws.station, status
)
else: else:
self._forecast = self.nws.forecast self._forecast = self.nws.forecast
return return
@@ -191,7 +238,7 @@ class NWSWeather(WeatherEntity):
"""Return the current temperature.""" """Return the current temperature."""
temp_c = None temp_c = None
if self.observation: if self.observation:
temp_c = self.observation.get('temperature') temp_c = self.observation.get("temperature")
if temp_c: if temp_c:
return convert_temperature(temp_c, TEMP_CELSIUS, TEMP_FAHRENHEIT) return convert_temperature(temp_c, TEMP_CELSIUS, TEMP_FAHRENHEIT)
return None return None
@@ -201,16 +248,14 @@ class NWSWeather(WeatherEntity):
"""Return the current pressure.""" """Return the current pressure."""
pressure_pa = None pressure_pa = None
if self.observation: if self.observation:
pressure_pa = self.observation.get('seaLevelPressure') pressure_pa = self.observation.get("seaLevelPressure")
if pressure_pa is None: if pressure_pa is None:
return None return None
if self.is_metric: if self.is_metric:
pressure = convert_pressure(pressure_pa, pressure = convert_pressure(pressure_pa, PRESSURE_PA, PRESSURE_HPA)
PRESSURE_PA, PRESSURE_HPA)
pressure = round(pressure) pressure = round(pressure)
else: else:
pressure = convert_pressure(pressure_pa, pressure = convert_pressure(pressure_pa, PRESSURE_PA, PRESSURE_INHG)
PRESSURE_PA, PRESSURE_INHG)
pressure = round(pressure, 2) pressure = round(pressure, 2)
return pressure return pressure
@@ -219,7 +264,7 @@ class NWSWeather(WeatherEntity):
"""Return the name of the sensor.""" """Return the name of the sensor."""
humidity = None humidity = None
if self.observation: if self.observation:
humidity = self.observation.get('relativeHumidity') humidity = self.observation.get("relativeHumidity")
return humidity return humidity
@property @property
@@ -227,14 +272,13 @@ class NWSWeather(WeatherEntity):
"""Return the current windspeed.""" """Return the current windspeed."""
wind_m_s = None wind_m_s = None
if self.observation: if self.observation:
wind_m_s = self.observation.get('windSpeed') wind_m_s = self.observation.get("windSpeed")
if wind_m_s is None: if wind_m_s is None:
return None return None
wind_m_hr = wind_m_s * 3600 wind_m_hr = wind_m_s * 3600
if self.is_metric: if self.is_metric:
wind = convert_distance(wind_m_hr, wind = convert_distance(wind_m_hr, LENGTH_METERS, LENGTH_KILOMETERS)
LENGTH_METERS, LENGTH_KILOMETERS)
else: else:
wind = convert_distance(wind_m_hr, LENGTH_METERS, LENGTH_MILES) wind = convert_distance(wind_m_hr, LENGTH_METERS, LENGTH_MILES)
return round(wind) return round(wind)
@@ -244,7 +288,7 @@ class NWSWeather(WeatherEntity):
"""Return the current wind bearing (degrees).""" """Return the current wind bearing (degrees)."""
wind_bearing = None wind_bearing = None
if self.observation: if self.observation:
wind_bearing = self.observation.get('windDirection') wind_bearing = self.observation.get("windDirection")
return wind_bearing return wind_bearing
@property @property
@@ -257,8 +301,8 @@ class NWSWeather(WeatherEntity):
"""Return current condition.""" """Return current condition."""
weather = None weather = None
if self.observation: if self.observation:
weather = self.observation.get('iconWeather') weather = self.observation.get("iconWeather")
time = self.observation.get('iconTime') time = self.observation.get("iconTime")
if weather: if weather:
cond, _ = convert_condition(time, weather) cond, _ = convert_condition(time, weather)
@@ -270,7 +314,7 @@ class NWSWeather(WeatherEntity):
"""Return visibility.""" """Return visibility."""
vis_m = None vis_m = None
if self.observation: if self.observation:
vis_m = self.observation.get('visibility') vis_m = self.observation.get("visibility")
if vis_m is None: if vis_m is None:
return None return None
@@ -289,15 +333,16 @@ class NWSWeather(WeatherEntity):
for forecast_entry in self._forecast: for forecast_entry in self._forecast:
data = { data = {
ATTR_FORECAST_DETAIL_DESCRIPTION: forecast_entry.get( ATTR_FORECAST_DETAIL_DESCRIPTION: forecast_entry.get(
'detailedForecast'), "detailedForecast"
ATTR_FORECAST_TEMP: forecast_entry.get('temperature'), ),
ATTR_FORECAST_TIME: forecast_entry.get('startTime'), ATTR_FORECAST_TEMP: forecast_entry.get("temperature"),
ATTR_FORECAST_TIME: forecast_entry.get("startTime"),
} }
if self.mode == 'daynight': if self.mode == "daynight":
data[ATTR_FORECAST_DAYTIME] = forecast_entry.get('isDaytime') data[ATTR_FORECAST_DAYTIME] = forecast_entry.get("isDaytime")
time = forecast_entry.get('iconTime') time = forecast_entry.get("iconTime")
weather = forecast_entry.get('iconWeather') weather = forecast_entry.get("iconWeather")
if time and weather: if time and weather:
cond, precip = convert_condition(time, weather) cond, precip = convert_condition(time, weather)
else: else:
@@ -305,14 +350,13 @@ class NWSWeather(WeatherEntity):
data[ATTR_FORECAST_CONDITION] = cond data[ATTR_FORECAST_CONDITION] = cond
data[ATTR_FORECAST_PRECIP_PROB] = precip data[ATTR_FORECAST_PRECIP_PROB] = precip
data[ATTR_FORECAST_WIND_BEARING] = \ data[ATTR_FORECAST_WIND_BEARING] = forecast_entry.get("windBearing")
forecast_entry.get('windBearing') wind_speed = forecast_entry.get("windSpeedAvg")
wind_speed = forecast_entry.get('windSpeedAvg')
if wind_speed: if wind_speed:
if self.is_metric: if self.is_metric:
data[ATTR_FORECAST_WIND_SPEED] = round( data[ATTR_FORECAST_WIND_SPEED] = round(
convert_distance(wind_speed, convert_distance(wind_speed, LENGTH_MILES, LENGTH_KILOMETERS)
LENGTH_MILES, LENGTH_KILOMETERS)) )
else: else:
data[ATTR_FORECAST_WIND_SPEED] = round(wind_speed) data[ATTR_FORECAST_WIND_SPEED] = round(wind_speed)
else: else: