Skip to content

Commit

Permalink
serialize uuid and allow overwriting serializers (#4888)
Browse files Browse the repository at this point in the history
* serialize uuid and allow overwriting serializers

* add frame info

* reword place info
  • Loading branch information
adhami3310 authored Mar 1, 2025
1 parent 3905df5 commit 33714aa
Showing 1 changed file with 38 additions and 4 deletions.
42 changes: 38 additions & 4 deletions reflex/utils/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import contextlib
import dataclasses
import functools
import inspect
import json
import warnings
from datetime import date, datetime, time, timedelta
Expand All @@ -21,13 +22,14 @@
get_type_hints,
overload,
)
from uuid import UUID

from pydantic import BaseModel as BaseModelV2
from pydantic.v1 import BaseModel as BaseModelV1

from reflex.base import Base
from reflex.constants.colors import Color, format_color
from reflex.utils import types
from reflex.utils import console, types

# Mapping from type to a serializer.
# The serializer should convert the type to a JSON object.
Expand All @@ -47,25 +49,29 @@
def serializer(
fn: None = None,
to: Type[SerializedType] | None = None,
overwrite: bool | None = None,
) -> Callable[[SERIALIZED_FUNCTION], SERIALIZED_FUNCTION]: ...


@overload
def serializer(
fn: SERIALIZED_FUNCTION,
to: Type[SerializedType] | None = None,
overwrite: bool | None = None,
) -> SERIALIZED_FUNCTION: ...


def serializer(
fn: SERIALIZED_FUNCTION | None = None,
to: Any = None,
overwrite: bool | None = None,
) -> SERIALIZED_FUNCTION | Callable[[SERIALIZED_FUNCTION], SERIALIZED_FUNCTION]:
"""Decorator to add a serializer for a given type.
Args:
fn: The function to decorate.
to: The type returned by the serializer. If this is `str`, then any Var created from this type will be treated as a string.
overwrite: Whether to overwrite the existing serializer.
Returns:
The decorated function.
Expand All @@ -85,9 +91,24 @@ def wrapper(fn: SERIALIZED_FUNCTION) -> SERIALIZED_FUNCTION:

# Make sure the type is not already registered.
registered_fn = SERIALIZERS.get(type_)
if registered_fn is not None and registered_fn != fn:
raise ValueError(
f"Serializer for type {type_} is already registered as {registered_fn.__qualname__}."
if registered_fn is not None and registered_fn != fn and overwrite is not True:
message = f"Overwriting serializer for type {type_} from {registered_fn.__module__}:{registered_fn.__qualname__} to {fn.__module__}:{fn.__qualname__}."
if overwrite is False:
raise ValueError(message)
caller_frame = next(
filter(
lambda frame: frame.filename != __file__,
inspect.getouterframes(inspect.currentframe()),
),
None,
)
file_info = (
f"(at {caller_frame.filename}:{caller_frame.lineno})"
if caller_frame
else ""
)
console.warn(
f"{message} Call rx.serializer with `overwrite=True` if this is intentional. {file_info}"
)

to_type = to or type_hints.get("return")
Expand Down Expand Up @@ -351,6 +372,19 @@ def serialize_enum(en: Enum) -> str:
return en.value


@serializer(to=str)
def serialize_uuid(uuid: UUID) -> str:
"""Serialize a UUID to a JSON string.
Args:
uuid: The UUID to serialize.
Returns:
The serialized UUID.
"""
return str(uuid)


@serializer(to=str)
def serialize_color(color: Color) -> str:
"""Serialize a color.
Expand Down

0 comments on commit 33714aa

Please sign in to comment.