env-canada 0.7.2__py3-none-any.whl → 0.8.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/__init__.py CHANGED
@@ -1,3 +1,12 @@
1
+ __all__ = [
2
+ "ECAirQuality",
3
+ "ECHistorical",
4
+ "ECHistoricalRange",
5
+ "ECHydro",
6
+ "ECRadar",
7
+ "ECWeather",
8
+ ]
9
+
1
10
  from .ec_aqhi import ECAirQuality
2
11
  from .ec_historical import ECHistorical, ECHistoricalRange
3
12
  from .ec_hydro import ECHydro
env_canada/constants.py CHANGED
@@ -1 +1 @@
1
- USER_AGENT = "env_canada/0.7.2"
1
+ USER_AGENT = "env_canada/0.8.0"
env_canada/ec_aqhi.py CHANGED
@@ -1,10 +1,10 @@
1
- from datetime import datetime, timezone
2
1
  import logging
2
+ from datetime import datetime, timezone
3
3
 
4
+ import voluptuous as vol
4
5
  from aiohttp import ClientSession
5
- import defusedxml.ElementTree as et
6
6
  from geopy import distance
7
- import voluptuous as vol
7
+ from lxml import etree as et
8
8
 
9
9
  from .constants import USER_AGENT
10
10
 
@@ -43,7 +43,7 @@ async def get_aqhi_regions(language):
43
43
  )
44
44
  result = await response.read()
45
45
 
46
- site_xml = result.decode("utf-8")
46
+ site_xml = result
47
47
  xml_object = et.fromstring(site_xml)
48
48
 
49
49
  for zone in xml_object.findall("./EC_administrativeZone"):
@@ -83,7 +83,7 @@ async def find_closest_region(language, lat, lon):
83
83
  return min(region_list, key=site_distance)
84
84
 
85
85
 
86
- class ECAirQuality(object):
86
+ class ECAirQuality:
87
87
  """Get air quality data from Environment Canada."""
88
88
 
89
89
  def __init__(self, **kwargs):
@@ -152,7 +152,7 @@ class ECAirQuality(object):
152
152
  return None
153
153
 
154
154
  result = await response.read()
155
- aqhi_xml = result.decode("ISO-8859-1")
155
+ aqhi_xml = result
156
156
  return et.fromstring(aqhi_xml)
157
157
 
158
158
  async def update(self):
env_canada/ec_cache.py CHANGED
@@ -1,8 +1,9 @@
1
1
  from datetime import datetime
2
+ from typing import Any, ClassVar
2
3
 
3
4
 
4
5
  class Cache:
5
- _cache = {}
6
+ _cache: ClassVar[dict[str, tuple[datetime, Any]]] = {}
6
7
 
7
8
  @classmethod
8
9
  def add(cls, cache_key, item, cache_time):
@@ -1,26 +1,28 @@
1
+ import asyncio
1
2
  import copy
2
3
  import csv
4
+ import logging
3
5
  from datetime import datetime
4
- from dateutil.relativedelta import relativedelta
5
6
  from io import StringIO
6
- import logging
7
- import xml.etree.ElementTree as et
8
- import pandas as pd
9
- import asyncio
10
7
 
11
- from aiohttp import ClientSession
12
- from dateutil import parser, tz
13
- import defusedxml.ElementTree as et
14
8
  import lxml.html
9
+ import pandas as pd
15
10
  import voluptuous as vol
11
+ from aiohttp import ClientSession
12
+ from dateutil import parser, tz
13
+ from dateutil.relativedelta import relativedelta
14
+ from lxml import etree as et
16
15
 
17
16
  from .constants import USER_AGENT
18
17
 
19
-
20
18
  STATIONS_URL = "https://climate.weather.gc.ca/historical_data/search_historic_data_stations_{}.html"
21
19
 
22
20
  WEATHER_URL = "https://climate.weather.gc.ca/climate_data/bulk_data_{}.html"
23
21
 
