2018-10-27 22:31:51 +00:00
|
|
|
#vim: fileencoding=utf-8
|
|
|
|
|
|
|
|
"""
|
|
|
|
One-line output mode.
|
|
|
|
|
|
|
|
Initial implementation of one-line output mode.
|
|
|
|
|
|
|
|
[ ] forecast
|
|
|
|
[ ] spark
|
|
|
|
[ ] several locations
|
|
|
|
[ ] location handling
|
|
|
|
[ ] more preconfigured format lines
|
|
|
|
[ ] add information about this mode to /:help
|
|
|
|
"""
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import re
|
2018-11-02 17:52:42 +00:00
|
|
|
import datetime
|
2019-01-11 09:59:17 +00:00
|
|
|
from astral import Astral, Location
|
2018-10-27 22:31:51 +00:00
|
|
|
from constants import WWO_CODE, WEATHER_SYMBOL, WIND_DIRECTION
|
|
|
|
from weather_data import get_weather_data
|
|
|
|
|
|
|
|
PRECONFIGURED_FORMAT = {
|
|
|
|
'1': u'%c %t',
|
|
|
|
'2': u'%c 🌡️%t 🌬️%w',
|
|
|
|
'3': u'%l: %c %t',
|
|
|
|
'4': u'%l: %c 🌡️%t 🌬️%w',
|
|
|
|
}
|
|
|
|
|
2018-11-02 17:52:42 +00:00
|
|
|
MOON_PHASES = (
|
|
|
|
u"🌑", u"🌒", u"🌓", u"🌔", u"🌕", u"🌖", u"🌗", u"🌘"
|
|
|
|
)
|
|
|
|
|
2019-01-11 09:59:17 +00:00
|
|
|
def convert_to_fahrenheit(temp):
|
|
|
|
"Convert Celcius `temp` to Fahrenheit"
|
|
|
|
|
|
|
|
return (temp*9.0/5)+32
|
|
|
|
|
|
|
|
def render_temperature(data, query):
|
2018-10-27 22:31:51 +00:00
|
|
|
"""
|
|
|
|
temperature (t)
|
|
|
|
"""
|
|
|
|
|
2019-01-11 09:59:17 +00:00
|
|
|
if query.get('use_imperial', False):
|
2019-02-19 19:25:52 +00:00
|
|
|
temperature = u'%s°F' % data['temp_F']
|
2019-01-11 09:59:17 +00:00
|
|
|
else:
|
2019-02-19 19:25:52 +00:00
|
|
|
temperature = u'%s°C' % data['temp_C']
|
2019-01-11 09:59:17 +00:00
|
|
|
|
2018-10-27 22:31:51 +00:00
|
|
|
if temperature[0] != '-':
|
|
|
|
temperature = '+' + temperature
|
2019-01-11 09:59:17 +00:00
|
|
|
|
2018-10-27 22:31:51 +00:00
|
|
|
return temperature
|
|
|
|
|
2019-01-11 09:59:17 +00:00
|
|
|
def render_condition(data, query):
|
2018-10-27 22:31:51 +00:00
|
|
|
"""
|
|
|
|
condition (c)
|
|
|
|
"""
|
|
|
|
|
|
|
|
weather_condition = WEATHER_SYMBOL[WWO_CODE[data['weatherCode']]]
|
|
|
|
return weather_condition
|
|
|
|
|
2019-02-19 19:25:52 +00:00
|
|
|
def render_humidity(data, query):
|
|
|
|
"""
|
|
|
|
humidity (h)
|
|
|
|
"""
|
|
|
|
|
|
|
|
humidity = data.get('humidity', '')
|
|
|
|
if humidity:
|
|
|
|
humidity += '%'
|
|
|
|
return humidity
|
|
|
|
|
2019-01-11 09:59:17 +00:00
|
|
|
def render_wind(data, query):
|
2018-10-27 22:31:51 +00:00
|
|
|
"""
|
|
|
|
wind (w)
|
|
|
|
"""
|
|
|
|
|
|
|
|
try:
|
|
|
|
degree = data["winddirDegree"]
|
|
|
|
except KeyError:
|
|
|
|
degree = ""
|
|
|
|
|
|
|
|
try:
|
|
|
|
degree = int(degree)
|
|
|
|
except ValueError:
|
|
|
|
degree = ""
|
|
|
|
|
|
|
|
if degree:
|
|
|
|
wind_direction = WIND_DIRECTION[((degree+22)%360)/45]
|
|
|
|
else:
|
|
|
|
wind_direction = ""
|
|
|
|
|
2019-03-15 19:20:05 +00:00
|
|
|
if query.get('use_ms_for_wind', False):
|
|
|
|
unit = ' m/s'
|
|
|
|
wind = u'%s%.1f%s' % (wind_direction, float(data['windspeedKmph'])/36.0*10.0, unit)
|
|
|
|
elif query.get('use_imperial', False):
|
2019-01-11 09:59:17 +00:00
|
|
|
unit = ' mph'
|
|
|
|
wind = u'%s%s%s' % (wind_direction, data['windspeedMiles'], unit)
|
|
|
|
else:
|
|
|
|
unit = ' km/h'
|
|
|
|
wind = u'%s%s%s' % (wind_direction, data['windspeedKmph'], unit)
|
|
|
|
|
2018-10-27 22:31:51 +00:00
|
|
|
return wind
|
|
|
|
|
2019-01-11 09:59:17 +00:00
|
|
|
def render_location(data, query):
|
2018-10-27 22:31:51 +00:00
|
|
|
"""
|
|
|
|
location (l)
|
|
|
|
"""
|
|
|
|
|
2019-02-01 22:32:17 +00:00
|
|
|
return (data['override_location'] or data['location']) # .title()
|
2018-10-27 22:31:51 +00:00
|
|
|
|
2019-01-11 09:59:17 +00:00
|
|
|
def render_moonphase(_, query):
|
2018-11-02 17:52:42 +00:00
|
|
|
"""
|
|
|
|
A symbol describing the phase of the moon
|
|
|
|
"""
|
|
|
|
astral = Astral()
|
|
|
|
moon_index = int(
|
|
|
|
int(32.0*astral.moon_phase(date=datetime.datetime.today())/28+2)%32/4
|
|
|
|
)
|
|
|
|
return MOON_PHASES[moon_index]
|
|
|
|
|
2019-01-11 09:59:17 +00:00
|
|
|
def render_moonday(_, query):
|
2018-11-02 17:52:42 +00:00
|
|
|
"""
|
|
|
|
An number describing the phase of the moon (days after the New Moon)
|
|
|
|
"""
|
|
|
|
astral = Astral()
|
|
|
|
return str(int(astral.moon_phase(date=datetime.datetime.today())))
|
|
|
|
|
2019-01-11 09:59:17 +00:00
|
|
|
def render_sunset(data, query):
|
|
|
|
location = data['location']
|
|
|
|
city_name = location
|
|
|
|
astral = Astral()
|
|
|
|
location = Location(('Nuremberg', 'Germany',
|
|
|
|
49.453872, 11.077298, 'Europe/Berlin', 0))
|
|
|
|
sun = location.sun(date=datetime.datetime.today(), local=True)
|
|
|
|
|
|
|
|
|
|
|
|
return str(sun['sunset'])
|
|
|
|
|
2018-10-27 22:31:51 +00:00
|
|
|
FORMAT_SYMBOL = {
|
|
|
|
'c': render_condition,
|
2019-02-19 19:25:52 +00:00
|
|
|
'h': render_humidity,
|
2018-10-27 22:31:51 +00:00
|
|
|
't': render_temperature,
|
|
|
|
'w': render_wind,
|
|
|
|
'l': render_location,
|
2018-11-02 17:52:42 +00:00
|
|
|
'm': render_moonphase,
|
|
|
|
'M': render_moonday,
|
2019-01-11 09:59:17 +00:00
|
|
|
's': render_sunset,
|
2018-10-27 22:31:51 +00:00
|
|
|
}
|
|
|
|
|
2019-01-11 09:59:17 +00:00
|
|
|
def render_line(line, data, query):
|
2018-10-27 22:31:51 +00:00
|
|
|
"""
|
|
|
|
Render format `line` using `data`
|
|
|
|
"""
|
|
|
|
|
|
|
|
def render_symbol(match):
|
|
|
|
"""
|
|
|
|
Render one format symbol from re `match`
|
|
|
|
using `data` from external scope.
|
|
|
|
"""
|
|
|
|
|
|
|
|
symbol_string = match.group(0)
|
|
|
|
symbol = symbol_string[-1]
|
|
|
|
|
|
|
|
if symbol not in FORMAT_SYMBOL:
|
|
|
|
return ''
|
|
|
|
|
|
|
|
render_function = FORMAT_SYMBOL[symbol]
|
2019-01-11 09:59:17 +00:00
|
|
|
return render_function(data, query)
|
2018-10-27 22:31:51 +00:00
|
|
|
|
2018-11-02 17:52:42 +00:00
|
|
|
return re.sub(r'%[^%]*[a-zA-Z]', render_symbol, line)
|
2018-10-27 22:31:51 +00:00
|
|
|
|
2019-02-01 22:32:17 +00:00
|
|
|
def format_weather_data(format_line, location, override_location, data, query):
|
2018-10-27 22:31:51 +00:00
|
|
|
"""
|
|
|
|
Format information about current weather `data` for `location`
|
|
|
|
with specified in `format_line` format
|
|
|
|
"""
|
|
|
|
|
2019-03-15 19:20:36 +00:00
|
|
|
if 'data' not in data:
|
|
|
|
return 'Unknow location; please try ~%s' % location
|
2018-10-27 22:31:51 +00:00
|
|
|
current_condition = data['data']['current_condition'][0]
|
|
|
|
current_condition['location'] = location
|
2019-02-01 22:32:17 +00:00
|
|
|
current_condition['override_location'] = override_location
|
2019-01-11 09:59:17 +00:00
|
|
|
output = render_line(format_line, current_condition, query)
|
2018-10-27 22:31:51 +00:00
|
|
|
return output
|
|
|
|
|
2019-02-01 22:32:17 +00:00
|
|
|
def wttr_line(location, override_location_name, query):
|
2018-10-27 22:31:51 +00:00
|
|
|
"""
|
|
|
|
Return 1line weather information for `location`
|
|
|
|
in format `line_format`
|
|
|
|
"""
|
|
|
|
|
2018-10-28 14:41:39 +00:00
|
|
|
format_line = query.get('format', '')
|
2018-10-27 22:31:51 +00:00
|
|
|
|
|
|
|
if format_line in PRECONFIGURED_FORMAT:
|
|
|
|
format_line = PRECONFIGURED_FORMAT[format_line]
|
|
|
|
|
|
|
|
weather_data = get_weather_data(location)
|
|
|
|
|
2019-02-01 22:32:17 +00:00
|
|
|
output = format_weather_data(format_line, location, override_location_name, weather_data, query)
|
2018-10-27 22:31:51 +00:00
|
|
|
output = output.rstrip("\n")+"\n"
|
|
|
|
return output
|
|
|
|
|
|
|
|
def main():
|
|
|
|
"""
|
|
|
|
Function for standalone module usage
|
|
|
|
"""
|
|
|
|
|
|
|
|
location = sys.argv[1]
|
|
|
|
query = {
|
|
|
|
'line': sys.argv[2],
|
|
|
|
}
|
|
|
|
|
2019-02-01 22:32:17 +00:00
|
|
|
sys.stdout.write(wttr_line(location, location, query))
|
2018-10-27 22:31:51 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|