Created
June 15, 2019 06:33
-
-
Save dmontagu/18bba9f3b748e525319e909a508a45a4 to your computer and use it in GitHub Desktop.
Inherit from APIModel instead of BaseModel to get from_orm functionality
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Any, Dict, Set, Type, TypeVar | |
from pydantic import BaseConfig, BaseModel, ConfigError, DictError, validate_model | |
from pydantic.utils import change_exception | |
Model = TypeVar("Model", bound=BaseModel) | |
class APIModel(BaseModel): | |
class Config(BaseConfig): | |
orm_mode = True | |
@classmethod | |
def validate(cls: Type["Model"], value: Any) -> "Model": | |
if isinstance(value, dict): | |
return cls(**value) | |
elif isinstance(value, cls): | |
return value.copy() | |
elif cls.__config__.orm_mode: | |
return cls.from_orm(value) | |
else: | |
with change_exception(DictError, TypeError, ValueError): | |
return cls(**dict(value)) | |
@classmethod | |
def from_orm(cls: Type["Model"], obj: Any) -> "Model": | |
if not cls.__config__.orm_mode: | |
raise ConfigError("You must have the config attribute orm_mode=True to use from_orm") | |
obj = cls._decompose_class(obj) | |
m = cls.__new__(cls) | |
values, fields_set, _ = validate_model(m, obj) | |
object.__setattr__(m, "__values__", values) | |
object.__setattr__(m, "__fields_set__", fields_set) | |
return m | |
@classmethod | |
def _decompose_class(cls: Type["Model"], obj: Any) -> "GetterDict": | |
return GetterDict(obj) | |
class GetterDict: | |
""" | |
Hack to make object's smell just enough like dicts for validate_model. | |
""" | |
__slots__ = ("_obj",) | |
def __init__(self, obj: Any): | |
self._obj = obj | |
def get(self, item: Any, default: Any) -> Any: | |
return getattr(self._obj, item, default) | |
def keys(self) -> Set[Any]: | |
""" | |
We don't want to get any other attributes of obj if the model didn't explicitly ask for them | |
""" | |
return set() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment