Skip to content

Commit c84ac49

Browse files
author
Robert Holt
committed
Python: implement new codegen
Generated python code now only depends on sqlalchemy. Query functions are now inside classes as well.
1 parent 937915c commit c84ac49

File tree

20 files changed

+677
-726
lines changed

20 files changed

+677
-726
lines changed

examples/python/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ pytest~=6.2.2
22
pytest-asyncio~=0.14.0
33
psycopg2-binary~=2.8.6
44
asyncpg~=0.21.0
5-
sqlalchemy==1.4.0b3
5+
sqlalchemy==1.4.0

examples/python/sqlc.json

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
"gen": {
99
"python": {
1010
"out": "src/authors",
11-
"package": "authors"
11+
"package": "authors",
12+
"emit_sync_querier": true,
13+
"emit_async_querier": true
1214
}
1315
}
1416
},
@@ -19,7 +21,8 @@
1921
"gen": {
2022
"python": {
2123
"out": "src/booktest",
22-
"package": "booktest"
24+
"package": "booktest",
25+
"emit_async_querier": true
2326
}
2427
}
2528
},
@@ -30,7 +33,8 @@
3033
"gen": {
3134
"python": {
3235
"out": "src/jets",
33-
"package": "jets"
36+
"package": "jets",
37+
"emit_async_querier": true
3438
}
3539
}
3640
},
@@ -41,7 +45,8 @@
4145
"gen": {
4246
"python": {
4347
"out": "src/ondeck",
44-
"package": "ondeck"
48+
"package": "ondeck",
49+
"emit_async_querier": true
4550
}
4651
}
4752
}

examples/python/src/authors/models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# Code generated by sqlc. DO NOT EDIT.
22
from typing import Optional
3+
34
import dataclasses
45

56

6-
# Enums
77

8-
# Models
8+
99
@dataclasses.dataclass()
1010
class Author:
1111
id: int

examples/python/src/authors/query.py

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
# Code generated by sqlc. DO NOT EDIT.
23
from typing import AsyncIterator, Iterator, Optional
34

@@ -35,43 +36,76 @@
3536
"""
3637

3738

38-
class Query:
39+
class Querier:
3940
def __init__(self, conn: sqlalchemy.engine.Connection):
4041
self._conn = conn
4142

42-
def create_author(self, name: str, bio: Optional[str]) -> Optional[models.Author]:
43-
result = self._conn.execute(sqlalchemy.text(CREATE_AUTHOR), {"p1": name, "p2": bio})
44-
return models.Author(**dict(result.first()))
45-
46-
def delete_author(self, id: int) -> None:
43+
def create_author(self, *, name: str, bio: Optional[str]) -> Optional[models.Author]:
44+
row = self._conn.execute(sqlalchemy.text(CREATE_AUTHOR), {"p1": name, "p2": bio}).first()
45+
if row is None:
46+
return None
47+
return models.Author(
48+
id=row[0],
49+
name=row[1],
50+
bio=row[2],
51+
)
52+
53+
def delete_author(self, *, id: int) -> None:
4754
self._conn.execute(sqlalchemy.text(DELETE_AUTHOR), {"p1": id})
4855

49-
def get_author(self, id: int) -> Optional[models.Author]:
50-
result = self._conn.execute(sqlalchemy.text(GET_AUTHOR), {"p1": id})
51-
return models.Author(**dict(result.first()))
56+
def get_author(self, *, id: int) -> Optional[models.Author]:
57+
row = self._conn.execute(sqlalchemy.text(GET_AUTHOR), {"p1": id}).first()
58+
if row is None:
59+
return None
60+
return models.Author(
61+
id=row[0],
62+
name=row[1],
63+
bio=row[2],
64+
)
5265

5366
def list_authors(self) -> Iterator[models.Author]:
5467
result = self._conn.execute(sqlalchemy.text(LIST_AUTHORS))
5568
for row in result:
56-
yield models.Author(**dict(row))
69+
yield models.Author(
70+
id=row[0],
71+
name=row[1],
72+
bio=row[2],
73+
)
5774

5875

59-
class AsyncQuery:
76+
class AsyncQuerier:
6077
def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection):
6178
self._conn = conn
6279

63-
async def create_author(self, name: str, bio: Optional[str]) -> Optional[models.Author]:
64-
result = await self._conn.execute(sqlalchemy.text(CREATE_AUTHOR), {"p1": name, "p2": bio})
65-
return models.Author(**dict(result.first()))
66-
67-
async def delete_author(self, id: int) -> None:
80+
async def create_author(self, *, name: str, bio: Optional[str]) -> Optional[models.Author]:
81+
row = (await self._conn.execute(sqlalchemy.text(CREATE_AUTHOR), {"p1": name, "p2": bio})).first()
82+
if row is None:
83+
return None
84+
return models.Author(
85+
id=row[0],
86+
name=row[1],
87+
bio=row[2],
88+
)
89+
90+
async def delete_author(self, *, id: int) -> None:
6891
await self._conn.execute(sqlalchemy.text(DELETE_AUTHOR), {"p1": id})
6992

70-
async def get_author(self, id: int) -> Optional[models.Author]:
71-
result = await self._conn.execute(sqlalchemy.text(GET_AUTHOR), {"p1": id})
72-
return models.Author(**dict(result.first()))
93+
async def get_author(self, *, id: int) -> Optional[models.Author]:
94+
row = (await self._conn.execute(sqlalchemy.text(GET_AUTHOR), {"p1": id})).first()
95+
if row is None:
96+
return None
97+
return models.Author(
98+
id=row[0],
99+
name=row[1],
100+
bio=row[2],
101+
)
73102

74103
async def list_authors(self) -> AsyncIterator[models.Author]:
75104
result = await self._conn.stream(sqlalchemy.text(LIST_AUTHORS))
76105
async for row in result:
77-
yield models.Author(**dict(row))
106+
yield models.Author(
107+
id=row[0],
108+
name=row[1],
109+
bio=row[2],
110+
)
111+

examples/python/src/booktest/models.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,24 @@
33
import datetime
44
import enum
55

6-
import pydantic
6+
import dataclasses
7+
78

89

9-
# Enums
1010
class BookType(str, enum.Enum):
1111
FICTION = "FICTION"
1212
NONFICTION = "NONFICTION"
1313

1414

15-
# Models
16-
class Author(pydantic.BaseModel):
15+
@dataclasses.dataclass()
16+
class Author:
1717
author_id: int
1818
name: str
1919

2020

21-
class Book(pydantic.BaseModel):
21+
22+
@dataclasses.dataclass()
23+
class Book:
2224
book_id: int
2325
author_id: int
2426
isbn: str

0 commit comments

Comments
 (0)