@@ -165,6 +165,8 @@ def validate_default(cls, value: Any) -> Optional[Any]:
165
165
return None
166
166
if isinstance (value , SecretStr ):
167
167
return value .get_secret_value ()
168
+ if isinstance (value , bool ):
169
+ return str (value ).lower ()
168
170
return value
169
171
170
172
@field_validator ("type" , mode = "before" )
@@ -175,6 +177,24 @@ def validate_type(cls, value: Any) -> str:
175
177
176
178
origin = get_origin (value )
177
179
args = get_args (value )
180
+
181
+ def type_to_str (t : type [Any ]) -> str :
182
+ if lenient_issubclass (value , str ):
183
+ return "str"
184
+ if lenient_issubclass (value , Enum ):
185
+ # Get the name of the first enum member type
186
+ # Will fail if enum has no members
187
+ return str (list (value )[0 ]) # pyright: ignore[reportUnknownArgumentType]
188
+ # Types that are represented as strings in config (paths, secrets, etc.)
189
+ if typ := TYPE_MAP .get (t ):
190
+ return typ
191
+ # Primitives and built-in generics (str, int, list[str], dict[str, int], etc.)
192
+ if origin in TYPE_CAN_STR :
193
+ return str (value )
194
+ # Fall back on the string representation of the type
195
+ return getattr (value , "__name__" , str (value ))
196
+
197
+ # Handle generics, literals, etc.
178
198
if origin and args :
179
199
# Get the name of the first type in the Literal type
180
200
# NOTE: we expect that Literal is only used with a single type
@@ -183,26 +203,11 @@ def validate_type(cls, value: Any) -> str:
183
203
# Get first non-None type in Union
184
204
# NOTE: we expect that the config does not have unions of more than 2 types
185
205
elif origin is Union and args :
186
- return next (a .__name__ for a in args if a is not type (None ))
187
-
188
- if lenient_issubclass (value , str ):
189
- return "str"
190
-
191
- if lenient_issubclass (value , Enum ):
192
- # Get the name of the first enum member type
193
- # Will fail if enum has no members
194
- return str (list (value )[0 ]) # pyright: ignore[reportUnknownArgumentType]
195
-
196
- # Types that are represented as strings in config (paths, secrets, etc.)
197
- if t := TYPE_MAP .get (value ):
198
- return t
199
-
200
- # Primitives and built-in generics (str, int, list[str], dict[str, int], etc.)
201
- if origin in TYPE_CAN_STR :
202
- return str (value )
206
+ # Strip None from the Union
207
+ ar = (type_to_str (a ) for a in args if a is not type (None ))
208
+ return " | " .join (ar )
203
209
204
- # Fall back on the string representation of the type
205
- return getattr (value , "__name__" , str (value ))
210
+ return type_to_str (value )
206
211
207
212
@field_validator ("description" , mode = "before" )
208
213
@classmethod
0 commit comments