Dana Sandbox API Reference¶
The Dana Sandbox is the primary public API for executing Dana code safely. It provides a clean, simple interface for running Dana files and evaluating code expressions.
Quick Start¶
# Import the Dana module
import opendxa.dana as dana
# Method 1: Convenience functions (recommended for simple use)
result = dana.run("my_program.na")
result = dana.eval("x = 10\ny = 20\nx + y")
# Method 2: DanaSandbox instance (recommended for advanced use)
sandbox = dana.DanaSandbox(debug=True)
result = sandbox.run("my_program.na")
result = sandbox.eval("x = 10\ny = 20\nx + y")
Classes¶
DanaSandbox¶
The main class for executing Dana code in a secure sandbox environment.
Constructor¶
Parameters:
- debug
(bool): Enable debug logging output
- context
(Optional[SandboxContext]): Custom execution context (creates default if None)
Example:
import opendxa.dana as dana
# Basic sandbox
sandbox = dana.DanaSandbox()
# Debug sandbox with logging
debug_sandbox = dana.DanaSandbox(debug=True)
# Custom context sandbox
from opendxa.dana.sandbox.sandbox_context import SandboxContext
custom_context = SandboxContext()
custom_context.set("public:api_key", "secret-key")
sandbox = dana.DanaSandbox(context=custom_context)
Instance Methods¶
run(file_path)¶
Execute a Dana file from disk.
Parameters:
- file_path
(str | Path): Path to the .na
file to execute
Returns:
- ExecutionResult
: Result object with success status and execution details
Raises:
- FileNotFoundError
: If the file doesn't exist
- ValueError
: If the file doesn't have .na
extension
Example:
import opendxa.dana as dana
sandbox = dana.DanaSandbox()
# Execute a Dana file
result = sandbox.run("examples/basic.na")
if result.success:
print(f"Program output: {result.output}")
print(f"Final result: {result.result}")
else:
print(f"Error: {result.error}")
eval(source_code, filename=None)¶
Evaluate Dana source code directly.
Parameters:
- source_code
(str): Dana code to execute
- filename
(Optional[str]): Optional filename for error reporting
Returns:
- ExecutionResult
: Result object with success status and execution details
Example:
import opendxa.dana as dana
sandbox = dana.DanaSandbox()
# Evaluate Dana code
result = sandbox.eval('''
# Simple calculation
x = 10
y = 20
result = x * y
log(f"Calculation: {x} * {y} = {result}")
result
''')
if result.success:
print(f"Result: {result.result}") # Output: 200
print(f"Log output: {result.output}")
Class Methods¶
quick_run(file_path, debug=False, context=None)¶
Quick file execution without creating a sandbox instance.
@classmethod
quick_run(
cls,
file_path: Union[str, Path],
debug: bool = False,
context: Optional[SandboxContext] = None
) -> ExecutionResult
Parameters:
- file_path
(str | Path): Path to the .na
file to execute
- debug
(bool): Enable debug logging
- context
(Optional[SandboxContext]): Custom execution context
Returns:
- ExecutionResult
: Result object with success status and execution details
Example:
import opendxa.dana as dana
# Quick file execution
result = dana.DanaSandbox.quick_run("my_program.na", debug=True)
print(f"Success: {result.success}, Result: {result.result}")
quick_eval(source_code, filename=None, debug=False, context=None)¶
Quick code evaluation without creating a sandbox instance.
@classmethod
quick_eval(
cls,
source_code: str,
filename: Optional[str] = None,
debug: bool = False,
context: Optional[SandboxContext] = None
) -> ExecutionResult
Parameters:
- source_code
(str): Dana code to execute
- filename
(Optional[str]): Optional filename for error reporting
- debug
(bool): Enable debug logging
- context
(Optional[SandboxContext]): Custom execution context
Returns:
- ExecutionResult
: Result object with success status and execution details
Example:
import opendxa.dana as dana
# Quick code evaluation
result = dana.DanaSandbox.quick_eval("x = 42\nx * 2")
print(f"Result: {result.result}") # Output: 84
ExecutionResult¶
Result object returned by all Dana execution methods.
Attributes¶
@dataclass
class ExecutionResult:
success: bool # Whether execution succeeded
result: Any = None # Final result value
final_context: Optional[SandboxContext] = None # Final execution context
execution_time: float = 0.0 # Execution time in seconds
error: Optional[Exception] = None # Error if execution failed
output: str = "" # Captured output from log() and print()
Methods¶
str()¶
Human-readable execution summary.
Returns:
- str
: Summary of execution result
Example:
import opendxa.dana as dana
result = dana.eval("x = 10\nx + 5")
print(str(result)) # Output: "Success: 15"
result = dana.eval("invalid syntax")
print(str(result)) # Output: "Error: [error details]"
Convenience Functions¶
dana.run(file_path, debug=False, context=None)¶
Convenience function for quick file execution.
Example:
import opendxa.dana as dana
# These are equivalent:
result1 = dana.run("my_program.na")
result2 = dana.DanaSandbox.quick_run("my_program.na")
dana.eval(source_code, filename=None, debug=False, context=None)¶
Convenience function for quick code evaluation.
Example:
import opendxa.dana as dana
# These are equivalent:
result1 = dana.eval("2 + 2")
result2 = dana.DanaSandbox.quick_eval("2 + 2")
Usage Patterns¶
Basic Script Execution¶
import opendxa.dana as dana
# Execute a Dana script
result = dana.run("scripts/data_analysis.na")
if result.success:
print("Analysis complete!")
print(f"Results: {result.result}")
# Access final variable states
user_data = result.final_context.get("public:user_data")
print(f"Processed data: {user_data}")
else:
print(f"Script failed: {result.error}")
Interactive Code Evaluation¶
import opendxa.dana as dana
# Create a persistent sandbox for multiple evaluations
sandbox = dana.DanaSandbox(debug=True)
# Set up initial data
setup_result = sandbox.eval('''
public:data = {"users": ["Alice", "Bob", "Charlie"], "scores": [95, 87, 92]}
private:api_key = "secret-key"
''')
# Perform analysis
analysis_result = sandbox.eval('''
# Analyze user scores
total_users = len(public:data["users"])
avg_score = sum(public:data["scores"]) / total_users
log(f"Analyzed {total_users} users")
log(f"Average score: {avg_score}")
analysis = reason(f"Analyze these user scores: {public:data}")
analysis
''')
if analysis_result.success:
print(f"Analysis: {analysis_result.result}")
print(f"Log output:\n{analysis_result.output}")
Error Handling¶
import opendxa.dana as dana
# Handle different types of errors
def safe_execute(code: str) -> None:
result = dana.eval(code)
if result.success:
print(f"✓ Success: {result.result}")
else:
error = result.error
# Handle specific error types
if isinstance(error, FileNotFoundError):
print("✗ File not found")
elif isinstance(error, SyntaxError):
print(f"✗ Syntax error: {error}")
elif "NameError" in str(error):
print("✗ Variable not defined")
else:
print(f"✗ Execution failed: {error}")
# Test different scenarios
safe_execute("x = 10\ny = 20\nx + y") # Success
safe_execute("undefined_variable + 5") # NameError
safe_execute("x = 10\nx +") # Syntax error
Working with Context¶
import opendxa.dana as dana
from opendxa.dana.sandbox.sandbox_context import SandboxContext
# Create custom context with pre-loaded data
context = SandboxContext()
context.set("public:config", {"api_url": "https://api.example.com", "timeout": 30})
context.set("private:credentials", {"token": "auth-token"})
# Use context in execution
sandbox = dana.DanaSandbox(context=context)
result = sandbox.eval('''
# Access pre-loaded configuration
api_url = public:config["api_url"]
timeout = public:config["timeout"]
token = private:credentials["token"]
log(f"Connecting to {api_url} with timeout {timeout}s")
# Simulate API call logic
connection_status = "connected"
connection_status
''')
print(f"Connection status: {result.result}")
Batch Processing¶
import opendxa.dana as dana
from pathlib import Path
def process_dana_files(directory: str) -> dict:
"""Process all .na files in a directory."""
results = {}
for file_path in Path(directory).glob("*.na"):
print(f"Processing {file_path.name}...")
result = dana.run(str(file_path))
results[file_path.name] = {
"success": result.success,
"result": result.result,
"error": str(result.error) if result.error else None
}
return results
# Process all Dana files in a directory
batch_results = process_dana_files("scripts/")
# Generate summary
successful = sum(1 for r in batch_results.values() if r["success"])
total = len(batch_results)
print(f"Processed {successful}/{total} files successfully")
Security Considerations¶
Sandbox Isolation¶
The Dana Sandbox provides security isolation for executing untrusted code:
import opendxa.dana as dana
# Dana code runs in a secure sandbox
untrusted_code = '''
# This code cannot access the host system
private:data = "safe data"
result = len(private:data)
result
'''
result = dana.eval(untrusted_code)
# Safe to execute - sandbox prevents system access
Context Security¶
Variables are isolated by scope:
import opendxa.dana as dana
# Sensitive data in private scope
result = dana.eval('''
private:secret = "sensitive-data"
public:safe_data = "public-data"
# private: scope is isolated and secure
# public: scope can be shared between contexts
len(private:secret)
''')
# Access public data safely
public_data = result.final_context.get("public:safe_data")
# Cannot access private:secret from outside the sandbox
Performance Tips¶
Reuse Sandbox Instances¶
import opendxa.dana as dana
# Efficient: Reuse sandbox for multiple operations
sandbox = dana.DanaSandbox()
for i in range(100):
result = sandbox.eval(f"x = {i}\nx * 2")
# Sandbox context is preserved between calls
Minimize Context Creation¶
import opendxa.dana as dana
# Efficient: Share context for related operations
sandbox = dana.DanaSandbox()
# Setup once
sandbox.eval("public:data = [1, 2, 3, 4, 5]")
# Multiple operations on same data
result1 = sandbox.eval("sum(public:data)")
result2 = sandbox.eval("max(public:data)")
result3 = sandbox.eval("len(public:data)")
Integration Examples¶
FastAPI Integration¶
from fastapi import FastAPI, HTTPException
import opendxa.dana as dana
app = FastAPI()
@app.post("/execute")
async def execute_dana_code(code: str):
"""Execute Dana code via REST API."""
result = dana.eval(code)
if result.success:
return {
"success": True,
"result": result.result,
"output": result.output
}
else:
raise HTTPException(
status_code=400,
detail=f"Execution failed: {result.error}"
)
@app.post("/analyze")
async def analyze_data(data: dict):
"""Analyze data using Dana reasoning."""
dana_code = f'''
public:input_data = {data}
analysis = reason("Analyze this data: " + str(public:input_data))
analysis
'''
result = dana.eval(dana_code)
if result.success:
return {"analysis": result.result}
else:
raise HTTPException(
status_code=500,
detail="Analysis failed"
)
Jupyter Notebook Integration¶
# In a Jupyter notebook cell
import opendxa.dana as dana
# Create a persistent sandbox for the notebook session
%%python
notebook_sandbox = dana.DanaSandbox(debug=True)
# Dana code execution in notebook
%%python
result = notebook_sandbox.eval('''
# Data analysis in Dana
public:dataset = [1, 4, 7, 2, 9, 3, 8, 5, 6]
mean_value = sum(public:dataset) / len(public:dataset)
# AI-powered analysis
insight = reason(f"What insights can you provide about this dataset: {public:dataset}?")
log(f"Dataset mean: {mean_value}")
log(f"AI insight: {insight}")
{
"mean": mean_value,
"insight": insight,
"dataset_size": len(public:dataset)
}
''')
print(f"Analysis complete: {result.result}")
print(f"Output:\n{result.output}")
Troubleshooting¶
Common Issues¶
File Not Found Error:
# ❌ Incorrect
result = dana.run("nonexistent.na")
# ✅ Correct
from pathlib import Path
if Path("my_program.na").exists():
result = dana.run("my_program.na")
else:
print("File not found")
Variable Scope Issues:
# ❌ Incorrect - variables lost between evaluations
result1 = dana.eval("x = 10")
result2 = dana.eval("y = x + 5") # Error: x not defined
# ✅ Correct - use persistent sandbox
sandbox = dana.DanaSandbox()
result1 = sandbox.eval("x = 10")
result2 = sandbox.eval("y = x + 5") # Works: x persists in context
Syntax Errors:
# ❌ Incorrect
result = dana.eval("x = 10\ny = x +") # Syntax error
# ✅ Correct - check result
result = dana.eval("x = 10\ny = x + 5")
if not result.success:
print(f"Error: {result.error}")
Debug Mode¶
Enable debug mode for detailed execution information:
import opendxa.dana as dana
# Enable debug logging
sandbox = dana.DanaSandbox(debug=True)
result = sandbox.eval('''
x = 10
log("Processing data...")
y = x * 2
log(f"Result: {y}")
y
''')
# Debug output shows detailed execution flow
Copyright © 2025 Aitomatic, Inc. Licensed under the MIT License.
https://aitomatic.com