Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
c96cb04
feat: run popen Message IO on Trio host threads
RonnyPfannschmidt Jul 22, 2026
33f2ca3
feat: schedule worker remote_exec from the Trio nursery
RonnyPfannschmidt Jul 22, 2026
80f25a2
refactor: drop eventlet and gevent execmodels
RonnyPfannschmidt Jul 22, 2026
5ccdc80
feat: bootstrap same-python popen worker via `python -m`
RonnyPfannschmidt Jul 22, 2026
dd29004
feat: provision foreign-python popen workers via uv
RonnyPfannschmidt Jul 22, 2026
d485ce7
test: add local ssh-connect harness + typing cleanups
RonnyPfannschmidt Jul 23, 2026
d9e218a
feat: run ssh gateways on the Trio path
RonnyPfannschmidt Jul 23, 2026
028f3a7
feat: ship the execnet wheel to ssh remotes for dev coordinators
RonnyPfannschmidt Jul 23, 2026
a1de883
feat: add execnet-socketserver console command
RonnyPfannschmidt Jul 23, 2026
6616bac
feat: run direct socket gateways on Trio with subprocess workers
RonnyPfannschmidt Jul 23, 2026
62ef74e
feat: migrate installvia to a GATEWAY_START_SOCKET protocol message
RonnyPfannschmidt Jul 23, 2026
b7376d4
refactor: remove the legacy socket coordinator code
RonnyPfannschmidt Jul 23, 2026
be480e2
feat: run popen via-gateways on Trio via GATEWAY_START_POPEN
RonnyPfannschmidt Jul 23, 2026
22624fd
feat: spawn arbitrary via sub-gateways with GATEWAY_START_SUB
RonnyPfannschmidt Jul 24, 2026
067040f
feat: run vagrant_ssh gateways on the Trio path
RonnyPfannschmidt Jul 24, 2026
7fc6896
refactor!: remove the legacy bootstrap stack and EXECNET_TRIO_HOST hatch
RonnyPfannschmidt Jul 24, 2026
765a311
refactor: unify transports on StapledStream with sans-IO frame decoding
RonnyPfannschmidt Jul 24, 2026
1a45745
refactor: extract the LoopPortal cross-thread primitive
RonnyPfannschmidt Jul 24, 2026
c0e8e3b
feat: add the trio-native AsyncGateway core with low-level RawChannels
RonnyPfannschmidt Jul 24, 2026
0a8d934
feat: layer the serialized AsyncChannel API on RawChannel
RonnyPfannschmidt Jul 24, 2026
927f1fd
feat: run async popen gateways with remote_exec inside the user's tri…
RonnyPfannschmidt Jul 24, 2026
2386ab7
feat: add AsyncGroup owning gateways as nursery child scopes
RonnyPfannschmidt Jul 24, 2026
f37f0c9
feat: make the via tunnel frame-native over raw channel routing
RonnyPfannschmidt Jul 24, 2026
1e79877
feat: rebuild the sync API as a facade over the async gateway engine
RonnyPfannschmidt Jul 24, 2026
aba8fbd
feat: split the public surface into execnet.sync / execnet.trio / exe…
RonnyPfannschmidt Jul 25, 2026
c6f419f
fix: attach the bridge session before it can serve messages
RonnyPfannschmidt Jul 25, 2026
b33074f
chore: add pytest-xdist to the dev group
RonnyPfannschmidt Jul 25, 2026
ffd167c
fix: drain asyncssh redirect cleanup in the local ssh harness
RonnyPfannschmidt Jul 25, 2026
fe67288
feat: introduce the boundary kit (Wakener/Mailbox/OneShot) in execnet…
RonnyPfannschmidt Jul 26, 2026
3a205b5
feat!: rebase the sync Channel onto the async core (single dispatch)
RonnyPfannschmidt Jul 26, 2026
75f636d
feat!: retire the ExecModel machinery; add the wait= spec axis
RonnyPfannschmidt Jul 26, 2026
5705de3
feat: add execnet.aio -- the asyncio-native API over the Trio host
RonnyPfannschmidt Jul 26, 2026
f8a36ce
feat: gevent wait backend (wait=gevent) with opt-in tests
RonnyPfannschmidt Jul 26, 2026
89fc420
refactor: extract worker exec placement strategies behind the FIFO pump
RonnyPfannschmidt Jul 26, 2026
953f79f
feat!: answer info natively and apply chdir/nice/env from worker config
RonnyPfannschmidt Jul 26, 2026
166bbf8
feat: pure-async worker profile (execmodel=trio)
RonnyPfannschmidt Jul 26, 2026
413b98a
feat!: restore classic hybrid exec for execmodel=thread
RonnyPfannschmidt Jul 26, 2026
44792db
feat: gevent worker profile and gevent-safe management ops
RonnyPfannschmidt Jul 26, 2026
ae9ba46
feat!: run channel callbacks in an off-loop consumer task
RonnyPfannschmidt Jul 28, 2026
4c87020
fix: serialize ints below the signed int4 minimum via the long opcode
RonnyPfannschmidt Jul 28, 2026
222bc50
test: hypothesis stress tests for channel callbacks with a --stress knob
RonnyPfannschmidt Jul 28, 2026
355917f
refactor: name the main_thread_only deadlock-admission timeout
RonnyPfannschmidt Jul 28, 2026
f5762ae
feat!: hide the standalone serializer from the public API
RonnyPfannschmidt Jul 28, 2026
5df4961
test: type-check the callback stress tests under mypy
RonnyPfannschmidt Jul 28, 2026
b282705
refactor!: drop the injected remote shell script
RonnyPfannschmidt Jul 28, 2026
638b70b
refactor!: drop the quitserver script
RonnyPfannschmidt Jul 28, 2026
86d9906
refactor!: drop the socketserver restart loop script
RonnyPfannschmidt Jul 28, 2026
9105cfd
refactor!: drop the pywin32 windows service wrapper
RonnyPfannschmidt Jul 28, 2026
719a429
refactor: move the socket server to execnet._socketserver
RonnyPfannschmidt Jul 28, 2026
9cb342f
refactor!: drop the py2/py3 string coercion machinery
RonnyPfannschmidt Jul 28, 2026
aa4a75e
refactor!: make the accidentally-public modules private
RonnyPfannschmidt Jul 28, 2026
bdf980d
refactor!: retire the wakener extension point, add execnet.gevent
RonnyPfannschmidt Jul 28, 2026
dc3373b
feat!: rename execmodel= to profile=, deprecate main_thread_only
RonnyPfannschmidt Jul 29, 2026
6efa720
feat!: share one Trio host, guard loop misuse, fix aio cancellation
RonnyPfannschmidt Jul 29, 2026
18c5af2
docs: record the surface review in the changelog
RonnyPfannschmidt Jul 29, 2026
9932f96
ci: run the pytest-xdist test suite against this execnet
RonnyPfannschmidt Jul 30, 2026
83531e3
feat!: add the execnet CLI and stop swallowing worker stdout
RonnyPfannschmidt Jul 30, 2026
4bda47b
feat!: dial back over ssh -R, run popen on a socketpair
RonnyPfannschmidt Jul 30, 2026
4af6ff5
refactor: one typed endmarker sentinel, collapsing make_receive_queue
RonnyPfannschmidt Jul 30, 2026
a975e54
fix(ci): install the declared test deps, so the suite actually runs
RonnyPfannschmidt Jul 30, 2026
5b292aa
feat(provision): EXECNET_PROVISION_WHEEL to name the wheel remotes get
RonnyPfannschmidt Jul 30, 2026
8f631b3
fix: start Windows workers again, over a threaded stdio stream
RonnyPfannschmidt Jul 30, 2026
3d3bd66
feat: hand workers a socket on Windows, and stop hanging when we cannot
RonnyPfannschmidt Jul 30, 2026
e714ba3
fix: the last four Windows failures, three of them latent everywhere
RonnyPfannschmidt Jul 31, 2026
95ffc46
docs: call the relaying gateway a coordinator, not a master
RonnyPfannschmidt Jul 31, 2026
eec889a
feat!: default every spawned worker to the socket transport
RonnyPfannschmidt Jul 31, 2026
a8339d7
fix: a killed worker is EOF on every transport, not a reset socket
RonnyPfannschmidt Jul 31, 2026
a55bb98
docs: describe execnet as it is now, and run the examples again
RonnyPfannschmidt Jul 31, 2026
c7c19d3
docs: stop telling readers not to use execnet
RonnyPfannschmidt Jul 31, 2026
a9d986c
docs: aim the branch at 3.0
RonnyPfannschmidt Jul 31, 2026
12acd1c
fix: closing a host breaks what it served, instead of half-working
RonnyPfannschmidt Jul 31, 2026
0f3a16e
fix: the host boundary fails loudly, instead of hanging or crashing t…
RonnyPfannschmidt Jul 31, 2026
cdcd2e6
fix: do not leave a worker running when makegateway fails late
RonnyPfannschmidt Jul 31, 2026
652c5fe
fix: a host loop that cannot start, and gevent's real constraint
RonnyPfannschmidt Jul 31, 2026
bb270d4
fix: a version-skewed worker refuses, instead of warning and carrying on
RonnyPfannschmidt Aug 1, 2026
c855075
docs: the README, execnet info and the xdist deselect say what 3.0 does
RonnyPfannschmidt Aug 1, 2026
fa13815
fix: a worker refuses execs it cannot place, and contains the ones it…
RonnyPfannschmidt Aug 1, 2026
cf7af3a
fix: a socket gateway is configured by its spec, like every other one
RonnyPfannschmidt Aug 1, 2026
a502226
refactor: drop safe_terminate, keep its bound; monotonic gateway ids
RonnyPfannschmidt Aug 1, 2026
7952400
fix: a test that only held locally, and a cap gevent should never hav…
RonnyPfannschmidt Aug 1, 2026
0d223dc
fix: free exec slots at the close, and make a pre-handshake death exp…
RonnyPfannschmidt Aug 1, 2026
ad4fbe5
fix: close the socketpairs the CLI tests open
RonnyPfannschmidt Aug 1, 2026
1302cea
ci: allow prereleases for 3.15 only, not for the whole matrix
RonnyPfannschmidt Sep 25, 2026
2f76549
fix: resolving what to launch no longer stalls the loop it launches on
RonnyPfannschmidt Aug 1, 2026
da8c590
fix: a monkey-patched process is refused a host loop, not left to fai…
RonnyPfannschmidt Aug 1, 2026
fcd8b69
feat!: configure every worker with a frame, so no argv ever carries one
RonnyPfannschmidt Aug 1, 2026
62025e4
fix: a remotely closed channel leaves the gateway's registry
RonnyPfannschmidt Aug 1, 2026
24a64da
feat: let an application choose when its loop thread comes up
RonnyPfannschmidt Aug 1, 2026
caa74c5
feat: rsync is a service the worker runs, not source shipped into it
RonnyPfannschmidt Aug 1, 2026
862b691
feat: deploy a project to a host, then start workers against it
RonnyPfannschmidt Aug 1, 2026
8bc0a40
refactor!: transfer and deployment become a layer, not part of the core
RonnyPfannschmidt Aug 2, 2026
185d6b9
refactor!: the deprecated RSync becomes an adapter, and the old path …
RonnyPfannschmidt Aug 2, 2026
61a0db0
fix: services stop eating the thread budget exec placement rations
RonnyPfannschmidt Aug 2, 2026
459afde
docs: the gateway a deployment runs through is the via host, not a bo…
RonnyPfannschmidt Aug 2, 2026
fb4887f
refactor!: the local loop thread is a ProtocolEngine, not a Host
RonnyPfannschmidt Aug 2, 2026
ad46e2a
refactor: the engine loop gets a module, and one door to its nursery
RonnyPfannschmidt Aug 2, 2026
103da71
feat!: closing an engine terminates what it served, and says so
RonnyPfannschmidt Aug 2, 2026
dda9feb
refactor: the asyncio bridge becomes the bridge
RonnyPfannschmidt Aug 2, 2026
5e7bf50
feat!: execnet.trio becomes a facade; the native surface is raw_trio
RonnyPfannschmidt Aug 2, 2026
b968e46
test: pin every namespace's public surface, and split loop-loss from …
RonnyPfannschmidt Aug 2, 2026
9ffd3e9
test: deploy from every surface, and fan out to more than one target
RonnyPfannschmidt Aug 2, 2026
17b50a7
docs: the engine, and which trio surface to pick
RonnyPfannschmidt Aug 2, 2026
15c905e
fix: a cancelled receive no longer eats an item
RonnyPfannschmidt Aug 2, 2026
cc72e12
feat: the engine seam takes an asyncio loop as well as a trio one
RonnyPfannschmidt Aug 2, 2026
deac9d0
docs: salvage, and the backend seam
RonnyPfannschmidt Aug 2, 2026
2e7ec0d
feat: the async vocabulary the core will be written against
RonnyPfannschmidt Aug 2, 2026
698fe96
feat: asyncio byte streams and processes for the core to reach IO thr…
RonnyPfannschmidt Aug 2, 2026
457257c
feat: the IO half of the vocabulary, on both backends
RonnyPfannschmidt Aug 2, 2026
6cd9dee
refactor!: the protocol core no longer names an async library
RonnyPfannschmidt Aug 2, 2026
c78e557
refactor!: the routing layer stops naming trio too
RonnyPfannschmidt Aug 2, 2026
8be1c58
feat!: execnet runs on asyncio, coordinator and worker
RonnyPfannschmidt Aug 2, 2026
e4de890
build!: trio becomes an extra where asyncio can run the protocol
RonnyPfannschmidt Aug 2, 2026
3f65f18
feat!: exceptions a caller can act on
RonnyPfannschmidt Aug 2, 2026
1713184
feat!: give the wire format a type, and stop erasing the ones we have
RonnyPfannschmidt Aug 3, 2026
00d02b0
feat!: type the receive side as Payload too
RonnyPfannschmidt Aug 5, 2026
4b6b127
fix: a byte stream may hand back a bytearray
RonnyPfannschmidt Sep 25, 2026
bd515ad
docs: changelog the Payload typing and the empty receive queue
RonnyPfannschmidt Sep 25, 2026
171032c
docs: let sphinx -W pass the private Payload aliases
RonnyPfannschmidt Sep 25, 2026
bf24d14
fix: every surface raises the error that says what happened
RonnyPfannschmidt Sep 25, 2026
0bc4f4d
docs: changelog what the branch does since the engine seam
RonnyPfannschmidt Sep 25, 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
133 changes: 132 additions & 1 deletion .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 @@ -51,7 +76,13 @@ jobs:
uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python }}
allow-prereleases: true
# Only for the version that has no release yet: setup-python
# otherwise resolves released versions only, and a 3.15 job dies at
# setup ("version '3.15' with architecture 'x64' was not found").
# Scoped to 3.15 rather than switched on for the matrix, so the
# released versions keep testing what users actually install --
# move it to the next version when 3.15 ships.
allow-prereleases: ${{ matrix.python == '3.15' }}

- name: Install dependencies
run: pip install tox twine
Expand All @@ -63,5 +94,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 through the CLI
# (`python -m execnet worker --protocol-... --config ...`), so sys.argv
# legitimately differs. Needs an xdist-side update, not an execnet fix.
testing/test_remote.py::test_remote_inner_argv
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
Loading