Implements: allOf, anyOf #11
@@ -2,7 +2,7 @@ from jambo.parser import GenericTypeParser
|
|||||||
from jambo.types.json_schema_type import JSONSchema
|
from jambo.types.json_schema_type import JSONSchema
|
||||||
|
|
||||||
from jsonschema.exceptions import SchemaError
|
from jsonschema.exceptions import SchemaError
|
||||||
from jsonschema.protocols import Validator
|
from jsonschema.validators import validator_for
|
||||||
from pydantic import create_model
|
from pydantic import create_model
|
||||||
from pydantic.fields import Field
|
from pydantic.fields import Field
|
||||||
from pydantic.main import ModelT
|
from pydantic.main import ModelT
|
||||||
@@ -42,7 +42,8 @@ class SchemaConverter:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
Validator.check_schema(schema)
|
validator = validator_for(schema)
|
||||||
|
validator.check_schema(schema)
|
||||||
except SchemaError as e:
|
except SchemaError as e:
|
||||||
raise ValueError(f"Invalid JSON Schema: {e}")
|
raise ValueError(f"Invalid JSON Schema: {e}")
|
||||||
|
|
||||||
|
|||||||
31
tests/parser/test_type_parser.py
Normal file
31
tests/parser/test_type_parser.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
from jambo.parser._type_parser import GenericTypeParser
|
||||||
|
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidGenericTypeParser(GenericTypeParser):
|
||||||
|
mapped_type = str
|
||||||
|
json_schema_type = "invalid"
|
||||||
|
|
||||||
|
def from_properties(
|
||||||
|
self, name: str, properties: dict[str, any], required: bool = False
|
||||||
|
): ...
|
||||||
|
|
||||||
|
|
||||||
|
class TestGenericTypeParser(TestCase):
|
||||||
|
def test_invalid_get_impl(self):
|
||||||
|
# Assuming GenericTypeParser is imported from the module
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
GenericTypeParser.get_impl("another_invalid_type")
|
||||||
|
|
||||||
|
def test_invalid_json_schema_type(self):
|
||||||
|
InvalidGenericTypeParser.json_schema_type = None
|
||||||
|
|
||||||
|
# This is more for the developer's sanity check
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
GenericTypeParser.get_impl("another_invalid_type")
|
||||||
|
|
||||||
|
def test_invalid_mappings_properties_builder(self):
|
||||||
|
parser = InvalidGenericTypeParser()
|
||||||
|
with self.assertRaises(NotImplementedError):
|
||||||
|
parser.mappings_properties_builder({}, required=False)
|
||||||
@@ -10,6 +10,59 @@ def is_pydantic_model(cls):
|
|||||||
|
|
||||||
|
|
||||||
class TestSchemaConverter(TestCase):
|
class TestSchemaConverter(TestCase):
|
||||||
|
def test_build_expects_title(self):
|
||||||
|
schema = {
|
||||||
|
"description": "A person",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {"type": "string"},
|
||||||
|
"age": {"type": "integer"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
SchemaConverter.build(schema)
|
||||||
|
|
||||||
|
def test_build_expects_valid_schema(self):
|
||||||
|
invalid_schema = {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "strng"
|
||||||
|
} # typo: "strng" is not a valid JSON Schema type
|
||||||
|
},
|
||||||
|
"required": ["name"],
|
||||||
|
}
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
SchemaConverter.build_object("placeholder", invalid_schema)
|
||||||
|
|
||||||
|
def test_build_expects_object(self):
|
||||||
|
schema = {
|
||||||
|
"title": "Person",
|
||||||
|
"description": "A person",
|
||||||
|
"type": "string",
|
||||||
|
}
|
||||||
|
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
SchemaConverter.build(schema)
|
||||||
|
|
||||||
|
def test_is_invalid_field(self):
|
||||||
|
schema = {
|
||||||
|
"title": "Person",
|
||||||
|
"description": "A person",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"notType": "string",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
# 'required': ['name', 'age', 'is_active', 'friends', 'address'],
|
||||||
|
}
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
SchemaConverter.build(schema)
|
||||||
|
|
||||||
def test_jsonschema_to_pydantic(self):
|
def test_jsonschema_to_pydantic(self):
|
||||||
schema = {
|
schema = {
|
||||||
"title": "Person",
|
"title": "Person",
|
||||||
@@ -312,3 +365,35 @@ class TestSchemaConverter(TestCase):
|
|||||||
|
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
Model(name="")
|
Model(name="")
|
||||||
|
|
||||||
|
def test_any_of(self):
|
||||||
|
schema = {
|
||||||
|
"title": "Person",
|
||||||
|
"description": "A person",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"anyOf": [
|
||||||
|
{"type": "string", "maxLength": 11, "minLength": 1},
|
||||||
|
{"type": "integer", "maximum": 10},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Model = SchemaConverter.build(schema)
|
||||||
|
|
||||||
|
obj = Model(id=1)
|
||||||
|
self.assertEqual(obj.id, 1)
|
||||||
|
|
||||||
|
obj = Model(id="12345678901")
|
||||||
|
self.assertEqual(obj.id, "12345678901")
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Model(id="")
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Model(id="12345678901234567890")
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Model(id=11)
|
||||||
|
|||||||
Reference in New Issue
Block a user