simple-dwd-weatherforecast 2.0.29__py3-none-any.whl → 2.0.32__py3-none-any.whl

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.
@@ -400,8 +400,8 @@ class Weather:
400
400
  else:
401
401
  print("no report for this station available. Have you updated first?")
402
402
 
403
- def get_uv_index(self, days_from_today: int) -> int:
404
- if not self.uv_reports:
403
+ def get_uv_index(self, days_from_today: int, shouldUpdate=True) -> int:
404
+ if not self.uv_reports and shouldUpdate:
405
405
  self.update(
406
406
  force_hourly=False,
407
407
  with_forecast=False,
@@ -418,7 +418,11 @@ class Weather:
418
418
  day = "tomorrow"
419
419
  elif days_from_today == 2:
420
420
  day = "dayafter_to"
421
- return self.uv_reports[self.nearest_uv_index_station]["forecast"][day]
421
+ return (
422
+ self.uv_reports[self.nearest_uv_index_station]["forecast"][day]
423
+ if self.uv_reports
424
+ else None
425
+ )
422
426
 
423
427
  def get_timeframe_max(
424
428
  self,
@@ -542,6 +546,15 @@ class Weather:
542
546
  )
543
547
  return None
544
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
+
545
558
  def get_avg(_, weather_data, weatherDataType):
546
559
  value_sum = 0.0
547
560
  count = len(weather_data)
@@ -582,20 +595,16 @@ class Weather:
582
595
  time_step += timedelta(hours=1)
583
596
  else:
584
597
  time_step = first_entry_date
585
- endtime = (
586
- datetime(
587
- time_step.year,
588
- time_step.month,
589
- time_step.day,
590
- 0,
591
- 0,
592
- 0,
593
- 0,
594
- timezone.utc,
595
- )
596
- + timedelta(days=1)
597
- + timedelta(hours=-1)
598
- )
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)
599
608
  timediff = endtime - time_step
600
609
  for _ in range(round(timediff.total_seconds() / 3600)):
601
610
  result.append(self.forecast_data[self.strip_to_hour_str(time_step)])
