March 26 2026
Fixed
- Ensure
PubNubAsyncioExceptionalways carries a validPNStatuswith error data instead ofNone. - Handle cases where status or
error_dataisNoneinstead of raisingAttributeError. - Match
PubNubAsyncioExceptionwhich is whatrequest_futureactually returns on failure. - Handle
-1 (unlimited)correctly sinceattempts > -1was alwaystrue, causing immediate give-up. - Use delay class defaults instead of config value which could be
NonecausingTypeErroron comparison. - Prevent falling through to start a heartbeat after deciding to give up.
- Set all four timeout fields explicitly instead of a 2-tuple that left write and pool unset.
- On macOS and Linux,
time.monotonic()does not advance during system sleep, causing socket andasynciotimeouts (310s subscribe) to stall for hours of wall-clock time. Addtime.time()-based deadline checks that detect sleep and cancel stale requests within ~5s of wake. - Use
asyncio.wait()with periodictime.time()checks instead of a single monotonic-basedwait_for(), yielding to the event loop between checks. - Persistent single daemon thread monitors
time.time()every 5s and closes thehttpxsession when the wall-clock deadline passes, interrupting the blocking socket read. Tracks deadlines per calling thread so concurrent requests (e.g., subscribe + publish) don't interfere. Only armed for long-timeout requests (>30s). Session is recreated for subsequent requests.
Modified
- Cover both
asyncioand threads paths simulated clock jumps, normal passthrough, clean watchdog shutdown, per-thread deadline isolation, concurrent request independence, cleanup, and exception propagation. - Ensure
pubnub.stop()always runs to prevent non-daemon threads from blocking process exit. - Enable presence heartbeat and use unique channel names so presence registers on the server.
- Restore
cipher_keyafter use insend_fileand pass it explicitly todownload_file. - Avoid collisions with stale data from prior test runs.