← board

os has no rmdir

import os
os.rmdir(d)        # error: undefined variable (os)
os.path.isdir(d)   # fine
os.listdir("/tmp") # fine
os.sep             # fine
os.getpid()        # error: undefined variable (os)

The diagnostic is misleading and that is the expensive part

undefined variable (os) names the MODULE when the module is bound and working three lines earlier. Anyone reading it looks at the import first. The message for a genuinely missing member of a bound qualifier should look like the one tempfile gives — no member mkdtemp came of the qualifier tempfile — which is precise and sends the reader to the right place. shutil.rmtree produces exactly that better form, so the two diagnostics disagree about the same class of gap.

Not the same as os.remove / os.makedirs

Those exist as compiler-provided calls and refuse only as bare values:

print(os.remove)     -> Nil Python: os.remove is a compiler-provided ...
print(os.makedirs)   -> Nil Python: os.makedirs is a compiler-provided ...

Do not "fix" this ticket by finding those and concluding the family works.

Why it matters beyond tidiness

tempfile.TemporaryDirectory is the natural companion to the mkdtemp landed on 2026-09-12 and cannot be written without a directory removal. Any NilPy program that makes a scratch directory currently has no way to clean it up.

Log

How it was fixed (2026-09-12)

Three places, and the cheapness is the point:

Deliberately non-recursive, matching CPython: rmdir on a non-empty directory raises. The fixture asserts both halves (NONEMPTY raised True, MISSING raised).

It is a BUILTIN addition, so it is inert until a pin

compiler/builtin/*.pas is resolved CWD-relative by the live compiler, so this works immediately in the dev loop and is invisible to every $(PXX_STABLE) consumer until the owner pins. make pin is owner-only; this is recorded here rather than waited on.

Residuals, each with an owner

What it retired

This ticket's own summary used to say the mkdtemp fixture "has to leave two empty directories behind every run and says so". It does not any more — it cleans up with this rmdir and measures delta 0 inodes over three runs. The summary was corrected in the same commit, not left for a later reader.