Hello community,

here is the log from the commit of package python-asgiref for openSUSE:Factory 
checked in at 2020-07-02 23:54:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-asgiref (Old)
 and      /work/SRC/openSUSE:Factory/.python-asgiref.new.3060 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-asgiref"

Thu Jul  2 23:54:44 2020 rev:2 rq:817963 version:3.2.10

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-asgiref/python-asgiref.changes    
2020-04-25 20:34:37.830802287 +0200
+++ /work/SRC/openSUSE:Factory/.python-asgiref.new.3060/python-asgiref.changes  
2020-07-02 23:54:49.800572868 +0200
@@ -1,0 +2,10 @@
+Wed Jul  1 04:59:38 UTC 2020 - Steve Kowalik <steven.kowa...@suse.com>
+
+- Update to 3.2.10:
+  * Fixed bugs due to bad WeakRef handling introduced in 3.2.8
+  * Fixed regression with exception handling in 3.2.8 related to the
+    contextvars fix.
+  * Fixed small memory leak in local.Local
+  * contextvars are now persisted through AsyncToSync 
+
+-------------------------------------------------------------------

Old:
----
  asgiref-3.2.7.tar.gz

New:
----
  asgiref-3.2.10.tar.gz

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

Other differences:
------------------
++++++ python-asgiref.spec ++++++
--- /var/tmp/diff_new_pack.KrYhBi/_old  2020-07-02 23:54:50.480575122 +0200
+++ /var/tmp/diff_new_pack.KrYhBi/_new  2020-07-02 23:54:50.484575135 +0200
@@ -19,7 +19,7 @@
 %define skip_python2 1
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-asgiref
-Version:        3.2.7
+Version:        3.2.10
 Release:        0
 Summary:        ASGI specs, helper code, and adapters
 License:        BSD-3-Clause

++++++ asgiref-3.2.7.tar.gz -> asgiref-3.2.10.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.2.7/PKG-INFO new/asgiref-3.2.10/PKG-INFO
--- old/asgiref-3.2.7/PKG-INFO  2020-03-24 18:57:19.607391400 +0100
+++ new/asgiref-3.2.10/PKG-INFO 2020-06-18 20:49:06.533756500 +0200
@@ -1,11 +1,14 @@
 Metadata-Version: 2.1
 Name: asgiref
-Version: 3.2.7
+Version: 3.2.10
 Summary: ASGI specs, helper code, and adapters
-Home-page: http://github.com/django/asgiref/
+Home-page: https://github.com/django/asgiref/
 Author: Django Software Foundation
 Author-email: foundat...@djangoproject.com
 License: BSD
+Project-URL: Documentation, https://asgi.readthedocs.io/
+Project-URL: Further Documentation, 
https://docs.djangoproject.com/en/stable/topics/async/#async-adapter-functions
+Project-URL: Changelog, 
https://github.com/django/asgiref/blob/master/CHANGELOG.txt
 Description: asgiref
         =======
         
@@ -212,11 +215,11 @@
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Topic :: Internet :: WWW/HTTP
 Requires-Python: >=3.5
-Description-Content-Type: text/x-rst
 Provides-Extra: tests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.2.7/asgiref/__init__.py 
new/asgiref-3.2.10/asgiref/__init__.py
--- old/asgiref-3.2.7/asgiref/__init__.py       2020-03-24 18:57:04.000000000 
+0100
+++ new/asgiref-3.2.10/asgiref/__init__.py      2020-06-18 20:48:49.000000000 
+0200
@@ -1 +1 @@
-__version__ = "3.2.7"
+__version__ = "3.2.10"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.2.7/asgiref/local.py 
new/asgiref-3.2.10/asgiref/local.py
--- old/asgiref-3.2.7/asgiref/local.py  2020-03-24 18:57:04.000000000 +0100
+++ new/asgiref-3.2.10/asgiref/local.py 2020-06-18 20:48:49.000000000 +0200
@@ -35,7 +35,7 @@
     def __init__(self, thread_critical=False):
         self._thread_critical = thread_critical
         self._thread_lock = threading.RLock()
