Implements Object Defaults #10
@@ -1,5 +1,7 @@
|
||||
from jambo.parser._type_parser import GenericTypeParser
|
||||
from jambo.utils.properties_builder.numeric_properties_builder import numeric_properties_builder
|
||||
from jambo.utils.properties_builder.numeric_properties_builder import (
|
||||
numeric_properties_builder,
|
||||
)
|
||||
|
||||
|
||||
class FloatTypeParser(GenericTypeParser):
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from jambo.parser._type_parser import GenericTypeParser
|
||||
from jambo.utils.properties_builder.numeric_properties_builder import numeric_properties_builder
|
||||
from jambo.utils.properties_builder.numeric_properties_builder import (
|
||||
numeric_properties_builder,
|
||||
)
|
||||
|
||||
|
||||
class IntTypeParser(GenericTypeParser):
|
||||
|
||||
@@ -10,10 +10,12 @@ class ObjectTypeParser(GenericTypeParser):
|
||||
def from_properties(name, properties):
|
||||
from jambo.schema_converter import SchemaConverter
|
||||
|
||||
if "default" in properties:
|
||||
raise RuntimeError("Default values for objects are not supported.")
|
||||
type_parsing = SchemaConverter.build_object(name, properties)
|
||||
type_properties = {}
|
||||
|
||||
return (
|
||||
SchemaConverter.build_object(name, properties),
|
||||
{}, # The second argument is not used in this case
|
||||
if "default" in properties:
|
||||
type_properties["default_factory"] = lambda: type_parsing.model_validate(
|
||||
properties["default"]
|
||||
)
|
||||
|
||||
return type_parsing, type_properties
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
from jambo.parser import GenericTypeParser
|
||||
from jambo.types.json_schema_type import JSONSchema
|
||||
|
||||
from jsonschema.exceptions import SchemaError
|
||||
from jsonschema.protocols import Validator
|
||||
from pydantic import create_model
|
||||
from pydantic.fields import Field
|
||||
|
||||
from typing import Type
|
||||
|
||||
from jambo.types.json_schema_type import JSONSchema
|
||||
from pydantic.main import ModelT
|
||||
|
||||
|
||||
class SchemaConverter:
|
||||
@@ -20,7 +18,7 @@ class SchemaConverter:
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def build(schema: JSONSchema) -> Type:
|
||||
def build(schema: JSONSchema) -> ModelT:
|
||||
"""
|
||||
Converts a JSON Schema to a Pydantic model.
|
||||
:param schema: The JSON Schema to convert.
|
||||
@@ -35,7 +33,7 @@ class SchemaConverter:
|
||||
def build_object(
|
||||
name: str,
|
||||
schema: JSONSchema,
|
||||
) -> Type:
|
||||
) -> ModelT:
|
||||
"""
|
||||
Converts a JSON Schema object to a Pydantic model given a name.
|
||||
:param name:
|
||||
@@ -60,7 +58,7 @@ class SchemaConverter:
|
||||
@staticmethod
|
||||
def _build_model_from_properties(
|
||||
model_name: str, model_properties: dict, required_keys: list[str]
|
||||
) -> Type:
|
||||
) -> ModelT:
|
||||
properties = SchemaConverter._parse_properties(model_properties, required_keys)
|
||||
|
||||
return create_model(model_name, **properties)
|
||||
|
||||
@@ -66,3 +66,4 @@ section-order=[
|
||||
"third-party",
|
||||
"standard-library",
|
||||
]
|
||||
lines-after-imports = 2
|
||||
|
||||
@@ -21,3 +21,29 @@ class TestObjectTypeParser(TestCase):
|
||||
|
||||
self.assertEqual(obj.name, "name")
|
||||
self.assertEqual(obj.age, 10)
|
||||
|
||||
def test_object_type_parser_with_default(self):
|
||||
parser = ObjectTypeParser()
|
||||
|
||||
properties = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"age": {"type": "integer"},
|
||||
},
|
||||
"default": {
|
||||
"name": "default_name",
|
||||
"age": 20,
|
||||
},
|
||||
}
|
||||
|
||||
_, type_validator = parser.from_properties("placeholder", properties)
|
||||
|
||||
# Check default value
|
||||
default_obj = type_validator["default_factory"]()
|
||||
self.assertEqual(default_obj.name, "default_name")
|
||||
self.assertEqual(default_obj.age, 20)
|
||||
|
||||
# Chekc default factory new object id
|
||||
new_obj = type_validator["default_factory"]()
|
||||
self.assertNotEqual(id(default_obj), id(new_obj))
|
||||
|
||||
@@ -256,3 +256,28 @@ class TestSchemaConverter(TestCase):
|
||||
model_set = SchemaConverter.build(schema_set)
|
||||
|
||||
self.assertEqual(model_set().friends, {"John", "Jane"})
|
||||
|
||||
def test_default_for_object(self):
|
||||
schema = {
|
||||
"title": "Person",
|
||||
"description": "A person",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"street": {"type": "string"},
|
||||
"city": {"type": "string"},
|
||||
},
|
||||
"default": {"street": "123 Main St", "city": "Springfield"},
|
||||
},
|
||||
},
|
||||
"required": ["address"],
|
||||
}
|
||||
|
||||
model = SchemaConverter.build(schema)
|
||||
|
||||
obj = model(address={"street": "123 Main St", "city": "Springfield"})
|
||||
|
||||
self.assertEqual(obj.address.street, "123 Main St")
|
||||
self.assertEqual(obj.address.city, "Springfield")
|
||||
|
||||
Reference in New Issue
Block a user