Coverage for /home/runner/work/viur-core/viur-core/viur/src/viur/core/bones/boolean.py: 27%

35 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-03 13:41 +0000

1import typing as t 

2 

3from viur.core import conf, db, utils 

4from viur.core.bones.base import BaseBone 

5 

6 

7class BooleanBone(BaseBone): 

8 """ 

9 Represents a boolean data type, which can have two possible values: `True` or `False`. 

10 BooleanBones cannot be defined as `multiple=True`. 

11 

12 :param defaultValue: The default value of the `BooleanBone` instance. Defaults to `False`. 

13 :type defaultValue: bool 

14 :raises ValueError: If the `defaultValue` is not a boolean value (`True` or `False`). 

15 """ 

16 type = "bool" 

17 

18 def __init__( 

19 self, 

20 *, 

21 defaultValue: bool | list[bool] | dict[str, list[bool] | bool] = None, 

22 **kwargs 

23 ): 

24 if defaultValue is not None: 

25 # We have given an explicit defaultValue and maybe a complex structure 

26 if not (kwargs.get("multiple") or kwargs.get("languages")) and not (isinstance(defaultValue, bool)): 

27 raise TypeError("Only 'True', 'False' or 'None' can be provided as BooleanBone defaultValue") 

28 # TODO: missing validation for complex types, but in other bones too 

29 

30 super().__init__(defaultValue=defaultValue, **kwargs) 

31 

32 # Disallow creation of BooleanBone(multiple=True) 

33 if self.multiple: 

34 raise ValueError("BooleanBone cannot be multiple") 

35 

36 def singleValueFromClient(self, value, skel, bone_name, client_data): 

37 return utils.parse.bool(value, conf.bone_boolean_str2true), None 

38 

39 def getEmptyValue(self): 

40 """ 

41 Returns the empty value of the `BooleanBone` class, which is `False`. 

42 

43 :return: The empty value of the `BooleanBone` class (`False`). 

44 :rtype: bool 

45 """ 

46 return False 

47 

48 def isEmpty(self, value: t.Any): 

49 """ 

50 Checks if the given boolean value is empty. 

51 

52 :param value: The boolean value to be checked. 

53 :return: `True` if the boolean value is empty (i.e., equal to the empty value of the `BooleanBone` class), \ 

54 `False` otherwise. 

55 :rtype: bool 

56 """ 

57 if value is self.getEmptyValue(): 

58 return True 

59 return not bool(value) 

60 

61 def refresh(self, skel: 'viur.core.skeleton.SkeletonInstance', boneName: str) -> None: 

62 """ 

63 Inverse of serialize. Evaluates whats 

64 read from the datastore and populates 

65 this bone accordingly. 

66 

67 :param name: The property-name this bone has in its Skeleton (not the description!) 

68 """ 

69 if not isinstance(skel[boneName], bool): 

70 skel[boneName] = utils.parse.bool(skel[boneName], conf.bone_boolean_str2true) 

71 

72 def setBoneValue( 

73 self, 

74 skel: 'SkeletonInstance', 

75 boneName: str, 

76 value: t.Any, 

77 append: bool, 

78 language: None | str = None 

79 ) -> bool: 

80 """ 

81 Sets the value of the bone to the provided 'value'. 

82 Sanity checks are performed; if the value is invalid, the bone value will revert to its original 

83 (default) value and the function will return False. 

84 

85 :param skel: Dictionary with the current values from the skeleton the bone belongs to 

86 :param boneName: The name of the bone that should be modified 

87 :param value: The value that should be assigned. Its type depends on the type of the bone 

88 :param append: If True, the given value will be appended to the existing bone values instead of 

89 replacing them. Only supported on bones with multiple=True 

90 :param language: Optional, the language of the value if the bone is language-aware 

91 :return: A boolean indicating whether the operation succeeded or not 

92 :rtype: bool 

93 """ 

94 if append: 

95 raise ValueError(f"append is not possible on {self.type} bones") 

96 skel[boneName] = utils.parse.bool(value) 

97 return True 

98 

99 def singleValueSerialize(self, value, skel: 'SkeletonInstance', name: str, parentIndexed: bool): 

100 """ 

101 Serializes a single value of the bone for storage in the database. 

102 

103 Derived bone classes should overwrite this method to implement their own logic for serializing single 

104 values. 

105 The serialized value should be suitable for storage in the database. 

106 """ 

107 return utils.parse.bool(value) 

108 

109 def buildDBFilter( 

110 self, 

111 name: str, 

112 skel: 'viur.core.skeleton.SkeletonInstance', 

113 dbFilter: db.Query, 

114 rawFilter: dict, 

115 prefix: t.Optional[str] = None 

116 ) -> db.Query: 

117 """ 

118 Builds a database filter based on the boolean value. 

119 

120 :param name: The name of the `BooleanBone` instance. 

121 :param skel: The `SkeletonInstance` object representing the data of the current entity. 

122 :param dbFilter: The `Query` object representing the current database filter. 

123 :param rawFilter: The dictionary representing the raw filter data received from the client. 

124 :param prefix: A prefix to be added to the property name in the database filter. 

125 :return: The updated `Query` object representing the updated database filter. 

126 :rtype: google.cloud.ndb.query.Query 

127 """ 

128 if name in rawFilter: 

129 val = utils.parse.bool(rawFilter[name], conf.bone_boolean_str2true) 

130 return super().buildDBFilter(name, skel, dbFilter, {name: val}, prefix=prefix) 

131 

132 return dbFilter