feat: adds support for list of types
This commit is contained in:
@@ -73,10 +73,41 @@ class GenericTypeParser(ABC, Generic[T]):
|
|||||||
:param kwargs: Additional options for type parsing.
|
:param kwargs: Additional options for type parsing.
|
||||||
:return: A tuple containing the type and its properties.
|
:return: A tuple containing the type and its properties.
|
||||||
"""
|
"""
|
||||||
parser = cls._get_impl(properties)
|
|
||||||
|
parser = cls._get_impl(
|
||||||
|
cls._normalize_properties(properties)
|
||||||
|
)
|
||||||
|
|
||||||
return parser().from_properties(name=name, properties=properties, **kwargs)
|
return parser().from_properties(name=name, properties=properties, **kwargs)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _normalize_properties(properties: JSONSchema) -> JSONSchema:
|
||||||
|
"""
|
||||||
|
Normalizes the properties dictionary to ensure consistent structure.
|
||||||
|
:param properties: The properties to be normalized.
|
||||||
|
"""
|
||||||
|
type_value = properties.pop("type", None)
|
||||||
|
|
||||||
|
if isinstance(type_value, str):
|
||||||
|
properties["type"] = type_value
|
||||||
|
return properties
|
||||||
|
|
||||||
|
if isinstance(type_value, list) and len(type_value) == 0:
|
||||||
|
raise InvalidSchemaException(
|
||||||
|
"Invalid schema: 'type' list cannot be empty", invalid_field=str(properties)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if isinstance(type_value, list) and len(type_value) == 1:
|
||||||
|
properties["type"] = type_value[0]
|
||||||
|
return properties
|
||||||
|
|
||||||
|
if isinstance(type_value, list):
|
||||||
|
properties["anyOf"] = [{"type": t} for t in type_value]
|
||||||
|
return properties
|
||||||
|
|
||||||
|
return properties
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_impl(cls, properties: JSONSchema) -> type[Self]:
|
def _get_impl(cls, properties: JSONSchema) -> type[Self]:
|
||||||
for subcls in cls.__subclasses__():
|
for subcls in cls.__subclasses__():
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from jambo.exceptions import InvalidSchemaException, UnsupportedSchemaException
|
from jambo.exceptions import InternalAssertionException, InvalidSchemaException, UnsupportedSchemaException
|
||||||
from jambo.parser import ObjectTypeParser, RefTypeParser
|
from jambo.parser import ObjectTypeParser, RefTypeParser
|
||||||
from jambo.types import JSONSchema, RefCacheDict
|
from jambo.types import JSONSchema, RefCacheDict
|
||||||
|
|
||||||
@@ -136,4 +136,11 @@ class SchemaConverter:
|
|||||||
if "$ref" in schema:
|
if "$ref" in schema:
|
||||||
return "$ref"
|
return "$ref"
|
||||||
|
|
||||||
return schema.get("type")
|
type_value = schema.get("type")
|
||||||
|
if isinstance(type_value, list):
|
||||||
|
raise InternalAssertionException(
|
||||||
|
"SchemaConverter._get_schema_type: 'type' field should not be a list here."
|
||||||
|
" This should have been normalized earlier."
|
||||||
|
)
|
||||||
|
|
||||||
|
return type_value
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ JSONSchema = TypedDict(
|
|||||||
"description": str,
|
"description": str,
|
||||||
"default": JSONType,
|
"default": JSONType,
|
||||||
"examples": List[JSONType],
|
"examples": List[JSONType],
|
||||||
"type": JSONSchemaType,
|
"type": JSONSchemaType|List[JSONSchemaType],
|
||||||
"enum": List[JSONType],
|
"enum": List[JSONType],
|
||||||
"const": JSONType,
|
"const": JSONType,
|
||||||
"properties": Dict[str, "JSONSchema"],
|
"properties": Dict[str, "JSONSchema"],
|
||||||
|
|||||||
@@ -998,3 +998,52 @@ class TestSchemaConverter(TestCase):
|
|||||||
cached_address_model = self.converter.get_cached_ref("address")
|
cached_address_model = self.converter.get_cached_ref("address")
|
||||||
|
|
||||||
self.assertIsNotNone(cached_address_model)
|
self.assertIsNotNone(cached_address_model)
|
||||||
|
|
||||||
|
def test_parse_list_type_multiple_values(self):
|
||||||
|
schema = {
|
||||||
|
"title": "TestListType",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"values": {
|
||||||
|
"type": ["string", "number"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Model = self.converter.build_with_cache(schema)
|
||||||
|
|
||||||
|
obj1 = Model(values="a string")
|
||||||
|
self.assertEqual(obj1.values, "a string")
|
||||||
|
|
||||||
|
obj2 = Model(values=42)
|
||||||
|
self.assertEqual(obj2.values, 42)
|
||||||
|
|
||||||
|
def test_parse_list_type_one_value(self):
|
||||||
|
schema = {
|
||||||
|
"title": "TestListType",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"values": {
|
||||||
|
"type": ["string"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Model = self.converter.build_with_cache(schema)
|
||||||
|
|
||||||
|
obj1 = Model(values="a string")
|
||||||
|
self.assertEqual(obj1.values, "a string")
|
||||||
|
|
||||||
|
def test_parse_list_type_empty(self):
|
||||||
|
schema = {
|
||||||
|
"title": "TestListType",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"values": {
|
||||||
|
"type": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
with self.assertRaises(InvalidSchemaException):
|
||||||
|
self.converter.build_with_cache(schema)
|
||||||
Reference in New Issue
Block a user