# Python Types Supported in Monty: A Complete Guide to the Pydantic Sandbox Runtime

> Explore Python types supported in Monty. Discover primitives, containers, callables, and standard library types within Pydantic's sandbox runtime for robust data handling.

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

---

**Monty supports a comprehensive subset of Python's data model including primitives (None, bool, int, float), containers (list, dict, set, tuple), callables (functions, builtins), and standard library types like pathlib.Path, all implemented through the Type and Value enums in the Rust source.**

Monty is a secure Python interpreter from Pydantic that executes untrusted code in a sandboxed environment. Understanding which Python types are supported in Monty is essential for developers building safe code execution pipelines. This guide examines the complete type system implemented in the Monty Rust codebase, mapping every supported Python type to its underlying enum variants and source file locations.

## Primitive and Singleton Types in Monty

Monty implements Python's fundamental singletons and numeric types through dedicated enum variants in [`crates/monty/src/types/type.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs) and [`crates/monty/src/value.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/value.rs).

### None, bool, and Numeric Types

The basic building blocks include:

- **`None`** – Represented as `Type::NoneType` and `Value::None` ([type.rs L32-L33](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L32-L33))
- **`bool`** – `Type::Bool` with `Value::Bool(bool)` storage ([type.rs L33-L34](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L33-L34))
- **`int`** – Supports both small integers via `Value::Int(i64)` and arbitrarily large integers through `Value::InternLongInt(LongIntId)` ([type.rs L34-L35](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L34-L35))
- **`float`** – `Type::Float` with `Value::Float(f64)` for IEEE 754 double-precision storage ([type.rs L35-L36](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L35-L36))

### Ellipsis and Type Objects

Monty also supports Python's special singletons:

- **`Ellipsis`** (`...`) – `Type::Ellipsis` and `Value::Ellipsis` ([type.rs L30-L31](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L30-L31))
- **`type`** objects – `Type::Type` for metaclass operations and `isinstance` checks ([type.rs L31-L32](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L31-L32))

## Container and Collection Types Supported by Monty

Monty implements Python's core data structures with full mutability semantics and iterator support. Each container type resides in its own module (e.g., [`list.rs`](https://github.com/pydantic/monty/blob/main/list.rs), [`dict.rs`](https://github.com/pydantic/monty/blob/main/dict.rs)) and stores data on the heap via `Value::Ref` to keep the enum size small.

### Mutable Sequences and Mappings

- **`list`** – `Type::List` with heap-allocated `HeapData::List` storage ([type.rs L39-L41](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L39-L41))
- **`dict`** – `Type::Dict` with `HeapData::Dict` for key-value mappings ([type.rs L43-L44](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L43-L44))
- **`set`** – `Type::Set` with `HeapData::Set` for unordered unique collections ([type.rs L44-L45](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L44-L45))

### Immutable Collections and Sequences

- **`tuple`** – `Type::Tuple` with `HeapData::Tuple` for immutable sequences ([type.rs L40-L42](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L40-L42))
- **`frozenset`** – `Type::FrozenSet` with `HeapData::FrozenSet` for immutable sets ([type.rs L45-L46](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L45-L46))
- **`range`** – `Type::Range` with `HeapData::Range` for lazy integer sequences ([type.rs L36-L37](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L36-L37))
- **`slice`** – `Type::Slice` with `HeapData::Slice` for indexing operations ([type.rs L38-L39](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L38-L39))

### Text and Binary Data

- **`str`** – `Type::Str` with `HeapData::Str` for Unicode strings ([type.rs L38-L39](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L38-L39))
- **`bytes`** – `Type::Bytes` with `HeapData::Bytes` for immutable byte sequences ([type.rs L39-L40](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L39-L40))

## Callable and Iterator Types in Monty

Monty supports Python's callable objects and asynchronous primitives, enabling function definitions, built-in method calls, and async/await patterns.

### User-Defined Functions and Builtins

- **`function`** (user-defined) – `Type::Function` with `Value::DefFunction(FunctionId)` referencing the function definition table ([type.rs L48-L50](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L48-L50))
- **`builtin_function_or_method`** – `Type::BuiltinFunction` with `Value::Builtin(Builtins)` for sandbox-safe built-in operations like `len()` or `print()` ([type.rs L49-L51](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L49-L51))

