Shifted away from (abandoned) Yahoo API to OpenWeatherMap (#2038)

* Shifted away from (abandoned) Yahoo API to OpenWeatherMap
* Calculate gradient based on converted temperature
* Added Stubs for https://freegeoip.app as well as https://api.openweathermap.com
* Updated tests for weather segment with OpenWeatherMap mocking
* Make Weather API key configurable
* Added documentation for the OpenWeatherMap API keys
This commit is contained in:
StopMotionCuber 2020-09-19 07:31:49 +02:00 committed by GitHub
parent 992c5464ba
commit 73881c1dce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 142 additions and 129 deletions

View File

@ -117,10 +117,14 @@ segments that you may want to customize right away:
so unless youre on a VPN you probably wont have to change the location so unless youre on a VPN you probably wont have to change the location
query. query.
It is using OpenWeatherMap as a provider, which can be configured with a
personal API key. These can be generated `here
<https://home.openweathermap.org/api_keys>`_
If you want to change the location query or the temperature unit youll If you want to change the location query or the temperature unit youll
have to update the segment arguments. Open a theme file, scroll down to have to update the segment arguments. Open a theme file, scroll down to
the weather segment and update it to include unit/location query the weather segment and update it to include unit, location query or
arguments: api key arguments:
.. code-block:: javascript .. code-block:: javascript
@ -129,7 +133,8 @@ segments that you may want to customize right away:
"priority": 50, "priority": 50,
"args": { "args": {
"unit": "F", "unit": "F",
"location_query": "oslo, norway" "location_query": "oslo, norway",
"weather_api_key": "your_api_key"
} }
}, },

View File

