Make a generic function which calls a validator with the right arguments. Unfortunately other approaches (eg. return a partial of a function that builds the arguments) is slow, hence this laborious way of doing things. It's done like this so validators don't all need **kwargs in t
(validator: AnyCallable)
| 240 | |
| 241 | |
| 242 | def make_generic_validator(validator: AnyCallable) -> 'ValidatorCallable': |
| 243 | """ |
| 244 | Make a generic function which calls a validator with the right arguments. |
| 245 | |
| 246 | Unfortunately other approaches (eg. return a partial of a function that builds the arguments) is slow, |
| 247 | hence this laborious way of doing things. |
| 248 | |
| 249 | It's done like this so validators don't all need **kwargs in their signature, eg. any combination of |
| 250 | the arguments "values", "fields" and/or "config" are permitted. |
| 251 | """ |
| 252 | from inspect import signature |
| 253 | |
| 254 | if not isinstance(validator, (partial, partialmethod)): |
| 255 | # This should be the default case, so overhead is reduced |
| 256 | sig = signature(validator) |
| 257 | args = list(sig.parameters.keys()) |
| 258 | else: |
| 259 | # Fix the generated argument lists of partial methods |
| 260 | sig = signature(validator.func) |
| 261 | args = [ |
| 262 | k |
| 263 | for k in signature(validator.func).parameters.keys() |
| 264 | if k not in validator.args | validator.keywords.keys() |
| 265 | ] |
| 266 | |
| 267 | first_arg = args.pop(0) |
| 268 | if first_arg == 'self': |
| 269 | raise ConfigError( |
| 270 | f'Invalid signature for validator {validator}: {sig}, "self" not permitted as first argument, ' |
| 271 | f'should be: (cls, value, values, config, field), "values", "config" and "field" are all optional.' |
| 272 | ) |
| 273 | elif first_arg == 'cls': |
| 274 | # assume the second argument is value |
| 275 | return wraps(validator)(_generic_validator_cls(validator, sig, set(args[1:]))) |
| 276 | else: |
| 277 | # assume the first argument was value which has already been removed |
| 278 | return wraps(validator)(_generic_validator_basic(validator, sig, set(args))) |
| 279 | |
| 280 | |
| 281 | def prep_validators(v_funcs: Iterable[AnyCallable]) -> 'ValidatorsList': |
no test coverage detected