Coverage for pydantic/types.py: 100.00%

597 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-08-15 13:26 +0000

1import abc 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

2import math 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

3import re 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

4import warnings 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

5from datetime import date 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

6from decimal import Decimal, InvalidOperation 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

7from enum import Enum 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

8from pathlib import Path 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

9from types import new_class 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

10from typing import ( 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

11 TYPE_CHECKING, 

12 Any, 

13 Callable, 

14 ClassVar, 

15 Dict, 

16 FrozenSet, 

17 List, 

18 Optional, 

19 Pattern, 

20 Set, 

21 Tuple, 

22 Type, 

23 TypeVar, 

24 Union, 

25 cast, 

26 overload, 

27) 

28from uuid import UUID 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

29from weakref import WeakSet 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

30 

31from pydantic import errors 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

32from pydantic.datetime_parse import parse_date 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

33from pydantic.utils import import_string, update_not_none 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

34from pydantic.validators import ( 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

35 bytes_validator, 

36 constr_length_validator, 

37 constr_lower, 

38 constr_strip_whitespace, 

39 constr_upper, 

40 decimal_validator, 

41 float_finite_validator, 

42 float_validator, 

43 frozenset_validator, 

44 int_validator, 

45 list_validator, 

46 number_multiple_validator, 

47 number_size_validator, 

48 path_exists_validator, 

49 path_validator, 

50 set_validator, 

51 str_validator, 

52 strict_bytes_validator, 

53 strict_float_validator, 

54 strict_int_validator, 

55 strict_str_validator, 

56) 

57 

58__all__ = [ 1akblcmdneopzqArBsCtDKLMNPQRSTUOfugvhwixjy

59 'NoneStr', 

60 'NoneBytes', 

61 'StrBytes', 

62 'NoneStrBytes', 

63 'StrictStr', 

64 'ConstrainedBytes', 

65 'conbytes', 

66 'ConstrainedList', 

67 'conlist', 

68 'ConstrainedSet', 

69 'conset', 

70 'ConstrainedFrozenSet', 

71 'confrozenset', 

72 'ConstrainedStr', 

73 'constr', 

74 'PyObject', 

75 'ConstrainedInt', 

76 'conint', 

77 'PositiveInt', 

78 'NegativeInt', 

79 'NonNegativeInt', 

80 'NonPositiveInt', 

81 'ConstrainedFloat', 

82 'confloat', 

83 'PositiveFloat', 

84 'NegativeFloat', 

85 'NonNegativeFloat', 

86 'NonPositiveFloat', 

87 'FiniteFloat', 

88 'ConstrainedDecimal', 

89 'condecimal', 

90 'UUID1', 

91 'UUID3', 

92 'UUID4', 

93 'UUID5', 

94 'FilePath', 

95 'DirectoryPath', 

96 'Json', 

97 'JsonWrapper', 

98 'SecretField', 

99 'SecretStr', 

100 'SecretBytes', 

101 'StrictBool', 

102 'StrictBytes', 

103 'StrictInt', 

104 'StrictFloat', 

105 'PaymentCardNumber', 

106 'ByteSize', 

107 'PastDate', 

108 'FutureDate', 

109 'ConstrainedDate', 

110 'condate', 

111] 

112 

113NoneStr = Optional[str] 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

114NoneBytes = Optional[bytes] 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

115StrBytes = Union[str, bytes] 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

116NoneStrBytes = Optional[StrBytes] 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

117OptionalInt = Optional[int] 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

118OptionalIntFloat = Union[OptionalInt, float] 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

119OptionalIntFloatDecimal = Union[OptionalIntFloat, Decimal] 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

120OptionalDate = Optional[date] 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

121StrIntFloat = Union[str, int, float] 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

122 

123if TYPE_CHECKING: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

124 from typing_extensions import Annotated 

125 

126 from pydantic.dataclasses import Dataclass 

127 from pydantic.main import BaseModel 

128 from pydantic.typing import CallableGenerator 

129 

130 ModelOrDc = Type[Union[BaseModel, Dataclass]] 

131 

132T = TypeVar('T') 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

133_DEFINED_TYPES: 'WeakSet[type]' = WeakSet() 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

134 

135 

136@overload 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

137def _registered(typ: Type[T]) -> Type[T]: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

138 pass 

139 

140 

141@overload 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

142def _registered(typ: 'ConstrainedNumberMeta') -> 'ConstrainedNumberMeta': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

143 pass 

144 

145 

146def _registered(typ: Union[Type[T], 'ConstrainedNumberMeta']) -> Union[Type[T], 'ConstrainedNumberMeta']: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

147 # In order to generate valid examples of constrained types, Hypothesis needs 

148 # to inspect the type object - so we keep a weakref to each contype object 

149 # until it can be registered. When (or if) our Hypothesis plugin is loaded, 

150 # it monkeypatches this function. 

151 # If Hypothesis is never used, the total effect is to keep a weak reference 

152 # which has minimal memory usage and doesn't even affect garbage collection. 

153 _DEFINED_TYPES.add(typ) 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

154 return typ 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

155 

156 

157class ConstrainedNumberMeta(type): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

