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 = [
|
sub_types = [
|
||||||
GenericTypeParser.type_from_properties(
|
GenericTypeParser.type_from_properties(
|
||||||
f"{name}_sub{i}", subProperty, **kwargs
|
f"{name}.sub{i}", subProperty, **kwargs
|
||||||
)
|
)
|
||||||
for i, subProperty in enumerate(sub_properties)
|
for i, subProperty in enumerate(sub_properties)
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class ObjectTypeParser(GenericTypeParser):
|
|||||||
return model
|
return model
|
||||||
|
|
||||||
model_config = ConfigDict(validate_assignment=True)
|
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
|
model = create_model(name, __config__=model_config, **fields) # type: ignore
|
||||||
|
|
||||||
@@ -84,6 +84,7 @@ class ObjectTypeParser(GenericTypeParser):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def _parse_properties(
|
def _parse_properties(
|
||||||
cls,
|
cls,
|
||||||
|
name: str,
|
||||||
properties: dict[str, JSONSchema],
|
properties: dict[str, JSONSchema],
|
||||||
required_keys: list[str],
|
required_keys: list[str],
|
||||||
**kwargs: Unpack[TypeParserOptions],
|
**kwargs: Unpack[TypeParserOptions],
|
||||||
@@ -91,15 +92,15 @@ class ObjectTypeParser(GenericTypeParser):
|
|||||||
required_keys = required_keys or []
|
required_keys = required_keys or []
|
||||||
|
|
||||||
fields = {}
|
fields = {}
|
||||||
for name, prop in properties.items():
|
for field_name, field_prop in properties.items():
|
||||||
sub_property: TypeParserOptions = kwargs.copy()
|
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(
|
parsed_type, parsed_properties = GenericTypeParser.type_from_properties(
|
||||||
name,
|
f"{name}.{field_name}",
|
||||||
prop,
|
field_prop,
|
||||||
**sub_property, # type: ignore
|
**sub_property, # type: ignore
|
||||||
)
|
)
|
||||||
fields[name] = (parsed_type, Field(**parsed_properties))
|
fields[field_name] = (parsed_type, Field(**parsed_properties))
|
||||||
|
|
||||||
return fields
|
return fields
|
||||||
|
|||||||
@@ -942,3 +942,59 @@ class TestSchemaConverter(TestCase):
|
|||||||
cached_model = self.converter.get_cached_ref("NonExistentModel")
|
cached_model = self.converter.get_cached_ref("NonExistentModel")
|
||||||
|
|
||||||
self.assertIsNone(cached_model)
|
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