Something went wrong. Try again.
/x/perimental project monorepo
Something went wrong. Try again.
2.9 kB · 132 lines
Go
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133package python
import ( "bytes" "context" _ "embed" "io/fs" "os" "path/filepath"
"github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1")
var ( //go:embed python.wasm Binary []byte
r wazero.Runtime code wazero.CompiledModule)
func init() { ctx := context.Background() r = wazero.NewRuntime(ctx)
wasi_snapshot_preview1.MustInstantiate(ctx, r)
var err error code, err = r.CompileModule(ctx, Binary) if err != nil { panic(err) }}
type Result struct { Stdout string Stderr string PlatformError string}
// mainPyPath is the path where main.py is placed in the filesystem.const mainPyPath = "/.within.website.main.py"
func Run(ctx context.Context, fsys fs.FS, userCode string) (*Result, error) { fout := &bytes.Buffer{} ferr := &bytes.Buffer{} fin := &bytes.Buffer{}
// If fsys is nil, use an empty filesystem. if fsys == nil { fsys = emptyFS{} }
// Create a temporary directory and write main.py there. tmpDir, err := os.MkdirTemp("", "python-wasm-*") if err != nil { return nil, err } defer os.RemoveAll(tmpDir)
// Write main.py at the special path. // The path is /.within.website.main.py (no directory separator). if err := os.WriteFile(filepath.Join(tmpDir, ".within.website.main.py"), []byte(userCode), 0644); err != nil { return nil, err }
// Mount the temporary directory at root. fsConfig := wazero.NewFSConfig(). WithDirMount(tmpDir, "/")
config := wazero.NewModuleConfig(). // stdio WithStdout(fout). WithStderr(ferr). WithStdin(fin). // argv WithArgs("python", mainPyPath). WithName("python"). // fs / system WithFSConfig(fsConfig). WithSysNanosleep(). WithSysNanotime(). WithSysWalltime()
mod, err := r.InstantiateModule(ctx, code, config) if err != nil { result := &Result{ Stdout: fout.String(), Stderr: ferr.String(), PlatformError: err.Error(), } return result, err }
defer mod.Close(ctx)
return &Result{ Stdout: fout.String(), Stderr: ferr.String(), }, nil}
// emptyFS is an empty filesystem that returns ENOENT for all paths.type emptyFS struct{}
func (emptyFS) Open(name string) (fs.File, error) { // Return a more specific error for better debugging. return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist}}
// globFS implements fs.GlobFS for better compatibility.func (emptyFS) Glob(pattern string) ([]string, error) { return nil, nil}
// readDirFS implements fs.ReadDirFS for directory listing.func (emptyFS) ReadDir(name string) ([]fs.DirEntry, error) { return nil, &fs.PathError{Op: "readdir", Path: name, Err: fs.ErrNotExist}}
// subFS is a wrapper to make emptyFS implement fs.SubFS.type subFS struct { fs.FS}
func (s subFS) Sub(dir string) (fs.FS, error) { if dir == "." { return s, nil } return nil, &fs.PathError{Op: "sub", Path: dir, Err: fs.ErrNotExist}}