Skip to content

Commit 66066ed

Browse files
fix: add Optional to nullable columns in Python Insert/Update TypedDict (#1046)
Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com>
1 parent 5b6537d commit 66066ed

2 files changed

Lines changed: 48 additions & 45 deletions

File tree

src/server/templates/python.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,10 @@ class PythonTypedDictAttr implements Serializable {
278278
}
279279

280280
serialize(): string {
281-
const annotation = `Annotated[${this.py_type.serialize()}, Field(alias="${this.pg_name}")]`
281+
const py_type = this.nullable
282+
? `Optional[${this.py_type.serialize()}]`
283+
: this.py_type.serialize()
284+
const annotation = `Annotated[${py_type}, Field(alias="${this.pg_name}")]`
282285
const rhs = this.not_required ? `NotRequired[${annotation}]` : annotation
283286
return ` ${this.name}: ${rhs}`
284287
}

test/server/typegen.ts

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6654,31 +6654,31 @@ test('typegen: python', async () => {
66546654
user_uuid: Optional[uuid.UUID] = Field(alias="user_uuid")
66556655
66566656
class PublicUsersInsert(TypedDict):
6657-
decimal: NotRequired[Annotated[float, Field(alias="decimal")]]
6657+
decimal: NotRequired[Annotated[Optional[float], Field(alias="decimal")]]
66586658
id: NotRequired[Annotated[int, Field(alias="id")]]
6659-
name: NotRequired[Annotated[str, Field(alias="name")]]
6660-
status: NotRequired[Annotated[PublicUserStatus, Field(alias="status")]]
6661-
user_uuid: NotRequired[Annotated[uuid.UUID, Field(alias="user_uuid")]]
6659+
name: NotRequired[Annotated[Optional[str], Field(alias="name")]]
6660+
status: NotRequired[Annotated[Optional[PublicUserStatus], Field(alias="status")]]
6661+
user_uuid: NotRequired[Annotated[Optional[uuid.UUID], Field(alias="user_uuid")]]
66626662
66636663
class PublicUsersUpdate(TypedDict):
6664-
decimal: NotRequired[Annotated[float, Field(alias="decimal")]]
6664+
decimal: NotRequired[Annotated[Optional[float], Field(alias="decimal")]]
66656665
id: NotRequired[Annotated[int, Field(alias="id")]]
6666-
name: NotRequired[Annotated[str, Field(alias="name")]]
6667-
status: NotRequired[Annotated[PublicUserStatus, Field(alias="status")]]
6668-
user_uuid: NotRequired[Annotated[uuid.UUID, Field(alias="user_uuid")]]
6666+
name: NotRequired[Annotated[Optional[str], Field(alias="name")]]
6667+
status: NotRequired[Annotated[Optional[PublicUserStatus], Field(alias="status")]]
6668+
user_uuid: NotRequired[Annotated[Optional[uuid.UUID], Field(alias="user_uuid")]]
66696669
66706670
class PublicTodos(BaseModel):
66716671
details: Optional[str] = Field(alias="details")
66726672
id: int = Field(alias="id")
66736673
user_id: int = Field(alias="user-id")
66746674
66756675
class PublicTodosInsert(TypedDict):
6676-
details: NotRequired[Annotated[str, Field(alias="details")]]
6676+
details: NotRequired[Annotated[Optional[str], Field(alias="details")]]
66776677
id: NotRequired[Annotated[int, Field(alias="id")]]
66786678
user_id: Annotated[int, Field(alias="user-id")]
66796679
66806680
class PublicTodosUpdate(TypedDict):
6681-
details: NotRequired[Annotated[str, Field(alias="details")]]
6681+
details: NotRequired[Annotated[Optional[str], Field(alias="details")]]
66826682
id: NotRequired[Annotated[int, Field(alias="id")]]
66836683
user_id: NotRequired[Annotated[int, Field(alias="user-id")]]
66846684
@@ -6689,27 +6689,27 @@ test('typegen: python', async () => {
66896689
user_id: Optional[int] = Field(alias="user_id")
66906690
66916691
class PublicUsersAuditInsert(TypedDict):
6692-
created_at: NotRequired[Annotated[datetime.datetime, Field(alias="created_at")]]
6692+
created_at: NotRequired[Annotated[Optional[datetime.datetime], Field(alias="created_at")]]
66936693
id: NotRequired[Annotated[int, Field(alias="id")]]
6694-
previous_value: NotRequired[Annotated[Json[Any], Field(alias="previous_value")]]
6695-
user_id: NotRequired[Annotated[int, Field(alias="user_id")]]
6694+
previous_value: NotRequired[Annotated[Optional[Json[Any]], Field(alias="previous_value")]]
6695+
user_id: NotRequired[Annotated[Optional[int], Field(alias="user_id")]]
66966696
66976697
class PublicUsersAuditUpdate(TypedDict):
6698-
created_at: NotRequired[Annotated[datetime.datetime, Field(alias="created_at")]]
6698+
created_at: NotRequired[Annotated[Optional[datetime.datetime], Field(alias="created_at")]]
66996699
id: NotRequired[Annotated[int, Field(alias="id")]]
6700-
previous_value: NotRequired[Annotated[Json[Any], Field(alias="previous_value")]]
6701-
user_id: NotRequired[Annotated[int, Field(alias="user_id")]]
6700+
previous_value: NotRequired[Annotated[Optional[Json[Any]], Field(alias="previous_value")]]
6701+
user_id: NotRequired[Annotated[Optional[int], Field(alias="user_id")]]
67026702
67036703
class PublicUserDetails(BaseModel):
67046704
details: Optional[str] = Field(alias="details")
67056705
user_id: int = Field(alias="user_id")
67066706
67076707
class PublicUserDetailsInsert(TypedDict):
6708-
details: NotRequired[Annotated[str, Field(alias="details")]]
6708+
details: NotRequired[Annotated[Optional[str], Field(alias="details")]]
67096709
user_id: Annotated[int, Field(alias="user_id")]
67106710
67116711
class PublicUserDetailsUpdate(TypedDict):
6712-
details: NotRequired[Annotated[str, Field(alias="details")]]
6712+
details: NotRequired[Annotated[Optional[str], Field(alias="details")]]
67136713
user_id: NotRequired[Annotated[int, Field(alias="user_id")]]
67146714
67156715
class PublicEmpty(BaseModel):
@@ -6726,23 +6726,23 @@ test('typegen: python', async () => {
67266726
col2: Optional[PublicAView] = Field(alias="col2")
67276727
67286728
class PublicTableWithOtherTablesRowTypeInsert(TypedDict):
6729-
col1: NotRequired[Annotated[PublicUserDetails, Field(alias="col1")]]
6730-
col2: NotRequired[Annotated[PublicAView, Field(alias="col2")]]
6729+
col1: NotRequired[Annotated[Optional[PublicUserDetails], Field(alias="col1")]]
6730+
col2: NotRequired[Annotated[Optional[PublicAView], Field(alias="col2")]]
67316731
67326732
class PublicTableWithOtherTablesRowTypeUpdate(TypedDict):
6733-
col1: NotRequired[Annotated[PublicUserDetails, Field(alias="col1")]]
6734-
col2: NotRequired[Annotated[PublicAView, Field(alias="col2")]]
6733+
col1: NotRequired[Annotated[Optional[PublicUserDetails], Field(alias="col1")]]
6734+
col2: NotRequired[Annotated[Optional[PublicAView], Field(alias="col2")]]
67356735
67366736
class PublicTableWithPrimaryKeyOtherThanId(BaseModel):
67376737
name: Optional[str] = Field(alias="name")
67386738
other_id: int = Field(alias="other_id")
67396739
67406740
class PublicTableWithPrimaryKeyOtherThanIdInsert(TypedDict):
6741-
name: NotRequired[Annotated[str, Field(alias="name")]]
6741+
name: NotRequired[Annotated[Optional[str], Field(alias="name")]]
67426742
other_id: NotRequired[Annotated[int, Field(alias="other_id")]]
67436743
67446744
class PublicTableWithPrimaryKeyOtherThanIdUpdate(TypedDict):
6745-
name: NotRequired[Annotated[str, Field(alias="name")]]
6745+
name: NotRequired[Annotated[Optional[str], Field(alias="name")]]
67466746
other_id: NotRequired[Annotated[int, Field(alias="other_id")]]
67476747
67486748
class PublicEvents(BaseModel):
@@ -6753,14 +6753,14 @@ test('typegen: python', async () => {
67536753
67546754
class PublicEventsInsert(TypedDict):
67556755
created_at: NotRequired[Annotated[datetime.datetime, Field(alias="created_at")]]
6756-
data: NotRequired[Annotated[Json[Any], Field(alias="data")]]
6757-
event_type: NotRequired[Annotated[str, Field(alias="event_type")]]
6756+
data: NotRequired[Annotated[Optional[Json[Any]], Field(alias="data")]]
6757+
event_type: NotRequired[Annotated[Optional[str], Field(alias="event_type")]]
67586758
id: NotRequired[Annotated[int, Field(alias="id")]]
67596759
67606760
class PublicEventsUpdate(TypedDict):
67616761
created_at: NotRequired[Annotated[datetime.datetime, Field(alias="created_at")]]
6762-
data: NotRequired[Annotated[Json[Any], Field(alias="data")]]
6763-
event_type: NotRequired[Annotated[str, Field(alias="event_type")]]
6762+
data: NotRequired[Annotated[Optional[Json[Any]], Field(alias="data")]]
6763+
event_type: NotRequired[Annotated[Optional[str], Field(alias="event_type")]]
67646764
id: NotRequired[Annotated[int, Field(alias="id")]]
67656765
67666766
class PublicEvents2024(BaseModel):
@@ -6771,14 +6771,14 @@ test('typegen: python', async () => {
67716771
67726772
class PublicEvents2024Insert(TypedDict):
67736773
created_at: NotRequired[Annotated[datetime.datetime, Field(alias="created_at")]]
6774-
data: NotRequired[Annotated[Json[Any], Field(alias="data")]]
6775-
event_type: NotRequired[Annotated[str, Field(alias="event_type")]]
6774+
data: NotRequired[Annotated[Optional[Json[Any]], Field(alias="data")]]
6775+
event_type: NotRequired[Annotated[Optional[str], Field(alias="event_type")]]
67766776
id: Annotated[int, Field(alias="id")]
67776777
67786778
class PublicEvents2024Update(TypedDict):
67796779
created_at: NotRequired[Annotated[datetime.datetime, Field(alias="created_at")]]
6780-
data: NotRequired[Annotated[Json[Any], Field(alias="data")]]
6781-
event_type: NotRequired[Annotated[str, Field(alias="event_type")]]
6780+
data: NotRequired[Annotated[Optional[Json[Any]], Field(alias="data")]]
6781+
event_type: NotRequired[Annotated[Optional[str], Field(alias="event_type")]]
67826782
id: NotRequired[Annotated[int, Field(alias="id")]]
67836783
67846784
class PublicEvents2025(BaseModel):
@@ -6789,14 +6789,14 @@ test('typegen: python', async () => {
67896789
67906790
class PublicEvents2025Insert(TypedDict):
67916791
created_at: NotRequired[Annotated[datetime.datetime, Field(alias="created_at")]]
6792-
data: NotRequired[Annotated[Json[Any], Field(alias="data")]]
6793-
event_type: NotRequired[Annotated[str, Field(alias="event_type")]]
6792+
data: NotRequired[Annotated[Optional[Json[Any]], Field(alias="data")]]
6793+
event_type: NotRequired[Annotated[Optional[str], Field(alias="event_type")]]
67946794
id: Annotated[int, Field(alias="id")]
67956795
67966796
class PublicEvents2025Update(TypedDict):
67976797
created_at: NotRequired[Annotated[datetime.datetime, Field(alias="created_at")]]
6798-
data: NotRequired[Annotated[Json[Any], Field(alias="data")]]
6799-
event_type: NotRequired[Annotated[str, Field(alias="event_type")]]
6798+
data: NotRequired[Annotated[Optional[Json[Any]], Field(alias="data")]]
6799+
event_type: NotRequired[Annotated[Optional[str], Field(alias="event_type")]]
68006800
id: NotRequired[Annotated[int, Field(alias="id")]]
68016801
68026802
class PublicIntervalTest(BaseModel):
@@ -6805,12 +6805,12 @@ test('typegen: python', async () => {
68056805
id: int = Field(alias="id")
68066806
68076807
class PublicIntervalTestInsert(TypedDict):
6808-
duration_optional: NotRequired[Annotated[str, Field(alias="duration_optional")]]
6808+
duration_optional: NotRequired[Annotated[Optional[str], Field(alias="duration_optional")]]
68096809
duration_required: Annotated[str, Field(alias="duration_required")]
68106810
id: NotRequired[Annotated[int, Field(alias="id")]]
68116811
68126812
class PublicIntervalTestUpdate(TypedDict):
6813-
duration_optional: NotRequired[Annotated[str, Field(alias="duration_optional")]]
6813+
duration_optional: NotRequired[Annotated[Optional[str], Field(alias="duration_optional")]]
68146814
duration_required: NotRequired[Annotated[str, Field(alias="duration_required")]]
68156815
id: NotRequired[Annotated[int, Field(alias="id")]]
68166816
@@ -6835,20 +6835,20 @@ test('typegen: python', async () => {
68356835
status: Optional[PublicMemeStatus] = Field(alias="status")
68366836
68376837
class PublicMemesInsert(TypedDict):
6838-
category: NotRequired[Annotated[int, Field(alias="category")]]
6838+
category: NotRequired[Annotated[Optional[int], Field(alias="category")]]
68396839
created_at: Annotated[datetime.datetime, Field(alias="created_at")]
68406840
id: NotRequired[Annotated[int, Field(alias="id")]]
6841-
metadata: NotRequired[Annotated[Json[Any], Field(alias="metadata")]]
6841+
metadata: NotRequired[Annotated[Optional[Json[Any]], Field(alias="metadata")]]
68426842
name: Annotated[str, Field(alias="name")]
6843-
status: NotRequired[Annotated[PublicMemeStatus, Field(alias="status")]]
6843+
status: NotRequired[Annotated[Optional[PublicMemeStatus], Field(alias="status")]]
68446844
68456845
class PublicMemesUpdate(TypedDict):
6846-
category: NotRequired[Annotated[int, Field(alias="category")]]
6846+
category: NotRequired[Annotated[Optional[int], Field(alias="category")]]
68476847
created_at: NotRequired[Annotated[datetime.datetime, Field(alias="created_at")]]
68486848
id: NotRequired[Annotated[int, Field(alias="id")]]
6849-
metadata: NotRequired[Annotated[Json[Any], Field(alias="metadata")]]
6849+
metadata: NotRequired[Annotated[Optional[Json[Any]], Field(alias="metadata")]]
68506850
name: NotRequired[Annotated[str, Field(alias="name")]]
6851-
status: NotRequired[Annotated[PublicMemeStatus, Field(alias="status")]]
6851+
status: NotRequired[Annotated[Optional[PublicMemeStatus], Field(alias="status")]]
68526852
68536853
class PublicAView(BaseModel):
68546854
id: Optional[int] = Field(alias="id")

0 commit comments

Comments
 (0)