simple-dwd-weatherforecast 2.0.31__tar.gz → 2.0.32__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. {simple_dwd_weatherforecast-2.0.31/simple_dwd_weatherforecast.egg-info → simple_dwd_weatherforecast-2.0.32}/PKG-INFO +3 -1
  2. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/README.md +2 -0
  3. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/setup.py +1 -1
  4. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/simple_dwd_weatherforecast/dwdforecast.py +19 -14
  5. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/simple_dwd_weatherforecast/dwdmap.py +47 -8
  6. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32/simple_dwd_weatherforecast.egg-info}/PKG-INFO +3 -1
  7. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/simple_dwd_weatherforecast.egg-info/SOURCES.txt +1 -0
  8. simple_dwd_weatherforecast-2.0.32/tests/test_get_daily_avg.py +48 -0
  9. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_daily_sum.py +2 -2
  10. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_day_values.py +20 -0
  11. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/LICENCE +0 -0
  12. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/setup.cfg +0 -0
  13. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/simple_dwd_weatherforecast/__init__.py +0 -0
  14. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/simple_dwd_weatherforecast/stations.json +0 -0
  15. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/simple_dwd_weatherforecast/uv_stations.json +0 -0
  16. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/simple_dwd_weatherforecast.egg-info/dependency_links.txt +0 -0
  17. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/simple_dwd_weatherforecast.egg-info/requires.txt +0 -0
  18. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/simple_dwd_weatherforecast.egg-info/top_level.txt +0 -0
  19. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/__init__.py +0 -0
  20. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/dummy_data.py +0 -0
  21. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/dummy_data_full.py +0 -0
  22. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/dummy_uv.py +0 -0
  23. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_daily_condition.py +0 -0
  24. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_daily_max.py +0 -0
  25. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_daily_min.py +0 -0
  26. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_forecast_condition.py +0 -0
  27. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_forecast_data.py +0 -0
  28. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_station_name.py +0 -0
  29. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_timeframe_avg.py +0 -0
  30. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_timeframe_condition.py +0 -0
  31. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_timeframe_max.py +0 -0
  32. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_timeframe_min.py +0 -0
  33. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_timeframe_sum.py +0 -0
  34. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_get_timeframe_values.py +0 -0
  35. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_is_in_timerange.py +0 -0
  36. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_is_valid_timeframe.py +0 -0
  37. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_location_tools.py +0 -0
  38. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_map.py +0 -0
  39. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_parsekml.py +0 -0
  40. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_region.py +0 -0
  41. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_reported_weather.py +0 -0
  42. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_station.py +0 -0
  43. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_stationsfile.py +0 -0
  44. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_update.py +0 -0
  45. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_update_hourly.py +0 -0
  46. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_uv_index.py +0 -0
  47. {simple_dwd_weatherforecast-2.0.31 → simple_dwd_weatherforecast-2.0.32}/tests/test_weather.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: simple_dwd_weatherforecast
3
- Version: 2.0.31
3
+ Version: 2.0.32
4
4
  Summary: A simple tool to retrieve a weather forecast from DWD OpenData
5
5
  Home-page: https://github.com/FL550/simple_dwd_weatherforecast.git
6
6
  Author: Max Fermor
@@ -127,6 +127,8 @@ class Weather:
127
127
 
128
128
  get_timeframe_sum(weatherDataType: see WeatherDataType, datetime, timeframe: hours after datetime as int, optional bool shouldUpdate) # Returns the sum of that value within the time frame
129
129
 
130
+ get_daily_avg(weatherDataType: see WeatherDataType, datetime, optional bool shouldUpdate) # Returns the daily average of that value
131
+
130
132
  get_timeframe_avg(weatherDataType: see WeatherDataType, datetime, timeframe: hours after datetime as int, optional bool shouldUpdate) # Returns the average of that value within the time frame
131
133
 
132
134
  get_forecast_condition(datetime, optional bool shouldUpdate) # Result is condition as text
@@ -110,6 +110,8 @@ class Weather:
110
110
 
111
111
  get_timeframe_sum(weatherDataType: see WeatherDataType, datetime, timeframe: hours after datetime as int, optional bool shouldUpdate) # Returns the sum of that value within the time frame
112
112
 
