Skip to content

Commit 76d627a

Browse files
Add argument to convert weather code to string
1 parent 5a548db commit 76d627a

File tree

7 files changed

+371
-32
lines changed

7 files changed

+371
-32
lines changed

docs/source/getting-started.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,12 @@ request some data. To do this, use the `manager` object:
3838

3939
::
4040

41-
forecast = manager.get_forecast(51, 0, "hourly")
41+
forecast = manager.get_forecast(51, 0, "hourly", convert_weather_code=True)
4242

43-
This takes three parameters: the latitude and longitude of the location you want
44-
a forecast for and also a forecast type of “hourly”. We’ll discuss the forecast
45-
types later on.
43+
This takes four parameters: the latitude and longitude of the location you want
44+
a forecast for, a forecast type of “hourly” and an instruction to convert the
45+
numeric weather code to a string description. We’ll discuss the forecast types
46+
later on.
4647

4748
This Forecast Object which has been returned to us contains lots of information
4849
which we will cover in a later section, right now we’re just going to get the

src/datapoint/Forecast.py

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ class Forecast:
1616
1717
>>> import datapoint
1818
>>> m = datapoint.Manager.Manager(api_key = "blah")
19-
>>> f = m.get_forecast(latitude=50, longitude=0, frequency="hourly")
19+
>>> f = m.get_forecast(
20+
latitude=50,
21+
longitude=0,
22+
frequency="hourly",
23+
convert_weather_code=True,
24+
)
2025
>>> f.now()
2126
{
2227
'time': datetime.datetime(2024, 2, 19, 13, 0, tzinfo=datetime.timezone.utc),
@@ -101,12 +106,14 @@ class Forecast:
101106
}
102107
"""
103108

104-
def __init__(self, frequency, api_data):
109+
def __init__(self, frequency, api_data, convert_weather_code):
105110
"""
106111
:param frequency: Frequency of forecast: 'hourly', 'three-hourly' or 'daily'
107112
:param api_data: Data returned from API call
113+
:param: convert_weather_code: Convert numeric weather codes to string description
108114
:type frequency: string
109115
:type api_data: dict
116+
:type convert_weather_code: bool
110117
"""
111118
self.frequency = frequency
112119
# Need to parse format like 2024-02-17T15:00Z. This can only be
@@ -136,6 +143,10 @@ def __init__(self, frequency, api_data):
136143
2
137144
] #: The elevation of the location of the provided forecast
138145

146+
self.convert_weather_code = (
147+
convert_weather_code #: Convert numeric weather codes to string description
148+
)
149+
139150
forecasts = api_data["features"][0]["properties"]["timeSeries"]
140151
parameters = api_data["parameters"][0]
141152
if frequency == "daily":
@@ -203,23 +214,57 @@ def _build_timesteps_from_daily(self, forecasts, parameters):
203214
case_corrected_element = (
204215
trimmed_element[0].lower() + trimmed_element[1:]
205216
)
206-
day_step[case_corrected_element] = {
207-
"value": value,
208-
"description": parameters[element]["description"],
209-
"unit_name": parameters[element]["unit"]["label"],
210-
"unit_symbol": parameters[element]["unit"]["symbol"]["type"],
211-
}
217+
218+
if (
219+
case_corrected_element == "significantWeatherCode"
220+
and self.convert_weather_code
221+
):
222+
day_step[case_corrected_element] = {
223+
"value": WEATHER_CODES[str(value)],
224+
"description": parameters[element]["description"],
225+
"unit_name": parameters[element]["unit"]["label"],
226+
"unit_symbol": parameters[element]["unit"]["symbol"][
227+
"type"
228+
],
229+
}
230+
231+
else:
232+
day_step[case_corrected_element] = {
233+
"value": value,
234+
"description": parameters[element]["description"],
235+
"unit_name": parameters[element]["unit"]["label"],
236+
"unit_symbol": parameters[element]["unit"]["symbol"][
237+
"type"
238+
],
239+
}
212240
elif element.startswith("night"):
213241
trimmed_element = element.replace("night", "")
214242
case_corrected_element = (
215243
trimmed_element[0].lower() + trimmed_element[1:]
216244
)
217-
night_step[case_corrected_element] = {
218-
"value": value,
219-
"description": parameters[element]["description"],
220-
"unit_name": parameters[element]["unit"]["label"],
221-
"unit_symbol": parameters[element]["unit"]["symbol"]["type"],
222-
}
245+
246+
if (
247+
case_corrected_element == "significantWeatherCode"
248+
and self.convert_weather_code
249+
):
250+
night_step[case_corrected_element] = {
251+
"value": WEATHER_CODES[str(value)],
252+
"description": parameters[element]["description"],
253+
"unit_name": parameters[element]["unit"]["label"],
254+
"unit_symbol": parameters[element]["unit"]["symbol"][
255+
"type"
256+
],
257+
}
258+
259+
else:
260+
night_step[case_corrected_element] = {
261+
"value": value,
262+
"description": parameters[element]["description"],
263+
"unit_name": parameters[element]["unit"]["label"],
264+
"unit_symbol": parameters[element]["unit"]["symbol"][
265+
"type"
266+
],
267+
}
223268
elif element == "maxUvIndex":
224269
day_step[element] = {
225270
"value": value,
@@ -260,7 +305,7 @@ def _build_timestep(self, forecast, parameters):
260305
forecast["time"], "%Y-%m-%dT%H:%M%z"
261306
)
262307

263-
elif element == "significantWeatherCode":
308+
elif element == "significantWeatherCode" and self.convert_weather_code:
264309
timestep[element] = {
265310
"value": WEATHER_CODES[str(value)],
266311
"description": parameters[element]["description"],

src/datapoint/Manager.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ class Manager:
1818
1919
>>> import datapoint
2020
>>> m = datapoint.Manager.Manager(api_key = "blah")
21-
>>> f = m.get_forecast(latitude=50, longitude=0, frequency="hourly")
21+
>>> f = m.get_forecast(
22+
latitude=50,
23+
longitude=0,
24+
frequency="hourly",
25+
convert_weather_code=True
26+
)
2227
>>> f.now()
2328
{
2429
'time': datetime.datetime(2024, 2, 19, 13, 0, tzinfo=datetime.timezone.utc),
@@ -201,16 +206,20 @@ def __call_api(self, latitude, longitude, frequency):
201206

202207
return data
203208

204-
def get_forecast(self, latitude, longitude, frequency="daily"):
209+
def get_forecast(
210+
self, latitude, longitude, frequency="daily", convert_weather_code=True
211+
):
205212
"""
206213
Get a forecast for the provided site
207214
208215
:parameter latitude: Latitude of forecast location
209216
:parameter longitude: Longitude of forecast location
210217
:parameter frequency: Forecast frequency. One of 'hourly', 'three-hourly, 'daily'
218+
:parameter convert_weather_code: Convert numeric weather codes to string description
211219
:type latitude: float
212220
:type longitude: float
213221
:type frequency: string
222+
:type convert_weather_code: bool
214223
215224
:return: :class: `Forecast <Forecast>` object
216225
:rtype: datapoint.Forecast
@@ -220,6 +229,10 @@ def get_forecast(self, latitude, longitude, frequency="daily"):
220229
"frequency must be set to one of 'hourly', 'three-hourly', 'daily'"
221230
)
222231
data = self.__call_api(latitude, longitude, frequency)
223-
forecast = Forecast(frequency=frequency, api_data=data)
232+
forecast = Forecast(
233+
frequency=frequency,
234+
api_data=data,
235+
convert_weather_code=convert_weather_code,
236+
)
224237

