commit:     ffad4d6fdd33979f972594f1be9155a81a78a769
Author:     Ekaterina Vaartis <vaartis <AT> kotobank <DOT> ch>
AuthorDate: Thu May 20 19:48:37 2021 +0000
Commit:     Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Thu May 20 20:10:58 2021 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=ffad4d6f

dev-python/asgiref: Bump to python 3.10 with a patch for warnings

Upstream PR: https://github.com/django/asgiref/pull/262

Signed-off-by: Ekaterina Vaartis <vaartis <AT> kotobank.ch>
Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>

 dev-python/asgiref/asgiref-3.3.4.ebuild            |   7 +-
 .../files/asgiref-3.3.4-py310-warnings.patch       | 235 +++++++++++++++++++++
 2 files changed, 241 insertions(+), 1 deletion(-)

diff --git a/dev-python/asgiref/asgiref-3.3.4.ebuild 
b/dev-python/asgiref/asgiref-3.3.4.ebuild
index e32555868e8..709bb95bb8f 100644
--- a/dev-python/asgiref/asgiref-3.3.4.ebuild
+++ b/dev-python/asgiref/asgiref-3.3.4.ebuild
@@ -3,7 +3,7 @@
 
 EAPI=7
 
-PYTHON_COMPAT=( python3_{7..9} pypy3 )
+PYTHON_COMPAT=( python3_{7..10} pypy3 )
 inherit distutils-r1
 
 DESCRIPTION="ASGI utilities (successor to WSGI)"
@@ -24,4 +24,9 @@ RDEPEND="
 BDEPEND="
        test? ( dev-python/pytest-asyncio[${PYTHON_USEDEP}] )"
 
+PATCHES=(
+       # Provided to upstream: https://github.com/django/asgiref/pull/262
+       "${FILESDIR}/${P}-py310-warnings.patch"
+)
+
 distutils_enable_tests pytest

diff --git a/dev-python/asgiref/files/asgiref-3.3.4-py310-warnings.patch 
b/dev-python/asgiref/files/asgiref-3.3.4-py310-warnings.patch
new file mode 100644
index 00000000000..1cd017ddfbd
--- /dev/null
+++ b/dev-python/asgiref/files/asgiref-3.3.4-py310-warnings.patch
@@ -0,0 +1,235 @@
+From 0c9e989f18b99ea24a1fb3ea2c8a66fd295c2178 Mon Sep 17 00:00:00 2001
+From: Ekaterina Vaartis <vaar...@kotobank.ch>
+Date: Thu, 20 May 2021 19:44:15 +0300
+Subject: [PATCH] Fix deprecation warnings for python 3.10
+
+asyncio.get_event_loop was marked as deprecated, the documnetation
+now refers to asyncio.get_running_loop([1])
+
+asyncio.ensure_future issues a deprecation warning if there is no
+running event loop([2]), so use asyncio.run which creates and destroys the
+loop itself
+
+asyncio.gather issues a warning if run outside of event
+loop (i.e. there is no running event loop)([3]), so wrap it into an
+async def
+
+explicit passing of coroutine objects to asyncio.wait is deprecated
+since 3.8([4]), so wrap them in asyncio.create_task
+
+plus, add 3.10 to tox.ini
+
+[1]: 
https://docs.python.org/3.10/library/asyncio-eventloop.html#asyncio.get_event_loop
+[2]: 
https://docs.python.org/3.10/library/asyncio-future.html#asyncio.ensure_future
+[3]: https://docs.python.org/3.10/library/asyncio-task.html#asyncio.gather
+[4]: https://docs.python.org/3.10/library/asyncio-task.html#asyncio.wait
+---
+ asgiref/compatibility.py       | 14 ++++++++++++++
+ asgiref/server.py              |  8 ++++----
+ asgiref/sync.py                | 15 ++++++++++-----
+ tests/test_sync.py             | 19 ++++++++++++++-----
+ tests/test_sync_contextvars.py |  3 ++-
+ tox.ini                        |  2 +-
+ 6 files changed, 45 insertions(+), 16 deletions(-)
+
+diff --git a/asgiref/compatibility.py b/asgiref/compatibility.py
+index eccaee0..614b2e6 100644
+--- a/asgiref/compatibility.py
++++ b/asgiref/compatibility.py
+@@ -1,5 +1,6 @@
+ import asyncio
+ import inspect
++import sys
+ 
+ 
+ def is_double_callable(application):
+@@ -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
+diff --git a/asgiref/server.py b/asgiref/server.py
+index f975f78..fb1c394 100644
+--- a/asgiref/server.py
++++ b/asgiref/server.py
+@@ -3,7 +3,7 @@ import logging
+ 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__)
+ 
+@@ -56,7 +56,7 @@ class StatelessServer:
+         """
+         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())
+@@ -88,12 +88,12 @@ class StatelessServer:
+         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,
+diff --git a/asgiref/sync.py b/asgiref/sync.py
+index 6b87c7e..9476e66 100644
+--- a/asgiref/sync.py
++++ b/asgiref/sync.py
+@@ -9,6 +9,7 @@ import weakref
+ 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
+ 
+@@ -132,7 +133,7 @@ class AsyncToSync:
+             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
+@@ -151,7 +152,7 @@ class AsyncToSync:
+     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:
+@@ -238,7 +239,11 @@ class AsyncToSync:
+                     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
+@@ -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"]))
+         )
+@@ -370,7 +375,7 @@ class SyncToAsync:
+             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:
+diff --git a/tests/test_sync.py b/tests/test_sync.py
+index cf0e0c5..8ed76a7 100644
+--- a/tests/test_sync.py
++++ b/tests/test_sync.py
+@@ -9,6 +9,7 @@ from unittest import TestCase
+ 
+ import pytest
+ 
++from asgiref.compatibility import create_task, get_running_loop
+ from asgiref.sync import ThreadSensitiveContext, async_to_sync, sync_to_async
+ 
+ 
+@@ -33,12 +34,17 @@ async def test_sync_to_async():
+     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
+@@ -428,7 +434,7 @@ async def test_thread_sensitive_outside_async():
+         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()
+@@ -449,7 +455,10 @@ async def test_thread_sensitive_with_context_matches():
+         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()
+diff --git a/tests/test_sync_contextvars.py b/tests/test_sync_contextvars.py
+index b1027aa..9665bf9 100644
+--- a/tests/test_sync_contextvars.py
++++ b/tests/test_sync_contextvars.py
+@@ -4,6 +4,7 @@ import time
+ 
+ import pytest
+ 
++from asgiref.compatibility import create_task
+ from asgiref.sync import ThreadSensitiveContext, async_to_sync, sync_to_async
+ 
+ contextvars = pytest.importorskip("contextvars")
+@@ -25,7 +26,7 @@ async def test_thread_sensitive_with_context_different():
+             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()

Reply via email to