158 def __new__(cls, name: str, bases: Any, dct: Dict[str, Any]) -> 'ConstrainedInt': # type: ignore 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

159 new_cls = cast('ConstrainedInt', type.__new__(cls, name, bases, dct)) 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

160 

161 if new_cls.gt is not None and new_cls.ge is not None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

162 raise errors.ConfigError('bounds gt and ge cannot be specified at the same time') 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

163 if new_cls.lt is not None and new_cls.le is not None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

164 raise errors.ConfigError('bounds lt and le cannot be specified at the same time') 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

165 

166 return _registered(new_cls) # type: ignore 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

167 

168 

169# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BOOLEAN TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

170 

171if TYPE_CHECKING: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

172 StrictBool = bool 

173else: 

174 

175 class StrictBool(int): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

176 """ 

177 StrictBool to allow for bools which are not type-coerced. 

178 """ 

179 

180 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

181 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

182 field_schema.update(type='boolean') 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

183 

184 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

185 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

186 yield cls.validate 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

187 

188 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

189 def validate(cls, value: Any) -> bool: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

190 """ 

191 Ensure that we only allow bools. 

192 """ 

193 if isinstance(value, bool): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

194 return value 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

195 

196 raise errors.StrictBoolError() 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

197 

198 

199# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTEGER TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

200 

201 

202class ConstrainedInt(int, metaclass=ConstrainedNumberMeta): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

203 strict: bool = False 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

204 gt: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

205 ge: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

206 lt: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

207 le: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

208 multiple_of: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

209 

210 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

211 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

212 update_not_none( 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

213 field_schema, 

214 exclusiveMinimum=cls.gt, 

215 exclusiveMaximum=cls.lt, 

216 minimum=cls.ge, 

217 maximum=cls.le, 

218 multipleOf=cls.multiple_of, 

219 ) 

220 

221 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

222 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

223 yield strict_int_validator if cls.strict else int_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

224 yield number_size_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

225 yield number_multiple_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

226 

227 

228def conint( 1akblcmdneopzqArBsCtDKLMNPQRSTUOfugvhwixjy

229 *, 

230 strict: bool = False, 

231 gt: Optional[int] = None, 

232 ge: Optional[int] = None, 

233 lt: Optional[int] = None, 

234 le: Optional[int] = None, 

235 multiple_of: Optional[int] = None, 

236) -> Type[int]: 

237 # use kwargs then define conf in a dict to aid with IDE type hinting 

238 namespace = dict(strict=strict, gt=gt, ge=ge, lt=lt, le=le, multiple_of=multiple_of) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

239 return type('ConstrainedIntValue', (ConstrainedInt,), namespace) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

240 

241 

242if TYPE_CHECKING: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

243 PositiveInt = int 

244 NegativeInt = int 

245 NonPositiveInt = int 

246 NonNegativeInt = int 

247 StrictInt = int 

248else: 

249 

250 class PositiveInt(ConstrainedInt): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

251 gt = 0 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

252 

253 class NegativeInt(ConstrainedInt): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

254 lt = 0 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

255 

256 class NonPositiveInt(ConstrainedInt): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

257 le = 0 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

258 

259 class NonNegativeInt(ConstrainedInt): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

260 ge = 0 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

261 

262 class StrictInt(ConstrainedInt): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

263 strict = True 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

264 

265 

266# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FLOAT TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

267 

268 

269class ConstrainedFloat(float, metaclass=ConstrainedNumberMeta): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

270 strict: bool = False 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

271 gt: OptionalIntFloat = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

272 ge: OptionalIntFloat = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

273 lt: OptionalIntFloat = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

274 le: OptionalIntFloat = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

275 multiple_of: OptionalIntFloat = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

276 allow_inf_nan: Optional[bool] = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

277 

278 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

279 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

280 update_not_none( 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

281 field_schema, 

282 exclusiveMinimum=cls.gt, 

283 exclusiveMaximum=cls.lt, 

284 minimum=cls.ge, 

285 maximum=cls.le, 

286 multipleOf=cls.multiple_of, 

287 ) 

288 # Modify constraints to account for differences between IEEE floats and JSON 

289 if field_schema.get('exclusiveMinimum') == -math.inf: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

290 del field_schema['exclusiveMinimum'] 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

291 if field_schema.get('minimum') == -math.inf: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

292 del field_schema['minimum'] 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

293 if field_schema.get('exclusiveMaximum') == math.inf: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

294 del field_schema['exclusiveMaximum'] 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

295 if field_schema.get('maximum') == math.inf: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

296 del field_schema['maximum'] 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

297 

298 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

299 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

300 yield strict_float_validator if cls.strict else float_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

301 yield number_size_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

302 yield number_multiple_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

303 yield float_finite_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

304 

305 

306def confloat( 1akblcmdneopzqArBsCtDKLMNPQRSTUOfugvhwixjy

307 *, 

308 strict: bool = False, 

309 gt: float = None, 

310 ge: float = None, 

311 lt: float = None, 

312 le: float = None, 

313 multiple_of: float = None, 

314 allow_inf_nan: Optional[bool] = None, 

315) -> Type[float]: 

