169 lines
5.6 KiB
Markdown
169 lines
5.6 KiB
Markdown
|
|
---
|
||
|
|
model: claude-opus-4-7[1m]
|
||
|
|
service: claude
|
||
|
|
timestamp: 2026-04-17T12:44:37Z
|
||
|
|
git_ref: 5cd6df5
|
||
|
|
diff_cmd: git diff 5cd6df5~1..5cd6df5
|
||
|
|
---
|
||
|
|
|
||
|
|
Code generated in this turn was committed verbatim as
|
||
|
|
`5cd6df58` ("Add `'subint'` spawn backend scaffold
|
||
|
|
(#379)"). Per diff-ref mode, per-file code is captured
|
||
|
|
via the pointers below, each followed by a prose
|
||
|
|
summary. Non-code output (sanity-check results,
|
||
|
|
design rationale) is included verbatim.
|
||
|
|
|
||
|
|
## Per-file generated content
|
||
|
|
|
||
|
|
### `tractor/spawn/_subint.py` (new, 100 lines)
|
||
|
|
|
||
|
|
> `git diff 5cd6df5~1..5cd6df5 -- tractor/spawn/_subint.py`
|
||
|
|
|
||
|
|
New scaffolding module for the PEP 734 subinterpreter
|
||
|
|
backend. Contents:
|
||
|
|
- AGPL header + module docstring (describes backend
|
||
|
|
intent, 3.14+ availability gate, and explicit
|
||
|
|
"SCAFFOLDING STUB" status pointing at issue #379).
|
||
|
|
- Top-level `try/except ImportError` wrapping
|
||
|
|
`from concurrent import interpreters as
|
||
|
|
_interpreters` → sets module-global
|
||
|
|
`_has_subints: bool`. This lets the registry stay
|
||
|
|
introspectable on py<3.14 while spawn-time still
|
||
|
|
fails cleanly.
|
||
|
|
- `subint_proc()` coroutine with signature matching
|
||
|
|
`trio_proc`/`mp_proc` exactly (same param names,
|
||
|
|
defaults, and `TaskStatus[Portal]` typing) —
|
||
|
|
intentional so Phase B.2 can drop the impl in
|
||
|
|
without touching `_methods` or changing call-site
|
||
|
|
binding.
|
||
|
|
- Body raises `RuntimeError` on py<3.14 (with
|
||
|
|
`sys.version` printed) or `NotImplementedError`
|
||
|
|
with issue-#379 URL on py≥3.14.
|
||
|
|
|
||
|
|
### `tractor/spawn/_spawn.py` (modified, +15 LOC)
|
||
|
|
|
||
|
|
> `git diff 5cd6df5~1..5cd6df5 -- tractor/spawn/_spawn.py`
|
||
|
|
|
||
|
|
- `import sys` re-added (pruned during Phase A, now
|
||
|
|
needed again for the py-version string in the
|
||
|
|
`'subint'` gate-error).
|
||
|
|
- `SpawnMethodKey = Literal[...]` grows `'subint'` as
|
||
|
|
the 4th member, with inline comment `# py3.14+ via
|
||
|
|
`concurrent.interpreters` (PEP 734)`.
|
||
|
|
- `try_set_start_method()` match-block grows a new
|
||
|
|
`case 'subint':` arm that imports
|
||
|
|
`from ._subint import _has_subints` lazily and
|
||
|
|
raises `RuntimeError` with a multi-line gate msg
|
||
|
|
if unavailable.
|
||
|
|
- Bottom-of-module late-import section grows
|
||
|
|
`from ._subint import subint_proc` alongside the
|
||
|
|
existing `_trio` / `_mp` imports.
|
||
|
|
- `_methods` dict grows `'subint': subint_proc`.
|
||
|
|
|
||
|
|
### `tractor/_testing/pytest.py` (modified, +8 LOC)
|
||
|
|
|
||
|
|
> `git diff 5cd6df5~1..5cd6df5 -- tractor/_testing/pytest.py`
|
||
|
|
|
||
|
|
`pytest_configure()` wraps the
|
||
|
|
`try_set_start_method(backend)` call in a
|
||
|
|
`try/except RuntimeError` that re-raises as
|
||
|
|
`pytest.UsageError(str(err))`. Rationale: the gate
|
||
|
|
error on py<3.14 is legitimately a configuration
|
||
|
|
problem, not a test failure, so pytest's UsageError
|
||
|
|
path (exit code 4) gives a clean single-line banner
|
||
|
|
instead of a traceback.
|
||
|
|
|
||
|
|
### `pyproject.toml` (modified, +2 / -1)
|
||
|
|
|
||
|
|
> `git diff 5cd6df5~1..5cd6df5 -- pyproject.toml`
|
||
|
|
|
||
|
|
- `requires-python` pin relaxed `>=3.12, <3.14` →
|
||
|
|
`>=3.12, <3.15` to admit 3.14 as a valid target.
|
||
|
|
- Added `"Programming Language :: Python :: 3.14"`
|
||
|
|
to the trove classifiers.
|
||
|
|
|
||
|
|
## Non-code output (verbatim)
|
||
|
|
|
||
|
|
### Design choices captured in the prior turn
|
||
|
|
|
||
|
|
(Previously confirmed by the user on April 17 in this
|
||
|
|
session — relevant excerpts captured here for
|
||
|
|
provenance since they drove the shape of the impl):
|
||
|
|
|
||
|
|
1. **Python pin**: `<3.15` + feature-gate the subint
|
||
|
|
backend at spawn time — user answered option (a)
|
||
|
|
from the design triage.
|
||
|
|
2. **Deferred `fork()`-via-subint hack** from issue
|
||
|
|
#379's "Our own thoughts" section.
|
||
|
|
3. **Phase B phasing**: user approved the B.1 / B.2 /
|
||
|
|
B.3 / B.4 breakdown — this commit is strictly B.1
|
||
|
|
(scaffolding only, no spawn-flow impl).
|
||
|
|
4. **Option (B) worktree strategy**: new worktree
|
||
|
|
branched from `wkt/spawn_modularize`. *(Amended by
|
||
|
|
user at runtime: user switched the existing
|
||
|
|
`spawn_modularize` worktree to the
|
||
|
|
`subint_spawner_backend` branch instead.)*
|
||
|
|
|
||
|
|
### Sanity-check output (verbatim terminal excerpts)
|
||
|
|
|
||
|
|
Registry / feature-gate verification on py3.13:
|
||
|
|
```
|
||
|
|
SpawnMethodKey values: ('trio', 'mp_spawn',
|
||
|
|
'mp_forkserver', 'subint')
|
||
|
|
_methods keys: ['trio', 'mp_spawn',
|
||
|
|
'mp_forkserver', 'subint']
|
||
|
|
_has_subints: False (py version: (3, 13) )
|
||
|
|
[expected] RuntimeError: The 'subint' spawn backend
|
||
|
|
requires Python 3.14+ (stdlib
|
||
|
|
`concurrent.interpreters`, PEP 734).
|
||
|
|
```
|
||
|
|
|
||
|
|
`try_set_start_method('subint')` gate on py3.13:
|
||
|
|
```
|
||
|
|
[expected] RuntimeError: Spawn method 'subint'
|
||
|
|
requires Python 3.14+ (stdlib
|
||
|
|
`concurrent.interpreters`, PEP 734).
|
||
|
|
```
|
||
|
|
|
||
|
|
Pytest `--spawn-backend=subint` on py3.13 (the new
|
||
|
|
UsageError wrapper kicking in):
|
||
|
|
```
|
||
|
|
ERROR: Spawn method 'subint' requires Python 3.14+
|
||
|
|
(stdlib `concurrent.interpreters`, PEP 734).
|
||
|
|
Current runtime: 3.13.11 (main, Dec 5 2025,
|
||
|
|
16:06:33) [GCC 15.2.0]
|
||
|
|
```
|
||
|
|
|
||
|
|
Collection probe: `404 tests collected in 0.18s`
|
||
|
|
(no import errors from the new module).
|
||
|
|
|
||
|
|
Spawn-relevant test subset (`tests/test_local.py
|
||
|
|
test_rpc.py test_spawning.py test_multi_program.py
|
||
|
|
tests/discovery/`):
|
||
|
|
```
|
||
|
|
69 passed, 1 skipped, 10 warnings in 61.38s
|
||
|
|
```
|
||
|
|
|
||
|
|
Full suite was **not** run on py3.13 for this commit
|
||
|
|
— the scaffolding is no-op on <3.14 and full-suite
|
||
|
|
validation under py3.14 is pending that venv being
|
||
|
|
set up by the user.
|
||
|
|
|
||
|
|
### Commit message
|
||
|
|
|
||
|
|
Also AI-drafted (via `/commit-msg`, with the prose
|
||
|
|
rewrapped through `/home/goodboy/.claude/skills/pr-msg/
|
||
|
|
scripts/rewrap.py --width 67`) — the 33-line message
|
||
|
|
on commit `5cd6df58` itself. Not reproduced here; see
|
||
|
|
`git log -1 5cd6df58`.
|
||
|
|
|
||
|
|
### Known follow-ups flagged to user
|
||
|
|
|
||
|
|
- **`uv.lock` deferred**: pin-bump regenerated cp314
|
||
|
|
wheel entries in `uv.lock`, but the user chose to
|
||
|
|
not stage `uv.lock` for this commit. Warned
|
||
|
|
explicitly.
|
||
|
|
- **Phase B.2 needs py3.14 venv** — running the
|
||
|
|
actual subint impl requires it; user said they'd
|
||
|
|
set it up separately.
|