@@ -3328,35 +3328,104 @@ def test_non_frozen_normal_derived(self):
33283328 class D :
33293329 x : int
33303330 y : int = 10
3331+ z : int = 0
3332+
3333+ @property
3334+ def readonly (self ) -> int :
3335+ return self .x
3336+
3337+ @property
3338+ def prop (self ) -> int :
3339+ return self .z
3340+
3341+ @prop .setter
3342+ def prop (self , val : int ) -> None :
3343+ object .__setattr__ (self , 'z' , val )
3344+
3345+ @prop .deleter
3346+ def prop (self ) -> None :
3347+ object .__setattr__ (self , 'z' , 0 )
3348+
3349+ d = D (5 )
3350+ self .assertEqual (d .x , 5 )
3351+ self .assertEqual (d .y , 10 )
3352+ self .assertEqual (d .z , 0 )
3353+ self .assertEqual (d .readonly , 5 )
3354+ self .assertEqual (d .prop , 0 )
3355+
3356+ with self .assertRaises (FrozenInstanceError ):
3357+ d .x = 5
3358+ with self .assertRaises (FrozenInstanceError ):
3359+ d .readonly = 5
3360+ with self .assertRaises (FrozenInstanceError ):
3361+ d .z = 5
3362+ with self .assertRaises (FrozenInstanceError ):
3363+ d .prop = 5
3364+ with self .assertRaises (FrozenInstanceError ):
3365+ del d .prop
3366+
3367+ self .assertEqual (d .x , 5 )
3368+ self .assertEqual (d .y , 10 )
3369+ self .assertEqual (d .z , 0 )
3370+ self .assertEqual (d .readonly , 5 )
3371+ self .assertEqual (d .prop , 0 )
33313372
33323373 class S (D ):
33333374 pass
33343375
33353376 s = S (3 )
33363377 self .assertEqual (s .x , 3 )
33373378 self .assertEqual (s .y , 10 )
3379+ self .assertEqual (s .z , 0 )
3380+ self .assertEqual (s .readonly , 3 )
3381+ self .assertEqual (s .prop , 0 )
3382+ # Can set new attrs:
33383383 s .cached = True
3384+ # Can mutate them:
3385+ s .cached = False
3386+
3387+ # Can also change writable properties:
3388+ with self .assertRaises (AttributeError ) as cm :
3389+ s .readonly = 5
3390+ self .assertNotIsInstance (cm .exception , FrozenInstanceError )
3391+ s .prop = 1
3392+ self .assertEqual (s .x , 3 )
3393+ self .assertEqual (s .readonly , 3 )
3394+ self .assertEqual (s .prop , 1 )
3395+ self .assertEqual (s .z , 1 )
33393396
33403397 # But can't change the frozen attributes.
33413398 with self .assertRaises (FrozenInstanceError ):
33423399 s .x = 5
33433400 with self .assertRaises (FrozenInstanceError ):
33443401 s .y = 5
3402+ with self .assertRaises (FrozenInstanceError ):
3403+ s .z = 5
33453404 self .assertEqual (s .x , 3 )
33463405 self .assertEqual (s .y , 10 )
3347- self .assertEqual (s .cached , True )
3406+ self .assertEqual (s .z , 1 )
3407+ self .assertIs (s .cached , False )
33483408
33493409 with self .assertRaises (FrozenInstanceError ):
33503410 del s .x
33513411 self .assertEqual (s .x , 3 )
33523412 with self .assertRaises (FrozenInstanceError ):
33533413 del s .y
33543414 self .assertEqual (s .y , 10 )
3415+ with self .assertRaises (AttributeError ) as cm :
3416+ del s .readonly
3417+ self .assertNotIsInstance (cm .exception , FrozenInstanceError )
3418+ self .assertEqual (s .x , 3 )
3419+ self .assertEqual (s .readonly , 3 )
33553420 del s .cached
33563421 self .assertNotHasAttr (s , 'cached' )
33573422 with self .assertRaises (AttributeError ) as cm :
33583423 del s .cached
33593424 self .assertNotIsInstance (cm .exception , FrozenInstanceError )
3425+ del s .prop
3426+ self .assertEqual (s .z , 0 )
3427+ self .assertEqual (s .prop , 0 )
3428+ del s .prop
33603429
33613430 def test_non_frozen_normal_derived_from_empty_frozen (self ):
33623431 @dataclass (frozen = True )
0 commit comments