Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
3744b19
feat: run popen Message IO on Trio host threads
RonnyPfannschmidt Jul 22, 2026
beb36b9
feat: schedule worker remote_exec from the Trio nursery
RonnyPfannschmidt Jul 22, 2026
37a184f
refactor: drop eventlet and gevent execmodels
RonnyPfannschmidt Jul 22, 2026
60e6ce9
feat: bootstrap same-python popen worker via `python -m`
RonnyPfannschmidt Jul 22, 2026
dfe7391
add claude settings
RonnyPfannschmidt Jul 22, 2026
603dfc6
feat: provision foreign-python popen workers via uv
RonnyPfannschmidt Jul 22, 2026
7656368
test: add local ssh-connect harness + typing cleanups
RonnyPfannschmidt Jul 23, 2026
f153271
feat: run ssh gateways on the Trio path
RonnyPfannschmidt Jul 23, 2026
5197b1e
feat: ship the execnet wheel to ssh remotes for dev coordinators
RonnyPfannschmidt Jul 23, 2026
21096da
feat: add execnet-socketserver console command
RonnyPfannschmidt Jul 23, 2026
420693a
feat: run direct socket gateways on Trio with subprocess workers
RonnyPfannschmidt Jul 23, 2026
b83ff3b
feat: migrate installvia to a GATEWAY_START_SOCKET protocol message
RonnyPfannschmidt Jul 23, 2026
62b746b
refactor: remove the legacy socket coordinator code
RonnyPfannschmidt Jul 23, 2026
19d620d
feat: run popen via-gateways on Trio via GATEWAY_START_POPEN
RonnyPfannschmidt Jul 23, 2026
92969c5
feat: spawn arbitrary via sub-gateways with GATEWAY_START_SUB
RonnyPfannschmidt Jul 24, 2026
48d328c
feat: run vagrant_ssh gateways on the Trio path
RonnyPfannschmidt Jul 24, 2026
3d1d31e
refactor!: remove the legacy bootstrap stack and EXECNET_TRIO_HOST hatch
RonnyPfannschmidt Jul 24, 2026
0a24039
refactor: unify transports on StapledStream with sans-IO frame decoding
RonnyPfannschmidt Jul 24, 2026
f271da5
refactor: extract the LoopPortal cross-thread primitive
RonnyPfannschmidt Jul 24, 2026
0eb6cc5
feat: add the trio-native AsyncGateway core with low-level RawChannels
RonnyPfannschmidt Jul 24, 2026
ed5f99f
feat: layer the serialized AsyncChannel API on RawChannel
RonnyPfannschmidt Jul 24, 2026
80ad5df
feat: run async popen gateways with remote_exec inside the user's tri…
RonnyPfannschmidt Jul 24, 2026
b3b1ab8
feat: add AsyncGroup owning gateways as nursery child scopes
RonnyPfannschmidt Jul 24, 2026
8286b77
feat: make the via tunnel frame-native over raw channel routing
RonnyPfannschmidt Jul 24, 2026
57f899f
docs: record B.4 completion in the phase handoff
RonnyPfannschmidt Jul 24, 2026
f932084
feat: rebuild the sync API as a facade over the async gateway engine
RonnyPfannschmidt Jul 24, 2026
80e237a
docs: record B.5 completion in the phase handoff
RonnyPfannschmidt Jul 24, 2026
4f84335
feat: split the public surface into execnet.sync / execnet.trio / exe…
RonnyPfannschmidt Jul 25, 2026
33decae
docs: record phase B completion in the handoff
RonnyPfannschmidt Jul 25, 2026
51b9053
fix: attach the bridge session before it can serve messages
RonnyPfannschmidt Jul 25, 2026
a69b844
chore: add pytest-xdist to the dev group, ignore claude local settings
RonnyPfannschmidt Jul 25, 2026
72b0eef
docs: hand off phase C/D — worker axes gap analysis, supersede the B doc
RonnyPfannschmidt Jul 25, 2026
2742eb0
fix: drain asyncssh redirect cleanup in the local ssh harness
RonnyPfannschmidt Jul 25, 2026
0d123bd
docs: record PR #422 and the xfail audit in the phase C handoff
RonnyPfannschmidt Jul 26, 2026
2c78416
feat: introduce the boundary kit (Wakener/Mailbox/OneShot) in execnet…
RonnyPfannschmidt Jul 26, 2026
2a40a55
feat!: rebase the sync Channel onto the async core (single dispatch)
RonnyPfannschmidt Jul 26, 2026
811fd99
feat!: retire the ExecModel machinery; add the wait= spec axis
RonnyPfannschmidt Jul 26, 2026
845510e
feat: add execnet.aio -- the asyncio-native API over the Trio host
RonnyPfannschmidt Jul 26, 2026
b01d009
feat: gevent wait backend (wait=gevent) with opt-in tests
RonnyPfannschmidt Jul 26, 2026
5df051c
docs: record the landed boundary rethink (P1-P5) in the handoff
RonnyPfannschmidt Jul 26, 2026
7969f7e
docs: record the decided Phase C plan (axes matrix, trio-only core)
RonnyPfannschmidt Jul 26, 2026
b2f43c3
refactor: extract worker exec placement strategies behind the FIFO pump
RonnyPfannschmidt Jul 26, 2026
d8f22c5
feat!: answer info natively and apply chdir/nice/env from worker config
RonnyPfannschmidt Jul 26, 2026
cd2c871
feat: pure-async worker profile (execmodel=trio)
RonnyPfannschmidt Jul 26, 2026
36e904e
feat!: restore classic hybrid exec for execmodel=thread
RonnyPfannschmidt Jul 26, 2026
cbce183
feat: gevent worker profile and gevent-safe management ops
RonnyPfannschmidt Jul 26, 2026
87c5843
docs: record the landed Phase C worker profiles in the handoff
RonnyPfannschmidt Jul 26, 2026
3031810
feat!: run channel callbacks in an off-loop consumer task
RonnyPfannschmidt Jul 28, 2026
34c9953
fix: serialize ints below the signed int4 minimum via the long opcode
RonnyPfannschmidt Jul 28, 2026
0d36f7f
test: hypothesis stress tests for channel callbacks with a --stress knob
RonnyPfannschmidt Jul 28, 2026
f911ce7
refactor: name the main_thread_only deadlock-admission timeout
RonnyPfannschmidt Jul 28, 2026
8eee047
feat!: hide the standalone serializer from the public API
RonnyPfannschmidt Jul 28, 2026
6a33716
test: type-check the callback stress tests under mypy
RonnyPfannschmidt Jul 28, 2026
12fdbbe
refactor!: drop the injected remote shell script
RonnyPfannschmidt Jul 28, 2026
6718808
refactor!: drop the quitserver script
RonnyPfannschmidt Jul 28, 2026
7124fc0
refactor!: drop the socketserver restart loop script
RonnyPfannschmidt Jul 28, 2026
47e5b78
refactor!: drop the pywin32 windows service wrapper
RonnyPfannschmidt Jul 28, 2026
fa0d7a8
refactor: move the socket server to execnet._socketserver
RonnyPfannschmidt Jul 28, 2026
871dfd7
refactor!: drop the py2/py3 string coercion machinery
RonnyPfannschmidt Jul 28, 2026
740b11c
refactor!: make the accidentally-public modules private
RonnyPfannschmidt Jul 28, 2026
7aa17fe
refactor!: retire the wakener extension point, add execnet.gevent
RonnyPfannschmidt Jul 28, 2026
c0faa50
feat!: rename execmodel= to profile=, deprecate main_thread_only
RonnyPfannschmidt Jul 29, 2026
e75cd0a
feat!: share one Trio host, guard loop misuse, fix aio cancellation
RonnyPfannschmidt Jul 29, 2026
ddce312
docs: record the surface review in the changelog and handoffs
RonnyPfannschmidt Jul 29, 2026
320c89e
ci: run the pytest-xdist test suite against this execnet
RonnyPfannschmidt Jul 30, 2026
17e7c7a
ci: split the xdist job into a pinned release and a floating tip
RonnyPfannschmidt Jul 30, 2026
5710eed
feat!: add the execnet CLI and stop swallowing worker stdout
RonnyPfannschmidt Jul 30, 2026
a84380f
feat!: dial back over ssh -R, run popen on a socketpair
RonnyPfannschmidt Jul 30, 2026
e43db63
refactor: one typed endmarker sentinel, collapsing make_receive_queue
RonnyPfannschmidt Jul 30, 2026
1839800
fix(ci): install the declared test deps, so the suite actually runs
RonnyPfannschmidt Jul 30, 2026
cd42ce9
feat(provision): EXECNET_PROVISION_WHEEL to name the wheel remotes get
RonnyPfannschmidt Jul 30, 2026
9413a2e
fix: start Windows workers again, over a threaded stdio stream
RonnyPfannschmidt Jul 30, 2026
a5fee03
feat: hand workers a socket on Windows, and stop hanging when we cannot
RonnyPfannschmidt Jul 30, 2026
39251b9
fix: the last four Windows failures, three of them latent everywhere
RonnyPfannschmidt Jul 31, 2026
e8ff98d
fix: survive a host that cannot hand a socket to a worker (PyPy on Wi…
RonnyPfannschmidt Jul 31, 2026
a45c4d2
fix: probe both halves of the socket share, and a racy rinfo test
RonnyPfannschmidt Jul 31, 2026
5365105
fix: give share() the accepted socket's real family/type/proto
RonnyPfannschmidt Jul 31, 2026
f05f66d
fix: hand adopt_socket the socket, not its fd
RonnyPfannschmidt Jul 31, 2026
3a8f182
docs: call the relaying gateway a coordinator, not a master
RonnyPfannschmidt Jul 31, 2026
2fc4013
feat!: default every spawned worker to the socket transport
RonnyPfannschmidt Jul 31, 2026
f484d14
fix: a killed worker is EOF on every transport, not a reset socket
RonnyPfannschmidt Jul 31, 2026
0809f98
docs: hand off the transport and Windows work
RonnyPfannschmidt Jul 31, 2026
98eb08d
docs: describe execnet as it is now, and run the examples again
RonnyPfannschmidt Jul 31, 2026
17ee4e4
docs: review the public surface for engine neutrality
RonnyPfannschmidt Jul 31, 2026
f63e2ec
docs: stop telling readers not to use execnet
RonnyPfannschmidt Jul 31, 2026
30c77bd
docs: mark the docs handoff item done and point at the surface review
RonnyPfannschmidt Jul 31, 2026
ec3d703
docs: reconcile the handoff docs, and aim the branch at 3.0
RonnyPfannschmidt Jul 31, 2026
7a7936a
fix: closing a host breaks what it served, instead of half-working
RonnyPfannschmidt Jul 31, 2026
9c48594
fix: the host boundary fails loudly, instead of hanging or crashing t…
RonnyPfannschmidt Jul 31, 2026
d18f146
fix: do not leave a worker running when makegateway fails late
RonnyPfannschmidt Jul 31, 2026
9b804ab
fix: a host loop that cannot start, and gevent's real constraint
RonnyPfannschmidt Jul 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"Bash(uv run pytest:*)"
]
}
}
125 changes: 125 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ on:
branches:
- "main"

