Skip to content

Commit 87bc74d

Browse files
authored
fix(py/genkit): handle None type correctly in to_json_schema per JSON Schema spec (#4247)
1 parent 101a66b commit 87bc74d

File tree

2 files changed

+134
-1
lines changed

2 files changed

+134
-1
lines changed

py/packages/genkit/src/genkit/core/schema.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from pydantic import TypeAdapter
2222

2323

24-
def to_json_schema(schema: type | dict[str, Any] | None) -> dict[str, Any]:
24+
def to_json_schema(schema: type | dict[str, Any] | str | None) -> dict[str, Any]:
2525
"""Converts a Python type to a JSON schema.
2626
2727
If the input `schema` is already a dictionary (assumed json schema), it is
@@ -60,6 +60,8 @@ def to_json_schema(schema: type | dict[str, Any] | None) -> dict[str, Any]:
6060
>>> print(result)
6161
{'type': 'string'}
6262
"""
63+
if schema is None:
64+
return {'type': 'null'}
6365
if isinstance(schema, dict):
6466
return schema
6567
type_adapter = TypeAdapter(schema)

py/packages/genkit/tests/genkit/core/schema_test.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
"""Tests for the schema module."""
1818

19+
import pytest
1920
from pydantic import BaseModel, Field
2021

2122
from genkit.core.schema import to_json_schema
@@ -70,3 +71,133 @@ def test_to_json_schema_already_schema():
7071
}
7172

7273
assert to_json_schema(json_schema) == json_schema
74+
75+
76+
# =============================================================================
77+
# JSON Schema Specification-based Tests
78+
# See: https://json-schema.org/understanding-json-schema/reference/type
79+
# =============================================================================
80+
81+
82+
class TestNullType:
83+
"""Tests for null type as per JSON Schema spec.
84+
85+
See: https://json-schema.org/understanding-json-schema/reference/null
86+
"""
87+
88+
def test_none_produces_null_type(self):
89+
"""Python None should produce JSON Schema null type."""
90+
assert to_json_schema(None) == {'type': 'null'}
91+
92+
93+
class TestStringType:
94+
"""Tests for string type as per JSON Schema spec.
95+
96+
See: https://json-schema.org/understanding-json-schema/reference/string
97+
"""
98+
99+
def test_str_type(self):
100+
"""Python str type should produce JSON Schema string type."""
101+
assert to_json_schema(str) == {'type': 'string'}
102+
103+
104+
class TestNumericTypes:
105+
"""Tests for numeric types as per JSON Schema spec.
106+
107+
See: https://json-schema.org/understanding-json-schema/reference/numeric
108+
Note: JSON Schema has 'integer' and 'number' (floating point).
109+
"""
110+
111+
@pytest.mark.parametrize(
112+
'py_type, json_type_name',
113+
[
114+
(int, 'integer'),
115+
(float, 'number'),
116+
],
117+
)
118+
def test_numeric_types(self, py_type, json_type_name):
119+
"""Python numeric types should produce correct JSON Schema numeric types."""
120+
assert to_json_schema(py_type) == {'type': json_type_name}
121+
122+
123+
class TestBooleanType:
124+
"""Tests for boolean type as per JSON Schema spec.
125+
126+
See: https://json-schema.org/understanding-json-schema/reference/boolean
127+
"""
128+
129+
def test_bool_type(self):
130+
"""Python bool type should produce JSON Schema boolean type."""
131+
assert to_json_schema(bool) == {'type': 'boolean'}
132+
133+
134+
class TestArrayType:
135+
"""Tests for array type as per JSON Schema spec.
136+
137+
See: https://json-schema.org/understanding-json-schema/reference/array
138+
"""
139+
140+
@pytest.mark.parametrize(
141+
'list_type, item_schema',
142+
[
143+
(list[str], {'type': 'string'}),
144+
(list[int], {'type': 'integer'}),
145+
],
146+
)
147+
def test_list_types(self, list_type, item_schema):
148+
"""Python list types should produce array schema with correct item types."""
149+
result = to_json_schema(list_type)
150+
assert result['type'] == 'array'
151+
assert result['items'] == item_schema
152+
153+
154+
class TestObjectType:
155+
"""Tests for object type as per JSON Schema spec.
156+
157+
See: https://json-schema.org/understanding-json-schema/reference/object
158+
"""
159+
160+
def test_dict_type(self):
161+
"""Python dict should produce object schema."""
162+
result = to_json_schema(dict)
163+
assert result['type'] == 'object'
164+
165+
def test_pydantic_model(self):
166+
"""Pydantic BaseModel should produce object schema with properties."""
167+
168+
class Person(BaseModel):
169+
name: str
170+
age: int
171+
172+
result = to_json_schema(Person)
173+
assert result['type'] == 'object'
174+
assert 'properties' in result
175+
assert result['properties']['name']['type'] == 'string'
176+
assert result['properties']['age']['type'] == 'integer'
177+
assert result['required'] == ['name', 'age']
178+
179+
180+
class TestPassthroughBehavior:
181+
"""Tests for passthrough behavior when input is already a JSON Schema dict."""
182+
183+
@pytest.mark.parametrize(
184+
'schema',
185+
[
186+
{'type': 'string', 'minLength': 1},
187+
{
188+
'type': 'object',
189+
'properties': {
190+
'name': {'type': 'string'},
191+
'items': {
192+
'type': 'array',
193+
'items': {'type': 'integer'},
194+
},
195+
},
196+
'required': ['name'],
197+
},
198+
],
199+
ids=['simple_schema', 'complex_schema'],
200+
)
201+
def test_passthrough_behavior(self, schema):
202+
"""A dict representing a JSON Schema should be returned as-is."""
203+
assert to_json_schema(schema) == schema

0 commit comments

Comments
 (0)