Skip to content

Commit b84aa25

Browse files
authored
Merge branch 'master' into test-rustloop
2 parents 94f3692 + ecde050 commit b84aa25

8 files changed

Lines changed: 53 additions & 60 deletions

File tree

.github/workflows/test.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ on:
55
branches: [master]
66
pull_request:
77

8+
concurrency:
9+
group: ${{ github.workflow }}-${{ github.ref }}
10+
cancel-in-progress: true
11+
812
jobs:
913
changed-files:
1014
runs-on: ubuntu-latest

docs/versionhistory.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@ Version history
33

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

6+
**UNRELEASED**
7+
8+
- Changed the default name for a task spawned with ``TaskGroup.create_task(func())`` to
9+
match the default task name for the analogous task spawned with
10+
``TaskGroup.start_soon(func)`` or ``TaskGroup.start(func)`` in more situations.
11+
Previously, the default name of a ``TaskGroup.create_task`` task never included the
12+
module name. (The default name for a task spawned with ``TaskGroup.start_soon`` or
13+
``TaskGroup.start`` typically includes the module name.) (PR by @gschaffner)
14+
615
**4.14.2**
716

817
- Changed ``ByteReceiveStream.receive()`` implementations to raise a ``ValueError`` when

src/anyio/_backends/_asyncio.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
UNIXDatagramPacketType,
102102
)
103103
from ..abc._eventloop import StrOrBytesPath
104-
from ..abc._tasks import call_for_coroutine, get_callable_name
104+
from ..abc._tasks import call_for_coroutine, get_callable_name, get_coro_name
105105
from ..lowlevel import RunVar
106106
from ..streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
107107

@@ -926,10 +926,12 @@ def create_task(
926926
"This task group is not active; no new tasks can be started."
927927
)
928928

929+
final_name = get_coro_name(coro, name)
930+
929931
if context is not None:
930-
return context.run(self._spawn, coro, name=name)
932+
return context.run(self._spawn, coro, name=final_name)
931933
else:
932-
return self._spawn(coro, name=name)
934+
return self._spawn(coro, name=final_name)
933935

