66from osbot_utils .decorators .lists .index_by import index_by
77from osbot_utils .type_safe .Type_Safe__Primitive import Type_Safe__Primitive
88from fastapi .exceptions import RequestValidationError
9+ from osbot_utils .type_safe .shared .Type_Safe__Cache import type_safe_cache
910from osbot_fast_api .utils .type_safe .Type_Safe__To__BaseModel import type_safe__to__basemodel
1011
1112
@@ -31,15 +32,23 @@ def add_route_with_body(self, function, methods):
3132 sig = inspect .signature (function )
3233 type_hints = get_type_hints (function )
3334
34- # Find Type_Safe parameters and convert them to BaseModel classes
3535 type_safe_conversions = {}
36+ primitive_field_types = {} # Track which fields are Type_Safe__Primitive
3637
3738 for param_name , param in sig .parameters .items ():
3839 if param_name == 'self' :
3940 continue
4041 param_type = type_hints .get (param_name )
4142 if param_type and inspect .isclass (param_type ):
4243 if issubclass (param_type , Type_Safe ) and not issubclass (param_type , Type_Safe__Primitive ):
44+
45+ annotations = type_safe_cache .get_class_annotations (param_type ) # For Type_Safe classes, also track their primitive fields
46+ for field_name , field_type in annotations :
47+ if isinstance (field_type , type ) and issubclass (field_type , Type_Safe__Primitive ):
48+ if param_name not in primitive_field_types :
49+ primitive_field_types [param_name ] = {}
50+ primitive_field_types [param_name ][field_name ] = field_type
51+
4352 basemodel_class = type_safe__to__basemodel .convert_class (param_type )
4453 type_safe_conversions [param_name ] = (param_type , basemodel_class )
4554
@@ -51,17 +60,27 @@ def wrapper(**kwargs):
5160 if param_name in type_safe_conversions :
5261 type_safe_class , _ = type_safe_conversions [param_name ]
5362 if isinstance (param_value , dict ):
63+ # Convert primitive fields back to Type_Safe__Primitive instances
64+ if param_name in primitive_field_types :
65+ for field_name , primitive_class in primitive_field_types [param_name ].items ():
66+ if field_name in param_value :
67+ param_value [field_name ] = primitive_class (param_value [field_name ])
5468 converted_kwargs [param_name ] = type_safe_class (** param_value )
5569 else :
56- data = param_value .model_dump () # Get the data from BaseModel
57- converted_kwargs [param_name ] = type_safe_class (** data ) # Create instance of original Type_Safe class
70+ data = param_value .model_dump ()
71+ # Convert primitive fields here too
72+ if param_name in primitive_field_types :
73+ for field_name , primitive_class in primitive_field_types [param_name ].items ():
74+ if field_name in data :
75+ data [field_name ] = primitive_class (data [field_name ])
76+ converted_kwargs [param_name ] = type_safe_class (** data )
5877 else :
5978 converted_kwargs [param_name ] = param_value
6079
6180 try :
6281 result = function (** converted_kwargs )
6382 except Exception as e :
64- raise HTTPException (status_code = 400 , detail = f"{ type (e ).__name__ } : { e } " ) # Convert business logic validation errors to HTTP 400
83+ raise HTTPException (status_code = 400 , detail = f"{ type (e ).__name__ } : { e } " )
6584
6685 if isinstance (result , Type_Safe ):
6786 return type_safe__to__basemodel .convert_instance (result ).model_dump ()
0 commit comments