Skip to content

Commit dbc2d71

Browse files
Khwahish29mystical-prog
authored andcommitted
modify anyio_service.py
1 parent 3aedfd1 commit dbc2d71

File tree

10 files changed

+54
-42
lines changed

10 files changed

+54
-42
lines changed

libp2p/tools/anyio_service/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ The implementation maintains the same public API as the previous async service i
5555
To migrate from the previous async service implementation:
5656

5757
1. Update imports to use `libp2p.tools.anyio_service` instead of `libp2p.tools.async_service`
58-
2. No other code changes required - the API is fully compatible
58+
1. No other code changes required - the API is fully compatible
5959

6060
## Requirements
6161

6262
- Python 3.7+
63-
- anyio library
63+
- anyio library
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
from .abc import (
22
ServiceAPI,
33
)
4+
from .anyio_service import (
5+
AnyioManager,
6+
background_anyio_service,
7+
)
48
from .base import (
59
Service,
610
as_service,
@@ -9,10 +13,6 @@
913
DaemonTaskExit,
1014
LifecycleError,
1115
)
12-
from .anyio_service import (
13-
AnyioManager,
14-
background_anyio_service,
15-
)
1616

1717
__all__ = [
1818
"ServiceAPI",
@@ -22,4 +22,4 @@
2222
"LifecycleError",
2323
"AnyioManager",
2424
"background_anyio_service",
25-
]
25+
]

libp2p/tools/anyio_service/abc.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,11 @@ class InternalManagerAPI(ManagerAPI):
205205

