Skip to content

Commit 85d9e04

Browse files
Raise when TypeScript schema construction produces errors. (#202)
* Raise when TypeScript schema construction produces errors. * Fix issues with music example.
1 parent 7f61a5e commit 85d9e04

5 files changed

Lines changed: 21 additions & 13 deletions

File tree

python/examples/math/program.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@
4545

4646
translation_result = python_type_to_typescript_schema(JsonProgram)
4747
program_schema_text = translation_result.typescript_schema_str
48-
print(program_schema_text)
49-
print(translation_result.errors)
48+
5049

5150
JsonValue = str | int | float | bool | None | dict[str, "JsonValue"] | list["JsonValue"]
5251

@@ -127,7 +126,7 @@ class TypeChatProgramTranslator(TypeChatTranslator[JsonProgram]):
127126
_api_declaration_str: str
128127

129128
def __init__(self, model: TypeChatLanguageModel, validator: TypeChatProgramValidator, api_type: type):
130-
super().__init__(model=model, validator=validator, target_type=api_type)
129+
super().__init__(model=model, validator=validator, target_type=api_type, _raise_on_schema_errors = False)
131130
# TODO: the conversion result here has errors!
132131
conversion_result = python_type_to_typescript_schema(api_type)
133132
self._api_declaration_str = conversion_result.typescript_schema_str

python/examples/music/client.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,13 @@ async def handle_call(action: PlayerAction, context: ClientContext):
266266
case "selectDevice":
267267
deviceKeyword = action["parameters"]["keyword"].lower()
268268
devices = await context.service.devices()
269+
devices = devices["devices"]
269270
target_device = next(
270-
(d for d in devices if d.name.lower() == deviceKeyword or d.type.lower() == deviceKeyword), None # type: ignore
271+
(d for d in devices if d["name"].lower() == deviceKeyword or d["type"].lower() == deviceKeyword), None
271272
)
272273
if target_device:
273-
await context.service.transfer_playback(device_id=target_device.id) # type: ignore
274-
print(f"Selected device {target_device.name} of type {target_device.type}") # type: ignore
274+
await context.service.transfer_playback(device_id=target_device)
275+
print(f"Selected device {target_device}")
275276
case "setVolume":
276277
new_volume = action["parameters"].get("newVolumeLevel", None)
277278
new_volume = max(0, min(new_volume, 100))

python/examples/music/schema.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ class ListDevicesAction(TypedDict):
109109
parameters: EmptyParameters
110110

111111

112-
class SelectDecviceActionParameters(TypedDict):
112+
class SelectDeviceActionParameters(TypedDict):
113113
keyword: Annotated[str, Doc("keyword to match against device name")]
114114

115115

@@ -119,7 +119,7 @@ class SelectDeviceAction(TypedDict):
119119
"""
120120

121121
actionName: Literal["selectDevice"]
122-
parameters: SelectDecviceActionParameters
122+
parameters: SelectDeviceActionParameters
123123

124124

125125
class SelectVolumeActionParameters(TypedDict):

python/examples/music/spotipyWrapper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from typing_extensions import Any
2-
from pydantic.dataclasses import dataclass, field
2+
from dataclasses import dataclass, field
33
import spotipy # type: ignore
44

55
# The spotipy library does not provide type hints or async methods. This file has some wrappers and stubs

python/src/typechat/_internal/translator.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,14 @@ class TypeChatTranslator(Generic[T]):
1919
_schema_str: str
2020
_max_repair_attempts = 1
2121

22-
def __init__(self, model: TypeChatLanguageModel, validator: TypeChatValidator[T], target_type: type[T]):
22+
def __init__(
23+
self,
24+
model: TypeChatLanguageModel,
25+
validator: TypeChatValidator[T],
26+
target_type: type[T],
27+
*, # keyword-only parameters follow
28+
_raise_on_schema_errors: bool = True,
29+
):
2330
"""
2431
Args:
2532
model: The associated `TypeChatLanguageModel`.
@@ -32,9 +39,10 @@ def __init__(self, model: TypeChatLanguageModel, validator: TypeChatValidator[T]
3239
self.target_type = target_type
3340

3441
conversion_result = python_type_to_typescript_schema(target_type)
35-
# TODO: Examples may not work here!
36-
# if conversion_result.errors:
37-
# raise ValueError(f"Could not convert Python type to TypeScript schema: {conversion_result.errors}")
42+
43+
if _raise_on_schema_errors and conversion_result.errors:
44+
error_text = "".join(f"\n- {error}" for error in conversion_result.errors)
45+
raise ValueError(f"Could not convert Python type to TypeScript schema: \n{error_text}")
3846
self._type_name = conversion_result.typescript_type_reference
3947
self._schema_str = conversion_result.typescript_schema_str
4048

0 commit comments

Comments
 (0)