22
+ _TODAY = datetime.today().date()
23
+ _ONE_YEAR_AGO = _TODAY - relativedelta(years=1, months=1, day=1)
24
+ _YEAR = datetime.today().year
25
+
24
26
  LOG = logging.getLogger(__name__)
25
27
 
26
28
  __all__ = ["ECHistorical"]
@@ -126,7 +128,7 @@ async def get_historical_stations(
126
128
  coordinates,
127
129
  radius=25,
128
130
  start_year=1840,
129
- end_year=datetime.today().year,
131
+ end_year=_YEAR,
130
132
  limit=25,
131
133
  language="english",
132
134
  timeframe=2,
@@ -204,8 +206,7 @@ async def get_historical_stations(
204
206
  return stations
205
207
 
206
208
 
207
- class ECHistorical(object):
208
-
209
+ class ECHistorical:
209
210
  """Get historical weather data from Environment Canada."""
210
211
 
211
212
  def __init__(self, **kwargs):
@@ -353,30 +354,30 @@ def flip_daterange(f):
353
354
  return wrapper
354
355
 
355
356
 
356
- class ECHistoricalRange(object):
357
+ class ECHistoricalRange:
357
358
  """Get historical weather data from Environment Canada in the given range for the given station.
358
359
 
359
- options are daily or hourly data
360
+ options are daily or hourly data
360
361
 
361
- Example:
362
- import pandas as pd
363
- import asyncio
364
- from env_canada import ECHistoricalRange, get_historical_stations
365
- from datetime import datetime
362
+ Example:
363
+ import pandas as pd
364
+ import asyncio
365
+ from env_canada import ECHistoricalRange, get_historical_stations
366
+ from datetime import datetime
366
367
 
367
- coordinates = ['48.508333', '-68.467667']
368
+ coordinates = ['48.508333', '-68.467667']
368
369
 
369
- stations = pd.DataFrame(asyncio.run(get_historical_stations(coordinates, start_year=2022,
370
- end_year=2022, radius=200, limit=100))).T
370
+ stations = pd.DataFrame(asyncio.run(get_historical_stations(coordinates, start_year=2022,
371
+ end_year=2022, radius=200, limit=100))).T
371
372
 
372
- ec = ECHistoricalRange(station_id=int(stations.iloc[0,2]), timeframe="hourly",
373
- daterange=(datetime(2022, 7, 1, 12, 12), datetime(2022, 8, 1, 12, 12)))
373
+ ec = ECHistoricalRange(station_id=int(stations.iloc[0,2]), timeframe="hourly",
374
+ daterange=(datetime(2022, 7, 1, 12, 12), datetime(2022, 8, 1, 12, 12)))
374
375
 
375
- ec.get_data()
376
+ ec.get_data()
376
377
 
377
- ec.xml #yield an XML formatted str. For more options, use ec.to_xml(*arg, **kwargs) with pandas options
378
-
379
- ec.csv #yield an CSV formatted str. For more options, use ec.to_csv(*arg, **kwargs) with pandas options
378
+ ec.xml #yield an XML formatted str. For more options, use ec.to_xml(*arg, **kwargs) with pandas options
379
+ =
380
+ ec.csv #yield an CSV formatted str. For more options, use ec.to_csv(*arg, **kwargs) with pandas options
380
381
  """
381
382
 
382
383
  @flip_daterange
@@ -384,8 +385,8 @@ class ECHistoricalRange(object):
384
385
  self,
385
386
  station_id,
386
387
  daterange=(
387
- datetime.today().date() - relativedelta(years=1, months=1, day=1),
388
- datetime.today().date(),
388
+ _ONE_YEAR_AGO,
389
+ _TODAY,
389
390
  ),
390
391
  language="english",
391
392
  timeframe="daily",
@@ -409,7 +410,14 @@ class ECHistoricalRange(object):
409
410
  self.months = self.monthlist(daterange=daterange)
410
411
  self.language = language
411
412
  _tf = {"hourly": 1, "daily": 2, "monthly": 3}
412
- self.timeframe = _tf[timeframe]
413
+ timeframe_int = _tf[timeframe]
414
+ if timeframe_int == 2:
415
+ # prune the months list so it only has unique years. if daily is selected.
416
+ years = set()
417
+ for year, _ in self.months:
418
+ years.add(year)
419
+ self.months = [(year, 1) for year in years]
420
+ self.timeframe = timeframe_int
413
421
 
414
422
  def get_data(self):
415
423
  """
@@ -419,7 +427,6 @@ class ECHistoricalRange(object):
419
427
  """
420
428
  if not self.df.empty:
421
429
  self.df = pd.DataFrame()
422
-
423
430
  ec = [
424
431
  ECHistorical(
425
432
  station_id=self.station_id,
@@ -437,7 +444,7 @@ class ECHistoricalRange(object):
437
444
  self.df = pd.concat((self.df, pd.read_csv(data.station_data)))
438
445
 
439
446
  self.df = self.df.set_index(
440
- self.df.filter(regex="Date/*", axis=1).columns.values[0]
447
+ self.df.filter(regex="Date/*", axis=1).columns.to_numpy()[0]
441
448
  )
442
449
  self.df.index = pd.to_datetime(self.df.index)
443
450
 
@@ -477,7 +484,10 @@ class ECHistoricalRange(object):
477
484
  @flip_daterange
478
485
  def monthlist(self, daterange):
479
486
  startdate, stopdate = daterange
480
- total_months = lambda dt: dt.month + 12 * dt.year
487
+
488
+ def total_months(dt):
489
+ return dt.month + 12 * dt.year
490
+
481
491
  mlist = []
482
492
  for tot_m in range(total_months(startdate) - 1, total_months(stopdate)):
483
493
  y, m = divmod(tot_m, 12)
env_canada/ec_hydro.py CHANGED
@@ -1,10 +1,10 @@
1
1
  import csv
2
2
  import io
3
3
 
4
+ import voluptuous as vol
4
5
  from aiohttp import ClientSession
5
6
  from dateutil.parser import isoparse
6
7
  from geopy import distance
7
- import voluptuous as vol
8
8
 
9
9
  from .constants import USER_AGENT
10
10
 
@@ -54,8 +54,7 @@ async def closest_site(lat, lon):
54
54
  return closest
55
55
 
56
56
 
57
- class ECHydro(object):
58
-
57
+ class ECHydro:
59
58
  """Get hydrometric data from Environment Canada."""
60
59
 
61
60
  def __init__(self, **kwargs):
env_canada/ec_radar.py CHANGED
@@ -1,16 +1,16 @@
1
1
  import asyncio
2
- from datetime import date, timedelta
3
2
  import logging
4
3
  import math
5
4
  import os
5
+ from datetime import date, timedelta
6
6
  from io import BytesIO
7
7
  from typing import cast
8
8
 
9
9
  import dateutil.parser
10
- import defusedxml.ElementTree as et
11
10
  import voluptuous as vol
12
11
  from aiohttp import ClientSession
13
12
  from aiohttp.client_exceptions import ClientConnectorError
13
+ from lxml import etree as et
14
14
  from PIL import Image, ImageDraw, ImageFont
15
15
 
16
16
  from .constants import USER_AGENT
@@ -114,7 +114,7 @@ async def _get_resource(url, params, bytes=True):
114
114
  return await response.text()
115
115
 
116
116
 
117
- class ECRadar(object):
117
+ class ECRadar:
118
118
  def __init__(self, **kwargs):
119
119
  """Initialize the radar object."""
120
120
 
@@ -195,7 +195,7 @@ class ECRadar(object):
195
195
  return Cache.add("basemap", base_bytes, timedelta(days=7))
196
196
 
197
197
  except ClientConnectorError as e:
198
- logging.warning("Map from %s could not be retrieved: %s" % map_url, e)
198
+ logging.warning("Map from %s could not be retrieved: %s", map_url, e)
199
199
 
200
200
  async def _get_legend(self):
201
201
  """Fetch legend image."""
@@ -226,7 +226,7 @@ class ECRadar(object):
226
226
  if not (capabilities_xml := Cache.get(capabilities_cache_key)):
227
227
  capabilities_params["layer"] = precip_layers[self._precip_type_actual]
228
228
  capabilities_xml = await _get_resource(
229
- geomet_url, capabilities_params, bytes=False
229
+ geomet_url, capabilities_params, bytes=True
230
230
  )
231
231
  Cache.add(capabilities_cache_key, capabilities_xml, timedelta(minutes=5))
232
232
 
@@ -236,9 +236,9 @@ class ECRadar(object):
236
236
  )
237
237
  if dimension_string is not None:
238
238
  if dimension_string := dimension_string.text:
239
- start, end = [
239
+ start, end = (
240
240
  dateutil.parser.isoparse(t) for t in dimension_string.split("/")[:2]
241
- ]
241
+ )
242
242
  self.timestamp = end.isoformat()
243
243
  return (start, end)
244
244
  return None
env_canada/ec_weather.py CHANGED
@@ -3,11 +3,11 @@ import datetime
3
3
  import logging
4
4
  import re
5
5
 
6
+ import voluptuous as vol
6
7
  from aiohttp import ClientSession
7
8
  from dateutil import parser, relativedelta, tz
8
- import defusedxml.ElementTree as et
9
9
  from geopy import distance
10
- import voluptuous as vol
10
+ from lxml import etree as et
11
11
 
12
12
  from . import ec_exc
13
13
  from .constants import USER_AGENT
@@ -259,7 +259,7 @@ def closest_site(site_list, lat, lon):
259
259
  return "{}/{}".format(closest["Province Codes"], closest["Codes"])
260
260
 
261
261
 
262
- class ECWeather(object):
262
+ class ECWeather:
263
263
  """Get weather data from Environment Canada."""
264
264
 
265
265
  def __init__(self, **kwargs):
@@ -342,12 +342,14 @@ class ECWeather(object):
342
342
  timeout=10,
343
343
  )
344
344
  result = await response.read()
345
- weather_xml = result.decode()
345
+ weather_xml = result
346
346
 
347
347
  try:
348
348
  weather_tree = et.fromstring(weather_xml)
349
- except et.ParseError:
350
- raise ECWeatherUpdateFailed("Weather update failed; could not parse result")
349
+ except et.ParseError as err:
350
+ raise ECWeatherUpdateFailed(
351
+ "Weather update failed; could not parse result"
352
+ ) from err
351
353
 
352
354
  # Update metadata
353
355
  for m, meta in metadata_meta.items():
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
16
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
17
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
18
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
- SOFTWARE
19
+ SOFTWARE
@@ -1,34 +1,73 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: env_canada
3
- Version: 0.7.2
3
+ Version: 0.8.0
4
4
  Summary: A package to access meteorological data from Environment Canada
5
- Home-page: https://github.com/michaeldavie/env_canada
6
- Author: Michael Davie
7
- Author-email: michael.davie@gmail.com
8
- License: MIT
5
+ Author-email: Michael Davie <michael.davie@gmail.com>
6
+ Maintainer-email: Michael Davie <michael.davie@gmail.com>
7
+ License: Copyright (c) 2018 The Python Packaging Authority
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE
26
+
27
+ Project-URL: Homepage, https://github.com/michaeldavie/env_canada
28
+ Project-URL: Documentation, https://github.com/michaeldavie/env_canada
29
+ Project-URL: Repository, https://github.com/michaeldavie/env_canada
30
+ Project-URL: Bug Tracker, https://github.com/michaeldavie/env_canada/issues
31
+ Project-URL: Changelog, https://github.com/michaeldavie/env_canada/blob/master/CHANGELOG.md
9
32
  Classifier: Programming Language :: Python :: 3
10
33
  Classifier: License :: OSI Approved :: MIT License
11
34
  Classifier: Operating System :: OS Independent
35
+ Requires-Python: >=3.10
12
36
  Description-Content-Type: text/markdown
13
37
  License-File: LICENSE
14
- Requires-Dist: aiohttp >=3.9.0
15
- Requires-Dist: defusedxml
38
+ Requires-Dist: aiohttp>=3.9.0
16
39
  Requires-Dist: geopy
17
- Requires-Dist: imageio >=2.28.0
40
+ Requires-Dist: imageio>=2.28.0
18
41
  Requires-Dist: lxml
19
- Requires-Dist: numpy >=1.22.2
20
- Requires-Dist: pandas >=1.3.0
21
- Requires-Dist: Pillow >=10.0.1
42
+ Requires-Dist: numpy>=1.22.2
43
+ Requires-Dist: pandas>=1.3.0
44
+ Requires-Dist: Pillow>=10.0.1
22
45
  Requires-Dist: python-dateutil
23
46
  Requires-Dist: voluptuous
47
+ Provides-Extra: dev
48
+ Requires-Dist: pytest; extra == "dev"
24
49
 
25
50
  # Environment Canada (env_canada)
26
51
 
27
52
  [![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.7.2?utm_source=badge)
53
+ [![Snyk rating](https://snyk-widget.herokuapp.com/badge/pip/env-canada/badge.svg)](https://snyk.io/vuln/pip:env-canada@0.8.0?utm_source=badge)
54
+ [![Python Lint and Test](../..//actions/workflows/python-app.yml/badge.svg)](../../actions/workflows/python-app.yml)
29
55
 
30
56
  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
57
 
58
+ > [!IMPORTANT]
59
+ > If you're using the library in a Jupyter notebook, replace `asyncio.run(...)` with `await ...` in the examples below. For example:
60
+ >
61
+ > ```python
62
+ > asyncio.run(ec_en.update())
63
+ > ```
64
+ >
65
+ > becomes
66
+ >
67
+ > ```python
68
+ > await ec_en.update()
69
+ > ```
70
+
32
71
  ## Weather Observations and Forecasts
33
72
 
34
73
  `ECWeather` provides current conditions and forecasts. It automatically determines which weather station to use based on latitude/longitude provided. It is also possible to specify a specific station code of the form `AB/s0000123` based on those listed in [this CSV file](https://dd.weather.gc.ca/citypage_weather/docs/site_list_towns_en.csv). For example:
@@ -39,7 +78,7 @@ import asyncio
39
78
  from env_canada import ECWeather
40
79
 
41
80
  ec_en = ECWeather(coordinates=(50, -100))
42
- ec_fr = ECWeather(station_id='ON/s0000430', language='french')
81
+ ec_fr = ECWeather(station_id="ON/s0000430", language="french")
43
82
 
44
83
  asyncio.run(ec_en.update())
45
84
 
@@ -120,7 +159,7 @@ from env_canada import ECHistorical
120
159
  from env_canada.ec_historical import get_historical_stations
121
160
 
122
161
  # search for stations, response contains station_ids
123
- coordinates = [53.916944, -122.749444] # [lat, long]
162
+ coordinates = [53.916944, -122.749444] # [lat, long]
124
163
 
125
164
  # coordinates: [lat, long]
126
165
  # radius: km
@@ -136,8 +175,12 @@ ec_fr_csv = ECHistorical(station_id=31688, year=2020, language="french", format=
136
175
  # timeframe argument can be passed to change the granularity
137
176
  # timeframe=1 hourly (need to create of for every month in that case, use ECHistoricalRange to handle it automatically)
138
177
  # timeframe=2 daily (default)
139
- ec_en_xml = ECHistorical(station_id=31688, year=2020, month=1, language="english", format="xml", timeframe=1)
140
- ec_en_csv = ECHistorical(station_id=31688, year=2020, month=1, language="english", format="csv", timeframe=1)
178
+ ec_en_xml = ECHistorical(
179
+ station_id=31688, year=2020, month=1, language="english", format="xml", timeframe=1
180
+ )
181
+ ec_en_csv = ECHistorical(
182
+ station_id=31688, year=2020, month=1, language="english", format="csv", timeframe=1
183
+ )
141
184
 
142
185
  asyncio.run(ec_en_xml.update())
143
186
  asyncio.run(ec_en_csv.update())
@@ -150,8 +193,8 @@ ec_en_xml.station_data
150
193
 
151
194
  # csv-generated responses return csv-like station data
152
195
  import pandas as pd
153
- df = pd.read_csv(ec_en_csv.station_data)
154
196
 
197
+ df = pd.read_csv(ec_en_csv.station_data)
155
198
  ```
156
199
 
157
200
  `ECHistoricalRange` provides historical weather data within a specific range and handles the update by itself.
@@ -170,21 +213,29 @@ from env_canada import ECHistoricalRange
170
213
  from env_canada.ec_historical import get_historical_stations
171
214
  from datetime import datetime
172
215
 
173
- coordinates = ['48.508333', '-68.467667']
216
+ coordinates = ["48.508333", "-68.467667"]
174
217
 
175
- stations = pd.DataFrame(asyncio.run(get_historical_stations(coordinates, start_year=2022,
176
- end_year=2022, radius=200, limit=100))).T
218
+ stations = pd.DataFrame(
219
+ asyncio.run(
220
+ get_historical_stations(
221
+ coordinates, start_year=2022, end_year=2022, radius=200, limit=100
222
+ )
223
+ )
224
+ ).T
177
225
 
178
- ec = ECHistoricalRange(station_id=int(stations.iloc[0,2]), timeframe="daily",
179
- daterange=(datetime(2022, 7, 1, 12, 12), datetime(2022, 8, 1, 12, 12)))
226
+ ec = ECHistoricalRange(
227
+ station_id=int(stations.iloc[0, 2]),
228
+ timeframe="daily",
229
+ daterange=(datetime(2022, 7, 1, 12, 12), datetime(2022, 8, 1, 12, 12)),
230
+ )
180
231
 
181
232
  ec.get_data()
182
233
 
183
- #yield an XML formated str.
234
+ # yield an XML formated str.
184
235
  # For more options, use ec.to_xml(*arg, **kwargs) with pandas options
185
236
  ec.xml
186
237
 
187
- #yield an CSV formated str.
238
+ # yield an CSV formated str.
188
239
  # For more options, use ec.to_csv(*arg, **kwargs) with pandas options
189
240
  ec.csv
190
241
  ```
@@ -0,0 +1,16 @@
1
+ env_canada/10x20.pbm,sha256=ClKTs2WUmhUhTHAQzPuGwPTICGVBzCvos5l-vHRBE5M,2463
2
+ env_canada/10x20.pil,sha256=Oki6-TD7b0xFtfm6vxCKsmpEpsZ5Jaia_0v_aDz8bfE,5143
3
+ env_canada/__init__.py,sha256=Qqtu4qEY1gvzPF4D0qzi8kVvtYUizJDzQk5FZVqoo38,314
4
+ env_canada/constants.py,sha256=RHa-Hp2H6XroFE9Z5-H0MIUPWlFXUVKmWEidwuWzakE,32
5
+ env_canada/ec_aqhi.py,sha256=-N4XLLgApaWZvtepJvS2lvqDSNjwV2X_fkmbtKQv8rA,7741
6
+ env_canada/ec_cache.py,sha256=zb3n79ul7hUTE0IohDfZbRBLY-siOHPjYzWldMbuPVk,798
7
+ env_canada/ec_exc.py,sha256=SBJwzmLf94lTx7KYVLfQYrMXYNYUoIxeVXc-BLkuXoE,67
8
+ env_canada/ec_historical.py,sha256=qMr4RE6vfNiNa_zFolQ0PQGraok8bQtIVjs_o6sJKD4,16276
9
+ env_canada/ec_hydro.py,sha256=JoBe-QVV8GEeZXCNFscIs2R_spgkbxCZpLt7tL6-NUI,4889
10
+ env_canada/ec_radar.py,sha256=0SKusJWDTFODdn3D9yrhlkOS-Bv9hhBJM9EBh8TNRlk,12965
11
+ env_canada/ec_weather.py,sha256=PSgb67PODo8Lv7A7O01q97SjvHCK0lwpcDtqTa70GI8,17048
12
+ env_canada-0.8.0.dist-info/LICENSE,sha256=BkgGIGgy9sv-OsI7mRi9dIQ3Su0m4IbjpZlfxv8oBbM,1073
13
+ env_canada-0.8.0.dist-info/METADATA,sha256=U548dMi4w3eX8MqFQrQseJthoggUFfC_a1AefMYjemA,12723
14
+ env_canada-0.8.0.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
15
+ env_canada-0.8.0.dist-info/top_level.txt,sha256=fw7Pcl9ULBXYvqnAdyBdmwPXW8GSRFmhO0sLZWVfOCc,11
16
+ env_canada-0.8.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.3.0)
2
+ Generator: setuptools (75.7.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,16 +0,0 @@
1
- env_canada/10x20.pbm,sha256=ClKTs2WUmhUhTHAQzPuGwPTICGVBzCvos5l-vHRBE5M,2463
2
- env_canada/10x20.pil,sha256=Oki6-TD7b0xFtfm6vxCKsmpEpsZ5Jaia_0v_aDz8bfE,5143
3
- env_canada/__init__.py,sha256=wEx1BCwVUH__GoosSlhNMHuUKCKNZAvv5uuSa5ZWq_g,187
4
- env_canada/constants.py,sha256=DlW7o9XEpZNQry99jZ1vF0wX7Xm7ZRcK41n0YAwzp9U,32
5
- env_canada/ec_aqhi.py,sha256=zEEt2U8gCxaLlePexl23r9zCfQYgmfhsP0ur2ZiupZc,7793
6
- env_canada/ec_cache.py,sha256=xPlXBRLyrD6dTJWLRBy12J8kzBxMUC-20-xRuc56Hts,722
7
- env_canada/ec_exc.py,sha256=SBJwzmLf94lTx7KYVLfQYrMXYNYUoIxeVXc-BLkuXoE,67
8
- env_canada/ec_historical.py,sha256=slHaFwsoyW16uCVtE3_-IF3_BFhFD4IuWl7rpIRsCm4,15901
9
- env_canada/ec_hydro.py,sha256=LBsWreTlaTKec6ObjI0ih8-zOKBNjD02oiXKTyUa1EQ,4898
10
- env_canada/ec_radar.py,sha256=zh0tbazBbvLpuxrY0yfRm9EIaXNkM6HXPe1us99h4xM,12982
11
- env_canada/ec_weather.py,sha256=cLWMTuvASrxYeGnXvGwsNZxd_SfD1sdfInBU51QLFCo,17026
12
- env_canada-0.7.2.dist-info/LICENSE,sha256=c037dTHQWAgRgDqZNN-5d-CZvcteSYN37u39SNklO0I,1072
13
- env_canada-0.7.2.dist-info/METADATA,sha256=M-fb4_i9Je1a2e6T5M7RIYDW33nknvWN6GHSKg60Sds,10707
14
- env_canada-0.7.2.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
15
- env_canada-0.7.2.dist-info/top_level.txt,sha256=fw7Pcl9ULBXYvqnAdyBdmwPXW8GSRFmhO0sLZWVfOCc,11
16
- env_canada-0.7.2.dist-info/RECORD,,