workflow_dispatch:

# Cancel running jobs for the same workflow and branch.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand All @@ -24,6 +26,29 @@ jobs:
- name: Build and Check Package
uses: hynek/build-and-inspect-python-package@v2.18

# The docs build is `-W`, so a stale reference is an error, and the same
# env runs the doc examples as doctests -- they claim to be tested, and
# for years they silently were not.
docs:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.13"

- name: Install dependencies
run: pip install tox

- name: Build the docs and run the doc examples
run: tox run -e docs

test:

needs: [package]
Expand Down Expand Up @@ -62,5 +87,105 @@ jobs:

- name: Test
shell: bash
# The suite is installed from the sdist, which leaves a dev version
# with no source tree to build a provisioning wheel from -- so every
# test that needs a provisioned worker (ssh, foreign python, via)
# would skip. Hand it the wheel from the same build instead: the
# workers then run exactly the artifact under test.
run: |
export EXECNET_PROVISION_WHEEL="$PWD/$(find dist -name '*.whl' | head -1)"
tox run -e py --installpkg `find dist/*.tar.gz`

# pytest-xdist drives execnet's local parallel testing: popen gateways,
# the main-thread worker profile, crashed-worker replacement, and the
# report/warning serialization. Our own suite runs xdist as a *tool*,
# which does not exercise any of that -- so run xdist's own test suite
# against the execnet built from this branch.
#
# Two targets:
#
# * `release` is a pinned combination known to be green against the last
# *released* execnet, so a failure there means we broke something. It
# blocks. Bump `ref`/`pytest` together, and only after checking the new
# pair is green against released execnet -- otherwise the signal is
# gone. (xdist 3.8.0 needs pytest<9: with pytest 9 two of its tests
# fail against released execnet too.)
# * `default-branch` is early warning for drift on both sides. It is
# allowed to fail, because it can go red for reasons that are xdist's
# to fix. An empty `ref` follows whatever xdist's default branch is
# (`master` today) rather than hardcoding a name that could change.
#
# To reproduce locally:
# git clone https://github.com/pytest-dev/pytest-xdist
# git -C pytest-xdist checkout v3.8.0 # or stay on the default branch
# python -m venv .xdist-venv
# .xdist-venv/bin/pip install ./pytest-xdist[testing] "pytest<9" .
# cd pytest-xdist && ../.xdist-venv/bin/python -m pytest
xdist:

