env-canada 0.6.2__py3-none-any.whl → 0.7.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.
env_canada/constants.py CHANGED
@@ -1 +1 @@
1
- USER_AGENT = "env_canada/0.6.2"
1
+ USER_AGENT = "env_canada/0.7.0"
env_canada/ec_radar.py CHANGED
@@ -157,16 +157,12 @@ class ECRadar(object):
157
157
  # Get overlay parameters
158
158
 
159
159
  self.show_legend = kwargs["legend"]
160
- if self.show_legend:
161
- self.legend_layer = None
162
- self.legend_image = None
163
- self.legend_position = None
160
+ self.legend_layer = None
161
+ self.legend_image = None
162
+ self.legend_position = None
164
163
 
165
164
  self.show_timestamp = kwargs["timestamp"]
166
- if self.show_timestamp:
167
- self.font = ImageFont.load(
168
- os.path.join(os.path.dirname(__file__), "10x20.pil")
169
- )
165
+ self.font = None
170
166
 
171
167
  @property
172
168
  def precip_type(self):
@@ -198,22 +194,20 @@ class ECRadar(object):
198
194
  async with ClientSession(raise_for_status=True) as session:
199
195
  response = await session.get(url=basemap_url, params=basemap_params)
200
196
  base_bytes = await response.read()
201
- self.map_image = Image.open(BytesIO(base_bytes)).convert("RGBA")
202
197
 
203
198
  except ClientConnectorError as e:
204
199
  logging.warning("NRCan base map could not be retrieved: %s" % e)
205
-
206
200
  try:
207
201
  async with ClientSession(raise_for_status=True) as session:
208
202
  response = await session.get(
209
203
  url=backup_map_url, params=basemap_params
210
204
  )
211
205
  base_bytes = await response.read()
212
- self.map_image = Image.open(BytesIO(base_bytes)).convert("RGBA")
213
206
  except ClientConnectorError:
214
207
  logging.warning("Mapbox base map could not be retrieved")
208
+ return None
215
209
 
216
- return
210
+ return base_bytes
217
211
 
218
212
  async def _get_legend(self):
219
213
  """Fetch legend image."""
@@ -222,13 +216,13 @@ class ECRadar(object):
222
216
  layer=precip_layers[self.layer_key], style=legend_style[self.layer_key]
223
217
  )
224
218
  )
225
- async with ClientSession(raise_for_status=True) as session:
226
- response = await session.get(url=geomet_url, params=legend_params)
227
- legend_bytes = await response.read()
228
- self.legend_image = Image.open(BytesIO(legend_bytes)).convert("RGB")
229
- legend_width = self.legend_image.size[0]
230
- self.legend_position = (self.width - legend_width, 0)
231
- self.legend_layer = self.layer_key
219
+ try:
220
+ async with ClientSession(raise_for_status=True) as session:
221
+ response = await session.get(url=geomet_url, params=legend_params)
222
+ return await response.read()
223
+ except ClientConnectorError:
224
+ logging.warning("Legend could not be retrieved")
225
+ return None
232
226
 
233
227
  async def _get_dimensions(self):
234
228
  """Get time range of available data."""
@@ -256,54 +250,73 @@ class ECRadar(object):
256
250
  async def _combine_layers(self, radar_bytes, frame_time):
257
251
  """Add radar overlay to base layer and add timestamp."""
258
252
 
259
- radar = Image.open(BytesIO(radar_bytes)).convert("RGBA")
260
-
261
- # Add transparency to radar
262
-
263
- if self.radar_opacity < 100:
264
- alpha = round((self.radar_opacity / 100) * 255)
265
- radar_copy = radar.copy()
266
- radar_copy.putalpha(alpha)
267
- radar.paste(radar_copy, radar)
268
-
269
- # Overlay radar on basemap
270
-
253
+ base_bytes = None
271
254
  if not self.map_image:
