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

1 from functools import cached_property

2 from mixinforge import CacheablePropertiesMixin

3 import pytest

4

5 class 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

21 def 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

33 def 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

51 def 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

62 def 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

72 def 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

82 def 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

90 def 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

101 def 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