Files
py-libp2p/libp2p/tools/async_service/abc.py
Arush Kurundodi bdadec7519 ft. modernise py-libp2p (#618)
* fix pyproject.toml , add ruff

* rm lock

* make progress

* add poetry lock ignore

* fix type issues

* fix tcp type errors

* fix text example - type error - wrong args

* add setuptools to dev

* test ci

* fix docs build

* fix type issues for new_swarm & new_host

* fix types in gossipsub

* fix type issues in noise

* wip: factories

* revert factories

* fix more type issues

* more type fixes

* fix: add null checks for noise protocol initialization and key handling

* corrected argument-errors in peerId and Multiaddr in peer tests

* fix: Noice - remove redundant type casts in BaseNoiseMsgReadWriter

* fix: update test_notify.py to use SwarmFactory.create_batch_and_listen, fix type hints, and comment out ClosedStream assertions

* Fix type checks for pubsub module

Signed-off-by: sukhman <sukhmansinghsaluja@gmail.com>

* Fix type checks for pubsub module-tests

Signed-off-by: sukhman <sukhmansinghsaluja@gmail.com>

* noise: add checks for uninitialized protocol and key states in PatternXX

Signed-off-by: varun-r-mallya <varunrmallya@gmail.com>

* pubsub: add None checks for optional fields in FloodSub and Pubsub

Signed-off-by: varun-r-mallya <varunrmallya@gmail.com>

* Fix type hints and improve testing

Signed-off-by: varun-r-mallya <varunrmallya@gmail.com>

* remove redundant checks

Signed-off-by: varun-r-mallya <varunrmallya@gmail.com>

* fix build issues

* add optional to trio service

* fix types

* fix type errors

* Fix type errors

Signed-off-by: varun-r-mallya <varunrmallya@gmail.com>

* fixed more-type checks in crypto and peer_data files

* wip: factories

* replaced union with optional

* fix: type-error in interp-utils and peerinfo

* replace pyright with pyrefly

* add pyrefly.toml

* wip: fix multiselect issues

* try typecheck

* base check

* mcache test fixes , typecheck ci update

* fix ci

* will this work

* minor fix

* use poetry

* fix wokflow

* use cache,fix err

* fix pyrefly.toml

* fix pyrefly.toml

* fix cache in ci

* deploy commit

* add main baseline

* update to v5

* improve typecheck ci (#14)

* fix typo

* remove holepunching code (#16)

* fix gossipsub typeerrors (#17)

* fix: ensure initiator user includes remote peer id in handshake (#15)

* fix ci (#19)

* typefix: custom_types | core/peerinfo/test_peer_info | io/abc | pubsub/floodsub | protocol_muxer/multiselect (#18)

* fix: Typefixes in PeerInfo  (#21)

* fix minor type issue (#22)

* fix type errors in pubsub (#24)

* fix: Minor typefixes in tests (#23)

* Fix failing tests for type-fixed test/pubsub (#8)

* move pyrefly & ruff to pyproject.toml & rm .project-template (#28)

* move the async_context file to tests/core

* move crypto test to crypto folder

* fix: some typefixes (#25)

* fix type errors

* fix type issues

* fix: update gRPC API usage in autonat_pb2_grpc.py (#31)

* md: typecheck ci

* rm comments

* clean up : from review suggestions

* use | None over Optional as per new python standards

* drop supporto for py3.9

* newsfragments

---------

Signed-off-by: sukhman <sukhmansinghsaluja@gmail.com>
Signed-off-by: varun-r-mallya <varunrmallya@gmail.com>
Co-authored-by: acul71 <luca.pisani@birdo.net>
Co-authored-by: kaneki003 <sakshamchauhan707@gmail.com>
Co-authored-by: sukhman <sukhmansinghsaluja@gmail.com>
Co-authored-by: varun-r-mallya <varunrmallya@gmail.com>
Co-authored-by: varunrmallya <100590632+varun-r-mallya@users.noreply.github.com>
Co-authored-by: lla-dane <abhinavagarwalla6@gmail.com>
Co-authored-by: Collins <ArtemisfowlX@protonmail.com>
Co-authored-by: Abhinav Agarwalla <120122716+lla-dane@users.noreply.github.com>
Co-authored-by: guha-rahul <52607971+guha-rahul@users.noreply.github.com>
Co-authored-by: Sukhman Singh <63765293+sukhman-sukh@users.noreply.github.com>
Co-authored-by: acul71 <34693171+acul71@users.noreply.github.com>
Co-authored-by: pacrob <5199899+pacrob@users.noreply.github.com>
2025-06-09 11:39:59 -06:00

259 lines
6.2 KiB
Python

# Copied from https://github.com/ethereum/async-service
from abc import (
ABC,
abstractmethod,
)
from collections.abc import (
Hashable,
)
from typing import (
Any,
Optional,
)
import trio_typing
from .stats import (
Stats,
)
from .typing import (
AsyncFn,
)
class TaskAPI(Hashable):
name: str
daemon: bool
parent: Optional["TaskWithChildrenAPI"]
@abstractmethod
async def run(self) -> None: ...
@abstractmethod
async def cancel(self) -> None: ...
@property
@abstractmethod
def is_done(self) -> bool: ...
@abstractmethod
async def wait_done(self) -> None: ...
class TaskWithChildrenAPI(TaskAPI):
children: set[TaskAPI]
@abstractmethod
def add_child(self, child: TaskAPI) -> None: ...
@abstractmethod
def discard_child(self, child: TaskAPI) -> None: ...
class ServiceAPI(ABC):
_manager: "InternalManagerAPI"
@abstractmethod
def get_manager(self) -> "ManagerAPI":
"""
External retrieval of the manager for this service.
Will raise a :class:`~async_service.exceptions.LifecycleError` if the
service does not yet have a `manager` assigned to it.
"""
...
@abstractmethod
async def run(self) -> None:
"""
Primary entry point for all service logic.
.. note:: This method should **not** be directly invoked by user code.
Services may be run using the following approaches.
.. code-block: python
# 1. run the service in the background using a context manager
async with run_service(service) as manager:
# service runs inside context block
...
# service cancels and stops when context exits
# service will have fully stopped
# 2. run the service blocking until completion
await Manager.run_service(service)
# 3. create manager and then run service blocking until completion
manager = Manager(service)
await manager.run()
"""
...
class ManagerAPI(ABC):
@property
@abstractmethod
def is_started(self) -> bool:
"""
Return boolean indicating if the underlying service has been started.
"""
...
@property
@abstractmethod
def is_running(self) -> bool:
"""
Return boolean indicating if the underlying service is actively
running.
A service is considered running if it has been started and
has not yet been stopped.
"""
...
@property
@abstractmethod
def is_cancelled(self) -> bool:
"""
Return boolean indicating if the underlying service has been cancelled.
This can occure externally via the `cancel()` method or internally due
to a task crash or a crash of the actual :meth:`ServiceAPI.run` method.
"""
...
@property
@abstractmethod
def is_finished(self) -> bool:
"""
Return boolean indicating if the underlying service is stopped.
A stopped service will have completed all of the background tasks.
"""
...
@property
@abstractmethod
def did_error(self) -> bool:
"""
Return boolean indicating if the underlying service threw an exception.
"""
...
@abstractmethod
def cancel(self) -> None:
"""
Trigger cancellation of the service.
"""
...
@abstractmethod
async def stop(self) -> None:
"""
Trigger cancellation of the service and wait for it to finish.
"""
...
@abstractmethod
async def wait_started(self) -> None:
"""
Wait until the service is started.
"""
...
@abstractmethod
async def wait_finished(self) -> None:
"""
Wait until the service is stopped.
"""
...
@classmethod
@abstractmethod
async def run_service(cls, service: ServiceAPI) -> None:
"""
Run a service
"""
...
@abstractmethod
async def run(self) -> None:
"""
Run a service
"""
...
@property
@abstractmethod
def stats(self) -> Stats:
"""
Return a stats object with details about the service.
"""
...
class InternalManagerAPI(ManagerAPI):
"""
Defines the API that the `Service.manager` property exposes.
The InternalManagerAPI / ManagerAPI distinction is in place to ensure that
external callers to a service do not try to use the task scheduling
functionality as it is only designed to be used internally.
"""
@trio_typing.takes_callable_and_args
@abstractmethod
def run_task(
self,
async_fn: AsyncFn,
*args: Any,
daemon: bool = False,
name: str | None = None,
) -> None:
"""
Run a task in the background. If the function throws an exception it
will trigger the service to be cancelled and be propogated.
If `daemon == True` then the the task is expected to run indefinitely
and will trigger cancellation if the task finishes.
"""
...
@trio_typing.takes_callable_and_args
@abstractmethod
def run_daemon_task(
self, async_fn: AsyncFn, *args: Any, name: str | None = None
) -> None:
"""
Run a daemon task in the background.
Equivalent to `run_task(..., daemon=True)`.
"""
...
@abstractmethod
def run_child_service(
self, service: ServiceAPI, daemon: bool = False, name: str | None = None
) -> "ManagerAPI":
"""
Run a service in the background. If the function throws an exception it
will trigger the parent service to be cancelled and be propogated.
If `daemon == True` then the the service is expected to run indefinitely
and will trigger cancellation if the service finishes.
"""
...
@abstractmethod
def run_daemon_child_service(
self, service: ServiceAPI, name: str | None = None
) -> "ManagerAPI":
"""
Run a daemon service in the background.
Equivalent to `run_child_service(..., daemon=True)`.
"""
...