272
- await self._get_basemap()
273
- if self.map_image:
274
- frame = Image.alpha_composite(self.map_image, radar)
275
- else:
276
- frame = radar
277
-
278
- # Add legend
255
+ base_bytes = await self._get_basemap()
279
256
 
257
+ legend_bytes = None
280
258
  if self.show_legend:
281
259
  if not self.legend_image or self.legend_layer != self.layer_key:
282
- await self._get_legend()
283
- frame.paste(self.legend_image, self.legend_position)
260
+ legend_bytes = await self._get_legend()
284
261
 
285
- # Add timestamp
262
+ # All the synchronous PIL stuff here
263
+ def _create_image():
264
+ radar = Image.open(BytesIO(radar_bytes)).convert("RGBA")
286
265
 
287
- if self.show_timestamp:
288
- timestamp = (
289
- timestamp_label[self.layer_key][self.language]
290
- + " @ "
291
- + frame_time.astimezone().strftime("%H:%M")
292
- )
293
- text_box = Image.new("RGBA", self.font.getbbox(timestamp)[2:], "white")
294
- box_draw = ImageDraw.Draw(text_box)
295
- box_draw.text(xy=(0, 0), text=timestamp, fill=(0, 0, 0), font=self.font)
296
- double_box = text_box.resize((text_box.width * 2, text_box.height * 2))
297
- frame.paste(double_box)
298
- frame = frame.quantize()
299
-
300
- # Return frame as PNG bytes
301
-
302
- img_byte_arr = BytesIO()
303
- frame.save(img_byte_arr, format="PNG")
304
- frame_bytes = img_byte_arr.getvalue()
266
+ if base_bytes:
267
+ self.map_image = Image.open(BytesIO(base_bytes)).convert("RGBA")
305
268
 
306
- return frame_bytes
269
+ if legend_bytes:
270
+ self.legend_image = Image.open(BytesIO(legend_bytes)).convert("RGB")
271
+ legend_width = self.legend_image.size[0]
272
+ self.legend_position = (self.width - legend_width, 0)
273
+ self.legend_layer = self.layer_key
274
+
275
+ # Add transparency to radar
276
+ if self.radar_opacity < 100:
277
+ alpha = round((self.radar_opacity / 100) * 255)
278
+ radar_copy = radar.copy()
279
+ radar_copy.putalpha(alpha)
280
+ radar.paste(radar_copy, radar)
281
+
282
+ if self.show_timestamp and not self.font:
283
+ self.font = ImageFont.load(
284
+ os.path.join(os.path.dirname(__file__), "10x20.pil")
285
+ )
286
+
287
+ # Overlay radar on basemap
288
+ if self.map_image:
289
+ frame = Image.alpha_composite(self.map_image, radar)
290
+ else:
291
+ frame = radar
292
+
293
+ # Add legend
294
+ if self.show_legend and self.legend_image:
295
+ frame.paste(self.legend_image, self.legend_position)
296
+
297
+ # Add timestamp
298
+ if self.show_timestamp and self.font:
299
+ timestamp = (
300
+ timestamp_label[self.layer_key][self.language]
301
+ + " @ "
302
+ + frame_time.astimezone().strftime("%H:%M")
303
+ )
304
+ text_box = Image.new("RGBA", self.font.getbbox(timestamp)[2:], "white")
305
+ box_draw = ImageDraw.Draw(text_box)
306
+ box_draw.text(xy=(0, 0), text=timestamp, fill=(0, 0, 0), font=self.font)
307
+ double_box = text_box.resize((text_box.width * 2, text_box.height * 2))
308
+ frame.paste(double_box)
309
+ frame = frame.quantize()
310
+
311
+ # Return frame as PNG bytes
312
+ img_byte_arr = BytesIO()
313
+ frame.save(img_byte_arr, format="PNG")
314
+ frame_bytes = img_byte_arr.getvalue()
315
+
316
+ return frame_bytes
317
+
318
+ # Since PIL is synchronous, run it all in another thread
319
+ return await asyncio.get_event_loop().run_in_executor(None, _create_image)
307
320
 
