Skip to content

Commit 78377a8

Browse files
authored
[Python] Bump Granian to 2.6, update Emmett55 implementation (#10358)
* [Python] Update Granian to 2.6 * [Python] Review `emmett55` implementation
1 parent e543756 commit 78377a8

File tree

8 files changed

+53
-45
lines changed

8 files changed

+53
-45
lines changed

frameworks/Python/emmett55/app.py

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,19 @@
33
from random import randint, sample
44

55
import asyncpg
6-
from emmett55 import App, Pipe, current, request, response
6+
from emmett55 import App, Pipe, request, response
77
from emmett55.extensions import Extension, Signals, listen_signal
8-
from emmett55.tools import service
8+
from emmett55.tools import ServicePipe
99
from renoir import Renoir
1010

1111

12+
class NoResetConnection(asyncpg.Connection):
13+
__slots__ = ()
14+
15+
def get_reset_query(self):
16+
return ""
17+
18+
1219
class AsyncPG(Extension):
1320
__slots__ = ["pool"]
1421

@@ -23,10 +30,9 @@ async def build_pool(self):
2330
database='hello_world',
2431
host='tfb-database',
2532
port=5432,
26-
min_size=16,
27-
max_size=16,
28-
max_queries=64_000_000_000,
29-
max_inactive_connection_lifetime=0
33+
min_size=4,
34+
max_size=4,
35+
connection_class=NoResetConnection,
3036
)
3137

3238
@listen_signal(Signals.after_loop)
@@ -40,18 +46,32 @@ class AsyncPGPipe(Pipe):
4046
def __init__(self, ext):
4147
self.ext = ext
4248

43-
async def open(self):
44-
conn = current._db_conn = self.ext.pool.acquire()
45-
current.db = await conn.__aenter__()
49+
async def pipe(self, next_pipe, **kwargs):
50+
async with self.ext.pool.acquire() as conn:
51+
kwargs['db'] = conn
52+
return await next_pipe(**kwargs)
53+
4654

47-
async def close(self):
48-
await current._db_conn.__aexit__()
55+
class TemplatePipe(Pipe):
56+
__slots__ = ["template"]
57+
output = "str"
58+
59+
def __init__(self, template):
60+
self.template = f"templates/{template}"
61+
62+
async def pipe(self, next_pipe, **kwargs):
63+
response.content_type = "text/html; charset=utf-8"
64+
ctx = await next_pipe(**kwargs)
65+
return templates.render(self.template, ctx)
4966

5067

5168
app = App(__name__)
5269
app.config.handle_static = False
5370
templates = Renoir()
5471

72+
json_routes = app.module(__name__, 'json')
73+
json_routes.pipeline = [ServicePipe('json')]
74+
5575
db_ext = app.use_extension(AsyncPG)
5676

5777
SQL_SELECT = 'SELECT "randomnumber", "id" FROM "world" WHERE id = $1'
@@ -60,17 +80,15 @@ async def close(self):
6080
sort_key = itemgetter(1)
6181

6282

63-
@app.route()
64-
@service.json
83+
@json_routes.route()
6584
async def json():
6685
return {'message': 'Hello, World!'}
6786

6887

69-
@app.route("/db", pipeline=[db_ext.pipe])
70-
@service.json
71-
async def get_random_world():
88+
@json_routes.route("/db", pipeline=[db_ext.pipe])
89+
async def get_random_world(db):
7290
row_id = randint(1, 10000)
73-
number = await current.db.fetchval(SQL_SELECT, row_id)
91+
number = await db.fetchval(SQL_SELECT, row_id)
7492
return {'id': row_id, 'randomNumber': number}
7593

7694

@@ -86,41 +104,32 @@ def get_qparam():
86104
return rv
87105

88106

