Coverage for heritrace / utils / datatypes_validation.py: 99%

243 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-21 12:56 +0000

1# SPDX-FileCopyrightText: 2025 Arcangelo Massari <arcangelo.massari@unibo.it> 

2# 

3# SPDX-License-Identifier: ISC 

4 

5import base64 

6import re 

7from datetime import datetime 

8from urllib.parse import urlparse 

9 

10 

11def validate_string(value): 

12 try: 

13 value = str(value) 

14 return isinstance(value, str) 

15 except ValueError: 

16 return False 

17 

18 

19def validate_normalizedString(value): 

20 try: 

21 return "\n" not in value and "\r" not in value and "\t" not in value 

22 except Exception: 

23 return False 

24 

25 

26def validate_integer(value): 

27 try: 

28 int(value) 

29 return True 

30 except ValueError: 

31 return False 

32 

33 

34def validate_positive_integer(value): 

35 try: 

36 return int(value) > 0 

37 except ValueError: 

38 return False 

39 

40 

41def validate_negative_integer(value): 

42 try: 

43 return int(value) < 0 

44 except ValueError: 

45 return False 

46 

47 

48def validate_non_negative_integer(value): 

49 try: 

50 return int(value) >= 0 

51 except ValueError: 

52 return False 

53 

54 

55def validate_non_positive_integer(value): 

56 try: 

57 return int(value) <= 0 

58 except ValueError: 

59 return False 

60 

61 

62def validate_byte(value): 

63 try: 

64 val = int(value) 

65 return -128 <= val <= 127 

66 except ValueError: 

67 return False 

68 

69 

70def validate_short(value): 

71 try: 

72 val = int(value) 

73 return -32_768 <= val <= 32_767 

74 except ValueError: 

75 return False 

76 

77 

78def validate_long(value): 

79 try: 

80 val = int(value) 

81 return -2_147_483_648 <= val <= 2_147_483_647 

82 except ValueError: 

83 return False 

84 

85 

86def validate_unsigned_byte(value): 

87 try: 

88 val = int(value) 

89 return 0 <= val <= 255 

90 except ValueError: 

91 return False 

92 

93 

94def validate_unsigned_short(value): 

95 try: 

96 val = int(value) 

97 return 0 <= val <= 65_535 

98 except ValueError: 

99 return False 

100 

101 

102def validate_unsigned_long(value): 

103 try: 

104 val = int(value) 

105 return 0 <= val <= 4_294_967_295 

106 except ValueError: 

107 return False 

108 

109 

110def validate_unsigned_int(value): 

111 try: 

112 val = int(value) 

113 return 0 <= val <= 4_294_967_295 

114 except ValueError: 

115 return False 

116 

117 

118def validate_float(value): 

119 try: 

120 float(value) 

121 return True 

122 except ValueError: 

123 return False 

124 

125 

126def validate_double(value): 

127 try: 

128 float(value) 

129 return True 

130 except ValueError: 

131 return False 

132 

133 

134def validate_decimal(value): 

135 try: 

136 float(value) 

137 return True 

138 except ValueError: 

139 return False 

140 

141 

142def validate_duration(value): 

143 try: 

144 duration_pattern = re.compile( 

145 r"^P(?=\d|T\d)(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+?)?)S)?)?$" 

146 ) 

147 return bool(duration_pattern.match(value)) 

148 except Exception: 

149 return False 

150 

151 

152def validate_dayTimeDuration(value): 

153 try: 

154 dayTimeDuration_pattern = re.compile( 

155 r"^P(?:\d+D)?(?:T(?:\d+H)?(?:\d+M)?(?:\d+(?:\.\d+)?S)?)?$" 

156 ) 

157 return bool(dayTimeDuration_pattern.match(value)) 

158 except Exception: 

159 return False 

160 

161 

162def validate_yearMonthDuration(value): 

163 try: 

164 yearMonthDuration_pattern = re.compile(r"^P(?:\d+Y)?(?:\d+M)?$") 

165 return bool(yearMonthDuration_pattern.match(value)) 

166 except Exception: 

167 return False 

168 

169 

170def validate_gYearMonth(value): 

171 try: 

172 pattern = re.compile(r"^(\d{4})-(\d{2})$") 

173 match = pattern.match(value) 

174 if match: 

