Skip to content

Commit 85bf500

Browse files
Added an optional thread name parameter to start_blocking_portal() (#900)
1 parent 2a63fd0 commit 85bf500

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

docs/versionhistory.rst

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ Version history
33

44
This library adheres to `Semantic Versioning 2.0 <http://semver.org/>`_.
55

6+
**UNRELEASED**
7+
8+
- Added the ability to specify the thread name in ``start_blocking_portal()``
9+
(`#818 <https://github.com/agronholm/anyio/issues/818>`_; PR by @davidbrochart)
10+
611
**4.9.0**
712

813
- Added async support for temporary file handling

src/anyio/from_thread.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
)
1111
from dataclasses import dataclass, field
1212
from inspect import isawaitable
13-
from threading import Lock, Thread, get_ident
13+
from threading import Lock, Thread, current_thread, get_ident
1414
from types import TracebackType
1515
from typing import (
1616
Any,
@@ -454,7 +454,10 @@ def __exit__(
454454

455455
@contextmanager
456456
def start_blocking_portal(
457-
backend: str = "asyncio", backend_options: dict[str, Any] | None = None
457+
backend: str = "asyncio",
458+
backend_options: dict[str, Any] | None = None,
459+
*,
460+
name: str | None = None,
458461
) -> Generator[BlockingPortal, Any, None]:
459462
"""
460463
Start a new event loop in a new thread and run a blocking portal in its main task.
@@ -463,6 +466,7 @@ def start_blocking_portal(
463466
464467
:param backend: name of the backend
465468
:param backend_options: backend options
469+
:param name: name of the thread
466470
:return: a context manager that yields a blocking portal
467471
468472
.. versionchanged:: 3.0
@@ -472,6 +476,9 @@ def start_blocking_portal(
472476

473477
async def run_portal() -> None:
474478
async with BlockingPortal() as portal_:
479+
if name is None:
480+
current_thread().name = f"{backend}-portal-{id(portal_):x}"
481+
475482
future.set_result(portal_)
476483
await portal_.sleep_until_stopped()
477484

@@ -486,7 +493,7 @@ def run_blocking_portal() -> None:
486493
future.set_exception(exc)
487494

488495
future: Future[BlockingPortal] = Future()
489-
thread = Thread(target=run_blocking_portal, daemon=True)
496+
thread = Thread(target=run_blocking_portal, daemon=True, name=name)
490497
thread.start()
491498
try:
492499
cancel_remaining_tasks = False

tests/test_from_thread.py

+16
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,22 @@ async def async_get_thread_id() -> int:
371371
assert isinstance(thread_id, int)
372372
assert thread_id != threading.get_ident()
373373

374+
def test_start_with_thread_name(
375+
self, anyio_backend_name: str, anyio_backend_options: dict[str, Any]
376+
) -> None:
377+
with start_blocking_portal(
378+
anyio_backend_name, anyio_backend_options, name="foo"
379+
) as portal:
380+
assert portal.call(lambda: threading.current_thread().name) == "foo"
381+
382+
def test_start_without_thread_name(
383+
self, anyio_backend_name: str, anyio_backend_options: dict[str, Any]
384+
) -> None:
385+
with start_blocking_portal(anyio_backend_name, anyio_backend_options) as portal:
386+
assert portal.call(lambda: threading.current_thread().name) == (
387+
f"{anyio_backend_name}-portal-{id(portal):x}"
388+
)
389+
374390
def test_start_with_nonexistent_backend(self) -> None:
375391
with pytest.raises(LookupError) as exc:
376392
with start_blocking_portal("foo"):

0 commit comments

Comments
 (0)