limitations/os.md
os moduleThe sandbox exposes a small, host-mediated subset of os. Filesystem
functions route through the same OS-call mechanism as pathlib
and open — the host's mount table (or os callback) decides
whether each call is permitted.
os.getenv(key, default=None) — yields to the host; the host decides
which environment variables are visible (typically a curated subset, not
the full host environment).os.environ — property that yields to the host and returns a dict of
the same curated environment. It is a plain dict, not an os._Environ
object: mutating it does not propagate back to the host.os.listdir(path=None) — returns a list of entry names.os.stat(path) — returns the same 10-field stat result as Path.stat().os.mkdir(path, mode=0o777), os.makedirs(name, mode=0o777, exist_ok=False)os.remove(path), os.unlink(path), os.rmdir(path)os.rename(src, dst), os.replace(src, dst)os.fspath(path) — pure, no host involvement.os.sep == '/', os.altsep is None,
os.extsep == '.', os.curdir == '.', os.pardir == '..',
os.linesep == '\n', os.name == 'posix', os.devnull == '/dev/null'.bytes paths. Paths must be str or
pathlib.Path. bytes paths and integer fds (bools included — CPython
fd-converts them with only a RuntimeWarning) — which CPython accepts —
raise the path-converter TypeError with the accepted-types phrase
narrowed to what Monty takes, e.g.
stat: path should be string or os.PathLike, not bytes. For every other
rejected type the phrase is CPython's verbatim, so os.stat(1.5) still
says should be string, bytes, os.PathLike or integer. (Note open()
does accept bytes paths, decoding them as UTF-8; the os functions do
not.) The os.listdir wording always includes integer — POSIX CPython's
phrasing — even though Windows CPython omits it (no fd-based listdir there).__fspath__ protocol. os.fspath (and every path-taking function)
accepts only str, bytes (fspath only), and pathlib.Path — a
user-defined class implementing __fspath__ raises TypeError instead of
having its method called.dir_fd keywords (dir_fd, src_dir_fd, dst_dir_fd) are parsed
for signature parity but any non-None value raises the
NotImplementedError CPython uses on platforms without them
(dir_fd unavailable on this platform). Non-int values raise the
converter TypeError (argument should be integer or None, not str).os.stat(..., follow_symlinks=...) raises
NotImplementedError: stat: follow_symlinks unavailable on this platform
for any falsy value — CPython truth-tests the argument, so False,
None and 0 all mean "lstat", which Monty has no behavior for.
os.lstat itself is not implemented.os.fspath(path='a', foo=1) and
os.listdir(path='.', foo=1) match (takes at most 1 keyword argument (2 given)), but functions with keyword-only slots — os.stat, os.mkdir,
os.remove, os.rmdir, os.rename — report the first unknown keyword
(stat() got an unexpected keyword argument 'foo') where CPython reports
the arity (stat() takes at most 3 keyword arguments (4 given)).os.listdir()'s default '.' (or any relative
path) reaches the host unchanged; a mount table matches no mount and
raises PermissionError.mode arguments are type-checked ('str' object cannot be interpreted as an integer) but otherwise ignored — Monty's filesystem
backends do not model POSIX permission bits.os.replace is an alias of os.rename at the host boundary: both
suspend with the same rename OS call, so overwrite semantics are whatever
the host backend does (POSIX rename overwrites; a Windows host may
refuse). CPython's os.replace guarantees overwrite on all platforms.os.listdir suspends as
Path.iterdir (the interpreter reduces the returned paths to names),
os.stat as Path.stat, os.remove/os.unlink as Path.unlink,
os.mkdir/os.makedirs as Path.mkdir, os.rename/os.replace as
Path.rename. A custom os callback cannot distinguish e.g. os.listdir
from Path.iterdir.os.stat results print as StatResult(...), not
os.stat_result(...), and carry only the 10 core fields (same as
Path.stat() — see filesystem.md).os.makedirs: Monty validates
mode up front, while CPython only fails when it reaches the final
mkdir (after creating parent directories).Everything else, including but not limited to: os.path.* (use
pathlib.Path instead), os.getcwd, os.chdir, os.walk, os.scandir,
os.removedirs, os.renames, os.lstat, os.access, os.symlink,
os.readlink, os.link, os.chmod, os.chown, os.umask, os.truncate,
os.utime, os.system, os.popen, os.fork, os.exec*, os.spawn*,
os.kill, os.pipe, os.read, os.write, os.open, os.close,
os.dup, os.fsync, os.urandom, os.cpu_count, os.getpid,
os.getuid, os.getgid, os.uname, os.terminal_size, os.get_terminal_size.
subprocess, signal, socket, threading, multiprocessing are not
importable either (see modules.md).