-        self._context_refs = []
+        self._context_refs = weakref.WeakSet()
         # Random suffixes stop accidental reuse between different Locals,
         # though we try to force deletion as well.
         self._attr_name = "_asgiref_local_impl_%s_%s" % (
@@ -83,17 +83,20 @@
         context_obj = self._get_context_id()
         if not hasattr(context_obj, self._attr_name):
             setattr(context_obj, self._attr_name, {})
-            self._context_refs.append(weakref.ref(context_obj))
+            self._context_refs.add(context_obj)
         return getattr(context_obj, self._attr_name)
 
     def __del__(self):
-        for ref in self._context_refs:
-            context_obj = ref()
-            if context_obj:
+        try:
+            for context_obj in self._context_refs:
                 try:
                     delattr(context_obj, self._attr_name)
                 except AttributeError:
                     pass
+        except TypeError:
+            # WeakSet.__iter__ can crash when interpreter is shutting down due
+            # to _IterationGuard being None.
+            pass
 
     def __getattr__(self, key):
         with self._thread_lock:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.2.7/asgiref/sync.py 
new/asgiref-3.2.10/asgiref/sync.py
--- old/asgiref-3.2.7/asgiref/sync.py   2020-03-24 18:57:04.000000000 +0100
+++ new/asgiref-3.2.10/asgiref/sync.py  2020-06-18 20:48:49.000000000 +0200
@@ -15,6 +15,17 @@
     contextvars = None
 
 
+def _restore_context(context):
+    # Check for changes in contextvars, and set them to the current
+    # context for downstream consumers
+    for cvar in context:
+        try:
+            if cvar.get() != context.get(cvar):
+                cvar.set(context.get(cvar))
+        except LookupError:
+            cvar.set(context.get(cvar))
+
+
 class AsyncToSync:
     """
     Utility class which turns an awaitable that only works on the thread with
@@ -66,6 +77,14 @@
                     "You cannot use AsyncToSync in the same thread as an async 
event loop - "
                     "just await the async function directly."
                 )
+
+        if contextvars is not None:
+            # Wrapping context in list so it can be reassigned from within
+            # `main_wrap`.
+            context = [contextvars.copy_context()]
+        else:
+            context = None
+
         # Make a future for the return information
         call_result = Future()
         # Get the source thread
@@ -83,16 +102,16 @@
         # main event loop's thread if it's there, otherwise make a new loop
         # in this thread.
         try:
+            awaitable = self.main_wrap(
+                args, kwargs, call_result, source_thread, sys.exc_info(), 
context
+            )
+
             if not (self.main_event_loop and 
self.main_event_loop.is_running()):
                 # Make our own event loop - in a new thread - and run inside 
that.
                 loop = asyncio.new_event_loop()
                 loop_executor = ThreadPoolExecutor(max_workers=1)
                 loop_future = loop_executor.submit(
-                    self._run_event_loop,
-                    loop,
-                    self.main_wrap(
-                        args, kwargs, call_result, source_thread, 
sys.exc_info()
-                    ),
+                    self._run_event_loop, loop, awaitable
                 )
                 if current_executor:
                     # Run the CurrentThreadExecutor until the future is done
@@ -102,10 +121,7 @@
             else:
                 # Call it inside the existing loop
                 self.main_event_loop.call_soon_threadsafe(
-                    self.main_event_loop.create_task,
-                    self.main_wrap(
-                        args, kwargs, call_result, source_thread, 
sys.exc_info()
-                    ),
+                    self.main_event_loop.create_task, awaitable
                 )
                 if current_executor:
                     # Run the CurrentThreadExecutor until the future is done
@@ -116,6 +132,9 @@
                 del self.executors.current
             if old_current_executor:
                 self.executors.current = old_current_executor
+            if contextvars is not None:
+                _restore_context(context[0])
+
         # Wait for results from the future.
         return call_result.result()
 
@@ -161,11 +180,16 @@
         func = functools.partial(self.__call__, parent)
         return functools.update_wrapper(func, self.awaitable)
 
-    async def main_wrap(self, args, kwargs, call_result, source_thread, 
exc_info):
+    async def main_wrap(
+        self, args, kwargs, call_result, source_thread, exc_info, context
+    ):
         """
         Wraps the awaitable with something that puts the result into the
         result/exception future.
         """
+        if context is not None:
+            _restore_context(context[0])
+
         current_task = SyncToAsync.get_current_task()
         self.launch_map[current_task] = source_thread
         try:
@@ -185,6 +209,9 @@
         finally:
             del self.launch_map[current_task]
 
+            if context is not None:
+                context[0] = contextvars.copy_context()
+
 
 class SyncToAsync:
     """
@@ -269,14 +296,7 @@
         ret = await asyncio.wait_for(future, timeout=None)
 
         if contextvars is not None:
-            # Check for changes in contextvars, and set them to the current
-            # context for downstream consumers
-            for cvar in context:
-                try:
-                    if cvar.get() != context.get(cvar):
-                        cvar.set(context.get(cvar))
-                except LookupError:
-                    cvar.set(context.get(cvar))
+            _restore_context(context)
 
         return ret
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.2.7/asgiref.egg-info/PKG-INFO 
new/asgiref-3.2.10/asgiref.egg-info/PKG-INFO
--- old/asgiref-3.2.7/asgiref.egg-info/PKG-INFO 2020-03-24 18:57:19.000000000 
+0100
+++ new/asgiref-3.2.10/asgiref.egg-info/PKG-INFO        2020-06-18 
20:49:06.000000000 +0200
@@ -1,11 +1,14 @@
 Metadata-Version: 2.1
 Name: asgiref
-Version: 3.2.7
+Version: 3.2.10
 Summary: ASGI specs, helper code, and adapters
-Home-page: http://github.com/django/asgiref/
+Home-page: https://github.com/django/asgiref/
 Author: Django Software Foundation
 Author-email: foundat...@djangoproject.com
 License: BSD
+Project-URL: Documentation, https://asgi.readthedocs.io/
+Project-URL: Further Documentation, 
https://docs.djangoproject.com/en/stable/topics/async/#async-adapter-functions
+Project-URL: Changelog, 
https://github.com/django/asgiref/blob/master/CHANGELOG.txt
 Description: asgiref
         =======
         
@@ -212,11 +215,11 @@
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Topic :: Internet :: WWW/HTTP
 Requires-Python: >=3.5
-Description-Content-Type: text/x-rst
 Provides-Extra: tests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.2.7/asgiref.egg-info/requires.txt 
new/asgiref-3.2.10/asgiref.egg-info/requires.txt
--- old/asgiref-3.2.7/asgiref.egg-info/requires.txt     2020-03-24 
18:57:19.000000000 +0100
+++ new/asgiref-3.2.10/asgiref.egg-info/requires.txt    2020-06-18 
20:49:06.000000000 +0200
@@ -1,4 +1,4 @@
 
 [tests]
-pytest~=4.3.0
-pytest-asyncio~=0.10.0
+pytest
+pytest-asyncio
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.2.7/setup.cfg new/asgiref-3.2.10/setup.cfg
--- old/asgiref-3.2.7/setup.cfg 2020-03-24 18:57:19.607391400 +0100
+++ new/asgiref-3.2.10/setup.cfg        2020-06-18 20:49:06.537758600 +0200
@@ -1,5 +1,41 @@
-[bdist_wheel]
-universal = 1
+[metadata]
+name = asgiref
+version = attr: asgiref.__version__
+url = https://github.com/django/asgiref/
+author = Django Software Foundation
+author_email = foundat...@djangoproject.com
+description = ASGI specs, helper code, and adapters
+long_description = file: README.rst
+license = BSD
+classifiers = 
+       Development Status :: 5 - Production/Stable
+       Environment :: Web Environment
+       Intended Audience :: Developers
+       License :: OSI Approved :: BSD License
+       Operating System :: OS Independent
+       Programming Language :: Python
+       Programming Language :: Python :: 3
+       Programming Language :: Python :: 3 :: Only
+       Programming Language :: Python :: 3.5
+       Programming Language :: Python :: 3.6
+       Programming Language :: Python :: 3.7
+       Programming Language :: Python :: 3.8
+       Topic :: Internet :: WWW/HTTP
+project_urls = 
+       Documentation = https://asgi.readthedocs.io/
+       Further Documentation = 
https://docs.djangoproject.com/en/stable/topics/async/#async-adapter-functions
+       Changelog = https://github.com/django/asgiref/blob/master/CHANGELOG.txt
+
+[options]
+python_requires = >=3.5
+packages = find:
+include_package_data = true
+zip_safe = false
+
+[options.extras_require]
+tests = 
+       pytest
+       pytest-asyncio
 
 [tool:pytest]
 testpaths = tests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.2.7/setup.py new/asgiref-3.2.10/setup.py
--- old/asgiref-3.2.7/setup.py  2020-03-24 18:57:04.000000000 +0100
+++ new/asgiref-3.2.10/setup.py 2020-06-18 20:48:49.000000000 +0200
@@ -1,44 +1,3 @@
-import os
-from setuptools import find_packages, setup
-from asgiref import __version__
+from setuptools import setup
 
-
-# We use the README as the long_description
-readme_path = os.path.join(os.path.dirname(__file__), "README.rst")
-
-
-setup(
-    name='asgiref',
-    version=__version__,
-    url='http://github.com/django/asgiref/',
-    author='Django Software Foundation',
-    author_email='foundat...@djangoproject.com',
-    description='ASGI specs, helper code, and adapters',
-    long_description=open(readme_path).read(),
-    long_description_content_type='text/x-rst',
-    license='BSD',
-    zip_safe=False,
-    packages=find_packages(exclude=['tests']),
-    include_package_data=True,
-    python_requires=">=3.5",
-    extras_require={
-        "tests": [
-            "pytest~=4.3.0",
-            "pytest-asyncio~=0.10.0",
-        ],
-    },
-    classifiers=[
-        'Development Status :: 5 - Production/Stable',
-        'Environment :: Web Environment',
-        'Intended Audience :: Developers',
-        'License :: OSI Approved :: BSD License',
-        'Operating System :: OS Independent',
-        'Programming Language :: Python',
-        'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.5',
-        'Programming Language :: Python :: 3.6',
-        'Programming Language :: Python :: 3.7',
-        'Programming Language :: Python :: 3.8',
-        'Topic :: Internet :: WWW/HTTP',
-    ],
-)
+setup(name='asgiref')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.2.7/tests/test_local.py 
new/asgiref-3.2.10/tests/test_local.py
--- old/asgiref-3.2.7/tests/test_local.py       2020-03-24 18:57:04.000000000 
+0100
+++ new/asgiref-3.2.10/tests/test_local.py      2020-06-18 20:48:49.000000000 
+0200
@@ -298,3 +298,20 @@
 
     await sync_to_async(sync_function)(5)
     assert test_local.counter == 6
+
+
+def test_local_del_swallows_type_error(monkeypatch):
+    test_local = Local()
+
+    blow_up_calls = 0
+
+    def blow_up(self):
+        nonlocal blow_up_calls
+        blow_up_calls += 1
+        raise TypeError()
+
+    monkeypatch.setattr("weakref.WeakSet.__iter__", blow_up)
+
+    test_local.__del__()
+
+    assert blow_up_calls == 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asgiref-3.2.7/tests/test_sync_contextvars.py 
new/asgiref-3.2.10/tests/test_sync_contextvars.py
--- old/asgiref-3.2.7/tests/test_sync_contextvars.py    2020-03-24 
18:57:04.000000000 +0100
+++ new/asgiref-3.2.10/tests/test_sync_contextvars.py   2020-06-18 
20:48:49.000000000 +0200
@@ -1,8 +1,9 @@
+import asyncio
 import time
 
 import pytest
 
-from asgiref.sync import sync_to_async
+from asgiref.sync import async_to_sync, sync_to_async
 
 contextvars = pytest.importorskip("contextvars")
 
@@ -27,5 +28,26 @@
     # Wrap it
     foo.set("bar")
     async_function = sync_to_async(sync_function)
-    await async_function()
+    assert await async_function() == 42
+    assert foo.get() == "baz"
+
+
+def test_async_to_sync_contextvars():
+    """
+    Tests to make sure that contextvars from the calling context are
+    present in the called context, and that any changes in the called context
+    are then propagated back to the calling context.
+    """
+    # Define sync function
+    async def async_function():
+        await asyncio.sleep(1)
+        assert foo.get() == "bar"
+        foo.set("baz")
+        return 42
+
+    # Ensure outermost detection works
+    # Wrap it
+    foo.set("bar")
+    sync_function = async_to_sync(async_function)
+    assert sync_function() == 42
     assert foo.get() == "baz"


Reply via email to