316 # use kwargs then define conf in a dict to aid with IDE type hinting 

317 namespace = dict(strict=strict, gt=gt, ge=ge, lt=lt, le=le, multiple_of=multiple_of, allow_inf_nan=allow_inf_nan) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

318 return type('ConstrainedFloatValue', (ConstrainedFloat,), namespace) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

319 

320 

321if TYPE_CHECKING: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

322 PositiveFloat = float 

323 NegativeFloat = float 

324 NonPositiveFloat = float 

325 NonNegativeFloat = float 

326 StrictFloat = float 

327 FiniteFloat = float 

328else: 

329 

330 class PositiveFloat(ConstrainedFloat): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

331 gt = 0 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

332 

333 class NegativeFloat(ConstrainedFloat): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

334 lt = 0 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

335 

336 class NonPositiveFloat(ConstrainedFloat): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

337 le = 0 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

338 

339 class NonNegativeFloat(ConstrainedFloat): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

340 ge = 0 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

341 

342 class StrictFloat(ConstrainedFloat): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

343 strict = True 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

344 

345 class FiniteFloat(ConstrainedFloat): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

346 allow_inf_nan = False 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

347 

348 

349# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BYTES TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

350 

351 

352class ConstrainedBytes(bytes): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

353 strip_whitespace = False 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

354 to_upper = False 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

355 to_lower = False 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

356 min_length: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

357 max_length: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

358 strict: bool = False 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

359 

360 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

361 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

362 update_not_none(field_schema, minLength=cls.min_length, maxLength=cls.max_length) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

363 

364 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

365 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

366 yield strict_bytes_validator if cls.strict else bytes_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

367 yield constr_strip_whitespace 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

368 yield constr_upper 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

369 yield constr_lower 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

370 yield constr_length_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

371 

372 

373def conbytes( 1akblcmdneopzqArBsCtDKLMNPQRSTUOfugvhwixjy

374 *, 

375 strip_whitespace: bool = False, 

376 to_upper: bool = False, 

377 to_lower: bool = False, 

378 min_length: Optional[int] = None, 

379 max_length: Optional[int] = None, 

380 strict: bool = False, 

381) -> Type[bytes]: 

382 # use kwargs then define conf in a dict to aid with IDE type hinting 

383 namespace = dict( 1EGakblcmdneoHJpzqArBsCtDFIfugvhwixjy

384 strip_whitespace=strip_whitespace, 

385 to_upper=to_upper, 

386 to_lower=to_lower, 

387 min_length=min_length, 

388 max_length=max_length, 

389 strict=strict, 

390 ) 

391 return _registered(type('ConstrainedBytesValue', (ConstrainedBytes,), namespace)) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

392 

393 

394if TYPE_CHECKING: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

395 StrictBytes = bytes 

396else: 

397 

398 class StrictBytes(ConstrainedBytes): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

399 strict = True 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

400 

401 

402# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STRING TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

403 

404 

405class ConstrainedStr(str): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

406 strip_whitespace = False 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

407 to_upper = False 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

408 to_lower = False 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

409 min_length: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

410 max_length: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

411 curtail_length: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

412 regex: Optional[Union[str, Pattern[str]]] = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

413 strict = False 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

414 

415 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

416 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

417 update_not_none( 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

418 field_schema, 

419 minLength=cls.min_length, 

420 maxLength=cls.max_length, 

421 pattern=cls.regex and cls._get_pattern(cls.regex), 

422 ) 

423 

424 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

425 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

426 yield strict_str_validator if cls.strict else str_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

427 yield constr_strip_whitespace 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

428 yield constr_upper 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

429 yield constr_lower 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

430 yield constr_length_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

431 yield cls.validate 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

432 

433 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

434 def validate(cls, value: Union[str]) -> Union[str]: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

435 if cls.curtail_length and len(value) > cls.curtail_length: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

436 value = value[: cls.curtail_length] 1EabcdeHpqrstKLMNOFfghij

437 

438 if cls.regex: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

439 if not re.match(cls.regex, value): 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

440 raise errors.StrRegexError(pattern=cls._get_pattern(cls.regex)) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

441 

442 return value 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

443 

444 @staticmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

445 def _get_pattern(regex: Union[str, Pattern[str]]) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

446 return regex if isinstance(regex, str) else regex.pattern 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

447 

448 

449def constr( 1akblcmdneopzqArBsCtDKLMNPQRSTUOfugvhwixjy

450 *, 

451 strip_whitespace: bool = False, 

452 to_upper: bool = False, 

453 to_lower: bool = False, 

454 strict: bool = False, 

455 min_length: Optional[int] = None, 

456 max_length: Optional[int] = None, 

457 curtail_length: Optional[int] = None, 

458 regex: Optional[str] = None, 

459) -> Type[str]: 

460 # use kwargs then define conf in a dict to aid with IDE type hinting 

461 namespace = dict( 1EGakblcmdneoHJpzqArBsCtDFIfugvhwixjy

462 strip_whitespace=strip_whitespace, 

463 to_upper=to_upper, 

464 to_lower=to_lower, 

465 strict=strict, 

466 min_length=min_length, 

467 max_length=max_length, 

468 curtail_length=curtail_length, 

469 regex=regex and re.compile(regex), 

470 ) 

