Skip to content

Commit

Permalink
Implementation of #188 (wind speed units specification) (#189)
Browse files Browse the repository at this point in the history
  • Loading branch information
csparpa committed May 18, 2017
1 parent 93e2b8b commit 57f11ca
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 7 deletions.
27 changes: 26 additions & 1 deletion pyowm/utils/temputils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
"""
Module containing utility functions for temperature units conversion
Module containing utility functions for temperature and wind units conversion
"""

# Temperature coneversion constants
KELVIN_OFFSET = 273.15
FAHRENHEIT_OFFSET = 32.0
FAHRENHEIT_DEGREE_SCALE = 1.8

# Wind speed conversion constants
MILES_PER_HOUR_FOR_ONE_METER_PER_SEC = 2.23694


def kelvin_dict_to(d, target_temperature_unit):
"""
Expand Down Expand Up @@ -66,3 +70,24 @@ def kelvin_to_fahrenheit(kelvintemp):
fahrenheittemp = (kelvintemp - KELVIN_OFFSET) * \
FAHRENHEIT_DEGREE_SCALE + FAHRENHEIT_OFFSET
return float("{0:.2f}".format(fahrenheittemp))


def metric_wind_dict_to_imperial(d):
"""
Converts all the wind values in a dict from meters/sec (metric measurement
system) to miles/hour (imperial measurement system)
.
:param d: the dictionary containing metric values
:type d: dict
:returns: a dict with the same keys as the input dict and values converted
to miles/hour
"""
result = dict()
for key, value in d.items():
if key != 'deg': # do not convert wind degree
result[key] = value * MILES_PER_HOUR_FOR_ONE_METER_PER_SEC
else:
result[key] = value
return result
15 changes: 12 additions & 3 deletions pyowm/webapi25/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,22 @@ def get_snow(self):
"""
return self._snow

def get_wind(self):
def get_wind(self, unit='meters_sec'):
"""Returns a dict containing wind info
:param unit: the unit of measure for the wind values. May be:
'*meters_sec*' (default) or '*miles_hour*'
:type unit: str
:returns: a dict containing wind info
"""
return self._wind
if unit == 'meters_sec':
return self._wind
elif unit == 'miles_hour':
wind_dict = {k: self._wind[k] for k in self._wind if self._wind[k] is not None}
return temputils.metric_wind_dict_to_imperial(wind_dict)
else:
raise ValueError("Invalid value for target wind conversion unit")

def get_humidity(self):
"""Returns the atmospheric humidity as an int
Expand Down
14 changes: 14 additions & 0 deletions tests/unit/utils/test_temputils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,17 @@ def test_kelvin_to_fahrenheit(self):

def test_kelvin_to_fahrenheit_fails_with_negative_values(self):
self.assertRaises(ValueError, temputils.kelvin_to_fahrenheit, -137.0)

def test_metric_wind_dict_to_imperial(self):
input = {
'speed': 2,
'gust': 3,
'deg': 7.89
}
expected = {
'speed': 4.47388,
'gust': 6.71082,
'deg': 7.89
}
result = temputils.metric_wind_dict_to_imperial(input)
self.assertEqual(expected, result)
2 changes: 1 addition & 1 deletion tests/unit/webapi25/json_test_dumps.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
'{"press": 1030.119, "sea_level": 1038.589}, ' \
'"sunrise_time": 1378449600, "heat_index": 40.0, ' \
'"weather_icon_name": "04d", "humidity": 57, "wind": ' \
'{"speed": 1.1, "deg": 252.002}}'
'{"speed": 1.1, "deg": 252.002, "gust": 2.09}}'

OBSERVATION_JSON_DUMP = '{"reception_time": 1234567, "Location": ' \
'{"country": "UK", "name": "test", "coordinates": ' \
Expand Down
19 changes: 18 additions & 1 deletion tests/unit/webapi25/test_weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from pyowm.webapi25.weather import Weather, weather_from_dictionary
from pyowm.utils.timeformatutils import UTC
from tests.unit.webapi25.json_test_dumps import WEATHER_JSON_DUMP
from tests.unit.webapi25.xml_test_dumps import WEATHER_XML_DUMP
from datetime import datetime


Expand All @@ -22,7 +23,8 @@ class TestWeather(unittest.TestCase):
__test_clouds = 67
__test_rain = {"all": 20}
__test_snow = {"all": 0}
__test_wind = {"deg": 252.002, "speed": 1.100}
__test_wind = {"deg": 252.002, "speed": 1.100, "gust": 2.09}
__test_imperial_wind = {"deg": 252.002, "speed": 2.460634, "gust": 4.6752046}
__test_humidity = 57
__test_pressure = {"press": 1030.119, "sea_level": 1038.589}
__test_temperature = {"temp": 294.199, "temp_kf": -1.899,
Expand Down Expand Up @@ -380,6 +382,21 @@ def test_get_temperature_fails_with_unknown_units(self):
self.assertRaises(ValueError, Weather.get_temperature,
self.__test_instance, 'xyz')

def test_returning_different_units_for_wind_values(self):
result_imperial = self.__test_instance.get_wind(unit='miles_hour')
result_metric = self.__test_instance.get_wind(unit='meters_sec')
result_unspecified = self.__test_instance.get_wind()
self.assertEqual(result_unspecified, result_metric)
for item in self.__test_wind:
self.assertEqual(result_metric[item],
self.__test_wind[item])
self.assertEqual(result_imperial[item],
self.__test_imperial_wind[item])

def test_get_wind_fails_with_unknown_units(self):
self.assertRaises(ValueError, Weather.get_wind,
self.__test_instance, 'xyz')

# Test JSON and XML comparisons by ordering strings (this overcomes
# interpeter-dependant serialization of XML/JSON objects)

Expand Down
2 changes: 1 addition & 1 deletion tests/unit/webapi25/xml_test_dumps.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<location xmlns:l="http://github.com/csparpa/pyowm/tree/master/pyowm/webapi25/xsd/location.xsd"><l:name>London</l:name><l:coordinates><l:lon>12.3</l:lon><l:lat>43.7</l:lat></l:coordinates><l:ID>1234</l:ID><l:country>UK</l:country></location>"""

