The Python Subset
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 exhaustive, per-feature list lives in limitations/ in
the repository, and that directory — not this page — is the source of truth.
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__, class variables @dataclass, including theeq=andfrozen=options, and host dataclass instances passed in and out- 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.
Thirteen modules are importable.
Anything else raises ModuleNotFoundError.
| Module | Divergences |
|---|---|
asyncio | asyncio.md |
collections | collections.md |
dataclasses | dataclasses.md |
datetime | datetime.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: functools, enum, contextlib, random, time, io, copy, string, struct, operator,
inspect, logging, traceback, base64, 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
limitations/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 limitations/ file 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).- 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 limitations/ file named after the builtin, module or construct.
If you hit something that is neither in the subset nor in limitations/, open an
issue.