simple-dwd-weatherforecast 2.1.13__py3-none-any.whl → 2.1.15__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.
@@ -757,9 +757,13 @@ class Weather:
757
757
  return issue_time_new
758
758
 
759
759
  def parse_station_name(self, tree):
760
- return tree.xpath(
760
+ parsed_name = tree.xpath(
761
761
  "./kml:Document/kml:Placemark/kml:description", namespaces=self.namespaces
762
- )[0].text
762
+ )
763
+ if len(parsed_name) == 0:
764
+ return None
765
+ else:
766
+ return parsed_name[0].text
763
767
 
764
768
  def parse_timesteps(self, tree):
765
769
  return [
@@ -9,7 +9,8 @@ from datetime import datetime, timedelta, timezone
9
9
 
10
10
 
11
11
  class WeatherMapType(Enum):
12
- NIEDERSCHLAGSRADAR = "dwd:Niederschlagsradar,dwd:NCEW_EU"
12
+ NIEDERSCHLAGSRADAR = "dwd:Niederschlagsradar"
13
+ BLITZSCHLAG = "dwd:NCEW_EU"
13
14
  MAXTEMP = "dwd:GefuehlteTempMax"
14
15
  UVINDEX = "dwd:UVI_CS"
15
16
  POLLENFLUG = "dwd:Pollenflug"
@@ -89,6 +90,7 @@ def get_from_location(
89
90
  image_width=520,
90
91
  image_height=580,
91
92
  markers: list[Marker] = [],
93
+ dark_mode: bool = False,
92
94
  ):
93
95
  if radius_km <= 0:
94
96
  raise ValueError("Radius must be greater than 0")
@@ -107,6 +109,7 @@ def get_from_location(
107
109
  image_width,
108
110
  image_height,
109
111
  markers,
112
+ dark_mode,
110
113
  )
111
114
 
112
115
 
@@ -116,6 +119,7 @@ def get_germany(
116
119
  image_width=520,
117
120
  image_height=580,
118
121
  markers: list[Marker] = [],
122
+ dark_mode: bool = False,
119
123
  ):
120
124
  return get_map(
121
125
  germany_boundaries.minx,
@@ -127,6 +131,7 @@ def get_germany(
127
131
  image_width,
128
132
  image_height,
129
133
  markers,
134
+ dark_mode,
130
135
  )
131
136
 
132
137
 
@@ -140,6 +145,7 @@ def get_map(
140
145
  image_width=520,
141
146
  image_height=580,
142
147
  markers: list[Marker] = [],
148
+ dark_mode: bool = False,
143
149
  ):
144
150
  if image_width > 1200 or image_height > 1400:
145
151
  raise ValueError(
@@ -153,10 +159,20 @@ def get_map(
153
159
  layers = f"{background_type.value}, {map_type.value}"
154
160
  else:
155
161
  layers = f"{map_type.value}, {background_type.value}"
156
- 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"
162
+ url = f"https://maps.dwd.de/geoserver/dwd/wms?service=WMS&version=1.1.1&request=GetMap&layers={layers}&bbox={minx},{miny},{maxx},{maxy}&width={image_width}&height={image_height}&srs=EPSG:4326&styles=&format=image/png"
157
163
  request = requests.get(url, stream=True)
158
164
  if request.status_code == 200:
159
165
  image = Image.open(BytesIO(request.content))
166
+ if dark_mode:
167
+ new_image_data = []
168
+ for item in image.getdata(): # type: ignore
169
+ if item[0] == 255 and item[1] == 255 and item[2] == 255:
170
+ new_image_data.append((0, 0, 0))
171
+ else:
172
+ new_image_data.append(item)
173
+
174
+ # update image data
175
+ image.putdata(new_image_data)
160
176
  image = draw_marker(image, ImageBoundaries(minx, maxx, miny, maxy), markers)
161
177
  return image
162
178
 
@@ -186,6 +202,7 @@ class ImageLoop:
186
202
  image_width: int = 520,
187
203
  image_height: int = 580,
188
204
  markers: list[Marker] = [],
205
+ dark_mode: bool = False,
189
206
  ):
190
207
  if image_width > 1200 or image_height > 1400:
191
208
  raise ValueError(
@@ -203,6 +220,7 @@ class ImageLoop:
203
220
  self._image_width = image_width
204
221
  self._image_height = image_height
205
222
  self.markers = markers
223
+ self.dark_mode = dark_mode
206
224
  self._images = deque([], steps)
207
225
 
208
226
  self._full_reload()
@@ -220,7 +238,13 @@ class ImageLoop:
220
238
 
221
239
  while now > self._last_update:
222
240
  self._last_update += timedelta(minutes=5)
223
- self._images.append(self._get_image(self._last_update))
241
+ # Lightning in the NCEW_EU layer is only available in the last 5 minutes
242
+ self._images.append(
243
+ self._get_image(
244
+ self._last_update,
245
+ with_lightning=(now - self._last_update) < timedelta(minutes=5),
246
+ )
247
+ )
224
248
 
225
249
  def update(self):
226
250
  now = get_time_last_5_min(datetime.now(timezone.utc))
@@ -232,25 +256,43 @@ class ImageLoop:
232
256
  else:
233
257
  while now > self._last_update:
234
258
  self._last_update += timedelta(minutes=5)
235
- self._images.append(self._get_image(self._last_update))
259
+ self._images.append(
260
+ self._get_image(self._last_update, with_lightning=True)
261
+ )
236
262
 
237
263
  def _get_image(
238
264
  self,
239
265
  date: datetime,
266
+ with_lightning: bool = False,
240
267
  ) -> ImageFile.ImageFile:
268
+ # Lightning in the NCEW_EU layer is only available in the last 5 minutes
269
+ layer = self._map_type.value
270
+ if with_lightning:
271
+ layer += ",dwd:NCEW_EU"
241
272
  if self._background_type in [
242
273
  WeatherBackgroundMapType.SATELLIT,
243
274
  WeatherBackgroundMapType.KREISE,
244
275
  WeatherBackgroundMapType.GEMEINDEN,
245
276
  ]:
246
- layers = f"{self._background_type.value}, {self._map_type.value}"
277
+ layers = f"{self._background_type.value}, {layer}"
247
278
  else:
248
- layers = f"{self._map_type.value}, {self._background_type.value}"
249
- 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")}"
279
+ layers = f"{layer}, {self._background_type.value}"
280
+
281
+ url = f"https://maps.dwd.de/geoserver/dwd/wms?service=WMS&version=1.1.1&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')}"
250
282
  request = requests.get(url, stream=True)
251
- if request.status_code != 200:
283
+ if request.status_code != 200 or request.headers["content-type"] != "image/png":
252
284
  raise ConnectionError("Error during image request from DWD servers")
253
285
  image = Image.open(BytesIO(request.content))
286
+ if self.dark_mode:
287
+ new_image_data = []
288
+ for item in image.getdata(): # type: ignore
289
+ if item[0] == 255 and item[1] == 255 and item[2] == 255:
290
+ new_image_data.append((0, 0, 0))
291
+ else:
292
+ new_image_data.append(item)
293
+
294
+ # update image data
295
+ image.putdata(new_image_data)
254
296
  image = draw_marker(
255
297
  image,
256
298
  ImageBoundaries(self._minx, self._maxx, self._miny, self._maxy),
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: simple_dwd_weatherforecast
3
- Version: 2.1.13
3
+ Version: 2.1.15
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
@@ -17,6 +17,14 @@ Requires-Dist: arrow
17
17
  Requires-Dist: stream-inflate==0.0.41
18
18
  Requires-Dist: stream-unzip==0.0.98
19
19
  Requires-Dist: httpx
20
+ Dynamic: author
21
+ Dynamic: classifier
22
+ Dynamic: description
23
+ Dynamic: description-content-type
24
+ Dynamic: home-page
25
+ Dynamic: requires-dist
26
+ Dynamic: requires-python
27
+ Dynamic: summary
20
28
 
21
29
  # Simple DWD weather forecast
22
30
 
@@ -208,7 +216,7 @@ class MarkerShape(Enum):
208
216
  CIRCLE = "circle"
209
217
  SQUARE = "square"
210
218
  CROSS = "cross"
211
-
219
+
212
220
  class Marker(
213
221
  latitude: float,
214
222
  longitude: float,
@@ -218,11 +226,11 @@ class Marker(
218
226
  width: int = 0,
219
227
  )
220
228
 
221
- get_from_location(longitude, latitude, radius_km, map_type: WeatherMapType, background_type: WeatherBackgroundMapType, optional integer image_width, optional integer image_height, optional markers: list[Marker]) #Returns map as pillow image with given radius from coordinates
229
+ get_from_location(longitude, latitude, radius_km, map_type: WeatherMapType, background_type: WeatherBackgroundMapType, optional integer image_width, optional integer image_height, optional markers: list[Marker], optional bool dark_mode) #Returns map as pillow image with given radius from coordinates
222
230
 
223
- get_germany(map_type: WeatherMapType, optional WeatherBackgroundMapType background_type, optional integer image_width, optional integer image_height, optional markers: list[Marker]) #Returns map as pillow image of whole germany
231
+ get_germany(map_type: WeatherMapType, optional WeatherBackgroundMapType background_type, optional integer image_width, optional integer image_height, optional markers: list[Marker], optional bool dark_mode) #Returns map as pillow image of whole germany
224
232
 
225
- get_map(minx,miny,maxx,maxy, map_type: WeatherMapType, background_type: WeatherBackgroundMapType, optional integer image_width, optional integer image_height, optional markers: list[Marker]) #Returns map as pillow image
233
+ get_map(minx,miny,maxx,maxy, map_type: WeatherMapType, background_type: WeatherBackgroundMapType, optional integer image_width, optional integer image_height, optional markers: list[Marker], optional bool dark_mode) #Returns map as pillow image
226
234
  ```
227
235
 
228
236
 
@@ -254,7 +262,7 @@ for image in enumerate(maploop._images):
254
262
 
255
263
  ```python
256
264
  ImageLoop(minx: float, miny: float, maxx: float, maxy: float, map_type: WeatherMapType, background_type: WeatherBackgroundMapType,
257
- steps: int = 6, image_width: int = 520,image_height: int = 580, markers: list[Marker] = []) -> ImageLoop
265
+ steps: int = 6, image_width: int = 520,image_height: int = 580, markers: list[Marker] = [], optional bool dark_mode) -> ImageLoop
258
266
 
259
267
  get_images() -> Iterable[ImageFile.ImageFile] # Returns the image loop
260
268
 
@@ -1,6 +1,6 @@
1
1
  simple_dwd_weatherforecast/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- simple_dwd_weatherforecast/dwdforecast.py,sha256=wYg7XC9_5rb-ITdjoT-bLaBc_AGqii8d6eNEfdbfXtY,38863
3
- simple_dwd_weatherforecast/dwdmap.py,sha256=vN7ePXeLNFHwho9a2I1WONWy7d1588LzvWlEnXsOmFU,10932
2
+ simple_dwd_weatherforecast/dwdforecast.py,sha256=emM_zYQ0fOZhDIDz60yCXN8vCI3Nsp9VKq8tcOn3TZQ,38973
3
+ simple_dwd_weatherforecast/dwdmap.py,sha256=ckDP6MOTfzwvz01gjzkimIreVGUU7WqFV1CRoCQ9Z1k,12452
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
@@ -35,8 +35,8 @@ tests/test_update.py,sha256=AIzzHMxcjwQjeTB0l3YFgB7HkGDbuqiHofwy41mS0m4,7440
35
35
  tests/test_update_hourly.py,sha256=7Zl8ml3FTdqw3_Qwr_Tz-sWTzypvrBWmxeig2Vwp_ZQ,1781
36
36
  tests/test_uv_index.py,sha256=tr6wnOyHlXT1S3yp1oeHc4-Brmc-EMEdM4mtyrdpcHg,579
37
37
  tests/test_weather.py,sha256=ZyX4ldUoJpJp7YpiNQwU6Od-nYRay-3qcaDJdNq8fhY,780
38
- simple_dwd_weatherforecast-2.1.13.dist-info/LICENCE,sha256=27UG7gteqvSWuZlsbIq2_OAbh7VyifGGl-1zpuUoBcw,1072
39
- simple_dwd_weatherforecast-2.1.13.dist-info/METADATA,sha256=5OFufVijUNgbnStrmGtLtaPv6xPxqcQqxykEYSzlNpU,12557
40
- simple_dwd_weatherforecast-2.1.13.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
41
- simple_dwd_weatherforecast-2.1.13.dist-info/top_level.txt,sha256=iyEobUh14Tzitx39Oi8qm0NhBrnZovl_dNKtvLUkLEM,33
42
- simple_dwd_weatherforecast-2.1.13.dist-info/RECORD,,
38
+ simple_dwd_weatherforecast-2.1.15.dist-info/LICENCE,sha256=27UG7gteqvSWuZlsbIq2_OAbh7VyifGGl-1zpuUoBcw,1072
39
+ simple_dwd_weatherforecast-2.1.15.dist-info/METADATA,sha256=oviCLdT52WLFTVsqHpP6Uc2kEgiGCBI1-S86D04kVj8,12828
40
+ simple_dwd_weatherforecast-2.1.15.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
41
+ simple_dwd_weatherforecast-2.1.15.dist-info/top_level.txt,sha256=iyEobUh14Tzitx39Oi8qm0NhBrnZovl_dNKtvLUkLEM,33
42
+ simple_dwd_weatherforecast-2.1.15.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.5.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5