-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathforecast.py
114 lines (100 loc) · 4.01 KB
/
forecast.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import re
import aviation_weather
from aviation_weather import exceptions
class Forecast(object):
"""The Forecast class represents a weather forecast.
Attributes:
type (MessageType): The type of forecast (e.g. 'TAF' or 'TAF AMD').
location (Location): The location associated with the forecast.
time (Time): The issuance time of the forecast.
valid_period (str): The time period for which the forecast is valid.
wind (Wind): The forecast winds.
visibility (Visibility): The forecast prevailing visibility.
weather_groups (tuple(WeatherGroup)): The forecast weather groups.
sky_conditions (tuple(SkyConditions)): The forecast sky conditions.
wind_shear (WindShear): The forecast wind shear.
changes (list(ChangeGroup)): A list of the change groups (BECMG, FM, PROB, or TEMPO).
"""
def __init__(self, raw):
parts = re.split(r"\s(?=(?:BECMG|FM\d{6}|PROB\d{2}|TEMPO)\s)", raw) # separate the major parts
try:
self._parse(raw, parts)
except (exceptions.ComponentDecodeError, IndexError) as e:
raise exceptions.ForecastDecodeError("Forecast(%r) could not be parsed" % raw) from e
def _parse(self, raw, parts):
part = parts[0]
t = re.match(r"TAF(?: AMD)?\s+", raw)
if t is None:
self.type = None
r = part.split()
else:
tg = t.group()
self.type = aviation_weather.MessageType(tg.rstrip())
r = part.lstrip(tg).split()
self.location = aviation_weather.Location(r[0])
self.time = aviation_weather.Time(r[1])
self.valid_period = tuple(aviation_weather.Time("%s00Z" % period) for period in r[2].split("/"))
self.wind = aviation_weather.Wind(r[3])
self.visibility = aviation_weather.Visibility(r[4])
# Weather groups
t = list()
i = 5
try:
while True:
t.append(aviation_weather.WeatherGroup(r[i]))
i += 1
except (exceptions.WeatherGroupDecodeError, IndexError):
r = r[i:]
self.weather_groups = tuple(t)
# Sky conditions
t = list()
i = 0
try:
while True:
t.append(aviation_weather.SkyCondition(r[i]))
i += 1
except (exceptions.SkyConditionDecodeError, IndexError):
r = r[i:]
self.sky_conditions = tuple(t)
if r:
self.wind_shear = aviation_weather.WindShear(r[0])
else:
self.wind_shear = None
# Changes
self.changes = list()
for part in parts[1:]:
if part.startswith("BECMG"):
p = aviation_weather.BecomingGroup(part)
elif part.startswith("FM"):
p = aviation_weather.FromGroup(part)
elif part.startswith("PROB"):
p = aviation_weather.ProbabilityGroup(part)
elif part.startswith("TEMPO"):
p = aviation_weather.TemporaryGroup(part)
else:
p = None
if p:
self.changes.append(p)
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.raw)
def __str__(self):
return self.raw # TODO: change to self.decoded (if and when it is implemented)
@property
def raw(self):
raw = ""
if self.type:
raw += " %s" % self.type.raw
raw += " %s" % self.location.raw
raw += " %s" % self.time.raw
raw += " %s/%s" % (self.valid_period[0].raw[:-3], self.valid_period[1].raw[:-3])
raw += " %s" % self.wind.raw
raw += " %s" % self.visibility.raw
for weather_group in self.weather_groups:
raw += " %s" % weather_group.raw
for sky_condition in self.sky_conditions:
raw += " %s" % sky_condition.raw
if self.wind_shear:
raw += " %s" % self.wind_shear.raw
for change in self.changes:
raw += " %s" % change.raw
return raw[1:]