improvements to weather module

* use openstreetmap nominatim instead of geonames
* set temperature to None if there is no temp available
* add new test cases to better test geolocation for various places
master
mutantmonkey 2013-08-24 18:45:05 -07:00
parent de8d87c413
commit 6443442aff
3 changed files with 55 additions and 24 deletions

View File

@ -282,6 +282,8 @@ def parse(data):
if m: if m:
w.temperature = parse_temp(m.group('temp')) w.temperature = parse_temp(m.group('temp'))
w.dewpoint = parse_temp(m.group('dewpoint')) w.dewpoint = parse_temp(m.group('dewpoint'))
else:
w.temperature = None
# pressure # pressure
pressure_re = re.compile(r"([QA])(\d+)") pressure_re = re.compile(r"([QA])(\d+)")

View File

@ -13,17 +13,42 @@ class TestWeather(unittest.TestCase):
def setUp(self): def setUp(self):
self.phenny = MagicMock() self.phenny = MagicMock()
def test_location(self): def test_locations(self):
name, countryName, lat, lng = location('24060') def check_places(*args):
def validate(actual_name, actual_lat, actual_lon):
names = [n.strip() for n in actual_name.split(',')]
for arg in args:
self.assertIn(arg, names)
return validate
self.assertEqual(name, "Blacksburg") locations = [
self.assertEqual(countryName, "United States") ('24060', check_places("Blacksburg", "Virginia")),
self.assertEqual(lat, 37.2295733) ('92121', check_places("San Diego", "California")),
self.assertEqual(lng, -80.4139393) ('94110', check_places("San Francisco", "California")),
('94041', check_places("Mountain View", "California")),
('27959', check_places("Nags Head", "North Carolina")),
('48067', check_places("Royal Oak", "Michigan")),
('23606', check_places("Newport News", "Virginia")),
('23113', check_places("Midlothian", "Virginia")),
('27517', check_places("Chapel Hill", "North Carolina")),
('46530', check_places("Granger", "Indiana")),
('15213', check_places("Pittsburgh", "Pennsylvania")),
('90210', check_places("Beverly Hills", "California")),
('12144', check_places("Clinton Park", "New York")),
('33109', check_places("Homestead", "Florida")),
('80201', check_places("Denver", "Colorado")),
def test_code(self): ("Berlin", check_places("Berlin", "Deutschland")),
("Paris", check_places("Paris", "European Union")),
("Vilnius", check_places("Vilnius", "European Union")),
]
for loc, validator in locations:
names, lat, lon = location(loc)
validator(names, lat, lon)
def test_code_20164(self):
icao = code(self.phenny, '20164') icao = code(self.phenny, '20164')
self.assertEqual(icao, 'KIAD') self.assertEqual(icao, 'KIAD')
def test_airport(self): def test_airport(self):

View File

@ -9,26 +9,27 @@ http://inamidst.com/phenny/
import re import re
import metar import metar
import json
import web import web
from tools import deprecated, GrumbleError from tools import deprecated, GrumbleError
r_from = re.compile(r'(?i)([+-]\d+):00 from') r_from = re.compile(r'(?i)([+-]\d+):00 from')
def location(name):
name = web.quote(name)
uri = 'http://ws.geonames.org/searchJSON?q=%s&maxRows=1' % name
for i in range(10):
bytes = web.get(uri)
if bytes is not None: break
results = web.json(bytes) def location(q):
try: name = results['geonames'][0]['name'] uri = 'http://nominatim.openstreetmap.org/search/?q={query}&format=json'.\
except IndexError: format(query=web.quote(q))
return '?', '?', '0', '0' results = web.get(uri)
countryName = results['geonames'][0]['countryName'] data = json.loads(results)
lat = results['geonames'][0]['lat']
lng = results['geonames'][0]['lng'] if not 'display_name' in data:
return name, countryName, lat, lng return '?', None, None
display_name = data[0]['display_name']
lat = float(data[0]['lat'])
lon = float(data[0]['lon'])
return display_name, lat, lon
def local(icao, hour, minute): def local(icao, hour, minute):
uri = ('http://www.flightstats.com/' + uri = ('http://www.flightstats.com/' +
@ -47,14 +48,16 @@ def local(icao, hour, minute):
# ':' + str(minute) + 'Z)') # ':' + str(minute) + 'Z)')
return str(hour) + ':' + str(minute) + 'Z' return str(hour) + ':' + str(minute) + 'Z'
def code(phenny, search): def code(phenny, search):
from icao import data from icao import data
if search.upper() in [loc[0] for loc in data]: if search.upper() in [loc[0] for loc in data]:
return search.upper() return search.upper()
else: else:
name, country, latitude, longitude = location(search) display_name, latitude, longitude = location(search)
if name == '?': return False if not latitude or not longitude:
return False
sumOfSquares = (99999999999999999999999999999, 'ICAO') sumOfSquares = (99999999999999999999999999999, 'ICAO')
for icao_code, lat, lon in data: for icao_code, lat, lon in data:
latDiff = abs(latitude - lat) latDiff = abs(latitude - lat)
@ -64,6 +67,7 @@ def code(phenny, search):
sumOfSquares = (diff, icao_code) sumOfSquares = (diff, icao_code)
return sumOfSquares[1] return sumOfSquares[1]
def f_weather(phenny, input): def f_weather(phenny, input):
""".weather <ICAO> - Show the weather at airport with the code <ICAO>.""" """.weather <ICAO> - Show the weather at airport with the code <ICAO>."""
icao_code = input.group(2) icao_code = input.group(2)