From 97f064295b65dc1d7a2ded6fd24ba5be46d4c4f4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:30:06 +0200 Subject: [PATCH 1/7] [pre-commit.ci] pre-commit autoupdate (#838) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.1 → v0.8.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.1...v0.8.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 69e0878f..19bbdc19 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.1 + rev: v0.8.2 hooks: - id: ruff args: [--fix, --show-fixes] From 3c5d4a6e8c21b0fcc75574b0b4b45575492a772b Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 16 Dec 2024 09:15:17 +0000 Subject: [PATCH 2/7] Use settings from Trio for Selector waker socketpair (#836) --- docs/versionhistory.rst | 7 +++++++ src/anyio/_core/_asyncio_selector_thread.py | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/docs/versionhistory.rst b/docs/versionhistory.rst index 50745252..518aef88 100644 --- a/docs/versionhistory.rst +++ b/docs/versionhistory.rst @@ -3,6 +3,13 @@ Version history This library adheres to `Semantic Versioning 2.0 `_. +**UNRELEASED** + +- Configure ``SO_RCVBUF``, ``SO_SNDBUF`` and ``TCP_NODELAY`` on the selector + thread waker socket pair. This should improve the performance of ``wait_readable()`` + and ``wait_writable()`` when using the ``ProactorEventLoop`` + (`#836 `_; PR by @graingert) + **4.7.0** - Updated ``TaskGroup`` to work with asyncio's eager task factories diff --git a/src/anyio/_core/_asyncio_selector_thread.py b/src/anyio/_core/_asyncio_selector_thread.py index d98c3040..f4d18cf0 100644 --- a/src/anyio/_core/_asyncio_selector_thread.py +++ b/src/anyio/_core/_asyncio_selector_thread.py @@ -21,6 +21,23 @@ def __init__(self) -> None: self._send, self._receive = socket.socketpair() self._send.setblocking(False) self._receive.setblocking(False) + # This somewhat reduces the amount of memory wasted queueing up data + # for wakeups. With these settings, maximum number of 1-byte sends + # before getting BlockingIOError: + # Linux 4.8: 6 + # macOS (darwin 15.5): 1 + # Windows 10: 525347 + # Windows you're weird. (And on Windows setting SNDBUF to 0 makes send + # blocking, even on non-blocking sockets, so don't do that.) + self._receive.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1) + self._send.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1) + # On Windows this is a TCP socket so this might matter. On other + # platforms this fails b/c AF_UNIX sockets aren't actually TCP. + try: + self._send.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + except OSError: + pass + self._selector.register(self._receive, EVENT_READ) self._closed = False From d14f005c9649a42019f0d3fd4394d1fd66d54d18 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 00:06:48 +0200 Subject: [PATCH 3/7] [pre-commit.ci] pre-commit autoupdate (#842) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.2 → v0.8.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.2...v0.8.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 19bbdc19..5e65d60e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.2 + rev: v0.8.3 hooks: - id: ruff args: [--fix, --show-fixes] From c518300593f2411196fd492d917269dcb6f7682b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Wed, 18 Dec 2024 00:07:30 +0200 Subject: [PATCH 4/7] Fixed AssertionError when using nest_asyncio (#841) This stems from the incorrect placement of `nest_asyncio.apply()`, as it should be called before `asyncio.run()`. Fixes #840. --- docs/versionhistory.rst | 2 ++ src/anyio/_backends/_asyncio.py | 32 +++++++++++++++++--------------- tests/test_taskgroups.py | 13 ++++++++++++- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/docs/versionhistory.rst b/docs/versionhistory.rst index 518aef88..4901da4c 100644 --- a/docs/versionhistory.rst +++ b/docs/versionhistory.rst @@ -9,6 +9,8 @@ This library adheres to `Semantic Versioning 2.0 `_. thread waker socket pair. This should improve the performance of ``wait_readable()`` and ``wait_writable()`` when using the ``ProactorEventLoop`` (`#836 `_; PR by @graingert) +- Fixed ``AssertionError`` when using ``nest-asyncio`` + (`#840 `_) **4.7.0** diff --git a/src/anyio/_backends/_asyncio.py b/src/anyio/_backends/_asyncio.py index 0b7479d2..5a0aa936 100644 --- a/src/anyio/_backends/_asyncio.py +++ b/src/anyio/_backends/_asyncio.py @@ -677,40 +677,42 @@ def __init__(self, parent_id: int | None, cancel_scope: CancelScope | None): self.cancel_scope = cancel_scope -class TaskStateStore(MutableMapping["Awaitable[Any] | asyncio.Task", TaskState]): +class TaskStateStore( + MutableMapping["Coroutine[Any, Any, Any] | asyncio.Task", TaskState] +): def __init__(self) -> None: self._task_states = WeakKeyDictionary[asyncio.Task, TaskState]() - self._preliminary_task_states: dict[Awaitable[Any], TaskState] = {} + self._preliminary_task_states: dict[Coroutine[Any, Any, Any], TaskState] = {} - def __getitem__(self, key: Awaitable[Any] | asyncio.Task, /) -> TaskState: - assert isinstance(key, asyncio.Task) + def __getitem__(self, key: Coroutine[Any, Any, Any] | asyncio.Task, /) -> TaskState: + task = cast(asyncio.Task, key) try: - return self._task_states[key] + return self._task_states[task] except KeyError: - if coro := key.get_coro(): + if coro := task.get_coro(): if state := self._preliminary_task_states.get(coro): return state raise KeyError(key) def __setitem__( - self, key: asyncio.Task | Awaitable[Any], value: TaskState, / + self, key: asyncio.Task | Coroutine[Any, Any, Any], value: TaskState, / ) -> None: - if isinstance(key, asyncio.Task): - self._task_states[key] = value - else: + if isinstance(key, Coroutine): self._preliminary_task_states[key] = value - - def __delitem__(self, key: asyncio.Task | Awaitable[Any], /) -> None: - if isinstance(key, asyncio.Task): - del self._task_states[key] else: + self._task_states[key] = value + + def __delitem__(self, key: asyncio.Task | Coroutine[Any, Any, Any], /) -> None: + if isinstance(key, Coroutine): del self._preliminary_task_states[key] + else: + del self._task_states[key] def __len__(self) -> int: return len(self._task_states) + len(self._preliminary_task_states) - def __iter__(self) -> Iterator[Awaitable[Any] | asyncio.Task]: + def __iter__(self) -> Iterator[Coroutine[Any, Any, Any] | asyncio.Task]: yield from self._task_states yield from self._preliminary_task_states diff --git a/tests/test_taskgroups.py b/tests/test_taskgroups.py index 1f536940..d20565c1 100644 --- a/tests/test_taskgroups.py +++ b/tests/test_taskgroups.py @@ -11,7 +11,7 @@ import pytest from exceptiongroup import catch -from pytest import FixtureRequest +from pytest import FixtureRequest, MonkeyPatch from pytest_mock import MockerFixture import anyio @@ -1778,3 +1778,14 @@ async def sync_coro() -> None: async with create_task_group() as tg: tg.start_soon(sync_coro) tg.cancel_scope.cancel() + + +@pytest.mark.parametrize("anyio_backend", ["asyncio"]) +async def test_patched_asyncio_task(monkeypatch: MonkeyPatch) -> None: + monkeypatch.setattr( + asyncio, + "Task", + asyncio.tasks._PyTask, # type: ignore[attr-defined] + ) + async with create_task_group() as tg: + tg.start_soon(sleep, 0) From 3f8c639d36d0ac01d341b25f6f99f1bc7aff6d12 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 24 Dec 2024 04:52:24 +0200 Subject: [PATCH 5/7] [pre-commit.ci] pre-commit autoupdate (#846) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.3 → v0.8.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.3...v0.8.4) - [github.com/pre-commit/mirrors-mypy: v1.13.0 → v1.14.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.13.0...v1.14.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5e65d60e..620a059d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,14 +22,14 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.3 + rev: v0.8.4 hooks: - id: ruff args: [--fix, --show-fixes] - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.13.0 + rev: v1.14.0 hooks: - id: mypy additional_dependencies: From 2a105b2bc6ebb4d12b67b4c9c1777ff5cc54f42b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Thu, 2 Jan 2025 04:08:35 +0200 Subject: [PATCH 6/7] Updated downstream test workflow --- .github/workflows/test-downstream.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-downstream.yml b/.github/workflows/test-downstream.yml index 9a8b128f..5a95664b 100644 --- a/.github/workflows/test-downstream.yml +++ b/.github/workflows/test-downstream.yml @@ -74,7 +74,7 @@ jobs: with: python-version: "${{ matrix.python-version }}" - name: Setup uv - uses: astral-sh/setup-uv@v3 + uses: astral-sh/setup-uv@v5 with: version: "0.4.15" enable-cache: true @@ -96,7 +96,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.12"] + python-version: ["3.9", "3.13"] steps: - uses: actions/checkout@v4 with: @@ -106,7 +106,7 @@ jobs: with: python-version: ${{ inputs.python-version }} - name: Install uv - uses: astral-sh/setup-uv@v4 + uses: astral-sh/setup-uv@v5 with: version: "0.5.4" enable-cache: true From 9a792f3568f450ad97363d7bf0baa04f768ae291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Thu, 2 Jan 2025 15:39:57 +0200 Subject: [PATCH 7/7] Pruned unnecessary mypy options --- pyproject.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 73f6642b..9fed760f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -93,12 +93,9 @@ extend-select = [ [tool.mypy] python_version = "3.13" strict = true -ignore_missing_imports = true disallow_any_generics = false warn_return_any = false disallow_untyped_decorators = false -disallow_subclassing_any = false -show_error_codes = true [tool.pytest.ini_options] addopts = "-rsfE --tb=short --strict-config --strict-markers -p anyio -p no:asyncio -p no:trio"