Drop test-local timeouts, +`sync_pause` to dev

In `pyproject.toml`,
- include the `sync_pause` group from `dev`, so dev
  installs ship `greenback` for `pause_from_sync()`.

Comment out per-test `@pytest.mark.timeout(...)`
markers in,
- `tests/devx/test_debugger.py`
- `tests/discovery/test_registrar.py`
- `tests/spawn/test_main_thread_forkserver.py`
- `tests/spawn/test_subint_cancellation.py`
- `tests/test_advanced_streaming.py`
- `tests/test_cancellation.py`

The global cap was already dropped (3c366cac); these
were the leftover per-test caps which now block
interactive `pdb` flows under the new spawn backends.

In `uv.lock`,
- pull `greenback` into the resolved `dev` deps
  (per the `sync_pause` include above).
- catch up the prior `xonsh` editable→PyPI switch
  (from the `pyproject.toml` `tool.uv.sources` edit).

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
subint_forkserver_backend
Gud Boi 2026-04-29 18:10:40 -04:00
parent 208e7c0926
commit b7115fc875
9 changed files with 40 additions and 87 deletions

View File

@ -62,6 +62,7 @@ dev = [
{include-group = 'devx'}, {include-group = 'devx'},
{include-group = 'testing'}, {include-group = 'testing'},
{include-group = 'repl'}, {include-group = 'repl'},
{include-group = 'sync_pause'},
] ]
devx = [ devx = [
# `tractor.devx` tooling # `tractor.devx` tooling

View File

@ -4,6 +4,7 @@
''' '''
from __future__ import annotations from __future__ import annotations
import platform import platform
import os
import signal import signal
import time import time
from typing import ( from typing import (
@ -90,7 +91,6 @@ def spawn(
https://docs.python.org/3/using/cmdline.html#using-on-controlling-color https://docs.python.org/3/using/cmdline.html#using-on-controlling-color
''' '''
import os
# disable colored tbs # disable colored tbs
os.environ['PYTHON_COLORS'] = '0' os.environ['PYTHON_COLORS'] = '0'
# disable all ANSI color output # disable all ANSI color output
@ -104,7 +104,6 @@ def spawn(
without requiring per-script CLI plumbing. without requiring per-script CLI plumbing.
''' '''
import os
os.environ['TRACTOR_SPAWN_METHOD'] = start_method os.environ['TRACTOR_SPAWN_METHOD'] = start_method
def set_loglevel(): def set_loglevel():
@ -116,7 +115,6 @@ def spawn(
the test harness without per-script edits. the test harness without per-script edits.
''' '''
import os
if loglevel: if loglevel:
os.environ['TRACTOR_LOGLEVEL'] = loglevel os.environ['TRACTOR_LOGLEVEL'] = loglevel
else: else:
@ -176,13 +174,11 @@ def spawn(
if ptyproc.isalive(): if ptyproc.isalive():
ptyproc.kill(signal.SIGKILL) ptyproc.kill(signal.SIGKILL)
# Scope our env-var mutations to this single fixture # Scope our env-var mutations to this single fixture invocation
# invocation — both `TRACTOR_SPAWN_METHOD` and # — both `TRACTOR_SPAWN_METHOD` and `TRACTOR_LOGLEVEL` are
# `TRACTOR_LOGLEVEL` are honored by # honored by `tractor._root.open_root_actor()` so leaking them
# `tractor._root.open_root_actor()` so leaking them past # past this test could inadvertently re-route a later in-process
# this test could inadvertently re-route a later # tractor test's spawn-backend / loglevel.
# in-process tractor test's spawn-backend / loglevel.
import os
os.environ.pop('TRACTOR_SPAWN_METHOD', None) os.environ.pop('TRACTOR_SPAWN_METHOD', None)
os.environ.pop('TRACTOR_LOGLEVEL', None) os.environ.pop('TRACTOR_LOGLEVEL', None)

View File

@ -841,7 +841,7 @@ def test_multi_nested_subactors_error_through_nurseries(
) )
@pytest.mark.timeout(15) # @pytest.mark.timeout(15)
@has_nested_actors @has_nested_actors
def test_root_nursery_cancels_before_child_releases_tty_lock( def test_root_nursery_cancels_before_child_releases_tty_lock(
spawn, spawn,

View File

@ -535,13 +535,13 @@ async def kill_transport(
# At timeout the plugin hard-kills the pytest process — that's # At timeout the plugin hard-kills the pytest process — that's
# the intended behavior here; the alternative is an unattended # the intended behavior here; the alternative is an unattended
# suite run that never returns. # suite run that never returns.
@pytest.mark.timeout( # @pytest.mark.timeout(
30, # 30,
# NOTE should be a 2.1s happy path. # # NOTE should be a 2.1s happy path.
# XXX for `main_thread_forkserver` this is SUPER SENSITIVE # # XXX for `main_thread_forkserver` this is SUPER SENSITIVE
# so keep it higher to avoid flaky runs.. # # so keep it higher to avoid flaky runs..
method='thread', # method='thread',
) # )
@pytest.mark.skipon_spawn_backend( @pytest.mark.skipon_spawn_backend(
'subint', 'subint',
# 'main_thread_forkserver', # 'main_thread_forkserver',

View File

@ -182,7 +182,7 @@ async def run_fork_in_non_trio_thread(
# `subint_sigint_starvation_issue.md`. Each test also has an # `subint_sigint_starvation_issue.md`. Each test also has an
# inner `trio.fail_after()` so assertion failures fire fast # inner `trio.fail_after()` so assertion failures fire fast
# under normal conditions. # under normal conditions.
@pytest.mark.timeout(30, method='thread') # @pytest.mark.timeout(30, method='thread')
def test_fork_from_worker_thread_via_trio( def test_fork_from_worker_thread_via_trio(
) -> None: ) -> None:
''' '''

View File

@ -179,10 +179,10 @@ def test_subint_happy_teardown(
# `subint_sigint_starvation_issue.md` GIL-starvation flavor, # `subint_sigint_starvation_issue.md` GIL-starvation flavor,
# so `method='thread'` keeps us safe in case ordering or # so `method='thread'` keeps us safe in case ordering or
# load shifts the failure mode. # load shifts the failure mode.
@pytest.mark.timeout( # @pytest.mark.timeout(
3, # NOTE never passes pre-3.14+ subints support. # 3, # NOTE never passes pre-3.14+ subints support.
method='thread', # method='thread',
) # )
def test_subint_non_checkpointing_child( def test_subint_non_checkpointing_child(
reg_addr: tuple[str, int|str], reg_addr: tuple[str, int|str],
) -> None: ) -> None:

View File

@ -430,10 +430,10 @@ async def inf_streamer(
print('streamer exited .open_streamer() block') print('streamer exited .open_streamer() block')
@pytest.mark.timeout( # @pytest.mark.timeout(
6, # 6,
method='signal', # method='signal',
) # )
def test_local_task_fanout_from_stream( def test_local_task_fanout_from_stream(
reg_addr: tuple, reg_addr: tuple,
debug_mode: bool, debug_mode: bool,

View File

@ -458,10 +458,10 @@ async def spawn_and_error(
# `test_nested_multierrors`. See # `test_nested_multierrors`. See
# `ai/conc-anal/subint_forkserver_test_cancellation_leak_issue.md` # `ai/conc-anal/subint_forkserver_test_cancellation_leak_issue.md`
# / #449 for the post-mortem. # / #449 for the post-mortem.
@pytest.mark.timeout( # @pytest.mark.timeout(
10, # 10,
method='thread', # method='thread',
) # )
@tractor_test @tractor_test
async def test_nested_multierrors( async def test_nested_multierrors(
reg_addr: tuple, reg_addr: tuple,

68
uv.lock
View File

@ -682,6 +682,7 @@ dependencies = [
[package.dev-dependencies] [package.dev-dependencies]
dev = [ dev = [
{ name = "greenback", marker = "python_full_version < '3.14'" },
{ name = "pexpect" }, { name = "pexpect" },
{ name = "prompt-toolkit" }, { name = "prompt-toolkit" },
{ name = "psutil" }, { name = "psutil" },
@ -736,6 +737,7 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
{ name = "greenback", marker = "python_full_version == '3.13.*'", specifier = ">=1.2.1,<2" },
{ name = "pexpect", specifier = ">=4.9.0,<5" }, { name = "pexpect", specifier = ">=4.9.0,<5" },
{ name = "prompt-toolkit", specifier = ">=3.0.50" }, { name = "prompt-toolkit", specifier = ">=3.0.50" },
{ name = "psutil", specifier = ">=7.0.0" }, { name = "psutil", specifier = ">=7.0.0" },
@ -744,7 +746,7 @@ dev = [
{ name = "pytest-timeout", specifier = ">=2.3" }, { name = "pytest-timeout", specifier = ">=2.3" },
{ name = "stackscope", specifier = ">=0.2.2,<0.3" }, { name = "stackscope", specifier = ">=0.2.2,<0.3" },
{ name = "typing-extensions", specifier = ">=4.14.1" }, { name = "typing-extensions", specifier = ">=4.14.1" },
{ name = "xonsh", editable = "../xonsh" }, { name = "xonsh", specifier = ">=0.23.0" },
] ]
devx = [ devx = [
{ name = "stackscope", specifier = ">=0.2.2,<0.3" }, { name = "stackscope", specifier = ">=0.2.2,<0.3" },
@ -756,7 +758,7 @@ repl = [
{ name = "prompt-toolkit", specifier = ">=3.0.50" }, { name = "prompt-toolkit", specifier = ">=3.0.50" },
{ name = "psutil", specifier = ">=7.0.0" }, { name = "psutil", specifier = ">=7.0.0" },
{ name = "pyperclip", specifier = ">=1.9.0" }, { name = "pyperclip", specifier = ">=1.9.0" },
{ name = "xonsh", editable = "../xonsh" }, { name = "xonsh", specifier = ">=0.23.0" },
] ]
subints = [{ name = "msgspec", marker = "python_full_version >= '3.14'", specifier = ">=0.21.0" }] subints = [{ name = "msgspec", marker = "python_full_version >= '3.14'", specifier = ">=0.21.0" }]
sync-pause = [{ name = "greenback", marker = "python_full_version == '3.13.*'", specifier = ">=1.2.1,<2" }] sync-pause = [{ name = "greenback", marker = "python_full_version == '3.13.*'", specifier = ">=1.2.1,<2" }]
@ -870,61 +872,15 @@ wheels = [
[[package]] [[package]]
name = "xonsh" name = "xonsh"
source = { editable = "../xonsh" } version = "0.23.2"
source = { registry = "https://pypi.org/simple" }
[package.metadata] sdist = { url = "https://files.pythonhosted.org/packages/60/e5/2dfa99e21a8118bed0e73ed50e91962fdad01b900e23497064e8810b03b5/xonsh-0.23.2.tar.gz", hash = "sha256:633608c8292938af0f242f05326cc2912f25fa72bd808824ab0534a6df304402", size = 1030659, upload-time = "2026-04-26T19:28:40.744Z" }
requires-dist = [ wheels = [
{ name = "click", marker = "extra == 'full'" }, { url = "https://files.pythonhosted.org/packages/53/0d/bf7869dd57b40888ea1da8fc88f70d8e94ec2f8ee236ea4c22a757593235/xonsh-0.23.2-py311-none-any.whl", hash = "sha256:a38dd84e23e97fc42e0156c80024b3449474dfcbb6c3a344bd38c45a2b2de44d", size = 756215, upload-time = "2026-04-26T19:28:38.875Z" },
{ name = "coverage", marker = "extra == 'test'", specifier = ">=5.3.1" }, { url = "https://files.pythonhosted.org/packages/f7/9f/b1bb0c15bf2120469c94b062f4b854588370ab94c7a1679c84ff646bf50b/xonsh-0.23.2-py312-none-any.whl", hash = "sha256:190a348fa19774de8e697af5f44c9adb95aca687fa475b31dda23d1a3462a3c6", size = 756224, upload-time = "2026-04-26T19:28:39.17Z" },
{ name = "distro", marker = "sys_platform == 'linux' and extra == 'full'" }, { url = "https://files.pythonhosted.org/packages/83/23/8e037579ac86d8f266b4116338f902eab04175b88574a6438ee739dd3084/xonsh-0.23.2-py313-none-any.whl", hash = "sha256:4ebbf42a94f505d25694f154556ca0caa149a3f59870ec850bd13ad8df519dce", size = 756728, upload-time = "2026-04-26T19:28:39.493Z" },
{ name = "distro", marker = "extra == 'linux'" }, { url = "https://files.pythonhosted.org/packages/05/ec/090300d9c5f14f58b5a684302f43535457f733a62f11673aa3ac38460717/xonsh-0.23.2-py314-none-any.whl", hash = "sha256:5efcd0f6db8f9f1dace256de2c04c3c044f2d86b48434187c43a69d602283a9e", size = 756767, upload-time = "2026-04-26T19:28:37.218Z" },
{ name = "furo", marker = "extra == 'doc'" },
{ name = "gnureadline", marker = "sys_platform == 'darwin' and extra == 'full'" },
{ name = "gnureadline", marker = "extra == 'mac'" },
{ name = "matplotlib", marker = "extra == 'doc'" },
{ name = "myst-parser", marker = "extra == 'doc'" },
{ name = "numpydoc", marker = "extra == 'doc'" },
{ name = "pre-commit", marker = "extra == 'dev'" },
{ name = "prompt-toolkit", marker = "extra == 'bestshell'", specifier = ">=3.0.29" },
{ name = "prompt-toolkit", marker = "extra == 'ptk'", specifier = ">=3.0.29" },
{ name = "prompt-toolkit", marker = "extra == 'test'", specifier = ">=3.0.29" },
{ name = "psutil", marker = "extra == 'doc'" },
{ name = "pygments", marker = "extra == 'bestshell'", specifier = ">=2.2" },
{ name = "pygments", marker = "extra == 'pygments'", specifier = ">=2.2" },
{ name = "pygments", marker = "extra == 'test'", specifier = ">=2.2" },
{ name = "pyperclip", marker = "extra == 'ptk'" },
{ name = "pyte", marker = "extra == 'test'", specifier = ">=0.8.0" },
{ name = "pytest", marker = "extra == 'test'", specifier = ">=7" },
{ name = "pytest-cov", marker = "extra == 'test'" },
{ name = "pytest-mock", marker = "extra == 'test'" },
{ name = "pytest-rerunfailures", marker = "extra == 'test'" },
{ name = "pytest-subprocess", marker = "extra == 'test'" },
{ name = "pytest-timeout", marker = "extra == 'test'" },
{ name = "pyzmq", marker = "extra == 'doc'" },
{ name = "re-ver", marker = "extra == 'dev'" },
{ name = "requests", marker = "extra == 'test'" },
{ name = "restructuredtext-lint", marker = "extra == 'test'" },
{ name = "runthis-sphinxext", marker = "extra == 'doc'" },
{ name = "setproctitle", marker = "sys_platform == 'win32' and extra == 'full'" },
{ name = "setproctitle", marker = "extra == 'proctitle'" },
{ name = "sphinx", marker = "extra == 'doc'", specifier = ">=3.1" },
{ name = "sphinx-autobuild", marker = "extra == 'doc'" },
{ name = "sphinx-prompt", marker = "extra == 'doc'" },
{ name = "sphinx-reredirects", marker = "extra == 'doc'" },
{ name = "sphinx-sitemap", marker = "extra == 'doc'" },
{ name = "tomli", marker = "extra == 'dev'" },
{ name = "tornado", marker = "extra == 'doc'" },
{ name = "ujson", marker = "extra == 'full'" },
{ name = "virtualenv", marker = "extra == 'test'", specifier = ">=20.16.2" },
{ name = "xonsh", extras = ["bestshell"], marker = "extra == 'doc'" },
{ name = "xonsh", extras = ["bestshell"], marker = "extra == 'test'" },
{ name = "xonsh", extras = ["doc", "test"], marker = "extra == 'dev'" },
{ name = "xonsh", extras = ["ptk", "pygments"], marker = "extra == 'full'" },
] ]
provides-extras = ["ptk", "pygments", "mac", "linux", "proctitle", "full", "bestshell", "test", "dev", "doc"]
[package.metadata.requires-dev]
dev = [{ name = "xonsh", extras = ["dev"] }]
[[package]] [[package]]
name = "zipp" name = "zipp"