Skip to content

Commit 6bcb2b6

Browse files
committed
Refactor to use get_property_name in __name__ implementation
Consolidate duplicate logic by making name_getter() use the existing get_property_name() helper method. This eliminates code duplication and improves maintainability. Changes: - Update get_property_name() to return PyResult<Option<PyObjectRef>> to properly handle and propagate non-AttributeError exceptions - Simplify name_getter() to delegate to get_property_name() - Update format_property_error() to handle the new return type This addresses review feedback about the relationship between get_property_name() and __name__ implementation.
1 parent 0878b8e commit 6bcb2b6

File tree

1 file changed

+25
-34
lines changed

1 file changed

+25
-34
lines changed

vm/src/builtins/property.rs

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,30 @@ impl GetDescriptor for PyProperty {
6767
#[pyclass(with(Constructor, Initializer, GetDescriptor), flags(BASETYPE))]
6868
impl PyProperty {
6969
// Helper method to get property name
70-
fn get_property_name(&self, vm: &VirtualMachine) -> Option<PyObjectRef> {
70+
// Returns the name if available, None if not found, or propagates errors
71+
fn get_property_name(&self, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>> {
7172
// First check if name was set via __set_name__
7273
if let Some(name) = self.name.read().as_ref() {
73-
return Some(name.clone());
74+
return Ok(Some(name.clone()));
7475
}
7576

7677
// Otherwise try to get __name__ from getter
77-
if let Some(getter) = self.getter.read().as_ref()
78-
&& let Ok(name) = getter.get_attr("__name__", vm)
79-
{
80-
return Some(name);
78+
if let Some(getter) = self.getter.read().as_ref() {
79+
match getter.get_attr("__name__", vm) {
80+
Ok(name) => Ok(Some(name)),
81+
Err(e) => {
82+
// If it's an AttributeError from the getter, return None
83+
// Otherwise, propagate the original exception (e.g., RuntimeError)
84+
if e.class().is(vm.ctx.exceptions.attribute_error) {
85+
Ok(None)
86+
} else {
87+
Err(e)
88+
}
89+
}
90+
}
91+
} else {
92+
Ok(None)
8193
}
82-
83-
None
8494
}
8595

8696
// Descriptor methods
@@ -145,31 +155,12 @@ impl PyProperty {
145155

146156
#[pygetset(name = "__name__")]
147157
fn name_getter(&self, vm: &VirtualMachine) -> PyResult {
148-
// If name was explicitly set via __set_name__ or direct assignment
149-
// (even to None), return it as-is
150-
if let Some(name) = self.name.read().as_ref() {
151-
return Ok(name.clone());
152-
}
153-
154-
// Fallback to getter's __name__ if available
155-
if let Some(getter) = self.getter.read().as_ref() {
156-
match getter.get_attr("__name__", vm) {
157-
Ok(name) => Ok(name),
158-
Err(e) => {
159-
// If it's an AttributeError from the getter, convert to property's AttributeError
160-
// Otherwise, propagate the original exception (e.g., RuntimeError)
161-
if e.class().is(vm.ctx.exceptions.attribute_error) {
162-
return Err(vm.new_attribute_error(
163-
"'property' object has no attribute '__name__'".to_owned(),
164-
));
165-
}
166-
167-
Err(e)
168-
}
169-
}
170-
} else {
171-
// If no getter, raise AttributeError
172-
Err(vm.new_attribute_error("'property' object has no attribute '__name__'".to_owned()))
158+
// Use get_property_name helper to get the name
159+
match self.get_property_name(vm)? {
160+
Some(name) => Ok(name),
161+
None => Err(
162+
vm.new_attribute_error("'property' object has no attribute '__name__'".to_owned())
163+
),
173164
}
174165
}
175166

@@ -323,7 +314,7 @@ impl PyProperty {
323314
error_type: &str,
324315
vm: &VirtualMachine,
325316
) -> PyResult<String> {
326-
let prop_name = self.get_property_name(vm);
317+
let prop_name = self.get_property_name(vm)?;
327318
let obj_type = obj.class();
328319
let qualname = obj_type.__qualname__(vm);
329320

0 commit comments

Comments
 (0)