@@ -766,79 +775,92 @@ class Weather:
766
775
  self.report_data = {
767
776
  "time": row["Parameter description"],
768
777
  "date": row["surface observations"],
769
- WeatherDataType.CONDITION.value[0]: int(
770
- row[WeatherDataType.CONDITION.value[1]]
771
- )
772
- if row[WeatherDataType.CONDITION.value[1]] != self.NOT_AVAILABLE
773
- else None,
774
- WeatherDataType.TEMPERATURE.value[0]: round(
775
- float(
776
- row[WeatherDataType.TEMPERATURE.value[1]]
777
- .replace(self.NOT_AVAILABLE, "0.0")
778
- .replace(",", ".")
778
+ WeatherDataType.CONDITION.value[0]: (
779
+ int(row[WeatherDataType.CONDITION.value[1]])
780
+ if row[WeatherDataType.CONDITION.value[1]] != self.NOT_AVAILABLE
781
+ else None
782
+ ),
783
+ WeatherDataType.TEMPERATURE.value[0]: (
784
+ round(
785
+ float(
786
+ row[WeatherDataType.TEMPERATURE.value[1]]
787
+ .replace(self.NOT_AVAILABLE, "0.0")
788
+ .replace(",", ".")
789
+ )
790
+ + 273.1,
791
+ 1,
779
792
  )
780
- + 273.1,
781
- 1,
782
- )
783
- if row[WeatherDataType.TEMPERATURE.value[1]] != self.NOT_AVAILABLE
784
- else None,
785
- WeatherDataType.DEWPOINT.value[0]: round(
786
- float(row[WeatherDataType.DEWPOINT.value[1]].replace(",", ".")) + 273.1,
787
- 1,
788
- )
789
- if row[WeatherDataType.DEWPOINT.value[1]] != self.NOT_AVAILABLE
790
- else None,
791
- WeatherDataType.PRESSURE.value[0]: float(
792
- row[WeatherDataType.PRESSURE.value[1]].replace(",", ".")
793
- )
794
- * 100
795
- if row[WeatherDataType.PRESSURE.value[1]] != self.NOT_AVAILABLE
796
- else None,
797
- WeatherDataType.WIND_SPEED.value[0]: round(
798
- float(row[WeatherDataType.WIND_SPEED.value[1]].replace(",", ".")) / 3.6,
799
- 1,
800
- )
801
- if row[WeatherDataType.WIND_SPEED.value[1]] != self.NOT_AVAILABLE
802
- else None,
803
- WeatherDataType.WIND_DIRECTION.value[0]: int(
804
- row[WeatherDataType.WIND_DIRECTION.value[1]]
805
- )
806
- if row[WeatherDataType.WIND_DIRECTION.value[1]] != self.NOT_AVAILABLE
807
- else None,
808
- WeatherDataType.WIND_GUSTS.value[0]: round(
809
- float(row[WeatherDataType.WIND_GUSTS.value[1]].replace(",", ".")) / 3.6,
810
- 1,
811
- )
812
- if row[WeatherDataType.WIND_GUSTS.value[1]] != self.NOT_AVAILABLE
813
- else None,
814
- WeatherDataType.PRECIPITATION.value[0]: float(
815
- row[WeatherDataType.PRECIPITATION.value[1]].replace(",", ".")
816
- )
817
- if row[WeatherDataType.PRECIPITATION.value[1]] != self.NOT_AVAILABLE
818
- else None,
819
- WeatherDataType.CLOUD_COVERAGE.value[0]: float(
820
- row[WeatherDataType.CLOUD_COVERAGE.value[1]].replace(",", ".")
821
- )
822
- if row[WeatherDataType.CLOUD_COVERAGE.value[1]] != self.NOT_AVAILABLE
823
- else None,
824
- WeatherDataType.VISIBILITY.value[0]: float(
825
- row[WeatherDataType.VISIBILITY.value[1]].replace(",", ".")
826
- )
827
- * 1e3
828
- if row[WeatherDataType.VISIBILITY.value[1]] != self.NOT_AVAILABLE
829
- else None,
830
- WeatherDataType.SUN_IRRADIANCE.value[0]: round(
831
- float(row[WeatherDataType.SUN_IRRADIANCE.value[1]].replace(",", "."))
832
- * 3.6,
833
- 1,
834
- )
835
- if row[WeatherDataType.SUN_IRRADIANCE.value[1]] != self.NOT_AVAILABLE
836
- else None,
837
- WeatherDataType.HUMIDITY.value[0]: float(
838
- row[WeatherDataType.HUMIDITY.value[1]].replace(",", ".")
839
- )
840
- if row[WeatherDataType.HUMIDITY.value[1]] != self.NOT_AVAILABLE
841
- else None,
793
+ if row[WeatherDataType.TEMPERATURE.value[1]] != self.NOT_AVAILABLE
794
+ else None
795
+ ),
796
+ WeatherDataType.DEWPOINT.value[0]: (
797
+ round(
798
+ float(row[WeatherDataType.DEWPOINT.value[1]].replace(",", "."))
799
+ + 273.1,
800
+ 1,
801
+ )
802
+ if row[WeatherDataType.DEWPOINT.value[1]] != self.NOT_AVAILABLE
803
+ else None
804
+ ),
805
+ WeatherDataType.PRESSURE.value[0]: (
806
+ float(row[WeatherDataType.PRESSURE.value[1]].replace(",", ".")) * 100
807
+ if row[WeatherDataType.PRESSURE.value[1]] != self.NOT_AVAILABLE
808
+ else None
809
+ ),
810
+ WeatherDataType.WIND_SPEED.value[0]: (
811
+ round(
812
+ float(row[WeatherDataType.WIND_SPEED.value[1]].replace(",", "."))
813
+ / 3.6,
814
+ 1,
815
+ )
816
+ if row[WeatherDataType.WIND_SPEED.value[1]] != self.NOT_AVAILABLE
817
+ else None
818
+ ),
819
+ WeatherDataType.WIND_DIRECTION.value[0]: (
820
+ int(row[WeatherDataType.WIND_DIRECTION.value[1]])
821
+ if row[WeatherDataType.WIND_DIRECTION.value[1]] != self.NOT_AVAILABLE
822
+ else None
823
+ ),
824
+ WeatherDataType.WIND_GUSTS.value[0]: (
825
+ round(
826
+ float(row[WeatherDataType.WIND_GUSTS.value[1]].replace(",", "."))
827
+ / 3.6,
828
+ 1,
829
+ )
830
+ if row[WeatherDataType.WIND_GUSTS.value[1]] != self.NOT_AVAILABLE
831
+ else None
832
+ ),
833
+ WeatherDataType.PRECIPITATION.value[0]: (
834
+ float(row[WeatherDataType.PRECIPITATION.value[1]].replace(",", "."))
835
+ if row[WeatherDataType.PRECIPITATION.value[1]] != self.NOT_AVAILABLE
836
+ else None
837
+ ),
838
+ WeatherDataType.CLOUD_COVERAGE.value[0]: (
839
+ float(row[WeatherDataType.CLOUD_COVERAGE.value[1]].replace(",", "."))
840
+ if row[WeatherDataType.CLOUD_COVERAGE.value[1]] != self.NOT_AVAILABLE
841
+ else None
842
+ ),
843
+ WeatherDataType.VISIBILITY.value[0]: (
844
+ float(row[WeatherDataType.VISIBILITY.value[1]].replace(",", ".")) * 1e3
845
+ if row[WeatherDataType.VISIBILITY.value[1]] != self.NOT_AVAILABLE
846
+ else None
847
+ ),
848
+ WeatherDataType.SUN_IRRADIANCE.value[0]: (
849
+ round(
850
+ float(
851
+ row[WeatherDataType.SUN_IRRADIANCE.value[1]].replace(",", ".")
852
+ )
853
+ * 3.6,
854
+ 1,
855
+ )
856
+ if row[WeatherDataType.SUN_IRRADIANCE.value[1]] != self.NOT_AVAILABLE
857
+ else None
858
+ ),
859
+ WeatherDataType.HUMIDITY.value[0]: (
860
+ float(row[WeatherDataType.HUMIDITY.value[1]].replace(",", "."))
861
+ if row[WeatherDataType.HUMIDITY.value[1]] != self.NOT_AVAILABLE
862
+ else None
863
+ ),
842
864
  }
843
865
 
844
866
  def get_weather_report(self, shouldUpdate=False):
@@ -852,21 +874,24 @@ class Weather:
852
874
  "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"
853
875
  }