225238
return forecast

src/datapoint/weather_codes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# See https://www.metoffice.gov.uk/services/data/datapoint/code-definitions for definitions
1+
# See https://datahub.metoffice.gov.uk/support/faqs for definitions
22
WEATHER_CODES = {
3-
"-1": "Trace rain",
3+
"NA": "Not available",
44
"0": "Clear night",
55
"1": "Sunny day",
66
"2": "Partly cloudy",

tests/integration/test_manager.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def mock_get(*args, **kwargs):
2828
@pytest.fixture
2929
def hourly_forecast(mock_response_hourly):
3030
m = Manager(api_key="aaaaaaaaaaaaaaaaaaaaaaaaa")
31-
f = m.get_forecast(50.9992, 0.0154, frequency="hourly")
31+
f = m.get_forecast(50.9992, 0.0154, frequency="hourly", convert_weather_code=True)
3232
return f
3333

3434

@@ -60,7 +60,9 @@ def mock_get(*args, **kwargs):
6060
@pytest.fixture
6161
def three_hourly_forecast(mock_response_three_hourly):
6262
m = Manager(api_key="aaaaaaaaaaaaaaaaaaaaaaaaa")
63-
f = m.get_forecast(50.9992, 0.0154, frequency="three-hourly")
63+
f = m.get_forecast(
64+
50.9992, 0.0154, frequency="three-hourly", convert_weather_code=True
65+
)
6466
return f
6567

6668

@@ -92,7 +94,7 @@ def mock_get(*args, **kwargs):
9294
@pytest.fixture
9395
def daily_forecast(mock_response_daily):
9496
m = Manager(api_key="aaaaaaaaaaaaaaaaaaaaaaaaa")
95-
f = m.get_forecast(50.9992, 0.0154, frequency="daily")
97+
f = m.get_forecast(50.9992, 0.0154, frequency="daily", convert_weather_code=True)
9698
return f
9799

98100

0 commit comments

Comments
 (0)