175 year, month = map(int, match.groups()) 

176 return year <= 9999 and 1 <= month <= 12 

177 return False 

178 except Exception: 

179 return False 

180 

181 

182def validate_gYear(value): 

183 try: 

184 pattern = re.compile(r"^\d{4}$") 

185 if pattern.match(value): 

186 year = int(value) 

187 return 1582 <= year <= 9999 

188 return False 

189 except Exception: 

190 return False 

191 

192 

193def validate_dateTime(value): 

194 try: 

195 pattern = re.compile( 

196 r"^-?\d{4,}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?$" 

197 ) 

198 return bool(pattern.match(value)) 

199 except Exception: 

200 return False 

201 

202 

203def validate_dateTimeStamp(value): 

204 try: 

205 pattern = re.compile( 

206 r"^-?\d{4,}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(Z|[+-]\d{2}:\d{2})$" 

207 ) 

208 return bool(pattern.match(value)) 

209 except Exception: 

210 return False 

211 

212 

213def validate_date(value): 

214 try: 

215 datetime.strptime(value, "%Y-%m-%d").date() 

216 return True 

217 except ValueError: 

218 return False 

219 

220 

221def validate_time(value): 

222 try: 

223 return bool(re.match(r"^([01]\d|2[0-3]):?([0-5]\d):?([0-5]\d)$", value)) 

224 except Exception: 

225 return False 

226 

227 

228def validate_hour(value): 

229 try: 

230 return 0 <= int(value) <= 23 

231 except ValueError: 

232 return False 

233 

234 

235def validate_minute(value): 

236 try: 

237 return 0 <= int(value) <= 59 

238 except ValueError: 

239 return False 

240 

241 

242def validate_second(value): 

243 try: 

244 return 0 <= float(value) < 60 

245 except ValueError: 

246 return False 

247 

248 

249def validate_timezoneOffset(value): 

250 try: 

251 timezoneOffset_pattern = re.compile(r"^[+-]\d{2}:\d{2}$") 

252 return bool(timezoneOffset_pattern.match(value)) 

253 except Exception: 

254 return False 

255 

256 

257def validate_boolean(value): 

258 try: 

259 return value.lower() in ["true", "false"] 

260 except Exception: 

261 return False 

262 

263 

264def validate_hexBinary(value): 

265 try: 

266 bytes.fromhex(value) 

267 return True 

268 except ValueError: 

269 return False 

270 

271 

272def validate_base64Binary(value): 

273 try: 

274 base64.b64decode(value) 

275 return True 

276 except ValueError: 

277 return False 

278 

279 

280def validate_url(value): 

281 try: 

282 result = urlparse(value) 

283 return all([result.scheme, result.netloc]) 

284 except ValueError: 

285 return False 

286 

287 

288def validate_QName(value): 

289 try: 

290 QName_pattern = re.compile(r"^(?:[a-zA-Z_][\w.-]*:)?[a-zA-Z_][\w.-]*$") 

291 return bool(QName_pattern.match(value)) 

292 except Exception: 

293 return False 

294 

295 

296def validate_ENTITIES(value): 

297 try: 

298 entities = value.split() 

299 return all(re.match(r"^[a-zA-Z_][\w.-]*$", entity) for entity in entities) 

300 except Exception: 

301 return False 

302 

303 

304validate_ENTITY = validate_ENTITIES 

305 

306 

307def validate_ID(value): 

308 try: 

309 return re.match(r"^[a-zA-Z_][\w.-]*$", value) is not None 

310 except Exception: 

311 return False 

312 

313 

314validate_IDREF = validate_ID 

315validate_IDREFS = validate_ENTITIES 

316validate_NCName = validate_ID 

317 

318 

319def validate_NMTOKEN(value): 

320 try: 

321 return re.match(r"^[\w.-]+$", value) is not None 

322 except Exception: 

323 return False 

324 

325 

326def validate_NMTOKENS(value): 

327 try: 

328 tokens = value.split() 

329 return all(re.match(r"^[\w.-]+$", token) for token in tokens) 

330 except Exception: 

331 return False 

332 

333 

334validate_NOTATION = validate_QName 

335 

336 

337def validate_Name(value): 

338 try: 

339 return re.match(r"^[a-zA-Z_:][\w.-]*$", value) is not None 

340 except Exception: 

341 return False