113
+ get_daily_avg(weatherDataType: see WeatherDataType, datetime, optional bool shouldUpdate) # Returns the daily average of that value
114
+
113
115
  get_timeframe_avg(weatherDataType: see WeatherDataType, datetime, timeframe: hours after datetime as int, optional bool shouldUpdate) # Returns the average of that value within the time frame
114
116
 
115
117
  get_forecast_condition(datetime, optional bool shouldUpdate) # Result is condition as text
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="simple_dwd_weatherforecast",
8
- version="2.0.31",
8
+ version="2.0.32",
9
9
  author="Max Fermor",
10
10
  description="A simple tool to retrieve a weather forecast from DWD OpenData",
11
11
  long_description=long_description,
@@ -546,6 +546,15 @@ class Weather:
546
546
  )
547
547
  return None
548
548
 
549
+ def get_daily_avg(
550
+ self, weatherDataType: WeatherDataType, timestamp: datetime, shouldUpdate=True
551
+ ):
552
+ if shouldUpdate:
553
+ self.update()
554
+ if self.is_in_timerange(timestamp):
555
+ return self.get_avg(self.get_day_values(timestamp), weatherDataType)
556
+ return None
557
+
549
558
  def get_avg(_, weather_data, weatherDataType):
550
559
  value_sum = 0.0
551
560
  count = len(weather_data)
@@ -586,20 +595,16 @@ class Weather:
586
595
  time_step += timedelta(hours=1)
587
596
  else:
588
597
  time_step = first_entry_date
589
- endtime = (
590
- datetime(
591
- time_step.year,
592
- time_step.month,
593
- time_step.day,
594
- 0,
595
- 0,
596
- 0,
597
- 0,
598
- timezone.utc,
599
- )
600
- + timedelta(days=1)
601
- + timedelta(hours=-1)
602
- )
598
+ endtime = datetime(
599
+ time_step.year,
600
+ time_step.month,
601
+ time_step.day,
602
+ 0,
603
+ 0,
604
+ 0,
605
+ 0,
606
+ timezone.utc,
607
+ ) + timedelta(days=1)
603
608
  timediff = endtime - time_step
604
609
  for _ in range(round(timediff.total_seconds() / 3600)):
605
610
  result.append(self.forecast_data[self.strip_to_hour_str(time_step)])
@@ -15,6 +15,7 @@ class WeatherMapType(Enum):
15
15
  WARNUNGEN_GEMEINDEN = "dwd:Warnungen_Gemeinden"
16
16
  WARNUNGEN_KREISE = "dwd:Warnungen_Landkreise"
17
17
 
18
+
18
19
  class WeatherBackgroundMapType(Enum):
19
20
  LAENDER = "dwd:Laender"
20
21
  BUNDESLAENDER = "dwd:Warngebiete_Bundeslaender"
@@ -23,7 +24,16 @@ class WeatherBackgroundMapType(Enum):
23
24
  SATELLIT = "dwd:bluemarble"
24
25
  GEWAESSER = "dwd:Gewaesser"
25
26
 
26
- def get_from_location(longitude, latitude, radius_km, map_type: WeatherMapType, background_type: WeatherBackgroundMapType = WeatherBackgroundMapType.BUNDESLAENDER, image_width=520, image_height=580):
27
+
28
+ def get_from_location(
29
+ longitude,
30
+ latitude,
31
+ radius_km,
32
+ map_type: WeatherMapType,
33
+ background_type: WeatherBackgroundMapType = WeatherBackgroundMapType.BUNDESLAENDER,
34
+ image_width=520,
35
+ image_height=580,
36
+ ):
27
37
  if radius_km <= 0:
28
38
  raise ValueError("Radius must be greater than 0")
29
39
  if latitude < -90 or latitude > 90:
