1+ import contextlib
2+ import datetime
13import inspect
24from enum import Enum
35from typing import Any , Callable , NamedTuple , Optional , cast , get_type_hints
46
5- from pydantic import BaseModel
7+ from pydantic import BaseModel , TypeAdapter
68
79from workflowai .core .utils ._schema_generator import JsonSchemaGenerator
810
@@ -15,6 +17,14 @@ class SchemaDeserializer(NamedTuple):
1517 deserializer : Optional [Callable [[Any ], Any ]] = None
1618
1719
20+ def _serialize_datetime (x : datetime .datetime ) -> str :
21+ return x .isoformat ()
22+
23+
24+ def _deserialize_datetime (x : str ) -> datetime .datetime :
25+ return datetime .datetime .fromisoformat (x )
26+
27+
1828def _get_type_schema (param_type : type ):
1929 """Convert a Python type to its corresponding JSON schema type.
2030
@@ -24,10 +34,6 @@ def _get_type_schema(param_type: type):
2434 Returns:
2535 A dictionary containing the JSON schema type definition
2636 """
27- if issubclass (param_type , Enum ):
28- if not issubclass (param_type , str ):
29- raise ValueError (f"Non string enums are not supported: { param_type } " )
30- return SchemaDeserializer ({"type" : "string" , "enum" : [e .value for e in param_type ]})
3137
3238 if param_type is str :
3339 return SchemaDeserializer ({"type" : "string" })
@@ -41,11 +47,33 @@ def _get_type_schema(param_type: type):
4147 if param_type is bool :
4248 return SchemaDeserializer ({"type" : "boolean" })
4349
44- if issubclass (param_type , BaseModel ):
50+ if param_type is datetime .datetime :
51+ return SchemaDeserializer (
52+ {"type" : "string" , "format" : "date-time" },
53+ serializer = _serialize_datetime ,
54+ deserializer = _deserialize_datetime ,
55+ )
56+
57+ if inspect .isclass (param_type ):
58+ if issubclass (param_type , BaseModel ):
59+ return SchemaDeserializer (
60+ schema = param_type .model_json_schema (by_alias = True , schema_generator = JsonSchemaGenerator ),
61+ serializer = lambda x : cast (BaseModel , x ).model_dump (mode = "json" ), # pyright: ignore [reportUnknownLambdaType]
62+ deserializer = param_type .model_validate ,
63+ )
64+
65+ if issubclass (param_type , Enum ):
66+ if not issubclass (param_type , str ):
67+ raise ValueError (f"Non string enums are not supported: { param_type } " )
68+ return SchemaDeserializer ({"type" : "string" , "enum" : [e .value for e in param_type ]})
69+
70+ # Attempting to build a type adapter with pydantic
71+ with contextlib .suppress (Exception ):
72+ adapter = TypeAdapter [Any ](param_type )
4573 return SchemaDeserializer (
46- schema = param_type . model_json_schema ( by_alias = True , schema_generator = JsonSchemaGenerator ),
47- serializer = lambda x : cast ( BaseModel , x ). model_dump ( mode = "json" ) , # pyright: ignore [reportUnknownLambdaType]
48- deserializer = param_type . model_validate ,
74+ schema = adapter . json_schema ( ),
75+ deserializer = adapter . validate_python , # pyright: ignore [reportUnknownLambdaType]
76+ serializer = lambda x : adapter . dump_python ( x , mode = "json" ), # pyright: ignore [reportUnknownLambdaType]
4977 )
5078
5179 raise ValueError (f"Unsupported type: { param_type } " )
0 commit comments