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

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

49 statements  

1# SPDX-License-Identifier: MIT 

2 

3""" 

4Commonly useful converters. 

5""" 

6 

7 

8import typing 

9 

10from ._compat import _AnnotationExtractor 

11from ._make import NOTHING, Factory, pipe 

12 

13 

14__all__ = [ 

15 "default_if_none", 

16 "optional", 

17 "pipe", 

18 "to_bool", 

19] 

20 

21 

22def optional(converter): 

23 """ 

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

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

26 

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

28 any. 

29 

30 Args: 

31 converter (typing.Callable): 

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

33 

34 .. versionadded:: 17.1.0 

35 """ 

36 

37 def optional_converter(val): 

38 if val is None: 

39 return None 

40 return converter(val) 

41 

42 xtr = _AnnotationExtractor(converter) 

43 

44 t = xtr.get_first_param_type() 

45 if t: 

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

47 

48 rt = xtr.get_return_type() 

49 if rt: 

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

51 

52 return optional_converter 

53 

54 

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

56 """ 

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

58 of *factory*. 

59 

60 Args: 

61 default: 

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

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

64 *not*. 

65 

66 factory (typing.Callable): 

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

68 is passed. 

69 

70 Raises: 

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

72 

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

74 

75 ValueError: 

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

77 ``takes_self=True``. 

78 

79 .. versionadded:: 18.2.0 

80 """ 

81 if default is NOTHING and factory is None: 

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

83 raise TypeError(msg) 

84 

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

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

87 raise TypeError(msg) 

88 

89 if factory is not None: 

90 default = Factory(factory) 

91 

92 if isinstance(default, Factory): 

93 if default.takes_self: 

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

95 raise ValueError(msg) 

96 

97 def default_if_none_converter(val): 

98 if val is not None: 

99 return val 

100 

101 return default.factory() 

102 

103 else: 

104 

105 def default_if_none_converter(val): 

106 if val is not None: 

107 return val 

108 

109 return default 

110 

111 return default_if_none_converter 

112 

113 

114def to_bool(val): 

115 """ 

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

117 booleans. 

118 

119 Values mapping to `True`: 

120 

121 - ``True`` 

122 - ``"true"`` / ``"t"`` 

123 - ``"yes"`` / ``"y"`` 

124 - ``"on"`` 

125 - ``"1"`` 

126 - ``1`` 

127 

128 Values mapping to `False`: 

129 

130 - ``False`` 

131 - ``"false"`` / ``"f"`` 

132 - ``"no"`` / ``"n"`` 

133 - ``"off"`` 

134 - ``"0"`` 

135 - ``0`` 

136 

137 Raises: 

138 ValueError: For any other value. 

139 

140 .. versionadded:: 21.3.0 

141 """ 

142 if isinstance(val, str): 

143 val = val.lower() 

144 

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

146 return True 

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

148 return False 

149 

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

151 raise ValueError(msg)