@@ -31,17 +41,46 @@ def get_from_location(longitude, latitude, radius_km, map_type: WeatherMapType,
31
41
  if longitude < -180 or longitude > 180:
32
42
  raise ValueError("Longitude must be between -180 and 180")
33
43
  radius = math.fabs(radius_km / (111.3 * math.cos(latitude)))
34
- return get_map(latitude-radius, longitude-radius, latitude+radius, longitude+radius, map_type, background_type, image_width, image_height)
44
+ return get_map(
45
+ latitude - radius,
46
+ longitude - radius,
47
+ latitude + radius,
48
+ longitude + radius,
49
+ map_type,
50
+ background_type,
51
+ image_width,
52
+ image_height,
53
+ )
54
+
55
+
56
+ def get_germany(
57
+ map_type: WeatherMapType,
58
+ background_type: WeatherBackgroundMapType = WeatherBackgroundMapType.BUNDESLAENDER,
59
+ image_width=520,
60
+ image_height=580,
61
+ ):
62
+ return get_map(
63
+ 4.4, 46.4, 16.1, 55.6, map_type, background_type, image_width, image_height
64
+ )
35
65
 
36
- def get_germany(map_type: WeatherMapType, background_type: WeatherBackgroundMapType = WeatherBackgroundMapType.BUNDESLAENDER, image_width=520, image_height=580):
37
- return get_map(4.4, 46.4, 16.1, 55.6, map_type, background_type, image_width, image_height)
38
66
 
39
- def get_map(minx,miny,maxx,maxy, map_type: WeatherMapType, background_type: WeatherBackgroundMapType, image_width=520, image_height=580):
67
+ def get_map(
68
+ minx,
69
+ miny,
70
+ maxx,
71
+ maxy,
72
+ map_type: WeatherMapType,
73
+ background_type: WeatherBackgroundMapType,
74
+ image_width=520,
75
+ image_height=580,
76
+ ):
40
77
  if image_width > 1200 or image_height > 1400:
41
- raise ValueError("Width and height must not exceed 1200 and 1400 respectively. Please be kind to the DWD servers.")
78
+ raise ValueError(
79
+ "Width and height must not exceed 1200 and 1400 respectively. Please be kind to the DWD servers."
80
+ )
42
81
 
43
- url = f"https://maps.dwd.de/geoserver/dwd/wms?service=WMS&version=1.1.0&request=GetMap&layers={background_type.value},{map_type.value}&bbox={minx},{miny},{maxx},{maxy}&width={image_width}&height={image_height}&srs=EPSG:4326&styles=&format=image/png"
82
+ url = f"https://maps.dwd.de/geoserver/dwd/wms?service=WMS&version=1.1.0&request=GetMap&layers={map_type.value},{background_type.value}&bbox={minx},{miny},{maxx},{maxy}&width={image_width}&height={image_height}&srs=EPSG:4326&styles=&format=image/png"
44
83
  request = requests.get(url, stream=True)
45
84
  if request.status_code == 200:
46
85
  image = Image.open(BytesIO(request.content))
47
- return image
86
+ return image
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: simple_dwd_weatherforecast
3
- Version: 2.0.31
3
+ Version: 2.0.32
4
4
  Summary: A simple tool to retrieve a weather forecast from DWD OpenData
5
5
  Home-page: https://github.com/FL550/simple_dwd_weatherforecast.git
6
6
  Author: Max Fermor
@@ -127,6 +127,8 @@ class Weather:
127
127
 
128
128
  get_timeframe_sum(weatherDataType: see WeatherDataType, datetime, timeframe: hours after datetime as int, optional bool shouldUpdate) # Returns the sum of that value within the time frame
129
129
 
130
+ get_daily_avg(weatherDataType: see WeatherDataType, datetime, optional bool shouldUpdate) # Returns the daily average of that value
131
+
130
132
  get_timeframe_avg(weatherDataType: see WeatherDataType, datetime, timeframe: hours after datetime as int, optional bool shouldUpdate) # Returns the average of that value within the time frame
131
133
 
132
134
  get_forecast_condition(datetime, optional bool shouldUpdate) # Result is condition as text
@@ -15,6 +15,7 @@ tests/__init__.py
15
15
  tests/dummy_data.py
16
16
  tests/dummy_data_full.py
17
17
  tests/dummy_uv.py
18
+ tests/test_get_daily_avg.py
18
19
  tests/test_get_daily_condition.py
19
20
  tests/test_get_daily_max.py
20
21
  tests/test_get_daily_min.py
@@ -0,0 +1,48 @@
1
+ from simple_dwd_weatherforecast.dwdforecast import WeatherDataType
2
+ import unittest
3
+ from unittest.mock import patch
4
+ from datetime import datetime
5
+ from simple_dwd_weatherforecast import dwdforecast
6
+ from dummy_data import parsed_data
7
+
8
+
9
+ class Weather_get_daily_avg(unittest.TestCase):
10
+ def setUp(self):
11
+ self.dwd_weather = dwdforecast.Weather("H889")
12
+ self.dwd_weather.forecast_data = parsed_data
13
+ self.dwd_weather.station_name = "BAD HOMBURG"
14
+
15
+ @patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
16
+ def test_shouldupdate(self, mock_update):
17
+ test_time = datetime(2020, 11, 7, 3, 30)
18
+ self.dwd_weather.get_daily_avg(WeatherDataType.PRECIPITATION, test_time, True)
19
+ mock_update.assert_called()
20
+
21
+ @patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
22
+ def test_shouldupdate_not(self, mock_update):
23
+ test_time = datetime(2020, 11, 7, 3, 30)
24
+ self.dwd_weather.get_daily_avg(WeatherDataType.PRECIPITATION, test_time, False)
25
+ mock_update.assert_not_called()
26
+
27
+ def test_not_in_timerange(self):
28
+ test_time = datetime(2000, 11, 7, 3, 30)
29
+ self.assertIsNone(
30
+ self.dwd_weather.get_daily_avg(WeatherDataType.PRECIPITATION, test_time)
31
+ )
32
+
33
+ @patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
34
+ def test_precipitation(self, mock_update):
35
+ test_time = datetime(2020, 11, 6, 12, 0)
36
+ print(self.dwd_weather.get_day_values(test_time))
37
+ self.assertEqual(
38
+ self.dwd_weather.get_daily_avg(WeatherDataType.PRECIPITATION, test_time),
39
+ 1.8,
40
+ )
41
+
42
+ @patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
43
+ def test_temperature(self, mock_update):
44
+ test_time = datetime(2020, 11, 6, 23, 0)
45
+ self.assertEqual(
46
+ self.dwd_weather.get_daily_avg(WeatherDataType.TEMPERATURE, test_time),
47
+ 278.09,
48
+ )
@@ -35,7 +35,7 @@ class Weather_get_daily_sum(unittest.TestCase):
35
35
  test_time = datetime(2020, 11, 6, 10, 0)
36
36
  self.assertEqual(
37
37
  self.dwd_weather.get_daily_sum(WeatherDataType.PRECIPITATION, test_time),
38
- 27.25,
38
+ 36.01,
39
39
  )
40
40
 
41
41
  @patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
@@ -43,5 +43,5 @@ class Weather_get_daily_sum(unittest.TestCase):
43
43
  test_time = datetime(2020, 11, 6, 10, 0)
44
44
  self.assertEqual(
45
45
  self.dwd_weather.get_daily_sum(WeatherDataType.TEMPERATURE, test_time),
46
- 5286.25,
46
+ 5561.8,
47
47
  )
@@ -451,6 +451,7 @@ class Weather_get_day_values(unittest.TestCase):
451
451
  self.dwd_weather.get_day_values(test_time),
452
452
  test_data,
453
453
  )