### Iterators, Coroutines, and Modules

- **`iterator`** – `Type::Iterator` with `HeapData::Iter` for objects returned by `iter()` ([type.rs L52-L53](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L52-L53))
- **`coroutine`** / **`external_future`** – `Type::Coroutine` with `Value::ExternalFuture(CallId)` for async/await patterns and external async calls ([type.rs L54-L56](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L54-L56))
- **`module`** – `Type::Module` with `Value::Ref` → `HeapData::Module` for imported namespace objects ([type.rs L55-L56](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L55-L56))

## Standard Library Types in the Monty Sandbox

Beyond core built-ins, Monty includes carefully selected standard library types that maintain sandbox safety while providing essential functionality.

### pathlib.Path and Dataclasses

- **`pathlib.Path`** (POSIX) – `Type::Path` with `HeapData::Path` for filesystem path manipulation without unsafe operations ([type.rs L63-L65](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L63-L65))
- **`dataclass`** – `Type::Dataclass` with `HeapData::Dataclass` for the runtime representation of data classes ([type.rs L46-L47](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L46-L47))

### Descriptors, Typing, and I/O

- **`property`** descriptor – `Type::Property` with `Value::Property(Property)` for managed attributes ([type.rs L66-L68](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L66-L68))
- **`typing._SpecialForm`** (e.g., `Any`, `Union`) – `Type::SpecialForm` for generic type hints ([type.rs L60-L62](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L60-L62))
- **`io.TextIOWrapper`** (stdout/stderr) – `Type::TextIOWrapper` with `Value::Marker(Marker)` for stream handling ([type.rs L57-L59](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L57-L59))

### Exception Types

