Skip to content

Commit 697bb38

Browse files
committed
Add journey test for gevent+wsgi usage, add back litestar test
1 parent 8c0b0f1 commit 697bb38

7 files changed

Lines changed: 110 additions & 75 deletions

File tree

journey_tests/gunicorn/wsgi.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from typing import List
2+
3+
from flask import Flask, g
4+
5+
from journey_tests.journeys import SyncJourneys
6+
7+
app = Flask(__name__)
8+
9+
10+
def get_sync_client() -> SyncJourneys:
11+
if "sync" not in g:
12+
g.sync = SyncJourneys.use()
13+
return g.sync
14+
15+
16+
@app.route("/sync-in-sync")
17+
def sync() -> List[dict]:
18+
return get_sync_client().simple()
19+
20+
21+
if __name__ == "__main__":
22+
app.run(debug=False, host="0.0.0.0")

journey_tests/journeys.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from typing import List
1+
from typing import List, cast
22

33
from weaviate import WeaviateAsyncClient, WeaviateClient, connect_to_local, use_async_with_local
4-
from weaviate.classes.config import Configure, DataType, Property
4+
from weaviate.classes.config import DataType, Property
55

66

77
class SyncJourneys:
@@ -25,14 +25,13 @@ def simple(self) -> List[dict]:
2525
Property(name="name", data_type=DataType.TEXT),
2626
Property(name="age", data_type=DataType.INT),
2727
],
28-
vectorizer_config=Configure.Vectorizer.text2vec_contextionary(),
2928
)
3029
with collection.batch.dynamic() as batch:
3130
for i in range(1000):
3231
batch.add_object({"name": f"Person {i}", "age": i})
3332
res = collection.query.fetch_objects(limit=100)
3433
self.__client.collections.delete(name)
35-
return [obj.properties for obj in res.objects]
34+
return [cast(dict, obj.properties) for obj in res.objects]
3635

3736

3837
class AsyncJourneys:
@@ -58,9 +57,8 @@ async def simple(self) -> List[dict]:
5857
Property(name="name", data_type=DataType.TEXT),
5958
Property(name="age", data_type=DataType.INT),
6059
],
61-
vectorizer_config=Configure.Vectorizer.text2vec_contextionary(),
6260
)
6361
await collection.data.insert_many([{"name": f"Person {i}", "age": i} for i in range(100)])
6462
res = await collection.query.fetch_objects(limit=1000)
6563
await self.__client.collections.delete(name)
66-
return [obj.properties for obj in res.objects]
64+
return [cast(dict, obj.properties) for obj in res.objects]

journey_tests/run.sh

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,23 @@ function wait(){
3232
}
3333

3434
pytest ./journey_tests
35+
3536
pip install gunicorn
3637
pip install uvicorn
37-
nohup gunicorn --bind=0.0.0.0:8000 --workers=2 --worker-class "uvicorn.workers.UvicornWorker" --preload journey_tests.gunicorn.app:app &
38+
39+
nohup gunicorn --bind=0.0.0.0:8000 --workers=2 --worker-class "uvicorn.workers.UvicornWorker" --preload journey_tests.gunicorn.asgi:app &
3840
echo $! > gunicorn_pid.txt
3941
wait "http://localhost:8000"
42+
4043
pytest ./journey_tests/gunicorn/test.py
4144
kill -9 $(cat gunicorn_pid.txt)
4245
rm gunicorn_pid.txt
46+
47+
nohup gunicorn --bind=0.0.0.0:8000 --workers=2 --worker-class "gevent" --preload journey_tests.gunicorn.wsgi:app &
48+
echo $! > gunicorn_pid.txt
49+
wait "http://localhost:8000"
50+
51+
pytest ./journey_tests/gunicorn/test.py
52+
kill -9 $(cat gunicorn_pid.txt)
53+
rm gunicorn_pid.txt
54+

journey_tests/test_flask.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import List
2+
13
from flask import Flask, g
24

35
from journey_tests.journeys import AsyncJourneys, SyncJourneys
@@ -18,17 +20,17 @@ async def get_async_client() -> AsyncJourneys:
1820

1921

2022
@app.route("/sync-in-sync")
21-
def sync() -> dict:
23+
def sync() -> List[dict]:
2224
return get_sync_client().simple()
2325

2426

2527
@app.route("/sync-in-async")
26-
async def sync_() -> dict:
28+
async def sync_() -> List[dict]:
2729
return get_sync_client().simple()
2830

2931

3032
@app.route("/async-in-async")
31-
async def async_() -> dict:
33+
async def async_() -> List[dict]:
3234
return await (await get_async_client()).simple()
3335

3436

journey_tests/test_litestar.py

