Skip to content

Commit 56e7d32

Browse files
authored
Allow using pydantic for from_dict, schema for FastList (#479)
* Allow using pydantic for from_dict, schema for FastList --------- Signed-off-by: Nijat Khanbabayev <[email protected]>
1 parent 81483c8 commit 56e7d32

File tree

3 files changed

+134
-56
lines changed

3 files changed

+134
-56
lines changed

csp/impl/struct.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,18 @@ def serializer(val, handler):
151151

152152

153153
class Struct(_csptypesimpl.PyStruct, metaclass=StructMeta):
154+
@classmethod
155+
def type_adapter(cls):
156+
internal_type_adapter = getattr(cls, "_pydantic_type_adapter", None)
157+
if internal_type_adapter:
158+
return internal_type_adapter
159+
160+
# Late import to avoid autogen issues
161+
from pydantic import TypeAdapter
162+
163+
cls._pydantic_type_adapter = TypeAdapter(cls)
164+
return cls._pydantic_type_adapter
165+
154166
@classmethod
155167
def metadata(cls, typed=False):
156168
if typed:
@@ -235,7 +247,9 @@ def _obj_from_python(cls, json, obj_type):
235247
return obj_type(json)
236248

237249
@classmethod
238-
def from_dict(cls, json: dict):
250+
def from_dict(cls, json: dict, use_pydantic: bool = False):
251+
if use_pydantic:
252+
return cls.type_adapter().validate_python(json)
239253
return cls._obj_from_python(json, cls)
240254

241255
def to_dict_depr(self):

csp/impl/types/typing_utils.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,33 @@ class FastList(typing.List, typing.Generic[T]): # Need to inherit from Generic[
1515
def __init__(self):
1616
raise NotImplementedError("Can not init FastList class")
1717

18+
@classmethod
19+
def __get_pydantic_core_schema__(cls, source_type, handler):
20+
from pydantic_core import core_schema
21+
22+
# Late import to not interfere with autogen
23+
args = typing.get_args(source_type)
24+
if args:
25+
inner_type = args[0]
26+
list_schema = handler.generate_schema(typing.List[inner_type])
27+
else:
28+
list_schema = handler.generate_schema(typing.List)
29+
30+
def create_instance(raw_data, validator):
31+
if isinstance(raw_data, FastList):
32+
return raw_data
33+
return validator(raw_data) # just return a list
34+
35+
return core_schema.no_info_wrap_validator_function(
36+
function=create_instance,
37+
schema=list_schema,
38+
serialization=core_schema.plain_serializer_function_ser_schema(
39+
lambda val: list(v for v in val),
40+
return_schema=list_schema,
41+
when_used="json",
42+
),
43+
)
44+
1845

1946
class CspTypingUtils39:
2047
_ORIGIN_COMPAT_MAP = {list: typing.List, set: typing.Set, dict: typing.Dict, tuple: typing.Tuple}

0 commit comments

Comments
 (0)