fix(jambo): skip Annotated wrapping for trivial anyOf field constraints (#3)
This commit is contained in:
@@ -34,8 +34,34 @@ class AnyOfTypeParser(GenericTypeParser):
|
|||||||
# By defining the type as Union of Annotated type we can use the Field validator
|
# By defining the type as Union of Annotated type we can use the Field validator
|
||||||
# to enforce the constraints of each union type when needed.
|
# to enforce the constraints of each union type when needed.
|
||||||
# We use Annotated to attach the Field validators to the type.
|
# We use Annotated to attach the Field validators to the type.
|
||||||
|
# Only wrap in Annotated[T, Field(**v)] if there are meaningful field constraints
|
||||||
|
# Don't wrap for simple cases where v only contains {'default': None}
|
||||||
field_types = [
|
field_types = [
|
||||||
Annotated[t, Field(**v)] if v is not None else t for t, v in sub_types
|
Annotated[t, Field(**v)] if self._has_meaningful_constraints(v) else t
|
||||||
|
for t, v in sub_types
|
||||||
]
|
]
|
||||||
|
|
||||||
return Union[(*field_types,)], mapped_properties
|
return Union[(*field_types,)], mapped_properties
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _has_meaningful_constraints(field_props):
|
||||||
|
"""
|
||||||
|
Check if field properties contain meaningful constraints that require Field wrapping.
|
||||||
|
|
||||||
|
Returns False if:
|
||||||
|
- field_props is None or empty
|
||||||
|
- field_props only contains {'default': None}
|
||||||
|
|
||||||
|
Returns True if:
|
||||||
|
- field_props contains a non-None default value
|
||||||
|
- field_props contains other constraint properties (min_length, max_length, pattern, etc.)
|
||||||
|
"""
|
||||||
|
if not field_props:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# If only default is set and it's None, no meaningful constraints
|
||||||
|
if len(field_props) == 1 and field_props.get('default') is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# If there are multiple properties or non-None default, that's meaningful
|
||||||
|
return True
|
||||||
@@ -46,11 +46,8 @@ class TestAnyOfTypeParser(TestCase):
|
|||||||
|
|
||||||
type_1, type_2 = get_args(type_parsing)
|
type_1, type_2 = get_args(type_parsing)
|
||||||
|
|
||||||
self.assertEqual(get_origin(type_1), Annotated)
|
self.assertEqual(type_1, str)
|
||||||
self.assertIn(str, get_args(type_1))
|
self.assertEqual(type_2, int)
|
||||||
|
|
||||||
self.assertEqual(get_origin(type_2), Annotated)
|
|
||||||
self.assertIn(int, get_args(type_2))
|
|
||||||
|
|
||||||
def test_any_of_string_or_int_with_default(self):
|
def test_any_of_string_or_int_with_default(self):
|
||||||
"""
|
"""
|
||||||
@@ -74,11 +71,8 @@ class TestAnyOfTypeParser(TestCase):
|
|||||||
|
|
||||||
type_1, type_2 = get_args(type_parsing)
|
type_1, type_2 = get_args(type_parsing)
|
||||||
|
|
||||||
self.assertEqual(get_origin(type_1), Annotated)
|
self.assertEqual(type_1, str)
|
||||||
self.assertIn(str, get_args(type_1))
|
self.assertEqual(type_2, int)
|
||||||
|
|
||||||
self.assertEqual(get_origin(type_2), Annotated)
|
|
||||||
self.assertIn(int, get_args(type_2))
|
|
||||||
|
|
||||||
self.assertEqual(type_validator["default"], 42)
|
self.assertEqual(type_validator["default"], 42)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user