@@ -651,3 +651,73 @@ def test_check_shape(target, test_shape):
651651 with pytest .raises (ValueError ,
652652 match = error_pattern ):
653653 cbook ._check_shape (target , aardvark = data )
654+
655+
656+ def test_setattr_cm ():
657+ class A :
658+
659+ cls_level = object ()
660+ override = object ()
661+ def __init__ (self ):
662+ self .aardvark = 'aardvark'
663+ self .override = 'override'
664+ self ._p = 'p'
665+
666+ def meth (self ):
667+ ...
668+
669+ @property
670+ def prop (self ):
671+ return self ._p
672+
673+ @prop .setter
674+ def prop (self , val ):
675+ self ._p = val
676+
677+ class B (A ):
678+ ...
679+
680+ other = A ()
681+
682+ def verify_pre_post_state (obj ):
683+ # When you access a Python method the function is bound
684+ # to the object at access time so you get a new instance
685+ # of MethodType every time.
686+ #
687+ # https://docs.python.org/3/howto/descriptor.html#functions-and-methods
688+ assert obj .meth is not obj .meth
689+ # normal attribute should give you back the same instance every time
690+ assert obj .aardvark is obj .aardvark
691+ assert a .aardvark == 'aardvark'
692+ # and our property happens to give the same instance every time
693+ assert obj .prop is obj .prop
694+ assert obj .cls_level is A .cls_level
695+ assert obj .override == 'override'
696+ assert not hasattr (obj , 'extra' )
697+ assert obj .prop == 'p'
698+ assert obj .monkey == other .meth
699+
700+ a = B ()
701+
702+ a .monkey = other .meth
703+ verify_pre_post_state (a )
704+ with cbook ._setattr_cm (
705+ a , prop = 'squirrel' ,
706+ aardvark = 'moose' , meth = lambda : None ,
707+ override = 'boo' , extra = 'extra' ,
708+ monkey = lambda : None ):
709+ # because we have set a lambda, it is normal attribute access
710+ # and the same every time
711+ assert a .meth is a .meth
712+ assert a .aardvark is a .aardvark
713+ assert a .aardvark == 'moose'
714+ assert a .override == 'boo'
715+ assert a .extra == 'extra'
716+ assert a .prop == 'squirrel'
717+ assert a .monkey != other .meth
718+
719+ verify_pre_post_state (a )
720+
721+ with pytest .raises (ValueError ):
722+ with cbook ._setattr_cm (a , cls_level = 'bob' ):
723+ pass
0 commit comments