Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add argument to convert weather code to string #196

Merged
merged 1 commit into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions docs/source/getting-started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ request some data. To do this, use the `manager` object:

::

forecast = manager.get_forecast(51, 0, "hourly")
forecast = manager.get_forecast(51, 0, "hourly", convert_weather_code=True)

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

This Forecast Object which has been returned to us contains lots of information
which we will cover in a later section, right now we’re just going to get the
Expand Down
75 changes: 60 additions & 15 deletions src/datapoint/Forecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ class Forecast:

>>> import datapoint
>>> m = datapoint.Manager.Manager(api_key = "blah")
>>> f = m.get_forecast(latitude=50, longitude=0, frequency="hourly")
>>> f = m.get_forecast(
latitude=50,
longitude=0,
frequency="hourly",
convert_weather_code=True,
)
>>> f.now()
{
'time': datetime.datetime(2024, 2, 19, 13, 0, tzinfo=datetime.timezone.utc),
Expand Down Expand Up @@ -101,12 +106,14 @@ class Forecast:
}
"""

def __init__(self, frequency, api_data):
def __init__(self, frequency, api_data, convert_weather_code):
"""
:param frequency: Frequency of forecast: 'hourly', 'three-hourly' or 'daily'
:param api_data: Data returned from API call
:param: convert_weather_code: Convert numeric weather codes to string description
:type frequency: string
:type api_data: dict
:type convert_weather_code: bool
"""
self.frequency = frequency
# Need to parse format like 2024-02-17T15:00Z. This can only be
Expand Down Expand Up @@ -136,6 +143,10 @@ def __init__(self, frequency, api_data):
2
] #: The elevation of the location of the provided forecast

self.convert_weather_code = (
convert_weather_code #: Convert numeric weather codes to string description
)

forecasts = api_data["features"][0]["properties"]["timeSeries"]
parameters = api_data["parameters"][0]
if frequency == "daily":
Expand Down Expand Up @@ -203,23 +214,57 @@ def _build_timesteps_from_daily(self, forecasts, parameters):
case_corrected_element = (
trimmed_element[0].lower() + trimmed_element[1:]
)
day_step[case_corrected_element] = {
"value": value,
"description": parameters[element]["description"],
"unit_name": parameters[element]["unit"]["label"],
"unit_symbol": parameters[element]["unit"]["symbol"]["type"],
}

if (
case_corrected_element == "significantWeatherCode"
and self.convert_weather_code
):
day_step[case_corrected_element] = {
"value": WEATHER_CODES[str(value)],
"description": parameters[element]["description"],
"unit_name": parameters[element]["unit"]["label"],
"unit_symbol": parameters[element]["unit"]["symbol"][
"type"
],
}

else:
day_step[case_corrected_element] = {
"value": value,
"description": parameters[element]["description"],
"unit_name": parameters[element]["unit"]["label"],
"unit_symbol": parameters[element]["unit"]["symbol"][
"type"
],
}
elif element.startswith("night"):
trimmed_element = element.replace("night", "")
case_corrected_element = (
trimmed_element[0].lower() + trimmed_element[1:]
)
night_step[case_corrected_element] = {
"value": value,
"description": parameters[element]["description"],
"unit_name": parameters[element]["unit"]["label"],
"unit_symbol": parameters[element]["unit"]["symbol"]["type"],
}

if (
case_corrected_element == "significantWeatherCode"
and self.convert_weather_code
):
night_step[case_corrected_element] = {
"value": WEATHER_CODES[str(value)],
"description": parameters[element]["description"],
"unit_name": parameters[element]["unit"]["label"],
"unit_symbol": parameters[element]["unit"]["symbol"][
"type"
],
}

else:
night_step[case_corrected_element] = {
"value": value,
"description": parameters[element]["description"],
"unit_name": parameters[element]["unit"]["label"],
"unit_symbol": parameters[element]["unit"]["symbol"][
"type"
],
}
elif element == "maxUvIndex":
day_step[element] = {
"value": value,
Expand Down Expand Up @@ -260,7 +305,7 @@ def _build_timestep(self, forecast, parameters):
forecast["time"], "%Y-%m-%dT%H:%M%z"
)

elif element == "significantWeatherCode":
elif element == "significantWeatherCode" and self.convert_weather_code:
timestep[element] = {
"value": WEATHER_CODES[str(value)],
"description": parameters[element]["description"],
Expand Down
19 changes: 16 additions & 3 deletions src/datapoint/Manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ class Manager:

>>> import datapoint
>>> m = datapoint.Manager.Manager(api_key = "blah")
>>> f = m.get_forecast(latitude=50, longitude=0, frequency="hourly")
>>> f = m.get_forecast(
latitude=50,
longitude=0,
frequency="hourly",
convert_weather_code=True
)
>>> f.now()
{
'time': datetime.datetime(2024, 2, 19, 13, 0, tzinfo=datetime.timezone.utc),
Expand Down Expand Up @@ -201,16 +206,20 @@ def __call_api(self, latitude, longitude, frequency):

return data

def get_forecast(self, latitude, longitude, frequency="daily"):
def get_forecast(
self, latitude, longitude, frequency="daily", convert_weather_code=True
):
"""
Get a forecast for the provided site

