Summary
A module-level __dir__ function (PEP 562) is ignored: dir(module) returns the raw __dict__ keys instead of calling the module's __dir__.
# mod.py
import sys
def __dir__():
return ['gamma', 'alpha', 'beta']
print(dir(sys.modules[__name__]))
- CPython 3.14.2:
['alpha', 'beta', 'gamma'] (calls the function, dir() sorts the result)
- RustPython:
['__builtins__', '__cached__', '__dir__', ..., 'sys']
Verified on main @ 7044fdc. PEP 562's other half, module-level __getattr__, works — only __dir__ is missing.
Cause
PyModule.__dir__ (crates/vm/src/builtins/module.rs:300) unconditionally returns the module dict's keys:
fn __dir__(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
let dict_attr = zelf.as_object().get_attr(identifier!(vm, __dict__), vm)?;
...
Ok(dict.into_iter().map(|(k, _v)| k).collect())
}
CPython's module___dir___impl (Objects/moduleobject.c) first looks up __dir__ in the module's __dict__ and, if present, calls it and returns its result; only otherwise does it fall back to list(__dict__).
Found while running synthetic benchmark/compat suites; researched and reported by Claude on behalf of @youknowone.
Summary
A module-level
__dir__function (PEP 562) is ignored:dir(module)returns the raw__dict__keys instead of calling the module's__dir__.['alpha', 'beta', 'gamma'](calls the function,dir()sorts the result)['__builtins__', '__cached__', '__dir__', ..., 'sys']Verified on
main@ 7044fdc. PEP 562's other half, module-level__getattr__, works — only__dir__is missing.Cause
PyModule.__dir__(crates/vm/src/builtins/module.rs:300) unconditionally returns the module dict's keys:CPython's
module___dir___impl(Objects/moduleobject.c) first looks up__dir__in the module's__dict__and, if present, calls it and returns its result; only otherwise does it fall back tolist(__dict__).Found while running synthetic benchmark/compat suites; researched and reported by Claude on behalf of @youknowone.