Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/attr/converters.py: 25%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

57 statements  

1# SPDX-License-Identifier: MIT 

2 

3""" 

4Commonly useful converters. 

5""" 

6 

7import typing 

8 

9from ._compat import _AnnotationExtractor 

10from ._make import NOTHING, Converter, Factory, pipe 

11 

12 

13__all__ = [ 

14 "default_if_none", 

15 "optional", 

16 "pipe", 

17 "to_bool", 

18] 

19 

20 

21def optional(converter): 

22 """ 

23 A converter that allows an attribute to be optional. An optional attribute 

24 is one which can be set to `None`. 

25 

26 Type annotations will be inferred from the wrapped converter's, if it has 

27 any. 

28 

29 Args: 

30 converter (typing.Callable): 

31 the converter that is used for non-`None` values. 

32 

33 .. versionadded:: 17.1.0 

34 """ 

35 

36 if isinstance(converter, Converter): 

37 

38 def optional_converter(val, inst, field): 

39 if val is None: 

40 return None 

41 return converter(val, inst, field) 

42 

43 else: 

44 

45 def optional_converter(val): 

46 if val is None: 

47 return None 

48 return converter(val) 

49 

50 xtr = _AnnotationExtractor(converter) 

51 

52 t = xtr.get_first_param_type() 

53 if t: 

54 optional_converter.__annotations__["val"] = typing.Optional[t] 

55 

56 rt = xtr.get_return_type() 

57 if rt: 

58 optional_converter.__annotations__["return"] = typing.Optional[rt] 

59 

60 if isinstance(converter, Converter): 

61 return Converter(optional_converter, takes_self=True, takes_field=True) 

62 

63 return optional_converter 

64 

65 

66def default_if_none(default=NOTHING, factory=None): 

67 """ 

68 A converter that allows to replace `None` values by *default* or the result 

69 of *factory*. 

70 

71 Args: 

72 default: 

73 Value to be used if `None` is passed. Passing an instance of 

74 `attrs.Factory` is supported, however the ``takes_self`` option is 

75 *not*. 

76 

77 factory (typing.Callable): 

78 A callable that takes no parameters whose result is used if `None` 

79 is passed. 

80 

81 Raises: 

82 TypeError: If **neither** *default* or *factory* is passed. 

83 

84 TypeError: If **both** *default* and *factory* are passed. 

85 

86 ValueError: 

87 If an instance of `attrs.Factory` is passed with 

88 ``takes_self=True``. 

89 

90 .. versionadded:: 18.2.0 

91 """ 

92 if default is NOTHING and factory is None: 

93 msg = "Must pass either `default` or `factory`." 

94 raise TypeError(msg) 

95 

96 if default is not NOTHING and factory is not None: 

97 msg = "Must pass either `default` or `factory` but not both." 

98 raise TypeError(msg) 

99 

100 if factory is not None: 

101 default = Factory(factory) 

102 

103 if isinstance(default, Factory): 

104 if default.takes_self: 

105 msg = "`takes_self` is not supported by default_if_none." 

106 raise ValueError(msg) 

107 

108 def default_if_none_converter(val): 

109 if val is not None: 

110 return val 

111 

112 return default.factory() 

113 

114 else: 

115 

116 def default_if_none_converter(val): 

117 if val is not None: 

118 return val 

119 

120 return default 

121 

122 return default_if_none_converter 

123 

124 

125def to_bool(val): 

126 """ 

127 Convert "boolean" strings (for example, from environment variables) to real 

128 booleans. 

129 

130 Values mapping to `True`: 

131 

132 - ``True`` 

133 - ``"true"`` / ``"t"`` 

134 - ``"yes"`` / ``"y"`` 

135 - ``"on"`` 

136 - ``"1"`` 

137 - ``1`` 

138 

139 Values mapping to `False`: 

140 

141 - ``False`` 

142 - ``"false"`` / ``"f"`` 

143 - ``"no"`` / ``"n"`` 

144 - ``"off"`` 

145 - ``"0"`` 

146 - ``0`` 

147 

148 Raises: 

149 ValueError: For any other value. 

150 

151 .. versionadded:: 21.3.0 

152 """ 

153 if isinstance(val, str): 

154 val = val.lower() 

155 

156 if val in (True, "true", "t", "yes", "y", "on", "1", 1): 

157 return True 

158 if val in (False, "false", "f", "no", "n", "off", "0", 0): 

159 return False 

160 

161 msg = f"Cannot convert value to bool: {val!r}" 

162 raise ValueError(msg)