854
876
  headers["If-None-Match"] = self.etags[url] if url in self.etags else ""
855
- request = requests.get(url, headers=headers)
856
- # If resource has not been modified, return
857
- if request.status_code == 304:
858
- return
859
- elif request.status_code != 200:
860
- raise Exception(f"Unexpected status code {request.status_code}")
861
- self.etags[url] = request.headers["ETag"]
862
- uv_reports = json.loads(request.text)["content"]
863
- # Match with existing stations
864
- for uv_report in uv_reports:
865
- station = get_station_by_name(
866
- self.uv_index_stations_reference_names[uv_report["city"]]
867
- )
868
- # uv_report.update({"lat": station[1]["lat"], "lon": station[1]["lon"]})
869
- self.uv_reports[station[0]] = uv_report
877
+ try:
878
+ request = requests.get(url, headers=headers, timeout=30)
879
+ # If resource has not been modified, return
880
+ if request.status_code == 304:
881
+ return
882
+ elif request.status_code != 200:
883
+ raise Exception(f"Unexpected status code {request.status_code}")
884
+ self.etags[url] = request.headers["ETag"]
885
+ uv_reports = json.loads(request.text)["content"]
886
+ # Match with existing stations
887
+ for uv_report in uv_reports:
888
+ station = get_station_by_name(
889
+ self.uv_index_stations_reference_names[uv_report["city"]]
890
+ )
891
+ # uv_report.update({"lat": station[1]["lat"], "lon": station[1]["lon"]})
892
+ self.uv_reports[station[0]] = uv_report
893
+ except Exception as error:
894
+ print(f"Error in download_weather_report: {type(error)} args: {error.args}")
870
895
 
