14
14
15
15
16
16
import json
17
- from unittest .mock import MagicMock
18
10000
code>
- from unittest .mock import patch
17
+ from unittest .mock import MagicMock , patch
19
18
20
- from fastapi .openapi .models import MediaType
21
- from fastapi .openapi .models import Operation
19
+ from fastapi .openapi .models import MediaType , Operation
22
20
from fastapi .openapi .models import Parameter as OpenAPIParameter
23
21
from fastapi .openapi .models import RequestBody
24
22
from fastapi .openapi .models import Schema as OpenAPISchema
27
25
from google .adk .tools .openapi_tool .common .common import ApiParameter
28
26
from google .adk .tools .openapi_tool .openapi_spec_parser .openapi_spec_parser import OperationEndpoint
29
27
from google .adk .tools .openapi_tool .openapi_spec_parser .operation_parser import OperationParser
30
- from google .adk .tools .openapi_tool .openapi_spec_parser .rest_api_tool import RestApiTool
31
- from google .adk .tools .openapi_tool .openapi_spec_parser .rest_api_tool import snake_to_lower_camel
32
- from google .adk .tools .openapi_tool .openapi_spec_parser .rest_api_tool import to_gemini_schema
28
+ from google .adk .tools .openapi_tool .openapi_spec_parser .rest_api_tool import (
29
+ RestApiTool ,
30
+ snake_to_lower_camel ,
31
+ to_gemini_schema ,
32
+ )
33
33
from google .adk .tools .tool_context import ToolContext
34
- from google .genai .types import FunctionDeclaration
35
- from google .genai .types import Schema
36
- from google .genai .types import Type
34
+ from google .genai .types import FunctionDeclaration , Schema , Type
37
35
import pytest
38
36
39
37
@@ -790,13 +788,13 @@ def test_to_gemini_schema_empty_dict(self):
790
788
result = to_gemini_schema ({})
791
789
assert isinstance (result , Schema )
792
790
assert result .type == Type .OBJECT
793
- assert result .properties == { "dummy_DO_NOT_GENERATE" : Schema ( type = "string" )}
791
+ assert result .properties is None
794
792
795
793
def test_to_gemini_schema_dict_with_only_object_type (self ):
796
794
result = to_gemini_schema ({"type" : "object" })
797
795
assert isinstance (result , Schema )
798
796
assert result .type == Type .OBJECT
799
- assert result .properties == { "dummy_DO_NOT_GENERATE" : Schema ( type = "string" )}
797
+ assert result .properties is None
800
798
801
799
def test_to_gemini_schema_basic_types (self ):
802
800
openapi_schema = {
@@ -814,6 +812,42 @@ def test_to_gemini_schema_basic_types(self):
814
812
assert gemini_schema .properties ["age" ].type == Type .INTEGER
815
813
assert gemini_schema .properties ["is_active" ].type == Type .BOOLEAN
816
814
815
+ def test_to_gemini_schema_array_string_types (self ):
816
+ openapi_schema = {
817
+ "type" : "object" ,
818
+ "properties" : {
819
+ "boolean_field" : {"type" : "boolean" },
820
+ "nonnullable_string" : {"type" : ["string" ]},
821
+ "nullable_string" : {"type" : ["string" , "null" ]},
822
+ "nullable_number" : {"type" : ["null" , "integer" ]},
823
+ "object_nullable" : {"type" : "null" },
824
+ "multi_types_nullable" : {"type" : ["string" , "null" , "integer" ]},
825
+ "empty_default_object" : {},
826
+ },
827
+ }
828
+ gemini_schema = to_gemini_schema (openapi_schema )
829
+ assert isinstance (gemini_schema , Schema )
830
+ assert gemini_schema .type == Type .OBJECT
831
+ assert gemini_schema .properties ["boolean_field" ].type == Type .BOOLEAN
832
+
833
+ assert gemini_schema .properties ["nonnullable_string" ].type == Type .STRING
834
+ assert not gemini_schema .properties ["nonnullable_string" ].nullable
835
+
836
+ assert gemini_schema .properties ["nullable_string" ].type == Type .STRING
837
+ assert gemini_schema .properties ["nullable_string" ].nullable
838
+
839
+ assert gemini_schema .properties ["nullable_number" ].type == Type .INTEGER
840
+ assert gemini_schema .properties ["nullable_number" ].nullable
841
+
842
+ assert gemini_schema .properties ["object_nullable" ].type == Type .OBJECT
843
+ assert gemini_schema .properties ["object_nullable" ].nullable
844
+
845
+ assert gemini_schema .properties ["multi_types_nullable" ].type == Type .STRING
846
+ assert gemini_schema .properties ["multi_types_nullable" ].nullable
847
+
848
+ assert gemini_schema .properties ["empty_default_object" ].type == Type .OBJECT
849
+ assert not gemini_schema .properties ["empty_default_object" ].nullable
850
+
817
851
def test_to_gemini_schema_nested_objects (self ):
818
852
openapi_schema = {
819
853
"type" : "object" ,
@@ -895,17 +929,31 @@ def test_to_gemini_schema_required(self):
895
929
def test_to_gemini_schema_nested_dict (self ):
896
930
openapi_schema = {
897
931
"type" : "object" ,
898
- "properties" : {"metadata" : {"key1" : "value1" , "key2" : 123 }},
932
+ "properties" : {
933
+ "metadata" : {
934
+ "type" : "object" ,
935
+ "properties" : {
936
+ "key1" : {"type" : "object" },
937
+ "key2" : {"type" : "string" },
938
+ },
939
+ }
940
+ },
899
941
}
900
942
gemini_schema = to_gemini_schema (openapi_schema )
901
943
# Since metadata is not properties nor item, it will call to_gemini_schema recursively.
902
944
assert isinstance (gemini_schema .properties ["metadata" ], Schema )
903
945
assert (
904
946
gemini_schema .properties ["metadata" ].type == Type .OBJECT
905
947
) # add object type by default
906
- assert gemini_schema .properties ["metadata" ].properties == {
907
- "dummy_DO_NOT_GENERATE" : Schema (type = "string" )
908
- }
948
+ assert len (gemini_schema .properties ["metadata" ].properties ) == 2
949
+ assert (
950
+ gemini_schema .properties ["metadata" ].properties ["key1" ].type
951
+ == Type .OBJECT
952
+ )
953
+ assert (
954
+ gemini_schema .properties ["metadata" ].properties ["key2" ].type
955
+ == Type .STRING
956
+ )
909
957
910
958
def test_to_gemini_schema_ignore_title_default_format (self ):
911
959
openapi_schema = {
0 commit comments