@@ -556,6 +556,44 @@ def _make_cached_property_getattr(cached_properties, original_getattr, cls):
556556 )["__getattr__" ]
557557
558558
559+ def _closure_cells (item , seen ):
560+ """
561+ Yield closure cells for *item* and any wrapped functions it closes over.
562+ """
563+ item_id = id (item )
564+ if item_id in seen :
565+ return
566+ seen .add (item_id )
567+
568+ if isinstance (item , (classmethod , staticmethod )):
569+ item = item .__func__
570+ elif isinstance (item , property ):
571+ for accessor in (item .fget , item .fset , item .fdel ):
572+ if accessor is not None :
573+ yield from _closure_cells (accessor , seen )
574+ return
575+ elif isinstance (item , cached_property ):
576+ item = item .func
577+ elif isinstance (item , types .MethodType ):
578+ item = item .__func__
579+
580+ closure = getattr (item , "__closure__" , None )
581+ if closure :
582+ yield from closure
583+
584+ for cell in closure :
585+ try :
586+ cell_contents = cell .cell_contents
587+ except ValueError :
588+ continue
589+
590+ yield from _closure_cells (cell_contents , seen )
591+
592+ wrapped = getattr (item , "__wrapped__" , None )
593+ if wrapped is not None :
594+ yield from _closure_cells (wrapped , seen )
595+
596+
559597def _frozen_setattrs (self , name , value ):
560598 """
561599 Attached to frozen classes as __setattr__.
@@ -973,20 +1011,7 @@ def _create_slots_class(self):
9731011 for item in itertools .chain (
9741012 cls .__dict__ .values (), additional_closure_functions_to_update
9751013 ):
976- if isinstance (item , (classmethod , staticmethod )):
977- # Class- and staticmethods hide their functions inside.
978- # These might need to be rewritten as well.
979- closure_cells = getattr (item .__func__ , "__closure__" , None )
980- elif isinstance (item , property ):
981- # Workaround for property `super()` shortcut (PY3-only).
982- # There is no universal way for other descriptors.
983- closure_cells = getattr (item .fget , "__closure__" , None )
984- else :
985- closure_cells = getattr (item , "__closure__" , None )
986-
987- if not closure_cells : # Catch None or the empty list.
988- continue
989- for cell in closure_cells :
1014+ for cell in _closure_cells (item , set ()):
9901015 try :
9911016 match = cell .cell_contents is self ._cls
9921017 except ValueError : # noqa: PERF203
0 commit comments