You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_serialization.py 5.0 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. from dataclasses import dataclass
  2. from typing import Union
  3. import pytest
  4. from autogen_core.base import (
  5. JSON_DATA_CONTENT_TYPE,
  6. MessageSerializer,
  7. SerializationRegistry,
  8. try_get_known_serializers_for_type,
  9. )
  10. from autogen_core.base._serialization import DataclassJsonMessageSerializer, PydanticJsonMessageSerializer
  11. from autogen_core.components import Image
  12. from PIL import Image as PILImage
  13. from pydantic import BaseModel
  14. class PydanticMessage(BaseModel):
  15. message: str
  16. class NestingPydanticMessage(BaseModel):
  17. message: str
  18. nested: PydanticMessage
  19. @dataclass
  20. class DataclassMessage:
  21. message: str
  22. @dataclass
  23. class NestingDataclassMessage:
  24. message: str
  25. nested: DataclassMessage
  26. @dataclass
  27. class NestingPydanticDataclassMessage:
  28. message: str
  29. nested: PydanticMessage
  30. def test_pydantic() -> None:
  31. serde = SerializationRegistry()
  32. serde.add_serializer(try_get_known_serializers_for_type(PydanticMessage))
  33. message = PydanticMessage(message="hello")
  34. name = serde.type_name(message)
  35. json = serde.serialize(message, type_name=name, data_content_type=JSON_DATA_CONTENT_TYPE)
  36. assert name == "PydanticMessage"
  37. assert json == b'{"message":"hello"}'
  38. deserialized = serde.deserialize(json, type_name=name, data_content_type=JSON_DATA_CONTENT_TYPE)
  39. assert deserialized == message
  40. def test_nested_pydantic() -> None:
  41. serde = SerializationRegistry()
  42. serde.add_serializer(try_get_known_serializers_for_type(NestingPydanticMessage))
  43. message = NestingPydanticMessage(message="hello", nested=PydanticMessage(message="world"))
  44. name = serde.type_name(message)
  45. json = serde.serialize(message, type_name=name, data_content_type=JSON_DATA_CONTENT_TYPE)
  46. assert json == b'{"message":"hello","nested":{"message":"world"}}'
  47. deserialized = serde.deserialize(json, type_name=name, data_content_type=JSON_DATA_CONTENT_TYPE)
  48. assert deserialized == message
  49. def test_dataclass() -> None:
  50. serde = SerializationRegistry()
  51. serde.add_serializer(try_get_known_serializers_for_type(DataclassMessage))
  52. message = DataclassMessage(message="hello")
  53. name = serde.type_name(message)
  54. json = serde.serialize(message, type_name=name, data_content_type=JSON_DATA_CONTENT_TYPE)
  55. assert json == b'{"message": "hello"}'
  56. deserialized = serde.deserialize(json, type_name=name, data_content_type=JSON_DATA_CONTENT_TYPE)
  57. assert deserialized == message
  58. def test_nesting_dataclass_dataclass() -> None:
  59. serde = SerializationRegistry()
  60. with pytest.raises(ValueError):
  61. serde.add_serializer(try_get_known_serializers_for_type(NestingDataclassMessage))
  62. @dataclass
  63. class DataclassNestedUnionSyntaxOldMessage:
  64. message: Union[str, int]
  65. @dataclass
  66. class DataclassNestedUnionSyntaxNewMessage:
  67. message: str | int
  68. @pytest.mark.parametrize("cls", [DataclassNestedUnionSyntaxOldMessage, DataclassNestedUnionSyntaxNewMessage])
  69. def test_nesting_union_old_syntax_dataclass(
  70. cls: type[DataclassNestedUnionSyntaxOldMessage | DataclassNestedUnionSyntaxNewMessage],
  71. ) -> None:
  72. with pytest.raises(ValueError):
  73. _serializer = DataclassJsonMessageSerializer(cls)
  74. def test_nesting_dataclass_pydantic() -> None:
  75. serde = SerializationRegistry()
  76. with pytest.raises(ValueError):
  77. serde.add_serializer(try_get_known_serializers_for_type(NestingPydanticDataclassMessage))
  78. def test_invalid_type() -> None:
  79. serde = SerializationRegistry()
  80. try:
  81. serde.add_serializer(try_get_known_serializers_for_type(str))
  82. except ValueError as e:
  83. assert str(e) == "Unsupported type <class 'str'>"
  84. def test_custom_type() -> None:
  85. serde = SerializationRegistry()
  86. class CustomStringTypeSerializer(MessageSerializer[str]):
  87. @property
  88. def data_content_type(self) -> str:
  89. return "str"
  90. @property
  91. def type_name(self) -> str:
  92. return "custom_str"
  93. def deserialize(self, payload: bytes) -> str:
  94. message = payload.decode("utf-8")
  95. return message[1:-1]
  96. def serialize(self, message: str) -> bytes:
  97. return f'"{message}"'.encode("utf-8")
  98. serde.add_serializer(CustomStringTypeSerializer())
  99. message = "hello"
  100. json = serde.serialize(message, type_name="custom_str", data_content_type="str")
  101. assert json == b'"hello"'
  102. deserialized = serde.deserialize(json, type_name="custom_str", data_content_type="str")
  103. assert deserialized == message
  104. def test_image_type() -> None:
  105. pil_image = PILImage.new("RGB", (100, 100))
  106. image = Image(pil_image)
  107. class PydanticImageMessage(BaseModel):
  108. image: Image
  109. serializer = PydanticJsonMessageSerializer(PydanticImageMessage)
  110. json = serializer.serialize(PydanticImageMessage(image=image))
  111. deserialized = serializer.deserialize(json)
  112. assert deserialized.image.image.size == (100, 100)
  113. assert deserialized.image.image.mode == "RGB"
  114. assert deserialized.image.image == image.image