# Python Features Not Supported in Monty: A Complete Guide to Sandbox Limitations

> Explore Python features unsupported in the pydantic Monty sandbox. Understand security limitations including class definitions, pattern matching, and generators.

- Repository: [Pydantic/monty](https://github.com/pydantic/monty)
- Tags: deep-dive
- Published: 2026-02-16

---

**Monty deliberately omits dangerous or complex Python features—including class definitions, pattern matching, generators, and most standard library modules—to maintain a secure, LLM-controlled sandbox environment.**

Monty is a restricted Python interpreter developed by Pydantic that executes code inside a secure sandbox. Understanding which Python features are not supported in Monty is essential for developers writing code intended for LLM-controlled environments. This guide examines the specific syntax restrictions, runtime limitations, and standard library constraints implemented in the `pydantic/monty` repository.

## Syntax and Parser Limitations

Monty's parser, located in [`crates/monty/src/parse.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/parse.rs), explicitly rejects several Python syntax constructs that are either too complex for the sandbox or not yet implemented.

### Class Definitions and OOP Features

**Class definitions** using the `class` keyword are currently not implemented. According to the source code in [`parse.rs`](https://github.com/pydantic/monty/blob/main/parse.rs) at lines 79-82, attempting to define a class raises a `NotImplementedError`.

```python
code = "class Point: pass"

# Raises: NotImplementedError: class definitions

```

### Pattern Matching Statements

**Structural pattern matching** (`match` / `case` syntax) introduced in Python 3.10 is not supported. The parser at [`parse.rs`](https://github.com/pydantic/monty/blob/main/parse.rs) lines 55-58 rejects these statements.

```python
code = """
match x:
    case 1: pass
"""

# Raises: NotImplementedError: pattern matching (match statements)

```

### Import Statement Restrictions

Monty imposes strict limitations on **import statements** to prevent sandbox escape:

- **Wildcard imports** (`from ... import *`) are explicitly rejected at [`parse.rs`](https://github.com/pydantic/monty/blob/main/parse.rs) lines 52-57
- **Multi-module imports** (`import a, b`) are not supported; only single-module imports are allowed at lines 5-11
- **Relative imports** (`from .module import ...`) are blocked; only absolute imports (level 0) are accepted at lines 30-38

```python

# Wildcard import - NotSupportedError

code = "from math import *"

# Multi-module import - NotImplementedError

code = "import sys, os"

# Relative import - ImportError

code = "from .utils import foo"

```

### Variable Deletion and Type Aliases

The **`del` statement** is not supported, as documented at [`parse.rs`](https://github.com/pydantic/monty/blob/main/parse.rs) lines 87-90. Additionally, **type aliases** using the `type X = ...` syntax (Python 3.12+) are not implemented at lines 91-92.

```python

# del statement - NotImplementedError

code = "del x"

# Type alias - NotImplementedError

code = "type MyInt = int"

```

### Generator Functions and Yield Expressions

**Generators** and `yield` expressions are not supported according to [`parse.rs`](https://github.com/pydantic/monty/blob/main/parse.rs) lines 786-791. This prevents the creation of generator functions and asynchronous generators.

```python
code = """
def gen():
    yield 1
"""

# Raises: NotImplementedError: yield expressions are not supported

```

## Asynchronous Programming Constraints

While Monty includes `asyncio` in its whitelist, many async features are restricted or unimplemented.

### Async Iteration and Context Managers

**Async for loops** are rejected at [`parse.rs`](https://github.com/pydantic/monty/blob/main/parse.rs) lines 13-18, and **async context managers** (`async with`) are not implemented at lines 42-47.

```python

# Async for - NotImplementedError

code = """
async for item in aiter():
    print(item)
"""

# Async with - NotImplementedError

code = """
async with some_cm():
    pass
"""

```

### Awaiting Coroutines in Standard Execution

While async functions can be defined, **awaiting a coroutine in standard execution** is blocked by the VM. According to [`crates/monty/src/run.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/run.rs) at line 927, the VM refuses to run async futures with a `NotImplementedError`.

```python
code = "await asyncio.sleep(1)"

# Raises: NotImplementedError: async futures not supported by standard execution.

```

## Runtime and Operator Limitations

Several Python operators and runtime features are disabled in Monty's VM implementation.

### Context Managers and With Statements

All **context managers** are unsupported. Synchronous `with` statements are rejected at [`parse.rs`](https://github.com/pydantic/monty/blob/main/parse.rs) lines 48-53, preventing resource management via context managers.

```python
code = """
with open('file.txt') as f:
    data = f.read()
"""

# Raises: NotImplementedError: context managers (with statements)

```

### Matrix Multiplication and Complex Numbers

The **matrix multiplication operator `@`** is not implemented in the binary-op VM at [`crates/monty/src/bytecode/vm/binary.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/bytecode/vm/binary.rs) line 253. Additionally, **complex number literals** (`1+2j`) are not supported according to [`parse.rs`](https://github.com/pydantic/monty/blob/main/parse.rs) lines 932-934.

```python

# Matrix multiplication - NotImplementedError

code = "a @ b"

# Complex literals - NotImplementedError

code = "z = 1+2j"

```

### Starred Expressions and Argument Unpacking

**Starred expressions** (`*expr`) outside of function calls are rejected at [`parse.rs`](https://github.com/pydantic/monty/blob/main/parse.rs) lines 968-970. Additionally, **multiple `*args` unpacking** in a single call is not supported at lines 833-840.

```python

# Starred expression - NotImplementedError

code = "*x"

# Multiple *args - NotImplementedError

code = "func(*args1, *args2)"

```

## Standard Library and Built-in Restrictions

Monty's sandbox model requires strict control over available modules and built-in functions.

### Whitelisted Modules and Third-Party Imports

According to the README at lines 39-44, Monty only allows a **tiny whitelist of standard library modules**: `sys`, `typing`, and `asyncio` (with `dataclasses` and `json` planned). **Third-party libraries** like `numpy` or `pydantic` are explicitly blocked to prevent sandbox escape.

```python

# Non-whitelisted stdlib - ImportError

code = "import json"  # If not yet whitelisted

# Raises: ImportError: No module named 'json'

# Third-party - ImportError

code = "import numpy"

# Raises: ImportError

```

### Built-in Function Limitations

The **`print()` function** has restricted functionality. According to [`crates/monty/src/builtins/print.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/builtins/print.rs) lines 22-102, the `file` keyword argument is deliberately disabled to prevent unauthorized file system access.

```python
code = "print('hi', file=sys.stdout)"

# Raises: TypeError: print() 'file' argument is not supported

```

Additionally, **deletion operations** on attributes and subscripts are blocked. The bytecodes `DeleteSubscr` and `DeleteAttr` are omitted from [`crates/monty/src/bytecode/op.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/bytecode/op.rs) lines 234-244, and the `raise ... from ...` syntax is not parsed at lines 335-337.

## Summary

Monty implements a **minimal, secure subset** of Python by explicitly rejecting features that compromise sandbox integrity or require complex runtime machinery. Key unsupported Python features in Monty include:

- **Object-oriented syntax**: Class definitions and complex OOP features are rejected at parse time in [`parse.rs`](https://github.com/pydantic/monty/blob/main/parse.rs)
- **Advanced control flow**: Pattern matching, generators, `del` statements, and `yield` expressions are not implemented
- **Import restrictions**: Wildcard imports, relative imports, multi-module imports, and third-party libraries are blocked
- **Async limitations**: While `asyncio` is whitelisted, `async for`, `async with`, and awaiting coroutines in standard execution fail
- **Context managers**: Both synchronous and asynchronous `with` statements are unsupported
- **Operators and types**: Matrix multiplication (`@`), complex numbers, and starred expressions outside calls are rejected
- **Standard library**: Only `sys`, `typing`, and `asyncio` are available; most built-in functions have restricted arguments

## Frequently Asked Questions

### Why does Monty block class definitions?

Monty rejects class definitions to simplify the sandbox model and reduce the attack surface for LLM-controlled code execution. According to [`crates/monty/src/parse.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/parse.rs) lines 79-82, the parser raises `NotImplementedError` for class syntax, though the developers note this may be implemented in future versions once the security model is hardened.

### Can I use async/await in Monty?

You can define async functions using `async def`, but most async operations are restricted. **Async for loops** and **async context managers** are rejected at parse time ([`parse.rs`](https://github.com/pydantic/monty/blob/main/parse.rs) lines 13-18 and 42-47), and **awaiting coroutines** in standard execution raises `NotImplementedError` according to [`crates/monty/src/run.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/run.rs) line 927. Only basic `asyncio` primitives from the whitelisted module are available.

### Which standard library modules work in Monty?

Monty maintains a strict whitelist of standard library modules to prevent filesystem and network access. According to the README at lines 39-44, only **`sys`**, **`typing`**, and **`asyncio`** are currently available, with **`dataclasses`** and **`json`** planned for future releases. All third-party libraries are explicitly blocked.

### How does Monty handle the `print()` function?

The `print()` function in Monty has restricted functionality to prevent unauthorized output redirection. According to [`crates/monty/src/builtins/print.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/builtins/print.rs) lines 22-102, the `file` keyword argument is deliberately disabled and raises `TypeError` if used. Basic `print()` calls with string arguments work normally within the sandbox.