@@ -255,21 +255,38 @@ impl PyProperty {
255255 }
256256
257257 #[ pygetset( magic) ]
258- fn isabstractmethod ( & self , vm : & VirtualMachine ) -> PyObjectRef {
259- let getter_abstract = match self . getter . read ( ) . to_owned ( ) {
260- Some ( getter) => getter
261- . get_attr ( "__isabstractmethod__" , vm)
262- . unwrap_or_else ( |_| vm. ctx . new_bool ( false ) . into ( ) ) ,
263- _ => vm. ctx . new_bool ( false ) . into ( ) ,
264- } ;
265- let setter_abstract = match self . setter . read ( ) . to_owned ( ) {
266- Some ( setter) => setter
267- . get_attr ( "__isabstractmethod__" , vm)
268- . unwrap_or_else ( |_| vm. ctx . new_bool ( false ) . into ( ) ) ,
269- _ => vm. ctx . new_bool ( false ) . into ( ) ,
270- } ;
271- vm. _or ( & setter_abstract, & getter_abstract)
272- . unwrap_or_else ( |_| vm. ctx . new_bool ( false ) . into ( ) )
258+ fn isabstractmethod ( & self , vm : & VirtualMachine ) -> PyResult {
259+ // Check getter first
260+ if let Some ( getter) = self . getter . read ( ) . as_ref ( ) {
261+ if let Ok ( isabstract) = getter. get_attr ( "__isabstractmethod__" , vm) {
262+ let is_true = isabstract. try_to_bool ( vm) ?;
263+ if is_true {
264+ return Ok ( vm. ctx . new_bool ( true ) . into ( ) ) ;
265+ }
266+ }
267+ }
268+
269+ // Check setter
270+ if let Some ( setter) = self . setter . read ( ) . as_ref ( ) {
271+ if let Ok ( isabstract) = setter. get_attr ( "__isabstractmethod__" , vm) {
272+ let is_true = isabstract. try_to_bool ( vm) ?;
273+ if is_true {
274+ return Ok ( vm. ctx . new_bool ( true ) . into ( ) ) ;
275+ }
276+ }
277+ }
278+
279+ // Check deleter
280+ if let Some ( deleter) = self . deleter . read ( ) . as_ref ( ) {
281+ if let Ok ( isabstract) = deleter. get_attr ( "__isabstractmethod__" , vm) {
282+ let is_true = isabstract. try_to_bool ( vm) ?;
283+ if is_true {
284+ return Ok ( vm. ctx . new_bool ( true ) . into ( ) ) ;
285+ }
286+ }
287+ }
288+
289+ Ok ( vm. ctx . new_bool ( false ) . into ( ) )
273290 }
274291
275292 #[ pygetset( magic, setter) ]
@@ -329,7 +346,25 @@ impl Initializer for PyProperty {
329346 }
330347 } ;
331348
332- * zelf. doc . write ( ) = doc;
349+ // Check if this is a property subclass
350+ let is_exact_property = zelf. class ( ) . is ( vm. ctx . types . property_type ) ;
351+
352+ if is_exact_property {
353+ // For exact property type, store doc in the field
354+ * zelf. doc . write ( ) = doc;
355+ } else {
356+ // For property subclass, set __doc__ as an attribute
357+ let doc_to_set = doc. unwrap_or_else ( || vm. ctx . none ( ) ) ;
358+ match zelf. as_object ( ) . set_attr ( "__doc__" , doc_to_set, vm) {
359+ Ok ( ( ) ) => { }
360+ Err ( e) if !getter_doc && e. class ( ) . is ( vm. ctx . exceptions . attribute_error ) => {
361+ // Silently ignore AttributeError for backwards compatibility
362+ // (only when not using getter_doc)
363+ }
364+ Err ( e) => return Err ( e) ,
365+ }
366+ }
367+
333368 zelf. getter_doc . store ( getter_doc, Ordering :: Relaxed ) ;
334369
335370 Ok ( ( ) )
0 commit comments