206206
@abstractmethod
207207
def run_task(
208-
self, async_fn: AsyncFn, *args: Any, daemon: bool = False, name: Optional[str] = None
208+
self,
209+
async_fn: AsyncFn,
210+
*args: Any,
211+
daemon: bool = False,
212+
name: Optional[str] = None
209213
) -> None:
210214
"""
211215
Run a task in the background. If the function throws an exception it
@@ -217,7 +221,9 @@ def run_task(
217221
...
218222

219223
@abstractmethod
220-
def run_daemon_task(self, async_fn: AsyncFn, *args: Any, name: Optional[str] = None) -> None:
224+
def run_daemon_task(
225+
self, async_fn: AsyncFn, *args: Any, name: Optional[str] = None
226+
) -> None:
221227
"""
222228
Run a daemon task in the background.
223229
@@ -247,4 +253,4 @@ def run_daemon_child_service(
247253
248254
Equivalent to `run_child_service(..., daemon=True)`.
249255
"""
250-
...
256+
...

libp2p/tools/anyio_service/anyio_service.py

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import anyio
2-
import logging
3-
import sys
41
from collections.abc import (
2+
AsyncIterator,
53
Awaitable,
64
Callable,
75
)
@@ -11,15 +9,17 @@
119
from functools import (
1210
wraps,
1311
)
12+
import logging
13+
import sys
1414
from typing import (
1515
Any,
16-
AsyncIterator,
1716
Optional,
1817
TypeVar,
1918
cast,
20-
Union,
2119
)
2220

21+
import anyio
22+
2323
if sys.version_info >= (3, 11):
2424
from builtins import (
2525
ExceptionGroup,
@@ -52,18 +52,16 @@
5252

5353
T = TypeVar("T", bound=Callable[..., Any])
5454

55+
5556
def external_api(func: T) -> T:
56-
"""
57-
Decorator to mark a method as an external API that can be called from outside the service.
58-
This ensures that the service is in the correct state before allowing the method to be called.
59-
"""
6057
@wraps(func)
6158
def wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
6259
if not hasattr(self, "manager"):
6360
raise LifecycleError("Service has no manager")
6461
if not self.manager.is_running:
6562
raise LifecycleError("Service is not running")
6663
return func(self, *args, **kwargs)
64+
6765
return cast(T, wrapper)
6866

6967

@@ -204,11 +202,11 @@ def __init__(self, service: ServiceAPI) -> None:
204202
self._total_task_count = 0
205203
self._done_task_count = 0
206204

207-
self._started = anyio.create_event()
208-
self._cancelled = anyio.create_event()
209-
self._finished = anyio.create_event()
205+
self._started = anyio.Event()
206+
self._cancelled = anyio.Event()
207+
self._finished = anyio.Event()
210208

211-
self._run_lock = anyio.create_lock()
209+
self._run_lock = anyio.Lock()
212210
self._task_group: Optional[anyio.abc.TaskGroup] = None
213211

214212
def __str__(self) -> str:
@@ -238,7 +236,10 @@ async def stop(self) -> None:
238236
await self.wait_finished()
239237

240238
def run_daemon_task(
241-
self, async_fn: Callable[..., Awaitable[Any]], *args: Any, name: Optional[str] = None
239+
self,
240+
async_fn: Callable[..., Awaitable[Any]],
241+
*args: Any,
242+
name: Optional[str] = None,
242243
) -> None:
243244
self.run_task(async_fn, *args, daemon=True, name=name)
244245

@@ -255,7 +256,9 @@ def stats(self) -> Stats:
255256
tasks=TaskStats(total_count=total_count, finished_count=finished_count)
256257
)
257258

258-
def _add_child_task(self, parent: Optional[TaskWithChildrenAPI], task: TaskAPI) -> None:
259+
def _add_child_task(
260+
self, parent: Optional[TaskWithChildrenAPI], task: TaskAPI
261+
) -> None:
259262
if parent is not None:
260263
parent.add_child(task)
261264

@@ -355,7 +358,7 @@ async def run(self) -> None:
355358
if not isinstance(exc_value, DaemonTaskExit):
356359
exceptions.append(exc_value.with_traceback(exc_tb))
357360
error_messages.append(f"{exc_type.__name__}: {str(exc_value)}")
358-
361+
359362
if len(exceptions) == 1:
360363
raise exceptions[0]
361364
elif len(exceptions) > 1:
@@ -440,8 +443,9 @@ def run_child_service(
440443

441444
@asynccontextmanager
442445
async def background_anyio_service(service: ServiceAPI) -> AsyncIterator[ManagerAPI]:
443-
"""Run a service in the background and yield its manager.
444-
446+
"""
447+
Run a service in the background and yield its manager.
448+
445449
The service will be stopped when the context exits.
446450
"""
447451
async with anyio.create_task_group() as tg:

libp2p/tools/anyio_service/base.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
from abc import (
2-
abstractmethod,
3-
)
41
from collections.abc import (
52
Awaitable,
63
)
74
from typing import (
85
Any,
96
Callable,
10-
TypeVar,
11-
cast,
127
)
138

149
from .abc import (
@@ -63,4 +58,4 @@ async def run(self) -> None:
6358

6459
_Service.__name__ = service_fn.__name__
6560
_Service.__doc__ = service_fn.__doc__
66-
return _Service
61+
return _Service

libp2p/tools/anyio_service/exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ class LifecycleError(ServiceException):
1313
class DaemonTaskExit(ServiceException):
1414
"""
1515
Raised when a daemon task exits unexpectedly.
16-
"""
16+
"""

libp2p/tools/anyio_service/stats.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from dataclasses import dataclass
1+
from dataclasses import (
2+
dataclass,
3+
)
24

35

46
@dataclass
@@ -9,4 +11,4 @@ class TaskStats:
911

1012
@dataclass
1113
class Stats:
12-
tasks: TaskStats
14+
tasks: TaskStats

libp2p/tools/anyio_service/typing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@
1111

1212
AsyncFn = Callable[..., Awaitable[Any]]
1313

14-
TFunc = TypeVar("TFunc", bound=Callable[..., Awaitable[Any]])
14+
TFunc = TypeVar("TFunc", bound=Callable[..., Awaitable[Any]])

newsfragments/604.feature.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Transitioned from `async_service` to `anyio_service`, leveraging AnyIO's robust async primitives for improved task management and exception handling. This change enhances compatibility with modern async patterns and improves overall service reliability.
1+
Transitioned from `async_service` to `anyio_service`, leveraging AnyIO's robust async primitives for improved task management and exception handling. This change enhances compatibility with modern async patterns and improves overall service reliability.

tests/core/tools/anyio_service/test_anyio_service.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import sys
2+
13
import pytest
24
import anyio
3-
import sys
45

56
if sys.version_info >= (3, 11):
67
from builtins import (
@@ -10,12 +11,13 @@
1011
from exceptiongroup import ExceptionGroup
1112

1213
from libp2p.tools.anyio_service import (
13-
Service,
1414
AnyioManager,
15+
Service,
1516
as_service,
1617
background_anyio_service,
1718
)
1819

20+
1921
@pytest.mark.anyio
2022
async def test_service_lifecycle():
2123
class SimpleService(Service):
@@ -28,6 +30,7 @@ async def run(self):
2830
assert manager.is_running
2931
assert manager.is_finished
3032

33+
3134
@pytest.mark.anyio
3235
async def test_exception_handling():
3336
class ErrorService(Service):
@@ -44,6 +47,7 @@ async def run(self):
4447
for e in exc_info.value.exceptions
4548
)
4649

50+
4751
@pytest.mark.anyio
4852
async def test_task_management():
4953
task_event = anyio.Event()
@@ -60,6 +64,7 @@ async def task_fn():
6064
with anyio.fail_after(0.1):
6165
await task_event.wait()
6266

67+
6368
@pytest.mark.anyio
6469
async def test_cancellation_and_cleanup():
6570
class CancellableService(Service):
@@ -71,4 +76,4 @@ async def run(self):
7176
assert manager.is_running
7277
manager.cancel()
7378
assert manager.is_cancelled
74-
assert manager.is_finished
79+
assert manager.is_finished

0 commit comments

Comments
 (0)