Feature/explicit exception type #47
@@ -1,3 +1,4 @@
|
||||
from jambo.exceptions import InvalidSchemaException
|
||||
from jambo.parser._type_parser import GenericTypeParser
|
||||
from jambo.types.type_parser_options import TypeParserOptions
|
||||
|
||||
@@ -14,10 +15,15 @@ class AnyOfTypeParser(GenericTypeParser):
|
||||
self, name, properties, **kwargs: Unpack[TypeParserOptions]
|
||||
):
|
||||
if "anyOf" not in properties:
|
||||
raise ValueError(f"Invalid JSON Schema: {properties}")
|
||||
raise InvalidSchemaException(
|
||||
f"AnyOf type {name} must have 'anyOf' property defined.",
|
||||
invalid_field="anyOf",
|
||||
)
|
||||
|
||||
if not isinstance(properties["anyOf"], list):
|
||||
raise ValueError(f"Invalid JSON Schema: {properties['anyOf']}")
|
||||
raise InvalidSchemaException(
|
||||
"AnyOf must be a list of types.", invalid_field="anyOf"
|
||||
)
|
||||
|
||||
mapped_properties = self.mappings_properties_builder(properties, **kwargs)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from jambo.exceptions import InvalidSchemaException
|
||||
from jambo.parser._type_parser import GenericTypeParser
|
||||
from jambo.types.type_parser_options import TypeParserOptions
|
||||
|
||||
@@ -26,8 +27,15 @@ class ArrayTypeParser(GenericTypeParser):
|
||||
):
|
||||
item_properties = kwargs.copy()
|
||||
item_properties["required"] = True
|
||||
|
||||
if (items := properties.get("items")) is None:
|
||||
raise InvalidSchemaException(
|
||||
f"Array type {name} must have 'items' property defined.",
|
||||
invalid_field="items",
|
||||
)
|
||||
|
||||
_item_type, _item_args = GenericTypeParser.type_from_properties(
|
||||
name, properties["items"], **item_properties
|
||||
name, items, **item_properties
|
||||
)
|
||||
|
||||
wrapper_type = set if properties.get("uniqueItems", False) else list
|
||||
@@ -47,8 +55,9 @@ class ArrayTypeParser(GenericTypeParser):
|
||||
return lambda: None
|
||||
|
||||
if not isinstance(default_list, Iterable):
|
||||
raise ValueError(
|
||||
f"Default value for array must be an iterable, got {type(default_list)}"
|
||||
raise InvalidSchemaException(
|
||||
f"Default value for array must be an iterable, got {type(default_list)}",
|
||||
invalid_field="default",
|
||||
)
|
||||
|
||||
return lambda: copy.deepcopy(wrapper_type(default_list))
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from jambo.exceptions import InvalidSchemaException
|
||||
from jambo.parser._type_parser import GenericTypeParser
|
||||
from jambo.types.type_parser_options import TypeParserOptions
|
||||
|
||||
@@ -20,6 +21,9 @@ class BooleanTypeParser(GenericTypeParser):
|
||||
|
||||
default_value = properties.get("default")
|
||||
if default_value is not None and not isinstance(default_value, bool):
|
||||
raise ValueError(f"Default value for {name} must be a boolean.")
|
||||
raise InvalidSchemaException(
|
||||
f"Default value for {name} must be a boolean.",
|
||||
invalid_field="default",
|
||||
)
|
||||
|
||||
return bool, mapped_properties
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from jambo.exceptions import InvalidSchemaException
|
||||
from jambo.parser._type_parser import GenericTypeParser
|
||||
from jambo.types.json_schema_type import JSONSchemaNativeTypes
|
||||
from jambo.types.type_parser_options import TypeParserOptions
|
||||
@@ -18,13 +19,17 @@ class ConstTypeParser(GenericTypeParser):
|
||||
self, name, properties, **kwargs: Unpack[TypeParserOptions]
|
||||
):
|
||||
if "const" not in properties:
|
||||
raise ValueError(f"Const type {name} must have 'const' property defined.")
|
||||
raise InvalidSchemaException(
|
||||
f"Const type {name} must have 'const' property defined.",
|
||||
invalid_field="const",
|
||||
)
|
||||
|
||||
const_value = properties["const"]
|
||||
|
||||
if not isinstance(const_value, JSONSchemaNativeTypes):
|
||||
raise ValueError(
|
||||
f"Const type {name} must have 'const' value of allowed types: {JSONSchemaNativeTypes}."
|
||||
raise InvalidSchemaException(
|
||||
f"Const type {name} must have 'const' value of allowed types: {JSONSchemaNativeTypes}.",
|
||||
invalid_field="const",
|
||||
)
|
||||
|
||||
const_type = self._build_const_type(const_value)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from jambo.exceptions import InvalidSchemaException
|
||||
from jambo.parser._type_parser import GenericTypeParser
|
||||
from jambo.types.json_schema_type import JSONSchemaNativeTypes
|
||||
from jambo.types.type_parser_options import JSONSchema, TypeParserOptions
|
||||
@@ -14,16 +15,23 @@ class EnumTypeParser(GenericTypeParser):
|
||||
self, name: str, properties: JSONSchema, **kwargs: Unpack[TypeParserOptions]
|
||||
):
|
||||
if "enum" not in properties:
|
||||
raise ValueError(f"Enum type {name} must have 'enum' property defined.")
|
||||
raise InvalidSchemaException(
|
||||
f"Enum type {name} must have 'enum' property defined.",
|
||||
invalid_field="enum",
|
||||
)
|
||||
|
||||
enum_values = properties["enum"]
|
||||
|
||||
if not isinstance(enum_values, list):
|
||||
raise ValueError(f"Enum type {name} must have 'enum' as a list of values.")
|
||||
raise InvalidSchemaException(
|
||||
f"Enum type {name} must have 'enum' as a list of values.",
|
||||
invalid_field="enum",
|
||||
)
|
||||
|
||||
if any(not isinstance(value, JSONSchemaNativeTypes) for value in enum_values):
|
||||
raise ValueError(
|
||||
f"Enum type {name} must have 'enum' values of allowed types: {JSONSchemaNativeTypes}."
|
||||
raise InvalidSchemaException(
|
||||
f"Enum type {name} must have 'enum' values of allowed types: {JSONSchemaNativeTypes}.",
|
||||
invalid_field="enum",
|
||||
)
|
||||
|
||||
# Create a new Enum type dynamically
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from jambo.exceptions import InvalidSchemaException
|
||||
from jambo.parser._type_parser import GenericTypeParser
|
||||
from jambo.types.type_parser_options import TypeParserOptions
|
||||
|
||||
@@ -17,10 +18,14 @@ class OneOfTypeParser(GenericTypeParser):
|
||||
self, name, properties, **kwargs: Unpack[TypeParserOptions]
|
||||
):
|
||||
if "oneOf" not in properties:
|
||||
raise ValueError(f"Invalid JSON Schema: {properties}")
|
||||
raise InvalidSchemaException(
|
||||
f"Invalid JSON Schema: {properties}", invalid_field="oneOf"
|
||||
)
|
||||
|
||||
if not isinstance(properties["oneOf"], list) or len(properties["oneOf"]) == 0:
|
||||
raise ValueError(f"Invalid JSON Schema: {properties['oneOf']}")
|
||||
raise InvalidSchemaException(
|
||||
f"Invalid JSON Schema: {properties['oneOf']}", invalid_field="oneOf"
|
||||
)
|
||||
|
||||
mapped_properties = self.mappings_properties_builder(properties, **kwargs)
|
||||
|
||||
@@ -58,7 +63,9 @@ class OneOfTypeParser(GenericTypeParser):
|
||||
Build a type with a discriminator.
|
||||
"""
|
||||
if not isinstance(discriminator_prop, dict):
|
||||
raise ValueError("Discriminator must be a dictionary")
|
||||
raise InvalidSchemaException(
|
||||
"Discriminator must be a dictionary", invalid_field="discriminator"
|
||||
)
|
||||
|
||||
for field in subfield_types:
|
||||
field_type, field_info = get_args(field)
|
||||
@@ -66,13 +73,17 @@ class OneOfTypeParser(GenericTypeParser):
|
||||
if issubclass(field_type, BaseModel):
|
||||
continue
|
||||
|
||||
raise ValueError(
|
||||
"When using a discriminator, all subfield types must be of type 'object'."
|
||||
raise InvalidSchemaException(
|
||||
"When using a discriminator, all subfield types must be of type 'object'.",
|
||||
invalid_field="discriminator",
|
||||
)
|
||||
|
||||
property_name = discriminator_prop.get("propertyName")
|
||||
if property_name is None or not isinstance(property_name, str):
|
||||
raise ValueError("Discriminator must have a 'propertyName' key")
|
||||
raise InvalidSchemaException(
|
||||
"Discriminator must have a 'propertyName' key",
|
||||
invalid_field="propertyName",
|
||||
)
|
||||
|
||||
return Annotated[Union[(*subfield_types,)], Field(discriminator=property_name)]
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from jambo.exceptions import InvalidSchemaException
|
||||
from jambo.parser import GenericTypeParser
|
||||
from jambo.types.json_schema_type import JSONSchema
|
||||
from jambo.types.type_parser_options import TypeParserOptions
|
||||
@@ -17,18 +18,21 @@ class RefTypeParser(GenericTypeParser):
|
||||
self, name: str, properties: JSONSchema, **kwargs: Unpack[TypeParserOptions]
|
||||
) -> tuple[RefType, dict]:
|
||||
if "$ref" not in properties:
|
||||
raise ValueError(f"RefTypeParser: Missing $ref in properties for {name}")
|
||||
raise InvalidSchemaException(
|
||||
f"Missing $ref in properties for {name}", invalid_field="$ref"
|
||||
)
|
||||
|
||||
context = kwargs.get("context")
|
||||
if context is None:
|
||||
raise RuntimeError(
|
||||
f"RefTypeParser: Missing `content` in properties for {name}"
|
||||
raise InvalidSchemaException(
|
||||
f"Missing `context` in properties for {name}", invalid_field="context"
|
||||
)
|
||||
|
||||
ref_cache = kwargs.get("ref_cache")
|
||||
if ref_cache is None:
|
||||
raise RuntimeError(
|
||||
f"RefTypeParser: Missing `ref_cache` in properties for {name}"
|
||||
raise InvalidSchemaException(
|
||||
f"Missing `ref_cache` in properties for {name}",
|
||||
invalid_field="ref_cache",
|
||||
)
|
||||
|
||||
mapped_properties = self.mappings_properties_builder(properties, **kwargs)
|
||||
@@ -63,8 +67,8 @@ class RefTypeParser(GenericTypeParser):
|
||||
ref_name, ref_property, **kwargs
|
||||
)
|
||||
case _:
|
||||
raise ValueError(
|
||||
f"RefTypeParser: Unsupported $ref {ref_property['$ref']}"
|
||||
raise InvalidSchemaException(
|
||||
f"Unsupported $ref {ref_property['$ref']}", invalid_field="$ref"
|
||||
)
|
||||
|
||||
return mapped_type
|
||||
@@ -93,8 +97,9 @@ class RefTypeParser(GenericTypeParser):
|
||||
if properties.get("$ref") == "#":
|
||||
ref_name = kwargs["context"].get("title")
|
||||
if ref_name is None:
|
||||
raise ValueError(
|
||||
"RefTypeParser: Missing title in properties for $ref of Root Reference"
|
||||
raise InvalidSchemaException(
|
||||
"Missing title in properties for $ref of Root Reference",
|
||||
invalid_field="title",
|
||||
)
|
||||
return "forward_ref", ref_name, {}
|
||||
|
||||
@@ -104,8 +109,9 @@ class RefTypeParser(GenericTypeParser):
|
||||
)
|
||||
return "def_ref", target_name, target_property
|
||||
|
||||
raise ValueError(
|
||||
"RefTypeParser: Only Root and $defs references are supported at the moment"
|
||||
raise InvalidSchemaException(
|
||||
"Only Root and $defs references are supported at the moment",
|
||||
invalid_field="$ref",
|
||||
)
|
||||
|
||||
def _extract_target_ref(
|
||||
@@ -115,14 +121,16 @@ class RefTypeParser(GenericTypeParser):
|
||||
target_property = kwargs["context"]
|
||||
for prop_name in properties["$ref"].split("/")[1:]:
|
||||
if prop_name not in target_property:
|
||||
raise ValueError(
|
||||
f"RefTypeParser: Missing {prop_name} in"
|
||||
" properties for $ref {properties['$ref']}"
|
||||
raise InvalidSchemaException(
|
||||
f"Missing {prop_name} in properties for $ref {properties['$ref']}",
|
||||
invalid_field=prop_name,
|
||||
)
|
||||
target_name = prop_name
|
||||
target_property = target_property[prop_name] # type: ignore
|
||||
|
||||
if not isinstance(target_name, str) or target_property is None:
|
||||
raise ValueError(f"RefTypeParser: Invalid $ref {properties['$ref']}")
|
||||
raise InvalidSchemaException(
|
||||
f"Invalid $ref {properties['$ref']}", invalid_field="$ref"
|
||||
)
|
||||
|
||||
return target_name, target_property
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from jambo.exceptions import InvalidSchemaException
|
||||
from jambo.parser._type_parser import GenericTypeParser
|
||||
from jambo.types.type_parser_options import TypeParserOptions
|
||||
|
||||
@@ -54,7 +55,9 @@ class StringTypeParser(GenericTypeParser):
|
||||
return str, mapped_properties
|
||||
|
||||
if format_type not in self.format_type_mapping:
|
||||
raise ValueError(f"Unsupported string format: {format_type}")
|
||||
raise InvalidSchemaException(
|
||||
f"Unsupported string format: {format_type}", invalid_field="format"
|
||||
)
|
||||
|
||||
mapped_type = self.format_type_mapping[format_type]
|
||||
if format_type in self.format_pattern_mapping:
|
||||
|
||||
@@ -52,7 +52,7 @@ JSONSchema = TypedDict(
|
||||
"minProperties": int,
|
||||
"maxProperties": int,
|
||||
"dependencies": Dict[str, Union[List[str], "JSONSchema"]],
|
||||
"items": Union["JSONSchema", List["JSONSchema"]],
|
||||
"items": "JSONSchema",
|
||||
"prefixItems": List["JSONSchema"],
|
||||
"additionalItems": Union[bool, "JSONSchema"],
|
||||
"contains": "JSONSchema",
|
||||
|
||||
@@ -40,7 +40,7 @@ class TestRefTypeParser(TestCase):
|
||||
},
|
||||
}
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
with self.assertRaises(ValueError):
|
||||
RefTypeParser().from_properties(
|
||||
"person",
|
||||
properties,
|
||||
@@ -63,7 +63,7 @@ class TestRefTypeParser(TestCase):
|
||||
},
|
||||
}
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
with self.assertRaises(ValueError):
|
||||
RefTypeParser().from_properties(
|
||||
"person",
|
||||
properties,
|
||||
|
||||
@@ -187,7 +187,8 @@ class TestStringTypeParser(TestCase):
|
||||
parser.from_properties("placeholder", properties)
|
||||
|
||||
self.assertEqual(
|
||||
str(context.exception), "Unsupported string format: unsupported-format"
|
||||
str(context.exception),
|
||||
"Invalid JSON Schema: Unsupported string format: unsupported-format (invalid field: format)",
|
||||
)
|
||||
|
||||
def test_string_parser_with_date_format(self):
|
||||
|
||||
Reference in New Issue
Block a user