Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-asgiref for openSUSE:Factory 
checked in at 2023-11-30 21:59:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-asgiref (Old)
 and      /work/SRC/openSUSE:Factory/.python-asgiref.new.25432 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-asgiref"

Thu Nov 30 21:59:42 2023 rev:10 rq:1129812 version:3.7.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-asgiref/python-asgiref.changes    
2023-04-22 22:03:06.386165616 +0200
+++ /work/SRC/openSUSE:Factory/.python-asgiref.new.25432/python-asgiref.changes 
2023-11-30 22:00:40.927647124 +0100
@@ -1,0 +2,21 @@
+Wed Nov 29 13:04:33 UTC 2023 - Dirk Müller <dmuel...@suse.com>
+
+- update to 3.7.2:
+  * The type annotations for SyncToAsync and AsyncToSync have been
+    changed to more accurately reflect the kind of callables they
+    return.
+  * On Python 3.10 and below, the version of the "typing_extensions"
+    package is now constrained to be at least version 4 (as we depend
+    on functionality in that version and above)
+  * Contextvars are now required for the implementation of `sync`
+    as Python 3.6 is now no longer a supported version.
+  * sync_to_async and async_to_sync now pass-through
+  * Debug and Lifespan State extensions have resulted in a typing
+    change for some request and response types. This change should
+    be backwards-compatible.
+  * ``asgiref`` frames will now be hidden in Django tracebacks
+    by default.
+  * Raw performance and garbage collection improvements in Local,
+    SyncToAsync, and AsyncToSync.
+
+-------------------------------------------------------------------

Old:
----
  asgiref-3.6.0.tar.gz

New:
----
  asgiref-3.7.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-asgiref.spec ++++++
--- /var/tmp/diff_new_pack.TyK56N/_old  2023-11-30 22:00:41.431665691 +0100
+++ /var/tmp/diff_new_pack.TyK56N/_new  2023-11-30 22:00:41.435665839 +0100
@@ -16,32 +16,25 @@
 #
 
 
-%define skip_python2 1
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %{?sle15_python_module_pythons}
 Name:           python-asgiref
-Version:        3.6.0
+Version:        3.7.2
 Release:        0
 Summary:        ASGI specs, helper code, and adapters
 License:        BSD-3-Clause
 Group:          Development/Languages/Python
 URL:            https://github.com/django/asgiref/
 Source:         
https://files.pythonhosted.org/packages/source/a/asgiref/asgiref-%{version}.tar.gz
-BuildRequires:  %{python_module base >= 3.6}
+BuildRequires:  %{python_module base >= 3.7}
+BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module pytest-asyncio}
 BuildRequires:  %{python_module pytest}
-BuildRequires:  %{python_module setuptools}
+BuildRequires:  %{python_module wheel}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
 BuildArch:      noarch
-%if %{?suse_version} < 1540
-BuildRequires:  %{python_module typing_extensions}
-%else
-BuildRequires:  %{python_module typing_extensions if %python-base < 3.8}
-%endif
-%if 0%{python_version_nodots} < 38
-Requires:       python-typing_extensions
-%endif
+BuildRequires:  %{python_module typing-extensions > 4}
+Requires:       python-typing-extensions > 4
 %python_subpackages
 
 %description
@@ -53,10 +46,10 @@
 %setup -q -n asgiref-%{version}
 
 %build
-%python_build
+%pyproject_wheel
 
 %install
-%python_install
+%pyproject_install
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check
@@ -65,5 +58,6 @@
 %files %{python_files}
 %license LICENSE
 %doc README.rst
