Skip to content

Commit 878d864

Browse files
committed
added another way to extract validators (WIP)
1 parent 7de4d37 commit 878d864

File tree

1 file changed

+52
-1
lines changed

1 file changed

+52
-1
lines changed

fastapi_jsonapi/schema_builder.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""JSON API schemas builder class."""
2+
from copy import deepcopy
23
from dataclasses import dataclass
34
from typing import (
45
Any,
@@ -17,7 +18,12 @@
1718
import pydantic
1819
from pydantic import BaseConfig, root_validator, validator
1920
from pydantic import BaseModel as PydanticBaseModel
20-
from pydantic.class_validators import ROOT_VALIDATOR_CONFIG_KEY, VALIDATOR_CONFIG_KEY
21+
from pydantic.class_validators import (
22+
ROOT_VALIDATOR_CONFIG_KEY,
23+
VALIDATOR_CONFIG_KEY,
24+
extract_validators,
25+
inherit_validators,
26+
)
2127
from pydantic.fields import FieldInfo, ModelField, Validator
2228

2329
from fastapi_jsonapi.data_typing import TypeSchema
@@ -378,6 +384,51 @@ def create_relationship_data_schema(
378384
self.relationship_schema_cache[cache_key] = relationship_data_schema
379385
return relationship_data_schema
380386

387+
def deduplicate_field_validators(self, validators: dict) -> dict:
388+
result_validators = {}
389+
390+
for field_name, field_validators in validators.items():
391+
result_validators[field_name] = list(
392+
{
393+
# override in definition order
394+
field_validator.func.__name__: field_validator
395+
for field_validator in field_validators
396+
}.values(),
397+
)
398+
399+
return result_validators
400+
401+
def prepare_validators(self, model: Type[BaseModel]):
402+
validators = inherit_validators(
403+
extract_validators(model.__dict__),
404+
deepcopy(model.__validators__),
405+
)
406+
validators = self.deduplicate_field_validators(validators)
407+
validator_origin_param_keys = (
408+
"pre",
409+
"each_item",
410+
"always",
411+
"check_fields",
412+
)
413+
414+
result_validators = {}
415+
for field_name, field_validators in validators.items():
416+
field_validator: Validator
417+
for field_validator in field_validators:
418+
validator_name = f"{field_name}_{field_validator.func.__name__}_validator"
419+
validator_params = {
420+
# copy validator params
421+
param_key: getattr(field_validator, param_key)
422+
for param_key in validator_origin_param_keys
423+
}
424+
result_validators[validator_name] = validator(
425+
field_name,
426+
**validator_params,
427+
allow_reuse=True,
428+
)(field_validator.func)
429+
430+
return result_validators
431+
381432
def _is_target_validator(self, attr_name: str, value: Any, validator_config_key: str) -> bool:
382433
"""
383434
True if passed object is validator of type identified by "validator_config_key" arg

0 commit comments

Comments
 (0)