simple-dwd-weatherforecast 2.1.0__tar.gz → 2.1.2__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.
- {simple_dwd_weatherforecast-2.1.0/simple_dwd_weatherforecast.egg-info → simple_dwd_weatherforecast-2.1.2}/PKG-INFO +4 -2
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/README.md +3 -1
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/setup.py +1 -1
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/simple_dwd_weatherforecast/dwdforecast.py +74 -26
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/simple_dwd_weatherforecast/dwdmap.py +23 -2
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2/simple_dwd_weatherforecast.egg-info}/PKG-INFO +4 -2
- simple_dwd_weatherforecast-2.1.2/tests/test_parsekml.py +52 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_update.py +4 -1
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_update_hourly.py +2 -0
- simple_dwd_weatherforecast-2.1.0/tests/test_parsekml.py +0 -33
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/LICENCE +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/setup.cfg +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/simple_dwd_weatherforecast/__init__.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/simple_dwd_weatherforecast/stations.json +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/simple_dwd_weatherforecast/uv_stations.json +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/simple_dwd_weatherforecast.egg-info/SOURCES.txt +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/simple_dwd_weatherforecast.egg-info/dependency_links.txt +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/simple_dwd_weatherforecast.egg-info/requires.txt +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/simple_dwd_weatherforecast.egg-info/top_level.txt +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/__init__.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/dummy_data.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/dummy_data_full.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/dummy_uv.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_daily_avg.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_daily_condition.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_daily_max.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_daily_min.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_daily_sum.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_day_values.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_forecast_condition.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_forecast_data.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_station_name.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_timeframe_avg.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_timeframe_condition.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_timeframe_max.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_timeframe_min.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_timeframe_sum.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_timeframe_values.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_is_in_timerange.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_is_valid_timeframe.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_location_tools.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_map.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_region.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_reported_weather.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_station.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_stationsfile.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_uv_index.py +0 -0
- {simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/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.1.
|
3
|
+
Version: 2.1.2
|
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
|
@@ -21,6 +21,8 @@ Requires-Dist: arrow
|
|
21
21
|
|
22
22
|
DISCLAIMER: This project is a private open source project and doesn't have any connection with Deutscher Wetterdienst.
|
23
23
|
|
24
|
+
**If you like my work, I would be really happy if you buy me some coffee: [Buy Me A Coffee][buymecoffee]**
|
25
|
+
|
24
26
|
## Weather data
|
25
27
|
|
26
28
|
This is a python package for simple access to hourly forecast data for the next 10 days. The data is updated every six hours and updated when needed. Some stations also have actual reported weather, which you can also retrieve.
|
@@ -208,7 +210,7 @@ get_map(minx,miny,maxx,maxy, map_type: WeatherMapType, background_type: WeatherB
|
|
208
210
|
|
209
211
|
### Image loop
|
210
212
|
|
211
|
-
There is also the possibility to retrieve multiple images as a loop. This can be done by the class ImageLoop.
|
213
|
+
There is also the possibility to retrieve multiple images as a loop. This can be done by the class ImageLoop. This however only works for the precipitation radar.
|
212
214
|
|
213
215
|
|
214
216
|
#### Usage example
|
@@ -4,6 +4,8 @@
|
|
4
4
|
|
5
5
|
DISCLAIMER: This project is a private open source project and doesn't have any connection with Deutscher Wetterdienst.
|
6
6
|
|
7
|
+
**If you like my work, I would be really happy if you buy me some coffee: [Buy Me A Coffee][buymecoffee]**
|
8
|
+
|
7
9
|
## Weather data
|
8
10
|
|
9
11
|
This is a python package for simple access to hourly forecast data for the next 10 days. The data is updated every six hours and updated when needed. Some stations also have actual reported weather, which you can also retrieve.
|
@@ -191,7 +193,7 @@ get_map(minx,miny,maxx,maxy, map_type: WeatherMapType, background_type: WeatherB
|
|
191
193
|
|
192
194
|
### Image loop
|
193
195
|
|
194
|
-
There is also the possibility to retrieve multiple images as a loop. This can be done by the class ImageLoop.
|
196
|
+
There is also the possibility to retrieve multiple images as a loop. This can be done by the class ImageLoop. This however only works for the precipitation radar.
|
195
197
|
|
196
198
|
|
197
199
|
#### Usage example
|
@@ -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.1.
|
8
|
+
version="2.1.2",
|
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,
|
@@ -7,6 +7,8 @@ from datetime import datetime, timedelta, timezone
|
|
7
7
|
from enum import Enum
|
8
8
|
from io import BytesIO
|
9
9
|
from zipfile import ZipFile
|
10
|
+
import httpx
|
11
|
+
from stream_unzip import stream_unzip
|
10
12
|
|
11
13
|
import arrow
|
12
14
|
import requests
|
@@ -677,7 +679,7 @@ class Weather:
|
|
677
679
|
|
678
680
|
items = []
|
679
681
|
result = kmlTree.xpath(
|
680
|
-
'./kml:ExtendedData/dwd:Forecast[@dwd:elementName="{}"]/dwd:value'.format(
|
682
|
+
'./kml:Document/kml:Placemark/kml:ExtendedData/dwd:Forecast[@dwd:elementName="{}"]/dwd:value'.format(
|
681
683
|
weatherDataType.value[0]
|
682
684
|
),
|
683
685
|
namespaces=self.namespaces,
|
@@ -694,14 +696,11 @@ class Weather:
|
|
694
696
|
items.append(None)
|
695
697
|
return items
|
696
698
|
|
697
|
-
def parse_kml(self, kml
|
698
|
-
|
699
|
-
(_, tree) = next(stream)
|
699
|
+
def parse_kml(self, kml):
|
700
|
+
tree = etree.fromstring(kml) # type: ignore
|
700
701
|
timesteps = self.parse_timesteps(tree)
|
701
702
|
issue_time_new = self.parse_issue_time(tree)
|
702
|
-
tree.clear()
|
703
703
|
|
704
|
-
tree = self.parse_placemark(stream)
|
705
704
|
self.issue_time = issue_time_new
|
706
705
|
|
707
706
|
self.loaded_station_name = self.parse_station_name(tree)
|
@@ -748,17 +747,6 @@ class Weather:
|
|
748
747
|
for (i, t) in enumerate(timesteps)
|
749
748
|
)
|
750
749
|
|
751
|
-
def parse_placemark(self, stream):
|
752
|
-
for _, tree in stream:
|
753
|
-
for placemark in tree.findall(
|
754
|
-
".//kml:Placemark", namespaces=self.namespaces
|
755
|
-
):
|
756
|
-
item = placemark.find(".//kml:name", namespaces=self.namespaces)
|
757
|
-
|
758
|
-
if item is not None and item.text == self.station_id:
|
759
|
-
return placemark
|
760
|
-
# placemark.clear()
|
761
|
-
|
762
750
|
def parse_issue_time(self, tree):
|
763
751
|
issue_time_new = arrow.get(
|
764
752
|
tree.xpath("//dwd:IssueTime", namespaces=self.namespaces)[0].text,
|
@@ -767,7 +755,9 @@ class Weather:
|
|
767
755
|
return issue_time_new
|
768
756
|
|
769
757
|
def parse_station_name(self, tree):
|
770
|
-
return tree.xpath(
|
758
|
+
return tree.xpath(
|
759
|
+
"./kml:Document/kml:Placemark/kml:description", namespaces=self.namespaces
|
760
|
+
)[0].text
|
771
761
|
|
772
762
|
def parse_timesteps(self, tree):
|
773
763
|
return [
|
@@ -781,7 +771,7 @@ class Weather:
|
|
781
771
|
return [
|
782
772
|
elem.split(".")[0]
|
783
773
|
for elem in tree.xpath(
|
784
|
-
'./kml:ExtendedData/dwd:Forecast[@dwd:elementName="ww"]/dwd:value',
|
774
|
+
'./kml:Document/kml:Placemark/kml:ExtendedData/dwd:Forecast[@dwd:elementName="ww"]/dwd:value',
|
785
775
|
namespaces=self.namespaces,
|
786
776
|
)[0].text.split()
|
787
777
|
]
|
@@ -945,11 +935,8 @@ class Weather:
|
|
945
935
|
except Exception as error:
|
946
936
|
print(f"Error in download_weather_report: {type(error)} args: {error.args}")
|
947
937
|
|
948
|
-
def
|
949
|
-
|
950
|
-
url = "https://opendata.dwd.de/weather/local_forecasts/mos/MOSMIX_S/all_stations/kml/MOSMIX_S_LATEST_240.kmz"
|
951
|
-
else:
|
952
|
-
url = f"https://opendata.dwd.de/weather/local_forecasts/mos/MOSMIX_L/single_stations/{stationid}/kml/MOSMIX_L_LATEST_{stationid}.kmz"
|
938
|
+
def download_small_kml(self, stationid) -> bytes | None:
|
939
|
+
url = f"https://opendata.dwd.de/weather/local_forecasts/mos/MOSMIX_L/single_stations/{stationid}/kml/MOSMIX_L_LATEST_{stationid}.kmz"
|
953
940
|
headers = {"If-None-Match": self.etags[url] if url in self.etags else ""} # type: ignore
|
954
941
|
try:
|
955
942
|
request = requests.get(url, headers=headers, timeout=30)
|
@@ -958,12 +945,73 @@ class Weather:
|
|
958
945
|
return
|
959
946
|
self.etags[url] = request.headers["ETag"] # type: ignore
|
960
947
|
with ZipFile(BytesIO(request.content), "r") as kmz:
|
961
|
-
# large RAM allocation
|
962
948
|
with kmz.open(kmz.namelist()[0], "r") as kml:
|
963
|
-
|
949
|
+
return kml.read()
|
950
|
+
|
964
951
|
except Exception as error:
|
965
952
|
print(f"Error in download_latest_kml: {type(error)} args: {error.args}")
|
966
953
|
|
954
|
+
def get_chunks(self):
|
955
|
+
def zipped_chunks():
|
956
|
+
# Iterable that yields the bytes of a zip file
|
957
|
+
with httpx.stream(
|
958
|
+
"GET",
|
959
|
+
"https://opendata.dwd.de/weather/local_forecasts/mos/MOSMIX_S/all_stations/kml/MOSMIX_S_LATEST_240.kmz",
|
960
|
+
) as r:
|
961
|
+
yield from r.iter_bytes(chunk_size=131072)
|
962
|
+
|
963
|
+
return stream_unzip(zipped_chunks())
|
964
|
+
|
965
|
+
def download_large_kml(self, stationid):
|
966
|
+
placemark = b""
|
967
|
+
|
968
|
+
for file_name, file_size, unzipped_chunks in self.get_chunks():
|
969
|
+
chunk1 = b""
|
970
|
+
chunk2 = b""
|
971
|
+
first_chunk = None
|
972
|
+
|
973
|
+
save_next = False
|
974
|
+
save_next_next = False
|
975
|
+
stop = False
|
976
|
+
# unzipped_chunks must be iterated to completion or UnfinishedIterationError will be raised
|
977
|
+
for chunk in unzipped_chunks:
|
978
|
+
if stop:
|
979
|
+
continue
|
980
|
+
if not first_chunk:
|
981
|
+
first_chunk = chunk
|
982
|
+
if save_next_next:
|
983
|
+
placemark = chunk1 + chunk2 + chunk
|
984
|
+
save_next_next = False
|
985
|
+
stop = True
|
986
|
+
if save_next:
|
987
|
+
chunk2 = chunk
|
988
|
+
save_next_next = True
|
989
|
+
save_next = False
|
990
|
+
|
991
|
+
if stationid.encode() in chunk:
|
992
|
+
chunk1 = chunk
|
993
|
+
save_next = True
|
994
|
+
if first_chunk:
|
995
|
+
start = placemark.find(b"<kml:Placemark>\n")
|
996
|
+
|
997
|
+
result = (
|
998
|
+
first_chunk[: first_chunk.find(b"<kml:Placemark>")]
|
999
|
+
+ placemark[
|
1000
|
+
start : placemark.find(b"</kml:Placemark>\n", start) + 17
|
1001
|
+
]
|
1002
|
+
+ b"</kml:Document></kml:kml>"
|
1003
|
+
)
|
1004
|
+
return result
|
1005
|
+
|
1006
|
+
def download_latest_kml(self, stationid, force_hourly=False):
|
1007
|
+
kml = (
|
1008
|
+
self.download_large_kml(stationid)
|
1009
|
+
if force_hourly
|
1010
|
+
else self.download_small_kml(stationid)
|
1011
|
+
)
|
1012
|
+
if kml is not None:
|
1013
|
+
self.parse_kml(kml)
|
1014
|
+
|
967
1015
|
def download_latest_report(self):
|
968
1016
|
station_id = self.station_id
|
969
1017
|
if len(station_id) == 4:
|
@@ -95,7 +95,15 @@ def get_map(
|
|
95
95
|
raise ValueError(
|
96
96
|
"Width and height must not exceed 1200 and 1400 respectively. Please be kind to the DWD servers."
|
97
97
|
)
|
98
|
-
|
98
|
+
if background_type in [
|
99
|
+
WeatherBackgroundMapType.SATELLIT,
|
100
|
+
WeatherBackgroundMapType.KREISE,
|
101
|
+
WeatherBackgroundMapType.GEMEINDEN,
|
102
|
+
]:
|
103
|
+
layers = f"{background_type.value}, {map_type.value}"
|
104
|
+
else:
|
105
|
+
layers = f"{map_type.value}, {background_type.value}"
|
106
|
+
url = f"https://maps.dwd.de/geoserver/dwd/wms?service=WMS&version=1.1.0&request=GetMap&layers={layers}&bbox={minx},{miny},{maxx},{maxy}&width={image_width}&height={image_height}&srs=EPSG:4326&styles=&format=image/png"
|
99
107
|
request = requests.get(url, stream=True)
|
100
108
|
if request.status_code == 200:
|
101
109
|
image = Image.open(BytesIO(request.content))
|
@@ -135,6 +143,8 @@ class ImageLoop:
|
|
135
143
|
self._miny = miny
|
136
144
|
self._maxx = maxx
|
137
145
|
self._maxy = maxy
|
146
|
+
if map_type != WeatherMapType.NIEDERSCHLAGSRADAR:
|
147
|
+
raise ValueError("Only NIEDERSCHLAGSRADAR is supported in a loop")
|
138
148
|
self._map_type = map_type
|
139
149
|
self._background_type = background_type
|
140
150
|
self._steps = steps
|
@@ -145,6 +155,9 @@ class ImageLoop:
|
|
145
155
|
|
146
156
|
self._full_reload()
|
147
157
|
|
158
|
+
def __getitem__(self, key):
|
159
|
+
return self._images[key]
|
160
|
+
|
148
161
|
def get_images(self) -> Iterable[ImageFile.ImageFile]:
|
149
162
|
return self._images
|
150
163
|
|
@@ -170,7 +183,15 @@ class ImageLoop:
|
|
170
183
|
self._images.append(self._get_image(self._last_update))
|
171
184
|
|
172
185
|
def _get_image(self, date: datetime) -> ImageFile.ImageFile:
|
173
|
-
|
186
|
+
if self._background_type in [
|
187
|
+
WeatherBackgroundMapType.SATELLIT,
|
188
|
+
WeatherBackgroundMapType.KREISE,
|
189
|
+
WeatherBackgroundMapType.GEMEINDEN,
|
190
|
+
]:
|
191
|
+
layers = f"{self._background_type.value}, {self._map_type.value}"
|
192
|
+
else:
|
193
|
+
layers = f"{self._map_type.value}, {self._background_type.value}"
|
194
|
+
url = f"https://maps.dwd.de/geoserver/dwd/wms?service=WMS&version=1.1.0&request=GetMap&layers={layers}&bbox={self._minx},{self._miny},{self._maxx},{self._maxy}&width={self._image_width}&height={self._image_height}&srs=EPSG:4326&styles=&format=image/png&TIME={date.strftime("%Y-%m-%dT%H:%M:00.0Z")}"
|
174
195
|
request = requests.get(url, stream=True)
|
175
196
|
if request.status_code != 200:
|
176
197
|
raise ConnectionError("Error during image request from DWD servers")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: simple_dwd_weatherforecast
|
3
|
-
Version: 2.1.
|
3
|
+
Version: 2.1.2
|
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
|
@@ -21,6 +21,8 @@ Requires-Dist: arrow
|
|
21
21
|
|
22
22
|
DISCLAIMER: This project is a private open source project and doesn't have any connection with Deutscher Wetterdienst.
|
23
23
|
|
24
|
+
**If you like my work, I would be really happy if you buy me some coffee: [Buy Me A Coffee][buymecoffee]**
|
25
|
+
|
24
26
|
## Weather data
|
25
27
|
|
26
28
|
This is a python package for simple access to hourly forecast data for the next 10 days. The data is updated every six hours and updated when needed. Some stations also have actual reported weather, which you can also retrieve.
|
@@ -208,7 +210,7 @@ get_map(minx,miny,maxx,maxy, map_type: WeatherMapType, background_type: WeatherB
|
|
208
210
|
|
209
211
|
### Image loop
|
210
212
|
|
211
|
-
There is also the possibility to retrieve multiple images as a loop. This can be done by the class ImageLoop.
|
213
|
+
There is also the possibility to retrieve multiple images as a loop. This can be done by the class ImageLoop. This however only works for the precipitation radar.
|
212
214
|
|
213
215
|
|
214
216
|
#### Usage example
|
@@ -0,0 +1,52 @@
|
|
1
|
+
from datetime import datetime, timezone
|
2
|
+
import unittest
|
3
|
+
from unittest.mock import patch
|
4
|
+
|
5
|
+
from simple_dwd_weatherforecast import dwdforecast
|
6
|
+
import dummy_data
|
7
|
+
import dummy_data_full
|
8
|
+
|
9
|
+
|
10
|
+
class KMLParseTestCase(unittest.TestCase):
|
11
|
+
FILE_NAME = "development/TEST_N4333.kml"
|
12
|
+
|
13
|
+
def setUp(self):
|
14
|
+
self.dwd_weather = dwdforecast.Weather("N4333")
|
15
|
+
|
16
|
+
def test_parse_kml(self):
|
17
|
+
with open(self.FILE_NAME, "rb") as kml:
|
18
|
+
self.dwd_weather.parse_kml(kml.read())
|
19
|
+
self.assertEqual(self.dwd_weather.forecast_data, dummy_data.parsed_data)
|
20
|
+
self.assertEqual(
|
21
|
+
self.dwd_weather.issue_time,
|
22
|
+
datetime(2020, 11, 6, 3, 0, tzinfo=timezone.utc),
|
23
|
+
)
|
24
|
+
|
25
|
+
|
26
|
+
def helper():
|
27
|
+
result = []
|
28
|
+
read_size = 131072
|
29
|
+
# Iterable that yields the bytes of a zip file
|
30
|
+
with open("development/MOSMIX_L_2023100809_stripped.kml", "rb") as kml:
|
31
|
+
content = kml.read(read_size)
|
32
|
+
while len(content) > 0:
|
33
|
+
result.append(content)
|
34
|
+
content = kml.read(read_size)
|
35
|
+
return zip([0], [0], [result])
|
36
|
+
|
37
|
+
|
38
|
+
class KMLParseFullTestCase(unittest.TestCase):
|
39
|
+
FILE_NAME = "development/MOSMIX_L_2023100809_stripped.kml"
|
40
|
+
|
41
|
+
def setUp(self):
|
42
|
+
self.dwd_weather = dwdforecast.Weather("L511")
|
43
|
+
|
44
|
+
@patch(
|
45
|
+
"simple_dwd_weatherforecast.dwdforecast.Weather.get_chunks",
|
46
|
+
return_value=helper(),
|
47
|
+
)
|
48
|
+
def test_parse_kml(self, _):
|
49
|
+
self.dwd_weather.download_latest_kml(
|
50
|
+
self.dwd_weather.station_id, force_hourly=True
|
51
|
+
)
|
52
|
+
self.assertEqual(self.dwd_weather.forecast_data, dummy_data_full.parsed_data)
|
@@ -22,6 +22,9 @@ class WeatherUpdate(unittest.TestCase):
|
|
22
22
|
def test_download(self, _1, _2):
|
23
23
|
self.dwd_weather.update()
|
24
24
|
self.assertIsNotNone(self.dwd_weather.forecast_data)
|
25
|
+
self.assertIsNotNone(self.dwd_weather.forecast_data)
|
26
|
+
self.assertEqual(self.dwd_weather.station_id, "H889")
|
27
|
+
self.assertEqual(self.dwd_weather.issue_time.date(), datetime.now().date()) # type: ignore
|
25
28
|
|
26
29
|
@patch(
|
27
30
|
"simple_dwd_weatherforecast.dwdforecast.Weather.download_latest_report",
|
@@ -55,7 +58,7 @@ class WeatherUpdate(unittest.TestCase):
|
|
55
58
|
self.dwd_weather.issue_time = datetime(
|
56
59
|
*(time.strptime("2020-11-06T03:00:00.000Z", "%Y-%m-%dT%H:%M:%S.%fZ")[0:6]),
|
57
60
|
0,
|
58
|
-
timezone.utc
|
61
|
+
timezone.utc,
|
59
62
|
)
|
60
63
|
self.dwd_weather.update()
|
61
64
|
mock_function.assert_called()
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_update_hourly.py
RENAMED
@@ -14,6 +14,8 @@ class WeatherUpdate(unittest.TestCase):
|
|
14
14
|
def test_download(self):
|
15
15
|
self.dwd_weather.update(force_hourly=True)
|
16
16
|
self.assertIsNotNone(self.dwd_weather.forecast_data)
|
17
|
+
self.assertEqual(self.dwd_weather.station_id, "H889")
|
18
|
+
self.assertEqual(self.dwd_weather.issue_time.date(), datetime.now().date()) # type: ignore
|
17
19
|
|
18
20
|
@patch(
|
19
21
|
"simple_dwd_weatherforecast.dwdforecast.Weather.download_latest_kml",
|
@@ -1,33 +0,0 @@
|
|
1
|
-
from datetime import datetime, timezone
|
2
|
-
import unittest
|
3
|
-
|
4
|
-
from simple_dwd_weatherforecast import dwdforecast
|
5
|
-
import dummy_data
|
6
|
-
import dummy_data_full
|
7
|
-
|
8
|
-
|
9
|
-
class KMLParseTestCase(unittest.TestCase):
|
10
|
-
FILE_NAME = "development/TEST_N4333.kml"
|
11
|
-
|
12
|
-
def setUp(self):
|
13
|
-
self.dwd_weather = dwdforecast.Weather("N4333")
|
14
|
-
|
15
|
-
def test_parse_kml(self):
|
16
|
-
with open(self.FILE_NAME, "rb") as kml:
|
17
|
-
self.dwd_weather.parse_kml(kml)
|
18
|
-
self.assertEqual(self.dwd_weather.forecast_data, dummy_data.parsed_data)
|
19
|
-
self.assertEqual(self.dwd_weather.issue_time, datetime(2020, 11, 6, 3, 0, tzinfo=timezone.utc))
|
20
|
-
|
21
|
-
|
22
|
-
class KMLParseFullTestCase(unittest.TestCase):
|
23
|
-
FILE_NAME = "development/MOSMIX_L_2023100809_stripped.kml"
|
24
|
-
|
25
|
-
def setUp(self):
|
26
|
-
self.dwd_weather = dwdforecast.Weather("L511")
|
27
|
-
|
28
|
-
def test_parse_kml(self):
|
29
|
-
with open(self.FILE_NAME, "rb") as kml:
|
30
|
-
self.dwd_weather.parse_kml(kml)
|
31
|
-
self.assertEqual(
|
32
|
-
self.dwd_weather.forecast_data, dummy_data_full.parsed_data
|
33
|
-
)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/dummy_data_full.py
RENAMED
File without changes
|
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_daily_avg.py
RENAMED
File without changes
|
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_daily_max.py
RENAMED
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_daily_min.py
RENAMED
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_daily_sum.py
RENAMED
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_day_values.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_get_station_name.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_is_in_timerange.py
RENAMED
File without changes
|
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_location_tools.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_reported_weather.py
RENAMED
File without changes
|
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_stationsfile.py
RENAMED
File without changes
|
{simple_dwd_weatherforecast-2.1.0 → simple_dwd_weatherforecast-2.1.2}/tests/test_uv_index.py
RENAMED
File without changes
|
File without changes
|