feat(code_runner): rename module, fix __del__ + kernel name, expand tests
- Rename `wrenn.code_interpreter` → `wrenn.code_runner` (canonical).
Keep old path as deprecation alias that emits a FutureWarning on
import, mirroring the existing `Sandbox` → `Capsule` pattern.
Submodule shims `code_interpreter/{capsule,async_capsule,models}.py`
keep direct-submodule imports working.
- Fix sync/async ctor-failure-safe `__del__`: initialise `_kernel_id`,
`_kernel_name`, `_proxy_client` before calling `super().__init__` so
a failed creation no longer crashes the destructor with
AttributeError.
- Send the kernel name to Jupyter. Previously `POST /api/kernels` had
no body, so the server picked an arbitrary default kernelspec. Now
sends `{"name": "wrenn"}` (override via `Capsule(kernel=...)`) and
reuses an existing kernel only when its `name` matches.
- Preserve Jupyter `text/plain` verbatim in `Result.from_bundle`.
The previous outer-quote strip was lossy (the string `'2'` became
indistinguishable from the int `2`, and strings containing escaped
quotes were mangled). `text` is now the `repr()` Jupyter sends.
Updated the stale `test_capsule_features` quote-strip test.
- Validate `run_code(language=...)`. Anything other than `"python"`
now raises `ValueError` instead of being silently ignored.
- Async `__del__` no longer touches the event loop; users must call
`await close()` or use `async with`.
- New unit suite `tests/test_code_runner_unit.py` (46 tests): MIME
unpacking, deprecation alias + warning, default template + kernel,
custom kernel override, ctor-failure-safe __del__, kernel
create/reuse/cache, retry on 5xx, 4xx propagation, request shape,
run_code stream/result/error/foreign-parent/idle/unsupported-language,
async variants.
- New e2e suite `tests/test_code_runner_e2e.py` (44 tests, integration
marker): template == `code-runner-beta`, kernel == `wrenn`, stdout
/stderr capture, state/import/function/class persistence, exceptions
(Value/Name/Syntax), callbacks, multi-line, `text` repr preservation,
filesystem round-trip, isolation between capsules, deprecated import
path. MIME-type class covers html, markdown, json, latex, svg,
javascript, png (matplotlib + seaborn), jpeg, multi-format bundles,
and text-round-trip via numpy + requests.
- `make test-code-runner` runs unit + e2e together. `make test`
extended to include the unit file.
- README: "Code Interpreter" section renamed to "Code Runner", all
imports updated, `kernel=` documented, removed the incorrect
"quotes stripped automatically" claim, replaced with the actual
`text/plain` semantics.
- CLAUDE.md: appended a "Code Runner Module" section covering module
path, defaults, kernel-reuse semantics, lifecycle invariant, and
the new test files + make target.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
36
CLAUDE.md
36
CLAUDE.md
@ -169,3 +169,39 @@ Fall back to Grep/Glob/Read **only** when the graph doesn't cover what you need.
|
||||
2. Use `detect_changes` for code review.
|
||||
3. Use `get_affected_flows` to understand impact.
|
||||
4. Use `query_graph` pattern="tests_for" to check coverage.
|
||||
|
||||
## Code Runner Module
|
||||
|
||||
`wrenn.code_runner` — stateful code execution capsule via persistent
|
||||
Jupyter kernel.
|
||||
|
||||
- **Module path:** `wrenn.code_runner` (canonical). The old path
|
||||
`wrenn.code_interpreter` is a deprecation alias that emits a
|
||||
`FutureWarning` on import; do not introduce new uses.
|
||||
- **Defaults:** template `code-runner-beta`, kernelspec `wrenn`.
|
||||
Both overridable via `Capsule(template=..., kernel=...)`.
|
||||
- **Kernel reuse:** `_ensure_kernel` lists `/api/kernels`, reuses the
|
||||
first kernel whose `name` matches the configured kernelspec, else
|
||||
POSTs `{"name": <kernel>}` to create one. Matching by name (not just
|
||||
"any kernel") is intentional — multiple kernelspecs may coexist on
|
||||
the same Jupyter.
|
||||
- **Lifecycle invariant:** the constructor sets `_kernel_id`,
|
||||
`_kernel_name`, `_proxy_client` to safe defaults *before* calling
|
||||
`super().__init__`. `__del__` must never assume construction
|
||||
completed. Async `__del__` only drops the reference — the proxy
|
||||
`httpx.AsyncClient` must be closed via `await close()` or
|
||||
`async with`.
|
||||
|
||||
### Tests
|
||||
|
||||
- `tests/test_code_runner_unit.py` — pure unit tests (respx + mocked
|
||||
WebSocket). Covers `Result.from_bundle`, MIME unpacking,
|
||||
quote-stripping, `Execution.text`, kernel reuse vs create, retry on
|
||||
5xx, 4xx propagation, ctor-failure-safe `__del__`, deprecation
|
||||
alias.
|
||||
- `tests/test_code_runner_e2e.py` — live integration tests (marked
|
||||
`integration`, skipped without `WRENN_API_KEY`). Covers stateful
|
||||
execution, exceptions, callbacks, rich outputs (HTML, matplotlib,
|
||||
pandas), async variant, isolation between capsules, and the
|
||||
deprecated `code_interpreter` import path.
|
||||
- Run both: `make test-code-runner`.
|
||||
|
||||
Reference in New Issue
Block a user