WEATHER_XML_DUMP = """<?xml version='1.0' encoding='utf8'?>
<weather xmlns:w="http://github.com/csparpa/pyowm/tree/master/pyowm/webapi25/xsd/weather.xsd"><w:status>Clouds</w:status><w:weather_code>804</w:weather_code><w:rain><w:all>20</w:all></w:rain><w:snow><w:all>0</w:all></w:snow><w:pressure><w:press>1030.119</w:press><w:sea_level>1038.589</w:sea_level></w:pressure><w:sunrise_time>1378449600</w:sunrise_time><w:weather_icon_name>04d</w:weather_icon_name><w:clouds>67</w:clouds><w:temperature><w:temp_kf>-1.899</w:temp_kf><w:temp_min>294.199</w:temp_min><w:temp>294.199</w:temp><w:temp_max>296.098</w:temp_max></w:temperature><w:detailed_status>Overcast clouds</w:detailed_status><w:reference_time>1378459200</w:reference_time><w:sunset_time>1378496400</w:sunset_time><w:humidity>57</w:humidity><w:wind><w:speed>1.1</w:speed><w:deg>252.002</w:deg></w:wind><w:visibility_distance>1000</w:visibility_distance><w:dewpoint>300.0</w:dewpoint><w:humidex>298.0</w:humidex><w:heat_index>40.0</w:heat_index></weather>"""
<weather xmlns:w="http://github.com/csparpa/pyowm/tree/master/pyowm/webapi25/xsd/weather.xsd"><w:status>Clouds</w:status><w:weather_code>804</w:weather_code><w:rain><w:all>20</w:all></w:rain><w:snow><w:all>0</w:all></w:snow><w:pressure><w:press>1030.119</w:press><w:sea_level>1038.589</w:sea_level></w:pressure><w:sunrise_time>1378449600</w:sunrise_time><w:weather_icon_name>04d</w:weather_icon_name><w:clouds>67</w:clouds><w:temperature><w:temp_kf>-1.899</w:temp_kf><w:temp_min>294.199</w:temp_min><w:temp>294.199</w:temp><w:temp_max>296.098</w:temp_max></w:temperature><w:detailed_status>Overcast clouds</w:detailed_status><w:reference_time>1378459200</w:reference_time><w:sunset_time>1378496400</w:sunset_time><w:humidity>57</w:humidity><w:wind><w:speed>1.1</w:speed><w:deg>252.002</w:deg><w:gust>2.09</w:gust></w:wind><w:visibility_distance>1000</w:visibility_distance><w:dewpoint>300.0</w:dewpoint><w:humidex>298.0</w:humidex><w:heat_index>40.0</w:heat_index></weather>"""

OBSERVATION_XML_DUMP = """<?xml version='1.0' encoding='utf8'?>
<observation xmlns:o="http://github.com/csparpa/pyowm/tree/master/pyowm/webapi25/xsd/observation.xsd"><o:reception_time>1234567</o:reception_time><o:location><o:name>test</o:name><o:coordinates><o:lon>12.3</o:lon><o:lat>43.7</o:lat></o:coordinates><o:ID>987</o:ID><o:country>UK</o:country></o:location><o:weather><o:status>Clouds</o:status><o:weather_code>804</o:weather_code><o:rain><o:all>20</o:all></o:rain><o:snow><o:all>0</o:all></o:snow><o:pressure><o:press>1030.119</o:press><o:sea_level>1038.589</o:sea_level></o:pressure><o:sunrise_time>1378449600</o:sunrise_time><o:weather_icon_name>04d</o:weather_icon_name><o:clouds>67</o:clouds><o:temperature><o:temp_kf>-1.899</o:temp_kf><o:temp_min>294.199</o:temp_min><o:temp>294.199</o:temp><o:temp_max>296.098</o:temp_max></o:temperature><o:detailed_status>Overcast clouds</o:detailed_status><o:reference_time>1378459200</o:reference_time><o:sunset_time>1378496400</o:sunset_time><o:humidity>57</o:humidity><o:wind><o:speed>1.1</o:speed><o:deg>252.002</o:deg></o:wind><o:visibility_distance>1000</o:visibility_distance><o:dewpoint>300.0</o:dewpoint><o:humidex>298.0</o:humidex><o:heat_index>296.0</o:heat_index></o:weather></observation>"""
Expand Down

0 comments on commit 57f11ca

Please sign in to comment.