454
+ self.assertEqual(len(self.dwd_weather.get_day_values(test_time)), 24)
454
455
 
455
456
  def test_day_not_last_day(self):
456
457
  test_time = datetime(2020, 11, 16, 1, 0)
@@ -1004,8 +1005,27 @@ class Weather_get_day_values(unittest.TestCase):
1004
1005
  "wwM": 3.0,
1005
1006
  "humidity": 81.3,
1006
1007
  },
1008
+ {
1009
+ "TTT": 275.55,
1010
+ "Td": 273.45,
1011
+ "condition": "51",
1012
+ "PPPP": 103060.0,
1013
+ "DD": 52.0,
1014
+ "FF": 1.54,
1015
+ "FX1": 3.09,
1016
+ "RR1c": 8.76,
1017
+ "wwP": 2.0,
1018
+ "DRR1": 0.0,
1019
+ "N": 22.0,
1020
+ "VV": 15500.0,
1021
+ "SunD1": 0.0,
1022
+ "Rad1h": None,
1023
+ "wwM": 2.0,
1024
+ "humidity": 86.0,
1025
+ },
1007
1026
  ]
1008
1027
  self.assertEqual(
1009
1028
  self.dwd_weather.get_day_values(test_time),
1010
1029
  test_data,
1011
1030
  )
1031
+ self.assertEqual(len(self.dwd_weather.get_day_values(test_time)), 20)