- **Exception classes** (e.g., `ValueError`) – `Type::Exception(ExcType)` for the exception hierarchy, though notably disabled from `EnumString` parsing since exceptions cannot be constructed from plain string tokens ([type.rs L47-L48](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs#L47-L48))

## How Monty Implements Python Type Checking

Monty's type system relies on a dual-enum architecture that separates static type metadata from runtime object representation.

### The Type Enum vs Value Enum Architecture

The **Type** enum in [`crates/monty/src/types/type.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs) defines the static type system used for `isinstance` checks, `type()` calls, and constructor dispatch. The **Value** enum in [`crates/monty/src/value.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/value.rs) represents every Python object that can exist at runtime, with small values stored inline and larger containers allocated on the heap via `Value::Ref`.

This separation allows Monty to perform fast type comparisons using the `Type` enum while maintaining rich runtime semantics through `Value` variants like `Value::Int(i64)` for small integers or `Value::Ref` pointing to `HeapData::List` for mutable sequences.

### Constructor Dispatch and isinstance Checks

When the parser encounters a literal such as `'hello'`, `123`, or `[1, 2]`, it creates the appropriate `Value` variant directly. For constructor calls like `list(x)`, `int('42')`, or `str(b)`, the `Type::call` method (defined in [`type.rs`](https://github.com/pydantic/monty/blob/main/type.rs) lines 72-78) dispatches to the concrete type's `init` implementation—such as `List::init`, `Str::init`, or the `Int` conversion logic.

The `isinstance` builtin compares the object's runtime type tag against the `Type` enum variant, ensuring CPython-compatible behavior while maintaining sandbox safety.

## Working with Monty Types: Code Examples

The following examples demonstrate that Monty's supported types behave identically to CPython, whether accessed through the Python bindings (`pydantic_monty`) or the Rust API.

### Using Monty from Python

```python
from pydantic_monty import Monty

code = """

# primitives

a = None
b = True
c = 42
d = 3.14
e = ...

# containers

lst = [1, 2, 3]
tpl = (4, 5)
dct = {'x': 1, 'y': 2}
st = {1, 2, 3}
frz = frozenset([4, 5])
rng = range(0, 10, 2)
slc = slice(1, 5, 2)
bts = b'abc'
txt = "hello"

# callable / iterator

it = iter(lst)
next(it)

# special objects

import pathlib
p = pathlib.Path('.')
p / 'subdir' / 'file.txt'

# show types

print(type(a), type(b), type(c), type(d), type(e))
print(type(lst), type(tpl), type(dct), type(st), type(frz), type(rng), type(slc))
print(type(bts), type(txt))
print(type(it), type(p))
"""

m = Monty(code)
result = m.run()
print(result)

```

**Expected output** (matching CPython):

```text
<class 'NoneType'> <class 'bool'> <class 'int'> <class 'float'> <class 'ellipsis'>
<class 'list'> <class 'tuple'> <class 'dict'> <class 'set'> <class 'frozenset'> <class 'range'> <class 'slice'>
<class 'bytes'> <class 'str'>
<class 'range_iterator'> <class 'PosixPath'>

```

### Creating a Monty Sandbox from Rust

For Rust developers embedding the interpreter directly:

```rust
use pydantic_monty::Monty;

let src = r#"
x = [1, 2, 3]
print(type(x))   # -> <class 'list'>

"#;

let mut interpreter = Monty::new(src);
interpreter.run().unwrap();

```

The output matches CPython because the `Type` enum implements `fmt::Display` to return the exact Python type names (see `impl fmt::Display for Type` in [`type.rs`](https://github.com/pydantic/monty/blob/main/type.rs)).

## Summary

- Monty supports **primitive types** including `None`, `bool`, `int`, `float`, and `Ellipsis`, with `int` handling both small values and arbitrarily large integers through separate variants.
- **Container types** cover the full Python collection hierarchy: mutable (`list`, `dict`, `set`), immutable (`tuple`, `frozenset`, `range`), and sequence helpers (`slice`, `str`, `bytes`), all heap-allocated via `Value::Ref`.
- **Callable types** include user-defined functions (`Type::Function`), built-in methods (`Type::BuiltinFunction`), iterators, coroutines, and modules, enabling complete Python program execution.
- **Standard library extensions** such as `pathlib.Path`, `dataclass`, `property` descriptors, and exception types extend the sandbox with safe I/O and data structure capabilities.
- The dual-enum architecture separates static type checking (`Type` in [`type.rs`](https://github.com/pydantic/monty/blob/main/type.rs)) from runtime object representation (`Value` in [`value.rs`](https://github.com/pydantic/monty/blob/main/value.rs)), with constructor dispatch handled by `Type::call` methods.

## Frequently Asked Questions

### Does Monty support Python's arbitrary-precision integers?

Yes. Monty handles arbitrarily large integers through the `Value::InternLongInt(LongIntId)` variant for values exceeding `i64` range, while small integers use the inline `Value::Int(i64)` representation. This matches CPython's transparent `int`/`long` unification.

### How does Monty handle mutable versus immutable container types?

Mutable containers like `list`, `dict`, and `set` are stored on the heap via `Value::Ref` pointing to `HeapData` variants (e.g., `HeapData::List`), allowing reference-counted sharing and in-place modification. Immutable types like `tuple` and `frozenset` use the same heap storage but enforce immutability through their method implementations in [`tuple.rs`](https://github.com/pydantic/monty/blob/main/tuple.rs) and [`set.rs`](https://github.com/pydantic/monty/blob/main/set.rs).

### Can Monty execute Python code that uses type hints from the typing module?

Yes. Monty supports `typing._SpecialForm` objects including `Any`, `Union`, and other generic constructs through the `Type::SpecialForm` variant. However, these are currently treated as runtime objects rather than participating in static type checking within the sandbox.

### What file paths contain the core type definitions in Monty?

The master type system lives in [`crates/monty/src/types/type.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/type.rs) (the `Type` enum for `isinstance` and constructors) and [`crates/monty/src/value.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/value.rs) (the `Value` enum for runtime object representation). Container implementations are modularized in [`crates/monty/src/types/list.rs`](https://github.com/pydantic/monty/blob/main/crates/monty/src/types/list.rs), [`dict.rs`](https://github.com/pydantic/monty/blob/main/dict.rs), [`set.rs`](https://github.com/pydantic/monty/blob/main/set.rs), and [`str.rs`](https://github.com/pydantic/monty/blob/main/str.rs).