simple-dwd-weatherforecast 2.0.32__tar.gz → 2.0.34__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.0.32/simple_dwd_weatherforecast.egg-info → simple_dwd_weatherforecast-2.0.34}/PKG-INFO +1 -1
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/setup.py +4 -4
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/simple_dwd_weatherforecast/dwdforecast.py +116 -82
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/simple_dwd_weatherforecast/dwdmap.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34/simple_dwd_weatherforecast.egg-info}/PKG-INFO +1 -1
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_daily_avg.py +8 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_daily_condition.py +9 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_daily_max.py +9 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_daily_min.py +9 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_daily_sum.py +9 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_day_values.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_forecast_condition.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_forecast_data.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_station_name.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_timeframe_avg.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_timeframe_condition.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_timeframe_max.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_timeframe_min.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_timeframe_sum.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_timeframe_values.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_is_in_timerange.py +13 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_is_valid_timeframe.py +2 -3
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_station.py +2 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_update.py +1 -2
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_update_hourly.py +2 -3
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_weather.py +2 -3
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/LICENCE +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/README.md +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/setup.cfg +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/simple_dwd_weatherforecast/__init__.py +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/simple_dwd_weatherforecast/stations.json +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/simple_dwd_weatherforecast/uv_stations.json +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/simple_dwd_weatherforecast.egg-info/SOURCES.txt +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/simple_dwd_weatherforecast.egg-info/dependency_links.txt +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/simple_dwd_weatherforecast.egg-info/requires.txt +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/simple_dwd_weatherforecast.egg-info/top_level.txt +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/__init__.py +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/dummy_data.py +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/dummy_data_full.py +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/dummy_uv.py +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_location_tools.py +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_map.py +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_parsekml.py +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_region.py +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_reported_weather.py +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_stationsfile.py +0 -0
- {simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_uv_index.py +0 -0
@@ -5,20 +5,20 @@ with open("README.md", "r") as fh:
|
|
5
5
|
|
6
6
|
setuptools.setup(
|
7
7
|
name="simple_dwd_weatherforecast",
|
8
|
-
version="2.0.
|
8
|
+
version="2.0.34",
|
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,
|
12
12
|
long_description_content_type="text/markdown",
|
13
13
|
url="https://github.com/FL550/simple_dwd_weatherforecast.git",
|
14
14
|
packages=setuptools.find_packages(),
|
15
|
-
package_data={
|
15
|
+
package_data={"": ["stations.json", "uv_stations.json"]},
|
16
16
|
include_package_data=True,
|
17
17
|
classifiers=[
|
18
18
|
"Programming Language :: Python :: 3",
|
19
19
|
"License :: OSI Approved :: MIT License",
|
20
20
|
"Operating System :: OS Independent",
|
21
21
|
],
|
22
|
-
python_requires=
|
23
|
-
install_requires=[
|
22
|
+
python_requires=">=3.6",
|
23
|
+
install_requires=["lxml", "requests", "Pillow", "arrow"],
|
24
24
|
)
|
@@ -1,22 +1,23 @@
|
|
1
|
+
import csv
|
2
|
+
import importlib
|
3
|
+
import json
|
4
|
+
import math
|
1
5
|
from collections import OrderedDict, defaultdict
|
2
|
-
import
|
6
|
+
from datetime import datetime, timedelta, timezone
|
7
|
+
from enum import Enum
|
3
8
|
from io import BytesIO
|
4
9
|
from zipfile import ZipFile
|
5
|
-
|
6
|
-
from lxml import etree
|
7
|
-
from datetime import datetime, timedelta, timezone
|
10
|
+
|
8
11
|
import arrow
|
9
|
-
import
|
10
|
-
import
|
11
|
-
import csv
|
12
|
-
import importlib
|
12
|
+
import requests
|
13
|
+
from lxml import etree
|
13
14
|
|
14
|
-
with importlib.resources.files("simple_dwd_weatherforecast").joinpath(
|
15
|
+
with importlib.resources.files("simple_dwd_weatherforecast").joinpath( # type: ignore
|
15
16
|
"stations.json"
|
16
17
|
).open("r", encoding="utf-8") as file:
|
17
18
|
stations = json.load(file)
|
18
19
|
|
19
|
-
with importlib.resources.files("simple_dwd_weatherforecast").joinpath(
|
20
|
+
with importlib.resources.files("simple_dwd_weatherforecast").joinpath( # type: ignore
|
20
21
|
"uv_stations.json"
|
21
22
|
).open("r", encoding="utf-8") as file:
|
22
23
|
uv_stations = json.load(file)
|
@@ -32,6 +33,7 @@ def get_station_by_name(station_name: str):
|
|
32
33
|
for station in stations.items():
|
33
34
|
if station[1]["name"] == station_name:
|
34
35
|
return station
|
36
|
+
return None
|
35
37
|
|
36
38
|
|
37
39
|
def get_nearest_station_id(lat: float, lon: float):
|
@@ -40,14 +42,21 @@ def get_nearest_station_id(lat: float, lon: float):
|
|
40
42
|
|
41
43
|
def get_stations_sorted_by_distance(lat: float, lon: float):
|
42
44
|
"""
|
43
|
-
|
45
|
+
Return stations sort by distance.
|
44
46
|
|
45
|
-
|
46
|
-
|
47
|
-
|
47
|
+
Given a latitude and longitude, this function returns a list of stations sorted by
|
48
|
+
their distance from the provided location.
|
49
|
+
|
50
|
+
Args:
|
51
|
+
----
|
52
|
+
lat: The latitude of the location.
|
53
|
+
lon: The longitude of the location.
|
48
54
|
|
49
55
|
Returns:
|
50
|
-
|
56
|
+
-------
|
57
|
+
list: A list of stations sorted by distance, where each element is a list
|
58
|
+
containing the station ID and its distance from the location.
|
59
|
+
|
51
60
|
"""
|
52
61
|
result = []
|
53
62
|
for station in stations.items():
|
@@ -70,40 +79,40 @@ def get_distance(lat, lon, _lat, _lon):
|
|
70
79
|
|
71
80
|
def get_region(station_id: str):
|
72
81
|
if (
|
73
|
-
station_id in stations
|
74
|
-
and stations[station_id]["bundesland"] in Weather.region_codes
|
82
|
+
station_id in stations
|
83
|
+
and stations[station_id]["bundesland"] in Weather.region_codes
|
75
84
|
):
|
76
85
|
return stations[station_id]["bundesland"]
|
77
86
|
return None
|
78
87
|
|
79
88
|
|
80
89
|
class WeatherDataType(Enum):
|
81
|
-
CONDITION =
|
82
|
-
TEMPERATURE =
|
83
|
-
DEWPOINT =
|
84
|
-
PRESSURE =
|
85
|
-
WIND_SPEED =
|
90
|
+
CONDITION = ("condition", "present_weather")
|
91
|
+
TEMPERATURE = ("TTT", "dry_bulb_temperature_at_2_meter_above_ground") # Unit: K
|
92
|
+
DEWPOINT = ("Td", "dew_point_temperature_at_2_meter_above_ground") # Unit: K
|
93
|
+
PRESSURE = ("PPPP", "pressure_reduced_to_mean_sea_level") # Unit: Pa
|
94
|
+
WIND_SPEED = (
|
86
95
|
"FF",
|
87
96
|
"maximum_wind_speed_as_10_minutes_mean_during_last_hour",
|
88
|
-
|
89
|
-
WIND_DIRECTION =
|
97
|
+
) # Unit: m/s
|
98
|
+
WIND_DIRECTION = (
|
90
99
|
"DD",
|
91
100
|
"mean_wind_direction_during_last_10 min_at_10_meters_above_ground",
|
92
|
-
|
93
|
-
WIND_GUSTS =
|
94
|
-
PRECIPITATION =
|
95
|
-
PRECIPITATION_PROBABILITY =
|
96
|
-
PRECIPITATION_DURATION =
|
97
|
-
CLOUD_COVERAGE =
|
98
|
-
VISIBILITY =
|
99
|
-
SUN_DURATION =
|
100
|
-
SUN_IRRADIANCE =
|
101
|
-
FOG_PROBABILITY =
|
102
|
-
HUMIDITY =
|
101
|
+
) # Unit: Degrees
|
102
|
+
WIND_GUSTS = ("FX1", "maximum_wind_speed_last_hour") # Unit: m/s
|
103
|
+
PRECIPITATION = ("RR1c", "precipitation_amount_last_hour") # Unit: kg/m^2
|
104
|
+
PRECIPITATION_PROBABILITY = ("wwP", "") # Unit: % (0..100)
|
105
|
+
PRECIPITATION_DURATION = ("DRR1", "") # Unit: s
|
106
|
+
CLOUD_COVERAGE = ("N", "cloud_cover_total") # Unit: % (0..100)
|
107
|
+
VISIBILITY = ("VV", "horizontal_visibility") # Unit: m
|
108
|
+
SUN_DURATION = ("SunD1", "") # Unit: s
|
109
|
+
SUN_IRRADIANCE = ("Rad1h", "global_radiation_last_hour") # Unit: kJ/m^2
|
110
|
+
FOG_PROBABILITY = ("wwM", "") # Unit: % (0..100)
|
111
|
+
HUMIDITY = ("humidity", "relative_humidity") # Unit: %
|
103
112
|
|
104
113
|
|
105
114
|
class Weather:
|
106
|
-
"""A class for interacting with weather data from dwd.de"""
|
115
|
+
"""A class for interacting with weather data from dwd.de."""
|
107
116
|
|
108
117
|
NOT_AVAILABLE = "---"
|
109
118
|
|
@@ -254,15 +263,17 @@ class Weather:
|
|
254
263
|
self.region = get_region(station_id)
|
255
264
|
self.nearest_uv_index_station = self.get_nearest_station_id_with_uv()
|
256
265
|
else:
|
257
|
-
|
266
|
+
msg = "Not a valid station_id"
|
267
|
+
raise ValueError(msg)
|
258
268
|
|
259
269
|
def get_nearest_station_id_with_uv(self):
|
260
270
|
nearest_distance = float("inf")
|
261
271
|
nearest_station_id = None
|
272
|
+
_station = self.station
|
262
273
|
for station in uv_stations.items():
|
263
274
|
distance = get_distance(
|
264
|
-
self.station["lat"],
|
265
|
-
self.station["lon"],
|
275
|
+
self.station["lat"], # type: ignore
|
276
|
+
self.station["lon"], # type: ignore
|
266
277
|
station[1]["lat"],
|
267
278
|
station[1]["lon"],
|
268
279
|
)
|
@@ -274,17 +285,34 @@ class Weather:
|
|
274
285
|
return nearest_station_id
|
275
286
|
|
276
287
|
def get_station_name(self):
|
277
|
-
return self.station["name"]
|
288
|
+
return self.station["name"] # type: ignore
|
278
289
|
|
279
290
|
def is_in_timerange(self, timestamp: datetime):
|
280
291
|
return (
|
281
|
-
list(self.forecast_data.keys())[0]
|
292
|
+
list(self.forecast_data.keys())[0] # type: ignore
|
282
293
|
<= self.strip_to_hour_str(timestamp)
|
283
|
-
<= list(self.forecast_data.keys())[-1]
|
294
|
+
<= list(self.forecast_data.keys())[-1] # type: ignore
|
284
295
|
)
|
285
296
|
|
286
|
-
def
|
287
|
-
|
297
|
+
def is_in_timerange_day(self, timestamp: datetime):
|
298
|
+
return (
|
299
|
+
self.strip_to_day(
|
300
|
+
arrow.get(
|
301
|
+
list(self.forecast_data.keys())[0], # type: ignore
|
302
|
+
"YYYY-MM-DDTHH:mm:ss.SSSZ", # type: ignore
|
303
|
+
).datetime
|
304
|
+
)
|
305
|
+
<= self.strip_to_day(timestamp)
|
306
|
+
<= self.strip_to_day(
|
307
|
+
arrow.get(
|
308
|
+
list(self.forecast_data.keys())[-1], # type: ignore
|
309
|
+
"YYYY-MM-DDTHH:mm:ss.SSSZ", # type: ignore
|
310
|
+
).datetime
|
311
|
+
)
|
312
|
+
)
|
313
|
+
|
314
|
+
def is_valid_timeframe(self, timeframe: int) -> bool:
|
315
|
+
if timeframe > 24 or timeframe <= 0:
|
288
316
|
return False
|
289
317
|
return 24 % timeframe == 0
|
290
318
|
|
@@ -299,7 +327,7 @@ class Weather:
|
|
299
327
|
if shouldUpdate:
|
300
328
|
self.update()
|
301
329
|
if self.is_in_timerange(timestamp):
|
302
|
-
return self.forecast_data[self.strip_to_hour_str(timestamp)][
|
330
|
+
return self.forecast_data[self.strip_to_hour_str(timestamp)][ # type: ignore
|
303
331
|
weatherDataType.value[0]
|
304
332
|
]
|
305
333
|
return None
|
@@ -311,7 +339,7 @@ class Weather:
|
|
311
339
|
if self.is_in_timerange(timestamp):
|
312
340
|
return str(
|
313
341
|
self.weather_codes[
|
314
|
-
self.forecast_data[self.strip_to_hour_str(timestamp)][
|
342
|
+
self.forecast_data[self.strip_to_hour_str(timestamp)][ # type: ignore
|
315
343
|
WeatherDataType.CONDITION.value[0]
|
316
344
|
]
|
317
345
|
][0]
|
@@ -330,9 +358,11 @@ class Weather:
|
|
330
358
|
return None
|
331
359
|
|
332
360
|
def get_daily_condition(self, timestamp: datetime, shouldUpdate=True):
|
361
|
+
print("testieng")
|
333
362
|
if shouldUpdate:
|
334
363
|
self.update()
|
335
|
-
if self.
|
364
|
+
if self.is_in_timerange_day(timestamp):
|
365
|
+
print("working")
|
336
366
|
return self.get_condition(self.get_day_values(timestamp))
|
337
367
|
return None
|
338
368
|
|
@@ -400,7 +430,7 @@ class Weather:
|
|
400
430
|
else:
|
401
431
|
print("no report for this station available. Have you updated first?")
|
402
432
|
|
403
|
-
def get_uv_index(self, days_from_today: int, shouldUpdate=True) -> int:
|
433
|
+
def get_uv_index(self, days_from_today: int, shouldUpdate=True) -> int | None:
|
404
434
|
if not self.uv_reports and shouldUpdate:
|
405
435
|
self.update(
|
406
436
|
force_hourly=False,
|
@@ -444,11 +474,11 @@ class Weather:
|
|
444
474
|
):
|
445
475
|
if shouldUpdate:
|
446
476
|
self.update()
|
447
|
-
if self.
|
477
|
+
if self.is_in_timerange_day(timestamp):
|
448
478
|
return self.get_max(self.get_day_values(timestamp), weatherDataType)
|
449
479
|
return None
|
450
480
|
|
451
|
-
def get_max(
|
481
|
+
def get_max(self, weather_data, weatherDataType: WeatherDataType):
|
452
482
|
value = None
|
453
483
|
for item in weather_data:
|
454
484
|
value_new = item[weatherDataType.value[0]]
|
@@ -481,11 +511,11 @@ class Weather:
|
|
481
511
|
):
|
482
512
|
if shouldUpdate:
|
483
513
|
self.update()
|
484
|
-
if self.
|
514
|
+
if self.is_in_timerange_day(timestamp):
|
485
515
|
return self.get_min(self.get_day_values(timestamp), weatherDataType)
|
486
516
|
return None
|
487
517
|
|
488
|
-
def get_min(
|
518
|
+
def get_min(self, weather_data, weatherDataType: WeatherDataType):
|
489
519
|
value = None
|
490
520
|
for item in weather_data:
|
491
521
|
value_new = item[weatherDataType.value[0]]
|
@@ -519,11 +549,11 @@ class Weather:
|
|
519
549
|
):
|
520
550
|
if shouldUpdate:
|
521
551
|
self.update()
|
522
|
-
if self.
|
552
|
+
if self.is_in_timerange_day(timestamp):
|
523
553
|
return self.get_sum(self.get_day_values(timestamp), weatherDataType)
|
524
554
|
return None
|
525
555
|
|
526
|
-
def get_sum(
|
556
|
+
def get_sum(self, weather_data, weatherDataType):
|
527
557
|
value_sum = 0.0
|
528
558
|
for item in weather_data:
|
529
559
|
value = item[weatherDataType.value[0]]
|
@@ -551,11 +581,11 @@ class Weather:
|
|
551
581
|
):
|
552
582
|
if shouldUpdate:
|
553
583
|
self.update()
|
554
|
-
if self.
|
584
|
+
if self.is_in_timerange_day(timestamp):
|
555
585
|
return self.get_avg(self.get_day_values(timestamp), weatherDataType)
|
556
586
|
return None
|
557
587
|
|
558
|
-
def get_avg(
|
588
|
+
def get_avg(self, weather_data, weatherDataType):
|
559
589
|
value_sum = 0.0
|
560
590
|
count = len(weather_data)
|
561
591
|
if count != 0:
|
@@ -574,24 +604,25 @@ class Weather:
|
|
574
604
|
for _ in range(timeframe):
|
575
605
|
hour_str = self.strip_to_hour_str(time_step)
|
576
606
|
time_step += timedelta(hours=1)
|
577
|
-
if hour_str not in self.forecast_data:
|
607
|
+
if hour_str not in self.forecast_data: # type: ignore
|
578
608
|
continue
|
579
|
-
result.append(self.forecast_data[hour_str])
|
609
|
+
result.append(self.forecast_data[hour_str]) # type: ignore
|
580
610
|
return result
|
581
611
|
|
582
612
|
def get_day_values(self, timestamp: datetime):
|
583
613
|
"timestamp has to be checked prior to be in timerange"
|
584
614
|
result = []
|
585
615
|
first_entry_date = arrow.get(
|
586
|
-
next(iter(self.forecast_data)),
|
587
|
-
|
616
|
+
next(iter(self.forecast_data)), # type: ignore
|
617
|
+
"YYYY-MM-DDTHH:mm:ss.SSSZ", # type: ignore
|
618
|
+
).datetime # type: ignore
|
588
619
|
if timestamp.day != first_entry_date.day:
|
589
620
|
time_step = self.strip_to_day(timestamp)
|
590
621
|
for _ in range(24):
|
591
622
|
hour_str = self.strip_to_hour_str(time_step)
|
592
|
-
if hour_str not in self.forecast_data:
|
623
|
+
if hour_str not in self.forecast_data: # type: ignore
|
593
624
|
break
|
594
|
-
result.append(self.forecast_data[hour_str])
|
625
|
+
result.append(self.forecast_data[hour_str]) # type: ignore
|
595
626
|
time_step += timedelta(hours=1)
|
596
627
|
else:
|
597
628
|
time_step = first_entry_date
|
@@ -607,17 +638,17 @@ class Weather:
|
|
607
638
|
) + timedelta(days=1)
|
608
639
|
timediff = endtime - time_step
|
609
640
|
for _ in range(round(timediff.total_seconds() / 3600)):
|
610
|
-
result.append(self.forecast_data[self.strip_to_hour_str(time_step)])
|
641
|
+
result.append(self.forecast_data[self.strip_to_hour_str(time_step)]) # type: ignore
|
611
642
|
time_step += timedelta(hours=1)
|
612
643
|
return result
|
613
644
|
|
614
|
-
def strip_to_hour_str(
|
645
|
+
def strip_to_hour_str(self, timestamp: datetime):
|
615
646
|
return timestamp.strftime("%Y-%m-%dT%H:00:00.000Z")
|
616
647
|
|
617
|
-
def strip_to_hour(
|
648
|
+
def strip_to_hour(self, timestamp: datetime):
|
618
649
|
return datetime(timestamp.year, timestamp.month, timestamp.day, timestamp.hour)
|
619
650
|
|
620
|
-
def strip_to_day(
|
651
|
+
def strip_to_day(self, timestamp: datetime):
|
621
652
|
return datetime(timestamp.year, timestamp.month, timestamp.day)
|
622
653
|
|
623
654
|
def update(
|
@@ -677,7 +708,8 @@ class Weather:
|
|
677
708
|
|
678
709
|
self.loaded_station_name = self.parse_station_name(tree)
|
679
710
|
|
680
|
-
value
|
711
|
+
def value(wdt):
|
712
|
+
return self.get_weather_type(tree, wdt)
|
681
713
|
|
682
714
|
values = [
|
683
715
|
(wdt, value(wdt))
|
@@ -725,9 +757,9 @@ class Weather:
|
|
725
757
|
):
|
726
758
|
item = placemark.find(".//kml:name", namespaces=self.namespaces)
|
727
759
|
|
728
|
-
if item.text == self.station_id:
|
760
|
+
if item is not None and item.text == self.station_id:
|
729
761
|
return placemark
|
730
|
-
placemark.clear()
|
762
|
+
# placemark.clear()
|
731
763
|
|
732
764
|
def parse_issue_time(self, tree):
|
733
765
|
issue_time_new = arrow.get(
|
@@ -760,7 +792,9 @@ class Weather:
|
|
760
792
|
if None in (temperature, dewpoint):
|
761
793
|
return
|
762
794
|
|
763
|
-
celsius
|
795
|
+
def celsius(t):
|
796
|
+
return t - 273.1
|
797
|
+
|
764
798
|
T = celsius(temperature)
|
765
799
|
TD = celsius(dewpoint)
|
766
800
|
|
@@ -873,7 +907,7 @@ class Weather:
|
|
873
907
|
headers = {
|
874
908
|
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.116 Safari/537.36"
|
875
909
|
}
|
876
|
-
headers["If-None-Match"] = self.etags[url] if url in self.etags else ""
|
910
|
+
headers["If-None-Match"] = self.etags[url] if url in self.etags else "" # type: ignore
|
877
911
|
try:
|
878
912
|
request = requests.get(url, headers=headers, timeout=30)
|
879
913
|
# If resource has not been modified, return
|
@@ -881,7 +915,7 @@ class Weather:
|
|
881
915
|
return
|
882
916
|
elif request.status_code != 200:
|
883
917
|
raise Exception(f"Unexpected status code {request.status_code}")
|
884
|
-
self.etags[url] = request.headers["ETag"]
|
918
|
+
self.etags[url] = request.headers["ETag"] # type: ignore
|
885
919
|
uv_reports = json.loads(request.text)["content"]
|
886
920
|
# Match with existing stations
|
887
921
|
for uv_report in uv_reports:
|
@@ -889,22 +923,22 @@ class Weather:
|
|
889
923
|
self.uv_index_stations_reference_names[uv_report["city"]]
|
890
924
|
)
|
891
925
|
# uv_report.update({"lat": station[1]["lat"], "lon": station[1]["lon"]})
|
892
|
-
self.uv_reports[station[0]] = uv_report
|
926
|
+
self.uv_reports[station[0]] = uv_report # type: ignore
|
893
927
|
except Exception as error:
|
894
|
-
print(f"Error in
|
928
|
+
print(f"Error in download_uv_index: {type(error)} args: {error.args}")
|
895
929
|
|
896
930
|
def download_weather_report(self, region_code):
|
897
931
|
url = f"https://www.dwd.de/DWD/wetter/wv_allg/deutschland/text/vhdl13_{region_code}.html"
|
898
932
|
headers = {
|
899
933
|
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.116 Safari/537.36"
|
900
934
|
}
|
901
|
-
headers["If-None-Match"] = self.etags[url] if url in self.etags else ""
|
935
|
+
headers["If-None-Match"] = self.etags[url] if url in self.etags else "" # type: ignore
|
902
936
|
try:
|
903
937
|
request = requests.get(url, headers=headers, timeout=30)
|
904
938
|
# If resource has not been modified, return
|
905
939
|
if request.status_code == 304:
|
906
940
|
return
|
907
|
-
self.etags[url] = request.headers["ETag"]
|
941
|
+
self.etags[url] = request.headers["ETag"] # type: ignore
|
908
942
|
weather_report = request.text
|
909
943
|
a = weather_report.find(">")
|
910
944
|
if a != -1:
|
@@ -915,22 +949,22 @@ class Weather:
|
|
915
949
|
|
916
950
|
def download_latest_kml(self, stationid, force_hourly=False):
|
917
951
|
if force_hourly:
|
918
|
-
url =
|
952
|
+
url = "https://opendata.dwd.de/weather/local_forecasts/mos/MOSMIX_S/all_stations/kml/MOSMIX_S_LATEST_240.kmz"
|
919
953
|
else:
|
920
954
|
url = f"https://opendata.dwd.de/weather/local_forecasts/mos/MOSMIX_L/single_stations/{stationid}/kml/MOSMIX_L_LATEST_{stationid}.kmz"
|
921
|
-
headers = {"If-None-Match": self.etags[url] if url in self.etags else ""}
|
955
|
+
headers = {"If-None-Match": self.etags[url] if url in self.etags else ""} # type: ignore
|
922
956
|
try:
|
923
957
|
request = requests.get(url, headers=headers, timeout=30)
|
924
958
|
# If resource has not been modified, return
|
925
959
|
if request.status_code == 304:
|
926
960
|
return
|
927
|
-
self.etags[url] = request.headers["ETag"]
|
961
|
+
self.etags[url] = request.headers["ETag"] # type: ignore
|
928
962
|
with ZipFile(BytesIO(request.content), "r") as kmz:
|
929
963
|
# large RAM allocation
|
930
964
|
with kmz.open(kmz.namelist()[0], "r") as kml:
|
931
965
|
self.parse_kml(kml, force_hourly)
|
932
966
|
except Exception as error:
|
933
|
-
print(f"Error in
|
967
|
+
print(f"Error in download_latest_kml: {type(error)} args: {error.args}")
|
934
968
|
|
935
969
|
def download_latest_report(self):
|
936
970
|
station_id = self.station_id
|
@@ -939,7 +973,7 @@ class Weather:
|
|
939
973
|
url = (
|
940
974
|
f"https://opendata.dwd.de/weather/weather_reports/poi/{station_id}-BEOB.csv"
|
941
975
|
)
|
942
|
-
headers = {"If-None-Match": self.etags[url] if url in self.etags else ""}
|
976
|
+
headers = {"If-None-Match": self.etags[url] if url in self.etags else ""} # type: ignore
|
943
977
|
try:
|
944
978
|
response = requests.get(url, headers=headers, timeout=30)
|
945
979
|
if response.status_code == 200:
|
@@ -979,4 +1013,4 @@ class Weather:
|
|
979
1013
|
# Handle other status codes
|
980
1014
|
print(f"Failed to download report. Status code: {response.status_code}")
|
981
1015
|
except Exception as error:
|
982
|
-
print(f"Error in
|
1016
|
+
print(f"Error in download_latest_report: {type(error)} args: {error.args}")
|
@@ -6,7 +6,7 @@ from enum import Enum
|
|
6
6
|
|
7
7
|
|
8
8
|
class WeatherMapType(Enum):
|
9
|
-
NIEDERSCHLAGSRADAR = "dwd:Niederschlagsradar"
|
9
|
+
NIEDERSCHLAGSRADAR = "dwd:Niederschlagsradar,dwd:NCEW_EU"
|
10
10
|
MAXTEMP = "dwd:GefuehlteTempMax"
|
11
11
|
UVINDEX = "dwd:UVI_CS"
|
12
12
|
POLLENFLUG = "dwd:Pollenflug"
|
@@ -78,7 +78,6 @@ def get_map(
|
|
78
78
|
raise ValueError(
|
79
79
|
"Width and height must not exceed 1200 and 1400 respectively. Please be kind to the DWD servers."
|
80
80
|
)
|
81
|
-
|
82
81
|
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"
|
83
82
|
request = requests.get(url, stream=True)
|
84
83
|
if request.status_code == 200:
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_daily_avg.py
RENAMED
@@ -46,3 +46,11 @@ class Weather_get_daily_avg(unittest.TestCase):
|
|
46
46
|
self.dwd_weather.get_daily_avg(WeatherDataType.TEMPERATURE, test_time),
|
47
47
|
278.09,
|
48
48
|
)
|
49
|
+
|
50
|
+
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
51
|
+
def test_midnight(self, mock_update):
|
52
|
+
test_time = datetime(2020, 11, 6, 0, 0)
|
53
|
+
self.assertEqual(
|
54
|
+
self.dwd_weather.get_daily_avg(WeatherDataType.TEMPERATURE, test_time),
|
55
|
+
278.09,
|
56
|
+
)
|
@@ -8,8 +8,7 @@ from dummy_data import parsed_data
|
|
8
8
|
class Weather_get_daily_condition(unittest.TestCase):
|
9
9
|
def setUp(self):
|
10
10
|
self.dwd_weather = dwdforecast.Weather("H889")
|
11
|
-
self.dwd_weather.forecast_data = parsed_data
|
12
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
11
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
13
12
|
|
14
13
|
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
15
14
|
def test_shouldupdate(self, mock_update):
|
@@ -50,3 +49,11 @@ class Weather_get_daily_condition(unittest.TestCase):
|
|
50
49
|
self.dwd_weather.get_daily_condition(test_time),
|
51
50
|
"cloudy",
|
52
51
|
)
|
52
|
+
|
53
|
+
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
54
|
+
def test_same_day(self, _):
|
55
|
+
test_time = datetime(2020, 11, 6, 0, 0)
|
56
|
+
self.assertEqual(
|
57
|
+
self.dwd_weather.get_daily_condition(test_time),
|
58
|
+
"sunny",
|
59
|
+
)
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_daily_max.py
RENAMED
@@ -9,8 +9,7 @@ from dummy_data import parsed_data
|
|
9
9
|
class Weather_get_daily_max(unittest.TestCase):
|
10
10
|
def setUp(self):
|
11
11
|
self.dwd_weather = dwdforecast.Weather("H889")
|
12
|
-
self.dwd_weather.forecast_data = parsed_data
|
13
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
12
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
14
13
|
|
15
14
|
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
16
15
|
def test_shouldupdate(self, mock_update):
|
@@ -45,3 +44,11 @@ class Weather_get_daily_max(unittest.TestCase):
|
|
45
44
|
self.dwd_weather.get_daily_max(WeatherDataType.TEMPERATURE, test_time),
|
46
45
|
283.05,
|
47
46
|
)
|
47
|
+
|
48
|
+
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
49
|
+
def test_midnight(self, mock_update):
|
50
|
+
test_time = datetime(2020, 11, 6, 0, 0)
|
51
|
+
self.assertEqual(
|
52
|
+
self.dwd_weather.get_daily_max(WeatherDataType.TEMPERATURE, test_time),
|
53
|
+
283.05,
|
54
|
+
)
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_daily_min.py
RENAMED
@@ -9,8 +9,7 @@ from dummy_data import parsed_data
|
|
9
9
|
class Weather_get_daily_min(unittest.TestCase):
|
10
10
|
def setUp(self):
|
11
11
|
self.dwd_weather = dwdforecast.Weather("H889")
|
12
|
-
self.dwd_weather.forecast_data = parsed_data
|
13
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
12
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
14
13
|
|
15
14
|
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
16
15
|
def test_shouldupdate(self, mock_update):
|
@@ -45,3 +44,11 @@ class Weather_get_daily_min(unittest.TestCase):
|
|
45
44
|
self.dwd_weather.get_daily_min(WeatherDataType.TEMPERATURE, test_time),
|
46
45
|
272.95,
|
47
46
|
)
|
47
|
+
|
48
|
+
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
49
|
+
def test_midnight(self, mock_update):
|
50
|
+
test_time = datetime(2020, 11, 6, 0, 0)
|
51
|
+
self.assertEqual(
|
52
|
+
self.dwd_weather.get_daily_min(WeatherDataType.TEMPERATURE, test_time),
|
53
|
+
272.95,
|
54
|
+
)
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_daily_sum.py
RENAMED
@@ -9,8 +9,7 @@ from dummy_data import parsed_data
|
|
9
9
|
class Weather_get_daily_sum(unittest.TestCase):
|
10
10
|
def setUp(self):
|
11
11
|
self.dwd_weather = dwdforecast.Weather("H889")
|
12
|
-
self.dwd_weather.forecast_data = parsed_data
|
13
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
12
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
14
13
|
|
15
14
|
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
16
15
|
def test_shouldupdate(self, mock_update):
|
@@ -45,3 +44,11 @@ class Weather_get_daily_sum(unittest.TestCase):
|
|
45
44
|
self.dwd_weather.get_daily_sum(WeatherDataType.TEMPERATURE, test_time),
|
46
45
|
5561.8,
|
47
46
|
)
|
47
|
+
|
48
|
+
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
49
|
+
def test_midnight(self, mock_update):
|
50
|
+
test_time = datetime(2020, 11, 6, 0, 0)
|
51
|
+
self.assertEqual(
|
52
|
+
self.dwd_weather.get_daily_sum(WeatherDataType.TEMPERATURE, test_time),
|
53
|
+
5561.8,
|
54
|
+
)
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_get_day_values.py
RENAMED
@@ -7,8 +7,7 @@ from dummy_data import parsed_data
|
|
7
7
|
class Weather_get_day_values(unittest.TestCase):
|
8
8
|
def setUp(self):
|
9
9
|
self.dwd_weather = dwdforecast.Weather("H889")
|
10
|
-
self.dwd_weather.forecast_data = parsed_data
|
11
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
10
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
12
11
|
|
13
12
|
def test_day_not_current_day(self):
|
14
13
|
test_time = datetime(2020, 11, 7, 10, 0)
|
@@ -8,8 +8,7 @@ from dummy_data import parsed_data
|
|
8
8
|
class Weather_get_forecast_condition(unittest.TestCase):
|
9
9
|
def setUp(self):
|
10
10
|
self.dwd_weather = dwdforecast.Weather("H889")
|
11
|
-
self.dwd_weather.forecast_data = parsed_data
|
12
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
11
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
13
12
|
|
14
13
|
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
15
14
|
def test_shouldupdate(self, mock_update):
|
@@ -9,8 +9,7 @@ from dummy_data import parsed_data
|
|
9
9
|
class Weather_get_forecast_data(unittest.TestCase):
|
10
10
|
def setUp(self):
|
11
11
|
self.dwd_weather = dwdforecast.Weather("H889")
|
12
|
-
self.dwd_weather.forecast_data = parsed_data
|
13
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
12
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
14
13
|
|
15
14
|
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
16
15
|
def test_shouldupdate(self, mock_update):
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import unittest
|
2
|
-
from unittest.mock import patch
|
3
2
|
from simple_dwd_weatherforecast import dwdforecast
|
4
3
|
from dummy_data import parsed_data
|
5
4
|
|
@@ -7,7 +6,7 @@ from dummy_data import parsed_data
|
|
7
6
|
class Weather_get_station_name(unittest.TestCase):
|
8
7
|
def setUp(self):
|
9
8
|
self.dwd_weather = dwdforecast.Weather("H889")
|
10
|
-
self.dwd_weather.forecast_data = parsed_data
|
9
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
11
10
|
|
12
11
|
def test_get_station_name(self):
|
13
12
|
self.assertEqual(self.dwd_weather.get_station_name(), "Burbach-Wuergendorf")
|
@@ -9,8 +9,7 @@ from dummy_data import parsed_data
|
|
9
9
|
class Weather_get_timeframe_avg(unittest.TestCase):
|
10
10
|
def setUp(self):
|
11
11
|
self.dwd_weather = dwdforecast.Weather("H889")
|
12
|
-
self.dwd_weather.forecast_data = parsed_data
|
13
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
12
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
14
13
|
|
15
14
|
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
16
15
|
def test_shouldupdate(self, mock_update):
|
@@ -8,8 +8,7 @@ from dummy_data import parsed_data
|
|
8
8
|
class Weather_get_timeframe_condition(unittest.TestCase):
|
9
9
|
def setUp(self):
|
10
10
|
self.dwd_weather = dwdforecast.Weather("H889")
|
11
|
-
self.dwd_weather.forecast_data = parsed_data
|
12
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
11
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
13
12
|
|
14
13
|
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
15
14
|
def test_shouldupdate(self, mock_update):
|
@@ -9,8 +9,7 @@ from dummy_data import parsed_data
|
|
9
9
|
class Weather_get_timeframe_max(unittest.TestCase):
|
10
10
|
def setUp(self):
|
11
11
|
self.dwd_weather = dwdforecast.Weather("H889")
|
12
|
-
self.dwd_weather.forecast_data = parsed_data
|
13
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
12
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
14
13
|
|
15
14
|
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
16
15
|
def test_shouldupdate(self, mock_update):
|
@@ -9,8 +9,7 @@ from dummy_data import parsed_data
|
|
9
9
|
class Weather_get_timeframe_min(unittest.TestCase):
|
10
10
|
def setUp(self):
|
11
11
|
self.dwd_weather = dwdforecast.Weather("H889")
|
12
|
-
self.dwd_weather.forecast_data = parsed_data
|
13
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
12
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
14
13
|
|
15
14
|
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
16
15
|
def test_shouldupdate(self, mock_update):
|
@@ -9,8 +9,7 @@ from dummy_data import parsed_data
|
|
9
9
|
class Weather_get_timeframe_sum(unittest.TestCase):
|
10
10
|
def setUp(self):
|
11
11
|
self.dwd_weather = dwdforecast.Weather("H889")
|
12
|
-
self.dwd_weather.forecast_data = parsed_data
|
13
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
12
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
14
13
|
|
15
14
|
@patch("simple_dwd_weatherforecast.dwdforecast.Weather.update", return_value=None)
|
16
15
|
def test_shouldupdate(self, mock_update):
|
@@ -7,8 +7,7 @@ from dummy_data import parsed_data
|
|
7
7
|
class Weather_get_timeframe_values(unittest.TestCase):
|
8
8
|
def setUp(self):
|
9
9
|
self.dwd_weather = dwdforecast.Weather("H889")
|
10
|
-
self.dwd_weather.forecast_data = parsed_data
|
11
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
10
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
12
11
|
|
13
12
|
def test_timeframe_6(self):
|
14
13
|
test_time = datetime(2020, 11, 7, 1, 0)
|
@@ -7,8 +7,7 @@ from dummy_data import parsed_data
|
|
7
7
|
class Weather_is_in_timerange(unittest.TestCase):
|
8
8
|
def setUp(self):
|
9
9
|
self.dwd_weather = dwdforecast.Weather("H889")
|
10
|
-
self.dwd_weather.forecast_data = parsed_data
|
11
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
10
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
12
11
|
|
13
12
|
def test_is_in_timerange(self):
|
14
13
|
test_time = datetime(2020, 11, 7, 3, 30)
|
@@ -21,3 +20,15 @@ class Weather_is_in_timerange(unittest.TestCase):
|
|
21
20
|
def test_is_in_timerange_future(self):
|
22
21
|
test_time = datetime(2102, 11, 5, 7, 30)
|
23
22
|
self.assertFalse(self.dwd_weather.is_in_timerange(test_time))
|
23
|
+
|
24
|
+
def test_is_in_timerange_day(self):
|
25
|
+
test_time = datetime(2020, 11, 6, 0, 0)
|
26
|
+
self.assertTrue(self.dwd_weather.is_in_timerange_day(test_time))
|
27
|
+
|
28
|
+
def test_is_in_timerange_day_past(self):
|
29
|
+
test_time = datetime(2000, 11, 5, 17, 30)
|
30
|
+
self.assertFalse(self.dwd_weather.is_in_timerange(test_time))
|
31
|
+
|
32
|
+
def test_is_in_timerange_day_future(self):
|
33
|
+
test_time = datetime(2102, 11, 5, 7, 30)
|
34
|
+
self.assertFalse(self.dwd_weather.is_in_timerange(test_time))
|
@@ -6,8 +6,7 @@ from dummy_data import parsed_data
|
|
6
6
|
class Weather_is_valid_timeframe(unittest.TestCase):
|
7
7
|
def setUp(self):
|
8
8
|
self.dwd_weather = dwdforecast.Weather("H889")
|
9
|
-
self.dwd_weather.forecast_data = parsed_data
|
10
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
9
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
11
10
|
|
12
11
|
def test_is_day(self):
|
13
12
|
self.assertTrue(self.dwd_weather.is_valid_timeframe(24))
|
@@ -25,4 +24,4 @@ class Weather_is_valid_timeframe(unittest.TestCase):
|
|
25
24
|
self.assertFalse(self.dwd_weather.is_valid_timeframe(0))
|
26
25
|
|
27
26
|
def test_is_negative(self):
|
28
|
-
self.assertFalse(self.dwd_weather.is_valid_timeframe(-5))
|
27
|
+
self.assertFalse(self.dwd_weather.is_valid_timeframe(-5))
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_station.py
RENAMED
@@ -17,7 +17,7 @@ class StationTestCase(unittest.TestCase):
|
|
17
17
|
|
18
18
|
def test_is_valid_station_id_empty_string(self):
|
19
19
|
self.assertFalse(dwdforecast.load_station_id(""))
|
20
|
-
self.assertFalse(dwdforecast.load_station_id(1))
|
20
|
+
self.assertFalse(dwdforecast.load_station_id("1"))
|
21
21
|
|
22
22
|
def test_get_station_by_name(self):
|
23
|
-
self.assertEqual(dwdforecast.get_station_by_name("Ulm")[0], "10838")
|
23
|
+
self.assertEqual(dwdforecast.get_station_by_name("Ulm")[0], "10838") # type: ignore
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_update.py
RENAMED
@@ -9,8 +9,7 @@ import time
|
|
9
9
|
class WeatherUpdate(unittest.TestCase):
|
10
10
|
def setUp(self):
|
11
11
|
self.dwd_weather = dwdforecast.Weather("H889")
|
12
|
-
self.dwd_weather.forecast_data = parsed_data
|
13
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
12
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
14
13
|
|
15
14
|
@patch(
|
16
15
|
"simple_dwd_weatherforecast.dwdforecast.Weather.download_latest_report",
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_update_hourly.py
RENAMED
@@ -2,15 +2,14 @@ import unittest
|
|
2
2
|
from unittest.mock import patch
|
3
3
|
from simple_dwd_weatherforecast import dwdforecast
|
4
4
|
from dummy_data import parsed_data
|
5
|
-
from datetime import datetime, timezone
|
5
|
+
from datetime import datetime, timezone
|
6
6
|
import time
|
7
7
|
|
8
8
|
|
9
9
|
class WeatherUpdate(unittest.TestCase):
|
10
10
|
def setUp(self):
|
11
11
|
self.dwd_weather = dwdforecast.Weather("H889")
|
12
|
-
self.dwd_weather.forecast_data = parsed_data
|
13
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
12
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
14
13
|
|
15
14
|
def test_download(self):
|
16
15
|
self.dwd_weather.update(force_hourly=True)
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_weather.py
RENAMED
@@ -6,8 +6,7 @@ from dummy_data import parsed_data
|
|
6
6
|
class WeatherInit(unittest.TestCase):
|
7
7
|
def setUp(self):
|
8
8
|
self.dwd_weather = dwdforecast.Weather("L821")
|
9
|
-
self.dwd_weather.forecast_data = parsed_data
|
10
|
-
self.dwd_weather.station_name = "BAD HOMBURG"
|
9
|
+
self.dwd_weather.forecast_data = parsed_data # type: ignore
|
11
10
|
|
12
11
|
def test_init_with_wrong_id(self):
|
13
12
|
with self.assertRaises(ValueError) as _:
|
@@ -19,7 +18,7 @@ class WeatherInit(unittest.TestCase):
|
|
19
18
|
|
20
19
|
def test_init_with_no_id(self):
|
21
20
|
with self.assertRaises(TypeError) as _:
|
22
|
-
dwdforecast.Weather()
|
21
|
+
dwdforecast.Weather() # type: ignore
|
23
22
|
|
24
23
|
def test_uv_index(self):
|
25
24
|
self.assertEqual(self.dwd_weather.nearest_uv_index_station, "10637")
|
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
|
File without changes
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/dummy_data_full.py
RENAMED
File without changes
|
File without changes
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_location_tools.py
RENAMED
File without changes
|
File without changes
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_parsekml.py
RENAMED
File without changes
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_region.py
RENAMED
File without changes
|
File without changes
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_stationsfile.py
RENAMED
File without changes
|
{simple_dwd_weatherforecast-2.0.32 → simple_dwd_weatherforecast-2.0.34}/tests/test_uv_index.py
RENAMED
File without changes
|