Python bindings for the Monty sandboxed Python interpreter
Project Links
Meta
Requires Python: >=3.10
Classifiers
Development Status
- 3 - Alpha
Programming Language
- Python :: Implementation
Intended Audience
- Developers
- Information Technology
- System Administrators
License
- OSI Approved :: MIT License
Operating System
- Unix
- POSIX :: Linux
Environment
- MacOS X
Topic
- Software Development :: Libraries :: Python Modules
- Internet
pydantic-monty
Python bindings for the Monty sandboxed Python interpreter.
Installation
pip install pydantic-monty
Usage
Basic Expression Evaluation
import pydantic_monty
# Simple code with no inputs
m = pydantic_monty.Monty('1 + 2')
print(m.run())
#> 3
Using Input Variables
import pydantic_monty
# Create with code that uses input variables
m = pydantic_monty.Monty('x * y', inputs=['x', 'y'])
# Run multiple times with different inputs
print(m.run(inputs={'x': 2, 'y': 3}))
#> 6
print(m.run(inputs={'x': 10, 'y': 5}))
#> 50
Resource Limits
import pydantic_monty
m = pydantic_monty.Monty('x + y', inputs=['x', 'y'])
# With resource limits
limits = pydantic_monty.ResourceLimits(max_duration_secs=1.0)
result = m.run(inputs={'x': 1, 'y': 2}, limits=limits)
assert result == 3
External Functions
import pydantic_monty
# Code that calls an external function
m = pydantic_monty.Monty('double(x)', inputs=['x'])
# Provide the external function implementation at runtime
result = m.run(inputs={'x': 5}, external_functions={'double': lambda x: x * 2})
print(result)
#> 10
Iterative Execution with External Functions
Use start() and resume() to handle external function calls iteratively,
giving you control over each call:
import pydantic_monty
code = """
data = fetch(url)
len(data)
"""
m = pydantic_monty.Monty(code, inputs=['url'])
# Start execution - pauses when fetch() is called
result = m.start(inputs={'url': 'https://example.com'})
print(type(result))
#> <class 'pydantic_monty.FunctionSnapshot'>
print(result.function_name) # fetch
#> fetch
print(result.args)
#> ('https://example.com',)
# Perform the actual fetch, then resume with the result
result = result.resume(return_value='hello world')
print(type(result))
#> <class 'pydantic_monty.MontyComplete'>
print(result.output)
#> 11
Serialization
Both Monty and FunctionSnapshot can be serialized to bytes and restored later.
This allows caching parsed code or suspending execution across process boundaries:
import pydantic_monty
# Serialize parsed code to avoid re-parsing
m = pydantic_monty.Monty('x + 1', inputs=['x'])
data = m.dump()
# Later, restore and run
m2 = pydantic_monty.Monty.load(data)
print(m2.run(inputs={'x': 41}))
#> 42
Execution state can also be serialized mid-flight:
import pydantic_monty
m = pydantic_monty.Monty('fetch(url)', inputs=['url'])
progress = m.start(inputs={'url': 'https://example.com'})
# Serialize the execution state
state = progress.dump()
# Later, restore and resume (e.g., in a different process)
progress2 = pydantic_monty.load_snapshot(state)
result = progress2.resume(return_value='response data')
print(result.output)
#> response data
0.0.9
Mar 28, 2026
0.0.8
Mar 10, 2026
0.0.7
Feb 19, 2026
0.0.6
Feb 16, 2026
0.0.5
Feb 16, 2026
0.0.4
Feb 07, 2026
0.0.3
Feb 04, 2026
0.0.2
Feb 04, 2026
0.0.1
Jan 27, 2026
0
Jan 26, 2026
Wheel compatibility matrix
Files in release
pydantic_monty-0.0.9-cp310-cp310-macosx_10_12_x86_64.whl (6.6MiB)
pydantic_monty-0.0.9-cp310-cp310-macosx_11_0_arm64.whl (6.7MiB)
pydantic_monty-0.0.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (6.4MiB)
pydantic_monty-0.0.9-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (6.7MiB)
pydantic_monty-0.0.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (7.2MiB)
pydantic_monty-0.0.9-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl (7.4MiB)
pydantic_monty-0.0.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.2MiB)
pydantic_monty-0.0.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl (7.1MiB)
pydantic_monty-0.0.9-cp310-cp310-musllinux_1_1_aarch64.whl (6.6MiB)
pydantic_monty-0.0.9-cp310-cp310-musllinux_1_1_x86_64.whl (7.0MiB)
pydantic_monty-0.0.9-cp310-cp310-win32.whl (6.5MiB)
pydantic_monty-0.0.9-cp310-cp310-win_amd64.whl (7.2MiB)
pydantic_monty-0.0.9-cp311-cp311-macosx_10_12_x86_64.whl (6.6MiB)
pydantic_monty-0.0.9-cp311-cp311-macosx_11_0_arm64.whl (6.7MiB)
pydantic_monty-0.0.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (6.4MiB)
pydantic_monty-0.0.9-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (6.7MiB)
pydantic_monty-0.0.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (7.2MiB)
pydantic_monty-0.0.9-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl (7.4MiB)
pydantic_monty-0.0.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.2MiB)
pydantic_monty-0.0.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl (7.1MiB)
pydantic_monty-0.0.9-cp311-cp311-musllinux_1_1_aarch64.whl (6.6MiB)
pydantic_monty-0.0.9-cp311-cp311-musllinux_1_1_x86_64.whl (7.0MiB)
pydantic_monty-0.0.9-cp311-cp311-win32.whl (6.5MiB)
pydantic_monty-0.0.9-cp311-cp311-win_amd64.whl (7.2MiB)
pydantic_monty-0.0.9-cp312-cp312-macosx_10_12_x86_64.whl (6.6MiB)
pydantic_monty-0.0.9-cp312-cp312-macosx_11_0_arm64.whl (6.6MiB)
pydantic_monty-0.0.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (6.4MiB)
pydantic_monty-0.0.9-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (6.7MiB)
pydantic_monty-0.0.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (7.2MiB)
pydantic_monty-0.0.9-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl (7.4MiB)
pydantic_monty-0.0.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.1MiB)
pydantic_monty-0.0.9-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl (7.1MiB)
pydantic_monty-0.0.9-cp312-cp312-musllinux_1_1_aarch64.whl (6.6MiB)
pydantic_monty-0.0.9-cp312-cp312-musllinux_1_1_x86_64.whl (7.0MiB)
pydantic_monty-0.0.9-cp312-cp312-win32.whl (6.5MiB)
pydantic_monty-0.0.9-cp312-cp312-win_amd64.whl (7.2MiB)
pydantic_monty-0.0.9-cp313-cp313-macosx_10_12_x86_64.whl (6.6MiB)
pydantic_monty-0.0.9-cp313-cp313-macosx_11_0_arm64.whl (6.6MiB)
pydantic_monty-0.0.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (6.4MiB)
pydantic_monty-0.0.9-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (6.7MiB)
pydantic_monty-0.0.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (7.2MiB)
pydantic_monty-0.0.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl (7.4MiB)
pydantic_monty-0.0.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.1MiB)
pydantic_monty-0.0.9-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl (7.1MiB)
pydantic_monty-0.0.9-cp313-cp313-musllinux_1_1_aarch64.whl (6.6MiB)
pydantic_monty-0.0.9-cp313-cp313-musllinux_1_1_x86_64.whl (7.0MiB)
pydantic_monty-0.0.9-cp313-cp313-win32.whl (6.5MiB)
pydantic_monty-0.0.9-cp313-cp313-win_amd64.whl (7.2MiB)
pydantic_monty-0.0.9-cp314-cp314-macosx_10_12_x86_64.whl (6.6MiB)
pydantic_monty-0.0.9-cp314-cp314-macosx_11_0_arm64.whl (6.6MiB)
pydantic_monty-0.0.9-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (6.4MiB)
pydantic_monty-0.0.9-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (6.7MiB)
pydantic_monty-0.0.9-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (7.2MiB)
pydantic_monty-0.0.9-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl (7.4MiB)
pydantic_monty-0.0.9-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.2MiB)
pydantic_monty-0.0.9-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl (7.1MiB)
pydantic_monty-0.0.9-cp314-cp314-musllinux_1_1_aarch64.whl (6.6MiB)
pydantic_monty-0.0.9-cp314-cp314-musllinux_1_1_x86_64.whl (7.0MiB)
pydantic_monty-0.0.9-cp314-cp314-win32.whl (6.5MiB)
pydantic_monty-0.0.9-cp314-cp314-win_amd64.whl (7.2MiB)
pydantic_monty-0.0.9.tar.gz (868.0KiB)
No dependencies