Skip to content

Commit 39d8aff

Browse files
Drain completed future exceptions for invalid callback returns
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 6664ff2 commit 39d8aff

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

hyperbrowser/client/polling.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,16 @@ def _ensure_non_awaitable(
9393
if inspect.isawaitable(result):
9494
if inspect.iscoroutine(result):
9595
result.close()
96-
elif isinstance(result, asyncio.Future) and not result.done():
97-
result.cancel()
96+
elif isinstance(result, asyncio.Future):
97+
if result.done():
98+
try:
99+
result.exception()
100+
except asyncio.CancelledError:
101+
pass
102+
except Exception:
103+
pass
104+
else:
105+
result.cancel()
98106
raise _NonRetryablePollingError(
99107
f"{callback_name} must return a non-awaitable result for {operation_name}"
100108
)

tests/test_polling.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,27 @@ def test_retry_operation_cancels_future_operation_results():
654654
loop.close()
655655

656656

657+
def test_retry_operation_consumes_completed_future_exceptions():
658+
loop = asyncio.new_event_loop()
659+
try:
660+
completed_future = loop.create_future()
661+
completed_future.set_exception(RuntimeError("boom"))
662+
663+
with pytest.raises(
664+
HyperbrowserError, match="operation must return a non-awaitable result"
665+
):
666+
retry_operation(
667+
operation_name="sync retry completed-future callback",
668+
operation=lambda: completed_future, # type: ignore[return-value]
669+
max_attempts=5,
670+
retry_delay_seconds=0.0001,
671+
)
672+
673+
assert getattr(completed_future, "_log_traceback", False) is False
674+
finally:
675+
loop.close()
676+
677+
657678
def test_async_polling_and_retry_helpers():
658679
async def run() -> None:
659680
status_values = iter(["pending", "completed"])

0 commit comments

Comments
 (0)