needs: [package]

runs-on: ubuntu-latest

name: xdist (${{ matrix.name }})

continue-on-error: ${{ matrix.experimental }}

strategy:
fail-fast: false
matrix:
include:
- name: release
ref: "v3.8.0"
pytest: "pytest<9"
experimental: false
- name: default-branch
ref: ""
pytest: "pytest"
experimental: true

steps:
- uses: actions/checkout@v7
with:
path: execnet

- uses: actions/checkout@v7
with:
repository: pytest-dev/pytest-xdist
ref: ${{ matrix.ref }}
path: pytest-xdist

- name: Download Package
uses: actions/download-artifact@v8
with:
name: Packages
path: dist

- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.13"

- name: Install pytest-xdist and this execnet
shell: bash
run: |
python -m pip install --upgrade pip
python -m pip install "./pytest-xdist[testing]" "${{ matrix.pytest }}"
# after xdist, so its execnet>=2.1 requirement does not win
python -m pip install --force-reinstall `find dist/*.tar.gz`
python -c "import execnet, xdist; print('execnet', execnet.__version__)"

- name: Run the pytest-xdist test suite
shell: bash
working-directory: pytest-xdist
run: |
deselect=()
# `|| [ -n "$line" ]` so a file without a trailing newline still
# contributes its last entry
while read -r line || [ -n "$line" ]; do
line="${line%%#*}"
line="$(echo "$line" | xargs)"
[ -n "$line" ] && deselect+=(--deselect "$line")
done < ../execnet/.github/xdist-known-failures.txt
printf 'deselecting %d known failure(s)\n' $(( ${#deselect[@]} / 2 ))
python -m pytest -ra "${deselect[@]}"
19 changes: 19 additions & 0 deletions .github/xdist-known-failures.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# pytest-xdist tests that are expected to fail against this execnet, with
# the reason. Everything not listed here must pass -- the whole point of
# the `xdist (release)` CI job is that this list stays short and justified.
#
# Blank lines and `#` comments are ignored; every other line is one pytest
# node id, passed to `pytest --deselect`. The same list is used for both
# the pinned release and the `main` target; a node id that does not exist
# in one of them is silently ignored, so an entry may name a test that
# only one version has.
#
# Do not add an entry to make CI green. Add one only for a test that is
# asserting behaviour execnet deliberately changed, and say so.

# Asserts `sys.argv == ["-c"]`, and its own docstring says it is
# documenting "the behavior due to execnet using `python -c`". execnet no
# longer ships source over the wire: workers are launched as
# `python -m execnet._trio_worker <config>`, so sys.argv legitimately
# differs. Needs an xdist-side update, not an execnet fix.
testing/test_remote.py::test_remote_inner_argv
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ include/
.vagrant.d/
.config/
.local/
.claude/settings.local.json
3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ repos:
- id: mypy
additional_dependencies:
- pytest
- trio
- hypothesis
- types-pywin32
- types-gevent
Loading