471 return _registered(type('ConstrainedStrValue', (ConstrainedStr,), namespace)) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

472 

473 

474if TYPE_CHECKING: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

475 StrictStr = str 

476else: 

477 

478 class StrictStr(ConstrainedStr): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

479 strict = True 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

480 

481 

482# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SET TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

483 

484 

485# This types superclass should be Set[T], but cython chokes on that... 

486class ConstrainedSet(set): # type: ignore 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

487 # Needed for pydantic to detect that this is a set 

488 __origin__ = set 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

489 __args__: Set[Type[T]] # type: ignore 1EGakblcmdneoHJpzqArBsCtDPQRSTUFIfugvhwixjy

490 

491 min_items: Optional[int] = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

492 max_items: Optional[int] = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

493 item_type: Type[T] # type: ignore 1EGakblcmdneoHJpzqArBsCtDPQRSTUFIfugvhwixjy

494 

495 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

496 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

497 yield cls.set_length_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

498 

499 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

500 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

501 update_not_none(field_schema, minItems=cls.min_items, maxItems=cls.max_items) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

502 

503 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

504 def set_length_validator(cls, v: 'Optional[Set[T]]') -> 'Optional[Set[T]]': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

505 if v is None: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

506 return None 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

507 

508 v = set_validator(v) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

509 v_len = len(v) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

510 

511 if cls.min_items is not None and v_len < cls.min_items: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

512 raise errors.SetMinLengthError(limit_value=cls.min_items) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

513 

514 if cls.max_items is not None and v_len > cls.max_items: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

515 raise errors.SetMaxLengthError(limit_value=cls.max_items) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

516 

517 return v 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

518 

519 

520def conset(item_type: Type[T], *, min_items: Optional[int] = None, max_items: Optional[int] = None) -> Type[Set[T]]: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

521 # __args__ is needed to conform to typing generics api 

522 namespace = {'min_items': min_items, 'max_items': max_items, 'item_type': item_type, '__args__': [item_type]} 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

523 # We use new_class to be able to deal with Generic types 

524 return new_class('ConstrainedSetValue', (ConstrainedSet,), {}, lambda ns: ns.update(namespace)) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

525 

526 

527# This types superclass should be FrozenSet[T], but cython chokes on that... 

528class ConstrainedFrozenSet(frozenset): # type: ignore 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

529 # Needed for pydantic to detect that this is a set 

530 __origin__ = frozenset 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

531 __args__: FrozenSet[Type[T]] # type: ignore 1EGakblcmdneoHJpzqArBsCtDPQRSTUFIfugvhwixjy

532 

533 min_items: Optional[int] = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

534 max_items: Optional[int] = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

535 item_type: Type[T] # type: ignore 1EGakblcmdneoHJpzqArBsCtDPQRSTUFIfugvhwixjy

536 

537 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

538 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

539 yield cls.frozenset_length_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

540 

541 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

542 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

543 update_not_none(field_schema, minItems=cls.min_items, maxItems=cls.max_items) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

544 

545 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

546 def frozenset_length_validator(cls, v: 'Optional[FrozenSet[T]]') -> 'Optional[FrozenSet[T]]': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

547 if v is None: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

548 return None 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

549 

550 v = frozenset_validator(v) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

551 v_len = len(v) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

552 

553 if cls.min_items is not None and v_len < cls.min_items: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

554 raise errors.FrozenSetMinLengthError(limit_value=cls.min_items) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

555 

556 if cls.max_items is not None and v_len > cls.max_items: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

557 raise errors.FrozenSetMaxLengthError(limit_value=cls.max_items) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

558 

559 return v 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

560 

561 

562def confrozenset( 1akblcmdneopzqArBsCtDKLMNPQRSTUOfugvhwixjy

563 item_type: Type[T], *, min_items: Optional[int] = None, max_items: Optional[int] = None 

564) -> Type[FrozenSet[T]]: 

565 # __args__ is needed to conform to typing generics api 

566 namespace = {'min_items': min_items, 'max_items': max_items, 'item_type': item_type, '__args__': [item_type]} 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

567 # We use new_class to be able to deal with Generic types 

568 return new_class('ConstrainedFrozenSetValue', (ConstrainedFrozenSet,), {}, lambda ns: ns.update(namespace)) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

569 

570 

571# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LIST TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

572 

573 

574# This types superclass should be List[T], but cython chokes on that... 

575class ConstrainedList(list): # type: ignore 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

576 # Needed for pydantic to detect that this is a list 

577 __origin__ = list 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

578 __args__: Tuple[Type[T], ...] # type: ignore 1EGakblcmdneoHJpzqArBsCtDPQRSTUFIfugvhwixjy

579 

580 min_items: Optional[int] = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

581 max_items: Optional[int] = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

582 unique_items: Optional[bool] = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

583 item_type: Type[T] # type: ignore 1EGakblcmdneoHJpzqArBsCtDPQRSTUFIfugvhwixjy

584 

585 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

586 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

587 yield cls.list_length_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

