|
@@ -62,6 +62,13 @@ try:
|
|
except ModuleNotFoundError:
|
|
except ModuleNotFoundError:
|
|
import pydantic
|
|
import pydantic
|
|
|
|
|
|
|
|
+from pydantic import BaseModel as BaseModelV2
|
|
|
|
+
|
|
|
|
+try:
|
|
|
|
+ from pydantic.v1 import BaseModel as BaseModelV1
|
|
|
|
+except ModuleNotFoundError:
|
|
|
|
+ BaseModelV1 = BaseModelV2
|
|
|
|
+
|
|
import wrapt
|
|
import wrapt
|
|
from redis.asyncio import Redis
|
|
from redis.asyncio import Redis
|
|
from redis.exceptions import ResponseError
|
|
from redis.exceptions import ResponseError
|
|
@@ -1250,7 +1257,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
if parent_state is not None:
|
|
if parent_state is not None:
|
|
return getattr(parent_state, name)
|
|
return getattr(parent_state, name)
|
|
|
|
|
|
- if isinstance(value, MutableProxy.__mutable_types__) and (
|
|
|
|
|
|
+ if MutableProxy._is_mutable_type(value) and (
|
|
name in super().__getattribute__("base_vars") or name in backend_vars
|
|
name in super().__getattribute__("base_vars") or name in backend_vars
|
|
):
|
|
):
|
|
# track changes in mutable containers (list, dict, set, etc)
|
|
# track changes in mutable containers (list, dict, set, etc)
|
|
@@ -3558,7 +3565,16 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
pydantic.BaseModel.__dict__
|
|
pydantic.BaseModel.__dict__
|
|
)
|
|
)
|
|
|
|
|
|
- __mutable_types__ = (list, dict, set, Base, DeclarativeBase)
|
|
|
|
|
|
+ # These types will be wrapped in MutableProxy
|
|
|
|
+ __mutable_types__ = (
|
|
|
|
+ list,
|
|
|
|
+ dict,
|
|
|
|
+ set,
|
|
|
|
+ Base,
|
|
|
|
+ DeclarativeBase,
|
|
|
|
+ BaseModelV2,
|
|
|
|
+ BaseModelV1,
|
|
|
|
+ )
|
|
|
|
|
|
def __init__(self, wrapped: Any, state: BaseState, field_name: str):
|
|
def __init__(self, wrapped: Any, state: BaseState, field_name: str):
|
|
"""Create a proxy for a mutable object that tracks changes.
|
|
"""Create a proxy for a mutable object that tracks changes.
|
|
@@ -3598,6 +3614,18 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
if wrapped is not None:
|
|
if wrapped is not None:
|
|
return wrapped(*args, **(kwargs or {}))
|
|
return wrapped(*args, **(kwargs or {}))
|
|
|
|
|
|
|
|
+ @classmethod
|
|
|
|
+ def _is_mutable_type(cls, value: Any) -> bool:
|
|
|
|
+ """Check if a value is of a mutable type and should be wrapped.
|
|
|
|
+
|
|
|
|
+ Args:
|
|
|
|
+ value: The value to check.
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ Whether the value is of a mutable type.
|
|
|
|
+ """
|
|
|
|
+ return isinstance(value, cls.__mutable_types__)
|
|
|
|
+
|
|
def _wrap_recursive(self, value: Any) -> Any:
|
|
def _wrap_recursive(self, value: Any) -> Any:
|
|
"""Wrap a value recursively if it is mutable.
|
|
"""Wrap a value recursively if it is mutable.
|
|
|
|
|
|
@@ -3608,9 +3636,7 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
The wrapped value.
|
|
The wrapped value.
|
|
"""
|
|
"""
|
|
# Recursively wrap mutable types, but do not re-wrap MutableProxy instances.
|
|
# Recursively wrap mutable types, but do not re-wrap MutableProxy instances.
|
|
- if isinstance(value, self.__mutable_types__) and not isinstance(
|
|
|
|
- value, MutableProxy
|
|
|
|
- ):
|
|
|
|
|
|
+ if self._is_mutable_type(value) and not isinstance(value, MutableProxy):
|
|
return type(self)(
|
|
return type(self)(
|
|
wrapped=value,
|
|
wrapped=value,
|
|
state=self._self_state,
|
|
state=self._self_state,
|
|
@@ -3668,7 +3694,7 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
self._wrap_recursive_decorator,
|
|
self._wrap_recursive_decorator,
|
|
)
|
|
)
|
|
|
|
|
|
- if isinstance(value, self.__mutable_types__) and __name not in (
|
|
|
|
|
|
+ if self._is_mutable_type(value) and __name not in (
|
|
"__wrapped__",
|
|
"__wrapped__",
|
|
"_self_state",
|
|
"_self_state",
|
|
):
|
|
):
|