871
896
  def download_weather_report(self, region_code):
872
897
  url = f"https://www.dwd.de/DWD/wetter/wv_allg/deutschland/text/vhdl13_{region_code}.html"
@@ -874,16 +899,19 @@ class Weather:
874
899
  "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
900
  }
876
901
  headers["If-None-Match"] = self.etags[url] if url in self.etags else ""
877
- request = requests.get(url, headers=headers)
878
- # If resource has not been modified, return
879
- if request.status_code == 304:
880
- return
881
- self.etags[url] = request.headers["ETag"]
882
- weather_report = request.text
883
- a = weather_report.find(">")
884
- if a != -1:
885
- weather_report = weather_report[a + 1 :]
886
- self.weather_report = weather_report
902
+ try:
903
+ request = requests.get(url, headers=headers, timeout=30)
904
+ # If resource has not been modified, return
905
+ if request.status_code == 304:
906
+ return
907
+ self.etags[url] = request.headers["ETag"]
908
+ weather_report = request.text
909
+ a = weather_report.find(">")
910
+ if a != -1:
911
+ weather_report = weather_report[a + 1 :]
912
+ self.weather_report = weather_report
913
+ except Exception as error:
914
+ print(f"Error in download_weather_report: {type(error)} args: {error.args}")
887
915
 
888
916
  def download_latest_kml(self, stationid, force_hourly=False):
889
917
  if force_hourly:
@@ -891,15 +919,18 @@ class Weather:
891
919
  else:
892
920
  url = f"https://opendata.dwd.de/weather/local_forecasts/mos/MOSMIX_L/single_stations/{stationid}/kml/MOSMIX_L_LATEST_{stationid}.kmz"
893
921
  headers = {"If-None-Match": self.etags[url] if url in self.etags else ""}
894
- request = requests.get(url, headers=headers)
895
- # If resource has not been modified, return
896
- if request.status_code == 304:
897
- return
898
- self.etags[url] = request.headers["ETag"]
899
- with ZipFile(BytesIO(request.content), "r") as kmz:
900
- # large RAM allocation
901
- with kmz.open(kmz.namelist()[0], "r") as kml:
902
- self.parse_kml(kml, force_hourly)
922
+ try:
923
+ request = requests.get(url, headers=headers, timeout=30)
924
+ # If resource has not been modified, return
925
+ if request.status_code == 304:
926
+ return
927
+ self.etags[url] = request.headers["ETag"]
928
+ with ZipFile(BytesIO(request.content), "r") as kmz:
929
+ # large RAM allocation
930
+ with kmz.open(kmz.namelist()[0], "r") as kml:
931
+ self.parse_kml(kml, force_hourly)
932
+ except Exception as error:
933
+ print(f"Error in download_weather_report: {type(error)} args: {error.args}")
903
934
 
904
935
  def download_latest_report(self):
905
936
  station_id = self.station_id
@@ -909,38 +940,43 @@ class Weather:
909
940
  f"https://opendata.dwd.de/weather/weather_reports/poi/{station_id}-BEOB.csv"
910
941
  )
911
942
  headers = {"If-None-Match": self.etags[url] if url in self.etags else ""}