-%{python_sitelib}/*
+%{python_sitelib}/asgiref
+%{python_sitelib}/asgiref-%{version}.dist-info
 

++++++ asgiref-3.6.0.tar.gz -> asgiref-3.7.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.6.0/PKG-INFO new/asgiref-3.7.2/PKG-INFO
--- old/asgiref-3.6.0/PKG-INFO  2022-12-20 10:06:25.459167200 +0100
+++ new/asgiref-3.7.2/PKG-INFO  2023-05-27 19:21:19.747680700 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: asgiref
-Version: 3.6.0
+Version: 3.7.2
 Summary: ASGI specs, helper code, and adapters
 Home-page: https://github.com/django/asgiref/
 Author: Django Software Foundation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.6.0/asgiref/__init__.py 
new/asgiref-3.7.2/asgiref/__init__.py
--- old/asgiref-3.6.0/asgiref/__init__.py       2022-12-20 09:57:26.000000000 
+0100
+++ new/asgiref-3.7.2/asgiref/__init__.py       2023-05-27 19:20:44.000000000 
+0200
@@ -1 +1 @@
-__version__ = "3.6.0"
+__version__ = "3.7.2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.6.0/asgiref/current_thread_executor.py 
new/asgiref-3.7.2/asgiref/current_thread_executor.py
--- old/asgiref-3.6.0/asgiref/current_thread_executor.py        2022-04-19 
09:47:42.000000000 +0200
+++ new/asgiref-3.7.2/asgiref/current_thread_executor.py        2023-05-23 
18:35:51.000000000 +0200
@@ -1,6 +1,17 @@
 import queue
+import sys
 import threading
 from concurrent.futures import Executor, Future
+from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union
+
+if sys.version_info >= (3, 10):
+    from typing import ParamSpec
+else:
+    from typing_extensions import ParamSpec
+
+_T = TypeVar("_T")
+_P = ParamSpec("_P")
+_R = TypeVar("_R")
 
 
 class _WorkItem:
@@ -9,13 +20,20 @@
     Copied from ThreadPoolExecutor (but it's private, so we're not going to 
rely on importing it)
     """
 
-    def __init__(self, future, fn, args, kwargs):
+    def __init__(
+        self,
+        future: "Future[_R]",
+        fn: Callable[_P, _R],
+        *args: _P.args,
+        **kwargs: _P.kwargs,
+    ):
         self.future = future
         self.fn = fn
         self.args = args
         self.kwargs = kwargs
 
-    def run(self):
+    def run(self) -> None:
+        __traceback_hide__ = True  # noqa: F841
         if not self.future.set_running_or_notify_cancel():
             return
         try:
@@ -23,7 +41,7 @@
         except BaseException as exc:
             self.future.set_exception(exc)
             # Break a reference cycle with the exception 'exc'
-            self = None
+            self = None  # type: ignore[assignment]
         else:
             self.future.set_result(result)
 
@@ -35,12 +53,12 @@
     the thread they came from.
     """
 
-    def __init__(self):
+    def __init__(self) -> None:
         self._work_thread = threading.current_thread()
-        self._work_queue = queue.Queue()
+        self._work_queue: queue.Queue[Union[_WorkItem, "Future[Any]"]] = 
queue.Queue()
         self._broken = False
 
-    def run_until_future(self, future):
+    def run_until_future(self, future: "Future[Any]") -> None:
         """
         Runs the code in the work queue until a result is available from the 
future.
         Should be run from the thread the executor is initialised in.
@@ -59,12 +77,18 @@
                 work_item = self._work_queue.get()
                 if work_item is future:
                     return
+                assert isinstance(work_item, _WorkItem)
                 work_item.run()
                 del work_item
         finally:
             self._broken = True
 
-    def submit(self, fn, *args, **kwargs):
+    def _submit(
+        self,
+        fn: Callable[_P, _R],
+        *args: _P.args,
+        **kwargs: _P.kwargs,
+    ) -> "Future[_R]":
         # Check they're not submitting from the same thread
         if threading.current_thread() == self._work_thread:
             raise RuntimeError(
@@ -74,8 +98,18 @@
         if self._broken:
             raise RuntimeError("CurrentThreadExecutor already quit or is 
broken")
         # Add to work queue
-        f = Future()
-        work_item = _WorkItem(f, fn, args, kwargs)
+        f: "Future[_R]" = Future()
+        work_item = _WorkItem(f, fn, *args, **kwargs)
         self._work_queue.put(work_item)
         # Return the future
         return f
+
+    # Python 3.9+ has a new signature for submit with a "/" after `fn`, to 
enforce
+    # it to be a positional argument. If we ignore[override] mypy on 3.9+ will 
be
+    # happy but 3.7/3.8 will say that the ignore comment is unused, even when
+    # defining them differently based on sys.version_info.
+    # We should be able to remove this when we drop support for 3.7/3.8.
+    if not TYPE_CHECKING:
+
+        def submit(self, fn, *args, **kwargs):
+            return self._submit(fn, *args, **kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.6.0/asgiref/sync.py 
new/asgiref-3.7.2/asgiref/sync.py
--- old/asgiref-3.6.0/asgiref/sync.py   2022-12-15 10:04:51.000000000 +0100
+++ new/asgiref-3.7.2/asgiref/sync.py   2023-05-27 19:19:57.000000000 +0200
@@ -9,21 +9,48 @@
 import warnings
 import weakref
 from concurrent.futures import Future, ThreadPoolExecutor
-from typing import Any, Callable, Dict, Optional, overload
+from typing import (
+    TYPE_CHECKING,
+    Any,
+    Awaitable,
+    Callable,
+    Coroutine,
+    Dict,
+    Generic,
+    List,
+    Optional,
+    TypeVar,
+    Union,
+    overload,
+)
 
 from .current_thread_executor import CurrentThreadExecutor
 from .local import Local
 
+if sys.version_info >= (3, 10):
+    from typing import ParamSpec
+else:
+    from typing_extensions import ParamSpec
 
-def _restore_context(context):
+if TYPE_CHECKING:
+    # This is not available to import at runtime
+    from _typeshed import OptExcInfo
+
+_F = TypeVar("_F", bound=Callable[..., Any])
+_P = ParamSpec("_P")
+_R = TypeVar("_R")
+
+
+def _restore_context(context: contextvars.Context) -> None:
     # Check for changes in contextvars, and set them to the current
     # context for downstream consumers
     for cvar in context:
+        cvalue = context.get(cvar)
         try:
-            if cvar.get() != context.get(cvar):
-                cvar.set(context.get(cvar))
+            if cvar.get() != cvalue:
+                cvar.set(cvalue)
         except LookupError:
-            cvar.set(context.get(cvar))
+            cvar.set(cvalue)
 
 
 # Python 3.12 deprecates asyncio.iscoroutinefunction() as an alias for
@@ -32,29 +59,25 @@
 # Until 3.12 is the minimum supported Python version, provide a shim.
 # Django 4.0 only supports 3.8+, so don't concern with the _or_partial 
backport.
 
-# Type hint: should be generic: whatever T it takes it returns. (Same id)
-def markcoroutinefunction(func: Any) -> Any:
-    if hasattr(inspect, "markcoroutinefunction"):
-        return inspect.markcoroutinefunction(func)
-    else:
+if hasattr(inspect, "markcoroutinefunction"):
+    iscoroutinefunction = inspect.iscoroutinefunction
+    markcoroutinefunction: Callable[[_F], _F] = inspect.markcoroutinefunction
+else:
+    iscoroutinefunction = asyncio.iscoroutinefunction  # type: 
ignore[assignment]
+
+    def markcoroutinefunction(func: _F) -> _F:
         func._is_coroutine = asyncio.coroutines._is_coroutine  # type: ignore
         return func
 
 
-def iscoroutinefunction(func: Any) -> bool:
-    if hasattr(inspect, "markcoroutinefunction"):
-        return inspect.iscoroutinefunction(func)
-    else:
-        return asyncio.iscoroutinefunction(func)
-
-
-def _iscoroutinefunction_or_partial(func: Any) -> bool:
-    # Python < 3.8 does not correctly determine partially wrapped
-    # coroutine functions are coroutine functions, hence the need for
-    # this to exist. Code taken from CPython.
-    if sys.version_info >= (3, 8):
-        return iscoroutinefunction(func)
-    else:
+if sys.version_info >= (3, 8):
+    _iscoroutinefunction_or_partial = iscoroutinefunction
+else:
+
+    def _iscoroutinefunction_or_partial(func: Any) -> bool:
+        # Python < 3.8 does not correctly determine partially wrapped
+        # coroutine functions are coroutine functions, hence the need for
+        # this to exist. Code taken from CPython.
         while inspect.ismethod(func):
             func = func.__func__
         while isinstance(func, functools.partial):
@@ -104,7 +127,7 @@
         SyncToAsync.thread_sensitive_context.reset(self.token)
 
 
-class AsyncToSync:
+class AsyncToSync(Generic[_P, _R]):
     """
     Utility class which turns an awaitable that only works on the thread with
     the event loop into a synchronous callable that works in a subthread.
@@ -128,7 +151,14 @@
     # inside create_task, we'll look it up here from the running event loop.
     loop_thread_executors: "Dict[asyncio.AbstractEventLoop, 
CurrentThreadExecutor]" = {}
 
-    def __init__(self, awaitable, force_new_loop=False):
+    def __init__(
+        self,
+        awaitable: Union[
+            Callable[_P, Coroutine[Any, Any, _R]],
+            Callable[_P, Awaitable[_R]],
+        ],
+        force_new_loop: bool = False,
+    ):
         if not callable(awaitable) or (
             not _iscoroutinefunction_or_partial(awaitable)
             and not _iscoroutinefunction_or_partial(
@@ -142,7 +172,7 @@
             )
         self.awaitable = awaitable
         try:
-            self.__self__ = self.awaitable.__self__
+            self.__self__ = self.awaitable.__self__  # type: ignore[union-attr]
         except AttributeError:
             pass
         if force_new_loop:
@@ -166,7 +196,9 @@
                 else:
                     self.main_event_loop = None
 
-    def __call__(self, *args, **kwargs):
+    def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> _R:
+        __traceback_hide__ = True  # noqa: F841
+
         # You can't call AsyncToSync from a thread with a running event loop
         try:
             event_loop = asyncio.get_running_loop()
@@ -184,7 +216,7 @@
         context = [contextvars.copy_context()]
 
         # Make a future for the return information
-        call_result = Future()
+        call_result: "Future[_R]" = Future()
         # Get the source thread
         source_thread = threading.current_thread()
         # Make a CurrentThreadExecutor we'll use to idle in this thread - we
@@ -202,7 +234,12 @@
         # in this thread.
         try:
             awaitable = self.main_wrap(
-                args, kwargs, call_result, source_thread, sys.exc_info(), 
context
+                call_result,
+                source_thread,
+                sys.exc_info(),
+                context,
+                *args,
+                **kwargs,
             )
 
             if not (self.main_event_loop and 
self.main_event_loop.is_running()):
@@ -275,7 +312,7 @@
                 loop.close()
                 asyncio.set_event_loop(self.main_event_loop)
 
-    def __get__(self, parent, objtype):
+    def __get__(self, parent: Any, objtype: Any) -> Callable[_P, _R]:
         """
         Include self for methods
         """
@@ -283,16 +320,26 @@
         return functools.update_wrapper(func, self.awaitable)
 
     async def main_wrap(
-        self, args, kwargs, call_result, source_thread, exc_info, context
-    ):
+        self,
+        call_result: "Future[_R]",
+        source_thread: threading.Thread,
+        exc_info: "OptExcInfo",
+        context: List[contextvars.Context],
+        *args: _P.args,
+        **kwargs: _P.kwargs,
+    ) -> None:
         """
         Wraps the awaitable with something that puts the result into the
         result/exception future.
         """
+
+        __traceback_hide__ = True  # noqa: F841
+
         if context is not None:
             _restore_context(context[0])
 
         current_task = SyncToAsync.get_current_task()
+        assert current_task is not None
         self.launch_map[current_task] = source_thread
         try:
             # If we have an exception, run the function inside the except block
@@ -314,7 +361,7 @@
             context[0] = contextvars.copy_context()
 
 
-class SyncToAsync:
+class SyncToAsync(Generic[_P, _R]):
     """
     Utility class which turns a synchronous callable into an awaitable that
     runs in a threadpool. It also sets a threadlocal inside the thread so
@@ -347,8 +394,8 @@
 
     # Maintain a contextvar for the current execution context. Optionally used
     # for thread sensitive mode.
-    thread_sensitive_context: "contextvars.ContextVar[str]" = 
contextvars.ContextVar(
-        "thread_sensitive_context"
+    thread_sensitive_context: "contextvars.ContextVar[ThreadSensitiveContext]" 
= (
+        contextvars.ContextVar("thread_sensitive_context")
     )
 
     # Contextvar that is used to detect if the single thread executor
@@ -359,13 +406,13 @@
 
     # Maintaining a weak reference to the context ensures that thread pools are
     # erased once the context goes out of scope. This terminates the thread 
pool.
-    context_to_thread_executor: "weakref.WeakKeyDictionary[object, 
ThreadPoolExecutor]" = (
+    context_to_thread_executor: 
"weakref.WeakKeyDictionary[ThreadSensitiveContext, ThreadPoolExecutor]" = (
         weakref.WeakKeyDictionary()
     )
 
     def __init__(
         self,
-        func: Callable[..., Any],
+        func: Callable[_P, _R],
         thread_sensitive: bool = True,
         executor: Optional["ThreadPoolExecutor"] = None,
     ) -> None:
@@ -387,7 +434,8 @@
         except AttributeError:
             pass
 
-    async def __call__(self, *args, **kwargs):
+    async def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> _R:
+        __traceback_hide__ = True  # noqa: F841
         loop = asyncio.get_running_loop()
 
         # Work out what thread to run the code in
@@ -395,9 +443,7 @@
             if hasattr(AsyncToSync.executors, "current"):
                 # If we have a parent sync thread above somewhere, use that
                 executor = AsyncToSync.executors.current
-            elif self.thread_sensitive_context and 
self.thread_sensitive_context.get(
-                None
-            ):
+            elif self.thread_sensitive_context.get(None):
                 # If we have a way of retrieving the current context, attempt
                 # to use a per-context thread pool executor
                 thread_sensitive_context = self.thread_sensitive_context.get()
@@ -412,15 +458,14 @@
             elif loop in AsyncToSync.loop_thread_executors:
                 # Re-use thread executor for running loop
                 executor = AsyncToSync.loop_thread_executors[loop]
-            elif self.deadlock_context and self.deadlock_context.get(False):
+            elif self.deadlock_context.get(False):
                 raise RuntimeError(
                     "Single thread executor already being used, would deadlock"
                 )
             else:
                 # Otherwise, we run it in a fixed single thread
                 executor = self.single_thread_executor
-                if self.deadlock_context:
-                    self.deadlock_context.set(True)
+                self.deadlock_context.set(True)
         else:
             # Use the passed in executor, or the loop's default if it is None
             executor = self._executor
@@ -428,12 +473,10 @@
         context = contextvars.copy_context()
         child = functools.partial(self.func, *args, **kwargs)
         func = context.run
-        args = (child,)
-        kwargs = {}
 
         try:
             # Run the code in the right thread
-            future = loop.run_in_executor(
+            ret: _R = await loop.run_in_executor(
                 executor,
                 functools.partial(
                     self.thread_handler,
@@ -441,20 +484,19 @@
                     self.get_current_task(),
                     sys.exc_info(),
                     func,
-                    *args,
-                    **kwargs,
+                    child,
                 ),
             )
-            ret = await asyncio.wait_for(future, timeout=None)
 
         finally:
             _restore_context(context)
-            if self.deadlock_context:
-                self.deadlock_context.set(False)
+            self.deadlock_context.set(False)
 
         return ret
 
-    def __get__(self, parent, objtype):
+    def __get__(
+        self, parent: Any, objtype: Any
+    ) -> Callable[_P, Coroutine[Any, Any, _R]]:
         """
         Include self for methods
         """
@@ -465,6 +507,9 @@
         """
         Wraps the sync application with exception handling.
         """
+
+        __traceback_hide__ = True  # noqa: F841
+
         # Set the threadlocal for AsyncToSync
         self.threadlocal.main_event_loop = loop
         self.threadlocal.main_event_loop_pid = os.getpid()
@@ -477,6 +522,9 @@
         else:
             self.launch_map[current_thread] = source_task
             parent_set = True
+        source_task = (
+            None  # allow the task to be garbage-collected in case of 
exceptions
+        )
         # Run the function
         try:
             # If we have an exception, run the function inside the except block
@@ -495,7 +543,7 @@
                 del self.launch_map[current_thread]
 
     @staticmethod
-    def get_current_task():
+    def get_current_task() -> Optional["asyncio.Task[Any]"]:
         """
         Implementation of asyncio.current_task()
         that returns None if there is no task.
@@ -506,33 +554,84 @@
             return None
 
 
-# Lowercase aliases (and decorator friendliness)
-async_to_sync = AsyncToSync
+@overload
+def async_to_sync(
+    *,
+    force_new_loop: bool = False,
+) -> Callable[
+    [Union[Callable[_P, Coroutine[Any, Any, _R]], Callable[_P, 
Awaitable[_R]]]],
+    Callable[_P, _R],
+]:
+    ...
+
+
+@overload
+def async_to_sync(
+    awaitable: Union[
+        Callable[_P, Coroutine[Any, Any, _R]],
+        Callable[_P, Awaitable[_R]],
+    ],
+    *,
+    force_new_loop: bool = False,
+) -> Callable[_P, _R]:
+    ...
+
+
+def async_to_sync(
+    awaitable: Optional[
+        Union[
+            Callable[_P, Coroutine[Any, Any, _R]],
+            Callable[_P, Awaitable[_R]],
+        ]
+    ] = None,
+    *,
+    force_new_loop: bool = False,
+) -> Union[
+    Callable[
+        [Union[Callable[_P, Coroutine[Any, Any, _R]], Callable[_P, 
Awaitable[_R]]]],
+        Callable[_P, _R],
+    ],
+    Callable[_P, _R],
+]:
+    if awaitable is None:
+        return lambda f: AsyncToSync(
+            f,
+            force_new_loop=force_new_loop,
+        )
+    return AsyncToSync(
+        awaitable,
+        force_new_loop=force_new_loop,
+    )
 
 
 @overload
 def sync_to_async(
-    func: None = None,
+    *,
     thread_sensitive: bool = True,
     executor: Optional["ThreadPoolExecutor"] = None,
-) -> Callable[[Callable[..., Any]], SyncToAsync]:
+) -> Callable[[Callable[_P, _R]], Callable[_P, Coroutine[Any, Any, _R]]]:
     ...
 
 
 @overload
 def sync_to_async(
-    func: Callable[..., Any],
+    func: Callable[_P, _R],
+    *,
     thread_sensitive: bool = True,
     executor: Optional["ThreadPoolExecutor"] = None,
-) -> SyncToAsync:
+) -> Callable[_P, Coroutine[Any, Any, _R]]:
     ...
 
 
 def sync_to_async(
-    func=None,
-    thread_sensitive=True,
-    executor=None,
-):
+    func: Optional[Callable[_P, _R]] = None,
+    *,
+    thread_sensitive: bool = True,
+    executor: Optional["ThreadPoolExecutor"] = None,
+) -> Union[
+    Callable[[Callable[_P, _R]], Callable[_P, Coroutine[Any, Any, _R]]],
+    Callable[_P, Coroutine[Any, Any, _R]],
+]:
     if func is None:
         return lambda f: SyncToAsync(
             f,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.6.0/asgiref/typing.py 
new/asgiref-3.7.2/asgiref/typing.py
--- old/asgiref-3.6.0/asgiref/typing.py 2022-12-15 10:04:51.000000000 +0100
+++ new/asgiref-3.7.2/asgiref/typing.py 2023-05-23 18:35:51.000000000 +0200
@@ -1,11 +1,26 @@
 import sys
-from typing import Awaitable, Callable, Dict, Iterable, Optional, Tuple, Type, 
Union
+from typing import (
+    Any,
+    Awaitable,
+    Callable,
+    Dict,
+    Iterable,
+    Optional,
+    Tuple,
+    Type,
+    Union,
+)
 
 if sys.version_info >= (3, 8):
     from typing import Literal, Protocol, TypedDict
 else:
     from typing_extensions import Literal, Protocol, TypedDict
 
+if sys.version_info >= (3, 11):
+    from typing import NotRequired
+else:
+    from typing_extensions import NotRequired
+
 __all__ = (
     "ASGIVersions",
     "HTTPScope",
@@ -62,6 +77,7 @@
     headers: Iterable[Tuple[bytes, bytes]]
     client: Optional[Tuple[str, int]]
     server: Optional[Tuple[str, Optional[int]]]
+    state: NotRequired[Dict[str, Any]]
     extensions: Optional[Dict[str, Dict[object, object]]]
 
 
@@ -78,12 +94,14 @@
     client: Optional[Tuple[str, int]]
     server: Optional[Tuple[str, Optional[int]]]
     subprotocols: Iterable[str]
+    state: NotRequired[Dict[str, Any]]
     extensions: Optional[Dict[str, Dict[object, object]]]
 
 
 class LifespanScope(TypedDict):
     type: Literal["lifespan"]
     asgi: ASGIVersions
+    state: NotRequired[Dict[str, Any]]
 
 
 WWWScope = Union[HTTPScope, WebSocketScope]
@@ -96,6 +114,11 @@
     more_body: bool
 
 
+class HTTPResponseDebugEvent(TypedDict):
+    type: Literal["http.response.debug"]
+    info: Dict[str, object]
+
+
 class HTTPResponseStartEvent(TypedDict):
     type: Literal["http.response.start"]
     status: int
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.6.0/asgiref.egg-info/PKG-INFO 
new/asgiref-3.7.2/asgiref.egg-info/PKG-INFO
--- old/asgiref-3.6.0/asgiref.egg-info/PKG-INFO 2022-12-20 10:06:25.000000000 
+0100
+++ new/asgiref-3.7.2/asgiref.egg-info/PKG-INFO 2023-05-27 19:21:19.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: asgiref
-Version: 3.6.0
+Version: 3.7.2
 Summary: ASGI specs, helper code, and adapters
 Home-page: https://github.com/django/asgiref/
 Author: Django Software Foundation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.6.0/asgiref.egg-info/requires.txt 
new/asgiref-3.7.2/asgiref.egg-info/requires.txt
--- old/asgiref-3.6.0/asgiref.egg-info/requires.txt     2022-12-20 
10:06:25.000000000 +0100
+++ new/asgiref-3.7.2/asgiref.egg-info/requires.txt     2023-05-27 
19:21:19.000000000 +0200
@@ -1,6 +1,6 @@
 
-[:python_version < "3.8"]
-typing_extensions
+[:python_version < "3.11"]
+typing_extensions>=4
 
 [tests]
 pytest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.6.0/setup.cfg new/asgiref-3.7.2/setup.cfg
--- old/asgiref-3.6.0/setup.cfg 2022-12-20 10:06:25.459771600 +0100
+++ new/asgiref-3.7.2/setup.cfg 2023-05-27 19:21:19.747680700 +0200
@@ -32,7 +32,7 @@
 packages = find:
 include_package_data = true
 install_requires = 
-       typing_extensions; python_version < "3.8"
+       typing_extensions>=4; python_version < "3.11"
 zip_safe = false
 
 [options.extras_require]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.6.0/tests/test_sync_contextvars.py 
new/asgiref-3.7.2/tests/test_sync_contextvars.py
--- old/asgiref-3.6.0/tests/test_sync_contextvars.py    2022-07-06 
16:22:11.000000000 +0200
+++ new/asgiref-3.7.2/tests/test_sync_contextvars.py    2023-05-23 
18:35:51.000000000 +0200
@@ -1,4 +1,5 @@
 import asyncio
+import contextvars
 import threading
 import time
 
@@ -6,9 +7,7 @@
 
 from asgiref.sync import ThreadSensitiveContext, async_to_sync, sync_to_async
 
-contextvars = pytest.importorskip("contextvars")
-
-foo = contextvars.ContextVar("foo")
+foo: "contextvars.ContextVar[str]" = contextvars.ContextVar("foo")
 
 
 @pytest.mark.asyncio

Reply via email to