python-google-weather-api 0.0.8__tar.gz → 0.0.9__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_google_weather_api-0.0.8/src/python_google_weather_api.egg-info → python_google_weather_api-0.0.9}/PKG-INFO +1 -1
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/pyproject.toml +1 -1
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/google_weather_api/api.py +6 -3
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9/src/python_google_weather_api.egg-info}/PKG-INFO +1 -1
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/tests/test_api.py +20 -2
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/LICENSE +0 -0
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/README.md +0 -0
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/setup.cfg +0 -0
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/google_weather_api/__init__.py +0 -0
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/google_weather_api/exceptions.py +0 -0
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/google_weather_api/model.py +0 -0
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/google_weather_api/py.typed +0 -0
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/python_google_weather_api.egg-info/SOURCES.txt +0 -0
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/python_google_weather_api.egg-info/dependency_links.txt +0 -0
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/python_google_weather_api.egg-info/requires.txt +0 -0
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/python_google_weather_api.egg-info/top_level.txt +0 -0
- {python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/tests/test_model.py +0 -0
{python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/google_weather_api/api.py
RENAMED
|
@@ -23,6 +23,8 @@ from .model import (
|
|
|
23
23
|
_LOGGER = logging.getLogger(__name__)
|
|
24
24
|
|
|
25
25
|
_BASE_URL = "https://weather.googleapis.com/v1"
|
|
26
|
+
# See https://docs.cloud.google.com/docs/authentication/api-keys-use
|
|
27
|
+
_API_KEY_HEADER = "X-Goog-Api-Key"
|
|
26
28
|
_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"
|
|
27
29
|
|
|
28
30
|
|
|
@@ -49,7 +51,10 @@ class GoogleWeatherApi:
|
|
|
49
51
|
async def _async_get(self, endpoint: str, params: dict[str, Any], *, include_language_code: bool = True) -> dict[str, Any]:
|
|
50
52
|
"""Perform a GET request."""
|
|
51
53
|
url = f"{_BASE_URL}/{endpoint}"
|
|
52
|
-
|
|
54
|
+
# Send the API key in a header rather than the "key" query parameter so it
|
|
55
|
+
# never ends up in a URL, which aiohttp includes in exceptions such as
|
|
56
|
+
# ContentTypeError and which callers commonly log.
|
|
57
|
+
headers = {aiohttp.hdrs.USER_AGENT: _USER_AGENT, _API_KEY_HEADER: self.api_key}
|
|
53
58
|
if self.referrer:
|
|
54
59
|
headers[aiohttp.hdrs.REFERER] = self.referrer
|
|
55
60
|
params = {
|
|
@@ -58,9 +63,7 @@ class GoogleWeatherApi:
|
|
|
58
63
|
}
|
|
59
64
|
if include_language_code:
|
|
60
65
|
params["language_code"] = self.language_code
|
|
61
|
-
# Log before adding the API key so it doesn't end up in debug logs.
|
|
62
66
|
_LOGGER.debug("GET %s with params: %s", url, params)
|
|
63
|
-
params["key"] = self.api_key
|
|
64
67
|
try:
|
|
65
68
|
async with self.session.get(
|
|
66
69
|
url,
|
|
@@ -41,7 +41,8 @@ async def test_request_params_and_headers(api: GoogleWeatherApi, mock_server: Mo
|
|
|
41
41
|
await api.async_get_current_conditions(LATITUDE, LONGITUDE)
|
|
42
42
|
|
|
43
43
|
request = mock_server.requests[0]
|
|
44
|
-
assert request.
|
|
44
|
+
assert request.headers["X-Goog-Api-Key"] == API_KEY
|
|
45
|
+
assert "key" not in request.query
|
|
45
46
|
assert request.query["location.latitude"] == str(LATITUDE)
|
|
46
47
|
assert request.query["location.longitude"] == str(LONGITUDE)
|
|
47
48
|
assert request.query["language_code"] == "en"
|
|
@@ -126,7 +127,7 @@ async def test_get_hourly_forecast_follows_pagination(api: GoogleWeatherApi, moc
|
|
|
126
127
|
assert first.query["hours"] == "4"
|
|
127
128
|
assert second.query["page_token"] == page1["nextPageToken"]
|
|
128
129
|
assert second.query["hours"] == "4"
|
|
129
|
-
assert second.
|
|
130
|
+
assert second.headers["X-Goog-Api-Key"] == API_KEY
|
|
130
131
|
|
|
131
132
|
|
|
132
133
|
async def test_hourly_forecast_stops_once_enough_records(api: GoogleWeatherApi, mock_server: MockServer) -> None:
|
|
@@ -238,6 +239,23 @@ async def test_non_json_response(api: GoogleWeatherApi, mock_server: MockServer)
|
|
|
238
239
|
await api.async_get_current_conditions(LATITUDE, LONGITUDE)
|
|
239
240
|
|
|
240
241
|
|
|
242
|
+
async def test_api_key_not_in_error_message(api: GoogleWeatherApi, mock_server: MockServer) -> None:
|
|
243
|
+
"""Test the API key does not leak into errors that include the request URL.
|
|
244
|
+
|
|
245
|
+
aiohttp includes the full request URL in ContentTypeError, which callers
|
|
246
|
+
commonly log, e.g. for a 502 HTML page from a proxy in front of the API.
|
|
247
|
+
"""
|
|
248
|
+
mock_server.add_response("<html>502 Bad Gateway</html>", status=HTTPStatus.BAD_GATEWAY)
|
|
249
|
+
|
|
250
|
+
with pytest.raises(GoogleWeatherApiConnectionError) as exc_info:
|
|
251
|
+
await api.async_get_current_conditions(LATITUDE, LONGITUDE)
|
|
252
|
+
|
|
253
|
+
assert "currentConditions:lookup" in str(exc_info.value)
|
|
254
|
+
assert API_KEY not in str(exc_info.value)
|
|
255
|
+
# Tracebacks render chained exceptions with str(), so the cause must be clean too.
|
|
256
|
+
assert API_KEY not in str(exc_info.value.__cause__)
|
|
257
|
+
|
|
258
|
+
|
|
241
259
|
@pytest.mark.parametrize(
|
|
242
260
|
("raised", "expected_message"),
|
|
243
261
|
[
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/google_weather_api/model.py
RENAMED
|
File without changes
|
{python_google_weather_api-0.0.8 → python_google_weather_api-0.0.9}/src/google_weather_api/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|