89-
@app.route("/queries", pipeline=[db_ext.pipe])
90-
@service.json
91-
async def get_random_worlds():
107+
@json_routes.route("/queries", pipeline=[db_ext.pipe])
108+
async def get_random_worlds(db):
92109
num_queries = get_qparam()
93110
row_ids = sample(range(1, 10000), num_queries)
94-
worlds = []
95-
statement = await current.db.prepare(SQL_SELECT)
96-
for row_id in row_ids:
97-
number = await statement.fetchval(row_id)
98-
worlds.append({'id': row_id, 'randomNumber': number})
99-
return worlds
111+
rows = await db.fetchmany(SQL_SELECT, [(v,) for v in row_ids])
112+
return [{'id': row_id, 'randomNumber': number[0]} for row_id, number in zip(row_ids, rows)]
100113

101114

102-
@app.route(pipeline=[db_ext.pipe], output='str')
103-
async def fortunes():
104-
response.content_type = "text/html; charset=utf-8"
105-
fortunes = await current.db.fetch('SELECT * FROM Fortune')
115+
@app.route(pipeline=[TemplatePipe("fortunes.html"), db_ext.pipe])
116+
async def fortunes(db):
117+
fortunes = await db.fetch('SELECT * FROM Fortune')
106118
fortunes.append(ROW_ADD)
107119
fortunes.sort(key=sort_key)
108-
return templates.render("templates/fortunes.html", {"fortunes": fortunes})
120+
return {"fortunes": fortunes}
109121

110122

111-
@app.route(pipeline=[db_ext.pipe])
112-
@service.json
113-
async def updates():
123+
@json_routes.route(pipeline=[db_ext.pipe])
124+
async def updates(db):
114125
num_queries = get_qparam()
115126
updates = list(zip(
116127
sample(range(1, 10000), num_queries),
117128
sorted(sample(range(1, 10000), num_queries))
118129
))
119130
worlds = [{'id': row_id, 'randomNumber': number} for row_id, number in updates]
120-
statement = await current.db.prepare(SQL_SELECT)
121-
for row_id, _ in updates:
122-
await statement.fetchval(row_id)
123-
await current.db.executemany(SQL_UPDATE, updates)
131+
await db.executemany(SQL_SELECT, [(i[0],) for i in updates])
132+
await db.executemany(SQL_UPDATE, updates)
124133
return worlds
125134

126135

frameworks/Python/emmett55/emmett55.dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:3.11-slim
1+
FROM python:3.13-slim
22

33
ADD ./ /emmett55
44

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
asyncpg==0.29.0
1+
asyncpg==0.30.0
22
emmett55[orjson,uvloop]>=1.2.0,<1.3.0
33
renoir==1.8.0

frameworks/Python/granian/app_asgi.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ async def route_db(scope, receive, send):
106106
async def route_queries(scope, receive, send):
107107
num_queries = get_num_queries(scope)
108108
row_ids = sample(range(1, 10000), num_queries)
109-
worlds = []
110109

111110
async with pool.acquire() as connection:
112111
rows = await connection.fetchmany(SQL_SELECT, [(v,) for v in row_ids])

frameworks/Python/granian/granian-nogil.dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ RUN uv pip install -r requirements-nogil.txt
1313

1414
EXPOSE 8080
1515

16-
CMD uv run python run_nogil.py rsgi st
16+
CMD uv run python run_nogil.py rsgi mt

frameworks/Python/granian/granian-rsgi.dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ RUN pip install -r /granian/requirements.txt
88

99
EXPOSE 8080
1010

11-
CMD python run.py rsgi st
11+
CMD python run.py rsgi mt
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
granian[rloop]>=2.5.0,<2.6.0
1+
granian[rloop]>=2.6.0,<2.7.0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
asyncpg==0.30.0
2-
granian[uvloop]>=2.5.0,<2.6.0
2+
granian[uvloop]>=2.6.0,<2.7.0
33
jinja2==3.1.6
44
orjson==3.11.3

0 commit comments

Comments
 (0)