Lines changed: 65 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,65 @@
1-
# litestart not yet supported by 3.13
2-
# from contextlib import asynccontextmanager
3-
#
4-
# from litestar import Litestar, get
5-
# from litestar.datastructures import State
6-
# from litestar.testing import TestClient
7-
#
8-
# from journey_tests.journeys import AsyncJourneys, SyncJourneys
9-
#
10-
# class MyState(State):
11-
# sync: SyncJourneys
12-
# async_: AsyncJourneys
13-
#
14-
#
15-
# @asynccontextmanager
16-
# async def lifespan(app: Litestar):
17-
# sync = SyncJourneys.use()
18-
# async_ = await AsyncJourneys.use()
19-
# app.state.sync = sync
20-
# app.state.async_ = async_
21-
# try:
22-
# yield
23-
# finally:
24-
# sync.close()
25-
# await async_.close()
26-
#
27-
#
28-
# @get("/sync-in-sync", sync_to_thread=True)
29-
# def sync_in_sync(state: MyState) -> dict:
30-
# return state.sync.simple()
31-
#
32-
#
33-
# @get("/sync-in-async", sync_to_thread=True)
34-
# async def sync_in_async(state: MyState) -> dict:
35-
# return state.sync.simple()
36-
#
37-
#
38-
# @get("/async-in-async")
39-
# async def async_in_async(state: MyState) -> dict:
40-
# return await state.async_.simple()
41-
#
42-
#
43-
# app = Litestar(route_handlers=[sync_in_sync, sync_in_async, async_in_async], lifespan=[lifespan])
44-
#
45-
#
46-
# def test_sync_in_sync() -> None:
47-
# with TestClient(app=app) as client:
48-
# res = client.get("/sync-in-sync")
49-
# assert res.status_code == 200
50-
# assert len(res.json()) == 100
51-
#
52-
#
53-
# def test_sync_in_async() -> None:
54-
# with TestClient(app=app) as client:
55-
# res = client.get("/sync-in-async")
56-
# assert res.status_code == 200
57-
# assert len(res.json()) == 100
58-
#
59-
#
60-
# def test_async_in_async() -> None:
61-
# with TestClient(app=app) as client:
62-
# res = client.get("/async-in-async")
63-
# assert res.status_code == 200
64-
# assert len(res.json()) == 100
1+
from contextlib import asynccontextmanager
2+
from typing import List
3+
4+
from litestar import Litestar, get
5+
from litestar.datastructures import State
6+
from litestar.testing import TestClient
7+
8+
from journey_tests.journeys import AsyncJourneys, SyncJourneys
9+
10+
11+
class MyState(State):
12+
sync: SyncJourneys
13+
async_: AsyncJourneys
14+
15+
16+
@asynccontextmanager
17+
async def lifespan(app: Litestar):
18+
sync = SyncJourneys.use()
19+
async_ = await AsyncJourneys.use()
20+
app.state.sync = sync
21+
app.state.async_ = async_
22+
try:
23+
yield
24+
finally:
25+
sync.close()
26+
await async_.close()
27+
28+
29+
@get("/sync-in-sync", sync_to_thread=True)
30+
def sync_in_sync(state: MyState) -> List[dict]:
31+
return state.sync.simple()
32+
33+
34+
@get("/sync-in-async", sync_to_thread=True)
35+
async def sync_in_async(state: MyState) -> List[dict]:
36+
return state.sync.simple()
37+
38+
39+
@get("/async-in-async")
40+
async def async_in_async(state: MyState) -> List[dict]:
41+
return await state.async_.simple()
42+
43+
44+
app = Litestar(route_handlers=[sync_in_sync, sync_in_async, async_in_async], lifespan=[lifespan])
45+
46+
47+
def test_sync_in_sync() -> None:
48+
with TestClient(app=app) as client:
49+
res = client.get("/sync-in-sync")
50+
assert res.status_code == 200
51+
assert len(res.json()) == 100
52+
53+
54+
def test_sync_in_async() -> None:
55+
with TestClient(app=app) as client:
56+
res = client.get("/sync-in-async")
57+
assert res.status_code == 200
58+
assert len(res.json()) == 100
59+
60+
61+
def test_async_in_async() -> None:
62+
with TestClient(app=app) as client:
63+
res = client.get("/async-in-async")
64+
assert res.status_code == 200
65+
assert len(res.json()) == 100

requirements-devel.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ polars>=0.20.26,<1.18.0
3333

3434
fastapi>=0.111.0,<1.0.0
3535
flask[async]>=2.0.0,<4.0.0
36-
# litestar>=2.13.0,<3.0.0 does not support python 3.13 yet - reenable when it does
36+
litestar>=2.14.0,<3.0.0
3737

3838
mypy==1.14.1
3939
mypy-extensions==1.0.0

0 commit comments

Comments
 (0)