python-google-weather-api 0.0.9__py3-none-any.whl → 0.0.11__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.
- google_weather_api/__init__.py +2 -0
- google_weather_api/api.py +41 -22
- google_weather_api/exceptions.py +4 -0
- google_weather_api/model.py +163 -41
- {python_google_weather_api-0.0.9.dist-info → python_google_weather_api-0.0.11.dist-info}/METADATA +1 -1
- python_google_weather_api-0.0.11.dist-info/RECORD +10 -0
- python_google_weather_api-0.0.9.dist-info/RECORD +0 -10
- {python_google_weather_api-0.0.9.dist-info → python_google_weather_api-0.0.11.dist-info}/WHEEL +0 -0
- {python_google_weather_api-0.0.9.dist-info → python_google_weather_api-0.0.11.dist-info}/licenses/LICENSE +0 -0
- {python_google_weather_api-0.0.9.dist-info → python_google_weather_api-0.0.11.dist-info}/top_level.txt +0 -0
google_weather_api/__init__.py
CHANGED
|
@@ -4,6 +4,7 @@ from .api import GoogleWeatherApi
|
|
|
4
4
|
from .exceptions import (
|
|
5
5
|
GoogleWeatherApiAuthError,
|
|
6
6
|
GoogleWeatherApiConnectionError,
|
|
7
|
+
GoogleWeatherApiConnectionTimeoutError,
|
|
7
8
|
GoogleWeatherApiError,
|
|
8
9
|
GoogleWeatherApiResponseError,
|
|
9
10
|
)
|
|
@@ -50,6 +51,7 @@ __all__ = [
|
|
|
50
51
|
"GoogleWeatherApi",
|
|
51
52
|
"GoogleWeatherApiAuthError",
|
|
52
53
|
"GoogleWeatherApiConnectionError",
|
|
54
|
+
"GoogleWeatherApiConnectionTimeoutError",
|
|
53
55
|
"GoogleWeatherApiError",
|
|
54
56
|
"GoogleWeatherApiResponseError",
|
|
55
57
|
"HourlyForecastResponse",
|
google_weather_api/api.py
CHANGED
|
@@ -4,16 +4,19 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
6
|
from http import HTTPStatus
|
|
7
|
-
from typing import Any
|
|
7
|
+
from typing import Any, TypeVar
|
|
8
8
|
|
|
9
9
|
import aiohttp
|
|
10
|
+
from mashumaro.exceptions import InvalidFieldValue, MissingField
|
|
10
11
|
|
|
11
12
|
from .exceptions import (
|
|
12
13
|
GoogleWeatherApiAuthError,
|
|
13
14
|
GoogleWeatherApiConnectionError,
|
|
15
|
+
GoogleWeatherApiConnectionTimeoutError,
|
|
14
16
|
GoogleWeatherApiResponseError,
|
|
15
17
|
)
|
|
16
18
|
from .model import (
|
|
19
|
+
BaseModel,
|
|
17
20
|
CurrentConditionsResponse,
|
|
18
21
|
DailyForecastResponse,
|
|
19
22
|
HourlyForecastResponse,
|
|
@@ -22,6 +25,17 @@ from .model import (
|
|
|
22
25
|
|
|
23
26
|
_LOGGER = logging.getLogger(__name__)
|
|
24
27
|
|
|
28
|
+
_ResponseT = TypeVar("_ResponseT", bound=BaseModel)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _parse_response(model: type[_ResponseT], data: dict[str, Any]) -> _ResponseT:
|
|
32
|
+
"""Deserialize an API response dictionary, wrapping schema errors."""
|
|
33
|
+
try:
|
|
34
|
+
return model.from_dict(data)
|
|
35
|
+
except (InvalidFieldValue, MissingField) as err:
|
|
36
|
+
raise GoogleWeatherApiResponseError(str(err)) from err
|
|
37
|
+
|
|
38
|
+
|
|
25
39
|
_BASE_URL = "https://weather.googleapis.com/v1"
|
|
26
40
|
# See https://docs.cloud.google.com/docs/authentication/api-keys-use
|
|
27
41
|
_API_KEY_HEADER = "X-Goog-Api-Key"
|
|
@@ -71,28 +85,33 @@ class GoogleWeatherApi:
|
|
|
71
85
|
headers=headers,
|
|
72
86
|
timeout=self.timeout,
|
|
73
87
|
) as resp:
|
|
74
|
-
res: dict[str, Any] = await resp.json()
|
|
75
88
|
_LOGGER.debug("Got %s for %s", resp.status, url)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
error_msg = error_data.get("message", "Unknown API error")
|
|
79
|
-
|
|
80
|
-
if resp.status in (HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN):
|
|
81
|
-
raise GoogleWeatherApiAuthError(error_msg)
|
|
82
|
-
|
|
83
|
-
# Google APIs often return 400 Bad Request for invalid API keys
|
|
84
|
-
if resp.status == HTTPStatus.BAD_REQUEST:
|
|
85
|
-
for detail in error_data.get("details", []):
|
|
86
|
-
if detail.get("reason") == "API_KEY_INVALID":
|
|
87
|
-
raise GoogleWeatherApiAuthError(error_msg)
|
|
88
|
-
|
|
89
|
-
raise GoogleWeatherApiResponseError(error_msg)
|
|
90
|
-
return res
|
|
89
|
+
status_code = resp.status
|
|
90
|
+
body = None if status_code == HTTPStatus.GATEWAY_TIMEOUT else await resp.json()
|
|
91
91
|
except TimeoutError as err:
|
|
92
|
-
raise
|
|
92
|
+
raise GoogleWeatherApiConnectionTimeoutError("Timeout") from err
|
|
93
93
|
except aiohttp.ClientError as err:
|
|
94
94
|
raise GoogleWeatherApiConnectionError(err) from err
|
|
95
95
|
|
|
96
|
+
if status_code == HTTPStatus.GATEWAY_TIMEOUT:
|
|
97
|
+
raise GoogleWeatherApiConnectionTimeoutError("Timeout")
|
|
98
|
+
res: dict[str, Any] = body if isinstance(body, dict) else {}
|
|
99
|
+
if status_code != HTTPStatus.OK:
|
|
100
|
+
error_data = res.get("error", {})
|
|
101
|
+
error_msg = error_data.get("message", "Unknown API error")
|
|
102
|
+
|
|
103
|
+
if status_code in (HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN):
|
|
104
|
+
raise GoogleWeatherApiAuthError(error_msg)
|
|
105
|
+
|
|
106
|
+
# Google APIs often return 400 Bad Request for invalid API keys
|
|
107
|
+
if status_code == HTTPStatus.BAD_REQUEST:
|
|
108
|
+
for detail in error_data.get("details", []):
|
|
109
|
+
if detail.get("reason") == "API_KEY_INVALID":
|
|
110
|
+
raise GoogleWeatherApiAuthError(error_msg)
|
|
111
|
+
|
|
112
|
+
raise GoogleWeatherApiResponseError(error_msg)
|
|
113
|
+
return res
|
|
114
|
+
|
|
96
115
|
async def _async_get_all_pages(
|
|
97
116
|
self,
|
|
98
117
|
endpoint: str,
|
|
@@ -134,7 +153,7 @@ class GoogleWeatherApi:
|
|
|
134
153
|
"location.longitude": longitude,
|
|
135
154
|
},
|
|
136
155
|
)
|
|
137
|
-
return CurrentConditionsResponse
|
|
156
|
+
return _parse_response(CurrentConditionsResponse, data)
|
|
138
157
|
|
|
139
158
|
async def async_get_hourly_forecast(self, latitude: float, longitude: float, hours: int = 48) -> HourlyForecastResponse:
|
|
140
159
|
"""Fetch hourly weather forecast.
|
|
@@ -151,7 +170,7 @@ class GoogleWeatherApi:
|
|
|
151
170
|
"forecastHours",
|
|
152
171
|
hours,
|
|
153
172
|
)
|
|
154
|
-
return HourlyForecastResponse
|
|
173
|
+
return _parse_response(HourlyForecastResponse, data)
|
|
155
174
|
|
|
156
175
|
async def async_get_daily_forecast(self, latitude: float, longitude: float, days: int = 10) -> DailyForecastResponse:
|
|
157
176
|
"""Fetch daily weather forecast.
|
|
@@ -168,7 +187,7 @@ class GoogleWeatherApi:
|
|
|
168
187
|
"forecastDays",
|
|
169
188
|
days,
|
|
170
189
|
)
|
|
171
|
-
return DailyForecastResponse
|
|
190
|
+
return _parse_response(DailyForecastResponse, data)
|
|
172
191
|
|
|
173
192
|
async def async_get_minute_forecast(
|
|
174
193
|
self, latitude: float, longitude: float, page_size: int = 360
|
|
@@ -191,4 +210,4 @@ class GoogleWeatherApi:
|
|
|
191
210
|
page_size,
|
|
192
211
|
include_language_code=False,
|
|
193
212
|
)
|
|
194
|
-
return MinuteForecastResponse
|
|
213
|
+
return _parse_response(MinuteForecastResponse, data)
|
google_weather_api/exceptions.py
CHANGED
|
@@ -9,6 +9,10 @@ class GoogleWeatherApiConnectionError(GoogleWeatherApiError):
|
|
|
9
9
|
"""Exception connecting to the Google Weather API."""
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
class GoogleWeatherApiConnectionTimeoutError(GoogleWeatherApiConnectionError, TimeoutError):
|
|
13
|
+
"""Exception raised when a request to the Google Weather API times out."""
|
|
14
|
+
|
|
15
|
+
|
|
12
16
|
class GoogleWeatherApiAuthError(GoogleWeatherApiError):
|
|
13
17
|
"""Exception raised for authentication errors in the Google Weather API."""
|
|
14
18
|
|
google_weather_api/model.py
CHANGED
|
@@ -42,6 +42,7 @@ class BaseModel(DataClassJSONMixin):
|
|
|
42
42
|
|
|
43
43
|
serialize_by_alias = True
|
|
44
44
|
allow_deserialization_not_by_alias = True
|
|
45
|
+
omit_none = True
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
@dataclass
|
|
@@ -92,14 +93,14 @@ class Temperature(BaseModel):
|
|
|
92
93
|
class TemperatureUnit(ApiStrEnum):
|
|
93
94
|
"""Represents a unit used to measure temperatures."""
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
UNIT_UNSPECIFIED = "UNIT_UNSPECIFIED"
|
|
96
97
|
CELSIUS = "CELSIUS"
|
|
97
98
|
FAHRENHEIT = "FAHRENHEIT"
|
|
98
99
|
|
|
99
|
-
degrees: float
|
|
100
|
+
degrees: float | None = None
|
|
100
101
|
"""The temperature value (in degrees) in the specified unit."""
|
|
101
102
|
|
|
102
|
-
unit: TemperatureUnit
|
|
103
|
+
unit: TemperatureUnit = TemperatureUnit.UNIT_UNSPECIFIED
|
|
103
104
|
"""The code for the unit used to measure the temperature value."""
|
|
104
105
|
|
|
105
106
|
|
|
@@ -114,10 +115,10 @@ class QuantitativePrecipitationForecast(BaseModel):
|
|
|
114
115
|
MILLIMETERS = "MILLIMETERS"
|
|
115
116
|
INCHES = "INCHES"
|
|
116
117
|
|
|
117
|
-
quantity: float
|
|
118
|
+
quantity: float | None = None
|
|
118
119
|
"""The amount of precipitation, measured as liquid water equivalent."""
|
|
119
120
|
|
|
120
|
-
unit: Unit
|
|
121
|
+
unit: Unit = Unit.UNIT_UNSPECIFIED
|
|
121
122
|
"""The code of the unit used to measure the amount of accumulated precipitation."""
|
|
122
123
|
|
|
123
124
|
|
|
@@ -128,7 +129,7 @@ class PrecipitationProbability(BaseModel):
|
|
|
128
129
|
class PrecipitationType(ApiStrEnum):
|
|
129
130
|
"""Represents the type of precipitation at a given location."""
|
|
130
131
|
|
|
131
|
-
|
|
132
|
+
TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED"
|
|
132
133
|
NONE = "NONE"
|
|
133
134
|
SNOW = "SNOW"
|
|
134
135
|
RAIN = "RAIN"
|
|
@@ -137,6 +138,7 @@ class PrecipitationProbability(BaseModel):
|
|
|
137
138
|
RAIN_AND_SNOW = "RAIN_AND_SNOW"
|
|
138
139
|
SLEET = "SLEET"
|
|
139
140
|
FREEZING_RAIN = "FREEZING_RAIN"
|
|
141
|
+
PRECIPITATION_TYPE_HAIL = "PRECIPITATION_TYPE_HAIL"
|
|
140
142
|
|
|
141
143
|
type: PrecipitationType
|
|
142
144
|
"""A code that indicates the type of precipitation."""
|
|
@@ -166,14 +168,14 @@ class WindSpeed(BaseModel):
|
|
|
166
168
|
class SpeedUnit(ApiStrEnum):
|
|
167
169
|
"""Represents the unit used to measure speed."""
|
|
168
170
|
|
|
169
|
-
|
|
171
|
+
UNIT_UNSPECIFIED = "UNIT_UNSPECIFIED"
|
|
170
172
|
KILOMETERS_PER_HOUR = "KILOMETERS_PER_HOUR"
|
|
171
173
|
MILES_PER_HOUR = "MILES_PER_HOUR"
|
|
172
174
|
|
|
173
|
-
value: float
|
|
175
|
+
value: float | None = None
|
|
174
176
|
"""The value of the wind speed."""
|
|
175
177
|
|
|
176
|
-
unit: SpeedUnit
|
|
178
|
+
unit: SpeedUnit = SpeedUnit.UNIT_UNSPECIFIED
|
|
177
179
|
"""The code that represents the unit used to measure the wind speed."""
|
|
178
180
|
|
|
179
181
|
|
|
@@ -184,7 +186,7 @@ class WindDirection(BaseModel):
|
|
|
184
186
|
class CardinalDirection(ApiStrEnum):
|
|
185
187
|
"""Represents a cardinal direction (including ordinal directions)."""
|
|
186
188
|
|
|
187
|
-
|
|
189
|
+
CARDINAL_UNSPECIFIED = "CARDINAL_UNSPECIFIED"
|
|
188
190
|
NORTH = "NORTH"
|
|
189
191
|
NORTH_NORTHEAST = "NORTH_NORTHEAST"
|
|
190
192
|
NORTHEAST = "NORTHEAST"
|
|
@@ -219,7 +221,7 @@ class Wind(BaseModel):
|
|
|
219
221
|
speed: WindSpeed
|
|
220
222
|
"""The speed of the wind."""
|
|
221
223
|
|
|
222
|
-
gust: WindSpeed
|
|
224
|
+
gust: WindSpeed | None = None
|
|
223
225
|
"""The wind gust (sudden increase in the wind speed)."""
|
|
224
226
|
|
|
225
227
|
|
|
@@ -234,10 +236,10 @@ class Visibility(BaseModel):
|
|
|
234
236
|
KILOMETERS = "KILOMETERS"
|
|
235
237
|
MILES = "MILES"
|
|
236
238
|
|
|
237
|
-
distance: float
|
|
239
|
+
distance: float | None = None
|
|
238
240
|
"""The visibility distance in the specified unit."""
|
|
239
241
|
|
|
240
|
-
unit: Unit
|
|
242
|
+
unit: Unit = Unit.UNIT_UNSPECIFIED
|
|
241
243
|
"""The code that represents the unit used to measure the distance."""
|
|
242
244
|
|
|
243
245
|
|
|
@@ -289,6 +291,120 @@ class WeatherCondition(BaseModel):
|
|
|
289
291
|
LIGHT_THUNDERSTORM_RAIN = "LIGHT_THUNDERSTORM_RAIN"
|
|
290
292
|
SCATTERED_THUNDERSTORMS = "SCATTERED_THUNDERSTORMS"
|
|
291
293
|
HEAVY_THUNDERSTORM = "HEAVY_THUNDERSTORM"
|
|
294
|
+
CLEAR_AFTER_FOG_IN_THE_MORNING = "CLEAR_AFTER_FOG_IN_THE_MORNING"
|
|
295
|
+
CLEAR_BUT_LATER_TURNING_CLOUDY = "CLEAR_BUT_LATER_TURNING_CLOUDY"
|
|
296
|
+
CLEAR_BUT_LATER_TURNING_TO_RAIN_AND_SNOW_MAIN_CONSTITUENT_RAIN = (
|
|
297
|
+
"CLEAR_BUT_LATER_TURNING_TO_RAIN_AND_SNOW_MAIN_CONSTITUENT_RAIN"
|
|
298
|
+
)
|
|
299
|
+
CLEAR_BUT_LATER_TURNING_TO_SNOW_AND_RAIN_MAIN_CONSTITUENT_SNOW = (
|
|
300
|
+
"CLEAR_BUT_LATER_TURNING_TO_SNOW_AND_RAIN_MAIN_CONSTITUENT_SNOW"
|
|
301
|
+
)
|
|
302
|
+
CLEAR_BUT_THUNDERSTORMS_LATER = "CLEAR_BUT_THUNDERSTORMS_LATER"
|
|
303
|
+
CLEAR_IN_THE_MORNING_BUT_CLOUDY_IN_THE_EVENING = "CLEAR_IN_THE_MORNING_BUT_CLOUDY_IN_THE_EVENING"
|
|
304
|
+
CLEAR_IN_THE_MORNING_WITH_BRIEF_RAIN_IN_THE_EVENING = "CLEAR_IN_THE_MORNING_WITH_BRIEF_RAIN_IN_THE_EVENING"
|
|
305
|
+
CLEAR_MORNING_WITH_BRIEF_RAIN = "CLEAR_MORNING_WITH_BRIEF_RAIN"
|
|
306
|
+
CLEAR_WITH_BRIEF_RAIN = "CLEAR_WITH_BRIEF_RAIN"
|
|
307
|
+
CLEAR_WITH_BRIEF_RAIN_AND_SNOW_RAIN_AS_MAIN_CONSTITUENT = "CLEAR_WITH_BRIEF_RAIN_AND_SNOW_RAIN_AS_MAIN_CONSTITUENT"
|
|
308
|
+
CLEAR_WITH_BRIEF_RAIN_LATER = "CLEAR_WITH_BRIEF_RAIN_LATER"
|
|
309
|
+
CLEAR_WITH_BRIEF_SNOW = "CLEAR_WITH_BRIEF_SNOW"
|
|
310
|
+
CLEAR_WITH_BRIEF_SNOW_AND_RAIN_SNOW_AS_MAIN_CONSTITUENT = "CLEAR_WITH_BRIEF_SNOW_AND_RAIN_SNOW_AS_MAIN_CONSTITUENT"
|
|
311
|
+
CLEAR_WITH_BRIEF_SNOW_LATER = "CLEAR_WITH_BRIEF_SNOW_LATER"
|
|
312
|
+
CLEAR_WITH_PERIODIC_CLOUDS_LATER = "CLEAR_WITH_PERIODIC_CLOUDS_LATER"
|
|
313
|
+
CLEAR_WITH_PERIODIC_RAIN = "CLEAR_WITH_PERIODIC_RAIN"
|
|
314
|
+
CLEAR_WITH_PERIODIC_RAIN_ACCOMPANIED_BY_THUNDER = "CLEAR_WITH_PERIODIC_RAIN_ACCOMPANIED_BY_THUNDER"
|
|
315
|
+
CLEAR_WITH_PERIODIC_RAIN_AND_SNOW_RAIN_AS_MAIN_CONSTITUENT = (
|
|
316
|
+
"CLEAR_WITH_PERIODIC_RAIN_AND_SNOW_RAIN_AS_MAIN_CONSTITUENT"
|
|
317
|
+
)
|
|
318
|
+
CLEAR_WITH_PERIODIC_RAIN_LATER = "CLEAR_WITH_PERIODIC_RAIN_LATER"
|
|
319
|
+
CLEAR_WITH_PERIODIC_SNOW = "CLEAR_WITH_PERIODIC_SNOW"
|
|
320
|
+
CLEAR_WITH_PERIODIC_SNOW_AND_RAIN_SNOW_AS_MAIN_CONSTITUENT = (
|
|
321
|
+
"CLEAR_WITH_PERIODIC_SNOW_AND_RAIN_SNOW_AS_MAIN_CONSTITUENT"
|
|
322
|
+
)
|
|
323
|
+
CLEAR_WITH_PERIODIC_SNOW_LATER = "CLEAR_WITH_PERIODIC_SNOW_LATER"
|
|
324
|
+
CLEAR_WITH_RAIN_AFTER_MIDNIGHT = "CLEAR_WITH_RAIN_AFTER_MIDNIGHT"
|
|
325
|
+
CLEAR_WITH_RAIN_IN_THE_NIGHT = "CLEAR_WITH_RAIN_IN_THE_NIGHT"
|
|
326
|
+
CLEAR_WITH_RAIN_LATER = "CLEAR_WITH_RAIN_LATER"
|
|
327
|
+
CLEAR_WITH_SNOW_ALONG_THE_MOUNTAINS = "CLEAR_WITH_SNOW_ALONG_THE_MOUNTAINS"
|
|
328
|
+
CLEAR_WITH_SNOW_LATER = "CLEAR_WITH_SNOW_LATER"
|
|
329
|
+
CLEAR_WITH_THUNDERSTORMS_ALONG_THE_MOUNTAINS = "CLEAR_WITH_THUNDERSTORMS_ALONG_THE_MOUNTAINS"
|
|
330
|
+
CLEAR_WITH_THUNDERSTORMS_IN_THE_AFTERNOON = "CLEAR_WITH_THUNDERSTORMS_IN_THE_AFTERNOON"
|
|
331
|
+
CLOUDY_BUT_CLEAR_LATER = "CLOUDY_BUT_CLEAR_LATER"
|
|
332
|
+
CLOUDY_BUT_LATER_TURNING_TO_RAIN_AND_SNOW_MAIN_CONSTITUENT_RAIN = (
|
|
333
|
+
"CLOUDY_BUT_LATER_TURNING_TO_RAIN_AND_SNOW_MAIN_CONSTITUENT_RAIN"
|
|
334
|
+
)
|
|
335
|
+
CLOUDY_BUT_LATER_TURNING_TO_SNOW_AND_RAIN_MAIN_CONSTITUENT_SNOW = (
|
|
336
|
+
"CLOUDY_BUT_LATER_TURNING_TO_SNOW_AND_RAIN_MAIN_CONSTITUENT_SNOW"
|
|
337
|
+
)
|
|
338
|
+
CLOUDY_BUT_PERIODICALLY_CLEAR_LATER = "CLOUDY_BUT_PERIODICALLY_CLEAR_LATER"
|
|
339
|
+
CLOUDY_BUT_THUNDERSTORMS_LATER = "CLOUDY_BUT_THUNDERSTORMS_LATER"
|
|
340
|
+
CLOUDY_MORNING_WITH_BRIEF_RAIN = "CLOUDY_MORNING_WITH_BRIEF_RAIN"
|
|
341
|
+
CLOUDY_PERIODICALLY_CLEAR = "CLOUDY_PERIODICALLY_CLEAR"
|
|
342
|
+
CLOUDY_SNOWING_IN_THE_EVENING = "CLOUDY_SNOWING_IN_THE_EVENING"
|
|
343
|
+
CLOUDY_SNOWING_IN_THE_NIGHT = "CLOUDY_SNOWING_IN_THE_NIGHT"
|
|
344
|
+
CLOUDY_WITH_BRIEF_RAIN = "CLOUDY_WITH_BRIEF_RAIN"
|
|
345
|
+
CLOUDY_WITH_BRIEF_RAIN_AND_SNOW_RAIN_AS_MAIN_CONSTITUENT = "CLOUDY_WITH_BRIEF_RAIN_AND_SNOW_RAIN_AS_MAIN_CONSTITUENT"
|
|
346
|
+
CLOUDY_WITH_BRIEF_RAIN_LATER = "CLOUDY_WITH_BRIEF_RAIN_LATER"
|
|
347
|
+
CLOUDY_WITH_BRIEF_SNOW = "CLOUDY_WITH_BRIEF_SNOW"
|
|
348
|
+
CLOUDY_WITH_BRIEF_SNOW_AND_RAIN_SNOW_AS_MAIN_CONSTITUENT = "CLOUDY_WITH_BRIEF_SNOW_AND_RAIN_SNOW_AS_MAIN_CONSTITUENT"
|
|
349
|
+
CLOUDY_WITH_BRIEF_SNOW_LATER = "CLOUDY_WITH_BRIEF_SNOW_LATER"
|
|
350
|
+
CLOUDY_WITH_BRIEF_THUNDERSTORM = "CLOUDY_WITH_BRIEF_THUNDERSTORM"
|
|
351
|
+
CLOUDY_WITH_FOG_ON_THE_OCEAN_AND_AT_THE_SEASHORE = "CLOUDY_WITH_FOG_ON_THE_OCEAN_AND_AT_THE_SEASHORE"
|
|
352
|
+
CLOUDY_WITH_PERIODIC_RAIN = "CLOUDY_WITH_PERIODIC_RAIN"
|
|
353
|
+
CLOUDY_WITH_PERIODIC_RAIN_ACCOMPANIED_BY_THUNDER = "CLOUDY_WITH_PERIODIC_RAIN_ACCOMPANIED_BY_THUNDER"
|
|
354
|
+
CLOUDY_WITH_PERIODIC_RAIN_AND_SNOW_RAIN_AS_MAIN_CONSTITUENT = (
|
|
355
|
+
"CLOUDY_WITH_PERIODIC_RAIN_AND_SNOW_RAIN_AS_MAIN_CONSTITUENT"
|
|
356
|
+
)
|
|
357
|
+
CLOUDY_WITH_PERIODIC_RAIN_LATER = "CLOUDY_WITH_PERIODIC_RAIN_LATER"
|
|
358
|
+
CLOUDY_WITH_PERIODIC_SNOW = "CLOUDY_WITH_PERIODIC_SNOW"
|
|
359
|
+
CLOUDY_WITH_PERIODIC_SNOW_ACCOMPANIED_BY_THUNDER = "CLOUDY_WITH_PERIODIC_SNOW_ACCOMPANIED_BY_THUNDER"
|
|
360
|
+
CLOUDY_WITH_PERIODIC_SNOW_AND_RAIN_SNOW_AS_MAIN_CONSTITUENT = (
|
|
361
|
+
"CLOUDY_WITH_PERIODIC_SNOW_AND_RAIN_SNOW_AS_MAIN_CONSTITUENT"
|
|
362
|
+
)
|
|
363
|
+
CLOUDY_WITH_PERIODIC_SNOW_LATER = "CLOUDY_WITH_PERIODIC_SNOW_LATER"
|
|
364
|
+
CLOUDY_WITH_RAIN_AFTER_MIDNIGHT = "CLOUDY_WITH_RAIN_AFTER_MIDNIGHT"
|
|
365
|
+
CLOUDY_WITH_RAIN_FROM_ABOUT_NOON = "CLOUDY_WITH_RAIN_FROM_ABOUT_NOON"
|
|
366
|
+
CLOUDY_WITH_RAIN_FROM_EVENING = "CLOUDY_WITH_RAIN_FROM_EVENING"
|
|
367
|
+
CLOUDY_WITH_RAIN_LATER = "CLOUDY_WITH_RAIN_LATER"
|
|
368
|
+
CLOUDY_WITH_SNOW_FROM_AROUND_NOON = "CLOUDY_WITH_SNOW_FROM_AROUND_NOON"
|
|
369
|
+
CLOUDY_WITH_SNOW_LATER = "CLOUDY_WITH_SNOW_LATER"
|
|
370
|
+
FOG = "FOG"
|
|
371
|
+
RAINSNOW_MIX_LATER_BECOMING_CLEAR_RAIN_AS_MAIN = "RAINSNOW_MIX_LATER_BECOMING_CLEAR_RAIN_AS_MAIN"
|
|
372
|
+
RAINSNOW_MIX_RAIN_AS_MAIN = "RAINSNOW_MIX_RAIN_AS_MAIN"
|
|
373
|
+
RAINY_BUT_PERIODICALLY_CLEAR = "RAINY_BUT_PERIODICALLY_CLEAR"
|
|
374
|
+
RAIN_ACCOMPANIED_BY_LIGHTNING = "RAIN_ACCOMPANIED_BY_LIGHTNING"
|
|
375
|
+
RAIN_ACCOMPANIED_BY_WINDSTORM = "RAIN_ACCOMPANIED_BY_WINDSTORM"
|
|
376
|
+
RAIN_CLEAR_AT_NIGHT = "RAIN_CLEAR_AT_NIGHT"
|
|
377
|
+
RAIN_CLEAR_FROM_AROUND_EVENING = "RAIN_CLEAR_FROM_AROUND_EVENING"
|
|
378
|
+
RAIN_CLEAR_FROM_AROUND_NOON = "RAIN_CLEAR_FROM_AROUND_NOON"
|
|
379
|
+
RAIN_LATER_BECOMING_CLEAR = "RAIN_LATER_BECOMING_CLEAR"
|
|
380
|
+
RAIN_LATER_BECOMING_CLOUDY = "RAIN_LATER_BECOMING_CLOUDY"
|
|
381
|
+
RAIN_LATER_BECOMING_SNOW = "RAIN_LATER_BECOMING_SNOW"
|
|
382
|
+
RAIN_LATER_WITH_PERIODIC_SNOW = "RAIN_LATER_WITH_PERIODIC_SNOW"
|
|
383
|
+
RAIN_SNOW_AT_NIGHT = "RAIN_SNOW_AT_NIGHT"
|
|
384
|
+
RAIN_SNOW_IN_THE_EVENING = "RAIN_SNOW_IN_THE_EVENING"
|
|
385
|
+
RAIN_TEMPORARILY_BECOMING_SLEET = "RAIN_TEMPORARILY_BECOMING_SLEET"
|
|
386
|
+
RAIN_THAT_PERIODICALLY_STOPS = "RAIN_THAT_PERIODICALLY_STOPS"
|
|
387
|
+
RAIN_WITH_BRIEF_SNOW = "RAIN_WITH_BRIEF_SNOW"
|
|
388
|
+
RAIN_WITH_PERIODIC_SNOW = "RAIN_WITH_PERIODIC_SNOW"
|
|
389
|
+
SNOWRAIN_MIX_LATER_BECOMING_CLEAR_SNOW_AS_MAIN = "SNOWRAIN_MIX_LATER_BECOMING_CLEAR_SNOW_AS_MAIN"
|
|
390
|
+
SNOWRAIN_MIX_LATER_BECOMING_CLOUDY_SNOW_AS_MAIN = "SNOWRAIN_MIX_LATER_BECOMING_CLOUDY_SNOW_AS_MAIN"
|
|
391
|
+
SNOWRAIN_MIX_SNOW_AS_MAIN = "SNOWRAIN_MIX_SNOW_AS_MAIN"
|
|
392
|
+
SNOW_ACCOMPANIED_BY_LIGHTNING = "SNOW_ACCOMPANIED_BY_LIGHTNING"
|
|
393
|
+
SNOW_BECOMING_SLEET = "SNOW_BECOMING_SLEET"
|
|
394
|
+
SNOW_LATER_CLEAR = "SNOW_LATER_CLEAR"
|
|
395
|
+
SNOW_LATER_CLOUDY = "SNOW_LATER_CLOUDY"
|
|
396
|
+
SNOW_LATER_RAIN = "SNOW_LATER_RAIN"
|
|
397
|
+
SNOW_PERIODICALLY_CLEAR = "SNOW_PERIODICALLY_CLEAR"
|
|
398
|
+
SNOW_THAT_PERIODICALLY_STOPS = "SNOW_THAT_PERIODICALLY_STOPS"
|
|
399
|
+
SNOW_TURNING_TO_RAIN_AROUND_NOON = "SNOW_TURNING_TO_RAIN_AROUND_NOON"
|
|
400
|
+
SNOW_TURNING_TO_RAIN_IN_THE_EVENING = "SNOW_TURNING_TO_RAIN_IN_THE_EVENING"
|
|
401
|
+
SNOW_TURNING_TO_RAIN_IN_THE_NIGHT = "SNOW_TURNING_TO_RAIN_IN_THE_NIGHT"
|
|
402
|
+
SNOW_WITH_BRIEF_RAIN = "SNOW_WITH_BRIEF_RAIN"
|
|
403
|
+
SNOW_WITH_BRIEF_SLEET = "SNOW_WITH_BRIEF_SLEET"
|
|
404
|
+
SNOW_WITH_PERIODIC_RAIN = "SNOW_WITH_PERIODIC_RAIN"
|
|
405
|
+
VERY_HOT = "VERY_HOT"
|
|
406
|
+
SLEET = "SLEET"
|
|
407
|
+
HEAVY_RAIN_TO_RAINSTORM = "HEAVY_RAIN_TO_RAINSTORM"
|
|
292
408
|
|
|
293
409
|
icon_base_uri: str = field(metadata={"alias": "iconBaseUri"})
|
|
294
410
|
"""The base URI for the icon not including the file type extension."""
|
|
@@ -311,10 +427,10 @@ class IceThickness(BaseModel):
|
|
|
311
427
|
MILLIMETERS = "MILLIMETERS"
|
|
312
428
|
INCHES = "INCHES"
|
|
313
429
|
|
|
314
|
-
thickness: float
|
|
430
|
+
thickness: float | None = None
|
|
315
431
|
"""The ice thickness value."""
|
|
316
432
|
|
|
317
|
-
unit: Unit
|
|
433
|
+
unit: Unit = Unit.UNIT_UNSPECIFIED
|
|
318
434
|
"""The code that represents the unit used to measure the ice thickness."""
|
|
319
435
|
|
|
320
436
|
|
|
@@ -334,6 +450,9 @@ class CurrentConditionsHistory(BaseModel):
|
|
|
334
450
|
qpf: QuantitativePrecipitationForecast
|
|
335
451
|
"""The amount of precipitation (rain or snow) accumulated over the last 24 hours."""
|
|
336
452
|
|
|
453
|
+
snow_qpf: QuantitativePrecipitationForecast | None = field(default=None, metadata={"alias": "snowQpf"})
|
|
454
|
+
"""The amount of snow accumulation over the last 24 hours, measured as liquid water equivalent."""
|
|
455
|
+
|
|
337
456
|
|
|
338
457
|
@dataclass
|
|
339
458
|
class CurrentConditionsResponse(BaseModel):
|
|
@@ -387,11 +506,11 @@ class CurrentConditionsResponse(BaseModel):
|
|
|
387
506
|
uv_index: int = field(metadata={"alias": "uvIndex"})
|
|
388
507
|
"""The current ultraviolet (UV) index."""
|
|
389
508
|
|
|
390
|
-
thunderstorm_probability: int = field(metadata={"alias": "thunderstormProbability"})
|
|
391
|
-
"""The current thunderstorm probability (0-100)."""
|
|
509
|
+
thunderstorm_probability: int | None = field(default=None, metadata={"alias": "thunderstormProbability"})
|
|
510
|
+
"""The current thunderstorm probability (0-100). Omitted in some regions (e.g. Japan and South Korea)."""
|
|
392
511
|
|
|
393
|
-
cloud_cover: int = field(metadata={"alias": "cloudCover"})
|
|
394
|
-
"""The current percentage of the sky covered by clouds (0-100)."""
|
|
512
|
+
cloud_cover: int | None = field(default=None, metadata={"alias": "cloudCover"})
|
|
513
|
+
"""The current percentage of the sky covered by clouds (0-100). Omitted in some regions (e.g. Japan and South Korea)."""
|
|
395
514
|
|
|
396
515
|
|
|
397
516
|
@dataclass
|
|
@@ -410,7 +529,7 @@ class Date(BaseModel):
|
|
|
410
529
|
|
|
411
530
|
@dataclass
|
|
412
531
|
class ForecastDayPart(BaseModel):
|
|
413
|
-
"""Represents a forecast record for a part of the day (daytime or
|
|
532
|
+
"""Represents a forecast record for a part of the day (daytime, nighttime, or full day)."""
|
|
414
533
|
|
|
415
534
|
interval: Interval
|
|
416
535
|
"""The UTC date and time when this part of the day starts and ends."""
|
|
@@ -430,11 +549,11 @@ class ForecastDayPart(BaseModel):
|
|
|
430
549
|
uv_index: int = field(metadata={"alias": "uvIndex"})
|
|
431
550
|
"""The maximum forecasted ultraviolet (UV) index."""
|
|
432
551
|
|
|
433
|
-
thunderstorm_probability: int = field(metadata={"alias": "thunderstormProbability"})
|
|
434
|
-
"""The average thunderstorm probability."""
|
|
552
|
+
thunderstorm_probability: int | None = field(default=None, metadata={"alias": "thunderstormProbability"})
|
|
553
|
+
"""The average thunderstorm probability. Omitted in some regions (e.g. Japan and South Korea)."""
|
|
435
554
|
|
|
436
|
-
cloud_cover: int = field(metadata={"alias": "cloudCover"})
|
|
437
|
-
"""Average cloud cover percent."""
|
|
555
|
+
cloud_cover: int | None = field(default=None, metadata={"alias": "cloudCover"})
|
|
556
|
+
"""Average cloud cover percent. Omitted in some regions (e.g. Japan and South Korea)."""
|
|
438
557
|
|
|
439
558
|
ice_thickness: IceThickness | None = field(default=None, metadata={"alias": "iceThickness"})
|
|
440
559
|
"""The forecasted ice thickness."""
|
|
@@ -458,7 +577,7 @@ class MoonEvents(BaseModel):
|
|
|
458
577
|
class MoonPhase(ApiStrEnum):
|
|
459
578
|
"""Marks the moon phase (a.k.a. lunar phase)."""
|
|
460
579
|
|
|
461
|
-
|
|
580
|
+
PHASE_UNSPECIFIED = "PHASE_UNSPECIFIED"
|
|
462
581
|
NEW_MOON = "NEW_MOON"
|
|
463
582
|
WAXING_CRESCENT = "WAXING_CRESCENT"
|
|
464
583
|
FIRST_QUARTER = "FIRST_QUARTER"
|
|
@@ -488,12 +607,6 @@ class ForecastDay(BaseModel):
|
|
|
488
607
|
display_date: Date = field(metadata={"alias": "displayDate"})
|
|
489
608
|
"""The local date in the time zone of the location."""
|
|
490
609
|
|
|
491
|
-
daytime_forecast: ForecastDayPart = field(metadata={"alias": "daytimeForecast"})
|
|
492
|
-
"""The forecasted weather conditions for the daytime part of the day."""
|
|
493
|
-
|
|
494
|
-
nighttime_forecast: ForecastDayPart = field(metadata={"alias": "nighttimeForecast"})
|
|
495
|
-
"""The forecasted weather conditions for the nighttime part of the day."""
|
|
496
|
-
|
|
497
610
|
max_temperature: Temperature = field(metadata={"alias": "maxTemperature"})
|
|
498
611
|
"""The maximum (high) temperature throughout the day."""
|
|
499
612
|
|
|
@@ -515,6 +628,15 @@ class ForecastDay(BaseModel):
|
|
|
515
628
|
moon_events: MoonEvents = field(metadata={"alias": "moonEvents"})
|
|
516
629
|
"""The events related to the moon (e.g. moonrise, moonset)."""
|
|
517
630
|
|
|
631
|
+
daytime_forecast: ForecastDayPart | None = field(default=None, metadata={"alias": "daytimeForecast"})
|
|
632
|
+
"""The forecasted weather conditions for the daytime part of the day."""
|
|
633
|
+
|
|
634
|
+
nighttime_forecast: ForecastDayPart | None = field(default=None, metadata={"alias": "nighttimeForecast"})
|
|
635
|
+
"""The forecasted weather conditions for the nighttime part of the day."""
|
|
636
|
+
|
|
637
|
+
full_day_forecast: ForecastDayPart | None = field(default=None, metadata={"alias": "fullDayForecast"})
|
|
638
|
+
"""The forecasted weather conditions for the full day (returned instead of daytime/nighttime in Japan and South Korea)."""
|
|
639
|
+
|
|
518
640
|
ice_thickness: IceThickness | None = field(default=None, metadata={"alias": "iceThickness"})
|
|
519
641
|
"""The accumulated amount of ice throughout the entire day."""
|
|
520
642
|
|
|
@@ -523,12 +645,12 @@ class ForecastDay(BaseModel):
|
|
|
523
645
|
class DailyForecastResponse(BaseModel):
|
|
524
646
|
"""Response model for the forecast.days.lookup method."""
|
|
525
647
|
|
|
526
|
-
forecast_days: list[ForecastDay] = field(metadata={"alias": "forecastDays"})
|
|
527
|
-
"""The daily forecast records."""
|
|
528
|
-
|
|
529
648
|
time_zone: TimeZone = field(metadata={"alias": "timeZone"})
|
|
530
649
|
"""The time zone at the requested location."""
|
|
531
650
|
|
|
651
|
+
forecast_days: list[ForecastDay] = field(default_factory=list, metadata={"alias": "forecastDays"})
|
|
652
|
+
"""The daily forecast records."""
|
|
653
|
+
|
|
532
654
|
next_page_token: str | None = field(default=None, metadata={"alias": "nextPageToken"})
|
|
533
655
|
"""The token to retrieve the next page."""
|
|
534
656
|
|
|
@@ -617,11 +739,11 @@ class ForecastHour(BaseModel):
|
|
|
617
739
|
uv_index: int = field(metadata={"alias": "uvIndex"})
|
|
618
740
|
"""The forecasted ultraviolet (UV) index."""
|
|
619
741
|
|
|
620
|
-
thunderstorm_probability: int = field(metadata={"alias": "thunderstormProbability"})
|
|
621
|
-
"""The forecasted thunderstorm probability (0-100)."""
|
|
742
|
+
thunderstorm_probability: int | None = field(default=None, metadata={"alias": "thunderstormProbability"})
|
|
743
|
+
"""The forecasted thunderstorm probability (0-100). Omitted in some regions (e.g. Japan and South Korea)."""
|
|
622
744
|
|
|
623
|
-
cloud_cover: int = field(metadata={"alias": "cloudCover"})
|
|
624
|
-
"""The forecasted percentage of the sky covered by clouds (0-100)."""
|
|
745
|
+
cloud_cover: int | None = field(default=None, metadata={"alias": "cloudCover"})
|
|
746
|
+
"""The forecasted percentage of the sky covered by clouds (0-100). Omitted in some regions (e.g. Japan and South Korea)."""
|
|
625
747
|
|
|
626
748
|
ice_thickness: IceThickness | None = field(default=None, metadata={"alias": "iceThickness"})
|
|
627
749
|
"""The forecasted ice thickness."""
|
|
@@ -631,12 +753,12 @@ class ForecastHour(BaseModel):
|
|
|
631
753
|
class HourlyForecastResponse(BaseModel):
|
|
632
754
|
"""Response model for the forecast.hours.lookup method."""
|
|
633
755
|
|
|
634
|
-
forecast_hours: list[ForecastHour] = field(metadata={"alias": "forecastHours"})
|
|
635
|
-
"""The hourly forecast records."""
|
|
636
|
-
|
|
637
756
|
time_zone: TimeZone = field(metadata={"alias": "timeZone"})
|
|
638
757
|
"""The time zone at the requested location."""
|
|
639
758
|
|
|
759
|
+
forecast_hours: list[ForecastHour] = field(default_factory=list, metadata={"alias": "forecastHours"})
|
|
760
|
+
"""The hourly forecast records."""
|
|
761
|
+
|
|
640
762
|
next_page_token: str | None = field(default=None, metadata={"alias": "nextPageToken"})
|
|
641
763
|
"""The token to retrieve the next page."""
|
|
642
764
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
google_weather_api/__init__.py,sha256=sOOI0Muwa4HERSM6W1OCtumAasjuV_7WkCFKEDm3T8c,1691
|
|
2
|
+
google_weather_api/api.py,sha256=m8P4RGegQPS--eDvotlF4LXK8ZglcjLJqydsv9MMiHY,8198
|
|
3
|
+
google_weather_api/exceptions.py,sha256=z4rKXfRZLhkFLt1MISki1-nTxV_5Uc14ppjW7qu0ZNQ,708
|
|
4
|
+
google_weather_api/model.py,sha256=6PKYNwBp6cjLQiCTgTxs_L75VjkrsJVY5sgj00tJiMA,33879
|
|
5
|
+
google_weather_api/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
python_google_weather_api-0.0.11.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
7
|
+
python_google_weather_api-0.0.11.dist-info/METADATA,sha256=p_PP-eNyR9kjornyCu3efxa-UN7aIM_Gyw4QQyyph_8,1413
|
|
8
|
+
python_google_weather_api-0.0.11.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
9
|
+
python_google_weather_api-0.0.11.dist-info/top_level.txt,sha256=ZkFbtKDHz3vUJhH6DGEPVLj3PPeNpR9-Wg0f4HqGD78,19
|
|
10
|
+
python_google_weather_api-0.0.11.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
google_weather_api/__init__.py,sha256=Su4PjNcbIJFYoFCEH4wwdtT-M2HSMtLNLvF-TWGHiNo,1601
|
|
2
|
-
google_weather_api/api.py,sha256=4_Y8TN6Mtrf4JDGoBOVm6W0uedxe5sPxMVx-ktD2kCI,7478
|
|
3
|
-
google_weather_api/exceptions.py,sha256=AHHzb-cbE0bgzp4PH2IC5s3jHAJHONbL9iw5b-_MvoU,534
|
|
4
|
-
google_weather_api/model.py,sha256=2Dx6VGh5Uaotb3McZSNs0BT6iJTrr5spYEUUC-IlXiA,24858
|
|
5
|
-
google_weather_api/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
python_google_weather_api-0.0.9.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
7
|
-
python_google_weather_api-0.0.9.dist-info/METADATA,sha256=SvCCnXAfToJfdwSvgBJ1D41y3lR3IsJGxgBwl_WJY5E,1412
|
|
8
|
-
python_google_weather_api-0.0.9.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
9
|
-
python_google_weather_api-0.0.9.dist-info/top_level.txt,sha256=ZkFbtKDHz3vUJhH6DGEPVLj3PPeNpR9-Wg0f4HqGD78,19
|
|
10
|
-
python_google_weather_api-0.0.9.dist-info/RECORD,,
|
{python_google_weather_api-0.0.9.dist-info → python_google_weather_api-0.0.11.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|