912
- response = requests.get(url, headers=headers)
913
- if response.status_code == 200:
914
- content = response.content
915
- reader = csv.DictReader(content.decode("utf-8").splitlines(), delimiter=";")
916
- is_first_run = True
917
- backuprows = []
918
- for row in reader:
919
- if is_first_run:
920
- is_first_run = False
921
- reader.__next__()
922
- continue
923
- backuprows.append(reader.__next__())
924
- backuprows.append(reader.__next__())
925
- backuprows.append(reader.__next__())
926
-
927
- # Some items are only reported each hour
928
- for backuprow in backuprows:
929
- if row["cloud_cover_total"] == self.NOT_AVAILABLE:
930
- row["cloud_cover_total"] = backuprow["cloud_cover_total"]
931
- if row["horizontal_visibility"] == self.NOT_AVAILABLE:
932
- row["horizontal_visibility"] = backuprow[
933
- "horizontal_visibility"
934
- ]
935
- if row["present_weather"] == self.NOT_AVAILABLE:
936
- row["present_weather"] = backuprow["present_weather"]
937
- self.parse_csv_row(row)
938
- # We only want the latest report
939
- break
940
-
941
- elif response.status_code == 304:
942
- # The report is already up to date
943
- print("Report is already up to date")
944
- else:
945
- # Handle other status codes
946
- print(f"Failed to download report. Status code: {response.status_code}")
943
+ try:
944
+ response = requests.get(url, headers=headers, timeout=30)
945
+ if response.status_code == 200:
946
+ content = response.content
947
+ reader = csv.DictReader(
948
+ content.decode("utf-8").splitlines(), delimiter=";"
949
+ )
950
+ is_first_run = True
951
+ backuprows = []
952
+ for row in reader:
953
+ if is_first_run:
954
+ is_first_run = False
955
+ reader.__next__()
956
+ continue
957
+ backuprows.append(reader.__next__())
958
+ backuprows.append(reader.__next__())
959
+ backuprows.append(reader.__next__())
960
+
961
+ # Some items are only reported each hour
962
+ for backuprow in backuprows:
963
+ if row["cloud_cover_total"] == self.NOT_AVAILABLE:
964
+ row["cloud_cover_total"] = backuprow["cloud_cover_total"]
965
+ if row["horizontal_visibility"] == self.NOT_AVAILABLE:
966
+ row["horizontal_visibility"] = backuprow[
967
+ "horizontal_visibility"
968
+ ]
969
+ if row["present_weather"] == self.NOT_AVAILABLE:
970
+ row["present_weather"] = backuprow["present_weather"]
971
+ self.parse_csv_row(row)
972
+ # We only want the latest report
973
+ break
974
+
975
+ elif response.status_code == 304:
976
+ # The report is already up to date
977
+ print("Report is already up to date")
978
+ else:
979
+ # Handle other status codes
980
+ print(f"Failed to download report. Status code: {response.status_code}")
981
+ except Exception as error:
982
+ print(f"Error in download_weather_report: {type(error)} args: {error.args}")
@@ -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.29
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
@@ -1,17 +1,18 @@
1
1
  simple_dwd_weatherforecast/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- simple_dwd_weatherforecast/dwdforecast.py,sha256=2yhMV4qXs8MllvL6vDXHGV20TX5811IrkjL7FnpR6Wg,33831
3
- simple_dwd_weatherforecast/dwdmap.py,sha256=bFAZfYjUryZkErJ3aDNRm9ZhNwKGMcy4pEl8TnWJKzA,2476
2
+ simple_dwd_weatherforecast/dwdforecast.py,sha256=45-nCx_amQE0lQH31aSZGYc51Va5AabKGN4OhfAkuPQ,35474
3
+ simple_dwd_weatherforecast/dwdmap.py,sha256=k6TTTMO6Db-qhaZhZwGssmYM5R9GUFcNxg4J8a3_J78,2684
4
4
  simple_dwd_weatherforecast/stations.json,sha256=1u8qc2CT_rVy49SAlOicGixzHln6Y0FXevuFAz2maBw,838948
5
5
  simple_dwd_weatherforecast/uv_stations.json,sha256=ADenYo-aR6qbf0UFkfYr72kkFzL9HyUKe4VQ23POGF8,2292
6
6
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  tests/dummy_data.py,sha256=sF8pXxq8innSpRc4lW0XxGcr34dESSAoBdAf2F2D4AI,63395
8
8
  tests/dummy_data_full.py,sha256=IwYoeqVX8cpfn_gE-7arXaWV9btRm_HHqka_LfKqW-E,64053
9
9
  tests/dummy_uv.py,sha256=TM1TwvNq_ea4WgIJyYsNAEXZJTx1dXH1ZVrW_LfLBLg,4548
