mirror of
https://github.com/hanzoai/base.git
synced 2026-10-21 03:41:50 +00:00
Fifth extension runtime alongside native/goja/wazero/v8go. Default build links the stub; real impl behind `-tags pyvm` requires pkg-config python-3.13-embed. Architecture: one process-wide CPython init, per-module pool of PEP 684 OWN_GIL sub-interpreters (default 4 / BASE_PYVM_POOL_SIZE). Each Invoke pins to OS thread, attaches a sub-interpreter, runs __main__.fn(json.loads(payload)), returns json.dumps(result). Free-threading (PEP 703) detected at runtime via Py_GIL_DISABLED. Honest limitations documented in README + capability flags: - HardSandbox=false (C extension segfault kills the host) - SupportsAbort=false (no primitive to abort a running sub-interp from another OS thread without holding its GIL) Direct cgo bridge (~150 lines), no DataDog/go-python3 or cpy3 dependency — both fail to compile against CPython 3.12+ because they reference removed PyFloat_ClearFreeList / PyDict_ClearFreeList. JSON marshaling stays inside Python's stdlib json module so the cgo surface stays narrow. Tests: 7 table tests pass on darwin/arm64 + Python 3.13.13.
49 lines
1.7 KiB
Go
49 lines
1.7 KiB
Go
//go:build !pyvm
|
|
// +build !pyvm
|
|
|
|
// Package pyvm is the CPython (cgo) extension runtime for Base.
|
|
//
|
|
// The real implementation lives behind the `pyvm` build tag because it
|
|
// links libpython at the C level and requires Python 3.12+ development
|
|
// headers (pkg-config python-3.13-embed or python-3.12-embed). Default
|
|
// base builds compile without it — this stub is what gets linked in
|
|
// normally so `NewRuntime()` is always callable, only the engine is
|
|
// opt-in via `go build -tags pyvm`.
|
|
package pyvm
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/hanzoai/base/plugins/extruntime"
|
|
)
|
|
|
|
// NewRuntime returns a CPython-shaped runtime that errors at Load time
|
|
// when the binary was built without the `pyvm` build tag. Name() and
|
|
// Capabilities() still report the pyvm identity so callers can detect
|
|
// the runtime is present-but-unavailable rather than missing entirely.
|
|
func NewRuntime() extruntime.Runtime { return &stubRuntime{} }
|
|
|
|
type stubRuntime struct{}
|
|
|
|
func (*stubRuntime) Name() string { return "pyvm" }
|
|
|
|
func (*stubRuntime) Capabilities() extruntime.Capabilities {
|
|
return extruntime.Capabilities{
|
|
AcceptsLanguages: []string{"py"},
|
|
// HardSandbox=false: cgo CPython shares the host process. A C
|
|
// extension segfault kills the whole Go binary. Use wazero +
|
|
// RustPython if you need a sandboxed Python.
|
|
HardSandbox: false,
|
|
Cgo: true,
|
|
// HONEST: pyvm cannot hard-abort a running invocation. See README.
|
|
SupportsAbort: false,
|
|
}
|
|
}
|
|
|
|
func (*stubRuntime) Load(_ context.Context, _ string) (extruntime.Module, error) {
|
|
return nil, fmt.Errorf("%w: built without -tags pyvm (cgo CPython disabled)", extruntime.ErrUnsupported)
|
|
}
|
|
|
|
func (*stubRuntime) Close() error { return nil }
|