python-google-weather-api 0.0.7__py3-none-any.whl → 0.0.8__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 +4 -0
- google_weather_api/api.py +41 -7
- google_weather_api/model.py +61 -0
- {python_google_weather_api-0.0.7.dist-info → python_google_weather_api-0.0.8.dist-info}/METADATA +1 -1
- python_google_weather_api-0.0.8.dist-info/RECORD +10 -0
- python_google_weather_api-0.0.7.dist-info/RECORD +0 -10
- {python_google_weather_api-0.0.7.dist-info → python_google_weather_api-0.0.8.dist-info}/WHEEL +0 -0
- {python_google_weather_api-0.0.7.dist-info → python_google_weather_api-0.0.8.dist-info}/licenses/LICENSE +0 -0
- {python_google_weather_api-0.0.7.dist-info → python_google_weather_api-0.0.8.dist-info}/top_level.txt +0 -0
google_weather_api/__init__.py
CHANGED
|
@@ -21,9 +21,11 @@ from .model import (
|
|
|
21
21
|
IceThickness,
|
|
22
22
|
Interval,
|
|
23
23
|
LocalizedText,
|
|
24
|
+
MinuteForecastResponse,
|
|
24
25
|
MoonEvents,
|
|
25
26
|
Precipitation,
|
|
26
27
|
PrecipitationProbability,
|
|
28
|
+
PrecipitationSegment,
|
|
27
29
|
QuantitativePrecipitationForecast,
|
|
28
30
|
SunEvents,
|
|
29
31
|
Temperature,
|
|
@@ -54,9 +56,11 @@ __all__ = [
|
|
|
54
56
|
"IceThickness",
|
|
55
57
|
"Interval",
|
|
56
58
|
"LocalizedText",
|
|
59
|
+
"MinuteForecastResponse",
|
|
57
60
|
"MoonEvents",
|
|
58
61
|
"Precipitation",
|
|
59
62
|
"PrecipitationProbability",
|
|
63
|
+
"PrecipitationSegment",
|
|
60
64
|
"QuantitativePrecipitationForecast",
|
|
61
65
|
"SunEvents",
|
|
62
66
|
"Temperature",
|
google_weather_api/api.py
CHANGED
|
@@ -17,6 +17,7 @@ from .model import (
|
|
|
17
17
|
CurrentConditionsResponse,
|
|
18
18
|
DailyForecastResponse,
|
|
19
19
|
HourlyForecastResponse,
|
|
20
|
+
MinuteForecastResponse,
|
|
20
21
|
)
|
|
21
22
|
|
|
22
23
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -45,7 +46,7 @@ class GoogleWeatherApi:
|
|
|
45
46
|
self.referrer = referrer
|
|
46
47
|
self.timeout = aiohttp.ClientTimeout(total=timeout)
|
|
47
48
|
|
|
48
|
-
async def _async_get(self, endpoint: str, params: dict[str, Any]) -> dict[str, Any]:
|
|
49
|
+
async def _async_get(self, endpoint: str, params: dict[str, Any], *, include_language_code: bool = True) -> dict[str, Any]:
|
|
49
50
|
"""Perform a GET request."""
|
|
50
51
|
url = f"{_BASE_URL}/{endpoint}"
|
|
51
52
|
headers = {aiohttp.hdrs.USER_AGENT: _USER_AGENT}
|
|
@@ -53,9 +54,10 @@ class GoogleWeatherApi:
|
|
|
53
54
|
headers[aiohttp.hdrs.REFERER] = self.referrer
|
|
54
55
|
params = {
|
|
55
56
|
**params,
|
|
56
|
-
"language_code": self.language_code,
|
|
57
57
|
"units_system": self.units_system,
|
|
58
58
|
}
|
|
59
|
+
if include_language_code:
|
|
60
|
+
params["language_code"] = self.language_code
|
|
59
61
|
# Log before adding the API key so it doesn't end up in debug logs.
|
|
60
62
|
_LOGGER.debug("GET %s with params: %s", url, params)
|
|
61
63
|
params["key"] = self.api_key
|
|
@@ -89,18 +91,27 @@ class GoogleWeatherApi:
|
|
|
89
91
|
raise GoogleWeatherApiConnectionError(err) from err
|
|
90
92
|
|
|
91
93
|
async def _async_get_all_pages(
|
|
92
|
-
self,
|
|
94
|
+
self,
|
|
95
|
+
endpoint: str,
|
|
96
|
+
params: dict[str, Any],
|
|
97
|
+
records_key: str,
|
|
98
|
+
limit: int,
|
|
99
|
+
*,
|
|
100
|
+
include_language_code: bool = True,
|
|
93
101
|
) -> dict[str, Any]:
|
|
94
102
|
"""Perform a GET request, following pagination until `limit` records are collected.
|
|
95
103
|
|
|
96
|
-
|
|
97
|
-
|
|
104
|
+
Some endpoints cap the number of records they return per page regardless of the
|
|
105
|
+
requested page size, for example 24 for hourly forecasts, so a single request is
|
|
106
|
+
not always enough.
|
|
98
107
|
"""
|
|
99
108
|
params = {**params, "page_size": limit}
|
|
100
|
-
data = await self._async_get(endpoint, params)
|
|
109
|
+
data = await self._async_get(endpoint, params, include_language_code=include_language_code)
|
|
101
110
|
records: list[Any] = data.get(records_key, [])
|
|
102
111
|
while len(records) < limit and (page_token := data.get("nextPageToken")):
|
|
103
|
-
data = await self._async_get(
|
|
112
|
+
data = await self._async_get(
|
|
113
|
+
endpoint, {**params, "page_token": page_token}, include_language_code=include_language_code
|
|
114
|
+
)
|
|
104
115
|
page_records: list[Any] = data.get(records_key, [])
|
|
105
116
|
if not page_records:
|
|
106
117
|
break
|
|
@@ -155,3 +166,26 @@ class GoogleWeatherApi:
|
|
|
155
166
|
days,
|
|
156
167
|
)
|
|
157
168
|
return DailyForecastResponse.from_dict(data)
|
|
169
|
+
|
|
170
|
+
async def async_get_minute_forecast(
|
|
171
|
+
self, latitude: float, longitude: float, page_size: int = 360
|
|
172
|
+
) -> MinuteForecastResponse:
|
|
173
|
+
"""Fetch the precipitation nowcast for up to 6 hours.
|
|
174
|
+
|
|
175
|
+
Segments cover 2- or 15-minute intervals depending on the location. The endpoint
|
|
176
|
+
does not accept language_code (a reserved field in google.maps.weather.v1), so it
|
|
177
|
+
is omitted from these requests.
|
|
178
|
+
|
|
179
|
+
See https://developers.google.com/maps/documentation/weather/minute-forecast
|
|
180
|
+
"""
|
|
181
|
+
data = await self._async_get_all_pages(
|
|
182
|
+
"forecast/minutes:lookup",
|
|
183
|
+
{
|
|
184
|
+
"location.latitude": latitude,
|
|
185
|
+
"location.longitude": longitude,
|
|
186
|
+
},
|
|
187
|
+
"segments",
|
|
188
|
+
page_size,
|
|
189
|
+
include_language_code=False,
|
|
190
|
+
)
|
|
191
|
+
return MinuteForecastResponse.from_dict(data)
|
google_weather_api/model.py
CHANGED
|
@@ -639,3 +639,64 @@ class HourlyForecastResponse(BaseModel):
|
|
|
639
639
|
|
|
640
640
|
next_page_token: str | None = field(default=None, metadata={"alias": "nextPageToken"})
|
|
641
641
|
"""The token to retrieve the next page."""
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
@dataclass
|
|
645
|
+
class PrecipitationSegment(BaseModel):
|
|
646
|
+
"""Represents a segment of precipitation forecast data."""
|
|
647
|
+
|
|
648
|
+
class DominantPrecipitationType(ApiStrEnum):
|
|
649
|
+
"""Represents the type of precipitation of a segment."""
|
|
650
|
+
|
|
651
|
+
DOMINANT_PRECIPITATION_TYPE_UNSPECIFIED = "DOMINANT_PRECIPITATION_TYPE_UNSPECIFIED"
|
|
652
|
+
NONE = "NONE"
|
|
653
|
+
RAIN = "RAIN"
|
|
654
|
+
SNOW = "SNOW"
|
|
655
|
+
HAIL = "HAIL"
|
|
656
|
+
|
|
657
|
+
class PrecipitationIntensity(ApiStrEnum):
|
|
658
|
+
"""Represents the precipitation intensity of a segment."""
|
|
659
|
+
|
|
660
|
+
PRECIPITATION_INTENSITY_UNSPECIFIED = "PRECIPITATION_INTENSITY_UNSPECIFIED"
|
|
661
|
+
NO_INTENSITY = "NO_INTENSITY"
|
|
662
|
+
LIGHT = "LIGHT"
|
|
663
|
+
MID_LIGHT = "MID_LIGHT"
|
|
664
|
+
MODERATE = "MODERATE"
|
|
665
|
+
MID_MODERATE = "MID_MODERATE"
|
|
666
|
+
HEAVY = "HEAVY"
|
|
667
|
+
MID_HEAVY = "MID_HEAVY"
|
|
668
|
+
|
|
669
|
+
time_frame: Interval = field(metadata={"alias": "timeFrame"})
|
|
670
|
+
"""The timeframe relevant to the segment."""
|
|
671
|
+
|
|
672
|
+
type: DominantPrecipitationType = DominantPrecipitationType.DOMINANT_PRECIPITATION_TYPE_UNSPECIFIED
|
|
673
|
+
"""A code that indicates the type of precipitation."""
|
|
674
|
+
|
|
675
|
+
probability: int = 0
|
|
676
|
+
"""The chance of precipitation (values from 0 to 100)."""
|
|
677
|
+
|
|
678
|
+
qpf: QuantitativePrecipitationForecast | None = None
|
|
679
|
+
"""The amount of precipitation, measured as liquid water equivalent."""
|
|
680
|
+
|
|
681
|
+
snowfall_amount: QuantitativePrecipitationForecast | None = field(default=None, metadata={"alias": "snowfallAmount"})
|
|
682
|
+
"""The amount of snow accumulation, measured as liquid water equivalent."""
|
|
683
|
+
|
|
684
|
+
intensity: PrecipitationIntensity = PrecipitationIntensity.PRECIPITATION_INTENSITY_UNSPECIFIED
|
|
685
|
+
"""A code that indicates the precipitation intensity of the segment."""
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
@dataclass
|
|
689
|
+
class MinuteForecastResponse(BaseModel):
|
|
690
|
+
"""Response model for the forecast.minutes.lookup method."""
|
|
691
|
+
|
|
692
|
+
overall_prediction_timeframe: Interval = field(metadata={"alias": "overallPredictionTimeframe"})
|
|
693
|
+
"""The overall timeframe for the predictions."""
|
|
694
|
+
|
|
695
|
+
time_zone: TimeZone = field(metadata={"alias": "timeZone"})
|
|
696
|
+
"""The time zone at the requested location."""
|
|
697
|
+
|
|
698
|
+
segments: list[PrecipitationSegment] = field(default_factory=list)
|
|
699
|
+
"""The minute-level prediction segments."""
|
|
700
|
+
|
|
701
|
+
next_page_token: str | None = field(default=None, metadata={"alias": "nextPageToken"})
|
|
702
|
+
"""The token to retrieve the next page."""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
google_weather_api/__init__.py,sha256=Su4PjNcbIJFYoFCEH4wwdtT-M2HSMtLNLvF-TWGHiNo,1601
|
|
2
|
+
google_weather_api/api.py,sha256=NOSVkaj7YKHy6DL8J6x2HnUfA0V_J4GRFcsMS_EpyCs,7235
|
|
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.8.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
7
|
+
python_google_weather_api-0.0.8.dist-info/METADATA,sha256=T33mjBiV5-p4PY__jHyKzYsvqI2sWOT-JGsskuGgYfk,1412
|
|
8
|
+
python_google_weather_api-0.0.8.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
9
|
+
python_google_weather_api-0.0.8.dist-info/top_level.txt,sha256=ZkFbtKDHz3vUJhH6DGEPVLj3PPeNpR9-Wg0f4HqGD78,19
|
|
10
|
+
python_google_weather_api-0.0.8.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
google_weather_api/__init__.py,sha256=mIsd7IvUJhucWozTmTKqDHT2wtGEPMG34Ux2Ve9q8QM,1489
|
|
2
|
-
google_weather_api/api.py,sha256=7RzupmA5E0ft-Yn_ygGCIDxIz1bcB1iXuo0cbcU0vsY,5997
|
|
3
|
-
google_weather_api/exceptions.py,sha256=AHHzb-cbE0bgzp4PH2IC5s3jHAJHONbL9iw5b-_MvoU,534
|
|
4
|
-
google_weather_api/model.py,sha256=9dwgYTRLi37XPNDL0X5OZrBut6qBjxqO8BL4kFl-iL0,22500
|
|
5
|
-
google_weather_api/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
python_google_weather_api-0.0.7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
7
|
-
python_google_weather_api-0.0.7.dist-info/METADATA,sha256=KJCoHyP64kq1mZdcH3r4_zUn955g3bbfwy3_b4MBwTw,1412
|
|
8
|
-
python_google_weather_api-0.0.7.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
9
|
-
python_google_weather_api-0.0.7.dist-info/top_level.txt,sha256=ZkFbtKDHz3vUJhH6DGEPVLj3PPeNpR9-Wg0f4HqGD78,19
|
|
10
|
-
python_google_weather_api-0.0.7.dist-info/RECORD,,
|
{python_google_weather_api-0.0.7.dist-info → python_google_weather_api-0.0.8.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|