meteostat 1.7.6__py3-none-any.whl → 2.0.1__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 (94) hide show
  1. meteostat/__init__.py +38 -19
  2. meteostat/api/config.py +158 -0
  3. meteostat/api/daily.py +76 -0
  4. meteostat/api/hourly.py +80 -0
  5. meteostat/api/interpolate.py +378 -0
  6. meteostat/api/inventory.py +59 -0
  7. meteostat/api/merge.py +103 -0
  8. meteostat/api/monthly.py +73 -0
  9. meteostat/api/normals.py +144 -0
  10. meteostat/api/point.py +30 -0
  11. meteostat/api/stations.py +234 -0
  12. meteostat/api/timeseries.py +334 -0
  13. meteostat/core/cache.py +212 -59
  14. meteostat/core/data.py +203 -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/guards.py +51 -0
  53. meteostat/utils/parsers.py +161 -0
  54. meteostat/utils/types.py +113 -0
  55. meteostat/utils/validators.py +31 -0
  56. meteostat-2.0.1.dist-info/METADATA +130 -0
  57. meteostat-2.0.1.dist-info/RECORD +64 -0
  58. {meteostat-1.7.6.dist-info → meteostat-2.0.1.dist-info}/WHEEL +1 -2
  59. meteostat/core/loader.py +0 -103
  60. meteostat/core/warn.py +0 -34
  61. meteostat/enumerations/granularity.py +0 -22
  62. meteostat/interface/base.py +0 -39
  63. meteostat/interface/daily.py +0 -118
  64. meteostat/interface/hourly.py +0 -154
  65. meteostat/interface/meteodata.py +0 -210
  66. meteostat/interface/monthly.py +0 -109
  67. meteostat/interface/normals.py +0 -245
  68. meteostat/interface/point.py +0 -143
  69. meteostat/interface/stations.py +0 -252
  70. meteostat/interface/timeseries.py +0 -237
  71. meteostat/series/aggregate.py +0 -48
  72. meteostat/series/convert.py +0 -28
  73. meteostat/series/count.py +0 -17
  74. meteostat/series/coverage.py +0 -20
  75. meteostat/series/fetch.py +0 -28
  76. meteostat/series/interpolate.py +0 -47
  77. meteostat/series/normalize.py +0 -76
  78. meteostat/series/stations.py +0 -22
  79. meteostat/units.py +0 -149
  80. meteostat/utilities/__init__.py +0 -0
  81. meteostat/utilities/aggregations.py +0 -37
  82. meteostat/utilities/endpoint.py +0 -33
  83. meteostat/utilities/helpers.py +0 -70
  84. meteostat/utilities/mutations.py +0 -89
  85. meteostat/utilities/validations.py +0 -30
  86. meteostat-1.7.6.dist-info/METADATA +0 -112
  87. meteostat-1.7.6.dist-info/RECORD +0 -39
  88. meteostat-1.7.6.dist-info/top_level.txt +0 -1
  89. /meteostat/{core → api}/__init__.py +0 -0
  90. /meteostat/{enumerations → interpolation}/__init__.py +0 -0
  91. /meteostat/{interface → providers}/__init__.py +0 -0
  92. /meteostat/{interface/interpolate.py → py.typed} +0 -0
  93. /meteostat/{series → utils}/__init__.py +0 -0
  94. {meteostat-1.7.6.dist-info → meteostat-2.0.1.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,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: meteostat
3
+ Version: 2.0.1
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
+ [![Downloads][downloads-shield]][downloads-url]
22
+ [![Provider Tests][provider-tests-shield]][provider-tests-url]
23
+ [![Issues][issues-shield]][issues-url]
24
+ [![MIT License][license-shield]][license-url]
25
+ [![Stargazers][stars-shield]][stars-url]
26
+
27
+ </div>
28
+
29
+
30
+ <!-- PROJECT LOGO -->
31
+ <br />
32
+ <div align="center">
33
+ <a href="https://github.com/meteostat/meteostat">
34
+ <img src="https://media.meteostat.net/icon.svg" alt="Meteostat Logo" width="80" height="80">
35
+ </a>
36
+
37
+ <h3 align="center">Meteostat Python Package</h3>
38
+
39
+ <p align="center">
40
+ Access and analyze historical weather and climate data with Python.
41
+ <p>
42
+ <a href="https://dev.meteostat.net/python"><strong>Explore the docs »</strong></a>
43
+ </p>
44
+ <p>
45
+ <a href="https://meteostat.net">Visit Website</a>
46
+ &middot;
47
+ <a href="https://github.com/meteostat/meteostat/issues">Report Bug</a>
48
+ &middot;
49
+ <a href="https://github.com/orgs/meteostat/discussions">Request Feature</a>
50
+ </p>
51
+ </p>
52
+ </div>
53
+
54
+ ## 📚 Installation
55
+
56
+ The Meteostat Python package is available through [PyPI](https://pypi.org/project/meteostat/):
57
+
58
+ ```sh
59
+ pip install meteostat
60
+ ```
61
+
62
+ ## 🚀 Usage
63
+
64
+ Let's plot 2018 temperature data for Frankfurt, Germany:
65
+
66
+ ```python
67
+ from datetime import date
68
+ import matplotlib.pyplot as plt
69
+ import meteostat as ms
70
+
71
+ # Specify location and time range
72
+ POINT = ms.Point(50.1155, 8.6842, 113) # Try with your location
73
+ START = date(2018, 1, 1)
74
+ END = date(2018, 12, 31)
75
+
76
+ # Get nearby weather stations
77
+ stations = ms.stations.nearby(POINT, limit=4)
78
+
79
+ # Get daily data & perform interpolation
80
+ ts = ms.daily(stations, START, END)
81
+ df = ms.interpolate(ts, POINT).fetch()
82
+
83
+ # Plot line chart including average, minimum and maximum temperature
84
+ df.plot(y=[ms.Parameter.TEMP, ms.Parameter.TMIN, ms.Parameter.TMAX])
85
+ plt.show()
86
+ ```
87
+
88
+ Take a look at the expected output:
89
+
90
+ ![2018 temperature data for Frankfurt, Germany][product-screenshot]
91
+
92
+ ## 🤝 Contributing
93
+
94
+ Please read our [contributing guidelines](https://dev.meteostat.net/python/contributing) for details on how to contribute to the Meteostat Python library.
95
+
96
+ **Top contributors**
97
+
98
+ <a href="https://github.com/meteostat/meteostat/graphs/contributors">
99
+ <img src="https://contrib.rocks/image?repo=meteostat/meteostat" alt="Meteostat Contributors" />
100
+ </a>
101
+
102
+ ## 🌟 Featured In
103
+
104
+ Meteostat has been featured and used by various media outlets and organizations, including:
105
+
106
+ - [Towards Data Science](https://towardsdatascience.com/get-temperature-data-by-location-with-python-52ed872dd621/)
107
+ - [ZEIT ONLINE](https://www.zeit.de/digital/internet/2022-03/desinformation-russland-ukraine-fotos-fake-news-falschinformation-echtheit)
108
+ - [Deutsche Presse-Agentur (dpa)](https://dpa-factchecking.com/germany/230103-99-92282/)
109
+ - [heise online](https://www.heise.de/news/Open-Source-Projekt-zu-Klimadaten-Meteostat-Python-Library-1-0-erschienen-4985015.html)
110
+
111
+ Join the growing community of users and researchers relying on Meteostat for their weather data needs.
112
+
113
+ ## 📄 License
114
+
115
+ 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.
116
+
117
+
118
+ <!-- MARKDOWN LINKS & IMAGES -->
119
+ <!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
120
+ [downloads-shield]: https://img.shields.io/pypi/dm/meteostat
121
+ [downloads-url]: https://pypi.org/project/meteostat/
122
+ [provider-tests-shield]: https://github.com/meteostat/meteostat/actions/workflows/provider-tests.yml/badge.svg
123
+ [provider-tests-url]: https://github.com/meteostat/meteostat/actions/workflows/provider-tests.yml
124
+ [issues-shield]: https://img.shields.io/github/issues/meteostat/meteostat.svg
125
+ [issues-url]: https://github.com/meteostat/meteostat/issues
126
+ [license-shield]: https://img.shields.io/github/license/meteostat/meteostat.svg
127
+ [license-url]: https://github.com/meteostat/meteostat?tab=readme-ov-file#-license
128
+ [product-screenshot]: https://dev.meteostat.net/assets/images/example-8b6cf2a3fe2efa285bc72d7dc72c4865.png
129
+ [stars-shield]: https://img.shields.io/github/stars/meteostat/meteostat.svg
130
+ [stars-url]: https://github.com/meteostat/meteostat/stargazers
@@ -0,0 +1,64 @@
1
+ meteostat/__init__.py,sha256=uoBFnarB7WQtLj61mM-U2FHBq06FLHKLfdSKlTVq7i4,1555
2
+ meteostat/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ meteostat/api/config.py,sha256=DpZ20TLcc7S1uJV_N_SBv2qtVorNgB0hFzX2sHs0tXM,5065
4
+ meteostat/api/daily.py,sha256=SUYxR7HC5Cqyd6cBG42QmSpEP74HwDq5VnqfSznM46Y,2371
5
+ meteostat/api/hourly.py,sha256=KGJ4xBwO__fBrQ5ll5ruLEkrpOCD8bybSBcXJ94-ntE,2556
6
+ meteostat/api/interpolate.py,sha256=6i128g_x5ea3X2Nkn6IlrtPaKqRfakozOcSheTbmxIM,12602
7
+ meteostat/api/inventory.py,sha256=xida9SVdYPm4GpiloVg-zXvkeUi7Egaj_XbxWWhNHuI,1405
8
+ meteostat/api/merge.py,sha256=CtoItPFsRxXWu50g1zjC9q94wTDC6ZzCLhvU3jmZhX4,2638
9
+ meteostat/api/monthly.py,sha256=cZmJiwVNxw5nNNmrx0ohy9bIN_dSt1Nk8crxcCJsJvU,2327
10
+ meteostat/api/normals.py,sha256=3CbRCYrp_mATZwkWbgBphcmLvhoR_hSaDCj0hfsIlKk,5138
11
+ meteostat/api/point.py,sha256=T4fRcf_ozE3O_ywS8lneSfG_dWexk-cNmVHLJKB_idc,718
12
+ meteostat/api/stations.py,sha256=RuS4yhxq-YJ_IOLhXGv-Y3h__8SlkmmtU1BnGUUe9jI,7001
13
+ meteostat/api/timeseries.py,sha256=zwrIT6URl4R4JYEFUDorn5QZg3VRMeKR2XMOF9D9REc,9889
14
+ meteostat/core/cache.py,sha256=Xo6KyExsCw9cRI_6-yJxJIJ9TfQ7x0IMMKarpZb2598,6645
15
+ meteostat/core/data.py,sha256=wnoqgRXeWNVCAcI_SDH-shLGpx_4z5wE6a5ayqbpZnU,5754
16
+ meteostat/core/logger.py,sha256=MUqPTxpw6C9zky4lCeOac9rLjjYkaiHVGVVvLuxKgEg,146
17
+ meteostat/core/network.py,sha256=JGjjWEpJEYJR6Q3NDbOOYdLo9laiValAip5jrxEnzKA,1939
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=D5Y2DLMgjCNmqfdm2J5MU67w0O6L0vx_TbgMaGrMQuc,2637
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=jEHvg9m8L0161n1j7DHOiBWyky7WL0SD-TrlkljoYCI,4875
30
+ meteostat/providers/dwd/daily.py,sha256=qVZjMUu6a1GODaWrKpzbOYdXS9HyEkKp9XwnY47Md44,4030
31
+ meteostat/providers/dwd/hourly.py,sha256=LAjnQJrp80wOhX24JwuceAtCi104DC8EDwEZetHDrso,6249
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=z4LT0fd7LFUqpVPJRJyNWJxK_6TRzJFDvolv6_Y9PME,2917
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=32vh0J5caMT9gshfUBQXoH8CB3r3qf4BUlB3VztvPN0,1795
42
+ meteostat/providers/meteostat/daily_derived.py,sha256=_fiLSKxkaH9Caxp-Tg77rH39UXwy7SPDlCS_M-7kIqE,3170
43
+ meteostat/providers/meteostat/hourly.py,sha256=INO5JVaDbd3zIEo3_spIwACoBpYqDXinyrL-pW1AIAk,1798
44
+ meteostat/providers/meteostat/monthly.py,sha256=4N2ThwBroQVz2wI5UI2WpvIUGOH61gS63rP8ZVaMqOE,1253
45
+ meteostat/providers/meteostat/monthly_derived.py,sha256=8BNSd2-xqABdr3lDU_9noypF91qhRJPhz5liTK0eoR8,3075
46
+ meteostat/providers/meteostat/shared.py,sha256=mK2K3tbgtCcKLMITR5NJVuJSBkPm_jLcN0dBRT9hM90,2571
47
+ meteostat/providers/metno/forecast.py,sha256=x-q21HiGkJ4yiv7vKcPnVSFin3rFGHWAZqtzJE0j4Tk,5661
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=wqH0zEUZO0gS0inK5vvxKulz-LF3NEZIAsYHmR0Do64,4188
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/guards.py,sha256=fuBd4_6BXfZT_jPYU6GzXgDBnCc_GVLDpI6PSK3PCno,1746
58
+ meteostat/utils/parsers.py,sha256=2y-QSubyrh_xdXJBdgWNiWNI_DDXCGxddcjGOZB9hCU,4646
59
+ meteostat/utils/types.py,sha256=_hzGcVueIGZdjCB6mR4vVFedrPUWw0iMRaLkpnqaN2Y,3470
60
+ meteostat/utils/validators.py,sha256=iBywF68ZhL3eD6fgemY2Tng3a-409eFU2oNZVqpYCpY,524
61
+ meteostat-2.0.1.dist-info/METADATA,sha256=cAXHfPnAXC-3gEpeUMfmRqURQWjOufDsXHfX_fjm650,5024
62
+ meteostat-2.0.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
63
+ meteostat-2.0.1.dist-info/licenses/LICENSE,sha256=kqpl7FVzWOCe11BZqJBZ1aRQi-aK87j3ljtG7P3VxLc,1066
64
+ meteostat-2.0.1.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