simple-dwd-weatherforecast 2.1.17__py3-none-any.whl → 3.0.0__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.
@@ -9,7 +9,7 @@ from datetime import datetime, timedelta, timezone
9
9
 
10
10
 
11
11
  class WeatherMapType(Enum):
12
- NIEDERSCHLAGSRADAR = "dwd:Niederschlagsradar"
12
+ NIEDERSCHLAGSRADAR = "dwd:Radar_rv_product_1x1km_ger"
13
13
  BLITZSCHLAG = "dwd:NCEW_EU"
14
14
  MAXTEMP = "dwd:GefuehlteTempMax"
15
15
  UVINDEX = "dwd:UVI_CS"
@@ -85,8 +85,10 @@ def get_from_location(
85
85
  longitude,
86
86
  latitude,
87
87
  radius_km,
88
- map_type: WeatherMapType,
89
- background_type: WeatherBackgroundMapType = WeatherBackgroundMapType.BUNDESLAENDER,
88
+ map_types: list[WeatherMapType],
89
+ background_types: list[WeatherBackgroundMapType] = [
90
+ WeatherBackgroundMapType.BUNDESLAENDER
91
+ ],
90
92
  image_width=520,
91
93
  image_height=580,
92
94
  markers: list[Marker] = [],
@@ -104,8 +106,8 @@ def get_from_location(
104
106
  latitude - radius,
105
107
  longitude + radius,
106
108
  latitude + radius,
107
- map_type,
108
- background_type,
109
+ map_types,
110
+ background_types,
109
111
  image_width,
110
112
  image_height,
111
113
  markers,
@@ -114,8 +116,10 @@ def get_from_location(
114
116
 
115
117
 
116
118
  def get_germany(
117
- map_type: WeatherMapType,
118
- background_type: WeatherBackgroundMapType = WeatherBackgroundMapType.BUNDESLAENDER,
119
+ map_types: list[WeatherMapType],
120
+ background_types: list[WeatherBackgroundMapType] = [
121
+ WeatherBackgroundMapType.BUNDESLAENDER
122
+ ],
119
123
  image_width=520,
120
124
  image_height=580,
121
125
  markers: list[Marker] = [],
@@ -126,8 +130,8 @@ def get_germany(
126
130
  germany_boundaries.miny,
127
131
  germany_boundaries.maxx,
128
132
  germany_boundaries.maxy,
129
- map_type,
130
- background_type,
133
+ map_types,
134
+ background_types,
131
135
  image_width,
132
136
  image_height,
133
137
  markers,
@@ -140,8 +144,8 @@ def get_map(
140
144
  miny,
141
145
  maxx,
142
146
  maxy,
143
- map_type: WeatherMapType,
144
- background_type: WeatherBackgroundMapType,
147
+ map_types: list[WeatherMapType],
148
+ background_types: list[WeatherBackgroundMapType],
145
149
  image_width=520,
146
150
  image_height=580,
147
151
  markers: list[Marker] = [],
@@ -151,15 +155,36 @@ def get_map(
151
155
  raise ValueError(
152
156
  "Width and height must not exceed 1200 and 1400 respectively. Please be kind to the DWD servers."
153
157
  )
154
- if background_type in [
155
- WeatherBackgroundMapType.SATELLIT,
156
- WeatherBackgroundMapType.KREISE,
157
- WeatherBackgroundMapType.GEMEINDEN,
158
- ]:
159
- layers = f"{background_type.value}, {map_type.value}"
160
- else:
161
- layers = f"{map_type.value}, {background_type.value}"
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"
158
+ # Separate special layers and others for background types
159
+ special_layers = [
160
+ layer.value
161
+ for layer in background_types
162
+ if layer
163
+ in [
164
+ WeatherBackgroundMapType.SATELLIT,
165
+ WeatherBackgroundMapType.KREISE,
166
+ WeatherBackgroundMapType.GEMEINDEN,
167
+ ]
168
+ ]
169
+ other_layers = [
170
+ layer.value
171
+ for layer in background_types
172
+ if layer
173
+ not in [
174
+ WeatherBackgroundMapType.SATELLIT,
175
+ WeatherBackgroundMapType.KREISE,
176
+ WeatherBackgroundMapType.GEMEINDEN,
177
+ ]
178
+ ]
179
+ # Combine map types into a single string
180
+ map_layers = ",".join(map_type.value for map_type in map_types)
181
+ # Combine layers with special layers first, then map types, then other layers
182
+ layers = f"{','.join(special_layers)},{map_layers},{','.join(other_layers)}".lstrip(
183
+ ","
184
+ )
185
+
186
+ url = f"https://maps.dwd.de/geoserver/dwd/wms?service=WMS&version=1.3.0&request=GetMap&layers={layers}&bbox={miny},{minx},{maxy},{maxx}&width={image_width}&height={image_height}&srs=EPSG:4326&styles=&format=image/png"
187
+ print(url)
163
188
  request = requests.get(url, stream=True)
164
189
  if request.status_code == 200:
165
190
  image = Image.open(BytesIO(request.content))
@@ -187,8 +212,8 @@ class ImageLoop:
187
212
  _miny: float
188
213
  _maxx: float
189
214
  _maxy: float
190
- _map_type: WeatherMapType
191
- _background_type: WeatherBackgroundMapType
215
+ _map_types: list[WeatherMapType]
216
+ _background_types: list[WeatherBackgroundMapType]
192
217
  _image_width: int
193
218
  _image_height: int
194
219
 
@@ -198,14 +223,16 @@ class ImageLoop:
198
223
  miny: float,
199
224
  maxx: float,
200
225
  maxy: float,
201
- map_type: WeatherMapType,
202
- background_type: WeatherBackgroundMapType,
226
+ map_types: list[WeatherMapType],
227
+ background_types: list[WeatherBackgroundMapType],
203
228
  steps: int = 6,
204
229
  image_width: int = 520,
205
230
  image_height: int = 580,
206
231
  markers: list[Marker] = [],
207
232
  dark_mode: bool = False,
208
233
  ):
234
+ if WeatherMapType.NIEDERSCHLAGSRADAR not in map_types:
235
+ raise ValueError("Only NIEDERSCHLAGSRADAR is supported in a loop")
209
236
  if image_width > 1200 or image_height > 1400:
210
237
  raise ValueError(
211
238
  "Width and height must not exceed 1200 and 1400 respectively. Please be kind to the DWD servers."
@@ -214,10 +241,8 @@ class ImageLoop:
214
241
  self._miny = miny
215
242
  self._maxx = maxx
216
243
  self._maxy = maxy
217
- if map_type != WeatherMapType.NIEDERSCHLAGSRADAR:
218
- raise ValueError("Only NIEDERSCHLAGSRADAR is supported in a loop")
219
- self._map_type = map_type
220
- self._background_type = background_type
244
+ self._map_types = map_types
245
+ self._background_types = background_types
221
246
  self._steps = steps
222
247
  self._image_width = image_width
223
248
  self._image_height = image_height
@@ -267,20 +292,39 @@ class ImageLoop:
267
292
  date: datetime,
268
293
  with_lightning: bool = False,
269
294
  ) -> ImageFile.ImageFile:
270
- # Lightning in the NCEW_EU layer is only available in the last 5 minutes
271
- layer = self._map_type.value
295
+ # Combine map types into a single string
296
+ map_layers = ",".join(map_type.value for map_type in self._map_types)
272
297
  if with_lightning:
273
- layer += ",dwd:NCEW_EU"
274
- if self._background_type in [
275
- WeatherBackgroundMapType.SATELLIT,
276
- WeatherBackgroundMapType.KREISE,
277
- WeatherBackgroundMapType.GEMEINDEN,
278
- ]:
279
- layers = f"{self._background_type.value}, {layer}"
280
- else:
281
- layers = f"{layer}, {self._background_type.value}"
282
-
283
- 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')}"
298
+ map_layers += ",dwd:NCEW_EU"
299
+ # Separate special layers and others for background types
300
+ special_layers = [
301
+ layer.value
302
+ for layer in self._background_types
303
+ if layer
304
+ in [
305
+ WeatherBackgroundMapType.SATELLIT,
306
+ WeatherBackgroundMapType.KREISE,
307
+ WeatherBackgroundMapType.GEMEINDEN,
308
+ ]
309
+ ]
310
+ other_layers = [
311
+ layer.value
312
+ for layer in self._background_types
313
+ if layer
314
+ not in [
315
+ WeatherBackgroundMapType.SATELLIT,
316
+ WeatherBackgroundMapType.KREISE,
317
+ WeatherBackgroundMapType.GEMEINDEN,
318
+ ]
319
+ ]
320
+ # Combine layers with special layers first, then map types, then other layers
321
+ layers = (
322
+ f"{','.join(special_layers)},{map_layers},{','.join(other_layers)}".lstrip(
323
+ ","
324
+ )
325
+ )
326
+ url = f"https://maps.dwd.de/geoserver/dwd/wms?service=WMS&version=1.3.0&request=GetMap&layers={layers}&bbox={self._miny},{self._minx},{self._maxy},{self._maxx}&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')}"
327
+ print(url)
284
328
  request = requests.get(url, stream=True)
285
329
  if request.status_code != 200 or request.headers["content-type"] != "image/png":
286
330
  raise ConnectionError("Error during image request from DWD servers")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simple_dwd_weatherforecast
3
- Version: 2.1.17
3
+ Version: 3.0.0
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
@@ -227,11 +227,11 @@ class Marker(
227
227
  width: int = 0,
228
228
  )
229
229
 
230
- 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
230
+ 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
231
231
 
232
- 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
232
+ 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
233
233
 
234
- 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
234
+ 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
235
235
  ```
236
236
 
237
237
 
@@ -249,8 +249,8 @@ maploop = dwdmap.ImageLoop(
249
249
  dwdmap.germany_boundaries.miny,
250
250
  dwdmap.germany_boundaries.maxx,
251
251
  dwdmap.germany_boundaries.maxy,
252
- dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR,
253
- dwdmap.WeatherBackgroundMapType.BUNDESLAENDER,
252
+ [dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR],
253
+ [dwdmap.WeatherBackgroundMapType.BUNDESLAENDER],
254
254
  steps=5,
255
255
  )
256
256
 
@@ -262,7 +262,7 @@ for image in enumerate(maploop._images):
262
262
  #### Available methods
263
263
 
264
264
  ```python
265
- ImageLoop(minx: float, miny: float, maxx: float, maxy: float, map_type: WeatherMapType, background_type: WeatherBackgroundMapType,
265
+ ImageLoop(minx: float, miny: float, maxx: float, maxy: float, map_type: [WeatherMapType], background_type: [WeatherBackgroundMapType],
266
266
  steps: int = 6, image_width: int = 520,image_height: int = 580, markers: list[Marker] = [], optional bool dark_mode) -> ImageLoop
267
267
 
268
268
  get_images() -> Iterable[ImageFile.ImageFile] # Returns the image loop
@@ -1,9 +1,9 @@
1
1
  simple_dwd_weatherforecast/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  simple_dwd_weatherforecast/dwdforecast.py,sha256=uZRWMN9RIPvC9r47JAdw_AiP9V9M2rQxh_pOsVF15Sw,39094
3
- simple_dwd_weatherforecast/dwdmap.py,sha256=H7W5_J91IbFbx9s8OZxvoNsJxc3mKITBZVU8EldMjjI,12720
3
+ simple_dwd_weatherforecast/dwdmap.py,sha256=qy5RLp_WcuyhCOyypab9vP9qSpO4omoi-dPFLZ0kVBc,14096
4
4
  simple_dwd_weatherforecast/stations.json,sha256=1u8qc2CT_rVy49SAlOicGixzHln6Y0FXevuFAz2maBw,838948
5
5
  simple_dwd_weatherforecast/uv_stations.json,sha256=ADenYo-aR6qbf0UFkfYr72kkFzL9HyUKe4VQ23POGF8,2292
6
- simple_dwd_weatherforecast-2.1.17.dist-info/licenses/LICENCE,sha256=27UG7gteqvSWuZlsbIq2_OAbh7VyifGGl-1zpuUoBcw,1072
6
+ simple_dwd_weatherforecast-3.0.0.dist-info/licenses/LICENCE,sha256=27UG7gteqvSWuZlsbIq2_OAbh7VyifGGl-1zpuUoBcw,1072
7
7
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  tests/dummy_data.py,sha256=qapeQxjh8kURf5b-9h4gUdJaqQJQDVdqfMtS2g5JReY,103406
9
9
  tests/dummy_data_full.py,sha256=3HRGAQBq4xPYs4jLzoLV_UAe1CXFzOsVBOouDL_5RHw,104062
@@ -26,7 +26,7 @@ tests/test_get_timeframe_values.py,sha256=D9NJ98sZykLKAW1eZgLFuy0FMb4f_jUCtr4clz
26
26
  tests/test_is_in_timerange.py,sha256=3y88L3N73NxSTJ-_edx6OCnxHWKJWWFma98gjZvJDGg,1338
27
27
  tests/test_is_valid_timeframe.py,sha256=mXjeu3lUyixiBUEljirTf6qDM_FZFQGWa-Rk0NBMUDU,891
28
28
  tests/test_location_tools.py,sha256=wto_XzVnARJQ-Qc83YAn0ahfMBSaOHpfzqAeKRDsNm8,1208
29
- tests/test_map.py,sha256=uKxNjMXLFT3pczZKLqkfPK5xaVfmql-r5L9VPgCbS3Q,5671
29
+ tests/test_map.py,sha256=X4zFmnoE7YzT6UudE0TtFmsBwhlrRP5C1p8K70_0yTg,5701
30
30
  tests/test_parsekml.py,sha256=aG98x3B409CqxKBIq50yf3_LxPROnI4CAhdKfp350uQ,1495
31
31
  tests/test_region.py,sha256=ReUB9Cy9roBemkpEkTjZZav-Mu3Ha7ADOAfa9J-gi80,877
32
32
  tests/test_reported_weather.py,sha256=ULg4ogZRxus01p2rdxiSFL75AisqtcvnLDOc7uJMBH0,767
@@ -36,7 +36,7 @@ tests/test_update.py,sha256=AIzzHMxcjwQjeTB0l3YFgB7HkGDbuqiHofwy41mS0m4,7440
36
36
  tests/test_update_hourly.py,sha256=7Zl8ml3FTdqw3_Qwr_Tz-sWTzypvrBWmxeig2Vwp_ZQ,1781
37
37
  tests/test_uv_index.py,sha256=tr6wnOyHlXT1S3yp1oeHc4-Brmc-EMEdM4mtyrdpcHg,579
38
38
  tests/test_weather.py,sha256=ZyX4ldUoJpJp7YpiNQwU6Od-nYRay-3qcaDJdNq8fhY,780
39
- simple_dwd_weatherforecast-2.1.17.dist-info/METADATA,sha256=aMMWbvdYlkKr0QNj5gsD_mRNufHZrjXOizxF20TtiHU,12850
40
- simple_dwd_weatherforecast-2.1.17.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
41
- simple_dwd_weatherforecast-2.1.17.dist-info/top_level.txt,sha256=iyEobUh14Tzitx39Oi8qm0NhBrnZovl_dNKtvLUkLEM,33
42
- simple_dwd_weatherforecast-2.1.17.dist-info/RECORD,,
39
+ simple_dwd_weatherforecast-3.0.0.dist-info/METADATA,sha256=N4jyf6cS2laZrwPKQBYGFBj7tyXshpMKBmkAQhKalnc,12869
40
+ simple_dwd_weatherforecast-3.0.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
41
+ simple_dwd_weatherforecast-3.0.0.dist-info/top_level.txt,sha256=iyEobUh14Tzitx39Oi8qm0NhBrnZovl_dNKtvLUkLEM,33
42
+ simple_dwd_weatherforecast-3.0.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (77.0.3)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
tests/test_map.py CHANGED
@@ -38,8 +38,8 @@ class MapTestCase(unittest.TestCase):
38
38
  46.4,
39
39
  16.1,
40
40
  55.6,
41
- dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR,
42
- dwdmap.WeatherBackgroundMapType.BUNDESLAENDER,
41
+ [dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR],
42
+ [dwdmap.WeatherBackgroundMapType.BUNDESLAENDER],
43
43
  1300,
44
44
  1700,
45
45
  )
@@ -53,8 +53,8 @@ class ImageLoopTestCase(unittest.TestCase):
53
53
  0.2,
54
54
  0.3,
55
55
  0.4,
56
- dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR,
57
- dwdmap.WeatherBackgroundMapType.BUNDESLAENDER,
56
+ [dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR],
57
+ [dwdmap.WeatherBackgroundMapType.BUNDESLAENDER],
58
58
  1,
59
59
  )
60
60
  self.assertEqual(
@@ -74,12 +74,12 @@ class ImageLoopTestCase(unittest.TestCase):
74
74
  0.4,
75
75
  )
76
76
  self.assertEqual(
77
- maploop._map_type,
78
- dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR,
77
+ maploop._map_types,
78
+ [dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR],
79
79
  )
80
80
  self.assertEqual(
81
- maploop._background_type,
82
- dwdmap.WeatherBackgroundMapType.BUNDESLAENDER,
81
+ maploop._background_types,
82
+ [dwdmap.WeatherBackgroundMapType.BUNDESLAENDER],
83
83
  )
84
84
  mock_function.assert_called_once()
85
85
 
@@ -90,8 +90,8 @@ class ImageLoopTestCase(unittest.TestCase):
90
90
  0.2,
91
91
  0.3,
92
92
  0.4,
93
- dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR,
94
- dwdmap.WeatherBackgroundMapType.BUNDESLAENDER,
93
+ [dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR],
94
+ [dwdmap.WeatherBackgroundMapType.BUNDESLAENDER],
95
95
  5,
96
96
  )
97
97
  self.assertEqual(mock_function.call_count, 5)
@@ -103,8 +103,8 @@ class ImageLoopTestCase(unittest.TestCase):
103
103
  0.2,
104
104
  0.3,
105
105
  0.4,
106
- dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR,
107
- dwdmap.WeatherBackgroundMapType.BUNDESLAENDER,
106
+ [dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR],
107
+ [dwdmap.WeatherBackgroundMapType.BUNDESLAENDER],
108
108
  10,
109
109
  )
110
110
  self.assertEqual(mock_function.call_count, 10)
@@ -116,8 +116,8 @@ class ImageLoopTestCase(unittest.TestCase):
116
116
  0.2,
117
117
  0.3,
118
118
  0.4,
119
- dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR,
120
- dwdmap.WeatherBackgroundMapType.BUNDESLAENDER,
119
+ [dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR],
120
+ [dwdmap.WeatherBackgroundMapType.BUNDESLAENDER],
121
121
  5,
122
122
  )
123
123
  maploop._last_update = datetime(year=2024, month=9, day=4, hour=5, minute=50)
@@ -130,8 +130,8 @@ class ImageLoopTestCase(unittest.TestCase):
130
130
  0.2,
131
131
  0.3,
132
132
  0.4,
133
- dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR,
134
- dwdmap.WeatherBackgroundMapType.BUNDESLAENDER,
133
+ [dwdmap.WeatherMapType.NIEDERSCHLAGSRADAR],
134
+ [dwdmap.WeatherBackgroundMapType.BUNDESLAENDER],
135
135
  5,
136
136
  )
137
137
  now = dwdmap.get_time_last_5_min(datetime.now(timezone.utc))