]> git.ipfire.org Git - thirdparty/fastapi/sqlmodel.git/commitdiff
🐛 Fix class initialization compatibility with Pydantic and SQLModel, fixing errors...
authorSebastián Ramírez <tiangolo@gmail.com>
Sat, 17 Feb 2024 13:34:57 +0000 (14:34 +0100)
committerGitHub <noreply@github.com>
Sat, 17 Feb 2024 13:34:57 +0000 (13:34 +0000)
.github/workflows/test.yml
sqlmodel/_compat.py
sqlmodel/main.py

index ade60f255968a398ee8449b47e539f7d14be9f05..89da640d1502ee1d39366050a74ba7923f0fa77a 100644 (file)
@@ -62,10 +62,10 @@ jobs:
         run: python -m poetry install
       - name: Install Pydantic v1
         if: matrix.pydantic-version == 'pydantic-v1'
-        run: pip install "pydantic>=1.10.0,<2.0.0"
+        run: pip install --upgrade "pydantic>=1.10.0,<2.0.0"
       - name: Install Pydantic v2
         if: matrix.pydantic-version == 'pydantic-v2'
-        run: pip install "pydantic>=2.0.2,<3.0.0"
+        run: pip install --upgrade "pydantic>=2.0.2,<3.0.0"
       - name: Lint
         # Do not run on Python 3.7 as mypy behaves differently
         if: matrix.python-version != '3.7' && matrix.pydantic-version == 'pydantic-v2'
index 2a2caca3e8f69c6612cb786c64e67cd99f543e24..76771ce7ff4210a0a3925872ffd4da48e666ca3c 100644 (file)
@@ -97,10 +97,10 @@ if IS_PYDANTIC_V2:
     def get_model_fields(model: InstanceOrType["SQLModel"]) -> Dict[str, "FieldInfo"]:
         return model.model_fields
 
-    def set_fields_set(
-        new_object: InstanceOrType["SQLModel"], fields: Set["FieldInfo"]
-    ) -> None:
-        object.__setattr__(new_object, "__pydantic_fields_set__", fields)
+    def init_pydantic_private_attrs(new_object: InstanceOrType["SQLModel"]) -> None:
+        object.__setattr__(new_object, "__pydantic_fields_set__", set())
+        object.__setattr__(new_object, "__pydantic_extra__", None)
+        object.__setattr__(new_object, "__pydantic_private__", None)
 
     def get_annotations(class_dict: Dict[str, Any]) -> Dict[str, Any]:
         return class_dict.get("__annotations__", {})
@@ -387,10 +387,8 @@ else:
     def get_model_fields(model: InstanceOrType["SQLModel"]) -> Dict[str, "FieldInfo"]:
         return model.__fields__  # type: ignore
 
-    def set_fields_set(
-        new_object: InstanceOrType["SQLModel"], fields: Set["FieldInfo"]
-    ) -> None:
-        object.__setattr__(new_object, "__fields_set__", fields)
+    def init_pydantic_private_attrs(new_object: InstanceOrType["SQLModel"]) -> None:
+        object.__setattr__(new_object, "__fields_set__", set())
 
     def get_annotations(class_dict: Dict[str, Any]) -> Dict[str, Any]:
         return resolve_annotations(  # type: ignore[no-any-return]
index 10064c71165f415b1de4ec89e82164c0632e370c..fec3bc79066535930a30cbd6143d23132f9b2e01 100644 (file)
@@ -70,11 +70,11 @@ from ._compat import (  # type: ignore[attr-defined]
     get_model_fields,
     get_relationship_to,
     get_type_from_field,
+    init_pydantic_private_attrs,
     is_field_noneable,
     is_table_model_class,
     post_init_field_info,
     set_config_value,
-    set_fields_set,
     sqlmodel_init,
     sqlmodel_validate,
 )
@@ -686,12 +686,12 @@ class SQLModel(BaseModel, metaclass=SQLModelMetaclass, registry=default_registry
 
     def __new__(cls, *args: Any, **kwargs: Any) -> Any:
         new_object = super().__new__(cls)
-        # SQLAlchemy doesn't call __init__ on the base class
+        # SQLAlchemy doesn't call __init__ on the base class when querying from DB
         # Ref: https://docs.sqlalchemy.org/en/14/orm/constructors.html
         # Set __fields_set__ here, that would have been set when calling __init__
         # in the Pydantic model so that when SQLAlchemy sets attributes that are
         # added (e.g. when querying from DB) to the __fields_set__, this already exists
-        set_fields_set(new_object, set())
+        init_pydantic_private_attrs(new_object)
         return new_object
 
     def __init__(__pydantic_self__, **data: Any) -> None: