Skip to content

Commit eacbae7

Browse files
committed
handling edge cases in run_sync
1 parent 77afec4 commit eacbae7

File tree

3 files changed

+30
-7
lines changed

3 files changed

+30
-7
lines changed

piccolo/apps/user/tables.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
import secrets
77
import typing as t
88

9-
from asgiref.sync import async_to_sync
10-
11-
from piccolo.table import Table
129
from piccolo.columns import Varchar, Boolean, Secret
1310
from piccolo.columns.readable import Readable
11+
from piccolo.table import Table
12+
from piccolo.utils.sync import run_sync
1413

1514

1615
class BaseUser(Table, tablename="piccolo_user"):
@@ -50,7 +49,7 @@ def get_readable(cls) -> Readable:
5049

5150
@classmethod
5251
def update_password_sync(cls, user: t.Union[str, int], password: str):
53-
return async_to_sync(cls.update_password)(user, password)
52+
return run_sync(cls.update_password(user, password))
5453

5554
@classmethod
5655
async def update_password(cls, user: t.Union[str, int], password: str):
@@ -112,7 +111,7 @@ def login_sync(cls, username: str, password: str) -> t.Optional[int]:
112111
"""
113112
Returns the user_id if a match is found.
114113
"""
115-
return async_to_sync(cls.login)(username, password)
114+
return run_sync(cls.login(username, password))
116115

117116
@classmethod
118117
async def login(cls, username: str, password: str) -> t.Optional[int]:

piccolo/utils/sync.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
import asyncio
2+
from concurrent.futures import ThreadPoolExecutor
23

34

45
def run_sync(coroutine):
5-
return asyncio.run(coroutine)
6+
"""
7+
Run the coroutine synchronously - trying to accomodate as many edge cases
8+
as possible.
9+
10+
1. When called within a coroutine.
11+
2. When called from `python -m asyncio`, or iPython with %autoawait
12+
enabled, which means an event loop may already be running in the
13+
current thread.
14+
15+
"""
16+
try:
17+
loop = asyncio.get_event_loop()
18+
except RuntimeError:
19+
return asyncio.run(coroutine)
20+
else:
21+
if loop.is_running():
22+
new_loop = asyncio.new_event_loop()
23+
24+
with ThreadPoolExecutor(max_workers=1) as executor:
25+
future = executor.submit(
26+
new_loop.run_until_complete, coroutine
27+
)
28+
return future.result()
29+
else:
30+
return loop.run_until_complete(coroutine)

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
aiosqlite==0.16.0
2-
asgiref==3.3.0
32
asyncpg==0.21.0
43
black==19.10b0
54
colorama==0.4.*

0 commit comments

Comments
 (0)