Skip to content

Commit 785854a

Browse files
authored
Merge pull request RustPython#818 from RustPython/dir_str_bug
Fix dir bug - not including object attributes correctly.
2 parents 42a3b7a + 80ec464 commit 785854a

File tree

3 files changed

+32
-21
lines changed

3 files changed

+32
-21
lines changed

tests/snippets/builtin_dir.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ def test():
88
assert "test" in dir(a), "test not in a"
99
assert "test" in dir(A), "test not in A"
1010

11+
a.x = 3
12+
assert "x" in dir(a), "x not in a"
13+
1114
class B(A):
1215
def __dir__(self):
1316
return ('q', 'h')

vm/src/obj/objdict.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,19 @@ impl PyDictRef {
239239
attrs
240240
}
241241

242+
pub fn from_attributes(attrs: PyAttributes, vm: &VirtualMachine) -> PyResult<Self> {
243+
let dict = DictContentType::default();
244+
let entries = RefCell::new(dict);
245+
246+
for (key, value) in attrs {
247+
entries
248+
.borrow_mut()
249+
.insert(vm, &vm.ctx.new_str(key), value)?;
250+
}
251+
252+
Ok(PyDict { entries }.into_ref(vm))
253+
}
254+
242255
fn hash(self, vm: &VirtualMachine) -> PyResult {
243256
Err(vm.new_type_error("unhashable type".to_string()))
244257
}

vm/src/obj/objobject.rs

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,22 @@ fn object_repr(zelf: PyObjectRef, _vm: &VirtualMachine) -> String {
117117
format!("<{} object at 0x{:x}>", zelf.class().name, zelf.get_id())
118118
}
119119

120-
pub fn object_dir(obj: PyObjectRef, vm: &VirtualMachine) -> PyList {
121-
let attributes = get_attributes(&obj);
122-
let attributes: Vec<PyObjectRef> = attributes
123-
.keys()
124-
.map(|k| vm.ctx.new_str(k.to_string()))
125-
.collect();
126-
PyList::from(attributes)
120+
pub fn object_dir(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyList> {
121+
let attributes: PyAttributes = objtype::get_attributes(obj.class());
122+
123+
let dict = PyDictRef::from_attributes(attributes, vm)?;
124+
125+
// Get instance attributes:
126+
if let Some(object_dict) = &obj.dict {
127+
vm.invoke(
128+
vm.get_attribute(dict.clone().into_object(), "update")?,
129+
object_dict.clone().into_object(),
130+
)?;
131+
}
132+
133+
let attributes: Vec<_> = dict.into_iter().map(|(k, _v)| k.clone()).collect();
134+
135+
Ok(PyList::from(attributes))
127136
}
128137

129138
fn object_format(
@@ -230,17 +239,3 @@ fn object_getattr(
230239
Ok(None)
231240
}
232241
}
233-
234-
pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes {
235-
// Get class attributes:
236-
let mut attributes = objtype::get_attributes(obj.class());
237-
238-
// Get instance attributes:
239-
if let Some(dict) = &obj.dict {
240-
for (key, value) in dict {
241-
attributes.insert(key.to_string(), value.clone());
242-
}
243-
}
244-
245-
attributes
246-
}

0 commit comments

Comments
 (0)