Fix `spawn` fixture cleanup + test assertions
Improve the `spawn` fixture teardown logic in `tests/devx/conftest.py` fixing the while-else bug, and fix `test_advanced_faults` genexp for `TransportClosed` exc type checking. Deats, - replace broken `while-else` pattern with direct `if ptyproc.isalive()` check after the SIGINT loop. - fix undefined `spawned` ref -> `ptyproc.isalive()` in while condition. - improve walrus expr formatting in timeout check (multiline style). Also fix `test_ipc_channel_break_during_stream()` assertion, - wrap genexp in `all()` call so it actually checks all excs are `TransportClosed` instead of just creating an unused generator. (this patch was suggested by copilot in, https://github.com/goodboy/tractor/pull/411) (this commit msg was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-codetpt_tolerance
parent
592d918394
commit
9470815f5a
|
|
@ -101,15 +101,18 @@ def spawn(
|
||||||
start: float = time.time()
|
start: float = time.time()
|
||||||
timeout: float = 5
|
timeout: float = 5
|
||||||
while (
|
while (
|
||||||
spawned
|
ptyproc.isalive()
|
||||||
and
|
and
|
||||||
spawned.isalive()
|
(
|
||||||
and
|
(_time_took := (time.time() - start))
|
||||||
(_time_took := (time.time() - start) < timeout)
|
<
|
||||||
|
timeout
|
||||||
|
)
|
||||||
):
|
):
|
||||||
ptyproc.kill(signal.SIGINT)
|
ptyproc.kill(signal.SIGINT)
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
else:
|
|
||||||
|
if ptyproc.isalive():
|
||||||
ptyproc.kill(signal.SIGKILL)
|
ptyproc.kill(signal.SIGKILL)
|
||||||
|
|
||||||
# TODO? ensure we've cleaned up any UDS-paths?
|
# TODO? ensure we've cleaned up any UDS-paths?
|
||||||
|
|
|
||||||
|
|
@ -255,8 +255,10 @@ def test_ipc_channel_break_during_stream(
|
||||||
assert (
|
assert (
|
||||||
len(excs) <= 2
|
len(excs) <= 2
|
||||||
and
|
and
|
||||||
(isinstance(exc, TransportClosed)
|
all(
|
||||||
for exc in excs)
|
isinstance(exc, TransportClosed)
|
||||||
|
for exc in excs
|
||||||
|
)
|
||||||
)
|
)
|
||||||
final_exc = excs[0]
|
final_exc = excs[0]
|
||||||
assert isinstance(final_exc, expect_final_exc)
|
assert isinstance(final_exc, expect_final_exc)
|
||||||
|
|
|
||||||
|
|
@ -284,9 +284,14 @@ async def _errors_relayed_via_ipc(
|
||||||
try:
|
try:
|
||||||
yield # run RPC invoke body
|
yield # run RPC invoke body
|
||||||
|
|
||||||
except TransportClosed:
|
# NOTE, never REPL any pseudo-expected tpt-disconnect.
|
||||||
log.exception('Tpt disconnect during remote-exc relay?')
|
except TransportClosed as err:
|
||||||
raise
|
rpc_err = err
|
||||||
|
log.warning(
|
||||||
|
f'Tpt disconnect during remote-exc relay due to,\n'
|
||||||
|
f'{err!r}\n'
|
||||||
|
)
|
||||||
|
raise err
|
||||||
|
|
||||||
# box and ship RPC errors for wire-transit via
|
# box and ship RPC errors for wire-transit via
|
||||||
# the task's requesting parent IPC-channel.
|
# the task's requesting parent IPC-channel.
|
||||||
|
|
@ -323,9 +328,6 @@ async def _errors_relayed_via_ipc(
|
||||||
and debug_kbis
|
and debug_kbis
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
# TODO? better then `debug_filter` below?
|
|
||||||
and
|
|
||||||
not isinstance(err, TransportClosed)
|
|
||||||
):
|
):
|
||||||
# XXX QUESTION XXX: is there any case where we'll
|
# XXX QUESTION XXX: is there any case where we'll
|
||||||
# want to debug IPC disconnects as a default?
|
# want to debug IPC disconnects as a default?
|
||||||
|
|
@ -346,13 +348,6 @@ async def _errors_relayed_via_ipc(
|
||||||
entered_debug = await debug._maybe_enter_pm(
|
entered_debug = await debug._maybe_enter_pm(
|
||||||
err,
|
err,
|
||||||
api_frame=inspect.currentframe(),
|
api_frame=inspect.currentframe(),
|
||||||
|
|
||||||
# don't REPL any psuedo-expected tpt-disconnect
|
|
||||||
# debug_filter=lambda exc: (
|
|
||||||
# type (exc) not in {
|
|
||||||
# TransportClosed,
|
|
||||||
# }
|
|
||||||
# ),
|
|
||||||
)
|
)
|
||||||
if not entered_debug:
|
if not entered_debug:
|
||||||
# if we prolly should have entered the REPL but
|
# if we prolly should have entered the REPL but
|
||||||
|
|
@ -438,7 +433,7 @@ async def _errors_relayed_via_ipc(
|
||||||
# cancel scope will not have been inserted yet
|
# cancel scope will not have been inserted yet
|
||||||
if is_rpc:
|
if is_rpc:
|
||||||
log.warning(
|
log.warning(
|
||||||
'RPC task likely errored or cancelled before start?\n'
|
'RPC task likely crashed or cancelled before start?\n'
|
||||||
f'|_{ctx._task}\n'
|
f'|_{ctx._task}\n'
|
||||||
f' >> {ctx.repr_rpc}\n'
|
f' >> {ctx.repr_rpc}\n'
|
||||||
)
|
)
|
||||||
|
|
@ -694,22 +689,6 @@ async def _invoke(
|
||||||
f'{pretty_struct.pformat(return_msg)}\n'
|
f'{pretty_struct.pformat(return_msg)}\n'
|
||||||
)
|
)
|
||||||
await chan.send(return_msg)
|
await chan.send(return_msg)
|
||||||
# ?TODO, remove the below since .send() already
|
|
||||||
# doesn't raise on tpt-closed?
|
|
||||||
# try:
|
|
||||||
# await chan.send(return_msg)
|
|
||||||
# except TransportClosed:
|
|
||||||
# log.exception(
|
|
||||||
# f"Failed send final result to 'parent'-side of IPC-ctx!\n"
|
|
||||||
# f'\n'
|
|
||||||
# f'{chan}\n'
|
|
||||||
# f'Channel already disconnected ??\n'
|
|
||||||
# f'\n'
|
|
||||||
# f'{pretty_struct.pformat(return_msg)}'
|
|
||||||
# )
|
|
||||||
# # ?TODO? will this ever be true though?
|
|
||||||
# if chan.connected():
|
|
||||||
# raise
|
|
||||||
|
|
||||||
# NOTE: this happens IFF `ctx._scope.cancel()` is
|
# NOTE: this happens IFF `ctx._scope.cancel()` is
|
||||||
# called by any of,
|
# called by any of,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue