meteostat 1.7.6__py3-none-any.whl → 2.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.
Files changed (93) hide show
  1. meteostat/__init__.py +32 -19
  2. meteostat/api/daily.py +76 -0
  3. meteostat/api/hourly.py +80 -0
  4. meteostat/api/interpolate.py +240 -0
  5. meteostat/api/inventory.py +59 -0
  6. meteostat/api/merge.py +103 -0
  7. meteostat/api/monthly.py +73 -0
  8. meteostat/api/normals.py +144 -0
  9. meteostat/api/point.py +30 -0
  10. meteostat/api/stations.py +234 -0
  11. meteostat/api/timeseries.py +334 -0
  12. meteostat/core/cache.py +212 -59
  13. meteostat/core/config.py +158 -0
  14. meteostat/core/data.py +199 -0
  15. meteostat/core/logger.py +9 -0
  16. meteostat/core/network.py +82 -0
  17. meteostat/core/parameters.py +112 -0
  18. meteostat/core/providers.py +184 -0
  19. meteostat/core/schema.py +170 -0
  20. meteostat/core/validator.py +38 -0
  21. meteostat/enumerations.py +149 -0
  22. meteostat/interpolation/idw.py +120 -0
  23. meteostat/interpolation/lapserate.py +91 -0
  24. meteostat/interpolation/nearest.py +31 -0
  25. meteostat/parameters.py +354 -0
  26. meteostat/providers/dwd/climat.py +166 -0
  27. meteostat/providers/dwd/daily.py +144 -0
  28. meteostat/providers/dwd/hourly.py +218 -0
  29. meteostat/providers/dwd/monthly.py +138 -0
  30. meteostat/providers/dwd/mosmix.py +351 -0
  31. meteostat/providers/dwd/poi.py +117 -0
  32. meteostat/providers/dwd/shared.py +155 -0
  33. meteostat/providers/eccc/daily.py +87 -0
  34. meteostat/providers/eccc/hourly.py +104 -0
  35. meteostat/providers/eccc/monthly.py +66 -0
  36. meteostat/providers/eccc/shared.py +45 -0
  37. meteostat/providers/index.py +496 -0
  38. meteostat/providers/meteostat/daily.py +65 -0
  39. meteostat/providers/meteostat/daily_derived.py +110 -0
  40. meteostat/providers/meteostat/hourly.py +66 -0
  41. meteostat/providers/meteostat/monthly.py +45 -0
  42. meteostat/providers/meteostat/monthly_derived.py +106 -0
  43. meteostat/providers/meteostat/shared.py +93 -0
  44. meteostat/providers/metno/forecast.py +186 -0
  45. meteostat/providers/noaa/ghcnd.py +228 -0
  46. meteostat/providers/noaa/isd_lite.py +142 -0
  47. meteostat/providers/noaa/metar.py +163 -0
  48. meteostat/typing.py +113 -0
  49. meteostat/utils/conversions.py +231 -0
  50. meteostat/utils/data.py +194 -0
  51. meteostat/utils/geo.py +28 -0
  52. meteostat/utils/parsers.py +168 -0
  53. meteostat/utils/types.py +113 -0
  54. meteostat/utils/validators.py +31 -0
  55. meteostat-2.0.0.dist-info/METADATA +134 -0
  56. meteostat-2.0.0.dist-info/RECORD +63 -0
  57. {meteostat-1.7.6.dist-info → meteostat-2.0.0.dist-info}/WHEEL +1 -2
  58. meteostat/core/loader.py +0 -103
  59. meteostat/core/warn.py +0 -34
  60. meteostat/enumerations/granularity.py +0 -22
  61. meteostat/interface/base.py +0 -39
  62. meteostat/interface/daily.py +0 -118
  63. meteostat/interface/hourly.py +0 -154
  64. meteostat/interface/meteodata.py +0 -210
  65. meteostat/interface/monthly.py +0 -109
  66. meteostat/interface/normals.py +0 -245
  67. meteostat/interface/point.py +0 -143
  68. meteostat/interface/stations.py +0 -252
  69. meteostat/interface/timeseries.py +0 -237
  70. meteostat/series/aggregate.py +0 -48
  71. meteostat/series/convert.py +0 -28
  72. meteostat/series/count.py +0 -17
  73. meteostat/series/coverage.py +0 -20
  74. meteostat/series/fetch.py +0 -28
  75. meteostat/series/interpolate.py +0 -47
  76. meteostat/series/normalize.py +0 -76
  77. meteostat/series/stations.py +0 -22
  78. meteostat/units.py +0 -149
  79. meteostat/utilities/__init__.py +0 -0
  80. meteostat/utilities/aggregations.py +0 -37
  81. meteostat/utilities/endpoint.py +0 -33
  82. meteostat/utilities/helpers.py +0 -70
  83. meteostat/utilities/mutations.py +0 -89
  84. meteostat/utilities/validations.py +0 -30
  85. meteostat-1.7.6.dist-info/METADATA +0 -112
  86. meteostat-1.7.6.dist-info/RECORD +0 -39
  87. meteostat-1.7.6.dist-info/top_level.txt +0 -1
  88. /meteostat/{core → api}/__init__.py +0 -0
  89. /meteostat/{enumerations → interpolation}/__init__.py +0 -0
  90. /meteostat/{interface → providers}/__init__.py +0 -0
  91. /meteostat/{interface/interpolate.py → py.typed} +0 -0
  92. /meteostat/{series → utils}/__init__.py +0 -0
  93. {meteostat-1.7.6.dist-info → meteostat-2.0.0.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,113 @@
1
+ """
2
+ Type parsing utilities
3
+
4
+ This module contains utilities for extracting and validating types
5
+ from class annotations without creating circular imports.
6
+ """
7
+
8
+ from typing import Any, Union
9
+
10
+
11
+ def extract_property_type(cls: type, property_name: str) -> tuple[Any, Any]:
12
+ """
13
+ Extract the expected type for a class property from type annotations.
14
+
15
+ Parameters
16
+ ----------
17
+ cls : type
18
+ The class to extract type information from
19
+ property_name : str
20
+ The name of the property to get the type for
21
+
22
+ Returns
23
+ -------
24
+ tuple[Any, Any]
25
+ A tuple containing (expected_type, original_type) where:
26
+ - expected_type: The actual type to validate against (unwrapped from Optional)
27
+ - original_type: The original type annotation (including Optional wrapper)
28
+
29
+ Raises
30
+ ------
31
+ ValueError
32
+ If the property doesn't exist on the class
33
+ """
34
+ if not hasattr(cls, property_name):
35
+ raise ValueError(f"Property '{property_name}' does not exist")
36
+
37
+ # Get type annotations for the class
38
+ annotations = getattr(cls, "__annotations__", {})
39
+ original_type = annotations.get(property_name)
40
+
41
+ if original_type is None:
42
+ return None, None
43
+
44
+ expected_type = original_type
45
+
46
+ # Handle Optional types (extract the inner type)
47
+ if hasattr(original_type, "__origin__") and original_type.__origin__ is Union:
48
+ args = getattr(original_type, "__args__", ())
49
+ if len(args) == 2 and type(None) in args:
50
+ # This is Optional[Type], extract the non-None type
51
+ # Type narrowing: we know len(args) == 2, so both indices are valid
52
+ arg0 = args[0] # type: ignore
53
+ arg1 = args[1] # type: ignore
54
+ expected_type = arg0 if arg1 is type(None) else arg1
55
+
56
+ return expected_type, original_type
57
+
58
+
59
+ def validate_parsed_value(
60
+ value: Any, expected_type: Any, original_type: Any, property_name: str
61
+ ) -> Any:
62
+ """
63
+ Validate a parsed value against the expected type and handle special cases.
64
+
65
+ Parameters
66
+ ----------
67
+ value : Any
68
+ The parsed value to validate
69
+ expected_type : Any
70
+ The expected type for validation
71
+ original_type : Any
72
+ The original type annotation (for Optional type checking)
73
+ property_name : str
74
+ The name of the property being validated (for error messages)
75
+
76
+ Returns
77
+ -------
78
+ Any
79
+ The validated (and potentially converted) value
80
+
81
+ Raises
82
+ ------
83
+ ValueError
84
+ If the value doesn't match the expected type
85
+ """
86
+ # Check if the parsed value matches the expected type
87
+ if isinstance(value, expected_type):
88
+ return value
89
+
90
+ # Special case for Optional types - None is allowed
91
+ if (
92
+ hasattr(original_type, "__origin__")
93
+ and original_type.__origin__ is Union
94
+ and value is None
95
+ ):
96
+ return value
97
+
98
+ # Special case for bool type - allow 0 and 1 to be parsed as False and True
99
+ if expected_type is bool and isinstance(value, int):
100
+ if value == 0:
101
+ return False
102
+ if value == 1:
103
+ return True
104
+ raise ValueError(
105
+ f"Environment variable '{property_name}' has value {value} "
106
+ f"but boolean type only accepts 0, 1, true, or false"
107
+ )
108
+
109
+ # Type mismatch
110
+ raise ValueError(
111
+ f"Environment variable '{property_name}' has type {type(value).__name__} "
112
+ f"but expected {expected_type.__name__}"
113
+ )
@@ -0,0 +1,31 @@
1
+ """
2
+ Validators Module
3
+
4
+ Provides validator functions for data validation.
5
+ """
6
+
7
+ from pandas import Series
8
+
9
+ from meteostat.core.validator import Validator
10
+
11
+
12
+ def minimum(value: int | float) -> Validator:
13
+ """
14
+ Numeric minimum
15
+ """
16
+
17
+ def _func(series: Series) -> Series:
18
+ return series >= value
19
+
20
+ return Validator(_func)
21
+
22
+
23
+ def maximum(value: int | float) -> Validator:
24
+ """
25
+ Numeric maximum
26
+ """
27
+
28
+ def _func(series: Series) -> Series:
29
+ return series <= value
30
+
31
+ return Validator(_func)
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.4
2
+ Name: meteostat
3
+ Version: 2.0.0
4
+ Summary: Access and analyze historical weather and climate data with Python.
5
+ License-File: LICENSE
6
+ Author: Meteostat
7
+ Requires-Python: >=3.11,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Dist: pandas (>=2.3.3,<3.0.0)
14
+ Requires-Dist: pytz (>=2023.3.post1,<2024.0)
15
+ Requires-Dist: requests (>=2.31.0,<3.0.0)
16
+ Description-Content-Type: text/markdown
17
+
18
+ <!-- PROJECT SHIELDS -->
19
+ <div align="center">
20
+
21
+ [![Contributors][contributors-shield]][contributors-url]
22
+ [![Forks][forks-shield]][forks-url]
23
+ [![Stargazers][stars-shield]][stars-url]
24
+ [![Issues][issues-shield]][issues-url]
25
+ [![Unlicense License][license-shield]][license-url]
26
+ [![LinkedIn][linkedin-shield]][linkedin-url]
27
+
28
+ </div>
29
+
30
+
31
+ <!-- PROJECT LOGO -->
32
+ <br />
33
+ <div align="center">
34
+ <a href="https://github.com/meteostat/meteostat">
35
+ <img src="https://media.meteostat.net/icon.svg" alt="Meteostat Logo" width="80" height="80">
36
+ </a>
37
+
38
+ <h3 align="center">Meteostat Python Package</h3>
39
+
40
+ <p align="center">
41
+ Access and analyze historical weather and climate data with Python.
42
+ <p>
43
+ <a href="https://dev.meteostat.net/python"><strong>Explore the docs »</strong></a>
44
+ </p>
45
+ <p>
46
+ <a href="https://meteostat.net">Visit Website</a>
47
+ &middot;
48
+ <a href="https://github.com/meteostat/meteostat/issues">Report Bug</a>
49
+ &middot;
50
+ <a href="https://github.com/orgs/meteostat/discussions">Request Feature</a>
51
+ </p>
52
+ </p>
53
+ </div>
54
+
55
+ ## 📚 Installation
56
+
57
+ The Meteostat Python package is available through [PyPI](https://pypi.org/project/meteostat/):
58
+
59
+ ```sh
60
+ pip install meteostat
61
+ ```
62
+
63
+ ## 🚀 Usage
64
+
65
+ Let's plot 2018 temperature data for Frankfurt, Germany:
66
+
67
+ ```python
68
+ from datetime import date
69
+ import matplotlib.pyplot as plt
70
+ import meteostat as ms
71
+
72
+ # Specify location and time range
73
+ POINT = ms.Point(50.1155, 8.6842, 113) # Try with your location
74
+ START = date(2018, 1, 1)
75
+ END = date(2018, 12, 31)
76
+
77
+ # Get nearby weather stations
78
+ stations = ms.stations.nearby(POINT, limit=4)
79
+
80
+ # Get daily data & perform interpolation
81
+ ts = ms.daily(stations, START, END)
82
+ df = ms.interpolate(ts, POINT).fetch()
83
+
84
+ # Plot line chart including average, minimum and maximum temperature
85
+ df.plot(y=[ms.Parameter.TEMP, ms.Parameter.TMIN, ms.Parameter.TMAX])
86
+ plt.show()
87
+ ```
88
+
89
+ Take a look at the expected output:
90
+
91
+ ![2018 temperature data for Frankfurt, Germany][product-screenshot]
92
+
93
+ ## 🤝 Contributing
94
+
95
+ Please read our [contributing guidelines](https://dev.meteostat.net/python/contributing) for details on how to contribute to the Meteostat Python library.
96
+
97
+ **Top contributors**
98
+
99
+ <a href="https://github.com/meteostat/meteostat/graphs/contributors">
100
+ <img src="https://contrib.rocks/image?repo=meteostat/meteostat" alt="Meteostat Contributors" />
101
+ </a>
102
+
103
+ ## 🌟 Featured In
104
+
105
+ Meteostat has been featured and used by various media outlets and organizations, including:
106
+
107
+ - [Towards Data Science](https://towardsdatascience.com/get-temperature-data-by-location-with-python-52ed872dd621/)
108
+ - [ZEIT ONLINE](https://www.zeit.de/digital/internet/2022-03/desinformation-russland-ukraine-fotos-fake-news-falschinformation-echtheit)
109
+ - [Deutsche Presse-Agentur (dpa)](https://dpa-factchecking.com/germany/230103-99-92282/)
110
+ - [heise online](https://www.heise.de/news/Open-Source-Projekt-zu-Klimadaten-Meteostat-Python-Library-1-0-erschienen-4985015.html)
111
+
112
+ Join the growing community of users and researchers relying on Meteostat for their weather data needs.
113
+
114
+ ## 📄 License
115
+
116
+ Meteostat is licensed under the [**MIT License**](https://github.com/meteostat/meteostat/blob/main/LICENSE). Data provided by Meteostat is generally licensed under the [**Creative Commons Attribution 4.0 International (CC BY 4.0)**](https://creativecommons.org/licenses/by/4.0) license. Please refer to the [documentation](https://dev.meteostat.net/license) for more information.
117
+
118
+
119
+ <!-- MARKDOWN LINKS & IMAGES -->
120
+ <!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
121
+ [contributors-shield]: https://img.shields.io/github/contributors/meteostat/meteostat.svg?style=for-the-badge
122
+ [contributors-url]: https://github.com/meteostat/meteostat/graphs/contributors
123
+ [forks-shield]: https://img.shields.io/github/forks/meteostat/meteostat.svg?style=for-the-badge
124
+ [forks-url]: https://github.com/meteostat/meteostat/network/members
125
+ [stars-shield]: https://img.shields.io/github/stars/meteostat/meteostat.svg?style=for-the-badge
126
+ [stars-url]: https://github.com/meteostat/meteostat/stargazers
127
+ [issues-shield]: https://img.shields.io/github/issues/meteostat/meteostat.svg?style=for-the-badge
128
+ [issues-url]: https://github.com/meteostat/meteostat/issues
129
+ [license-shield]: https://img.shields.io/github/license/meteostat/meteostat.svg?style=for-the-badge
130
+ [license-url]: https://github.com/meteostat/meteostat/blob/main/LICENSE
131
+ [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555
132
+ [linkedin-url]: https://www.linkedin.com/company/meteostat
133
+ [product-screenshot]: https://dev.meteostat.net/assets/images/example-8b6cf2a3fe2efa285bc72d7dc72c4865.png
134
+
@@ -0,0 +1,63 @@
1
+ meteostat/__init__.py,sha256=-Oq1cCBUSBIUMYK01RLV4oXgfo0f-F6S_9iVUNh39m0,1371
2
+ meteostat/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ meteostat/api/daily.py,sha256=SUYxR7HC5Cqyd6cBG42QmSpEP74HwDq5VnqfSznM46Y,2371
4
+ meteostat/api/hourly.py,sha256=KGJ4xBwO__fBrQ5ll5ruLEkrpOCD8bybSBcXJ94-ntE,2556
5
+ meteostat/api/interpolate.py,sha256=UJH_TJqCsmOTT3-DP2hh9rn3mHiISqqxHE083TtFb-M,8280
6
+ meteostat/api/inventory.py,sha256=xida9SVdYPm4GpiloVg-zXvkeUi7Egaj_XbxWWhNHuI,1405
7
+ meteostat/api/merge.py,sha256=CtoItPFsRxXWu50g1zjC9q94wTDC6ZzCLhvU3jmZhX4,2638
8
+ meteostat/api/monthly.py,sha256=cZmJiwVNxw5nNNmrx0ohy9bIN_dSt1Nk8crxcCJsJvU,2327
9
+ meteostat/api/normals.py,sha256=3CbRCYrp_mATZwkWbgBphcmLvhoR_hSaDCj0hfsIlKk,5138
10
+ meteostat/api/point.py,sha256=T4fRcf_ozE3O_ywS8lneSfG_dWexk-cNmVHLJKB_idc,718
11
+ meteostat/api/stations.py,sha256=AuG13Rn_WMujxmnifHbNPVPDMxXzWvqDS0ZfmvRWqSE,7002
12
+ meteostat/api/timeseries.py,sha256=zwrIT6URl4R4JYEFUDorn5QZg3VRMeKR2XMOF9D9REc,9889
13
+ meteostat/core/cache.py,sha256=t1BUJXIMvQ3a1h-_dzFWiSz6lLKGwp91zVbGE97ObzY,6646
14
+ meteostat/core/config.py,sha256=qjOOzh6c_yw0KzLnreWodewHwC2lTGyFm1zJVgJnKg4,5066
15
+ meteostat/core/data.py,sha256=0lzp2nX4VaMj6l7EAPNR74lDd9W_8qy526P34hVsd9A,5643
16
+ meteostat/core/logger.py,sha256=MUqPTxpw6C9zky4lCeOac9rLjjYkaiHVGVVvLuxKgEg,146
17
+ meteostat/core/network.py,sha256=7972WWNp90RNbCKntWCzGH-0sBFLcdExdqK6k20YzzE,1940
18
+ meteostat/core/parameters.py,sha256=7BJIkFQaxcBRi1yIDgpAYm2VZxBfVPbi5_UdZL9teXE,3288
19
+ meteostat/core/providers.py,sha256=DChq-vILb9uWEcsZmUcUnyeuVGtl3Ote49QhibdeNBo,5490
20
+ meteostat/core/schema.py,sha256=Jbp84bTgWmfhPYhORluGWLEnogevsFiAjwC21Y4Mbwg,5070
21
+ meteostat/core/validator.py,sha256=pJOJIU8FtYO4k7ihGqFxM6CSs9O6oO-fByYyJeJ9pZY,887
22
+ meteostat/enumerations.py,sha256=1lWrnzejtV1uP5CjyeyN-UcYt8wBIqlc5sxwzwh5Rqg,3271
23
+ meteostat/interpolation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ meteostat/interpolation/idw.py,sha256=AyZWxXjq8mS9BEQtxgSEHQzn7TZYIdkc22kPkF5qZww,4435
25
+ meteostat/interpolation/lapserate.py,sha256=5RanfTDc6OiyuYubjjbQQo23iS05pEf0TmAnqyshoR8,2638
26
+ meteostat/interpolation/nearest.py,sha256=xZg_6OCvU8uI-i7UbPQHjsJmtlz_DbZqrDz00dJthEM,782
27
+ meteostat/parameters.py,sha256=w7G3ktLVasAbaR9OnjuMAvrq_c1zLz5PVt3zofDFun4,10074
28
+ meteostat/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
+ meteostat/providers/dwd/climat.py,sha256=seBHREXkALb_ACP3bMErfBnFrt_oANX_qoaDCFjPsZ8,4876
30
+ meteostat/providers/dwd/daily.py,sha256=xYGmOY-jETqxpXiXHPvM2GeQuaQr3M2qn0ui4cqpscw,4031
31
+ meteostat/providers/dwd/hourly.py,sha256=UukcRv3eN9jIewvACC3dHDXrRn50pfEB51YQ2qUKxjI,6250
32
+ meteostat/providers/dwd/monthly.py,sha256=JaXklCJrH_xlQPm1G6PXoVvV81qwnhT2o1mXXEzM2LQ,3658
33
+ meteostat/providers/dwd/mosmix.py,sha256=uDalWL-_Vayyq3iiiCUWPFmKXSYqQttXiDOF2Lk_qB4,8892
34
+ meteostat/providers/dwd/poi.py,sha256=Qv4eDsi_a8hdBQKl1LPQJ0BO2UbTxfba9gH5Ht2giZ0,3087
35
+ meteostat/providers/dwd/shared.py,sha256=SxrrJFei-9W671cIVDNx7U58nmJF-DPPe3TvmmYcayc,2918
36
+ meteostat/providers/eccc/daily.py,sha256=K-akr9JXYMnsdG1YlM9SPXUcDfVzv61KsCqD9Ieo6YM,2722
37
+ meteostat/providers/eccc/hourly.py,sha256=W2qMX0HxffMs1IlBzKY4b0M58wPJvtDw7Py4xyDuNO8,3209
38
+ meteostat/providers/eccc/monthly.py,sha256=eA5JRpDa7-2H-Ce4FOstY24ECWj_gTY5vRbvZa_LCLE,1805
39
+ meteostat/providers/eccc/shared.py,sha256=2m00uWYdWQrVqvxwMioLIKFxlrjLmCfqIYwjx30r_9k,1324
40
+ meteostat/providers/index.py,sha256=6UrzxtynwbILOxg_lmE_Ylh747GZzDW_6ytGIEQHTNc,12670
41
+ meteostat/providers/meteostat/daily.py,sha256=WVghOSm-yOstq7mI_e0BnMBQS8c_aCN9lR591AX8Aw0,1796
42
+ meteostat/providers/meteostat/daily_derived.py,sha256=_fiLSKxkaH9Caxp-Tg77rH39UXwy7SPDlCS_M-7kIqE,3170
43
+ meteostat/providers/meteostat/hourly.py,sha256=pK3dEVPuv6sTGTapyu7iY-nbEbrpis_r-1e5vBYVzqQ,1799
44
+ meteostat/providers/meteostat/monthly.py,sha256=-8X_VHY8Ei0YK6Vg8vnKs9tEUhxITL7PY3dzoaQyZmk,1254
45
+ meteostat/providers/meteostat/monthly_derived.py,sha256=8BNSd2-xqABdr3lDU_9noypF91qhRJPhz5liTK0eoR8,3075
46
+ meteostat/providers/meteostat/shared.py,sha256=3B1EyCWd1EmyNsmddm1CEoKb3QsVJEX9pwQ6SlSr3uw,2572
47
+ meteostat/providers/metno/forecast.py,sha256=NBtQlcY_DbwAFEpiI2SulkEHsbTbXcOcLB9zGv4KXGc,5662
48
+ meteostat/providers/noaa/ghcnd.py,sha256=AaR-efQkbgc3afwcvMd_H25_l1dV5CFmautn9TWQ6Cw,6789
49
+ meteostat/providers/noaa/isd_lite.py,sha256=YfqhWJjNjxirbqeGaRsQo07koEREvY-APVETkZ3eBKM,3817
50
+ meteostat/providers/noaa/metar.py,sha256=b9kGnWRKMeKcR3WZR3Mgdx6v0qA3Ac8vbtrOSCRz5KM,4189
51
+ meteostat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ meteostat/typing.py,sha256=Q4_le4P_yOVyv1FAxtccNDfFc0OPzYKm3p-GTTptGAY,3504
53
+ meteostat/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ meteostat/utils/conversions.py,sha256=B1qaL3_OSbWniIsFCwDPnwWtmglRiBBswFK1q0NH4bI,4755
55
+ meteostat/utils/data.py,sha256=d_aQy53jdhDAvFvo0qVPyhR2NH-WKIAeNm_kIobJOq8,6119
56
+ meteostat/utils/geo.py,sha256=n_imXze6-u0vzFdYrgPyStKqGNuERcUmXUA-PsAja2w,664
57
+ meteostat/utils/parsers.py,sha256=IDuffIdiTmOitarmv6VEYPVrhzT9GT6Gh57cayS_FsM,4941
58
+ meteostat/utils/types.py,sha256=_hzGcVueIGZdjCB6mR4vVFedrPUWw0iMRaLkpnqaN2Y,3470
59
+ meteostat/utils/validators.py,sha256=iBywF68ZhL3eD6fgemY2Tng3a-409eFU2oNZVqpYCpY,524
60
+ meteostat-2.0.0.dist-info/METADATA,sha256=bCqZ8ZhjVU8ygMcDemSDOwxL4jxQJ7E01l8YSacMDQY,5312
61
+ meteostat-2.0.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
62
+ meteostat-2.0.0.dist-info/licenses/LICENSE,sha256=kqpl7FVzWOCe11BZqJBZ1aRQi-aK87j3ljtG7P3VxLc,1066
63
+ meteostat-2.0.0.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.45.1)
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
meteostat/core/loader.py DELETED
@@ -1,103 +0,0 @@
1
- """
2
- Core Class - Data Loader
3
-
4
- Meteorological data provided by Meteostat (https://dev.meteostat.net)
5
- under the terms of the Creative Commons Attribution-NonCommercial
6
- 4.0 International Public License.
7
-
8
- The code is licensed under the MIT license.
9
- """
10
-
11
- from io import BytesIO
12
- from gzip import GzipFile
13
- from urllib.request import Request, ProxyHandler, build_opener
14
- from urllib.error import HTTPError
15
- from multiprocessing import Pool
16
- from multiprocessing.pool import ThreadPool
17
- from typing import Callable, List, Optional
18
- import pandas as pd
19
- from meteostat.core.warn import warn
20
-
21
-
22
- def processing_handler(
23
- datasets: List, load: Callable[[dict], None], cores: int, threads: int
24
- ) -> None:
25
- """
26
- Load multiple datasets (simultaneously)
27
- """
28
-
29
- # Data output
30
- output = []
31
-
32
- # Multi-core processing
33
- if cores > 1 and len(datasets) > 1:
34
- # Create process pool
35
- with Pool(cores) as pool:
36
- # Process datasets in pool
37
- output = pool.starmap(load, datasets)
38
-
39
- # Wait for Pool to finish
40
- pool.close()
41
- pool.join()
42
-
43
- # Multi-thread processing
44
- elif threads > 1 and len(datasets) > 1:
45
- # Create process pool
46
- with ThreadPool(threads) as pool:
47
- # Process datasets in pool
48
- output = pool.starmap(load, datasets)
49
-
50
- # Wait for Pool to finish
51
- pool.close()
52
- pool.join()
53
-
54
- # Single-thread processing
55
- else:
56
- for dataset in datasets:
57
- output.append(load(*dataset))
58
-
59
- # Remove empty DataFrames
60
- filtered = list(filter(lambda df: not df.empty, output))
61
-
62
- return pd.concat(filtered) if len(filtered) > 0 else output[0]
63
-
64
-
65
- def load_handler(
66
- endpoint: str,
67
- path: str,
68
- proxy: Optional[str] = None,
69
- names: Optional[List] = None,
70
- dtype: Optional[dict] = None,
71
- parse_dates: Optional[List] = None,
72
- default_df: Optional[pd.DataFrame] = None,
73
- ) -> pd.DataFrame:
74
- """
75
- Load a single CSV file into a DataFrame
76
- """
77
-
78
- try:
79
- handlers = []
80
-
81
- # Set a proxy
82
- if proxy:
83
- handlers.append(ProxyHandler({"http": proxy, "https": proxy}))
84
-
85
- # Read CSV file from Meteostat endpoint
86
- with build_opener(*handlers).open(Request(endpoint + path)) as response:
87
- # Decompress the content
88
- with GzipFile(fileobj=BytesIO(response.read()), mode="rb") as file:
89
- df = pd.read_csv(
90
- file,
91
- names=names,
92
- dtype=dtype,
93
- parse_dates=parse_dates,
94
- )
95
-
96
- except (FileNotFoundError, HTTPError):
97
- df = default_df if default_df is not None else pd.DataFrame(columns=names)
98
-
99
- # Display warning
100
- warn(f"Cannot load {path} from {endpoint}")
101
-
102
- # Return DataFrame
103
- return df
meteostat/core/warn.py DELETED
@@ -1,34 +0,0 @@
1
- """
2
- Core Class - Warnings
3
-
4
- Meteorological data provided by Meteostat (https://dev.meteostat.net)
5
- under the terms of the Creative Commons Attribution-NonCommercial
6
- 4.0 International Public License.
7
-
8
- The code is licensed under the MIT license.
9
- """
10
-
11
- import warnings
12
-
13
-
14
- def _format(message, category, _filename, _lineno, _line=None) -> str:
15
- """
16
- Print warning on a single line
17
- """
18
-
19
- return f"{category.__name__}: {message}\n"
20
-
21
-
22
- # Set warning format
23
- warnings.formatwarning = _format
24
-
25
-
26
- def warn(message: str) -> None:
27
- """
28
- Create a warning
29
- """
30
-
31
- try:
32
- warnings.warn(message, Warning)
33
- except TypeError:
34
- pass
@@ -1,22 +0,0 @@
1
- """
2
- Granularity Enumeration
3
-
4
- Meteorological data provided by Meteostat (https://dev.meteostat.net)
5
- under the terms of the Creative Commons Attribution-NonCommercial
6
- 4.0 International Public License.
7
-
8
- The code is licensed under the MIT license.
9
- """
10
-
11
- from enum import Enum
12
-
13
-
14
- class Granularity(Enum):
15
- """
16
- The different levels of time series granularity
17
- """
18
-
19
- HOURLY = "hourly"
20
- DAILY = "daily"
21
- MONTHLY = "monthly"
22
- NORMALS = "normals"
@@ -1,39 +0,0 @@
1
- """
2
- Base Interface Class
3
-
4
- Meteorological data provided by Meteostat (https://dev.meteostat.net)
5
- under the terms of the Creative Commons Attribution-NonCommercial
6
- 4.0 International Public License.
7
-
8
- The code is licensed under the MIT license.
9
- """
10
-
11
- import os
12
- from typing import Optional
13
-
14
-
15
- class Base:
16
- """
17
- Base class that provides features which are used across the package
18
- """
19
-
20
- # Base URL of the Meteostat bulk data interface
21
- endpoint = "https://bulk.meteostat.net/v2/"
22
-
23
- # Proxy URL for the Meteostat (bulk) data interface
24
- proxy: Optional[str] = None
25
-
26
- # Location of the cache directory
27
- cache_dir = os.path.expanduser("~") + os.sep + ".meteostat" + os.sep + "cache"
28
-
29
- # Auto clean cache directories?
30
- autoclean = True
31
-
32
- # Maximum age of a cached file in seconds
33
- max_age = 24 * 60 * 60
34
-
35
- # Number of processes used for processing files
36
- processes = 1
37
-
38
- # Number of threads used for processing files
39
- threads = 1
@@ -1,118 +0,0 @@
1
- """
2
- Daily Class
3
-
4
- Meteorological data provided by Meteostat (https://dev.meteostat.net)
5
- under the terms of the Creative Commons Attribution-NonCommercial
6
- 4.0 International Public License.
7
-
8
- The code is licensed under the MIT license.
9
- """
10
-
11
- from datetime import datetime, timedelta
12
- from typing import Union
13
- import pandas as pd
14
- from meteostat.enumerations.granularity import Granularity
15
- from meteostat.utilities.aggregations import degree_mean
16
- from meteostat.interface.timeseries import TimeSeries
17
- from meteostat.interface.point import Point
18
-
19
-
20
- class Daily(TimeSeries):
21
- """
22
- Retrieve daily weather observations for one or multiple weather stations or
23
- a single geographical point
24
- """
25
-
26
- # The cache subdirectory
27
- cache_subdir = "daily"
28
-
29
- # Granularity
30
- granularity = Granularity.DAILY
31
-
32
- # Download data as annual chunks
33
- # This cannot be changed and is only kept for backward compatibility
34
- chunked = True
35
-
36
- # Default frequency
37
- _freq = "1D"
38
-
39
- # Source mappings
40
- _source_mappings = {
41
- "dwd_daily": "A",
42
- "eccc_daily": "A",
43
- "ghcnd": "B",
44
- "dwd_hourly": "C",
45
- "eccc_hourly": "C",
46
- "isd_lite": "D",
47
- "synop": "E",
48
- "dwd_poi": "E",
49
- "metar": "F",
50
- "model": "G",
51
- "dwd_mosmix": "G",
52
- "metno_forecast": "G",
53
- }
54
-
55
- # Flag which represents model data
56
- _model_flag = "G"
57
-
58
- # Columns
59
- _columns = [
60
- "year",
61
- "month",
62
- "day",
63
- {"tavg": "temp"},
64
- "tmin",
65
- "tmax",
66
- "prcp",
67
- {"snow": "snwd"},
68
- {"wdir": None},
69
- "wspd",
70
- "wpgt",
71
- "pres",
72
- "tsun",
73
- ]
74
-
75
- # Index of first meteorological column
76
- _first_met_col = 3
77
-
78
- # Columns for date parsing
79
- _parse_dates = ["year", "month", "day"]
80
-
81
- # Default aggregation functions
82
- aggregations = {
83
- "tavg": "mean",
84
- "tmin": "min",
85
- "tmax": "max",
86
- "prcp": "sum",
87
- "snow": "max",
88
- "wdir": degree_mean,
89
- "wspd": "mean",
90
- "wpgt": "max",
91
- "pres": "mean",
92
- "tsun": "sum",
93
- }
94
-
95
- def __init__(
96
- self,
97
- loc: Union[pd.DataFrame, Point, list, str], # Station(s) or geo point
98
- start=datetime(1781, 1, 1, 0, 0, 0),
99
- end=datetime.combine(
100
- datetime.today().date() + timedelta(days=10), datetime.max.time()
101
- ),
102
- model=True, # Include model data?
103
- flags=False, # Load source flags?
104
- ) -> None:
105
- # Extract relevant years
106
- if self.chunked:
107
- self._annual_steps = [
108
- start.year + i for i in range(end.year - start.year + 1)
109
- ]
110
- # Initialize time series
111
- self._init_time_series(loc, start, end, model, flags)
112
-
113
- def expected_rows(self) -> int:
114
- """
115
- Return the number of rows expected for the defined date range
116
- """
117
-
118
- return (self._end - self._start).days + 1