Skip to content

Commit b72caf8

Browse files
[chore] Remove type:ignore for field renames (#150)
Why === We had one overly-broad `# type: ignore` due to using the old-style of pydantic field renaming. Switching to PEP593-`Annotated` types, we can communicate the alias as well as the default value correctly. What changed ============ Simplified codegen Added tests Test plan ========= CI
1 parent fa382a7 commit b72caf8

File tree

3 files changed

+61
-43
lines changed

3 files changed

+61
-43
lines changed

src/replit_river/codegen/client.py

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -646,42 +646,24 @@ def extract_props(tpe: RiverType) -> list[dict[str, RiverType]]:
646646
case LiteralTypeExpr(literal_value):
647647
field_value = repr(literal_value)
648648
if name not in type.required:
649+
type_name = UnionTypeExpr(
650+
[
651+
type_name,
652+
NoneTypeExpr(),
653+
]
654+
)
649655
value = ""
650656
if base_model != "TypedDict":
651-
value = dedent(
652-
f"""\
653-
= Field(
654-
default=None,
655-
alias={repr(name)}, # type: ignore
656-
)
657-
"""
658-
)
659-
current_chunks.append(
660-
f" kind: {
661-
render_type_expr(
662-
UnionTypeExpr(
663-
[
664-
type_name,
665-
NoneTypeExpr(),
666-
]
667-
)
668-
)
669-
}{value}"
670-
)
657+
value = f"= {repr(None)}"
671658
else:
672659
value = ""
673660
if base_model != "TypedDict":
674-
value = dedent(
675-
f"""\
676-
= Field(
677-
{field_value},
678-
alias={repr(name)}, # type: ignore
679-
)
680-
"""
681-
)
682-
current_chunks.append(
683-
f" kind: {render_type_expr(type_name)}{value}"
684-
)
661+
value = f"= {field_value}"
662+
current_chunks.append(
663+
f" kind: Annotated[{render_type_expr(type_name)}, Field(alias={
664+
repr(name)
665+
})]{value}"
666+
)
685667
else:
686668
if name not in type.required:
687669
if base_model == "TypedDict":

tests/codegen/snapshot/snapshots/test_unknown_enum/enumService/needsEnumObject.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def encode_NeedsenumobjectInputOneOf_in_first(
3838

3939

4040
class NeedsenumobjectInputOneOf_in_first(TypedDict):
41-
kind: Literal["in_first"]
41+
kind: Annotated[Literal["in_first"], Field(alias="$kind")]
4242
value: str
4343

4444

@@ -58,7 +58,7 @@ def encode_NeedsenumobjectInputOneOf_in_second(
5858

5959

6060
class NeedsenumobjectInputOneOf_in_second(TypedDict):
61-
kind: Literal["in_second"]
61+
kind: Annotated[Literal["in_second"], Field(alias="$kind")]
6262
bleep: int
6363

6464

@@ -83,20 +83,12 @@ def encode_NeedsenumobjectInput(
8383

8484

8585
class NeedsenumobjectOutputFooOneOf_out_first(BaseModel):
86-
kind: Literal["out_first"] = Field(
87-
"out_first",
88-
alias="$kind", # type: ignore
89-
)
90-
86+
kind: Annotated[Literal["out_first"], Field(alias="$kind")] = "out_first"
9187
foo: int
9288

9389

9490
class NeedsenumobjectOutputFooOneOf_out_second(BaseModel):
95-
kind: Literal["out_second"] = Field(
96-
"out_second",
97-
alias="$kind", # type: ignore
98-
)
99-
91+
kind: Annotated[Literal["out_second"], Field(alias="$kind")] = "out_second"
10092
bar: int
10193

10294

tests/codegen/snapshot/test_enum.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import importlib
2+
import json
23
from io import StringIO
34

45
from pytest_snapshot.plugin import Snapshot
@@ -203,3 +204,46 @@ def test_unknown_enum(snapshot: Snapshot) -> None:
203204
x = NeedsenumErrorsTypeAdapter.validate_python(error)
204205
assert x.code == error["code"]
205206
assert x.message == error["message"]
207+
208+
209+
def test_unknown_enum_field_aliases(snapshot: Snapshot) -> None:
210+
validate_codegen(
211+
snapshot=snapshot,
212+
read_schema=lambda: StringIO(test_unknown_enum_schema),
213+
target_path="test_unknown_enum",
214+
client_name="foo",
215+
)
216+
217+
import tests.codegen.snapshot.snapshots.test_unknown_enum
218+
219+
importlib.reload(tests.codegen.snapshot.snapshots.test_unknown_enum)
220+
from tests.codegen.snapshot.snapshots.test_unknown_enum.enumService.needsEnumObject import ( # noqa
221+
NeedsenumobjectOutputTypeAdapter,
222+
NeedsenumobjectOutput,
223+
NeedsenumobjectOutputFooOneOf_out_first,
224+
)
225+
226+
initial = NeedsenumobjectOutput(foo=NeedsenumobjectOutputFooOneOf_out_first(foo=5))
227+
result = NeedsenumobjectOutputTypeAdapter.dump_json(
228+
initial,
229+
by_alias=True,
230+
)
231+
232+
obj = json.loads(result)
233+
234+
# Make sure we are testing what we think we are testing
235+
assert "foo" in obj
236+
237+
# We must not include the un-aliased field name
238+
assert "kind" not in obj["foo"]
239+
240+
# We must include the aliased field name
241+
assert "$kind" in obj["foo"]
242+
243+
# ... and finally that the values are what we think they should be
244+
assert obj["foo"]["$kind"] == "out_first"
245+
assert obj["foo"]["foo"] == 5
246+
247+
# And one more sanity check for the decoder
248+
decoded = NeedsenumobjectOutputTypeAdapter.validate_json(result)
249+
assert decoded == initial

0 commit comments

Comments
 (0)