:parameter latitude: Latitude of forecast location
:parameter longitude: Longitude of forecast location
:parameter frequency: Forecast frequency. One of 'hourly', 'three-hourly, 'daily'
:parameter convert_weather_code: Convert numeric weather codes to string description
:type latitude: float
:type longitude: float
:type frequency: string
:type convert_weather_code: bool

:return: :class: `Forecast <Forecast>` object
:rtype: datapoint.Forecast
Expand All @@ -220,6 +229,10 @@ def get_forecast(self, latitude, longitude, frequency="daily"):
"frequency must be set to one of 'hourly', 'three-hourly', 'daily'"
)
data = self.__call_api(latitude, longitude, frequency)
forecast = Forecast(frequency=frequency, api_data=data)
forecast = Forecast(
frequency=frequency,
api_data=data,
convert_weather_code=convert_weather_code,
)

return forecast
4 changes: 2 additions & 2 deletions src/datapoint/weather_codes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# See https://www.metoffice.gov.uk/services/data/datapoint/code-definitions for definitions
# See https://datahub.metoffice.gov.uk/support/faqs for definitions
WEATHER_CODES = {
"-1": "Trace rain",
"NA": "Not available",
"0": "Clear night",
"1": "Sunny day",
"2": "Partly cloudy",
Expand Down
8 changes: 5 additions & 3 deletions tests/integration/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def mock_get(*args, **kwargs):
@pytest.fixture
def hourly_forecast(mock_response_hourly):
m = Manager(api_key="aaaaaaaaaaaaaaaaaaaaaaaaa")
f = m.get_forecast(50.9992, 0.0154, frequency="hourly")
f = m.get_forecast(50.9992, 0.0154, frequency="hourly", convert_weather_code=True)
return f


Expand Down Expand Up @@ -60,7 +60,9 @@ def mock_get(*args, **kwargs):
@pytest.fixture
def three_hourly_forecast(mock_response_three_hourly):
m = Manager(api_key="aaaaaaaaaaaaaaaaaaaaaaaaa")
f = m.get_forecast(50.9992, 0.0154, frequency="three-hourly")
f = m.get_forecast(
50.9992, 0.0154, frequency="three-hourly", convert_weather_code=True
)
return f


Expand Down Expand Up @@ -92,7 +94,7 @@ def mock_get(*args, **kwargs):
@pytest.fixture
def daily_forecast(mock_response_daily):
m = Manager(api_key="aaaaaaaaaaaaaaaaaaaaaaaaa")
f = m.get_forecast(50.9992, 0.0154, frequency="daily")
f = m.get_forecast(50.9992, 0.0154, frequency="daily", convert_weather_code=True)
return f


Expand Down
Loading
Loading