@ -2,76 +2,80 @@
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
import json import json
from collections import namedtuple
from powerline.lib.url import urllib_read, urllib_urlencode from powerline.lib.url import urllib_read, urllib_urlencode
from powerline.lib.threaded import KwThreadedSegment from powerline.lib.threaded import KwThreadedSegment
from powerline.segments import with_docstring from powerline.segments import with_docstring
_WeatherKey = namedtuple('Key', 'location_query weather_api_key')
# XXX Warning: module name must not be equal to the segment name as long as this # XXX Warning: module name must not be equal to the segment name as long as this
# segment is imported into powerline.segments.common module. # segment is imported into powerline.segments.common module.
# Weather condition code descriptions available at # Weather condition code descriptions available at
# http://developer.yahoo.com/weather/#codes # https://openweathermap.org/weather-conditions
weather_conditions_codes = ( weather_conditions_codes = {
('tornado', 'stormy'), # 0 200: ('stormy',),
('tropical_storm', 'stormy'), # 1 201: ('stormy',),
('hurricane', 'stormy'), # 2 202: ('stormy',),
('severe_thunderstorms', 'stormy'), # 3 210: ('stormy',),
('thunderstorms', 'stormy'), # 4 211: ('stormy',),
('mixed_rain_and_snow', 'rainy' ), # 5 212: ('stormy',),
('mixed_rain_and_sleet', 'rainy' ), # 6 221: ('stormy',),
('mixed_snow_and_sleet', 'snowy' ), # 7 230: ('stormy',),
('freezing_drizzle', 'rainy' ), # 8 231: ('stormy',),
('drizzle', 'rainy' ), # 9 232: ('stormy',),
('freezing_rain', 'rainy' ), # 10 300: ('rainy',),
('showers', 'rainy' ), # 11 301: ('rainy',),
('showers', 'rainy' ), # 12 302: ('rainy',),
('snow_flurries', 'snowy' ), # 13 310: ('rainy',),
('light_snow_showers', 'snowy' ), # 14 311: ('rainy',),
('blowing_snow', 'snowy' ), # 15 312: ('rainy',),
('snow', 'snowy' ), # 16 313: ('rainy',),
('hail', 'snowy' ), # 17 314: ('rainy',),
('sleet', 'snowy' ), # 18 321: ('rainy',),
('dust', 'foggy' ), # 19 500: ('rainy',),
('fog', 'foggy' ), # 20 501: ('rainy',),
('haze', 'foggy' ), # 21 502: ('rainy',),
('smoky', 'foggy' ), # 22 503: ('rainy',),
('blustery', 'windy' ), # 23 504: ('rainy',),
('windy', ), # 24 511: ('snowy',),
('cold', 'day' ), # 25 520: ('rainy',),
('clouds', 'cloudy'), # 26 521: ('rainy',),
('mostly_cloudy_night', 'cloudy'), # 27 522: ('rainy',),
('mostly_cloudy_day', 'cloudy'), # 28 531: ('rainy',),
('partly_cloudy_night', 'cloudy'), # 29 600: ('snowy',),
('partly_cloudy_day', 'cloudy'), # 30 601: ('snowy',),
('clear_night', 'night' ), # 31 602: ('snowy',),
('sun', 'sunny' ), # 32 611: ('snowy',),
('fair_night', 'night' ), # 33 612: ('snowy',),
('fair_day', 'day' ), # 34 613: ('snowy',),
('mixed_rain_and_hail', 'rainy' ), # 35 615: ('snowy',),
('hot', 'sunny' ), # 36 616: ('snowy',),
('isolated_thunderstorms', 'stormy'), # 37 620: ('snowy',),
('scattered_thunderstorms', 'stormy'), # 38 621: ('snowy',),
('scattered_thunderstorms', 'stormy'), # 39 622: ('snowy',),
('scattered_showers', 'rainy' ), # 40 701: ('foggy',),
('heavy_snow', 'snowy' ), # 41 711: ('foggy',),
('scattered_snow_showers', 'snowy' ), # 42 721: ('foggy',),
('heavy_snow', 'snowy' ), # 43 731: ('foggy',),
('partly_cloudy', 'cloudy'), # 44 741: ('foggy',),
('thundershowers', 'rainy' ), # 45 751: ('foggy',),
('snow_showers', 'snowy' ), # 46 761: ('foggy',),
('isolated_thundershowers', 'rainy' ), # 47 762: ('foggy',),
) 771: ('foggy',),
# ('day', (25, 34)), 781: ('foggy',),
# ('rainy', (5, 6, 8, 9, 10, 11, 12, 35, 40, 45, 47)), 800: ('sunny',),
# ('cloudy', (26, 27, 28, 29, 30, 44)), 801: ('cloudy',),
# ('snowy', (7, 13, 14, 15, 16, 17, 18, 41, 42, 43, 46)), 802: ('cloudy',),
# ('stormy', (0, 1, 2, 3, 4, 37, 38, 39)), 803: ('cloudy',),
# ('foggy', (19, 20, 21, 22, 23)), 804: ('cloudy',),
# ('sunny', (32, 36)), }
# ('night', (31, 33))):
weather_conditions_icons = { weather_conditions_icons = {
'day': 'DAY', 'day': 'DAY',
'blustery': 'WIND', 'blustery': 'WIND',
@ -88,9 +92,9 @@ weather_conditions_icons = {
} }
temp_conversions = { temp_conversions = {
'C': lambda temp: temp, 'C': lambda temp: temp - 273.15,
'F': lambda temp: (temp * 9 / 5) + 32, 'F': lambda temp: (temp * 9 / 5) - 459.67,
'K': lambda temp: temp + 273.15, 'K': lambda temp: temp,
} }
# Note: there are also unicode characters for units: ℃, ℉ and # Note: there are also unicode characters for units: ℃, ℉ and
@ -105,38 +109,37 @@ class WeatherSegment(KwThreadedSegment):
interval = 600 interval = 600
default_location = None default_location = None
location_urls = {} location_urls = {}
weather_api_key = "fbc9549d91a5e4b26c15be0dbdac3460"
@staticmethod @staticmethod
def key(location_query=None, **kwargs): def key(location_query=None, **kwargs):
return location_query
def get_request_url(self, location_query):
try: try:
return self.location_urls[location_query] weather_api_key = kwargs["weather_api_key"]
except KeyError:
weather_api_key = WeatherSegment.weather_api_key
return _WeatherKey(location_query, weather_api_key)
def get_request_url(self, weather_key):
try:
return self.location_urls[weather_key]
except KeyError: except KeyError:
if location_query is None:
location_data = json.loads(urllib_read('http://geoip.nekudo.com/api/'))
location = ','.join((
location_data['city'],
location_data['country']['name'],
location_data['country']['code']
))
self.info('Location returned by nekudo is {0}', location)
else:
location = location_query
query_data = { query_data = {
'q': "appid": weather_key.weather_api_key
'use "https://raw.githubusercontent.com/yql/yql-tables/master/weather/weather.bylocation.xml" as we;'
'select * from weather.forecast where woeid in'
' (select woeid from geo.places(1) where text="{0}") and u="c"'.format(location).encode('utf-8'),
'format': 'json',
} }
location_query = weather_key.location_query
if location_query is None:
location_data = json.loads(urllib_read('https://freegeoip.app/json/'))
query_data["lat"] = location_data["latitude"]
query_data["lon"] = location_data["longitude"]
else:
query_data["q"] = location_query
self.location_urls[location_query] = url = ( self.location_urls[location_query] = url = (
'http://query.yahooapis.com/v1/public/yql?' + urllib_urlencode(query_data)) "https://api.openweathermap.org/data/2.5/weather?" +
urllib_urlencode(query_data))
return url return url
def compute_state(self, location_query): def compute_state(self, weather_key):
url = self.get_request_url(location_query) url = self.get_request_url(weather_key)
raw_response = urllib_read(url) raw_response = urllib_read(url)
if not raw_response: if not raw_response:
self.error('Failed to get response') self.error('Failed to get response')
@ -144,22 +147,18 @@ class WeatherSegment(KwThreadedSegment):
response = json.loads(raw_response) response = json.loads(raw_response)
try: try:
condition = response['query']['results']['channel']['item']['condition'] condition = response['weather'][0]
condition_code = int(condition['code']) condition_code = int(condition['id'])
temp = float(condition['temp']) temp = float(response['main']['temp'])
except (KeyError, ValueError): except (KeyError, ValueError):
self.exception('Yahoo returned malformed or unexpected response: {0}', repr(raw_response)) self.exception('OpenWeatherMap returned malformed or unexpected response: {0}', repr(raw_response))
return None return None
try: try:
icon_names = weather_conditions_codes[condition_code] icon_names = weather_conditions_codes[condition_code]
except IndexError: except IndexError:
if condition_code == 3200: icon_names = ('unknown',)
icon_names = ('not_available',) self.error('Unknown condition code: {0}', condition_code)
self.warn('Weather is not available for location {0}', self.location)
else:
icon_names = ('unknown',)
self.error('Unknown condition code: {0}', condition_code)
return (temp, icon_names) return (temp, icon_names)
@ -179,12 +178,12 @@ class WeatherSegment(KwThreadedSegment):
temp_format = temp_format or ('{temp:.0f}' + temp_units[unit]) temp_format = temp_format or ('{temp:.0f}' + temp_units[unit])
converted_temp = temp_conversions[unit](temp) converted_temp = temp_conversions[unit](temp)
if temp <= temp_coldest: if converted_temp <= temp_coldest:
gradient_level = 0 gradient_level = 0
elif temp >= temp_hottest: elif converted_temp >= temp_hottest:
gradient_level = 100 gradient_level = 100
else: else:
gradient_level = (temp - temp_coldest) * 100.0 / (temp_hottest - temp_coldest) gradient_level = (converted_temp - temp_coldest) * 100.0 / (temp_hottest - temp_coldest)
groups = ['weather_condition_' + icon_name for icon_name in icon_names] + ['weather_conditions', 'weather'] groups = ['weather_condition_' + icon_name for icon_name in icon_names] + ['weather_conditions', 'weather']
return [ return [
{ {
@ -202,9 +201,9 @@ class WeatherSegment(KwThreadedSegment):
weather = with_docstring(WeatherSegment(), weather = with_docstring(WeatherSegment(),
'''Return weather from Yahoo! Weather. '''Return weather from OpenWeatherMaps.
Uses GeoIP lookup from http://geoip.nekudo.com to automatically determine Uses GeoIP lookup from https://freegeoip.app to automatically determine
your current location. This should be changed if youre in a VPN or if your your current location. This should be changed if youre in a VPN or if your
IP address is registered at another location. IP address is registered at another location.
@ -231,5 +230,5 @@ weather conditions.
Divider highlight group used: ``background:divider``. Divider highlight group used: ``background:divider``.
Highlight groups used: ``weather_conditions`` or ``weather``, ``weather_temp_gradient`` (gradient) or ``weather``. Highlight groups used: ``weather_conditions`` or ``weather``, ``weather_temp_gradient`` (gradient) or ``weather``.
Also uses ``weather_conditions_{condition}`` for all weather conditions supported by Yahoo. Also uses ``weather_conditions_{condition}`` for all weather conditions supported by OpenWeatherMap.
''') ''')

View File

@ -44,15 +44,23 @@ def urllib_read(query_url):
return '127.0.0.1' return '127.0.0.1'
elif query_url.startswith('http://ipv6.icanhazip.com'): elif query_url.startswith('http://ipv6.icanhazip.com'):
return '2001:4801:7818:6:abc5:ba2c:ff10:275f' return '2001:4801:7818:6:abc5:ba2c:ff10:275f'
elif query_url.startswith('https://freegeoip.app/json/'):
return '{"ip":"82.145.55.16","country_code":"DE","country_name":"Germany","region_code":"NI","region_name":"Lower Saxony","city":"Meppen","zip_code":"49716","time_zone":"Europe/Berlin","latitude":52.6833,"longitude":7.3167,"metro_code":0}'
elif query_url.startswith('http://geoip.nekudo.com/api/'): elif query_url.startswith('http://geoip.nekudo.com/api/'):
return '{"city":"Meppen","country":{"name":"Germany", "code":"DE"},"location":{"accuracy_radius":100,"latitude":52.6833,"longitude":7.3167,"time_zone":"Europe\/Berlin"},"ip":"82.145.55.16"}' return '{"city":"Meppen","country":{"name":"Germany", "code":"DE"},"location":{"accuracy_radius":100,"latitude":52.6833,"longitude":7.3167,"time_zone":"Europe\/Berlin"},"ip":"82.145.55.16"}'
elif query_url.startswith('http://query.yahooapis.com/v1/public/'): elif query_url.startswith('http://query.yahooapis.com/v1/public/'):
if 'Meppen' in query_url: if 'Meppen' in query_url or '52.6833' in query_url:
return r'{"query":{"count":1,"created":"2016-05-13T19:43:18Z","lang":"en-US","results":{"channel":{"units":{"distance":"mi","pressure":"in","speed":"mph","temperature":"C"},"title":"Yahoo! Weather - Meppen, NI, DE","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/","description":"Yahoo! Weather for Meppen, NI, DE","language":"en-us","lastBuildDate":"Fri, 13 May 2016 09:43 PM CEST","ttl":"60","location":{"city":"Meppen","country":"Germany","region":" NI"},"wind":{"chill":"55","direction":"350","speed":"25"},"atmosphere":{"humidity":"57","pressure":"1004.0","rising":"0","visibility":"16.1"},"astronomy":{"sunrise":"5:35 am","sunset":"9:21 pm"},"image":{"title":"Yahoo! Weather","width":"142","height":"18","link":"http://weather.yahoo.com","url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"},"item":{"title":"Conditions for Meppen, NI, DE at 08:00 PM CEST","lat":"52.68993","long":"7.29115","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/","pubDate":"Fri, 13 May 2016 08:00 PM CEST","condition":{"code":"23","date":"Fri, 13 May 2016 08:00 PM CEST","temp":"14","text":"Breezy"},"forecast":[{"code":"30","date":"13 May 2016","day":"Fri","high":"71","low":"48","text":"Partly Cloudy"},{"code":"28","date":"14 May 2016","day":"Sat","high":"54","low":"44","text":"Mostly Cloudy"},{"code":"11","date":"15 May 2016","day":"Sun","high":"55","low":"43","text":"Showers"},{"code":"28","date":"16 May 2016","day":"Mon","high":"54","low":"42","text":"Mostly Cloudy"},{"code":"28","date":"17 May 2016","day":"Tue","high":"57","low":"43","text":"Mostly Cloudy"},{"code":"12","date":"18 May 2016","day":"Wed","high":"62","low":"45","text":"Rain"},{"code":"28","date":"19 May 2016","day":"Thu","high":"63","low":"48","text":"Mostly Cloudy"},{"code":"28","date":"20 May 2016","day":"Fri","high":"67","low":"50","text":"Mostly Cloudy"},{"code":"30","date":"21 May 2016","day":"Sat","high":"71","low":"50","text":"Partly Cloudy"},{"code":"30","date":"22 May 2016","day":"Sun","high":"74","low":"54","text":"Partly Cloudy"}],"description":"<![CDATA[<img src=\"http://l.yimg.com/a/i/us/we/52/23.gif\"/>\n<BR />\n<b>Current Conditions:</b>\n<BR />Breezy\n<BR />\n<BR />\n<b>Forecast:</b>\n<BR /> Fri - Partly Cloudy. High: 71Low: 48\n<BR /> Sat - Mostly Cloudy. High: 54Low: 44\n<BR /> Sun - Showers. High: 55Low: 43\n<BR /> Mon - Mostly Cloudy. High: 54Low: 42\n<BR /> Tue - Mostly Cloudy. High: 57Low: 43\n<BR />\n<BR />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/\">Full Forecast at Yahoo! Weather</a>\n<BR />\n<BR />\n(provided by <a href=\"http://www.weather.com\" >The Weather Channel</a>)\n<BR />\n]]>","guid":{"isPermaLink":"false"}}}}}}' return r'{"query":{"count":1,"created":"2016-05-13T19:43:18Z","lang":"en-US","results":{"channel":{"units":{"distance":"mi","pressure":"in","speed":"mph","temperature":"C"},"title":"Yahoo! Weather - Meppen, NI, DE","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/","description":"Yahoo! Weather for Meppen, NI, DE","language":"en-us","lastBuildDate":"Fri, 13 May 2016 09:43 PM CEST","ttl":"60","location":{"city":"Meppen","country":"Germany","region":" NI"},"wind":{"chill":"55","direction":"350","speed":"25"},"atmosphere":{"humidity":"57","pressure":"1004.0","rising":"0","visibility":"16.1"},"astronomy":{"sunrise":"5:35 am","sunset":"9:21 pm"},"image":{"title":"Yahoo! Weather","width":"142","height":"18","link":"http://weather.yahoo.com","url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"},"item":{"title":"Conditions for Meppen, NI, DE at 08:00 PM CEST","lat":"52.68993","long":"7.29115","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/","pubDate":"Fri, 13 May 2016 08:00 PM CEST","condition":{"code":"23","date":"Fri, 13 May 2016 08:00 PM CEST","temp":"14","text":"Breezy"},"forecast":[{"code":"30","date":"13 May 2016","day":"Fri","high":"71","low":"48","text":"Partly Cloudy"},{"code":"28","date":"14 May 2016","day":"Sat","high":"54","low":"44","text":"Mostly Cloudy"},{"code":"11","date":"15 May 2016","day":"Sun","high":"55","low":"43","text":"Showers"},{"code":"28","date":"16 May 2016","day":"Mon","high":"54","low":"42","text":"Mostly Cloudy"},{"code":"28","date":"17 May 2016","day":"Tue","high":"57","low":"43","text":"Mostly Cloudy"},{"code":"12","date":"18 May 2016","day":"Wed","high":"62","low":"45","text":"Rain"},{"code":"28","date":"19 May 2016","day":"Thu","high":"63","low":"48","text":"Mostly Cloudy"},{"code":"28","date":"20 May 2016","day":"Fri","high":"67","low":"50","text":"Mostly Cloudy"},{"code":"30","date":"21 May 2016","day":"Sat","high":"71","low":"50","text":"Partly Cloudy"},{"code":"30","date":"22 May 2016","day":"Sun","high":"74","low":"54","text":"Partly Cloudy"}],"description":"<![CDATA[<img src=\"http://l.yimg.com/a/i/us/we/52/23.gif\"/>\n<BR />\n<b>Current Conditions:</b>\n<BR />Breezy\n<BR />\n<BR />\n<b>Forecast:</b>\n<BR /> Fri - Partly Cloudy. High: 71Low: 48\n<BR /> Sat - Mostly Cloudy. High: 54Low: 44\n<BR /> Sun - Showers. High: 55Low: 43\n<BR /> Mon - Mostly Cloudy. High: 54Low: 42\n<BR /> Tue - Mostly Cloudy. High: 57Low: 43\n<BR />\n<BR />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/\">Full Forecast at Yahoo! Weather</a>\n<BR />\n<BR />\n(provided by <a href=\"http://www.weather.com\" >The Weather Channel</a>)\n<BR />\n]]>","guid":{"isPermaLink":"false"}}}}}}'
elif 'Moscow' in query_url: elif 'Moscow' in query_url:
return r'{"query":{"count":1,"created":"2016-05-13T19:47:01Z","lang":"en-US","results":{"channel":{"units":{"distance":"mi","pressure":"in","speed":"mph","temperature":"C"},"title":"Yahoo! Weather - Moscow, Moscow Federal City, RU","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/","description":"Yahoo! Weather for Moscow, Moscow Federal City, RU","language":"en-us","lastBuildDate":"Fri, 13 May 2016 10:47 PM MSK","ttl":"60","location":{"city":"Moscow","country":"Russia","region":" Moscow Federal City"},"wind":{"chill":"45","direction":"80","speed":"11"},"atmosphere":{"humidity":"52","pressure":"993.0","rising":"0","visibility":"16.1"},"astronomy":{"sunrise":"4:19 am","sunset":"8:34 pm"},"image":{"title":"Yahoo! Weather","width":"142","height":"18","link":"http://weather.yahoo.com","url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"},"item":{"title":"Conditions for Moscow, Moscow Federal City, RU at 09:00 PM MSK","lat":"55.741638","long":"37.605061","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/","pubDate":"Fri, 13 May 2016 09:00 PM MSK","condition":{"code":"33","date":"Fri, 13 May 2016 09:00 PM MSK","temp":"9","text":"Mostly Clear"},"forecast":[{"code":"30","date":"13 May 2016","day":"Fri","high":"62","low":"41","text":"Partly Cloudy"},{"code":"30","date":"14 May 2016","day":"Sat","high":"64","low":"43","text":"Partly Cloudy"},{"code":"30","date":"15 May 2016","day":"Sun","high":"63","low":"44","text":"Partly Cloudy"},{"code":"12","date":"16 May 2016","day":"Mon","high":"60","low":"47","text":"Rain"},{"code":"12","date":"17 May 2016","day":"Tue","high":"64","low":"48","text":"Rain"},{"code":"28","date":"18 May 2016","day":"Wed","high":"67","low":"48","text":"Mostly Cloudy"},{"code":"12","date":"19 May 2016","day":"Thu","high":"68","low":"49","text":"Rain"},{"code":"39","date":"20 May 2016","day":"Fri","high":"66","low":"50","text":"Scattered Showers"},{"code":"39","date":"21 May 2016","day":"Sat","high":"69","low":"49","text":"Scattered Showers"},{"code":"30","date":"22 May 2016","day":"Sun","high":"73","low":"50","text":"Partly Cloudy"}],"description":"<![CDATA[<img src=\"http://l.yimg.com/a/i/us/we/52/33.gif\"/>\n<BR />\n<b>Current Conditions:</b>\n<BR />Mostly Clear\n<BR />\n<BR />\n<b>Forecast:</b>\n<BR /> Fri - Partly Cloudy. High: 62Low: 41\n<BR /> Sat - Partly Cloudy. High: 64Low: 43\n<BR /> Sun - Partly Cloudy. High: 63Low: 44\n<BR /> Mon - Rain. High: 60Low: 47\n<BR /> Tue - Rain. High: 64Low: 48\n<BR />\n<BR />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/\">Full Forecast at Yahoo! Weather</a>\n<BR />\n<BR />\n(provided by <a href=\"http://www.weather.com\" >The Weather Channel</a>)\n<BR />\n]]>","guid":{"isPermaLink":"false"}}}}}}' return r'{"query":{"count":1,"created":"2016-05-13T19:47:01Z","lang":"en-US","results":{"channel":{"units":{"distance":"mi","pressure":"in","speed":"mph","temperature":"C"},"title":"Yahoo! Weather - Moscow, Moscow Federal City, RU","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/","description":"Yahoo! Weather for Moscow, Moscow Federal City, RU","language":"en-us","lastBuildDate":"Fri, 13 May 2016 10:47 PM MSK","ttl":"60","location":{"city":"Moscow","country":"Russia","region":" Moscow Federal City"},"wind":{"chill":"45","direction":"80","speed":"11"},"atmosphere":{"humidity":"52","pressure":"993.0","rising":"0","visibility":"16.1"},"astronomy":{"sunrise":"4:19 am","sunset":"8:34 pm"},"image":{"title":"Yahoo! Weather","width":"142","height":"18","link":"http://weather.yahoo.com","url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"},"item":{"title":"Conditions for Moscow, Moscow Federal City, RU at 09:00 PM MSK","lat":"55.741638","long":"37.605061","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/","pubDate":"Fri, 13 May 2016 09:00 PM MSK","condition":{"code":"33","date":"Fri, 13 May 2016 09:00 PM MSK","temp":"9","text":"Mostly Clear"},"forecast":[{"code":"30","date":"13 May 2016","day":"Fri","high":"62","low":"41","text":"Partly Cloudy"},{"code":"30","date":"14 May 2016","day":"Sat","high":"64","low":"43","text":"Partly Cloudy"},{"code":"30","date":"15 May 2016","day":"Sun","high":"63","low":"44","text":"Partly Cloudy"},{"code":"12","date":"16 May 2016","day":"Mon","high":"60","low":"47","text":"Rain"},{"code":"12","date":"17 May 2016","day":"Tue","high":"64","low":"48","text":"Rain"},{"code":"28","date":"18 May 2016","day":"Wed","high":"67","low":"48","text":"Mostly Cloudy"},{"code":"12","date":"19 May 2016","day":"Thu","high":"68","low":"49","text":"Rain"},{"code":"39","date":"20 May 2016","day":"Fri","high":"66","low":"50","text":"Scattered Showers"},{"code":"39","date":"21 May 2016","day":"Sat","high":"69","low":"49","text":"Scattered Showers"},{"code":"30","date":"22 May 2016","day":"Sun","high":"73","low":"50","text":"Partly Cloudy"}],"description":"<![CDATA[<img src=\"http://l.yimg.com/a/i/us/we/52/33.gif\"/>\n<BR />\n<b>Current Conditions:</b>\n<BR />Mostly Clear\n<BR />\n<BR />\n<b>Forecast:</b>\n<BR /> Fri - Partly Cloudy. High: 62Low: 41\n<BR /> Sat - Partly Cloudy. High: 64Low: 43\n<BR /> Sun - Partly Cloudy. High: 63Low: 44\n<BR /> Mon - Rain. High: 60Low: 47\n<BR /> Tue - Rain. High: 64Low: 48\n<BR />\n<BR />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/\">Full Forecast at Yahoo! Weather</a>\n<BR />\n<BR />\n(provided by <a href=\"http://www.weather.com\" >The Weather Channel</a>)\n<BR />\n]]>","guid":{"isPermaLink":"false"}}}}}}'
else: elif query_url.startswith('https://api.openweathermap.org/data/2.5/'):
raise NotImplementedError if 'Meppen' in query_url or '52.6833' in query_url:
return r'{"coord":{"lon":7.29,"lat":52.69},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"base":"stations","main":{"temp":293.15,"feels_like":295.16,"temp_min":293.15,"temp_max":295.37,"pressure":1018,"humidity":77},"visibility":10000,"wind":{"speed":1.12,"deg":126},"clouds":{"all":0},"dt":1600196220,"sys":{"type":1,"id":1871,"country":"DE","sunrise":1600146332,"sunset":1600191996},"timezone":7200,"id":2871845,"name":"Meppen","cod":200}'
elif 'Moscow' in query_url:
return r'{"coord":{"lon":37.62,"lat":55.75},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"base":"stations","main":{"temp":283.15,"feels_like":280.78,"temp_min":283.15,"temp_max":284.26,"pressure":1019,"humidity":71},"visibility":10000,"wind":{"speed":3,"deg":330},"clouds":{"all":0},"dt":1600196224,"sys":{"type":1,"id":9029,"country":"RU","sunrise":1600138909,"sunset":1600184863},"timezone":10800,"id":524901,"name":"Moscow","cod":200}'
raise NotImplementedError
class Process(object): class Process(object):

View File

@ -947,46 +947,47 @@ class TestWthr(TestCommon):
pl = Pl() pl = Pl()
with replace_attr(self.module, 'urllib_read', urllib_read): with replace_attr(self.module, 'urllib_read', urllib_read):
self.assertEqual(self.module.weather(pl=pl), [ self.assertEqual(self.module.weather(pl=pl), [
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_blustery', 'weather_condition_windy', 'weather_conditions', 'weather'], 'contents': 'WINDY '}, {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_sunny', 'weather_conditions', 'weather'], 'contents': 'SUN '},
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '14°C', 'gradient_level': 62.857142857142854} {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '20°C', 'gradient_level': 71.42857142857143}
]) ])
self.assertEqual(self.module.weather(pl=pl, temp_coldest=0, temp_hottest=100), [ self.assertEqual(self.module.weather(pl=pl, temp_coldest=0, temp_hottest=100), [
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_blustery', 'weather_condition_windy', 'weather_conditions', 'weather'], 'contents': 'WINDY '}, {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_sunny', 'weather_conditions', 'weather'], 'contents': 'SUN '},
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '14°C', 'gradient_level': 14.0} {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '20°C', 'gradient_level': 20}
]) ])
self.assertEqual(self.module.weather(pl=pl, temp_coldest=-100, temp_hottest=-50), [ self.assertEqual(self.module.weather(pl=pl, temp_coldest=-100, temp_hottest=-50), [
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_blustery', 'weather_condition_windy', 'weather_conditions', 'weather'], 'contents': 'WINDY '}, {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_sunny', 'weather_conditions', 'weather'], 'contents': 'SUN '},
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '14°C', 'gradient_level': 100} {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '20°C', 'gradient_level': 100}
]) ])
self.assertEqual(self.module.weather(pl=pl, icons={'blustery': 'o'}), [ self.assertEqual(self.module.weather(pl=pl, icons={'sunny': 'o'}), [
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_blustery', 'weather_condition_windy', 'weather_conditions', 'weather'], 'contents': 'o '}, {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_sunny', 'weather_conditions', 'weather'], 'contents': 'o '},
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '14°C', 'gradient_level': 62.857142857142854} {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '20°C', 'gradient_level': 71.42857142857143}
])
self.assertEqual(self.module.weather(pl=pl, icons={'windy': 'x'}), [
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_blustery', 'weather_condition_windy', 'weather_conditions', 'weather'], 'contents': 'x '},
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '14°C', 'gradient_level': 62.857142857142854}
]) ])
# Test is disabled as no request has more than 1 weather condition associated currently
# self.assertEqual(self.module.weather(pl=pl, icons={'windy': 'x'}), [
# {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_blustery', 'weather_condition_windy', 'weather_conditions', 'weather'], 'contents': 'x '},
# {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '14°C', 'gradient_level': 62.857142857142854}
# ])
self.assertEqual(self.module.weather(pl=pl, unit='F'), [ self.assertEqual(self.module.weather(pl=pl, unit='F'), [
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_blustery', 'weather_condition_windy', 'weather_conditions', 'weather'], 'contents': 'WINDY '}, {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_sunny', 'weather_conditions', 'weather'], 'contents': 'SUN '},
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '57°F', 'gradient_level': 62.857142857142854} {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '68°F', 'gradient_level': 100}
]) ])
self.assertEqual(self.module.weather(pl=pl, unit='K'), [ self.assertEqual(self.module.weather(pl=pl, unit='K'), [
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_blustery', 'weather_condition_windy', 'weather_conditions', 'weather'], 'contents': 'WINDY '}, {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_sunny', 'weather_conditions', 'weather'], 'contents': 'SUN '},
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '287K', 'gradient_level': 62.857142857142854} {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '293K', 'gradient_level': 100}
]) ])
self.assertEqual(self.module.weather(pl=pl, temp_format='{temp:.1e}C'), [ self.assertEqual(self.module.weather(pl=pl, temp_format='{temp:.1e}C'), [
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_blustery', 'weather_condition_windy', 'weather_conditions', 'weather'], 'contents': 'WINDY '}, {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_sunny', 'weather_conditions', 'weather'], 'contents': 'SUN '},
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '1.4e+01C', 'gradient_level': 62.857142857142854} {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '2.0e+01C', 'gradient_level': 71.42857142857143}
]) ])
with replace_attr(self.module, 'urllib_read', urllib_read): with replace_attr(self.module, 'urllib_read', urllib_read):
self.module.weather.startup(pl=pl, location_query='Meppen,06,DE') self.module.weather.startup(pl=pl, location_query='Meppen,06,DE')
self.assertEqual(self.module.weather(pl=pl), [ self.assertEqual(self.module.weather(pl=pl), [
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_blustery', 'weather_condition_windy', 'weather_conditions', 'weather'], 'contents': 'WINDY '}, {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_sunny', 'weather_conditions', 'weather'], 'contents': 'SUN '},
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '14°C', 'gradient_level': 62.857142857142854} {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '20°C', 'gradient_level': 71.42857142857143}
]) ])
self.assertEqual(self.module.weather(pl=pl, location_query='Moscow,RU'), [ self.assertEqual(self.module.weather(pl=pl, location_query='Moscow,RU'), [
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_fair_night', 'weather_condition_night', 'weather_conditions', 'weather'], 'contents': 'NIGHT '}, {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_condition_sunny', 'weather_conditions', 'weather'], 'contents': 'SUN '},
{'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '9°C', 'gradient_level': 55.714285714285715} {'divider_highlight_group': 'background:divider', 'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'], 'contents': '10°C', 'gradient_level': 57.142857142857146}
]) ])
self.module.weather.shutdown() self.module.weather.shutdown()