Limitations
Monty is not a Python implementation aiming for completeness. It implements enough Python for a model to express what it wants to do, and deliberately stops there. Everything it does implement is meant to behave exactly like CPython 3.14; everywhere it does not, the divergence is written down.
This page gives you the shape of the subset. The other pages in this section are the exhaustive record, one per builtin, module or construct. They list every known divergence, including the ones that feel obvious, so a behaviour missing from them can be assumed to match CPython 3.14. They exist for development and for agents debugging code that runs on Monty; most users need only this page.
Supported:
def,async def, nested functions, closures,lambda- Decorators on functions and classes
- Simple classes: instance methods,
__init__,__repr__/__str__,__eq__/__hash__,__iter__/__next__,__contains__,__index__, class variables @dataclass, with theeq=andfrozen=options only (every other option raisesNotImplementedError, and there is nofield(),fields()orasdict()), plus host class instances passed in and out (and host classes the sandbox may instantiate when granted)- List, dict and set comprehensions
try/except/else/finally,raise ... from ...for,while,if/elif/else,break,continue,pass,assert,global,nonlocal,returnwithstatements, for files and for classes implementing__enter__/__exit__- f-strings, including
=,!r/!s/!aand format specs async/await, andasyncio.run/asyncio.gatherimport x,import x.y,from x import y, z as w- Starred unpacking everywhere CPython allows it
Rejected at parse time, with NotImplementedError before any code runs:
- Class inheritance and metaclasses (
class Foo(Bar):) - Decorators on methods — so no
@classmethod,@staticmethod,@property yield/yield from— there are no generator functions. Generator expressions parse, but currently materialise to alistmatchstatementsdel, bothdel xanddel d[k]try*/except*exception groups- PEP 695
typealiases async with,async forand async comprehensions- Wildcard imports (
from m import *) - Complex literals (
1j) and t-strings
Missing in other ways:
- User-defined exception classes. The built-in exception types are a fixed set, and without inheritance you cannot add to it.
- Function attributes.
fn.__name__,fn.__doc__and friends raiseAttributeError, and new attributes cannot be set — sofunctools.wraps-style metadata copying and registries keyed onfn.__name__have no equivalent. eval,exec,compile,globals,locals,__import__andsuper— all raiseNameError.- Third-party packages.
There is no
sys.pathand no site-packages.
The following modules are present:
| Module | Divergences |
|---|---|
asyncio | asyncio.md |
base64 | base64.md |
binascii | base64.md |
collections | collections.md |
dataclasses | dataclasses.md |
datetime | datetime.md |
functools | functools.md |
itertools | itertools.md |
json | json.md |
math | math.md |
os | os.md |
pathlib | pathlib.md |
re | re.md |
sys | sys.md |
typing | typing.md |
unicodedata | unicodedata.md |
Each covers only part of its CPython surface — often a small part.
The absent names are missing from the module namespace rather than stubbed, so they fail type checking as well as
raising AttributeError at runtime.
Notably absent: enum, contextlib, random, time, io, copy, string, struct, operator,
inspect, logging, traceback, hashlib, uuid, urllib.
Some of those are absent by design — socket, subprocess, multiprocessing, threading and ctypes would breach
the sandbox — and others are simply not implemented yet.
The authoritative list is modules.md.
A few divergences are worth knowing up front because they change how code behaves rather than whether it runs. Each links to the page that owns it, which is where the full account lives:
assertfailures get pytest-style messages.assert 2 == 5raisesAssertionError: assert 2 == 5, not CPython’s emptyAssertionError. Turn it off withassert_message_annotations=Falseoncheckout()(assert.md).enumerate,zip,map,filterandreversedare eager, not lazy. Somap(f, itertools.count())runs until a resource limit trips (builtins.md).reis backed by Rust’sfancy-regex, not CPython’s engine: nobytespatterns, noVERBOSEflag, and some error messages differ (re.md).- Only the class dunders listed above are dispatched.
__lt__,__len__,__getitem__,__call__and the arithmetic dunders raiseTypeErroras if undefined, while__bool__and the__getattr__family are ignored silently, so an instance is always truthy (classes.md). - There is no event loop inside the sandbox.
async/awaitwork, andasyncioexposes exactly two functions:runandgather, the latter running host calls concurrently.create_task,sleepand everything else do not exist (asyncio.md). str.format()and%-formatting are not implemented. Use f-strings (format.md).- Only UTF-8, ASCII, UTF-16 and UTF-32 codecs exist.
latin-1and friends raiseLookupError(encoding.md).
For a specific feature, open the page in this section named after the builtin, module or construct.
The pages are the limitations/ directory of the repository, published
verbatim.
If you hit something that is neither in the subset nor on these pages, open an
issue.