Coverage for Users / vladimirpavlov / PycharmProjects / parameterizable / tests / test_cacheable_properties_mixin_set.py: 95%

74 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-01 16:37 -0600

1from functools import cached_property 

2from mixinforge import CacheablePropertiesMixin 

3import pytest 

4 

5class A(CacheablePropertiesMixin): 

6 @cached_property 

7 def x(self): 

8 return 1 

9 

10 @cached_property 

11 def y(self): 

12 return 2 

13 

14 @property 

15 def z(self): 

16 return 3 

17 

18 def regular_method(self): 

19 pass 

20 

21def test_set_cached_values_basic(): 

22 """Test that _set_cached_values() sets values for cached properties.""" 

23 a = A() 

24 

25 a._set_cached_properties(x=100, y=200) 

26 

27 # Values should be cached and accessible without computation 

28 assert a.__dict__["x"] == 100 

29 assert a.__dict__["y"] == 200 

30 assert a.x == 100 

31 assert a.y == 200 

32 

33def test_set_cached_values_bypass_computation(): 

34 """Test that _set_cached_values() bypasses property computation.""" 

35 class Counter(CacheablePropertiesMixin): 

36 def __init__(self): 

37 self.compute_count = 0 

38 

39 @cached_property 

40 def computed(self): 

41 self.compute_count += 1 

42 return 42 

43 

44 c = Counter() 

45 c._set_cached_properties(computed=999) 

46 

47 # Access the property - should return set value, not computed 

48 assert c.computed == 999 

49 assert c.compute_count == 0 # Never computed 

50 

51def test_set_cached_values_invalid_name(): 

52 """Test that _set_cached_values() raises ValueError for invalid names.""" 

53 a = A() 

54 

55 with pytest.raises(ValueError, match="non-cached properties"): 

56 a._set_cached_properties(invalid_name=123) 

57 

58 # Regular property should also be rejected 

59 with pytest.raises(ValueError, match="non-cached properties"): 

60 a._set_cached_properties(z=456) 

61 

62def test_set_cached_values_partial(): 

63 """Test that _set_cached_values() can set subset of cached properties.""" 

64 a = A() 

65 

66 a._set_cached_properties(x=50) 

67 

68 assert a.x == 50 

69 assert "y" not in a.__dict__ 

70 assert a.y == 2 # y computes normally 

71 

72def test_set_cached_values_overwrite(): 

73 """Test that _set_cached_values() can overwrite existing cached values.""" 

74 a = A() 

75 _ = a.x # Cache original value 

76 assert a.x == 1 

77 

78 a._set_cached_properties(x=999) 

79 

80 assert a.x == 999 

81 

82def test_set_cached_values_empty(): 

83 """Test that _set_cached_values() with no arguments is safe.""" 

84 a = A() 

85 

86 a._set_cached_properties() # Should not raise 

87 

88 assert a._get_all_cached_properties() == {} 

89 

90def test_set_cached_values_multiple_invalid(): 

91 """Test that error message includes all invalid property names.""" 

92 a = A() 

93 

94 with pytest.raises(ValueError) as exc_info: 

95 a._set_cached_properties(invalid1=1, invalid2=2, x=3) 

96 

97 error_msg = str(exc_info.value) 

98 assert "invalid1" in error_msg 

99 assert "invalid2" in error_msg 

100 

101def test_get_set_cached_values_roundtrip(): 

102 """Test that get/set cached values work together for state preservation.""" 

103 a = A() 

104 # Cache some values 

105 _ = a.x 

106 _ = a.y 

107 

108 # Save cached state 

109 saved_values = a._get_all_cached_properties() 

110 

111 # Invalidate cache 

112 a._invalidate_cache() 

113 assert a._get_all_cached_properties() == {} 

114 

115 # Restore cached state 

116 a._set_cached_properties(**saved_values) 

117 

118 # Verify restoration 

119 assert a._get_all_cached_properties() == saved_values 

120 assert a.x == 1 

121 assert a.y == 2