python-weather 1.0.2__tar.gz → 1.1.0__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-1.0.2/python_weather.egg-info → python-weather-1.1.0}/PKG-INFO +4 -3
- {python-weather-1.0.2 → python-weather-1.1.0}/pyproject.toml +4 -4
- {python-weather-1.0.2 → python-weather-1.1.0}/python_weather/__init__.py +1 -1
- {python-weather-1.0.2 → python-weather-1.1.0}/python_weather/base.py +12 -22
- {python-weather-1.0.2 → python-weather-1.1.0}/python_weather/client.py +2 -2
- {python-weather-1.0.2 → python-weather-1.1.0}/python_weather/constants.py +28 -3
- {python-weather-1.0.2 → python-weather-1.1.0}/python_weather/enums.py +135 -31
- {python-weather-1.0.2 → python-weather-1.1.0}/python_weather/forecast.py +15 -15
- {python-weather-1.0.2 → python-weather-1.1.0/python_weather.egg-info}/PKG-INFO +4 -3
- python-weather-1.1.0/python_weather.egg-info/requires.txt +1 -0
- python-weather-1.0.2/python_weather.egg-info/requires.txt +0 -1
- {python-weather-1.0.2 → python-weather-1.1.0}/LICENSE +0 -0
- {python-weather-1.0.2 → python-weather-1.1.0}/MANIFEST.in +0 -0
- {python-weather-1.0.2 → python-weather-1.1.0}/README.md +0 -0
- {python-weather-1.0.2 → python-weather-1.1.0}/python_weather/errors.py +0 -0
- {python-weather-1.0.2 → python-weather-1.1.0}/python_weather.egg-info/SOURCES.txt +0 -0
- {python-weather-1.0.2 → python-weather-1.1.0}/python_weather.egg-info/dependency_links.txt +0 -0
- {python-weather-1.0.2 → python-weather-1.1.0}/python_weather.egg-info/top_level.txt +0 -0
- {python-weather-1.0.2 → python-weather-1.1.0}/setup.cfg +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-weather
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: A free and asynchronous weather API wrapper made in Python, for Python.
|
|
5
5
|
Author: null8626
|
|
6
6
|
License: MIT
|
|
7
7
|
Project-URL: repository, https://github.com/null8626/python-weather
|
|
8
|
-
Project-URL: download_url, https://github.com/null8626/python-weather/archive/1.0.
|
|
8
|
+
Project-URL: download_url, https://github.com/null8626/python-weather/archive/1.1.0.tar.gz
|
|
9
9
|
Keywords: weather,forecast,weather-api,weather-forecast
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Framework :: aiohttp
|
|
@@ -29,9 +29,10 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
29
29
|
Classifier: Programming Language :: Python :: 3.10
|
|
30
30
|
Classifier: Programming Language :: Python :: 3.11
|
|
31
31
|
Classifier: Programming Language :: Python :: 3.12
|
|
32
|
-
Requires-Python: >=3.
|
|
32
|
+
Requires-Python: >=3.8
|
|
33
33
|
Description-Content-Type: text/markdown
|
|
34
34
|
License-File: LICENSE
|
|
35
|
+
Requires-Dist: aiohttp==3.9.0
|
|
35
36
|
|
|
36
37
|
# [python-weather][pypi-url] [![pypi][pypi-image]][pypi-url] [![downloads][downloads-image]][pypi-url] [![Build Status][ci-image]][ci-url] [![license][github-license-image]][github-license-url] [![BLAZINGLY FAST!!!][blazingly-fast-image]][blazingly-fast-url]
|
|
37
38
|
|
|
@@ -3,13 +3,13 @@ requires = ["setuptools"]
|
|
|
3
3
|
|
|
4
4
|
[project]
|
|
5
5
|
name = "python-weather"
|
|
6
|
-
version = "1.0
|
|
6
|
+
version = "1.1.0"
|
|
7
7
|
description = "A free and asynchronous weather API wrapper made in Python, for Python."
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
license = { text = "MIT" }
|
|
10
10
|
authors = [{ name = "null8626" }]
|
|
11
11
|
keywords = ["weather", "forecast", "weather-api", "weather-forecast"]
|
|
12
|
-
dependencies = ["aiohttp==3.
|
|
12
|
+
dependencies = ["aiohttp==3.9.0"]
|
|
13
13
|
classifiers = [
|
|
14
14
|
"Development Status :: 5 - Production/Stable",
|
|
15
15
|
"Framework :: aiohttp",
|
|
@@ -34,8 +34,8 @@ classifiers = [
|
|
|
34
34
|
"Programming Language :: Python :: 3.11",
|
|
35
35
|
"Programming Language :: Python :: 3.12"
|
|
36
36
|
]
|
|
37
|
-
requires-python = ">=3.
|
|
37
|
+
requires-python = ">=3.8"
|
|
38
38
|
|
|
39
39
|
[project.urls]
|
|
40
40
|
repository = "https://github.com/null8626/python-weather"
|
|
41
|
-
download_url = "https://github.com/null8626/python-weather/archive/1.0.
|
|
41
|
+
download_url = "https://github.com/null8626/python-weather/archive/1.1.0.tar.gz"
|
|
@@ -30,7 +30,7 @@ from .constants import METRIC, IMPERIAL
|
|
|
30
30
|
from .client import Client
|
|
31
31
|
from .errors import Error
|
|
32
32
|
|
|
33
|
-
__version__ = '1.0.
|
|
33
|
+
__version__ = '1.0.3'
|
|
34
34
|
__all__ = (
|
|
35
35
|
'METRIC', 'IMPERIAL', 'Client', 'Error', 'Kind', 'Locale', 'Phase',
|
|
36
36
|
'Ultraviolet', 'WindDirection'
|
|
@@ -25,12 +25,12 @@ SOFTWARE.
|
|
|
25
25
|
from enum import auto, Enum
|
|
26
26
|
|
|
27
27
|
from .enums import WindDirection, Kind, Locale, Ultraviolet
|
|
28
|
-
from .constants import
|
|
28
|
+
from .constants import _Unit
|
|
29
29
|
|
|
30
30
|
class CustomizableBase:
|
|
31
31
|
__slots__ = ('__unit', '__locale')
|
|
32
32
|
|
|
33
|
-
def __init__(self, unit:
|
|
33
|
+
def __init__(self, unit: _Unit, locale: Locale):
|
|
34
34
|
self.unit = unit
|
|
35
35
|
self.locale = locale
|
|
36
36
|
|
|
@@ -41,7 +41,7 @@ class CustomizableBase:
|
|
|
41
41
|
return self.__unit
|
|
42
42
|
|
|
43
43
|
@unit.setter
|
|
44
|
-
def unit(self, to:
|
|
44
|
+
def unit(self, to: _Unit):
|
|
45
45
|
"""
|
|
46
46
|
Sets the default measuring unit used to display information in this object.
|
|
47
47
|
|
|
@@ -56,7 +56,7 @@ class CustomizableBase:
|
|
|
56
56
|
If the ``to`` argument is not either :attr:`METRIC` or :attr:`IMPERIAL`.
|
|
57
57
|
"""
|
|
58
58
|
|
|
59
|
-
if
|
|
59
|
+
if not isinstance(to, _Unit):
|
|
60
60
|
raise Error('Invalid measuring unit specified!')
|
|
61
61
|
|
|
62
62
|
self.__unit = to
|
|
@@ -91,7 +91,7 @@ class CustomizableBase:
|
|
|
91
91
|
class BaseForecast(CustomizableBase):
|
|
92
92
|
__slots__ = ('__inner',)
|
|
93
93
|
|
|
94
|
-
def __init__(self, json: dict, unit:
|
|
94
|
+
def __init__(self, json: dict, unit: _Unit, locale: Locale):
|
|
95
95
|
self.__inner = json
|
|
96
96
|
|
|
97
97
|
super().__init__(unit, locale)
|
|
@@ -100,15 +100,14 @@ class BaseForecast(CustomizableBase):
|
|
|
100
100
|
def ultraviolet(self) -> Ultraviolet:
|
|
101
101
|
""":class:`Ultraviolet`: The UV (:term:`ultraviolet`) index."""
|
|
102
102
|
|
|
103
|
-
return Ultraviolet(int(self.__inner['uvIndex']))
|
|
103
|
+
return Ultraviolet._new(int(self.__inner['uvIndex']))
|
|
104
104
|
|
|
105
105
|
@property
|
|
106
106
|
def feels_like(self) -> int:
|
|
107
107
|
""":class:`int`: What it felt like, in Celcius or Fahrenheit."""
|
|
108
108
|
|
|
109
109
|
return int(
|
|
110
|
-
self.__inner[
|
|
111
|
-
f'FeelsLike{"C" if self._CustomizableBase__unit == METRIC else "F"}']
|
|
110
|
+
self.__inner[f'FeelsLike{self._CustomizableBase__unit.temperature}']
|
|
112
111
|
)
|
|
113
112
|
|
|
114
113
|
@property
|
|
@@ -121,18 +120,14 @@ class BaseForecast(CustomizableBase):
|
|
|
121
120
|
def temperature(self) -> int:
|
|
122
121
|
""":class:`int`: The weather temperature in either Celcius or Fahrenheit."""
|
|
123
122
|
|
|
124
|
-
return int(
|
|
125
|
-
self.
|
|
126
|
-
__inner[f'temp_{"C" if self._CustomizableBase__unit == METRIC else "F"}']
|
|
127
|
-
)
|
|
123
|
+
return int(self.__inner[f'temp_{self._CustomizableBase__unit.temperature}'])
|
|
128
124
|
|
|
129
125
|
@property
|
|
130
126
|
def precipitation(self) -> float:
|
|
131
127
|
""":class:`float`: The precipitation in either Millimeters or Inches."""
|
|
132
128
|
|
|
133
129
|
return float(
|
|
134
|
-
self.__inner[
|
|
135
|
-
f'precip{"MM" if self._CustomizableBase__unit == METRIC else "Inches"}']
|
|
130
|
+
self.__inner[f'precip{self._CustomizableBase__unit.precipitation}']
|
|
136
131
|
)
|
|
137
132
|
|
|
138
133
|
@property
|
|
@@ -140,8 +135,7 @@ class BaseForecast(CustomizableBase):
|
|
|
140
135
|
""":class:`float`: The pressure in either Pascal or Inches."""
|
|
141
136
|
|
|
142
137
|
return float(
|
|
143
|
-
self.__inner[
|
|
144
|
-
f'pressure{"" if self._CustomizableBase__unit == METRIC else "Inches"}']
|
|
138
|
+
self.__inner[f'pressure{self._CustomizableBase__unit.pressure}']
|
|
145
139
|
)
|
|
146
140
|
|
|
147
141
|
@property
|
|
@@ -149,9 +143,7 @@ class BaseForecast(CustomizableBase):
|
|
|
149
143
|
""":class:`int`: The visibility distance in either Kilometers or Miles."""
|
|
150
144
|
|
|
151
145
|
return int(
|
|
152
|
-
self.__inner[
|
|
153
|
-
f'visibility{"" if self._CustomizableBase__unit == METRIC else "Miles"}'
|
|
154
|
-
]
|
|
146
|
+
self.__inner[f'visibility{self._CustomizableBase__unit.visibility}']
|
|
155
147
|
)
|
|
156
148
|
|
|
157
149
|
@property
|
|
@@ -159,9 +151,7 @@ class BaseForecast(CustomizableBase):
|
|
|
159
151
|
""":class:`int`: The wind speeds in either Kilometers per hour or Miles per hour."""
|
|
160
152
|
|
|
161
153
|
return int(
|
|
162
|
-
self.__inner[
|
|
163
|
-
f'windspeed{"Kmph" if self._CustomizableBase__unit == METRIC else "Miles"}'
|
|
164
|
-
]
|
|
154
|
+
self.__inner[f'windspeed{self._CustomizableBase__unit.velocity}']
|
|
165
155
|
)
|
|
166
156
|
|
|
167
157
|
@property
|
|
@@ -28,7 +28,7 @@ from typing import Optional
|
|
|
28
28
|
from asyncio import sleep
|
|
29
29
|
from enum import auto
|
|
30
30
|
|
|
31
|
-
from .constants import
|
|
31
|
+
from .constants import _Unit, METRIC
|
|
32
32
|
from .base import CustomizableBase
|
|
33
33
|
from .forecast import Weather
|
|
34
34
|
from .errors import Error
|
|
@@ -115,7 +115,7 @@ class Client(CustomizableBase):
|
|
|
115
115
|
elif self.__session.closed:
|
|
116
116
|
raise Error('Client is already closed')
|
|
117
117
|
|
|
118
|
-
if
|
|
118
|
+
if not isinstance(unit, _Unit):
|
|
119
119
|
unit = self._CustomizableBase__unit
|
|
120
120
|
|
|
121
121
|
if not isinstance(locale, Locale):
|
|
@@ -22,11 +22,36 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
22
22
|
SOFTWARE.
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
+
from typing import Union
|
|
25
26
|
from re import compile
|
|
26
27
|
from enum import auto
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
class _Unit:
|
|
30
|
+
__slots__ = (
|
|
31
|
+
'temperature', 'velocity', 'pressure', 'precipitation', 'visibility',
|
|
32
|
+
'cm_divisor'
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
temperature: str,
|
|
38
|
+
velocity: str,
|
|
39
|
+
pressure: str,
|
|
40
|
+
precipitation: str,
|
|
41
|
+
visibility: str,
|
|
42
|
+
cm_divisor: Union[int, float],
|
|
43
|
+
):
|
|
44
|
+
self.temperature = temperature
|
|
45
|
+
self.velocity = velocity
|
|
46
|
+
self.pressure = pressure
|
|
47
|
+
self.precipitation = precipitation
|
|
48
|
+
self.visibility = visibility
|
|
49
|
+
self.cm_divisor = cm_divisor
|
|
50
|
+
|
|
51
|
+
def __repr__(self) -> str:
|
|
52
|
+
return f'<Unit [{self.temperature}, {self.velocity}]>'
|
|
53
|
+
|
|
54
|
+
METRIC = _Unit('C', 'Kmph', '', 'MM', '', 1)
|
|
55
|
+
IMPERIAL = _Unit('F', 'Miles', 'Inches', 'Inches', 'Miles', 2.54)
|
|
30
56
|
|
|
31
57
|
LATLON_REGEX = compile(r'^Lat (\-?[\d\.]+) and Lon (\-?[\d\.]+)$')
|
|
32
|
-
VALID_UNITS = (METRIC, IMPERIAL)
|
|
@@ -31,7 +31,7 @@ class BasicEnum(Enum):
|
|
|
31
31
|
__slots__ = ()
|
|
32
32
|
|
|
33
33
|
def __repr__(self) -> str:
|
|
34
|
-
""":class:`str`: The string representation of this
|
|
34
|
+
""":class:`str`: The string representation of this :class:`Enum`."""
|
|
35
35
|
|
|
36
36
|
return f'{self.__class__.__name__}.{self.name}'
|
|
37
37
|
|
|
@@ -40,10 +40,10 @@ class BasicEnum(Enum):
|
|
|
40
40
|
|
|
41
41
|
return self.name.replace('_', ' ').title()
|
|
42
42
|
|
|
43
|
-
class Ultraviolet(
|
|
43
|
+
class Ultraviolet(Enum):
|
|
44
44
|
"""Represents a :term:`UV index`."""
|
|
45
45
|
|
|
46
|
-
__slots__ = ()
|
|
46
|
+
__slots__ = ('__index',)
|
|
47
47
|
|
|
48
48
|
LOW = 13
|
|
49
49
|
MODERATE = auto()
|
|
@@ -51,6 +51,12 @@ class Ultraviolet(BasicEnum):
|
|
|
51
51
|
VERY_HIGH = auto()
|
|
52
52
|
EXTREME = auto()
|
|
53
53
|
|
|
54
|
+
def _new(index: int):
|
|
55
|
+
enum = Ultraviolet(index)
|
|
56
|
+
enum.__index = index
|
|
57
|
+
|
|
58
|
+
return enum
|
|
59
|
+
|
|
54
60
|
@classmethod
|
|
55
61
|
def _missing_(self, index: int):
|
|
56
62
|
if index <= 2:
|
|
@@ -63,6 +69,104 @@ class Ultraviolet(BasicEnum):
|
|
|
63
69
|
return self.VERY_HIGH
|
|
64
70
|
else:
|
|
65
71
|
return self.EXTREME
|
|
72
|
+
|
|
73
|
+
def __repr__(self) -> str:
|
|
74
|
+
""":class:`str`: The string representation of this :class:`Enum`."""
|
|
75
|
+
|
|
76
|
+
return f'<{self.__class__.__name__}.{self.name} index={self.__index}>'
|
|
77
|
+
|
|
78
|
+
def __str__(self) -> str:
|
|
79
|
+
""":class:`str`: The stylized name for this :class:`Enum`."""
|
|
80
|
+
|
|
81
|
+
return self.name.replace('_', ' ').title()
|
|
82
|
+
|
|
83
|
+
def __lt__(self, other: Union["Ultraviolet", int, float]) -> bool:
|
|
84
|
+
"""
|
|
85
|
+
Checks if this :class:`Enum`'s ultraviolet index is less than the other ultraviolet index.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
other: Union[:class:`Ultraviolet`, :class:`int`, :class:`float`]
|
|
90
|
+
The other ultraviolet index to compare. Besides :class:`int` and :class:`float`, this also works for any type that can be compared with an :class:`int`.
|
|
91
|
+
|
|
92
|
+
Raises
|
|
93
|
+
------
|
|
94
|
+
TypeError
|
|
95
|
+
If the ``other`` argument's type is incompatible.
|
|
96
|
+
|
|
97
|
+
Returns
|
|
98
|
+
-------
|
|
99
|
+
:class:`bool`
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
if isinstance(other, self.__class__):
|
|
103
|
+
return self.__index < other.index
|
|
104
|
+
else:
|
|
105
|
+
return self.__index < other
|
|
106
|
+
|
|
107
|
+
def __eq__(self, other: Union["Ultraviolet", int, float]) -> bool:
|
|
108
|
+
"""
|
|
109
|
+
Checks if this :class:`Enum`'s ultraviolet index is equal to the other ultraviolet index.
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
other: Union[:class:`Ultraviolet`, :class:`int`, :class:`float`]
|
|
114
|
+
The other ultraviolet index to compare. Besides :class:`int` and :class:`float`, this also works for any type that can be compared with an :class:`int`.
|
|
115
|
+
|
|
116
|
+
Raises
|
|
117
|
+
------
|
|
118
|
+
TypeError
|
|
119
|
+
If the ``other`` argument's type is incompatible.
|
|
120
|
+
|
|
121
|
+
Returns
|
|
122
|
+
-------
|
|
123
|
+
:class:`bool`
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
if isinstance(other, self.__class__):
|
|
127
|
+
return self.__index == other.index
|
|
128
|
+
else:
|
|
129
|
+
return self.__index == other
|
|
130
|
+
|
|
131
|
+
def __gt__(self, other: Union["Ultraviolet", int, float]) -> bool:
|
|
132
|
+
"""
|
|
133
|
+
Checks if this :class:`Enum`'s ultraviolet index is greater than the other ultraviolet index.
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
other: Union[:class:`Ultraviolet`, :class:`int`, :class:`float`]
|
|
138
|
+
The other ultraviolet index to compare. Besides :class:`int` and :class:`float`, this also works for any type that can be compared with an :class:`int`.
|
|
139
|
+
|
|
140
|
+
Raises
|
|
141
|
+
------
|
|
142
|
+
TypeError
|
|
143
|
+
If the ``other`` argument's type is incompatible.
|
|
144
|
+
|
|
145
|
+
Returns
|
|
146
|
+
-------
|
|
147
|
+
:class:`bool`
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
if isinstance(other, self.__class__):
|
|
151
|
+
return self.__index > other.index
|
|
152
|
+
else:
|
|
153
|
+
return self.__index > other
|
|
154
|
+
|
|
155
|
+
def __hash__(self) -> int:
|
|
156
|
+
""":class:`int`: A hashed version of this :class:`Enum`."""
|
|
157
|
+
|
|
158
|
+
return self.__index
|
|
159
|
+
|
|
160
|
+
def __int__(self) -> int:
|
|
161
|
+
""":class:`int`: The ultraviolet index."""
|
|
162
|
+
|
|
163
|
+
return self.__index
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def index(self) -> int:
|
|
167
|
+
""":class:`int`: The ultraviolet index."""
|
|
168
|
+
|
|
169
|
+
return self.__index
|
|
66
170
|
|
|
67
171
|
class WindDirection(Enum):
|
|
68
172
|
"""Represents a wind direction."""
|
|
@@ -93,7 +197,7 @@ class WindDirection(Enum):
|
|
|
93
197
|
return enum
|
|
94
198
|
|
|
95
199
|
def __repr__(self) -> str:
|
|
96
|
-
""":class:`str`: The string representation of this
|
|
200
|
+
""":class:`str`: The string representation of this :class:`Enum`."""
|
|
97
201
|
|
|
98
202
|
return f'<{self.__class__.__name__}.{self.name} degrees={self.__degrees!r}>'
|
|
99
203
|
|
|
@@ -102,60 +206,60 @@ class WindDirection(Enum):
|
|
|
102
206
|
|
|
103
207
|
return self.name.replace('_', ' ').title()
|
|
104
208
|
|
|
105
|
-
def __contains__(self,
|
|
209
|
+
def __contains__(self, other: Union["WindDirection", float, int]) -> bool:
|
|
106
210
|
"""
|
|
107
|
-
Checks if the degrees value is a part of this wind direction.
|
|
211
|
+
Checks if the other degrees value is a part of this :class:`Enum`'s wind direction category.
|
|
108
212
|
|
|
109
213
|
Parameters
|
|
110
214
|
----------
|
|
111
|
-
|
|
112
|
-
The degrees value.
|
|
215
|
+
other: Union[:class:`WindDirection`, :class:`int`, :class:`float`]
|
|
216
|
+
The other degrees value to compare. Besides :class:`int` and :class:`float`, this also works for any type that can be compared with a :class:`float`.
|
|
113
217
|
|
|
114
218
|
Raises
|
|
115
219
|
------
|
|
116
|
-
|
|
117
|
-
|
|
220
|
+
TypeError
|
|
221
|
+
If the ``other`` argument's type is incompatible.
|
|
118
222
|
|
|
119
223
|
Returns
|
|
120
224
|
-------
|
|
121
225
|
:class:`bool`
|
|
122
|
-
The boolean.
|
|
123
226
|
"""
|
|
124
227
|
|
|
125
|
-
if
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
228
|
+
if isinstance(other, self.__class__):
|
|
229
|
+
other = other.degrees
|
|
230
|
+
|
|
231
|
+
if self is self.NORTH:
|
|
232
|
+
return other > 348.75 or other <= 11.25
|
|
129
233
|
elif self is self.NORTH_NORTHEAST:
|
|
130
|
-
return 11.25 <
|
|
234
|
+
return 11.25 < other <= 33.75
|
|
131
235
|
elif self is self.NORTHEAST:
|
|
132
|
-
return 33.75 <
|
|
236
|
+
return 33.75 < other <= 56.25
|
|
133
237
|
elif self is self.EAST_NORTHEAST:
|
|
134
|
-
return 56.25 <
|
|
238
|
+
return 56.25 < other <= 78.75
|
|
135
239
|
elif self is self.EAST:
|
|
136
|
-
return 78.75 <
|
|
240
|
+
return 78.75 < other <= 101.25
|
|
137
241
|
elif self is self.EAST_SOUTHEAST:
|
|
138
|
-
return 101.25 <
|
|
242
|
+
return 101.25 < other <= 123.75
|
|
139
243
|
elif self is self.SOUTHEAST:
|
|
140
|
-
return 123.75 <
|
|
244
|
+
return 123.75 < other <= 146.25
|
|
141
245
|
elif self is self.SOUTH_SOUTHEAST:
|
|
142
|
-
return 146.25 <
|
|
246
|
+
return 146.25 < other <= 168.75
|
|
143
247
|
elif self is self.SOUTH:
|
|
144
|
-
return 168.75 <
|
|
248
|
+
return 168.75 < other <= 191.25
|
|
145
249
|
elif self is self.SOUTH_SOUTHWEST:
|
|
146
|
-
return 191.25 <
|
|
250
|
+
return 191.25 < other <= 213.75
|
|
147
251
|
elif self is self.SOUTHWEST:
|
|
148
|
-
return 213.75 <
|
|
252
|
+
return 213.75 < other <= 236.25
|
|
149
253
|
elif self is self.WEST_SOUTHWEST:
|
|
150
|
-
return 236.25 <
|
|
254
|
+
return 236.25 < other <= 258.75
|
|
151
255
|
elif self is self.WEST:
|
|
152
|
-
return 258.75 <
|
|
256
|
+
return 258.75 < other <= 281.25
|
|
153
257
|
elif self is self.WEST_NORTHWEST:
|
|
154
|
-
return 281.25 <
|
|
258
|
+
return 281.25 < other <= 303.75
|
|
155
259
|
elif self is self.NORTHWEST:
|
|
156
|
-
return 303.75 <
|
|
260
|
+
return 303.75 < other <= 326.25
|
|
157
261
|
else:
|
|
158
|
-
return 326.25 <
|
|
262
|
+
return 326.25 < other <= 348.75
|
|
159
263
|
|
|
160
264
|
@property
|
|
161
265
|
def degrees(self) -> int:
|
|
@@ -242,7 +346,7 @@ class Locale(Enum):
|
|
|
242
346
|
ZULU = 'zu'
|
|
243
347
|
|
|
244
348
|
def __repr__(self) -> str:
|
|
245
|
-
""":class:`str`: The string representation of this
|
|
349
|
+
""":class:`str`: The string representation of this :class:`Enum`."""
|
|
246
350
|
|
|
247
351
|
return f'{self.__class__.__name__}.{self.name}'
|
|
248
352
|
|
|
@@ -26,10 +26,9 @@ from typing import Iterable, Optional, Tuple
|
|
|
26
26
|
from datetime import datetime, date, time
|
|
27
27
|
from enum import auto
|
|
28
28
|
|
|
29
|
-
from .enums import Kind, Phase, WindDirection, Locale, Ultraviolet
|
|
30
|
-
from .constants import VALID_UNITS, LATLON_REGEX, METRIC
|
|
31
29
|
from .base import BaseForecast, CustomizableBase
|
|
32
|
-
from .
|
|
30
|
+
from .constants import _Unit, LATLON_REGEX
|
|
31
|
+
from .enums import Phase, Locale
|
|
33
32
|
|
|
34
33
|
class Area:
|
|
35
34
|
"""Represents the location of the weather forecast."""
|
|
@@ -164,7 +163,7 @@ class HourlyForecast(BaseForecast):
|
|
|
164
163
|
|
|
165
164
|
__slots__ = ()
|
|
166
165
|
|
|
167
|
-
def __init__(self, json: dict, unit:
|
|
166
|
+
def __init__(self, json: dict, unit: _Unit, locale: Locale):
|
|
168
167
|
# for inheritance purposes
|
|
169
168
|
if 'temp_C' not in json:
|
|
170
169
|
json['temp_C'] = json.pop('tempC')
|
|
@@ -183,7 +182,7 @@ class HourlyForecast(BaseForecast):
|
|
|
183
182
|
""":class:`int`: The dew point in either Celcius or Fahrenheit."""
|
|
184
183
|
|
|
185
184
|
return int(
|
|
186
|
-
self._BaseForecast__inner[f'DewPoint{
|
|
185
|
+
self._BaseForecast__inner[f'DewPoint{self._CustomizableBase__unit.temperature}']
|
|
187
186
|
) # yapf: disable
|
|
188
187
|
|
|
189
188
|
@property
|
|
@@ -191,7 +190,7 @@ class HourlyForecast(BaseForecast):
|
|
|
191
190
|
""":class:`int`: The heat index in either Celcius or Fahrenheit."""
|
|
192
191
|
|
|
193
192
|
return int(
|
|
194
|
-
self._BaseForecast__inner[f'HeatIndex{
|
|
193
|
+
self._BaseForecast__inner[f'HeatIndex{self._CustomizableBase__unit.temperature}']
|
|
195
194
|
) # yapf: disable
|
|
196
195
|
|
|
197
196
|
@property
|
|
@@ -199,14 +198,14 @@ class HourlyForecast(BaseForecast):
|
|
|
199
198
|
""":class:`int`: The wind chill value in either Celcius or Fahrenheit."""
|
|
200
199
|
|
|
201
200
|
return int(
|
|
202
|
-
self._BaseForecast__inner[f'WindChill{
|
|
201
|
+
self._BaseForecast__inner[f'WindChill{self._CustomizableBase__unit.temperature}']
|
|
203
202
|
) # yapf: disable
|
|
204
203
|
|
|
205
204
|
@property
|
|
206
205
|
def wind_gust(self) -> int:
|
|
207
206
|
""":class:`int`: The wind gust value in either Kilometers per hour or Miles per hour."""
|
|
208
207
|
|
|
209
|
-
key = f'WindGust{
|
|
208
|
+
key = f'WindGust{self._CustomizableBase__unit.velocity}'
|
|
210
209
|
return int(self._BaseForecast__inner[key])
|
|
211
210
|
|
|
212
211
|
@property
|
|
@@ -284,7 +283,7 @@ class HourlyForecast(BaseForecast):
|
|
|
284
283
|
class DailyForecast(CustomizableBase):
|
|
285
284
|
__slots__ = ('__inner',)
|
|
286
285
|
|
|
287
|
-
def __init__(self, json: dict, unit:
|
|
286
|
+
def __init__(self, json: dict, unit: _Unit, locale: Locale):
|
|
288
287
|
self.__inner = json
|
|
289
288
|
|
|
290
289
|
super().__init__(unit, locale)
|
|
@@ -311,7 +310,7 @@ class DailyForecast(CustomizableBase):
|
|
|
311
310
|
""":class:`int`: The lowest temperature in either Celcius or Fahrenheit."""
|
|
312
311
|
|
|
313
312
|
return int(
|
|
314
|
-
self.__inner[f'mintemp{
|
|
313
|
+
self.__inner[f'mintemp{self._CustomizableBase__unit.temperature}']
|
|
315
314
|
) # yapf: disable
|
|
316
315
|
|
|
317
316
|
@property
|
|
@@ -319,7 +318,7 @@ class DailyForecast(CustomizableBase):
|
|
|
319
318
|
""":class:`int`: The highest temperature in either Celcius or Fahrenheit."""
|
|
320
319
|
|
|
321
320
|
return int(
|
|
322
|
-
self.__inner[f'maxtemp{
|
|
321
|
+
self.__inner[f'maxtemp{self._CustomizableBase__unit.temperature}']
|
|
323
322
|
) # yapf: disable
|
|
324
323
|
|
|
325
324
|
@property
|
|
@@ -327,7 +326,7 @@ class DailyForecast(CustomizableBase):
|
|
|
327
326
|
""":class:`int`: The average temperature in either Celcius or Fahrenheit."""
|
|
328
327
|
|
|
329
328
|
return int(
|
|
330
|
-
self.__inner[f'avgtemp{
|
|
329
|
+
self.__inner[f'avgtemp{self._CustomizableBase__unit.temperature}']
|
|
331
330
|
) # yapf: disable
|
|
332
331
|
|
|
333
332
|
@property
|
|
@@ -340,8 +339,9 @@ class DailyForecast(CustomizableBase):
|
|
|
340
339
|
def snowfall(self) -> float:
|
|
341
340
|
""":class:`float`: Total snowfall in either Centimeters or Inches."""
|
|
342
341
|
|
|
343
|
-
|
|
344
|
-
|
|
342
|
+
return float(
|
|
343
|
+
self.__inner['totalSnow_cm']
|
|
344
|
+
) / self._CustomizableBase__unit.cm_divisor
|
|
345
345
|
|
|
346
346
|
@property
|
|
347
347
|
def hourly(self) -> Iterable[HourlyForecast]:
|
|
@@ -358,7 +358,7 @@ class Weather(CustomizableBase):
|
|
|
358
358
|
|
|
359
359
|
__slots__ = ('__inner',)
|
|
360
360
|
|
|
361
|
-
def __init__(self, json: dict, unit:
|
|
361
|
+
def __init__(self, json: dict, unit: _Unit, locale: Locale):
|
|
362
362
|
self.__inner = json
|
|
363
363
|
|
|
364
364
|
super().__init__(unit, locale)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-weather
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: A free and asynchronous weather API wrapper made in Python, for Python.
|
|
5
5
|
Author: null8626
|
|
6
6
|
License: MIT
|
|
7
7
|
Project-URL: repository, https://github.com/null8626/python-weather
|
|
8
|
-
Project-URL: download_url, https://github.com/null8626/python-weather/archive/1.0.
|
|
8
|
+
Project-URL: download_url, https://github.com/null8626/python-weather/archive/1.1.0.tar.gz
|
|
9
9
|
Keywords: weather,forecast,weather-api,weather-forecast
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Framework :: aiohttp
|
|
@@ -29,9 +29,10 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
29
29
|
Classifier: Programming Language :: Python :: 3.10
|
|
30
30
|
Classifier: Programming Language :: Python :: 3.11
|
|
31
31
|
Classifier: Programming Language :: Python :: 3.12
|
|
32
|
-
Requires-Python: >=3.
|
|
32
|
+
Requires-Python: >=3.8
|
|
33
33
|
Description-Content-Type: text/markdown
|
|
34
34
|
License-File: LICENSE
|
|
35
|
+
Requires-Dist: aiohttp==3.9.0
|
|
35
36
|
|
|
36
37
|
# [python-weather][pypi-url] [![pypi][pypi-image]][pypi-url] [![downloads][downloads-image]][pypi-url] [![Build Status][ci-image]][ci-url] [![license][github-license-image]][github-license-url] [![BLAZINGLY FAST!!!][blazingly-fast-image]][blazingly-fast-url]
|
|
37
38
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
aiohttp==3.9.0
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
aiohttp==3.8.4
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|