Explorar o código

[Python] Bump Panther to 5.0.1 (#9995)

Ali RajabNezhad hai 1 mes
pai
achega
890ba36aa7

+ 37 - 50
frameworks/Python/panther/app.py

@@ -1,5 +1,4 @@
 import multiprocessing
-from pathlib import Path
 from random import randint, sample
 
 import asyncpg
@@ -10,19 +9,22 @@ from panther.events import Event
 from panther.request import Request
 from panther.response import Response, PlainTextResponse, HTMLResponse
 
-READ_ROW_SQL = 'SELECT "id", "randomnumber" FROM "world" WHERE id = $1'
-WRITE_ROW_SQL = 'UPDATE "world" SET "randomnumber"=$1 WHERE id=$2'
-ADDITIONAL_ROW = [0, 'Additional fortune added at request time.']
-MAX_POOL_SIZE = 1000 // multiprocessing.cpu_count()
-MIN_POOL_SIZE = max(int(MAX_POOL_SIZE / 2), 1)
+cpu_count = multiprocessing.cpu_count()
+MAX_POOL_SIZE = 1000 // cpu_count
+MIN_POOL_SIZE = max(MAX_POOL_SIZE // 2, 1)
 
-pool = None
+connection_pool = None
+
+fortune_template = jinja2.Environment(
+    loader=jinja2.FileSystemLoader('templates'),
+    autoescape=True
+).get_template('fortune.html')
 
 
 @Event.startup
-async def create_db_pool():
-    global pool
-    pool = await asyncpg.create_pool(
+async def on_startup():
+    global connection_pool
+    connection_pool = await asyncpg.create_pool(
         user='benchmarkdbuser',
         password='benchmarkdbpass',
         database='hello_world',
@@ -34,60 +36,42 @@ async def create_db_pool():
 
 
 @Event.shutdown
-async def clean_db_pool():
-    await pool.close()
-
-
-with Path('templates/fortune.html').open() as f:
-    fortune_template = jinja2.Template(f.read())
-
-
-def get_num_queries(request):
-    value = request.query_params.get('queries')
-    if value is None:
-        return 1
-
-    try:
-        query_count = int(value)
-    except ValueError:
-        return 1
-    if query_count < 1:
-        return 1
-    if query_count > 500:
-        return 500
-    return query_count
+async def on_shutdown():
+    await connection_pool.close()
 
 
 @API()
-async def json_serialization():
+def json_serialization():
     return Response(data={'message': 'Hello, world!'})
 
 
 @API()
 async def single_database_query():
     row_id = randint(1, 10000)
-    async with pool.acquire() as connection:
-        number = await connection.fetchval(READ_ROW_SQL, row_id)
+    async with connection_pool.acquire() as connection:
+        number = await connection.fetchval('SELECT id, randomnumber FROM world WHERE id = $1', row_id)
     return Response(data={'id': row_id, 'randomNumber': number})
 
 
 @API()
 async def multiple_database_queries(request: Request):
-    num_queries = get_num_queries(request)
-    row_ids = sample(range(1, 10000), num_queries)
-
-    async with pool.acquire() as connection:
-        statement = await connection.prepare(READ_ROW_SQL)
+    try:
+        count = int(request.query_params.get('queries', 1))
+    except (ValueError, TypeError):
+        count = 1
+    row_ids = sample(range(1, 10000), min(max(count, 1), 500))
+    async with connection_pool.acquire() as connection:
+        statement = await connection.prepare('SELECT id, randomnumber FROM world WHERE id = $1')
         worlds = [{'id': i, 'randomNumber': await statement.fetchval(i)} for i in row_ids]
-
     return Response(data=worlds)
 
 
 @API()
 async def fortunes():
-    async with pool.acquire() as connection:
+    async with connection_pool.acquire() as connection:
         fortune_records = await connection.fetch('SELECT * FROM Fortune')
-    fortune_records.append(ADDITIONAL_ROW)
+    fortune_records = [(row['id'], row['message']) for row in fortune_records]
+    fortune_records.append((0, 'Additional fortune added at request time.'))
     fortune_records.sort(key=lambda row: row[1])
     data = fortune_template.render(fortunes=fortune_records)
     return HTMLResponse(data=data)
@@ -95,24 +79,27 @@ async def fortunes():
 
 @API()
 async def database_updates(request: Request):
-    num_queries = get_num_queries(request)
+    try:
+        count = int(request.query_params.get('queries', 1))
+    except (ValueError, TypeError):
+        count = 1
+    num_queries = min(max(count, 1), 500)
+
     updates = list(zip(
         sample(range(1, 10000), num_queries),
         sorted(sample(range(1, 10000), num_queries))
     ))
-
     worlds = [{'id': row_id, 'randomNumber': number} for row_id, number in updates]
-
-    async with pool.acquire() as connection:
-        statement = await connection.prepare(READ_ROW_SQL)
+    async with connection_pool.acquire() as connection:
+        statement = await connection.prepare('SELECT id, randomnumber FROM world WHERE id = $1')
         for _, row_id in updates:
             await statement.fetchval(row_id)
-        await connection.executemany(WRITE_ROW_SQL, updates)
+        await connection.executemany('UPDATE world SET randomnumber = $1 WHERE id = $2', updates)
     return Response(data=worlds)
 
 
 @API()
-async def plaintext():
+def plaintext():
     return PlainTextResponse(b'Hello, world!')
 
 

+ 11 - 7
frameworks/Python/panther/panther.dockerfile

@@ -1,12 +1,16 @@
-FROM python:3.11-bullseye
-
+FROM python:3.12 AS builder
 WORKDIR /panther
+RUN python -m venv /opt/venv
+RUN pip install --no-cache-dir uv
+COPY requirements.txt .
+RUN /usr/local/bin/uv pip install -r requirements.txt --python /opt/venv/bin/python
 
-COPY ./ /panther
-
-RUN pip3 install -U pip
-RUN pip3 install -r /panther/requirements.txt
+FROM python:3.12-slim AS production
+ENV PYTHONUNBUFFERED=1
+ENV PATH="/opt/venv/bin:$PATH"
+COPY --from=builder /opt/venv /opt/venv
+WORKDIR /panther
+COPY . /panther
 
 EXPOSE 8080
-
 CMD gunicorn app:app -k uvicorn.workers.UvicornWorker -c panther_conf.py

+ 4 - 4
frameworks/Python/panther/requirements.txt

@@ -1,5 +1,5 @@
-panther==4.3.1
-cython==3.0.11
-asyncpg==0.29.0
+panther==5.0.1
+cython==3.1.2
+asyncpg==0.30.0
 gunicorn==23.0.0
-uvloop==0.20.0
+uvloop==0.21.0