diff --git a/tests/snippets/builtin_dir.py b/tests/snippets/builtin_dir.py new file mode 100644 index 0000000000..b0c3949fa0 --- /dev/null +++ b/tests/snippets/builtin_dir.py @@ -0,0 +1,12 @@ + +class A: + def test(): + pass + +a = A() + +assert "test" in dir(a) + +import socket + +assert "AF_INET" in dir(socket) diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index c800b7f522..086f7f28f0 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -2,8 +2,8 @@ use super::objdict; use super::objstr; use super::objtype; // Required for arg_check! to use isinstance use crate::pyobject::{ - AttributeProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload, - PyObjectRef, PyResult, TypeProtocol, + AttributeProtocol, DictProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, + PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; use std::cell::RefCell; @@ -277,6 +277,13 @@ pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes { attributes.insert(name.to_string(), value.clone()); } } + + // Get module attributes: + if let PyObjectPayload::Module { ref scope, .. } = &obj.payload { + for (name, value) in scope.locals.get_key_value_pairs().iter() { + attributes.insert(objstr::get_value(name).to_string(), value.clone()); + } + } attributes }