mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
module: honor module-level __dir__ (PEP 562) (#8271)
* module: honor module-level __dir__ (PEP 562) dir(module) ignored a module-level __dir__ function and returned the raw __dict__ keys. Look up __dir__ in the module dict and, when present, call it and return its result — matching CPython's module___dir___impl. The existing expectedFailure markers on test_module_dir/test_module_dir_errors are removed since both now pass. Fixes #8231 Assisted-by: Claude Code:claude-opus-4-8 * test: unmark zoneinfo test_dir_contains_all (PEP 562 __dir__) Honoring a module-level __dir__ makes dir(zoneinfo) contain everything in __all__, so test_dir_contains_all now passes. Remove its stale expectedFailure marker to avoid an unexpected-success CI failure. Assisted-by: Claude Code:claude-opus-4-8 * test: unmark test_support.test_check__all__ (PEP 562 __dir__) check__all__ iterates dir(module); honoring a module-level __dir__ fixes dir(unittest), so test_check__all__ now passes. Remove its stale expectedFailure marker to avoid an unexpected-success CI failure. Assisted-by: Claude Code:claude-opus-4-8
This commit is contained in:
1 parent
f03618e952
commit
a777208f08
4 files changed
+4
-4
No files matched your search
Vendored
-2
@@ -151,13 +151,11 @@ a = A(destroyed)"""
|
||||
if 'test.test_module.bad_getattr2' in sys.modules:
|
||||
del sys.modules['test.test_module.bad_getattr2']
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_module_dir(self):
|
||||
import test.test_module.good_getattr as gga
|
||||
self.assertEqual(dir(gga), ['a', 'b', 'c'])
|
||||
del sys.modules['test.test_module.good_getattr']
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_module_dir_errors(self):
|
||||
import test.test_module.bad_getattr as bga
|
||||
from test.test_module import bad_getattr2
|
||||
|
||||
Vendored
-1
@@ -458,7 +458,6 @@ class TestSupport(unittest.TestCase):
|
||||
self.OtherClass, self.RefClass, ignore=ignore)
|
||||
self.assertEqual(set(), missing_items)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_check__all__(self):
|
||||
extra = {'tempdir'}
|
||||
not_exported = {'template'}
|
||||
|
||||
-1
@@ -1970,7 +1970,6 @@ class TestModule(ZoneInfoTestBase):
|
||||
with self.assertRaises(AttributeError):
|
||||
self.module.NOATTRIBUTE
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; dir(self.module) should at least contain everything in __all__.
|
||||
def test_dir_contains_all(self):
|
||||
"""dir(self.module) should at least contain everything in __all__."""
|
||||
module_all_set = set(self.module.__all__)
|
||||
|
||||
@@ -303,6 +303,10 @@ impl PyModule {
|
||||
let dict = dict_attr
|
||||
.downcast::<PyDict>()
|
||||
.map_err(|_| vm.new_type_error("<module>.__dict__ is not a dictionary"))?;
|
||||
// PEP 562: honor a module-level __dir__ if one is defined
|
||||
if let Some(dir_func) = dict.get_item_opt(identifier!(vm, __dir__), vm)? {
|
||||
return dir_func.call((), vm)?.try_to_value(vm);
|
||||
}
|
||||
let attrs = dict.into_iter().map(|(k, _v)| k).collect();
|
||||
Ok(attrs)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user