Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ index.d.ts
# npm pack tarballs
*.tgz

# Python
.venv/
__pycache__/
*.pyc
*.pyo
*.egg-info/
python/**/*.so

# Compiled binaries
guest-examples/hello-c
guest-examples/hello-cpp
Expand Down
164 changes: 164 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ libc = "0.2.178"
napi = { version = "3.5.0", optional = true, features = ["async", "serde-json"] }
napi-derive = { version = "3.3.0", optional = true }

# Python bindings (optional)
pyo3 = { version = "0.20", optional = true, features = ["extension-module", "abi3-py38"] }
pyo3-asyncio = { version = "0.20", optional = true, features = ["tokio-runtime"] }

[features]
default = []
napi = ["dep:napi", "dep:napi-derive", "dep:napi-build"]
python = ["dep:pyo3", "dep:pyo3-asyncio"]

[lib]
crate-type = ["cdylib", "rlib"]
Expand Down
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,29 @@ npm run build
node examples/napi.js
```

### Python


> **Setup (one-time):**
> ```bash
> pipx install maturin # to install, see: https://pipx.pypa.io/stable/
>
> pipx ensurepath # adds ~/.local/bin to PATH
>
> # Restart your terminal or run: export PATH="$HOME/.local/bin:$PATH"
> ```

Run from Python:
```bash
# Create and activate venv
python3 -m venv .venv
source .venv/bin/activate

# Build the Rust extension and install it in venv then run example
maturin develop --features python
python examples/python_sdk_example.py
```

### C & C++ Programs

For compiled languages, you'll need to compile first, then run.
Expand Down Expand Up @@ -120,6 +143,26 @@ if (result.success) {
}
```

### Python

```python
import asyncio
from hyperlight_nanvix import NanvixSandbox, SandboxConfig

async def main():
config = SandboxConfig(
log_directory="/tmp/hyperlight-nanvix",
tmp_directory="/tmp/hyperlight-nanvix"
)
sandbox = NanvixSandbox(config)

result = await sandbox.run('guest-examples/hello.js')
if result.success:
print('Execution completed')

asyncio.run(main())
```

To embed in your own project:

```bash
Expand Down
20 changes: 20 additions & 0 deletions examples/python_sdk_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import asyncio
from hyperlight_nanvix import NanvixSandbox

async def main():
print("Running guest-examples/hello.js...")

try:
sandbox = NanvixSandbox()
result = await sandbox.run("guest-examples/hello.js")

if result.success:
print("Workload completed successfully!")
else:
print(f"Error: {result.error}")
exit(1)
except Exception as error:
print(f"Error: {error}")
exit(1)

asyncio.run(main())
13 changes: 13 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"

[project]
name = "hyperlight-nanvix"
version = "0.1.0"
requires-python = ">=3.8"

[tool.maturin]
features = ["python"]
module-name = "hyperlight_nanvix.hyperlight_nanvix"
python-source = "python"
12 changes: 12 additions & 0 deletions python/hyperlight_nanvix/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""
hyperlight-nanvix: Python bindings for running sandboxed workloads

This module provides a Python interface to the Nanvix microkernel-based
sandbox system, allowing you to run JavaScript, Python, C, and C++
workloads in isolated environments.
"""

from .hyperlight_nanvix import NanvixSandbox, SandboxConfig, WorkloadResult

__version__ = "0.1.0"
__all__ = ["NanvixSandbox", "SandboxConfig", "WorkloadResult"]
17 changes: 17 additions & 0 deletions python/hyperlight_nanvix/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from typing import Optional

class SandboxConfig:
log_directory: Optional[str]
tmp_directory: Optional[str]
def __init__(self, log_directory: Optional[str] = None, tmp_directory: Optional[str] = None) -> None: ...

class WorkloadResult:
success: bool
error: Optional[str]

class NanvixSandbox:
def __init__(self, config: Optional[SandboxConfig] = None) -> None: ...
async def run(self, workload_path: str) -> WorkloadResult: ...
async def clear_cache(self) -> bool: ...

__all__ = ["NanvixSandbox", "SandboxConfig", "WorkloadResult"]
Loading