Skip to main content

dart_monty_core 0.120.1 copy "dart_monty_core: ^0.120.1" to clipboard
dart_monty_core: ^0.120.1 copied to clipboard

Sandboxed Python scripting for Dart. Low-level binding for pydantic/monty's interpreter.

example/example.dart

// Examples print what they show.
// ignore_for_file: avoid_print
//
// dart_monty_core — featured example
//
// Covers the five main usage patterns:
//
//  1. Pool and session — Monty.withPool, Monty.withSession, feedRun
//  2. Inputs           — feed one result into the next as a Python variable
//  3. Externals        — Dart functions Python calls, sync and async
//  4. State            — globals, functions and imports persist in a session
//  5. VFS              — sandboxed in-memory filesystem via Python pathlib
//
// Run: dart run example/example.dart

import 'package:dart_monty_core/dart_monty_core.dart';

Future<void> main(List<String> args) async {
  // In an AOT executable (`dart build cli`) the worker can be this very
  // program, relaunched; this call serves as that worker when it is one.
  // Under `dart run` it returns at once.
  runMontyWorkerIfChild(args);

  // A pool of worker processes. Each session holds one worker for itself.
  await Monty.withPool((monty) async {
    await monty.withSession((session) async {
      // ── 1. Run code ───────────────────────────────────────────────────────
      final pow = await session.feedRun('2 ** 10');
      print('2**10 = ${pow.dartValue}');
      _check(pow == const MontyInt(1024), '2 ** 10');

      // ── 2. Inputs: chain programs ─────────────────────────────────────────
      // A value from one run becomes a Python variable in the next.
      final squares = await session.feedRun('[x**2 for x in range(10)]');
      final total = await session.feedRun(
        'sum(squares)',
        inputs: {'squares': squares},
      );
      print('sum of squares 0-9 = ${total.dartValue}');
      _check(total == const MontyInt(285), 'sum(squares)');

      // ── 3. Externals ──────────────────────────────────────────────────────
      // A call to a name in `externalLookup` runs the Dart function. A returned
      // Future is awaited, and its value is the call's result.
      final shout = await session.feedRun(
        'shout(msg)',
        inputs: {'msg': const MontyString('hello')},
        externalLookup: {
          'shout': MontyHostFunction(
            'shout',
            (values, _) => MontyString(
              ((values.firstOrNull as MontyString?) ??
                      (throw StateError('Missing shout argument')))
                  .value
                  .toUpperCase(),
            ),
          ),
        },
      );
      print(shout.dartValue);
      _check(shout == const MontyString('HELLO'), 'shout');

      final fetched = await session.feedRun(
        'fetch(1) + fetch(2)',
        externalLookup: {
          'fetch': MontyHostFunction('fetch', (values, _) async {
            await Future<void>.delayed(const Duration(milliseconds: 1));

            return MontyInt(
              ((values.firstOrNull as MontyInt?) ??
                          (throw StateError('Missing fetch argument')))
                      .value *
                  10,
            );
          }),
        },
      );
      print('fetch(1) + fetch(2) = ${fetched.dartValue}');
      _check(fetched == const MontyInt(30), 'fetch');

      // ── 4. State persists across feeds ────────────────────────────────────
      await session.feedRun(
        'def fib(n): return n if n < 2 else fib(n-1) + fib(n-2)',
      );
      await session.feedRun('result = fib(10)');
      final fib = await session.feedRun('result');
      print('fib(10) = ${fib.dartValue}');
      _check(fib == const MontyInt(55), 'fib(10)');

      // ── 5. VFS: sandboxed in-memory filesystem ────────────────────────────
      // Writes update the very objects passed in, so Dart reads the result
      // with no serialisation.
      final input = MemoryFile('/data/input.txt', 'hello from Dart');
      final output = MemoryFile('/data/output.txt', '');
      final handler = OSAccess(files: [input, output]);
      await session.feedRun('''
from pathlib import Path
text = Path("/data/input.txt").read_text()
Path("/data/output.txt").write_text(text.upper())
''', os: handler);
      print(output.content);
      _check(output.content == 'HELLO FROM DART', 'VFS write');
    });
  });
}

void _check(bool ok, String what) {
  if (!ok) throw StateError('unexpected result: $what');
}
2
likes
140
points
552
downloads

Documentation

API reference

Publisher

verified publisherenfoldsystems.com

Weekly Downloads

Sandboxed Python scripting for Dart. Low-level binding for pydantic/monty's interpreter.

Repository (GitHub)
View/report issues

Topics

#python #sandbox #interpreter #scripting

License

MIT (license)

Dependencies

code_assets, collection, crypto, ffi, fixnum, hooks, meta, path, protobuf

More

Packages that depend on dart_monty_core