934936
async def start(
935937
self,

src/anyio/_backends/_trio.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
from .._core._tasks import TaskHandle
8585
from ..abc import IPSockAddrType, UDPPacketType, UNIXDatagramPacketType
8686
from ..abc._eventloop import AsyncBackend, StrOrBytesPath
87-
from ..abc._tasks import T_contra, call_for_coroutine, get_callable_name
87+
from ..abc._tasks import T_contra, call_for_coroutine, get_callable_name, get_coro_name
8888
from ..streams.memory import MemoryObjectSendStream
8989

9090
if TYPE_CHECKING:
@@ -267,7 +267,8 @@ def create_task(
267267
raise TypeError(f"expected a coroutine, got {coro.__class__.__qualname__}")
268268

269269
self._check_active(coro)
270-
handle = TaskHandle(coro, name)
270+
final_name = get_coro_name(coro, name)
271+
handle = TaskHandle(coro, final_name)
271272
if context is not None:
272273
context.run(
273274
partial(self._nursery.start_soon, handle._run_coro, name=handle.name)

src/anyio/abc/_tasks.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@
2525
PosArgsT = TypeVarTuple("PosArgsT")
2626

2727

28+
def get_coro_name(coro: Coroutine[Any, Any, object], override: object = None) -> str:
29+
if override is not None:
30+
return str(override)
31+
32+
try:
33+
cr_frame = coro.cr_frame # type: ignore[attr-defined]
34+
module = cr_frame.f_globals["__name__"]
35+
except (AttributeError, KeyError):
36+
module = None
37+
38+
qualname = getattr(coro, "__qualname__", None)
39+
return ".".join([x for x in (module, qualname) if x])
40+
41+
2842
def get_callable_name(func: Callable, override: object = None) -> str:
2943
if override is not None:
3044
return str(override)

tests/test_sockets.py

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from socket import AddressFamily
2222
from ssl import SSLContext, SSLError
2323
from threading import Thread
24-
from typing import TYPE_CHECKING, Any, Literal, NoReturn, Protocol, TypeVar, cast
24+
from typing import TYPE_CHECKING, Any, Literal, NoReturn, Protocol, cast
2525
from unittest import mock
2626
from unittest.mock import MagicMock, patch
2727

@@ -209,13 +209,6 @@ def factory(
209209
return factory
210210

211211

212-
_T = TypeVar("_T")
213-
214-
215-
def _identity(v: _T) -> _T:
216-
return v
217-
218-
219212
def fill_socket(sock: socket.socket) -> None:
220213
try:
221214
while True:
@@ -224,19 +217,6 @@ def fill_socket(sock: socket.socket) -> None:
224217
pass
225218

226219

227-
# _ProactorBasePipeTransport.abort() after _ProactorBasePipeTransport.close()
228-
# does not cancel writes: https://bugs.python.org/issue44428
229-
_ignore_win32_resource_warnings = (
230-
pytest.mark.filterwarnings(
231-
"ignore:unclosed <socket.socket:ResourceWarning",
232-
"ignore:unclosed transport <_ProactorSocketTransport closing:ResourceWarning",
233-
)
234-
if sys.version_info < (3, 10) and sys.platform == "win32"
235-
else _identity
236-
)
237-
238-
239-
@_ignore_win32_resource_warnings
240220
class TestTCPStream:
241221
@pytest.fixture
242222
def server_sock(self, family: AnyIPAddressFamily) -> Iterator[socket.socket]:
@@ -437,10 +417,6 @@ async def test_happy_eyeballs_refcycles(
437417
"""
438418
Test derived from https://github.com/python/cpython/pull/124859
439419
"""
440-
if anyio_backend_name == "asyncio" and sys.version_info < (3, 10):
441-
pytest.skip(
442-
"asyncio.BaseEventLoop.create_connection creates refcycles on py 3.9"
443-
)
444420
if (
445421
anyio_backend_name == "asyncio"
446422
and event_loop_implementation_name.startswith("rsloop")

tests/test_synchronization.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import asyncio
44
import math
5-
import sys
65
from contextlib import AbstractContextManager
76
from typing import Any
87

@@ -712,23 +711,12 @@ async def test_bad_init_type(self) -> None:
712711
"total_tokens must be an int or math.inf"
713712
)
714713

715-
async def test_bad_init_value(self, anyio_backend_name: str) -> None:
716-
# TODO: Remove this once Python 3.9 is dropped
717-
if sys.version_info < (3, 10) and anyio_backend_name == "trio":
718-
bad_value = 0
719-
min_value = 1
720-
else:
721-
bad_value = -1
722-
min_value = 0
723-
724-
pytest.raises(ValueError, CapacityLimiter, bad_value).match(
725-
f"total_tokens must be >= {min_value}"
714+
async def test_bad_init_value(self) -> None:
715+
pytest.raises(ValueError, CapacityLimiter, -1).match(
716+
"total_tokens must be >= 0"
726717
)
727718

728-
async def test_zero_tokens(self, anyio_backend_name: str) -> None:
729-
if sys.version_info < (3, 10) and anyio_backend_name == "trio":
730-
pytest.skip("Trio does not support zero-capacity limiters on Python 3.9")
731-
719+
async def test_zero_tokens(self) -> None:
732720
limiter = CapacityLimiter(0)
733721
assert limiter.total_tokens == 0
734722

tests/test_taskgroups.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,14 +2145,14 @@ async def taskfunc(x: int, y: int) -> int:
21452145

21462146
assert re.match(
21472147
r"<TaskHandle pending "
2148-
r"name='TestCreateTask.test_return_value.<locals>.taskfunc' "
2148+
r"name='tests.test_taskgroups.TestCreateTask.test_return_value.<locals>.taskfunc' "
21492149
r"coro=<coroutine object(.+)>>",
21502150
repr(handle),
21512151
)
21522152
assert await handle == 6
21532153
assert re.match(
21542154
r"<TaskHandle finished "
2155-
r"name='TestCreateTask.test_return_value.<locals>.taskfunc' "
2155+
r"name='tests.test_taskgroups.TestCreateTask.test_return_value.<locals>.taskfunc' "
21562156
r"coro=<coroutine object(.+)>>",
21572157
repr(handle),
21582158
)
@@ -2179,7 +2179,7 @@ async def taskfunc() -> NoReturn:
21792179

21802180
assert re.match(
21812181
r"<TaskHandle failed "
2182-
r"name='TestCreateTask.test_exception.<locals>.taskfunc' "
2182+
r"name='tests.test_taskgroups.TestCreateTask.test_exception.<locals>.taskfunc' "
21832183
r"coro=<coroutine object(.+)>",
21842184
repr(handle),
21852185
)
@@ -2202,7 +2202,7 @@ async def main() -> None:
22022202
assert handle.status is TaskHandle.Status.FAILED
22032203
assert re.match(
22042204
r"<TaskHandle failed "
2205-
r"name='TestCreateTask.test_base_exception.<locals>.taskfunc' "
2205+
r"name='tests.test_taskgroups.TestCreateTask.test_base_exception.<locals>.taskfunc' "
22062206
r"coro=<coroutine object(.+)>",
22072207
repr(handle),
22082208
)
@@ -2237,7 +2237,7 @@ async def taskfunc() -> None:
22372237
assert handle.status is TaskHandle.Status.CANCELLING
22382238
assert re.match(
22392239
r"<TaskHandle cancelling "
2240-
r"name='TestCreateTask.test_cancel.<locals>.taskfunc' "
2240+
r"name='tests.test_taskgroups.TestCreateTask.test_cancel.<locals>.taskfunc' "
22412241
r"coro=<coroutine object(.+)>>",
22422242
repr(handle),
22432243
)
@@ -2259,7 +2259,7 @@ async def taskfunc() -> None:
22592259
assert task_started
22602260
assert re.match(
22612261
r"<TaskHandle cancelled "
2262-
r"name='TestCreateTask.test_cancel.<locals>.taskfunc' "
2262+
r"name='tests.test_taskgroups.TestCreateTask.test_cancel.<locals>.taskfunc' "
22632263
r"coro=<coroutine object(.+)>>",
22642264
repr(handle),
22652265
)
@@ -2284,13 +2284,16 @@ async def taskfunc() -> str | None:
22842284
handle = tg.create_task(taskfunc())
22852285
assert re.match(
22862286
r"<TaskHandle pending "
2287-
r"name='TestCreateTask.test_task_name_default.<locals>.taskfunc' "
2287+
r"name='tests.test_taskgroups.TestCreateTask.test_task_name_default.<locals>.taskfunc' "
22882288
r"coro=<coroutine object(.+)>>",
22892289
repr(handle),
22902290
)
22912291
assert await handle == handle.name
22922292

2293-
assert handle.name == "TestCreateTask.test_task_name_default.<locals>.taskfunc"
2293+
assert (
2294+
handle.name
2295+
== "tests.test_taskgroups.TestCreateTask.test_task_name_default.<locals>.taskfunc"
2296+
)
22942297

22952298
async def test_task_name_custom_name(self) -> None:
22962299
async def taskfunc() -> None:
@@ -2326,11 +2329,7 @@ async def genfunc(x: int, y: int) -> AsyncGenerator[int, None]:
23262329

23272330
async with create_task_group() as tg:
23282331
async with aclosing(genfunc(3, 5)) as g:
2329-
if create_task:
2330-
handle = tg.create_task(g.asend(None))
2331-
assert handle.name.startswith("<async_generator_asend object at ")
2332-
else:
2333-
handle = tg.start_soon(g.asend, None)
2334-
assert handle.name == "async_generator.asend"
2332+
handle = tg.start_soon(g.asend, None)
2333+
assert handle.name == "async_generator.asend"
23352334

23362335
assert await handle == 8

0 commit comments

Comments
 (0)