588 if cls.unique_items: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

589 yield cls.unique_items_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

590 

591 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

592 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

593 update_not_none(field_schema, minItems=cls.min_items, maxItems=cls.max_items, uniqueItems=cls.unique_items) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

594 

595 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

596 def list_length_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

597 if v is None: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

598 return None 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

599 

600 v = list_validator(v) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

601 v_len = len(v) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

602 

603 if cls.min_items is not None and v_len < cls.min_items: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

604 raise errors.ListMinLengthError(limit_value=cls.min_items) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

605 

606 if cls.max_items is not None and v_len > cls.max_items: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

607 raise errors.ListMaxLengthError(limit_value=cls.max_items) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

608 

609 return v 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

610 

611 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

612 def unique_items_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

613 if v is None: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

614 return None 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

615 

616 for i, value in enumerate(v, start=1): 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

617 if value in v[i:]: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

618 raise errors.ListUniqueItemsError() 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

619 

620 return v 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

621 

622 

623def conlist( 1akblcmdneopzqArBsCtDKLMNPQRSTUOfugvhwixjy

624 item_type: Type[T], *, min_items: Optional[int] = None, max_items: Optional[int] = None, unique_items: bool = None 

625) -> Type[List[T]]: 

626 # __args__ is needed to conform to typing generics api 

627 namespace = dict( 1EGakblcmdneoHJpzqArBsCtDFIfugvhwixjy

628 min_items=min_items, max_items=max_items, unique_items=unique_items, item_type=item_type, __args__=(item_type,) 

629 ) 

630 # We use new_class to be able to deal with Generic types 

631 return new_class('ConstrainedListValue', (ConstrainedList,), {}, lambda ns: ns.update(namespace)) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

632 

633 

634# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PYOBJECT TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

635 

636 

637if TYPE_CHECKING: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

638 PyObject = Callable[..., Any] 

639else: 

640 

641 class PyObject: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

642 validate_always = True 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

643 

644 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

645 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

646 yield cls.validate 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

647 

648 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

649 def validate(cls, value: Any) -> Any: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

650 if isinstance(value, Callable): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

651 return value 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

652 

653 try: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

654 value = str_validator(value) 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

655 except errors.StrError: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

656 raise errors.PyObjectError(error_message='value is neither a valid import path not a valid callable') 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

657 

658 try: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

659 return import_string(value) 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

660 except ImportError as e: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

661 raise errors.PyObjectError(error_message=str(e)) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

662 

663 

664# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECIMAL TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

665 

666 

667class ConstrainedDecimal(Decimal, metaclass=ConstrainedNumberMeta): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

668 gt: OptionalIntFloatDecimal = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

669 ge: OptionalIntFloatDecimal = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

670 lt: OptionalIntFloatDecimal = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

671 le: OptionalIntFloatDecimal = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

672 max_digits: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

673 decimal_places: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

674 multiple_of: OptionalIntFloatDecimal = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

675 

676 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

677 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

678 update_not_none( 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

679 field_schema, 

680 exclusiveMinimum=cls.gt, 

681 exclusiveMaximum=cls.lt, 

682 minimum=cls.ge, 

683 maximum=cls.le, 

684 multipleOf=cls.multiple_of, 

685 ) 

686 

687 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

688 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

689 yield decimal_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

690 yield number_size_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

691 yield number_multiple_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

692 yield cls.validate 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

693 

694 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

695 def validate(cls, value: Decimal) -> Decimal: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

696 try: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

697 normalized_value = value.normalize() 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

698 except InvalidOperation: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

699 normalized_value = value 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

700 digit_tuple, exponent = normalized_value.as_tuple()[1:] 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

701 if exponent in {'F', 'n', 'N'}: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

702 raise errors.DecimalIsNotFiniteError() 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

703 

704 if exponent >= 0: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

705 # A positive exponent adds that many trailing zeros. 

706 digits = len(digit_tuple) + exponent 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

707 decimals = 0 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

708 else: 

709 # If the absolute value of the negative exponent is larger than the 

710 # number of digits, then it's the same as the number of digits, 

711 # because it'll consume all of the digits in digit_tuple and then 

712 # add abs(exponent) - len(digit_tuple) leading zeros after the 

713 # decimal point. 

714 if abs(exponent) > len(digit_tuple): 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

715 digits = decimals = abs(exponent) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

716 else: 

717 digits = len(digit_tuple) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

718 decimals = abs(exponent) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

719 whole_digits = digits - decimals 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

720 

721 if cls.max_digits is not None and digits > cls.max_digits: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

722 raise errors.DecimalMaxDigitsError(max_digits=cls.max_digits) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

723 

724 if cls.decimal_places is not None and decimals > cls.decimal_places: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

725 raise errors.DecimalMaxPlacesError(decimal_places=cls.decimal_places) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

726 

727 if cls.max_digits is not None and cls.decimal_places is not None: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

728 expected = cls.max_digits - cls.decimal_places 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

729 if whole_digits > expected: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

730 raise errors.DecimalWholeDigitsError(whole_digits=expected) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

731 

732 return value 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

733 

734 