308
321
  async def _get_radar_image(self, session, frame_time):
309
322
  params = dict(
env_canada/ec_weather.py CHANGED
@@ -137,24 +137,6 @@ conditions_meta = {
137
137
  "english": "Icon Code",
138
138
  "french": "Code icône",
139
139
  },
140
- "high_temp_yesterday": {
141
- "xpath": './yesterdayConditions/temperature[@class="high"]',
142
- "type": "float",
143
- "english": "High Temperature Yesterday",
144
- "french": "Haute température d'hier",
145
- },
146
- "low_temp_yesterday": {
147
- "xpath": './yesterdayConditions/temperature[@class="low"]',
148
- "type": "float",
149
- "english": "Low Temperature Yesterday",
150
- "french": "Basse température d'hier",
151
- },
152
- "precip_yesterday": {
153
- "xpath": "./yesterdayConditions/precip",
154
- "type": "float",
155
- "english": "Precipitation Yesterday",
156
- "french": "Précipitation d'hier",
157
- },
158
140
  "normal_high": {
159
141
  "xpath": './forecastGroup/regionalNormals/temperature[@class="high"]',
160
142
  "type": "int",
@@ -183,7 +165,7 @@ conditions_meta = {
183
165
  "xpath": "./currentConditions/dateTime/timeStamp",
184
166
  "type": "timestamp",
185
167
  "english": "Observation Time",
186
- "french": "Temps d'observation"
168
+ "french": "Temps d'observation",
187
169
  },
188
170
  }
189
171
 
@@ -278,7 +260,6 @@ def closest_site(site_list, lat, lon):
278
260
 
279
261
 
280
262
  class ECWeather(object):
281
-
282
263
  """Get weather data from Environment Canada."""
283
264
 
284
265
  def __init__(self, **kwargs):
@@ -432,7 +413,9 @@ class ECWeather(object):
432
413
  self.conditions[c].update(get_condition(meta))
433
414
 
434
415
  # Update station metadata
435
- self.metadata["station"] = weather_tree.find("./currentConditions/station").text
416
+ self.metadata["station"] = weather_tree.find(
417
+ "./currentConditions/station"
418
+ ).text
436
419
 
437
420
  # Update text summary
438
421
  period = get_condition(summary_meta["forecast_period"])["value"]
@@ -494,7 +477,9 @@ class ECWeather(object):
494
477
  "temperature": int(f.findtext("./temperature") or 0),
495
478
  "icon_code": f.findtext("./iconCode"),
496
479
  "precip_probability": int(f.findtext("./lop") or "0"),
497
- "wind_speed": int(wind_speed_text if wind_speed_text.isnumeric() else 0),
480
+ "wind_speed": int(
481
+ wind_speed_text if wind_speed_text.isnumeric() else 0
482
+ ),
498
483
  "wind_direction": f.findtext("./wind/direction"),
499
484
  }
500
485
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: env_canada
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: A package to access meteorological data from Environment Canada
5
5
  Home-page: https://github.com/michaeldavie/env_canada
6
6
  Author: Michael Davie
@@ -25,7 +25,7 @@ Requires-Dist: voluptuous
25
25
  # Environment Canada (env_canada)
26
26
 
