From d55f2dcee17da5946425803202be6ff8a7b8aa52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 25 Feb 2022 15:09:32 +0100 Subject: [PATCH] Compatibility with Blender 3.1 / Python 3.10 Blender 3.1 will be shipped with Python 3.10, which made some backward- incompatible changes in its asyncio module (the removal of the `loop` parameter from various functions). Depending on which Python version is used in Blender, the add-on now passes (or not) the `loop` parameter, retaining backward compatibility. --- CHANGELOG.md | 5 +++++ blender_cloud/async_loop.py | 5 ++++- blender_cloud/pillar.py | 20 ++++++++++++++------ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70a94bb..563ba33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Blender Cloud changelog +## Version 1.25 (in development) + +- Compatibility with Blender 3.1 (Python 3.10). + + ## Version 1.24 (2022-02-04) - Bump blender-asset-tracer version 1.8 → 1.10, for fixing a bug where files were doubly-compressed. diff --git a/blender_cloud/async_loop.py b/blender_cloud/async_loop.py index 7ad1ee9..4f3b496 100644 --- a/blender_cloud/async_loop.py +++ b/blender_cloud/async_loop.py @@ -56,8 +56,11 @@ def setup_asyncio_executor(): from . import pillar + # Python 3.8 deprecated the 'loop' parameter, 3.10 removed it. + kwargs = {"loop": loop} if sys.version_info < (3, 8) else {} + # No more than this many Pillar calls should be made simultaneously - pillar.pillar_semaphore = asyncio.Semaphore(3, loop=loop) + pillar.pillar_semaphore = asyncio.Semaphore(3, **kwargs) def kick_async_loop(*args) -> bool: diff --git a/blender_cloud/pillar.py b/blender_cloud/pillar.py index 4b8a437..197ba29 100755 --- a/blender_cloud/pillar.py +++ b/blender_cloud/pillar.py @@ -25,6 +25,7 @@ import logging from contextlib import closing, contextmanager import urllib.parse import pathlib +import sys import requests.adapters import requests.packages.urllib3.util.retry @@ -261,14 +262,17 @@ async def pillar_call(pillar_func, *args, caching=True, **kwargs): ) loop = asyncio.get_event_loop() + # Python 3.8 deprecated the 'loop' parameter, 3.10 removed it. + kwargs = {"loop": loop} if sys.version_info < (3, 8) else {} + # Use explicit calls to acquire() and release() so that we have more control over # how long we wait and how we handle timeouts. try: - await asyncio.wait_for(pillar_semaphore.acquire(), timeout=10, loop=loop) + await asyncio.wait_for(pillar_semaphore.acquire(), timeout=10, **kwargs) except asyncio.TimeoutError: log.info("Waiting for semaphore to call %s", pillar_func.__name__) try: - await asyncio.wait_for(pillar_semaphore.acquire(), timeout=50, loop=loop) + await asyncio.wait_for(pillar_semaphore.acquire(), timeout=50, **kwargs) except asyncio.TimeoutError: raise RuntimeError("Timeout waiting for Pillar Semaphore!") @@ -648,9 +652,11 @@ async def fetch_texture_thumbs( for texture_node in texture_nodes ) + # Python 3.8 deprecated the 'loop' parameter, 3.10 removed it. + kwargs = {"loop": asyncio.get_event_loop()} if sys.version_info < (3, 8) else {} + # raises any exception from failed handle_texture_node() calls. - loop = asyncio.get_event_loop() - await asyncio.gather(*coros, loop=loop) + await asyncio.gather(*coros, **kwargs) log.info("fetch_texture_thumbs: Done downloading texture thumbnails") @@ -929,8 +935,10 @@ async def download_texture( ) downloaders.append(dlr) - loop = asyncio.get_event_loop() - return await asyncio.gather(*downloaders, return_exceptions=True, loop=loop) + # Python 3.8 deprecated the 'loop' parameter, 3.10 removed it. + kwargs = {"loop": asyncio.get_event_loop()} if sys.version_info < (3, 8) else {} + + return await asyncio.gather(*downloaders, return_exceptions=True, **kwargs) async def upload_file(