feat: better methodology for accessing cached references of: objects, subobjects and defs
This commit is contained in:
@@ -31,7 +31,7 @@ class AnyOfTypeParser(GenericTypeParser):
|
||||
|
||||
sub_types = [
|
||||
GenericTypeParser.type_from_properties(
|
||||
f"{name}_sub{i}", subProperty, **kwargs
|
||||
f"{name}.sub{i}", subProperty, **kwargs
|
||||
)
|
||||
for i, subProperty in enumerate(sub_properties)
|
||||
]
|
||||
|
||||
@@ -67,7 +67,7 @@ class ObjectTypeParser(GenericTypeParser):
|
||||
return model
|
||||
|
||||
model_config = ConfigDict(validate_assignment=True)
|
||||
fields = cls._parse_properties(properties, required_keys, **kwargs)
|
||||
fields = cls._parse_properties(name, properties, required_keys, **kwargs)
|
||||
|
||||
model = create_model(name, __config__=model_config, **fields) # type: ignore
|
||||
|
||||
@@ -84,6 +84,7 @@ class ObjectTypeParser(GenericTypeParser):
|
||||
@classmethod
|
||||
def _parse_properties(
|
||||
cls,
|
||||
name: str,
|
||||
properties: dict[str, JSONSchema],
|
||||
required_keys: list[str],
|
||||
**kwargs: Unpack[TypeParserOptions],
|
||||
@@ -91,15 +92,15 @@ class ObjectTypeParser(GenericTypeParser):
|
||||
required_keys = required_keys or []
|
||||
|
||||
fields = {}
|
||||
for name, prop in properties.items():
|
||||
for field_name, field_prop in properties.items():
|
||||
sub_property: TypeParserOptions = kwargs.copy()
|
||||
sub_property["required"] = name in required_keys
|
||||
sub_property["required"] = field_name in required_keys
|
||||
|
||||
parsed_type, parsed_properties = GenericTypeParser.type_from_properties(
|
||||
name,
|
||||
prop,
|
||||
f"{name}.{field_name}",
|
||||
field_prop,
|
||||
**sub_property, # type: ignore
|
||||
)
|
||||
fields[name] = (parsed_type, Field(**parsed_properties))
|
||||
fields[field_name] = (parsed_type, Field(**parsed_properties))
|
||||
|
||||
return fields
|
||||
|
||||
@@ -942,3 +942,59 @@ class TestSchemaConverter(TestCase):
|
||||
cached_model = self.converter.get_cached_ref("NonExistentModel")
|
||||
|
||||
self.assertIsNone(cached_model)
|
||||
|
||||
def test_get_type_from_cache_nested_type(self):
|
||||
schema = {
|
||||
"title": "Person",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"age": {"type": "integer"},
|
||||
"address": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"street": {"type": "string"},
|
||||
"city": {"type": "string"},
|
||||
},
|
||||
"required": ["street", "city"],
|
||||
},
|
||||
},
|
||||
"required": ["name", "age", "address"],
|
||||
}
|
||||
|
||||
model = self.converter.build_with_instance(schema)
|
||||
|
||||
cached_model = self.converter.get_cached_ref("Person.address")
|
||||
|
||||
self.assertIsNotNone(cached_model)
|
||||
self.assertIs(model.model_fields["address"].annotation, cached_model)
|
||||
|
||||
def test_get_type_from_cache_with_def(self):
|
||||
schema = {
|
||||
"title": "person",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"age": {"type": "integer"},
|
||||
"address": {"$ref": "#/$defs/address"},
|
||||
},
|
||||
"$defs": {
|
||||
"address": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"street": {"type": "string"},
|
||||
"city": {"type": "string"},
|
||||
},
|
||||
"required": ["street", "city"],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
person_model = self.converter.build_with_instance(schema)
|
||||
cached_person_model = self.converter.get_cached_ref("person")
|
||||
|
||||
self.assertIs(person_model, cached_person_model)
|
||||
|
||||
cached_address_model = self.converter.get_cached_ref("address")
|
||||
|
||||
self.assertIsNotNone(cached_address_model)
|
||||
|
||||
Reference in New Issue
Block a user