@@ -95,15 +95,15 @@ impl PyProperty {
9595 match value {
9696 PySetterValue :: Assign ( value) => {
9797 if let Some ( setter) = zelf. setter . read ( ) . as_ref ( ) {
98- setter. call ( ( obj. clone ( ) , value) , vm) . map ( drop)
98+ setter. call ( ( obj, value) , vm) . map ( drop)
9999 } else {
100100 let error_msg = zelf. format_property_error ( & obj, "setter" , vm) ?;
101101 Err ( vm. new_attribute_error ( error_msg) )
102102 }
103103 }
104104 PySetterValue :: Delete => {
105105 if let Some ( deleter) = zelf. deleter . read ( ) . as_ref ( ) {
106- deleter. call ( ( obj. clone ( ) , ) , vm) . map ( drop)
106+ deleter. call ( ( obj, ) , vm) . map ( drop)
107107 } else {
108108 let error_msg = zelf. format_property_error ( & obj, "deleter" , vm) ?;
109109 Err ( vm. new_attribute_error ( error_msg) )
@@ -166,29 +166,33 @@ impl PyProperty {
166166
167167 // Python builder functions
168168
169- # [ pymethod ]
170- fn getter (
169+ // Helper method to create a new property with updated attributes
170+ fn clone_property_with (
171171 zelf : PyRef < Self > ,
172- getter : Option < PyObjectRef > ,
172+ new_getter : Option < PyObjectRef > ,
173+ new_setter : Option < PyObjectRef > ,
174+ new_deleter : Option < PyObjectRef > ,
173175 vm : & VirtualMachine ,
174176 ) -> PyResult < PyRef < Self > > {
175- let new_getter = getter. or_else ( || zelf. fget ( ) ) ;
176-
177- // Determine doc based on getter_doc flag
177+ // Determine doc based on getter_doc flag and whether we're updating the getter
178178 let doc = if zelf. getter_doc . load ( Ordering :: Relaxed ) && new_getter. is_some ( ) {
179179 // If the original property uses getter doc and we have a new getter,
180180 // pass Py_None to let __init__ get the doc from the new getter
181181 Some ( vm. ctx . none ( ) )
182+ } else if zelf. getter_doc . load ( Ordering :: Relaxed ) {
183+ // If original used getter_doc but we're not changing the getter,
184+ // pass None to let init get doc from existing getter
185+ Some ( vm. ctx . none ( ) )
182186 } else {
183187 // Otherwise use the existing doc
184188 zelf. doc_getter ( )
185189 } ;
186190
187- // Create property args
191+ // Create property args with updated values
188192 let args = PropertyArgs {
189- fget : new_getter,
190- fset : zelf. fset ( ) ,
191- fdel : zelf. fdel ( ) ,
193+ fget : new_getter. or_else ( || zelf . fget ( ) ) ,
194+ fset : new_setter . or_else ( || zelf. fset ( ) ) ,
195+ fdel : new_deleter . or_else ( || zelf. fdel ( ) ) ,
192196 doc,
193197 name : None ,
194198 } ;
@@ -206,38 +210,22 @@ impl PyProperty {
206210 Ok ( new_prop_ref)
207211 }
208212
213+ #[ pymethod]
214+ fn getter (
215+ zelf : PyRef < Self > ,
216+ getter : Option < PyObjectRef > ,
217+ vm : & VirtualMachine ,
218+ ) -> PyResult < PyRef < Self > > {
219+ Self :: clone_property_with ( zelf, getter, None , None , vm)
220+ }
221+
209222 #[ pymethod]
210223 fn setter (
211224 zelf : PyRef < Self > ,
212225 setter : Option < PyObjectRef > ,
213226 vm : & VirtualMachine ,
214227 ) -> PyResult < PyRef < Self > > {
215- // For setter, we need to preserve doc handling from the original property
216- let doc = if zelf. getter_doc . load ( Ordering :: Relaxed ) {
217- // If original used getter_doc, pass None to let init get doc from getter
218- Some ( vm. ctx . none ( ) )
219- } else {
220- zelf. doc_getter ( )
221- } ;
222-
223- let args = PropertyArgs {
224- fget : zelf. fget ( ) ,
225- fset : setter. or_else ( || zelf. fset ( ) ) ,
226- fdel : zelf. fdel ( ) ,
227- doc,
228- name : None ,
229- } ;
230-
231- let new_prop = PyProperty :: py_new ( zelf. class ( ) . to_owned ( ) , FuncArgs :: default ( ) , vm) ?;
232- let new_prop_ref = new_prop. downcast :: < PyProperty > ( ) . unwrap ( ) ;
233- PyProperty :: init ( new_prop_ref. clone ( ) , args, vm) ?;
234-
235- // Copy the name if it exists
236- if let Some ( name) = zelf. name . read ( ) . clone ( ) {
237- * new_prop_ref. name . write ( ) = Some ( name) ;
238- }
239-
240- Ok ( new_prop_ref)
228+ Self :: clone_property_with ( zelf, None , setter, None , vm)
241229 }
242230
243231 #[ pymethod]
@@ -246,32 +234,7 @@ impl PyProperty {
246234 deleter : Option < PyObjectRef > ,
247235 vm : & VirtualMachine ,
248236 ) -> PyResult < PyRef < Self > > {
249- // For deleter, we need to preserve doc handling from the original property
250- let doc = if zelf. getter_doc . load ( Ordering :: Relaxed ) {
251- // If original used getter_doc, pass None to let init get doc from getter
252- Some ( vm. ctx . none ( ) )
253- } else {
254- zelf. doc_getter ( )
255- } ;
256-
257- let args = PropertyArgs {
258- fget : zelf. fget ( ) ,
259- fset : zelf. fset ( ) ,
260- fdel : deleter. or_else ( || zelf. fdel ( ) ) ,
261- doc,
262- name : None ,
263- } ;
264-
265- let new_prop = PyProperty :: py_new ( zelf. class ( ) . to_owned ( ) , FuncArgs :: default ( ) , vm) ?;
266- let new_prop_ref = new_prop. downcast :: < PyProperty > ( ) . unwrap ( ) ;
267- PyProperty :: init ( new_prop_ref. clone ( ) , args, vm) ?;
268-
269- // Copy the name if it exists
270- if let Some ( name) = zelf. name . read ( ) . clone ( ) {
271- * new_prop_ref. name . write ( ) = Some ( name) ;
272- }
273-
274- Ok ( new_prop_ref)
237+ Self :: clone_property_with ( zelf, None , None , deleter, vm)
275238 }
276239
277240 #[ pygetset( magic) ]
@@ -365,11 +328,6 @@ impl Initializer for PyProperty {
365328 type Args = PropertyArgs ;
366329
367330 fn init ( zelf : PyRef < Self > , args : Self :: Args , vm : & VirtualMachine ) -> PyResult < ( ) > {
368- * zelf. getter . write ( ) = args. fget . clone ( ) ;
369- * zelf. setter . write ( ) = args. fset ;
370- * zelf. deleter . write ( ) = args. fdel ;
371- * zelf. name . write ( ) = args. name . map ( |a| a. as_object ( ) . to_owned ( ) ) ;
372-
373331 // Set doc and getter_doc flag
374332 let mut getter_doc = false ;
375333
@@ -411,6 +369,10 @@ impl Initializer for PyProperty {
411369 }
412370 }
413371
372+ * zelf. getter . write ( ) = args. fget ;
373+ * zelf. setter . write ( ) = args. fset ;
374+ * zelf. deleter . write ( ) = args. fdel ;
375+ * zelf. name . write ( ) = args. name . map ( |a| a. as_object ( ) . to_owned ( ) ) ;
414376 zelf. getter_doc . store ( getter_doc, Ordering :: Relaxed ) ;
415377
416378 Ok ( ( ) )
0 commit comments