27
27
  [![PyPI version](https://badge.fury.io/py/env-canada.svg)](https://badge.fury.io/py/env-canada)
28
- [![Snyk rating](https://snyk-widget.herokuapp.com/badge/pip/env-canada/badge.svg)](https://snyk.io/vuln/pip:env-canada@0.6.2?utm_source=badge)
28
+ [![Snyk rating](https://snyk-widget.herokuapp.com/badge/pip/env-canada/badge.svg)](https://snyk.io/vuln/pip:env-canada@0.7.0?utm_source=badge)
29
29
 
30
30
  This package provides access to various data sources published by [Environment and Climate Change Canada](https://www.canada.ca/en/environment-climate-change.html).
31
31
 
@@ -207,4 +207,4 @@ of `datetime(2022, 7, 1, 12, 12)`
207
207
 
208
208
  # License
209
209
 
210
- The code is available under terms of [MIT License](LICENSE.md)
210
+ The code is available under terms of [MIT License](https://github.com/michaeldavie/env_canada/tree/master/LICENSE.md)
@@ -1,16 +1,16 @@
1
1
  env_canada/10x20.pbm,sha256=ClKTs2WUmhUhTHAQzPuGwPTICGVBzCvos5l-vHRBE5M,2463
2
2
  env_canada/10x20.pil,sha256=Oki6-TD7b0xFtfm6vxCKsmpEpsZ5Jaia_0v_aDz8bfE,5143
3
3
  env_canada/__init__.py,sha256=wEx1BCwVUH__GoosSlhNMHuUKCKNZAvv5uuSa5ZWq_g,187
4
- env_canada/constants.py,sha256=aVL9KzeCGoOZ2odaGXcKNqcxHZRamfD0CLXSFmyoZSM,32
4
+ env_canada/constants.py,sha256=xUcfT4fpHqhAnvC1GZ_gpYYrJYozfitwFiOBKN65xXg,32
5
5
  env_canada/ec_aqhi.py,sha256=kJQ8xEgFnujGMYdxRXpoEK17B5e-ya-Y7rK0vLo_-w0,7768
6
6
  env_canada/ec_cache.py,sha256=qoFxmO-kOBT8jhgPeNWtVBRmguXcARIIOI54OaDh-20,1171
7
7
  env_canada/ec_exc.py,sha256=SBJwzmLf94lTx7KYVLfQYrMXYNYUoIxeVXc-BLkuXoE,67
8
8
  env_canada/ec_historical.py,sha256=slHaFwsoyW16uCVtE3_-IF3_BFhFD4IuWl7rpIRsCm4,15901
9
9
  env_canada/ec_hydro.py,sha256=LBsWreTlaTKec6ObjI0ih8-zOKBNjD02oiXKTyUa1EQ,4898
10
- env_canada/ec_radar.py,sha256=TPzIlzwkgnsCSbN9Isdo_Q-1ORemNdYEBCcKfl_-ZcE,12415
11
- env_canada/ec_weather.py,sha256=uBY6qd0-hVyZDhqPcpipfMDImXpJGiNIzMOjIzqNBfo,17358
12
- env_canada-0.6.2.dist-info/LICENSE,sha256=c037dTHQWAgRgDqZNN-5d-CZvcteSYN37u39SNklO0I,1072
13
- env_canada-0.6.2.dist-info/METADATA,sha256=0-49I2ZCrOoguMf9YnoCrmV3I0eR_Pn-l2_Rvvkpwxw,10652
14
- env_canada-0.6.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
15
- env_canada-0.6.2.dist-info/top_level.txt,sha256=fw7Pcl9ULBXYvqnAdyBdmwPXW8GSRFmhO0sLZWVfOCc,11
16
- env_canada-0.6.2.dist-info/RECORD,,
10
+ env_canada/ec_radar.py,sha256=gcLa2z5T_CkrY-NLEJRqaLDHODJRcO5unW5MGxjKxF8,13115
11
+ env_canada/ec_weather.py,sha256=M7nPeZIKLirRIcCENB8z2B8aBDZHrjltzMYPgRz9lz0,16789
12
+ env_canada-0.7.0.dist-info/LICENSE,sha256=c037dTHQWAgRgDqZNN-5d-CZvcteSYN37u39SNklO0I,1072
13
+ env_canada-0.7.0.dist-info/METADATA,sha256=IueyWyN-i8vtUD8G4p8kMumCncfOUyPUrUS_TMEfw7w,10707
14
+ env_canada-0.7.0.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
15
+ env_canada-0.7.0.dist-info/top_level.txt,sha256=fw7Pcl9ULBXYvqnAdyBdmwPXW8GSRFmhO0sLZWVfOCc,11
16
+ env_canada-0.7.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5