python-homely 0.1.7__py3-none-any.whl → 0.1.9__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.
homely/client.py CHANGED
@@ -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(url, json=payload, timeout=self._timeout) as response:
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:
homely/websocket.py CHANGED
@@ -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
@@ -368,10 +370,13 @@ class HomelyWebSocket:
368
370
 
369
371
  self._set_status("Connecting")
370
372
  try:
373
+ # SECURITY: never enable the engineio logger. It logs the full
374
+ # connection URL, which carries the bearer token in the query
375
+ # string (?token=Bearer <access_token>), leaking it to HA logs.
371
376
  self.socket = socketio.AsyncClient(
372
377
  reconnection=False,
373
378
  logger=False,
374
- engineio_logger=logging.getLogger("engineio.client"),
379
+ engineio_logger=False,
375
380
  )
376
381
 
377
382
  async def connect() -> None:
@@ -405,12 +410,16 @@ class HomelyWebSocket:
405
410
  self.socket.on("connect_error", connect_error)
406
411
 
407
412
  bearer_token = self._bearer_value(self.token)
408
- query = urlencode(
409
- {
410
- "locationId": str(self.location_id),
411
- "token": bearer_token,
412
- }
413
- )
413
+ query_params: dict[str, str] = {
414
+ "locationId": str(self.location_id),
415
+ "token": bearer_token,
416
+ }
417
+ # NOTE: do NOT send a "partner" query parameter. Homely's websocket
418
+ # server rejects it ("Partner <code> is not supported") and closes
419
+ # the connection immediately, causing a connect/disconnect loop.
420
+ # partner_code is accepted for API compatibility but intentionally
421
+ # unused here.
422
+ query = urlencode(query_params)
414
423
  url = f"{self.websocket_url}?{query}"
415
424
  _LOGGER.debug("WebSocket connecting %s to %s", self._ctx(), self.websocket_url)
416
425
  await asyncio.wait_for(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-homely
3
- Version: 0.1.7
3
+ Version: 0.1.9
4
4
  Summary: Async Python client for the Homely cloud API, built for Home Assistant but usable anywhere.
5
5
  Author: Ludvik Blichfeldt Rød
6
6
  License-Expression: MIT
@@ -0,0 +1,11 @@
1
+ homely/__init__.py,sha256=TK4sclUiHqDewtsOenxS9KNLkprZxqbiYkh__JeNmMA,1023
2
+ homely/client.py,sha256=4kDsZkj3P7z6iNlWZJX9De5GiRATD3GdY_beEXC_ZAg,18781
3
+ homely/exceptions.py,sha256=w6y5MC8yjPe5QtI-YEKUsbAPF1D0ARWx6ZkRsLTjrgQ,1040
4
+ homely/models.py,sha256=8chNpjo1SF4TGww7XPWFUK3kXILH3bSmUnjNteyfsys,1842
5
+ homely/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
6
+ homely/websocket.py,sha256=Zf-NcRO_pEqb9A2LEPVyeqYbMaAeUVFL_qBrLuJI9OI,20262
7
+ python_homely-0.1.9.dist-info/licenses/LICENSE,sha256=nNVHKvQjryAonWsz5TbhzLd6M2kZaoNUvhxz92MgeAA,1079
8
+ python_homely-0.1.9.dist-info/METADATA,sha256=nAPt3MWkZThc8lpYyqJXWzNBSMNkr5ZzNJiKfuT0mX8,5239
9
+ python_homely-0.1.9.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
10
+ python_homely-0.1.9.dist-info/top_level.txt,sha256=auE-j6ghVMdT_jAw04jiXthgbuLpi-jYBU0fCkKvREQ,7
11
+ python_homely-0.1.9.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- homely/__init__.py,sha256=TK4sclUiHqDewtsOenxS9KNLkprZxqbiYkh__JeNmMA,1023
2
- homely/client.py,sha256=iqM1ChFEVez5PJcvWk8BlkkVx4bekaQacBa-rAvSxpo,18276
3
- homely/exceptions.py,sha256=w6y5MC8yjPe5QtI-YEKUsbAPF1D0ARWx6ZkRsLTjrgQ,1040
4
- homely/models.py,sha256=8chNpjo1SF4TGww7XPWFUK3kXILH3bSmUnjNteyfsys,1842
5
- homely/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
6
- homely/websocket.py,sha256=X84KhYVsmqwSmab18D-MgMKi2W0J8aMgRcPx417CPCY,19624
7
- python_homely-0.1.7.dist-info/licenses/LICENSE,sha256=nNVHKvQjryAonWsz5TbhzLd6M2kZaoNUvhxz92MgeAA,1079
8
- python_homely-0.1.7.dist-info/METADATA,sha256=Rp3rNA6o9CjOP1oD2LmQjTBS6OPyVUt1YqZLySN_OwU,5239
9
- python_homely-0.1.7.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
10
- python_homely-0.1.7.dist-info/top_level.txt,sha256=auE-j6ghVMdT_jAw04jiXthgbuLpi-jYBU0fCkKvREQ,7
11
- python_homely-0.1.7.dist-info/RECORD,,