#1060

[1.0.0] Python compatibility gaps that block common agent scripts

Openzechengzopened 14d ago

Hi,

We run Monty as the sandboxed python3 for AI agents (via pydantic-monty==1.0.0 and @pydantic/monty@1.0.0). Agents write ordinary CPython, so every gap below shows up as a failed script. We tested each item against raw Monty with pool.checkout() + feed_run(code, os=OSAccess()).

Summary

Highest impact first.

1. Iterating over a file object

for line in open('/f'):
    ...

TypeError: '_io.TextIOWrapper' object is not iterable. readlines() works. See also #490.

2. Walking a tree / path helpers

  • os.walk, os.scandir, os.path (the module doesn't exist; posixpath neither)
  • glob, fnmatch
  • Path.glob, Path.rglob, Path.walk, Path.touch, Path.relative_to, Path.match, Path.expanduser, Path.home, Path.samefile, Path.lstat, Path.readlink, Path.symlink_to, Path.chmod, Path.replace
  • pathlib.PurePath, pathlib.PurePosixPath

Hosts can't fill these in: OsFunction is the only interception point, and modules and Path have no __dict__.

3. Parser: NotImplementedError

  • Class inheritance and metaclasses. This also blocks class MyError(Exception) and class P(Protocol).
  • @classmethod, @staticmethod, @property
  • yield (generator functions)
  • del (both del x and del x[0])
  • match statements
  • async for
  • try* / except*
  • Complex literals (1j)

4. Operator dunders ignored on user classes

__add__, __lt__, __len__, __getitem__ and __call__ all raise TypeError, so for example sorted() on objects fails. __repr__, __eq__, __iter__ and __hash__ work. obj.__dict__ is also missing.

5. Missing builtins

dir, vars, globals, locals, callable, issubclass, super, classmethod, staticmethod, delattr, input, help, ascii, bytearray, memoryview, complex, compile, __import__, aiter, anext, breakpoint

6. Gaps in modules that do import

ModuleMissing
sysexit, stdin, path, modules; sys.stdout.write
jsonload, dump
functoolslru_cache, cache, wraps, cmp_to_key
collectionsOrderedDict, ChainMap
typingTypedDict, NamedTuple
dataclassesfield, asdict
oswalk, path, scandir, cpu_count

7. Builtin types

  • bytes([65, 66]) raises cannot convert 'list' object to bytes
  • int.from_bytes is missing
  • str.translate is missing
  • A bound method can't be used as a value: f = [1].append raises AttributeError
  • open() refuses + modes (w+, r+)

8. Stdlib modules agents reach for most

enum, contextlib, operator, heapq, bisect, string, textwrap, csv, io, shutil, tempfile, hashlib, uuid, struct, decimal, statistics, logging, traceback

9. Limits

  • Recursion fails just under depth 1000 (900 passes, 1000 fails), with no knob in ResourceLimits.
  • max_suspensions can't be turned off. The default of 1000 stops a plain loop of 500 file reads.

Minimal reproduction

import pydantic_monty as m

CASES = {
    "file_iter": "open('/g','w').write('a\\nb\\n')\nprint([l for l in open('/g')])",
    "os_walk": "import os\nos.walk('/')",
    "rglob": "from pathlib import Path\nlist(Path('/').rglob('*'))",
    "inherit": "class E(Exception): pass",
    "yield": "def g():\n  yield 1",
    "del": "x = 1\ndel x",
    "dunder_lt": "class A:\n  def __lt__(s,o): return True\nsorted([A(), A()])",
    "dir": "dir([])",
    "json_load": "import json\njson.load",
    "sys_exit": "import sys\nsys.exit(0)",
}

with m.Monty() as pool:
    for name, code in CASES.items():
        with pool.checkout() as s:
            try:
                s.feed_run(code, print_callback=m.CollectStreams(), os=m.OSAccess())
                print(name, "OK")
            except Exception as e:
                print(name, "FAIL", str(e).strip().splitlines()[-1])

All ten print FAIL on 1.0.0.

Activity

0

No activity yet.