Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions Lib/test/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2074,8 +2074,6 @@ def f():


class AttributeErrorTests(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_attributes(self):
# Setting 'attr' should not be a problem.
exc = AttributeError('Ouch!')
Expand All @@ -2087,8 +2085,6 @@ def test_attributes(self):
self.assertEqual(exc.name, 'carry')
self.assertIs(exc.obj, sentinel)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_getattr_has_name_and_obj(self):
class A:
blech = None
Expand Down
6 changes: 1 addition & 5 deletions vm/src/builtins/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,7 @@ fn get_slot_from_object(
.get_slot(offset)
.unwrap_or_else(|| vm.ctx.new_bool(false).into()),
MemberKind::ObjectEx => obj.get_slot(offset).ok_or_else(|| {
vm.new_attribute_error(format!(
"'{}' object has no attribute '{}'",
obj.class().name(),
member.name
))
vm.new_no_attribute_error(obj.clone(), vm.ctx.new_str(member.name.clone()))
})?,
};
Ok(slot)
Expand Down
25 changes: 24 additions & 1 deletion vm/src/exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1260,10 +1260,33 @@ pub(super) mod types {
#[derive(Debug)]
pub struct PyAssertionError {}

#[pyexception(name, base = "PyException", ctx = "attribute_error", impl)]
#[pyexception(name, base = "PyException", ctx = "attribute_error")]
#[derive(Debug)]
pub struct PyAttributeError {}

#[pyexception]
impl PyAttributeError {
#[pyslot]
#[pymethod(name = "__init__")]
pub(crate) fn slot_init(
zelf: PyObjectRef,
args: ::rustpython_vm::function::FuncArgs,
vm: &::rustpython_vm::VirtualMachine,
) -> ::rustpython_vm::PyResult<()> {
zelf.set_attr(
"name",
vm.unwrap_or_none(args.kwargs.get("name").cloned()),
vm,
)?;
zelf.set_attr(
"obj",
vm.unwrap_or_none(args.kwargs.get("obj").cloned()),
vm,
)?;
Ok(())
}
}

#[pyexception(name, base = "PyException", ctx = "buffer_error", impl)]
#[derive(Debug)]
pub struct PyBufferError {}
Expand Down
21 changes: 4 additions & 17 deletions vm/src/protocol/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,34 +187,21 @@ impl PyObject {
} else {
dict.del_item(attr_name, vm).map_err(|e| {
if e.fast_isinstance(vm.ctx.exceptions.key_error) {
vm.new_attribute_error(format!(
"'{}' object has no attribute '{}'",
self.class().name(),
attr_name.as_str(),
))
vm.new_no_attribute_error(self.to_owned(), attr_name.to_owned())
} else {
e
}
})?;
}
Ok(())
} else {
Err(vm.new_attribute_error(format!(
"'{}' object has no attribute '{}'",
self.class().name(),
attr_name.as_str(),
)))
Err(vm.new_no_attribute_error(self.to_owned(), attr_name.to_owned()))
}
}

pub fn generic_getattr(&self, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
self.generic_getattr_opt(name, None, vm)?.ok_or_else(|| {
vm.new_attribute_error(format!(
"'{}' object has no attribute '{}'",
self.class().name(),
name
))
})
self.generic_getattr_opt(name, None, vm)?
.ok_or_else(|| vm.new_no_attribute_error(self.to_owned(), name.to_owned()))
}

/// CPython _PyObject_GenericGetAttrWithDict
Expand Down
8 changes: 1 addition & 7 deletions vm/src/vm/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,7 @@ impl PyMethod {
} else if let Some(getter) = cls.get_attr(identifier!(vm, __getattr__)) {
getter.call((obj, name.to_owned()), vm).map(Self::Attribute)
} else {
let exc = vm.new_attribute_error(format!(
"'{}' object has no attribute '{}'",
cls.name(),
name
));
vm.set_attribute_error_context(&exc, obj.clone(), name.to_owned());
Err(exc)
Err(vm.new_no_attribute_error(obj.clone(), name.to_owned()))
}
}

Expand Down
14 changes: 14 additions & 0 deletions vm/src/vm/vm_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,20 @@ impl VirtualMachine {
self.new_exception_msg(attribute_error, msg)
}

pub fn new_no_attribute_error(&self, obj: PyObjectRef, name: PyStrRef) -> PyBaseExceptionRef {
let msg = format!(
"'{}' object has no attribute '{}'",
obj.class().name(),
name
);
let attribute_error = self.new_attribute_error(msg);

// Use existing set_attribute_error_context function
self.set_attribute_error_context(&attribute_error, obj, name);

attribute_error
}

pub fn new_type_error(&self, msg: String) -> PyBaseExceptionRef {
let type_error = self.ctx.exceptions.type_error.to_owned();
self.new_exception_msg(type_error, msg)
Expand Down
Loading