phystack-hub-client 6.18.1__tar.gz → 6.18.2__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.
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/PKG-INFO +1 -1
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/pyproject.toml +1 -1
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/client.py +12 -2
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/cloud_twins.py +11 -3
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_client_integration.py +31 -1
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/.gitignore +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/CHANGELOG.md +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/README.md +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/examples/browser_test_backend.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/scripts/python-node-test.sh +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/scripts/webrtc-test.sh +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/__init__.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/advisory_validation.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/instances/__init__.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/instances/base_instance.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/instances/edge_instance.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/instances/peripheral_instance.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/scoped_hardware_id.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/__init__.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/cloud_app_connection.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/cloud_app_token.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/phyhub_connection.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/signals.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/web_session_code.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/webrtc/__init__.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/webrtc/data_channel.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/webrtc/data_responder.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/webrtc/media_responder.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/webrtc/media_source.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/services/webrtc/media_stream.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/twin_messaging.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/twin_registry.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/types/__init__.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/types/twin_types.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_advisory_validation.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_cloud_app_token.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_cloud_twins.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_communication.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_data_channel.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_instance_listeners.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_media_kinds.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_media_resilience.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_media_responder.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_media_source.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_no_google_stun.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_peripheral_lifecycle.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_signals_rollover.py +0 -0
- {phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_web_session_code.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: phystack-hub-client
|
|
3
|
-
Version: 6.18.
|
|
3
|
+
Version: 6.18.2
|
|
4
4
|
Summary: Python client for PhyHub - events, actions, DataChannel, and MediaStream
|
|
5
5
|
Project-URL: Homepage, https://github.com/phystack/phystack-pypi
|
|
6
6
|
Project-URL: Documentation, https://docs.phystack.com
|
|
@@ -7,7 +7,7 @@ name = "phystack-hub-client"
|
|
|
7
7
|
# Fixed version group with the Node hub-client (@phystack/hub-client in
|
|
8
8
|
# phystack/ps-platform): both clients implement the same twin/WebRTC contract
|
|
9
9
|
# and are released together under the same version.
|
|
10
|
-
version = "6.18.
|
|
10
|
+
version = "6.18.2"
|
|
11
11
|
description = "Python client for PhyHub - events, actions, DataChannel, and MediaStream"
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
license = "MIT"
|
|
@@ -365,8 +365,18 @@ class PhyHubClient:
|
|
|
365
365
|
|
|
366
366
|
self._connection.on(self.EVENTS.TWIN_MESSAGE, on_twin_message)
|
|
367
367
|
|
|
368
|
-
def on_twin_updated(payload: dict[str, Any]) -> None:
|
|
369
|
-
"""Handle twin property update events.
|
|
368
|
+
def on_twin_updated(payload: dict[str, Any], *_extra: Any) -> None:
|
|
369
|
+
"""Handle twin property update events.
|
|
370
|
+
|
|
371
|
+
``*_extra`` absorbs any trailing positional argument the server
|
|
372
|
+
appends to the ``twinUpdated`` emit. Some phyhub builds send twin
|
|
373
|
+
lifecycle events with a second positional arg (event metadata);
|
|
374
|
+
JS clients silently ignore it, but python-socketio passes every
|
|
375
|
+
positional arg through, so a strict ``(payload)`` signature raises
|
|
376
|
+
"takes 1 positional argument but 2 were given" and DROPS EVERY twin
|
|
377
|
+
update — the device stops seeing settings/desired-property changes
|
|
378
|
+
until restarted. Matches the tolerant ``on_twin_message`` sibling.
|
|
379
|
+
"""
|
|
370
380
|
twin_data = payload.get("data") or payload
|
|
371
381
|
twin_id = payload.get("twinId") or (twin_data.get("id") if isinstance(twin_data, dict) else None)
|
|
372
382
|
|
{phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/cloud_twins.py
RENAMED
|
@@ -83,15 +83,23 @@ class CloudTwinStore:
|
|
|
83
83
|
|
|
84
84
|
# --- lifecycle events ---
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
# ``*_extra`` on these three absorbs any trailing positional arg the
|
|
87
|
+
# server appends to a twin lifecycle emit. They are registered directly
|
|
88
|
+
# as socket.io handlers (PhyHubClient cloud-app mode), so a strict
|
|
89
|
+
# ``(payload)`` signature would raise "takes 1 positional argument but 2
|
|
90
|
+
# were given" and silently drop every cloud-twin update — the same defect
|
|
91
|
+
# fixed in PhyHubClient.on_twin_updated. Direct internal callers still
|
|
92
|
+
# pass a single argument.
|
|
93
|
+
|
|
94
|
+
def apply_created(self, payload: CloudTwinLifecycleEvent, *_extra: Any) -> None:
|
|
87
95
|
"""Apply a ``twinCreated`` event and notify ``on_created`` listeners."""
|
|
88
96
|
self._apply(_KIND_CREATED, payload)
|
|
89
97
|
|
|
90
|
-
def apply_updated(self, payload: CloudTwinLifecycleEvent) -> None:
|
|
98
|
+
def apply_updated(self, payload: CloudTwinLifecycleEvent, *_extra: Any) -> None:
|
|
91
99
|
"""Apply a ``twinUpdated`` event and notify ``on_updated`` listeners."""
|
|
92
100
|
self._apply(_KIND_UPDATED, payload)
|
|
93
101
|
|
|
94
|
-
def apply_deleted(self, payload: CloudTwinLifecycleEvent) -> None:
|
|
102
|
+
def apply_deleted(self, payload: CloudTwinLifecycleEvent, *_extra: Any) -> None:
|
|
95
103
|
"""Apply a ``twinDeleted`` event and notify ``on_deleted`` listeners."""
|
|
96
104
|
self._apply(_KIND_DELETED, payload)
|
|
97
105
|
|
|
@@ -12,6 +12,7 @@ class FakeConnection:
|
|
|
12
12
|
self.emitted: list[tuple[str, dict[str, Any]]] = []
|
|
13
13
|
self.device_id = "device-1"
|
|
14
14
|
self.ack_response: Optional[dict[str, Any]] = {"status": "success"}
|
|
15
|
+
self.handlers: dict[str, Any] = {}
|
|
15
16
|
|
|
16
17
|
@property
|
|
17
18
|
def is_connected(self) -> bool:
|
|
@@ -22,7 +23,7 @@ class FakeConnection:
|
|
|
22
23
|
return True
|
|
23
24
|
|
|
24
25
|
def on(self, event: str, handler: Any) -> None:
|
|
25
|
-
|
|
26
|
+
self.handlers[event] = handler
|
|
26
27
|
|
|
27
28
|
async def emit(
|
|
28
29
|
self, method: str, payload: Any = None, callback: bool = False
|
|
@@ -95,6 +96,35 @@ async def test_device_status_cached_for_ten_seconds() -> None:
|
|
|
95
96
|
assert status_calls.count("getDeviceStatus") == 1
|
|
96
97
|
|
|
97
98
|
|
|
99
|
+
def test_twin_updated_handler_tolerates_trailing_positional_arg() -> None:
|
|
100
|
+
"""Regression: some phyhub builds emit `twinUpdated` with a second
|
|
101
|
+
positional arg. python-socketio forwards every positional arg, so a
|
|
102
|
+
strict `(payload)` handler raised "takes 1 positional argument but 2 were
|
|
103
|
+
given" and dropped every twin update fleet-wide (edge apps stopped seeing
|
|
104
|
+
settings changes until restarted). The handler must accept and ignore the
|
|
105
|
+
extra arg the way JS clients do."""
|
|
106
|
+
client, connection = make_client()
|
|
107
|
+
client._setup_socket_listeners()
|
|
108
|
+
|
|
109
|
+
on_twin_updated = connection.handlers["twinUpdated"]
|
|
110
|
+
received: list[dict[str, Any]] = []
|
|
111
|
+
# Register the listener directly to keep the test on the handler's arity,
|
|
112
|
+
# not the subscribe machinery (`on_twin_update` spawns an async task).
|
|
113
|
+
client._twin_update_listeners["twin-x"] = {lambda data: received.append(data)}
|
|
114
|
+
|
|
115
|
+
payload = {
|
|
116
|
+
"twinId": "twin-x",
|
|
117
|
+
"data": {"id": "twin-x", "properties": {"desired": {"volume": 5}}},
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# One positional arg (phyhub master) — the baseline that already worked.
|
|
121
|
+
on_twin_updated(payload)
|
|
122
|
+
# Two positional args (the QA build that triggered the crash) — must not raise.
|
|
123
|
+
on_twin_updated(payload, {"eventId": "evt-1"})
|
|
124
|
+
|
|
125
|
+
assert received == [payload["data"], payload["data"]]
|
|
126
|
+
|
|
127
|
+
|
|
98
128
|
def test_public_exports_importable() -> None:
|
|
99
129
|
import phystack.hub_client as hub_client
|
|
100
130
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/__init__.py
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/twin_messaging.py
RENAMED
|
File without changes
|
{phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/twin_registry.py
RENAMED
|
File without changes
|
{phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/src/phystack/hub_client/types/__init__.py
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
{phystack_hub_client-6.18.1 → phystack_hub_client-6.18.2}/tests/test_peripheral_lifecycle.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|