Better Object Internal Structure and Type Selection #16

Merged
HideyoshiNakazone merged 10 commits from improvement/better-internal-structure into main 2025-06-04 04:27:29 +00:00
9 changed files with 38 additions and 28 deletions
Showing only changes of commit e37e9818ed - Show all commits

View File

@@ -1,8 +1,9 @@
from jambo.types.type_parser_options import TypeParserOptions
from pydantic import Field, TypeAdapter from pydantic import Field, TypeAdapter
from typing_extensions import Annotated, Self from typing_extensions import Annotated, Any, Generic, Self, TypeVar, Unpack
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Any, Generic, TypeVar
T = TypeVar("T") T = TypeVar("T")
@@ -18,9 +19,14 @@ class GenericTypeParser(ABC, Generic[T]):
"description": "description", "description": "description",
} }
@abstractmethod
def from_properties(
self, name: str, properties: dict[str, Any], **kwargs: Unpack[TypeParserOptions]
) -> tuple[T, dict]: ...
@classmethod @classmethod
def type_from_properties( def type_from_properties(
cls, name: str, properties: dict[str, Any], **kwargs cls, name: str, properties: dict[str, Any], **kwargs: Unpack[TypeParserOptions]
) -> tuple[type, dict]: ) -> tuple[type, dict]:
parser = cls._get_impl(properties) parser = cls._get_impl(properties)
@@ -51,12 +57,9 @@ class GenericTypeParser(ABC, Generic[T]):
return schema_definition[0], schema_definition[1] return schema_definition[0], schema_definition[1]
@abstractmethod def mappings_properties_builder(
def from_properties( self, properties, required=False, **kwargs: Unpack[TypeParserOptions]
self, name: str, properties: dict[str, Any], required: bool = False ) -> dict[str, Any]:
) -> tuple[T, dict]: ...
def mappings_properties_builder(self, properties, required=False) -> dict[str, Any]:
if self.type_mappings is None: if self.type_mappings is None:
raise NotImplementedError("Type mappings not defined") raise NotImplementedError("Type mappings not defined")

View File

@@ -1,6 +1,7 @@
from jambo.parser._type_parser import GenericTypeParser from jambo.parser._type_parser import GenericTypeParser
from jambo.types.type_parser_options import TypeParserOptions
from typing import Any from typing_extensions import Any, Unpack
class AllOfTypeParser(GenericTypeParser): class AllOfTypeParser(GenericTypeParser):
@@ -8,7 +9,7 @@ class AllOfTypeParser(GenericTypeParser):
json_schema_type = "allOf" json_schema_type = "allOf"
def from_properties(self, name, properties, required=False): def from_properties(self, name, properties, **kwargs: Unpack[TypeParserOptions]):
sub_properties = properties.get("allOf", []) sub_properties = properties.get("allOf", [])
root_type = properties.get("type") root_type = properties.get("type")
@@ -22,7 +23,7 @@ class AllOfTypeParser(GenericTypeParser):
sub_properties sub_properties
) )
return parser().from_properties(name, combined_properties) return parser().from_properties(name, combined_properties, **kwargs)
@staticmethod @staticmethod
def _get_type_parser( def _get_type_parser(

View File

@@ -1,9 +1,8 @@
from jambo.parser._type_parser import GenericTypeParser from jambo.parser._type_parser import GenericTypeParser
from jambo.types.type_parser_options import TypeParserOptions
from pydantic import Field from pydantic import Field
from typing_extensions import Annotated from typing_extensions import Annotated, Union, Unpack
from typing import Union
class AnyOfTypeParser(GenericTypeParser): class AnyOfTypeParser(GenericTypeParser):
@@ -11,7 +10,7 @@ class AnyOfTypeParser(GenericTypeParser):
json_schema_type = "anyOf" json_schema_type = "anyOf"
def from_properties(self, name, properties, required=False): def from_properties(self, name, properties, **kwargs: Unpack[TypeParserOptions]):
if "anyOf" not in properties: if "anyOf" not in properties:
raise ValueError(f"Invalid JSON Schema: {properties}") raise ValueError(f"Invalid JSON Schema: {properties}")
@@ -20,11 +19,11 @@ class AnyOfTypeParser(GenericTypeParser):
mapped_properties = dict() mapped_properties = dict()
subProperties = properties["anyOf"] sub_properties = properties["anyOf"]
sub_types = [ sub_types = [
GenericTypeParser.type_from_properties(name, subProperty) GenericTypeParser.type_from_properties(name, subProperty, **kwargs)
for subProperty in subProperties for subProperty in sub_properties
] ]
default_value = properties.get("default") default_value = properties.get("default")
@@ -42,12 +41,14 @@ class AnyOfTypeParser(GenericTypeParser):
mapped_properties["default"] = default_value mapped_properties["default"] = default_value
if not required: if not kwargs.get("required", False):
mapped_properties["default"] = mapped_properties.get("default") mapped_properties["default"] = mapped_properties.get("default")
# By defining the type as Union of Annotated type we can use the Field validator # By defining the type as Union of Annotated type we can use the Field validator
# to enforce the constraints of each union type when needed. # to enforce the constraints of each union type when needed.
# We use Annotated to attach the Field validators to the type. # We use Annotated to attach the Field validators to the type.
field_types = [Annotated[t, Field(**v)] if v else t for t, v in sub_types] field_types = [
Annotated[t, Field(**v)] if v is not None else t for t, v in sub_types
]
return Union[(*field_types,)], mapped_properties return Union[(*field_types,)], mapped_properties

View File

@@ -1,7 +1,8 @@
from jambo.parser._type_parser import GenericTypeParser from jambo.parser._type_parser import GenericTypeParser
from typing_extensions import TypeVar
import copy import copy
from typing import TypeVar
V = TypeVar("V") V = TypeVar("V")

View File

@@ -2,8 +2,7 @@ from jambo.parser._type_parser import GenericTypeParser
from pydantic import Field, create_model from pydantic import Field, create_model
from pydantic.main import ModelT from pydantic.main import ModelT
from typing_extensions import Any
from typing import Any
class ObjectTypeParser(GenericTypeParser): class ObjectTypeParser(GenericTypeParser):

View File

@@ -1,4 +1,4 @@
from typing import Dict, List, Literal, TypedDict, Union from typing_extensions import Dict, List, Literal, TypedDict, Union
JSONSchemaType = Literal[ JSONSchemaType = Literal[

View File

@@ -0,0 +1,5 @@
from typing_extensions import TypedDict
class TypeParserOptions(TypedDict):
required: bool

View File

@@ -1,8 +1,7 @@
from jambo.parser.anyof_type_parser import AnyOfTypeParser from jambo.parser.anyof_type_parser import AnyOfTypeParser
from typing_extensions import Annotated from typing_extensions import Annotated, Union, get_args, get_origin
from typing import Union, get_args, get_origin
from unittest import TestCase from unittest import TestCase

View File

@@ -1,6 +1,7 @@
from jambo.parser import ArrayTypeParser from jambo.parser import ArrayTypeParser
from typing import get_args from typing_extensions import get_args
from unittest import TestCase from unittest import TestCase