python-homely 0.1.7__tar.gz → 0.1.8__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_homely-0.1.7/src/python_homely.egg-info → python_homely-0.1.8}/PKG-INFO +1 -1
- {python_homely-0.1.7 → python_homely-0.1.8}/pyproject.toml +1 -1
- {python_homely-0.1.7 → python_homely-0.1.8}/src/homely/client.py +14 -2
- {python_homely-0.1.7 → python_homely-0.1.8}/src/homely/websocket.py +9 -6
- {python_homely-0.1.7 → python_homely-0.1.8/src/python_homely.egg-info}/PKG-INFO +1 -1
- {python_homely-0.1.7 → python_homely-0.1.8}/tests/test_sdk.py +3 -1
- {python_homely-0.1.7 → python_homely-0.1.8}/LICENSE +0 -0
- {python_homely-0.1.7 → python_homely-0.1.8}/README.md +0 -0
- {python_homely-0.1.7 → python_homely-0.1.8}/setup.cfg +0 -0
- {python_homely-0.1.7 → python_homely-0.1.8}/src/homely/__init__.py +0 -0
- {python_homely-0.1.7 → python_homely-0.1.8}/src/homely/exceptions.py +0 -0
- {python_homely-0.1.7 → python_homely-0.1.8}/src/homely/models.py +0 -0
- {python_homely-0.1.7 → python_homely-0.1.8}/src/homely/py.typed +0 -0
- {python_homely-0.1.7 → python_homely-0.1.8}/src/python_homely.egg-info/SOURCES.txt +0 -0
- {python_homely-0.1.7 → python_homely-0.1.8}/src/python_homely.egg-info/dependency_links.txt +0 -0
- {python_homely-0.1.7 → python_homely-0.1.8}/src/python_homely.egg-info/requires.txt +0 -0
- {python_homely-0.1.7 → python_homely-0.1.8}/src/python_homely.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-homely"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.8"
|
|
8
8
|
description = "Async Python client for the Homely cloud API, built for Home Assistant but usable anywhere."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -189,6 +189,7 @@ class HomelyClient:
|
|
|
189
189
|
payload=payload,
|
|
190
190
|
invalid_reason="invalid_refresh_token",
|
|
191
191
|
action="Token refresh",
|
|
192
|
+
extra_headers={"X-Forwarded-For": "0.0.0.0"},
|
|
192
193
|
)
|
|
193
194
|
|
|
194
195
|
async def fetch_refresh_token(self, refresh_token: str) -> dict[str, Any] | None:
|
|
@@ -217,12 +218,15 @@ class HomelyClient:
|
|
|
217
218
|
payload: dict[str, Any],
|
|
218
219
|
invalid_reason: TokenFailureReason,
|
|
219
220
|
action: str,
|
|
221
|
+
extra_headers: dict[str, str] | None = None,
|
|
220
222
|
) -> TokenEndpointResult:
|
|
221
223
|
"""Post to a token endpoint and return a detailed typed result."""
|
|
222
224
|
url = f"{self._base_url}{endpoint}"
|
|
223
225
|
|
|
224
226
|
try:
|
|
225
|
-
async with self._session.post(
|
|
227
|
+
async with self._session.post(
|
|
228
|
+
url, json=payload, headers=extra_headers, timeout=self._timeout
|
|
229
|
+
) as response:
|
|
226
230
|
body_preview = await self._response_text_preview(response)
|
|
227
231
|
if response.status in (200, 201):
|
|
228
232
|
try:
|
|
@@ -442,10 +446,18 @@ class HomelyClient:
|
|
|
442
446
|
)
|
|
443
447
|
return None, response.status
|
|
444
448
|
return parsed, response.status
|
|
449
|
+
retry_after = response.headers.get("Retry-After")
|
|
450
|
+
try:
|
|
451
|
+
body = await response.text()
|
|
452
|
+
except Exception:
|
|
453
|
+
body = "<unreadable>"
|
|
445
454
|
_LOGGER.debug(
|
|
446
|
-
"Location data fetch failed with status=%s location_id=%s"
|
|
455
|
+
"Location data fetch failed with status=%s location_id=%s "
|
|
456
|
+
"retry_after=%s body=%s",
|
|
447
457
|
response.status,
|
|
448
458
|
_log_identifier(location_id),
|
|
459
|
+
retry_after,
|
|
460
|
+
body[:500] if body else None,
|
|
449
461
|
)
|
|
450
462
|
return None, response.status
|
|
451
463
|
except (aiohttp.ClientError, TimeoutError) as err:
|
|
@@ -89,12 +89,14 @@ class HomelyWebSocket:
|
|
|
89
89
|
status_update_callback: Callable[[str, str | None], None] | None = None,
|
|
90
90
|
context_id: str | None = None,
|
|
91
91
|
entry_id: str | None = None,
|
|
92
|
+
partner_code: int | str | None = None,
|
|
92
93
|
) -> None:
|
|
93
94
|
"""Initialize WebSocket client."""
|
|
94
95
|
self.context_id = context_id or entry_id
|
|
95
96
|
self.entry_id = self.context_id
|
|
96
97
|
self.location_id = location_id
|
|
97
98
|
self.token = token
|
|
99
|
+
self.partner_code = partner_code
|
|
98
100
|
self.on_data_update = on_data_update
|
|
99
101
|
self.socket: Any | None = None
|
|
100
102
|
self._is_closing = False
|
|
@@ -405,12 +407,13 @@ class HomelyWebSocket:
|
|
|
405
407
|
self.socket.on("connect_error", connect_error)
|
|
406
408
|
|
|
407
409
|
bearer_token = self._bearer_value(self.token)
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
410
|
+
query_params: dict[str, str] = {
|
|
411
|
+
"locationId": str(self.location_id),
|
|
412
|
+
"token": bearer_token,
|
|
413
|
+
}
|
|
414
|
+
if self.partner_code is not None:
|
|
415
|
+
query_params["partner"] = str(self.partner_code)
|
|
416
|
+
query = urlencode(query_params)
|
|
414
417
|
url = f"{self.websocket_url}?{query}"
|
|
415
418
|
_LOGGER.debug("WebSocket connecting %s to %s", self._ctx(), self.websocket_url)
|
|
416
419
|
await asyncio.wait_for(
|
|
@@ -32,11 +32,13 @@ class _FakeResponse:
|
|
|
32
32
|
json_data=None,
|
|
33
33
|
text_data: str = "",
|
|
34
34
|
json_exc: Exception | None = None,
|
|
35
|
+
headers: dict[str, str] | None = None,
|
|
35
36
|
) -> None:
|
|
36
37
|
self.status = status
|
|
37
38
|
self._json_data = json_data
|
|
38
39
|
self._text_data = text_data
|
|
39
40
|
self._json_exc = json_exc
|
|
41
|
+
self.headers = headers or {}
|
|
40
42
|
|
|
41
43
|
async def __aenter__(self):
|
|
42
44
|
return self
|
|
@@ -93,7 +95,7 @@ class _FakeAsyncCallable:
|
|
|
93
95
|
async def test_sdk_exports_public_symbols():
|
|
94
96
|
"""The SDK should expose a clean public surface."""
|
|
95
97
|
assert auth_header_value("token") == "Bearer token"
|
|
96
|
-
assert __version__ == "0.1.
|
|
98
|
+
assert __version__ == "0.1.8"
|
|
97
99
|
|
|
98
100
|
|
|
99
101
|
async def test_authenticate_returns_typed_token():
|
|
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
|
|
File without changes
|
|
File without changes
|