python-weather 2.2.0__tar.gz → 2.2.2__tar.gz
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.
- {python_weather-2.2.0/python_weather.egg-info → python_weather-2.2.2}/PKG-INFO +8 -1
- {python_weather-2.2.0 → python_weather-2.2.2}/pyproject.toml +4 -1
- {python_weather-2.2.0 → python_weather-2.2.2}/python_weather/base.py +6 -2
- {python_weather-2.2.0 → python_weather-2.2.2}/python_weather/client.py +3 -5
- {python_weather-2.2.0 → python_weather-2.2.2}/python_weather/constants.py +2 -25
- {python_weather-2.2.0 → python_weather-2.2.2}/python_weather/errors.py +6 -7
- {python_weather-2.2.0 → python_weather-2.2.2}/python_weather/forecast.py +8 -4
- {python_weather-2.2.0 → python_weather-2.2.2}/python_weather/version.py +1 -1
- {python_weather-2.2.0 → python_weather-2.2.2/python_weather.egg-info}/PKG-INFO +8 -1
- python_weather-2.2.2/python_weather.egg-info/requires.txt +9 -0
- python_weather-2.2.0/python_weather.egg-info/requires.txt +0 -1
- {python_weather-2.2.0 → python_weather-2.2.2}/LICENSE +0 -0
- {python_weather-2.2.0 → python_weather-2.2.2}/MANIFEST.in +0 -0
- {python_weather-2.2.0 → python_weather-2.2.2}/README.md +0 -0
- {python_weather-2.2.0 → python_weather-2.2.2}/python_weather/__init__.py +0 -0
- {python_weather-2.2.0 → python_weather-2.2.2}/python_weather/enums.py +0 -0
- {python_weather-2.2.0 → python_weather-2.2.2}/python_weather.egg-info/SOURCES.txt +0 -0
- {python_weather-2.2.0 → python_weather-2.2.2}/python_weather.egg-info/dependency_links.txt +0 -0
- {python_weather-2.2.0 → python_weather-2.2.2}/python_weather.egg-info/top_level.txt +0 -0
- {python_weather-2.2.0 → python_weather-2.2.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-weather
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: A free and asynchronous weather API wrapper made in Python, for Python.
|
|
5
5
|
Author: null8626
|
|
6
6
|
License-Expression: MIT
|
|
@@ -34,6 +34,13 @@ Requires-Python: >=3.10
|
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
35
|
License-File: LICENSE
|
|
36
36
|
Requires-Dist: aiohttp>=3.13.5
|
|
37
|
+
Provides-Extra: dev
|
|
38
|
+
Requires-Dist: mock>=5.2.0; extra == "dev"
|
|
39
|
+
Requires-Dist: pytest>=9.0.3; extra == "dev"
|
|
40
|
+
Requires-Dist: pytest-asyncio>=1.3.0; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
|
|
42
|
+
Requires-Dist: multidict>=6.7.1; extra == "dev"
|
|
43
|
+
Requires-Dist: yarl>=1.23.0; extra == "dev"
|
|
37
44
|
Dynamic: license-file
|
|
38
45
|
|
|
39
46
|
# [python-weather][pypi-url] [![pypi][pypi-image]][pypi-url] [![pypi downloads][pypi-downloads-image]][pypi-url] [![codacy-badge][codacy-image]][codacy-url] [![codecov-badge][codecov-image]][codecov-url] [![ko-fi][ko-fi-brief-image]][ko-fi-url]
|
|
@@ -3,7 +3,7 @@ requires = ["setuptools"]
|
|
|
3
3
|
|
|
4
4
|
[project]
|
|
5
5
|
name = "python-weather"
|
|
6
|
-
version = "2.2.
|
|
6
|
+
version = "2.2.2"
|
|
7
7
|
description = "A free and asynchronous weather API wrapper made in Python, for Python."
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
license = "MIT"
|
|
@@ -34,6 +34,9 @@ classifiers = [
|
|
|
34
34
|
]
|
|
35
35
|
requires-python = ">=3.10"
|
|
36
36
|
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
dev = ["mock>=5.2.0", "pytest>=9.0.3", "pytest-asyncio>=1.3.0", "pytest-cov>=7.1.0", "multidict>=6.7.1", "yarl>=1.23.0"]
|
|
39
|
+
|
|
37
40
|
[project.urls]
|
|
38
41
|
Documentation = "https://python-weather.readthedocs.io/en/latest/"
|
|
39
42
|
Repository = "https://github.com/null8626/python-weather"
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
|
2
2
|
# SPDX-FileCopyrightText: 2021-2026 null8626
|
|
3
3
|
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
4
6
|
from .enums import WindDirection, Kind, Locale, UltraViolet
|
|
5
|
-
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from .constants import _Unit
|
|
6
10
|
|
|
7
11
|
|
|
8
12
|
class BaseForecast:
|
|
@@ -59,7 +63,7 @@ class BaseForecast:
|
|
|
59
63
|
description: str
|
|
60
64
|
"""The description regarding the forecast depending on the localization used."""
|
|
61
65
|
|
|
62
|
-
def __init__(self, json: dict, unit: _Unit, locale: Locale):
|
|
66
|
+
def __init__(self, json: dict, unit: '_Unit', locale: Locale):
|
|
63
67
|
description = (
|
|
64
68
|
json['weatherDesc'][0]['value']
|
|
65
69
|
if locale is Locale.ENGLISH
|
|
@@ -64,14 +64,14 @@ class Client:
|
|
|
64
64
|
unit: _Unit = METRIC,
|
|
65
65
|
locale: Locale = Locale.ENGLISH,
|
|
66
66
|
session: ClientSession | None = None,
|
|
67
|
-
max_retries: int
|
|
67
|
+
max_retries: int = 3,
|
|
68
68
|
):
|
|
69
69
|
self.__own_session = session is None
|
|
70
70
|
self.__session = session or ClientSession(
|
|
71
71
|
timeout=ClientTimeout(total=5000.0),
|
|
72
72
|
connector=TCPConnector(ssl=False),
|
|
73
73
|
)
|
|
74
|
-
self._max_retries = max_retries
|
|
74
|
+
self._max_retries = max_retries
|
|
75
75
|
self.unit = unit
|
|
76
76
|
self.locale = locale
|
|
77
77
|
|
|
@@ -182,9 +182,7 @@ class Client:
|
|
|
182
182
|
|
|
183
183
|
resp.raise_for_status()
|
|
184
184
|
|
|
185
|
-
return Forecast(
|
|
186
|
-
await resp.json(content_type='application/text'), unit, locale
|
|
187
|
-
)
|
|
185
|
+
return Forecast(await resp.json(content_type='text/plain'), unit, locale)
|
|
188
186
|
except ClientResponseError:
|
|
189
187
|
if attempts == self._max_retries:
|
|
190
188
|
raise RequestError(status, reason) from None
|
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
|
2
2
|
# SPDX-FileCopyrightText: 2021-2026 null8626
|
|
3
3
|
|
|
4
|
+
from dataclasses import dataclass
|
|
4
5
|
import re
|
|
5
6
|
|
|
6
7
|
|
|
8
|
+
@dataclass(frozen=True, repr=False, slots=True)
|
|
7
9
|
class _Unit:
|
|
8
10
|
"""A supported measurement unit."""
|
|
9
11
|
|
|
10
|
-
__slots__: tuple[str, ...] = (
|
|
11
|
-
'temperature',
|
|
12
|
-
'velocity',
|
|
13
|
-
'pressure',
|
|
14
|
-
'precipitation',
|
|
15
|
-
'visibility',
|
|
16
|
-
'cm_divisor',
|
|
17
|
-
)
|
|
18
|
-
|
|
19
12
|
temperature: str
|
|
20
13
|
velocity: str
|
|
21
14
|
pressure: str
|
|
@@ -23,22 +16,6 @@ class _Unit:
|
|
|
23
16
|
visibility: str
|
|
24
17
|
cm_divisor: float | int
|
|
25
18
|
|
|
26
|
-
def __init__(
|
|
27
|
-
self,
|
|
28
|
-
temperature: str,
|
|
29
|
-
velocity: str,
|
|
30
|
-
pressure: str,
|
|
31
|
-
precipitation: str,
|
|
32
|
-
visibility: str,
|
|
33
|
-
cm_divisor: float | int,
|
|
34
|
-
):
|
|
35
|
-
self.temperature = temperature
|
|
36
|
-
self.velocity = velocity
|
|
37
|
-
self.pressure = pressure
|
|
38
|
-
self.precipitation = precipitation
|
|
39
|
-
self.visibility = visibility
|
|
40
|
-
self.cm_divisor = cm_divisor
|
|
41
|
-
|
|
42
19
|
def __repr__(self) -> str:
|
|
43
20
|
"""The unit's debug string representation."""
|
|
44
21
|
return f'<Unit [{self.temperature}, {self.velocity}]>'
|
|
@@ -2,28 +2,27 @@
|
|
|
2
2
|
# SPDX-FileCopyrightText: 2021-2026 null8626
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
|
|
5
8
|
class Error(Exception):
|
|
6
9
|
"""The base error class. Extends :py:class:`Exception`."""
|
|
7
10
|
|
|
8
11
|
__slots__: tuple[str, ...] = ()
|
|
9
12
|
|
|
10
13
|
|
|
14
|
+
@dataclass(frozen=True, repr=False, slots=True)
|
|
11
15
|
class RequestError(Error):
|
|
12
16
|
"""Thrown upon HTTP request failure. Extends :class:`.Error`."""
|
|
13
17
|
|
|
14
|
-
__slots__: tuple[str, ...] = 'status', 'reason'
|
|
15
|
-
|
|
16
18
|
status: int | None
|
|
17
19
|
"""The status code."""
|
|
18
20
|
|
|
19
21
|
reason: str | None
|
|
20
22
|
"""The reason for this status code."""
|
|
21
23
|
|
|
22
|
-
def
|
|
23
|
-
self.status
|
|
24
|
-
self.reason = reason
|
|
25
|
-
|
|
26
|
-
super().__init__(f'{status}: {reason}')
|
|
24
|
+
def __post_init__(self) -> None:
|
|
25
|
+
super(Error, self).__init__(f'{self.status}: {self.reason}')
|
|
27
26
|
|
|
28
27
|
def __repr__(self) -> str: # pragma: nocover
|
|
29
28
|
"""The error's debug string representation."""
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
# SPDX-FileCopyrightText: 2021-2026 null8626
|
|
3
3
|
|
|
4
4
|
from datetime import datetime, date, time
|
|
5
|
-
from collections.abc import Iterator
|
|
6
5
|
from typing import TYPE_CHECKING
|
|
7
6
|
|
|
8
7
|
from .enums import Phase, HeatIndex
|
|
@@ -10,6 +9,8 @@ from .constants import LATLON_REGEX
|
|
|
10
9
|
from .base import BaseForecast
|
|
11
10
|
|
|
12
11
|
if TYPE_CHECKING:
|
|
12
|
+
from collections.abc import Iterator
|
|
13
|
+
|
|
13
14
|
from .constants import _Unit
|
|
14
15
|
from .enums import Locale
|
|
15
16
|
|
|
@@ -209,7 +210,7 @@ class DailyForecast:
|
|
|
209
210
|
"""The amount of hourly forecasts."""
|
|
210
211
|
return len(self.hourly_forecasts)
|
|
211
212
|
|
|
212
|
-
def __iter__(self) -> Iterator[HourlyForecast]:
|
|
213
|
+
def __iter__(self) -> 'Iterator[HourlyForecast]':
|
|
213
214
|
"""Iterates through the hourly forecasts."""
|
|
214
215
|
return iter(self.hourly_forecasts)
|
|
215
216
|
|
|
@@ -256,7 +257,10 @@ class Forecast(BaseForecast):
|
|
|
256
257
|
self.region = nearest['region'][0]['value']
|
|
257
258
|
self.location = nearest['areaName'][0]['value']
|
|
258
259
|
self.country = nearest['country'][0]['value']
|
|
259
|
-
self.datetime = datetime.
|
|
260
|
+
self.datetime = datetime.combine(
|
|
261
|
+
datetime.today(),
|
|
262
|
+
datetime.strptime(current['observation_time'], '%I:%M %p').time(),
|
|
263
|
+
)
|
|
260
264
|
|
|
261
265
|
try:
|
|
262
266
|
req = next(filter(lambda x: x['type'] == 'LatLon', json['request']))
|
|
@@ -283,6 +287,6 @@ class Forecast(BaseForecast):
|
|
|
283
287
|
"""The amount of daily forecasts."""
|
|
284
288
|
return len(self.daily_forecasts)
|
|
285
289
|
|
|
286
|
-
def __iter__(self) -> Iterator[DailyForecast]:
|
|
290
|
+
def __iter__(self) -> 'Iterator[DailyForecast]':
|
|
287
291
|
"""Iterates through the daily forecasts."""
|
|
288
292
|
return iter(self.daily_forecasts)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-weather
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: A free and asynchronous weather API wrapper made in Python, for Python.
|
|
5
5
|
Author: null8626
|
|
6
6
|
License-Expression: MIT
|
|
@@ -34,6 +34,13 @@ Requires-Python: >=3.10
|
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
35
|
License-File: LICENSE
|
|
36
36
|
Requires-Dist: aiohttp>=3.13.5
|
|
37
|
+
Provides-Extra: dev
|
|
38
|
+
Requires-Dist: mock>=5.2.0; extra == "dev"
|
|
39
|
+
Requires-Dist: pytest>=9.0.3; extra == "dev"
|
|
40
|
+
Requires-Dist: pytest-asyncio>=1.3.0; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
|
|
42
|
+
Requires-Dist: multidict>=6.7.1; extra == "dev"
|
|
43
|
+
Requires-Dist: yarl>=1.23.0; extra == "dev"
|
|
37
44
|
Dynamic: license-file
|
|
38
45
|
|
|
39
46
|
# [python-weather][pypi-url] [![pypi][pypi-image]][pypi-url] [![pypi downloads][pypi-downloads-image]][pypi-url] [![codacy-badge][codacy-image]][codacy-url] [![codecov-badge][codecov-image]][codecov-url] [![ko-fi][ko-fi-brief-image]][ko-fi-url]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
aiohttp>=3.13.5
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|