Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/openpyxl/descriptors/base.py: 75%

150 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1# Copyright (c) 2010-2022 openpyxl 

2 

3 

4""" 

5Based on Python Cookbook 3rd Edition, 8.13 

6http://chimera.labs.oreilly.com/books/1230000000393/ch08.html#_discussiuncion_130 

7""" 

8 

9import datetime 

10import re 

11 

12from openpyxl.utils.datetime import from_ISO8601 

13 

14from .namespace import namespaced 

15 

16class Descriptor(object): 

17 

18 def __init__(self, name=None, **kw): 

19 self.name = name 

20 for k, v in kw.items(): 

21 setattr(self, k, v) 

22 

23 def __set__(self, instance, value): 

24 instance.__dict__[self.name] = value 

25 

26 

27class Typed(Descriptor): 

28 """Values must of a particular type""" 

29 

30 expected_type = type(None) 

31 allow_none = False 

32 nested = False 

33 

34 def __init__(self, *args, **kw): 

35 super(Typed, self).__init__(*args, **kw) 

36 self.__doc__ = "Values must be of type {0}".format(self.expected_type) 

37 

38 def __set__(self, instance, value): 

39 if not isinstance(value, self.expected_type): 

40 if (not self.allow_none 40 ↛ 42line 40 didn't jump to line 42, because the condition on line 40 was never true

41 or (self.allow_none and value is not None)): 

42 raise TypeError('expected ' + str(self.expected_type)) 

43 super(Typed, self).__set__(instance, value) 

44 

45 def __repr__(self): 

46 return self.__doc__ 

47 

48 

49def _convert(expected_type, value): 

50 """ 

51 Check value is of or can be converted to expected type. 

52 """ 

53 if not isinstance(value, expected_type): 

54 try: 

55 value = expected_type(value) 

56 except: 

57 raise TypeError('expected ' + str(expected_type)) 

58 return value 

59 

60 

61class Convertible(Typed): 

62 """Values must be convertible to a particular type""" 

63 

64 def __set__(self, instance, value): 

65 if ((self.allow_none and value is not None) 

66 or not self.allow_none): 

67 value = _convert(self.expected_type, value) 

68 super(Convertible, self).__set__(instance, value) 

69 

70 

71class Max(Convertible): 

72 """Values must be less than a `max` value""" 

73 

74 expected_type = float 

75 allow_none = False 

76 

77 def __init__(self, **kw): 

78 if 'max' not in kw and not hasattr(self, 'max'): 78 ↛ 79line 78 didn't jump to line 79, because the condition on line 78 was never true

79 raise TypeError('missing max value') 

80 super(Max, self).__init__(**kw) 

81 

82 def __set__(self, instance, value): 

83 if ((self.allow_none and value is not None) 

84 or not self.allow_none): 

85 value = _convert(self.expected_type, value) 

86 if value > self.max: 86 ↛ 87line 86 didn't jump to line 87, because the condition on line 86 was never true

87 raise ValueError('Max value is {0}'.format(self.max)) 

88 super(Max, self).__set__(instance, value) 

89 

90 

91class Min(Convertible): 

92 """Values must be greater than a `min` value""" 

93 

94 expected_type = float 

95 allow_none = False 

96 

97 def __init__(self, **kw): 

98 if 'min' not in kw and not hasattr(self, 'min'): 98 ↛ 99line 98 didn't jump to line 99, because the condition on line 98 was never true

99 raise TypeError('missing min value') 

100 super(Min, self).__init__(**kw) 

101 

102 def __set__(self, instance, value): 

103 if ((self.allow_none and value is not None) 

104 or not self.allow_none): 

105 value = _convert(self.expected_type, value) 

106 if value < self.min: 106 ↛ 107line 106 didn't jump to line 107, because the condition on line 106 was never true

107 raise ValueError('Min value is {0}'.format(self.min)) 

108 super(Min, self).__set__(instance, value) 

109 

110 

111class MinMax(Min, Max): 

112 """Values must be greater than `min` value and less than a `max` one""" 

113 pass 

114 

115 

116class Set(Descriptor): 

117 """Value can only be from a set of know values""" 

118 

119 def __init__(self, name=None, **kw): 

120 if not 'values' in kw: 120 ↛ 121line 120 didn't jump to line 121, because the condition on line 120 was never true

121 raise TypeError("missing set of values") 