735def condecimal( 1akblcmdneopzqArBsCtDKLMNPQRSTUOfugvhwixjy

736 *, 

737 gt: Decimal = None, 

738 ge: Decimal = None, 

739 lt: Decimal = None, 

740 le: Decimal = None, 

741 max_digits: Optional[int] = None, 

742 decimal_places: Optional[int] = None, 

743 multiple_of: Decimal = None, 

744) -> Type[Decimal]: 

745 # use kwargs then define conf in a dict to aid with IDE type hinting 

746 namespace = dict( 1EGakblcmdneoHJpzqArBsCtDFIfugvhwixjy

747 gt=gt, ge=ge, lt=lt, le=le, max_digits=max_digits, decimal_places=decimal_places, multiple_of=multiple_of 

748 ) 

749 return type('ConstrainedDecimalValue', (ConstrainedDecimal,), namespace) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

750 

751 

752# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UUID TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

753 

754if TYPE_CHECKING: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

755 UUID1 = UUID 

756 UUID3 = UUID 

757 UUID4 = UUID 

758 UUID5 = UUID 

759else: 

760 

761 class UUID1(UUID): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

762 _required_version = 1 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

763 

764 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

765 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

766 field_schema.update(type='string', format=f'uuid{cls._required_version}') 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

767 

768 class UUID3(UUID1): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

769 _required_version = 3 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

770 

771 class UUID4(UUID1): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

772 _required_version = 4 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

773 

774 class UUID5(UUID1): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

775 _required_version = 5 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

776 

777 

778# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PATH TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

779 

780if TYPE_CHECKING: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

781 FilePath = Path 

782 DirectoryPath = Path 

783else: 

784 

785 class FilePath(Path): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

786 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

787 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

788 field_schema.update(format='file-path') 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

789 

790 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

791 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

792 yield path_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

793 yield path_exists_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

794 yield cls.validate 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

795 

796 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

797 def validate(cls, value: Path) -> Path: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

798 if not value.is_file(): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

799 raise errors.PathNotAFileError(path=value) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

800 

801 return value 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

802 

803 class DirectoryPath(Path): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

804 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

805 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

806 field_schema.update(format='directory-path') 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

807 

808 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

809 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

810 yield path_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

811 yield path_exists_validator 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

812 yield cls.validate 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

813 

814 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

815 def validate(cls, value: Path) -> Path: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

816 if not value.is_dir(): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

817 raise errors.PathNotADirectoryError(path=value) 1EGakblcmdneoKLMNOFIfugvhwixjy

818 

819 return value 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

820 

821 

822# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

823 

824 

825class JsonWrapper: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

826 pass 1EGakblcmdneoHJpzqArBsCtDPQRSTUFIfugvhwixjy

827 

828 

829class JsonMeta(type): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

830 def __getitem__(self, t: Type[Any]) -> Type[JsonWrapper]: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

831 if t is Any: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

832 return Json # allow Json[Any] to replecate plain Json 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

833 return _registered(type('JsonWrapperValue', (JsonWrapper,), {'inner_type': t})) 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

834 

835 

836if TYPE_CHECKING: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

837 Json = Annotated[T, ...] # Json[list[str]] will be recognized by type checkers as list[str] 

838 

839else: 

840 

841 class Json(metaclass=JsonMeta): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

842 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

843 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

844 field_schema.update(type='string', format='json-string') 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

845 

846 

847# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SECRET TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

848 

849 

850class SecretField(abc.ABC): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

851 """ 

852 Note: this should be implemented as a generic like `SecretField(ABC, Generic[T])`, 

853 the `__init__()` should be part of the abstract class and the 

854 `get_secret_value()` method should use the generic `T` type. 

855 

856 However Cython doesn't support very well generics at the moment and 

857 the generated code fails to be imported (see 

858 https://github.com/cython/cython/issues/2753). 

859 """ 

860 

861 def __eq__(self, other: Any) -> bool: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

862 return isinstance(other, self.__class__) and self.get_secret_value() == other.get_secret_value() 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

863 

864 def __str__(self) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

865 return '**********' if self.get_secret_value() else '' 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

866 

867 def __hash__(self) -> int: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

868 return hash(self.get_secret_value()) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

869 

870 @abc.abstractmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

871 def get_secret_value(self) -> Any: # pragma: no cover 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

872 ... 

873 

874 

875class SecretStr(SecretField): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

876 min_length: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

877 max_length: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

878 

879 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

880 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

881 update_not_none( 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

882 field_schema, 

883 type='string', 

884 writeOnly=True, 

885 format='password', 

886 minLength=cls.min_length, 

887 maxLength=cls.max_length, 

888 ) 

889 

890 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

891 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

892 yield cls.validate 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

893 yield constr_length_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

894 

895 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

896 def validate(cls, value: Any) -> 'SecretStr': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

897 if isinstance(value, cls): 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

898 return value 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

899 value = str_validator(value) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

900 return cls(value) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

901 

902 def __init__(self, value: str): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

903 self._secret_value = value 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

904 

905 def __repr__(self) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

906 return f"SecretStr('{self}')" 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

907 

908 def __len__(self) -> int: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

909 return len(self._secret_value) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

