From 59d83380e141a0c17b2c5da6acf45ccd2361a386 Mon Sep 17 00:00:00 2001 From: ptiurin Date: Fri, 19 Sep 2025 09:32:12 +0100 Subject: [PATCH 1/3] build(FIR-38687): Relax anyio version requirements --- .github/workflows/unit-tests.yml | 2 +- setup.cfg | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 12e1c15fe1f..c988a76f4dc 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -35,7 +35,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -e ".[dev]" + pip install -e ".[unit-tests]" - name: Run unit tests run: | diff --git a/setup.cfg b/setup.cfg index 64bcfd4547f..59df2f2b637 100755 --- a/setup.cfg +++ b/setup.cfg @@ -25,7 +25,7 @@ project_urls = packages = find: install_requires = aiorwlock==1.1.0 - anyio>=3.7.1,<4.5.0 + anyio>=3.7.1 appdirs>=1.4.4 appdirs-stubs>=0.1.0 async-generator>=1.10 @@ -69,6 +69,9 @@ dev = docs = sphinx==7.* sphinx-rtd-theme==2.* +unit_tests = + anyio>=3.7.1,<4.5.0 + firebolt-sdk[dev] [options.package_data] firebolt = py.typed From a813b195f0792cb39bd1ffc2f6a62b9498519dce Mon Sep 17 00:00:00 2001 From: ptiurin Date: Fri, 19 Sep 2025 10:15:16 +0100 Subject: [PATCH 2/3] Fix the issue instead --- .github/workflows/unit-tests.yml | 2 +- setup.cfg | 3 --- src/firebolt/client/auth/base.py | 19 ++++++++++++------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index c988a76f4dc..12e1c15fe1f 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -35,7 +35,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -e ".[unit-tests]" + pip install -e ".[dev]" - name: Run unit tests run: | diff --git a/setup.cfg b/setup.cfg index 59df2f2b637..b6425b6e83f 100755 --- a/setup.cfg +++ b/setup.cfg @@ -69,9 +69,6 @@ dev = docs = sphinx==7.* sphinx-rtd-theme==2.* -unit_tests = - anyio>=3.7.1,<4.5.0 - firebolt-sdk[dev] [options.package_data] firebolt = py.typed diff --git a/src/firebolt/client/auth/base.py b/src/firebolt/client/auth/base.py index 56af8026eb7..3a8a493bf0e 100644 --- a/src/firebolt/client/auth/base.py +++ b/src/firebolt/client/auth/base.py @@ -1,15 +1,18 @@ +import logging from abc import abstractmethod from enum import IntEnum from time import time from typing import AsyncGenerator, Generator, Optional -from anyio import Lock, get_current_task +from anyio import Lock from httpx import Auth as HttpxAuth from httpx import Request, Response, codes from firebolt.utils.token_storage import TokenSecureStorage from firebolt.utils.util import Timer, cached_property, get_internal_error_code +logger = logging.getLogger(__name__) + class FireboltAuthVersion(IntEnum): """Enum for Firebolt authentication versions.""" @@ -199,12 +202,14 @@ async def async_auth_flow( finally: # token gets updated only after flow.send is called # so unlock only after that - # TODO: FIR-38687 Fix support for anyio 4.5.0+ - if ( - self._lock.locked() - and self._lock._owner_task == get_current_task() # type: ignore - ): - self._lock.release() + if self._lock.locked(): + try: + self._lock.release() + except RuntimeError: + # This task does not own the lock, can't release + logging.warning( + "Tried to release a lock not owned by the current task" + ) def sync_auth_flow(self, request: Request) -> Generator[Request, Response, None]: """ From ce9d76b8c225cfc92a7f574850c0baa2fca892d1 Mon Sep 17 00:00:00 2001 From: ptiurin Date: Fri, 19 Sep 2025 10:36:05 +0100 Subject: [PATCH 3/3] refactor and safer check --- src/firebolt/client/auth/base.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/firebolt/client/auth/base.py b/src/firebolt/client/auth/base.py index 3a8a493bf0e..4c4132e3c2c 100644 --- a/src/firebolt/client/auth/base.py +++ b/src/firebolt/client/auth/base.py @@ -202,14 +202,19 @@ async def async_auth_flow( finally: # token gets updated only after flow.send is called # so unlock only after that - if self._lock.locked(): - try: - self._lock.release() - except RuntimeError: - # This task does not own the lock, can't release - logging.warning( - "Tried to release a lock not owned by the current task" - ) + self._release_lock() + + def _release_lock(self) -> None: + """Release the lock if held.""" + if self._lock.locked(): + try: + self._lock.release() + except RuntimeError as e: + # Check the error string since RuntimeError is very generic + if "a Lock you don't own" not in str(e): + raise + # This task does not own the lock, can't release + logging.warning("Tried to release a lock not owned by the current task") def sync_auth_flow(self, request: Request) -> Generator[Request, Response, None]: """