dart_monty_ffi 0.8.3 copy "dart_monty_ffi: ^0.8.3" to clipboard
dart_monty_ffi: ^0.8.3 copied to clipboard

Native FFI backend for dart_monty, pure Dart bindings for Monty — a restricted sandboxed Python interpreter built in Rust.

example/example.dart

// Printing to stdout is expected in an example.
// ignore_for_file: avoid_print

import 'package:dart_monty_ffi/dart_monty_ffi.dart';
import 'package:dart_monty_platform_interface/dart_monty_platform_interface.dart';

/// Demonstrates the native FFI API for running sandboxed Python.
///
/// Most apps should import `dart_monty` instead — the federated plugin
/// selects the correct backend automatically. Use this package directly
/// for CLI tools, server-side Dart, or when you need fine-grained control.
Future<void> main() async {
  final monty = MontyFfi(bindings: NativeBindingsFfi());

  await _simpleRun(monty);
  await _runWithLimits(monty);
  await _externalFunctionDispatch(monty);
  await _errorHandling(monty);
  await _printCapture(monty);
  await _snapshotRestore(monty);

  await monty.dispose();
}

/// Run a simple Python expression and read the result.
Future<void> _simpleRun(MontyFfi monty) async {
  final result = await monty.run('2 + 2');
  print('Simple: ${result.value}'); // 4
}

/// Run with resource limits (timeout, memory, stack depth).
Future<void> _runWithLimits(MontyFfi monty) async {
  final result = await monty.run(
    'sum(range(100))',
    limits: const MontyLimits(
      timeoutMs: 5000,
      memoryBytes: 10 * 1024 * 1024,
      stackDepth: 100,
    ),
  );
  print('With limits: ${result.value}'); // 4950
  print('Memory used: ${result.usage.memoryBytesUsed} bytes');
  print('Time elapsed: ${result.usage.timeElapsedMs} ms');
}

/// Use start/resume to handle external function calls from Python.
Future<void> _externalFunctionDispatch(MontyFfi monty) async {
  // Python calls fetch(), which pauses execution and returns to Dart.
  var progress = await monty.start(
    'fetch("https://api.example.com/data")',
    externalFunctions: ['fetch'],
  );

  // Dispatch loop — handle each external call until execution completes.
  while (progress is MontyPending) {
    print('Python called: ${progress.functionName}(${progress.arguments})');

    // Your app fulfills the call (HTTP, DB, etc.) and feeds the result
    // back to Python. Here we return a mock value.
    progress = await monty.resume({
      'users': ['alice', 'bob'],
    });
  }

  final complete = progress as MontyComplete;
  print('Dispatch result: ${complete.result.value}');
}

/// Catch Python errors with full exception details.
Future<void> _errorHandling(MontyFfi monty) async {
  try {
    await monty.run('1 / 0');
  } on MontyException catch (e) {
    print('Exception type: ${e.excType}'); // ZeroDivisionError
    print('Message: ${e.message}');
  }
}

/// Capture Python print() output.
Future<void> _printCapture(MontyFfi monty) async {
  final result = await monty.run('print("hello from Python")');
  print('Print output: ${result.printOutput}'); // hello from Python
}

/// Save and restore interpreter state via snapshots.
///
/// Snapshots capture state mid-execution (during a start/resume loop).
Future<void> _snapshotRestore(MontyFfi monty) async {
  // Start execution that pauses on an external function call.
  await monty.start(
    'x = 42\nget_value()',
    externalFunctions: ['get_value'],
  );
  // Interpreter is now paused — snapshot the in-progress state.
  final bytes = await monty.snapshot();
  print('Snapshot size: ${bytes.length} bytes');

  // Resume the original to completion.
  await monty.resume(99);

  // Restore the snapshot into a fresh instance — it resumes from the pause.
  final restored = await monty.restore(bytes) as MontyFfi;
  final restoredProgress = await restored.resume(100);
  final complete = restoredProgress as MontyComplete;
  print('Restored result: ${complete.result.value}'); // 100

  await restored.dispose();
}
1
likes
160
points
1.09k
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Native FFI backend for dart_monty, pure Dart bindings for Monty — a restricted sandboxed Python interpreter built in Rust.

Repository (GitHub)
View/report issues
Contributing

Topics

#python #sandbox #ffi #interpreter

License

MIT (license)

Dependencies

code_assets, dart_monty_platform_interface, ffi, hooks

More

Packages that depend on dart_monty_ffi