910 

911 def display(self) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

912 warnings.warn('`secret_str.display()` is deprecated, use `str(secret_str)` instead', DeprecationWarning) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

913 return str(self) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

914 

915 def get_secret_value(self) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

916 return self._secret_value 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

917 

918 

919class SecretBytes(SecretField): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

920 min_length: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

921 max_length: OptionalInt = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

922 

923 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

924 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

925 update_not_none( 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

926 field_schema, 

927 type='string', 

928 writeOnly=True, 

929 format='password', 

930 minLength=cls.min_length, 

931 maxLength=cls.max_length, 

932 ) 

933 

934 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

935 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

936 yield cls.validate 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

937 yield constr_length_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

938 

939 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

940 def validate(cls, value: Any) -> 'SecretBytes': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

941 if isinstance(value, cls): 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

942 return value 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

943 value = bytes_validator(value) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

944 return cls(value) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

945 

946 def __init__(self, value: bytes): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

947 self._secret_value = value 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

948 

949 def __repr__(self) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

950 return f"SecretBytes(b'{self}')" 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

951 

952 def __len__(self) -> int: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

953 return len(self._secret_value) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

954 

955 def display(self) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

956 warnings.warn('`secret_bytes.display()` is deprecated, use `str(secret_bytes)` instead', DeprecationWarning) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

957 return str(self) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

958 

959 def get_secret_value(self) -> bytes: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

960 return self._secret_value 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

961 

962 

963# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PAYMENT CARD TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

964 

965 

966class PaymentCardBrand(str, Enum): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

967 # If you add another card type, please also add it to the 

968 # Hypothesis strategy in `pydantic._hypothesis_plugin`. 

969 amex = 'American Express' 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

970 mastercard = 'Mastercard' 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

971 visa = 'Visa' 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

972 other = 'other' 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

973 

974 def __str__(self) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

975 return self.value 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

976 

977 

978class PaymentCardNumber(str): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

979 """ 

980 Based on: https://en.wikipedia.org/wiki/Payment_card_number 

981 """ 

982 

983 strip_whitespace: ClassVar[bool] = True 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

984 min_length: ClassVar[int] = 12 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

985 max_length: ClassVar[int] = 19 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

986 bin: str 1EGakblcmdneoHJpzqArBsCtDPQRSTUFIfugvhwixjy

987 last4: str 1EGakblcmdneoHJpzqArBsCtDPQRSTUFIfugvhwixjy

988 brand: PaymentCardBrand 1EGakblcmdneoHJpzqArBsCtDPQRSTUFIfugvhwixjy

989 

990 def __init__(self, card_number: str): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

991 self.bin = card_number[:6] 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

992 self.last4 = card_number[-4:] 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

993 self.brand = self._get_brand(card_number) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

994 

995 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

996 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

997 yield str_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

998 yield constr_strip_whitespace 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

999 yield constr_length_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1000 yield cls.validate_digits 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1001 yield cls.validate_luhn_check_digit 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1002 yield cls 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1003 yield cls.validate_length_for_brand 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1004 

1005 @property 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1006 def masked(self) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1007 num_masked = len(self) - 10 # len(bin) + len(last4) == 10 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1008 return f'{self.bin}{"*" * num_masked}{self.last4}' 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1009 

1010 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1011 def validate_digits(cls, card_number: str) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1012 if not card_number.isdigit(): 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1013 raise errors.NotDigitError 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1014 return card_number 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1015 

1016 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1017 def validate_luhn_check_digit(cls, card_number: str) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1018 """ 

1019 Based on: https://en.wikipedia.org/wiki/Luhn_algorithm 

1020 """ 

1021 sum_ = int(card_number[-1]) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1022 length = len(card_number) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1023 parity = length % 2 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1024 for i in range(length - 1): 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1025 digit = int(card_number[i]) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1026 if i % 2 == parity: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1027 digit *= 2 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1028 if digit > 9: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1029 digit -= 9 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1030 sum_ += digit 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1031 valid = sum_ % 10 == 0 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1032 if not valid: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1033 raise errors.LuhnValidationError 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1034 return card_number 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1035 

1036 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1037 def validate_length_for_brand(cls, card_number: 'PaymentCardNumber') -> 'PaymentCardNumber': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1038 """ 

1039 Validate length based on BIN for major brands: 

1040 https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_(IIN) 

1041 """ 

1042 required_length: Union[None, int, str] = None 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1043 if card_number.brand in PaymentCardBrand.mastercard: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1044 required_length = 16 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1045 valid = len(card_number) == required_length 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1046 elif card_number.brand == PaymentCardBrand.visa: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1047 required_length = '13, 16 or 19' 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1048 valid = len(card_number) in {13, 16, 19} 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1049 elif card_number.brand == PaymentCardBrand.amex: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1050 required_length = 15 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1051 valid = len(card_number) == required_length 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1052 else: 

1053 valid = True 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1054 if not valid: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1055 raise errors.InvalidLengthForBrand(brand=card_number.brand, required_length=required_length) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1056 return card_number 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1057 

