Better TypeParser Kwargs

This commit is contained in:
2025-06-03 02:05:21 -03:00
parent 2b2c823e27
commit be7f04e20d
7 changed files with 50 additions and 25 deletions

View File

@@ -48,7 +48,9 @@ class GenericTypeParser(ABC, Generic[T]):
@classmethod
def _get_schema_type(cls) -> tuple[str, str | None]:
if cls.json_schema_type is None:
raise RuntimeError("TypeParser: json_schema_type not defined")
raise RuntimeError(
f"TypeParser: json_schema_type not defined for subclass {cls.__name__}"
)
schema_definition = cls.json_schema_type.split(":")
@@ -58,12 +60,12 @@ class GenericTypeParser(ABC, Generic[T]):
return schema_definition[0], schema_definition[1]
def mappings_properties_builder(
self, properties, required=False, **kwargs: Unpack[TypeParserOptions]
self, properties, **kwargs: Unpack[TypeParserOptions]
) -> dict[str, Any]:
if self.type_mappings is None:
raise NotImplementedError("Type mappings not defined")
if not required:
if not kwargs.get("required", False):
properties["default"] = properties.get("default", None)
mappings = self.default_mappings | self.type_mappings

View File

@@ -1,6 +1,7 @@
from jambo.parser._type_parser import GenericTypeParser
from jambo.types.type_parser_options import TypeParserOptions
from typing_extensions import TypeVar
from typing_extensions import TypeVar, Unpack
import copy
@@ -20,18 +21,17 @@ class ArrayTypeParser(GenericTypeParser):
"minItems": "min_length",
}
def from_properties(self, name, properties, required=False):
def from_properties(self, name, properties, **kwargs: Unpack[TypeParserOptions]):
item_properties = kwargs.copy()
item_properties["required"] = True
_item_type, _item_args = GenericTypeParser.type_from_properties(
name, properties["items"], required=True
name, properties["items"], **item_properties
)
wrapper_type = set if properties.get("uniqueItems", False) else list
field_type = wrapper_type[_item_type]
mapped_properties = self.mappings_properties_builder(
properties,
required=required,
)
mapped_properties = self.mappings_properties_builder(properties, **kwargs)
default_list = properties.pop("default", None)
if default_list is not None:

View File

@@ -1,4 +1,7 @@
from jambo.parser._type_parser import GenericTypeParser
from jambo.types.type_parser_options import TypeParserOptions
from typing_extensions import Unpack
class BooleanTypeParser(GenericTypeParser):
@@ -10,8 +13,8 @@ class BooleanTypeParser(GenericTypeParser):
"default": "default",
}
def from_properties(self, name, properties, required=False):
mapped_properties = self.mappings_properties_builder(properties, required)
def from_properties(self, name, properties, **kwargs: Unpack[TypeParserOptions]):
mapped_properties = self.mappings_properties_builder(properties, **kwargs)
default_value = properties.get("default")
if default_value is not None and not isinstance(default_value, bool):

View File

@@ -1,4 +1,7 @@
from jambo.parser._type_parser import GenericTypeParser
from jambo.types.type_parser_options import TypeParserOptions
from typing_extensions import Unpack
class FloatTypeParser(GenericTypeParser):
@@ -15,8 +18,8 @@ class FloatTypeParser(GenericTypeParser):
"default": "default",
}
def from_properties(self, name, properties, required=False):
mapped_properties = self.mappings_properties_builder(properties, required)
def from_properties(self, name, properties, **kwargs: Unpack[TypeParserOptions]):
mapped_properties = self.mappings_properties_builder(properties, **kwargs)
default_value = mapped_properties.get("default")
if default_value is not None:

View File

@@ -1,4 +1,7 @@
from jambo.parser._type_parser import GenericTypeParser
from jambo.types.type_parser_options import TypeParserOptions
from typing_extensions import Unpack
class IntTypeParser(GenericTypeParser):
@@ -15,8 +18,8 @@ class IntTypeParser(GenericTypeParser):
"default": "default",
}
def from_properties(self, name, properties, required=False):
mapped_properties = self.mappings_properties_builder(properties, required)
def from_properties(self, name, properties, **kwargs: Unpack[TypeParserOptions]):
mapped_properties = self.mappings_properties_builder(properties, **kwargs)
default_value = mapped_properties.get("default")
if default_value is not None:

View File

@@ -1,8 +1,9 @@
from jambo.parser._type_parser import GenericTypeParser
from jambo.types.type_parser_options import TypeParserOptions
from pydantic import Field, create_model
from pydantic.main import ModelT
from typing_extensions import Any
from typing_extensions import Any, Unpack
class ObjectTypeParser(GenericTypeParser):
@@ -11,10 +12,13 @@ class ObjectTypeParser(GenericTypeParser):
json_schema_type = "type:object"
def from_properties(
self, name: str, properties: dict[str, Any], required: bool = False
self, name: str, properties: dict[str, Any], **kwargs: Unpack[TypeParserOptions]
):
type_parsing = self.to_model(
name, properties.get("properties", {}), properties.get("required", [])
name,
properties.get("properties", {}),
properties.get("required", []),
**kwargs,
)
type_properties = {}
@@ -26,7 +30,11 @@ class ObjectTypeParser(GenericTypeParser):
return type_parsing, type_properties
def to_model(
self, name: str, schema: dict[str, Any], required_keys: list[str], **kwargs
self,
name: str,
schema: dict[str, Any],
required_keys: list[str],
**kwargs: Unpack[TypeParserOptions],
) -> type[ModelT]:
"""
Converts JSON Schema object properties to a Pydantic model.
@@ -40,15 +48,19 @@ class ObjectTypeParser(GenericTypeParser):
@staticmethod
def _parse_properties(
properties: dict[str, Any], required_keys: list[str], **kwargs
properties: dict[str, Any],
required_keys: list[str],
**kwargs: Unpack[TypeParserOptions],
) -> dict[str, tuple[type, Field]]:
required_keys = required_keys or []
fields = {}
for name, prop in properties.items():
is_required = name in required_keys
sub_property = kwargs.copy()
sub_property["required"] = name in required_keys
parsed_type, parsed_properties = GenericTypeParser.type_from_properties(
name, prop, required=is_required, **kwargs
name, prop, **sub_property
)
fields[name] = (parsed_type, Field(**parsed_properties))

View File

@@ -1,6 +1,8 @@
from jambo.parser._type_parser import GenericTypeParser
from jambo.types.type_parser_options import TypeParserOptions
from pydantic import EmailStr, HttpUrl, IPvAnyAddress
from typing_extensions import Unpack
from datetime import date, datetime, time
@@ -32,8 +34,8 @@ class StringTypeParser(GenericTypeParser):
"hostname": r"^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$",
}
def from_properties(self, name, properties, required=False):
mapped_properties = self.mappings_properties_builder(properties, required)
def from_properties(self, name, properties, **kwargs: Unpack[TypeParserOptions]):
mapped_properties = self.mappings_properties_builder(properties, **kwargs)
format_type = properties.get("format")
if format_type: