Back to Monty

`os` module

limitations/os.md

0.0.215.5 KB
Original Source

os module

The 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.

Implemented

  • 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.
  • Constants (fixed POSIX values on every host OS, matching the sandbox's POSIX-only path model): os.sep == '/', os.altsep is None, os.extsep == '.', os.curdir == '.', os.pardir == '..', os.linesep == '\n', os.name == 'posix', os.devnull == '/dev/null'.

Divergences from CPython

  • No file descriptors, no 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).
  • No __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.
  • All-keyword calls that overflow the signature are not always reported the way CPython reports them. 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)).
  • No working directory. 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.
  • Hosts see pathlib-style call names. 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).
  • Error side-effects differ slightly for os.makedirs: Monty validates mode up front, while CPython only fails when it reaches the final mkdir (after creating parent directories).

Not implemented

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).