10
+ tests/test_get_daily_avg.py,sha256=ZD4mT7HLjzsFnb0DOLbi4U3sGMOCBSj49WYVbNGN7GQ,1997
10
11
  tests/test_get_daily_condition.py,sha256=J_0gg9fejPqESP7Np5wl5kr7wwcm04a-G1Txx4JH02g,2043
11
12
  tests/test_get_daily_max.py,sha256=vC873a1Uuw01a61fkvV0XKwTnkxJWkrOycTOSLrOp9Q,1940
12
13
  tests/test_get_daily_min.py,sha256=jYgPK-dK7P_QRBe1oNlSSZlnd-BrTDXGt5AfS-sEThw,1944
13
- tests/test_get_daily_sum.py,sha256=WeOVXl905X-n5gnPuNM6ut-q9VeBM2j2f6heBDol3Ok,1942
14
- tests/test_get_day_values.py,sha256=zn9GaLnsLA_rvk6pNApmR9ZHD_OsElU01T6oFJiqL7I,28680
14
+ tests/test_get_daily_sum.py,sha256=sViAjOq7IHs057Zr9zz36brZyFbckdasmHk1YluRNBc,1941
15
+ tests/test_get_day_values.py,sha256=iNVGP7roy5R5jGTvJNUHAIefSlXI4NBFnYVsr-WLECs,29348
15
16
  tests/test_get_forecast_condition.py,sha256=mawVIJ7xQgH9Xbz_nLnAHNS5Ib-mp-A3zLbkEllw2hw,2904
16
17
  tests/test_get_forecast_data.py,sha256=dsKtfGTlQbhB7tteBuB6d_RHEOtM7ikfVWh_Fk-CtyU,3432
17
18
  tests/test_get_station_name.py,sha256=58fBETHAgDaTAsAFP9xOcYfipNO-AqUf_n_bMj5FwWc,439
@@ -34,8 +35,8 @@ tests/test_update.py,sha256=JMdlN_lc9Zb58yU4GNrO_sOaKN9pZEx8nt4E2UeKBi0,7254
34
35
  tests/test_update_hourly.py,sha256=Zx0e_E2n2Wi1yGMDN6TURzIbk_xVYaMc-7IDK1sC5UY,1668
35
36
  tests/test_uv_index.py,sha256=tr6wnOyHlXT1S3yp1oeHc4-Brmc-EMEdM4mtyrdpcHg,579
36
37
  tests/test_weather.py,sha256=U4FkTtqLcLs8k-xy6YKNM_4HVscITymURCEIUShk6iE,802
37
- simple_dwd_weatherforecast-2.0.29.dist-info/LICENCE,sha256=27UG7gteqvSWuZlsbIq2_OAbh7VyifGGl-1zpuUoBcw,1072
38
- simple_dwd_weatherforecast-2.0.29.dist-info/METADATA,sha256=o5uk2kAj9w8j32s8wA6cKR2Q8JNZ0D7jZhtBT8GzaFE,10800
39
- simple_dwd_weatherforecast-2.0.29.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
40
- simple_dwd_weatherforecast-2.0.29.dist-info/top_level.txt,sha256=iyEobUh14Tzitx39Oi8qm0NhBrnZovl_dNKtvLUkLEM,33
41
- simple_dwd_weatherforecast-2.0.29.dist-info/RECORD,,
38
+ simple_dwd_weatherforecast-2.0.32.dist-info/LICENCE,sha256=27UG7gteqvSWuZlsbIq2_OAbh7VyifGGl-1zpuUoBcw,1072
39
+ simple_dwd_weatherforecast-2.0.32.dist-info/METADATA,sha256=o3F9zUnLganqA2_Sue4bhUjktjMePFwFw9YAjDD5lFU,10937
40
+ simple_dwd_weatherforecast-2.0.32.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
41
+ simple_dwd_weatherforecast-2.0.32.dist-info/top_level.txt,sha256=iyEobUh14Tzitx39Oi8qm0NhBrnZovl_dNKtvLUkLEM,33
42
+ simple_dwd_weatherforecast-2.0.32.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (71.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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)