1058 @staticmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1059 def _get_brand(card_number: str) -> PaymentCardBrand: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1060 if card_number[0] == '4': 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1061 brand = PaymentCardBrand.visa 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1062 elif 51 <= int(card_number[:2]) <= 55: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1063 brand = PaymentCardBrand.mastercard 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1064 elif card_number[:2] in {'34', '37'}: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1065 brand = PaymentCardBrand.amex 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1066 else: 

1067 brand = PaymentCardBrand.other 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1068 return brand 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1069 

1070 

1071# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BYTE SIZE TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

1072 

1073BYTE_SIZES = { 1akblcmdneopzqArBsCtDPQRSTUfugvhwixjy

1074 'b': 1, 

1075 'kb': 10**3, 

1076 'mb': 10**6, 

1077 'gb': 10**9, 

1078 'tb': 10**12, 

1079 'pb': 10**15, 

1080 'eb': 10**18, 

1081 'kib': 2**10, 

1082 'mib': 2**20, 

1083 'gib': 2**30, 

1084 'tib': 2**40, 

1085 'pib': 2**50, 

1086 'eib': 2**60, 

1087} 

1088BYTE_SIZES.update({k.lower()[0]: v for k, v in BYTE_SIZES.items() if 'i' not in k}) 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1089byte_string_re = re.compile(r'^\s*(\d*\.?\d+)\s*(\w+)?', re.IGNORECASE) 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1090 

1091 

1092class ByteSize(int): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1093 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1094 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1095 yield cls.validate 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1096 

1097 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1098 def validate(cls, v: StrIntFloat) -> 'ByteSize': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1099 try: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1100 return cls(int(v)) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1101 except ValueError: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1102 pass 1EGakblcmdneoHJpzqArBsCtDFIfugvhwixjy

1103 

1104 str_match = byte_string_re.match(str(v)) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1105 if str_match is None: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1106 raise errors.InvalidByteSize() 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1107 

1108 scalar, unit = str_match.groups() 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1109 if unit is None: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1110 unit = 'b' 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1111 

1112 try: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1113 unit_mult = BYTE_SIZES[unit.lower()] 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1114 except KeyError: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1115 raise errors.InvalidByteSizeUnit(unit=unit) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1116 

1117 return cls(int(float(scalar) * unit_mult)) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1118 

1119 def human_readable(self, decimal: bool = False) -> str: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1120 if decimal: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1121 divisor = 1000 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1122 units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'] 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1123 final_unit = 'EB' 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1124 else: 

1125 divisor = 1024 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1126 units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'] 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1127 final_unit = 'EiB' 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1128 

1129 num = float(self) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1130 for unit in units: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1131 if abs(num) < divisor: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1132 return f'{num:0.1f}{unit}' 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1133 num /= divisor 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1134 

1135 return f'{num:0.1f}{final_unit}' 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1136 

1137 def to(self, unit: str) -> float: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1138 try: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1139 unit_div = BYTE_SIZES[unit.lower()] 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1140 except KeyError: 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1141 raise errors.InvalidByteSizeUnit(unit=unit) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1142 

1143 return self / unit_div 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1144 

1145 

1146# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DATE TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

1147 

1148if TYPE_CHECKING: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1149 PastDate = date 

1150 FutureDate = date 

1151else: 

1152 

1153 class PastDate(date): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1154 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1155 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1156 yield parse_date 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1157 yield cls.validate 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1158 

1159 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1160 def validate(cls, value: date) -> date: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1161 if value >= date.today(): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1162 raise errors.DateNotInThePastError() 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1163 

1164 return value 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1165 

1166 class FutureDate(date): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1167 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1168 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1169 yield parse_date 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1170 yield cls.validate 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1171 

1172 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1173 def validate(cls, value: date) -> date: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1174 if value <= date.today(): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1175 raise errors.DateNotInTheFutureError() 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1176 

1177 return value 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1178 

1179 

1180class ConstrainedDate(date, metaclass=ConstrainedNumberMeta): 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1181 gt: OptionalDate = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1182 ge: OptionalDate = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1183 lt: OptionalDate = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1184 le: OptionalDate = None 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1185 

1186 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1187 def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1188 update_not_none(field_schema, exclusiveMinimum=cls.gt, exclusiveMaximum=cls.lt, minimum=cls.ge, maximum=cls.le) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1189 

1190 @classmethod 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1191 def __get_validators__(cls) -> 'CallableGenerator': 1EGakblcmdneoHJpzqArBsCtDKLMNPQRSTUOFIfugvhwixjy

1192 yield parse_date 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1193 yield number_size_validator 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1194 

1195 

1196def condate( 1akblcmdneopzqArBsCtDKLMNPQRSTUOfugvhwixjy

1197 *, 

1198 gt: date = None, 

1199 ge: date = None, 

1200 lt: date = None, 

1201 le: date = None, 

1202) -> Type[date]: 

1203 # use kwargs then define conf in a dict to aid with IDE type hinting 

1204 namespace = dict(gt=gt, ge=ge, lt=lt, le=le) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy

1205 return type('ConstrainedDateValue', (ConstrainedDate,), namespace) 1EGakblcmdneoHJpzqArBsCtDKLMNOFIfugvhwixjy