122 kw['values'] = set(kw['values']) 

123 super(Set, self).__init__(name, **kw) 

124 self.__doc__ = "Value must be one of {0}".format(self.values) 

125 

126 def __set__(self, instance, value): 

127 if value not in self.values: 127 ↛ 128line 127 didn't jump to line 128, because the condition on line 127 was never true

128 raise ValueError(self.__doc__) 

129 super(Set, self).__set__(instance, value) 

130 

131 

132class NoneSet(Set): 

133 

134 """'none' will be treated as None""" 

135 

136 def __init__(self, name=None, **kw): 

137 super(NoneSet, self).__init__(name, **kw) 

138 self.values.add(None) 

139 

140 def __set__(self, instance, value): 

141 if value == 'none': 141 ↛ 142line 141 didn't jump to line 142, because the condition on line 141 was never true

142 value = None 

143 super(NoneSet, self).__set__(instance, value) 

144 

145 

146class Integer(Convertible): 

147 

148 expected_type = int 

149 

150 

151class Float(Convertible): 

152 

153 expected_type = float 

154 

155 

156class Bool(Convertible): 

157 

158 expected_type = bool 

159 

160 def __set__(self, instance, value): 

161 if isinstance(value, str): 

162 if value in ('false', 'f', '0'): 

163 value = False 

164 super(Bool, self).__set__(instance, value) 

165 

166 

167class String(Typed): 

168 

169 expected_type = str 

170 

171 

172class Text(String, Convertible): 

173 

174 pass 

175 

176 

177class ASCII(Typed): 

178 

179 expected_type = bytes 

180 

181 

182class Tuple(Typed): 

183 

184 expected_type = tuple 

185 

186 

187class Length(Descriptor): 

188 

189 def __init__(self, name=None, **kw): 

190 if "length" not in kw: 

191 raise TypeError("value length must be supplied") 

192 super(Length, self).__init__(**kw) 

193 

194 

195 def __set__(self, instance, value): 

196 if len(value) != self.length: 

197 raise ValueError("Value must be length {0}".format(self.length)) 

198 super(Length, self).__set__(instance, value) 

199 

200 

201class Default(Typed): 

202 """ 

203 When called returns an instance of the expected type. 

204 Additional default values can be passed in to the descriptor 

205 """ 

206 

207 def __init__(self, name=None, **kw): 

208 if "defaults" not in kw: 

209 kw['defaults'] = {} 

210 super(Default, self).__init__(**kw) 

211 

212 def __call__(self): 

213 return self.expected_type() 

214 

215 

216class Alias(Descriptor): 

217 """ 

218 Aliases can be used when either the desired attribute name is not allowed 

219 or confusing in Python (eg. "type") or a more descriptve name is desired 

220 (eg. "underline" for "u") 

221 """ 

222 

223 def __init__(self, alias): 

224 self.alias = alias 

225 

226 def __set__(self, instance, value): 

227 setattr(instance, self.alias, value) 

228 

229 def __get__(self, instance, cls): 

230 return getattr(instance, self.alias) 

231 

232 

233class MatchPattern(Descriptor): 

234 """Values must match a regex pattern """ 

235 allow_none = False 

236 

237 def __init__(self, name=None, **kw): 

238 if 'pattern' not in kw and not hasattr(self, 'pattern'): 238 ↛ 239line 238 didn't jump to line 239, because the condition on line 238 was never true

239 raise TypeError('missing pattern value') 

240 

241 super(MatchPattern, self).__init__(name, **kw) 

242 self.test_pattern = re.compile(self.pattern, re.VERBOSE) 

243 

244 

245 def __set__(self, instance, value): 

246 

247 if value is None and not self.allow_none: 

248 raise ValueError("Value must not be none") 

249 

250 if ((self.allow_none and value is not None) 

251 or not self.allow_none): 

252 if not self.test_pattern.match(value): 

253 raise ValueError('Value does not match pattern {0}'.format(self.pattern)) 

254 

255 super(MatchPattern, self).__set__(instance, value) 

256 

257 

258class DateTime(Typed): 

259 

260 expected_type = datetime.datetime 

261 

262 def __set__(self, instance, value): 

263 if value is not None and isinstance(value, str): 

264 try: 

265 value = from_ISO8601(value) 

266 except ValueError: 

267 raise ValueError("Value must be ISO datetime format") 

268 super(DateTime, self).__set__(instance, value)