Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix deprecation warnings for python 3.10 #262

Merged
merged 1 commit into from
May 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions asgiref/compatibility.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import inspect
import sys


def is_double_callable(application):
Expand Down Expand Up @@ -45,3 +46,16 @@ def guarantee_single_callable(application):
if is_double_callable(application):
application = double_to_single_callable(application)
return application


if sys.version_info >= (3, 7):
# these were introduced in 3.7
get_running_loop = asyncio.get_running_loop
run_future = asyncio.run
create_task = asyncio.create_task
else:
# marked as deprecated in 3.10, did not exist before 3.7
get_running_loop = asyncio.get_event_loop
run_future = asyncio.ensure_future
# does nothing, this is fine for <3.7
create_task = lambda task: task
8 changes: 4 additions & 4 deletions asgiref/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import time
import traceback

from .compatibility import guarantee_single_callable
from .compatibility import get_running_loop, guarantee_single_callable, run_future

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -56,7 +56,7 @@ def run(self):
"""
Runs the asyncio event loop with our handler loop.
"""
event_loop = asyncio.get_event_loop()
event_loop = get_running_loop()
asyncio.ensure_future(self.application_checker())
try:
event_loop.run_until_complete(self.handle())
Expand Down Expand Up @@ -88,12 +88,12 @@ def get_or_create_application_instance(self, scope_id, scope):
input_queue = asyncio.Queue()
application_instance = guarantee_single_callable(self.application)
# Run it, and stash the future for later checking
future = asyncio.ensure_future(
future = run_future(
application_instance(
scope=scope,
receive=input_queue.get,
send=lambda message: self.application_send(scope, message),
)
),
)
self.application_instances[scope_id] = {
"input_queue": input_queue,
Expand Down
15 changes: 10 additions & 5 deletions asgiref/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from concurrent.futures import Future, ThreadPoolExecutor
from typing import Any, Callable, Dict, Optional, Union

from .compatibility import get_running_loop
from .current_thread_executor import CurrentThreadExecutor
from .local import Local

Expand Down Expand Up @@ -132,7 +133,7 @@ def __init__(self, awaitable, force_new_loop=False):
self.main_event_loop = None
else:
try:
self.main_event_loop = asyncio.get_event_loop()
self.main_event_loop = get_running_loop()
except RuntimeError:
# There's no event loop in this thread. Look for the threadlocal if
# we're inside SyncToAsync
Expand All @@ -151,7 +152,7 @@ def __init__(self, awaitable, force_new_loop=False):
def __call__(self, *args, **kwargs):
# You can't call AsyncToSync from a thread with a running event loop
try:
event_loop = asyncio.get_event_loop()
event_loop = get_running_loop()
except RuntimeError:
pass
else:
Expand Down Expand Up @@ -238,7 +239,11 @@ def _run_event_loop(self, loop, coro):
tasks = asyncio.Task.all_tasks(loop)
for task in tasks:
task.cancel()
loop.run_until_complete(asyncio.gather(*tasks, return_exceptions=True))

async def gather():
await asyncio.gather(*tasks, return_exceptions=True)

loop.run_until_complete(gather())
for task in tasks:
if task.cancelled():
continue
Expand Down Expand Up @@ -320,7 +325,7 @@ class SyncToAsync:

# If they've set ASGI_THREADS, update the default asyncio executor for now
if "ASGI_THREADS" in os.environ:
loop = asyncio.get_event_loop()
loop = get_running_loop()
loop.set_default_executor(
ThreadPoolExecutor(max_workers=int(os.environ["ASGI_THREADS"]))
)
Expand Down Expand Up @@ -370,7 +375,7 @@ def __init__(
pass

async def __call__(self, *args, **kwargs):
loop = asyncio.get_event_loop()
loop = get_running_loop()

# Work out what thread to run the code in
if self._thread_sensitive:
Expand Down
19 changes: 14 additions & 5 deletions tests/test_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import pytest

from asgiref.compatibility import create_task, get_running_loop
from asgiref.sync import ThreadSensitiveContext, async_to_sync, sync_to_async


Expand All @@ -33,12 +34,17 @@ def sync_function():
assert result == 42
assert end - start >= 1
# Set workers to 1, call it twice and make sure that works right
loop = asyncio.get_event_loop()
old_executor = loop._default_executor
loop = get_running_loop()
old_executor = loop._default_executor or ThreadPoolExecutor()
loop.set_default_executor(ThreadPoolExecutor(max_workers=1))
try:
start = time.monotonic()
await asyncio.wait([async_function(), async_function()])
await asyncio.wait(
[
create_task(async_function()),
create_task(async_function()),
]
)
end = time.monotonic()
# It should take at least 2 seconds as there's only one worker.
assert end - start >= 2
Expand Down Expand Up @@ -428,7 +434,7 @@ def inner(result):
result["thread"] = threading.current_thread()

# Run it (in supposed parallel!)
await asyncio.wait([outer(result_1), inner(result_2)])
await asyncio.wait([create_task(outer(result_1)), create_task(inner(result_2))])

# They should not have run in the main thread, but in the same thread
assert result_1["thread"] != threading.current_thread()
Expand All @@ -449,7 +455,10 @@ async def fn():
async with ThreadSensitiveContext():
# Run it (in supposed parallel!)
await asyncio.wait(
[store_thread_async(result_1), store_thread_async(result_2)]
[
create_task(store_thread_async(result_1)),
create_task(store_thread_async(result_2)),
]
)

await fn()
Expand Down
3 changes: 2 additions & 1 deletion tests/test_sync_contextvars.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import pytest

from asgiref.compatibility import create_task
from asgiref.sync import ThreadSensitiveContext, async_to_sync, sync_to_async

contextvars = pytest.importorskip("contextvars")
Expand All @@ -25,7 +26,7 @@ async def fn(result):
await store_thread(result)

# Run it (in true parallel!)
await asyncio.wait([fn(result_1), fn(result_2)])
await asyncio.wait([create_task(fn(result_1)), create_task(fn(result_2))])

# They should not have run in the main thread, and on different threads
assert result_1["thread"] != threading.current_thread()
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tox]
envlist =
py{36,37,38,39}-{test,mypy}
py{36,37,38,39,310}-{test,mypy}
qa

[testenv]
Expand Down