Skip to content

Commit 27b9b5e

Browse files
committed
Impl PyAttributeError args
1 parent 0dac02f commit 27b9b5e

6 files changed

Lines changed: 44 additions & 32 deletions

File tree

Lib/test/test_exceptions.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,8 +2087,6 @@ def test_attributes(self):
20872087
self.assertEqual(exc.name, 'carry')
20882088
self.assertIs(exc.obj, sentinel)
20892089

2090-
# TODO: RUSTPYTHON
2091-
@unittest.expectedFailure
20922090
def test_getattr_has_name_and_obj(self):
20932091
class A:
20942092
blech = None

vm/src/builtins/descriptor.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,7 @@ fn get_slot_from_object(
287287
.get_slot(offset)
288288
.unwrap_or_else(|| vm.ctx.new_bool(false).into()),
289289
MemberKind::ObjectEx => obj.get_slot(offset).ok_or_else(|| {
290-
vm.new_attribute_error(format!(
291-
"'{}' object has no attribute '{}'",
292-
obj.class().name(),
293-
member.name
294-
))
290+
vm.new_no_attribute_error(obj.clone(), vm.ctx.new_str(member.name.clone()))
295291
})?,
296292
};
297293
Ok(slot)

vm/src/exceptions.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1260,10 +1260,33 @@ pub(super) mod types {
12601260
#[derive(Debug)]
12611261
pub struct PyAssertionError {}
12621262

1263-
#[pyexception(name, base = "PyException", ctx = "attribute_error", impl)]
1263+
#[pyexception(name, base = "PyException", ctx = "attribute_error")]
12641264
#[derive(Debug)]
12651265
pub struct PyAttributeError {}
12661266

1267+
#[pyexception]
1268+
impl PyAttributeError {
1269+
#[pyslot]
1270+
#[pymethod(name = "__init__")]
1271+
pub(crate) fn slot_init(
1272+
zelf: PyObjectRef,
1273+
args: ::rustpython_vm::function::FuncArgs,
1274+
vm: &::rustpython_vm::VirtualMachine,
1275+
) -> ::rustpython_vm::PyResult<()> {
1276+
zelf.set_attr(
1277+
"name",
1278+
vm.unwrap_or_none(args.kwargs.get("name").cloned()),
1279+
vm,
1280+
)?;
1281+
zelf.set_attr(
1282+
"obj",
1283+
vm.unwrap_or_none(args.kwargs.get("obj").cloned()),
1284+
vm,
1285+
)?;
1286+
Ok(())
1287+
}
1288+
}
1289+
12671290
#[pyexception(name, base = "PyException", ctx = "buffer_error", impl)]
12681291
#[derive(Debug)]
12691292
pub struct PyBufferError {}

vm/src/protocol/object.rs

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -187,34 +187,21 @@ impl PyObject {
187187
} else {
188188
dict.del_item(attr_name, vm).map_err(|e| {
189189
if e.fast_isinstance(vm.ctx.exceptions.key_error) {
190-
vm.new_attribute_error(format!(
191-
"'{}' object has no attribute '{}'",
192-
self.class().name(),
193-
attr_name.as_str(),
194-
))
190+
vm.new_no_attribute_error(self.to_owned(), attr_name.to_owned())
195191
} else {
196192
e
197193
}
198194
})?;
199195
}
200196
Ok(())
201197
} else {
202-
Err(vm.new_attribute_error(format!(
203-
"'{}' object has no attribute '{}'",
204-
self.class().name(),
205-
attr_name.as_str(),
206-
)))
198+
Err(vm.new_no_attribute_error(self.to_owned(), attr_name.to_owned()))
207199
}
208200
}
209201

210202
pub fn generic_getattr(&self, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
211-
self.generic_getattr_opt(name, None, vm)?.ok_or_else(|| {
212-
vm.new_attribute_error(format!(
213-
"'{}' object has no attribute '{}'",
214-
self.class().name(),
215-
name
216-
))
217-
})
203+
self.generic_getattr_opt(name, None, vm)?
204+
.ok_or_else(|| vm.new_no_attribute_error(self.to_owned(), name.to_owned()))
218205
}
219206

220207
/// CPython _PyObject_GenericGetAttrWithDict

vm/src/vm/method.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,7 @@ impl PyMethod {
7979
} else if let Some(getter) = cls.get_attr(identifier!(vm, __getattr__)) {
8080
getter.call((obj, name.to_owned()), vm).map(Self::Attribute)
8181
} else {
82-
let exc = vm.new_attribute_error(format!(
83-
"'{}' object has no attribute '{}'",
84-
cls.name(),
85-
name
86-
));
87-
vm.set_attribute_error_context(&exc, obj.clone(), name.to_owned());
88-
Err(exc)
82+
Err(vm.new_no_attribute_error(obj.clone(), name.to_owned()))
8983
}
9084
}
9185

vm/src/vm/vm_new.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,20 @@ impl VirtualMachine {
135135
self.new_exception_msg(attribute_error, msg)
136136
}
137137

138+
pub fn new_no_attribute_error(&self, obj: PyObjectRef, name: PyStrRef) -> PyBaseExceptionRef {
139+
let msg = format!(
140+
"'{}' object has no attribute '{}'",
141+
obj.class().name(),
142+
name
143+
);
144+
let attribute_error = self.new_attribute_error(msg);
145+
146+
// Use existing set_attribute_error_context function
147+
self.set_attribute_error_context(&attribute_error, obj, name);
148+
149+
attribute_error
150+
}
151+
138152
pub fn new_type_error(&self, msg: String) -> PyBaseExceptionRef {
139153
let type_error = self.ctx.exceptions.type_error.to_owned();
140154
self.new_exception_msg(type_error, msg)

0 commit comments

Comments
 (0)