diff --git a/Lib/test/test_property.py b/Lib/test/test_property.py index 65153395b7..49dc2331e9 100644 --- a/Lib/test/test_property.py +++ b/Lib/test/test_property.py @@ -201,7 +201,6 @@ def test_gh_115618(self): self.assertIsNone(prop.fdel) self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_property_name(self): def getter(self): return 42 diff --git a/vm/src/builtins/property.rs b/vm/src/builtins/property.rs index 1568cb08d8..a75357f761 100644 --- a/vm/src/builtins/property.rs +++ b/vm/src/builtins/property.rs @@ -67,20 +67,30 @@ impl GetDescriptor for PyProperty { #[pyclass(with(Constructor, Initializer, GetDescriptor), flags(BASETYPE))] impl PyProperty { // Helper method to get property name - fn get_property_name(&self, vm: &VirtualMachine) -> Option { + // Returns the name if available, None if not found, or propagates errors + fn get_property_name(&self, vm: &VirtualMachine) -> PyResult> { // First check if name was set via __set_name__ if let Some(name) = self.name.read().as_ref() { - return Some(name.clone()); + return Ok(Some(name.clone())); } - // Otherwise try to get __name__ from getter - if let Some(getter) = self.getter.read().as_ref() - && let Ok(name) = getter.get_attr("__name__", vm) - { - return Some(name); - } + let getter = self.getter.read(); + let Some(getter) = getter.as_ref() else { + return Ok(None); + }; - None + match getter.get_attr("__name__", vm) { + Ok(name) => Ok(Some(name)), + Err(e) => { + // If it's an AttributeError from the getter, return None + // Otherwise, propagate the original exception (e.g., RuntimeError) + if e.class().is(vm.ctx.exceptions.attribute_error) { + Ok(None) + } else { + Err(e) + } + } + } } // Descriptor methods @@ -143,6 +153,21 @@ impl PyProperty { self.deleter.read().clone() } + #[pygetset(name = "__name__")] + fn name_getter(&self, vm: &VirtualMachine) -> PyResult { + match self.get_property_name(vm)? { + Some(name) => Ok(name), + None => Err( + vm.new_attribute_error("'property' object has no attribute '__name__'".to_owned()) + ), + } + } + + #[pygetset(name = "__name__", setter)] + fn name_setter(&self, value: PyObjectRef) { + *self.name.write() = Some(value); + } + fn doc_getter(&self) -> Option { self.doc.read().clone() } @@ -288,7 +313,7 @@ impl PyProperty { error_type: &str, vm: &VirtualMachine, ) -> PyResult { - let prop_name = self.get_property_name(vm); + let prop_name = self.get_property_name(vm)?; let obj_type = obj.class(); let qualname = obj_type.__qualname__(vm);