_tasks.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from __future__ import annotations
  2. import sys
  3. from abc import ABCMeta, abstractmethod
  4. from types import TracebackType
  5. from typing import TYPE_CHECKING, Any, Awaitable, Callable, TypeVar, overload
  6. from warnings import warn
  7. if sys.version_info >= (3, 8):
  8. from typing import Protocol
  9. else:
  10. from typing_extensions import Protocol
  11. if TYPE_CHECKING:
  12. from anyio._core._tasks import CancelScope
  13. T_Retval = TypeVar("T_Retval")
  14. T_contra = TypeVar("T_contra", contravariant=True)
  15. class TaskStatus(Protocol[T_contra]):
  16. @overload
  17. def started(self: TaskStatus[None]) -> None:
  18. ...
  19. @overload
  20. def started(self, value: T_contra) -> None:
  21. ...
  22. def started(self, value: T_contra | None = None) -> None:
  23. """
  24. Signal that the task has started.
  25. :param value: object passed back to the starter of the task
  26. """
  27. class TaskGroup(metaclass=ABCMeta):
  28. """
  29. Groups several asynchronous tasks together.
  30. :ivar cancel_scope: the cancel scope inherited by all child tasks
  31. :vartype cancel_scope: CancelScope
  32. """
  33. cancel_scope: CancelScope
  34. async def spawn(
  35. self,
  36. func: Callable[..., Awaitable[Any]],
  37. *args: object,
  38. name: object = None,
  39. ) -> None:
  40. """
  41. Start a new task in this task group.
  42. :param func: a coroutine function
  43. :param args: positional arguments to call the function with
  44. :param name: name of the task, for the purposes of introspection and debugging
  45. .. deprecated:: 3.0
  46. Use :meth:`start_soon` instead. If your code needs AnyIO 2 compatibility, you
  47. can keep using this until AnyIO 4.
  48. """
  49. warn(
  50. 'spawn() is deprecated -- use start_soon() (without the "await") instead',
  51. DeprecationWarning,
  52. )
  53. self.start_soon(func, *args, name=name)
  54. @abstractmethod
  55. def start_soon(
  56. self,
  57. func: Callable[..., Awaitable[Any]],
  58. *args: object,
  59. name: object = None,
  60. ) -> None:
  61. """
  62. Start a new task in this task group.
  63. :param func: a coroutine function
  64. :param args: positional arguments to call the function with
  65. :param name: name of the task, for the purposes of introspection and debugging
  66. .. versionadded:: 3.0
  67. """
  68. @abstractmethod
  69. async def start(
  70. self,
  71. func: Callable[..., Awaitable[Any]],
  72. *args: object,
  73. name: object = None,
  74. ) -> Any:
  75. """
  76. Start a new task and wait until it signals for readiness.
  77. :param func: a coroutine function
  78. :param args: positional arguments to call the function with
  79. :param name: name of the task, for the purposes of introspection and debugging
  80. :return: the value passed to ``task_status.started()``
  81. :raises RuntimeError: if the task finishes without calling ``task_status.started()``
  82. .. versionadded:: 3.0
  83. """
  84. @abstractmethod
  85. async def __aenter__(self) -> TaskGroup:
  86. """Enter the task group context and allow starting new tasks."""
  87. @abstractmethod
  88. async def __aexit__(
  89. self,
  90. exc_type: type[BaseException] | None,
  91. exc_val: BaseException | None,
  92. exc_tb: TracebackType | None,
  93. ) -> bool | None:
  94. """Exit the task group context waiting for all tasks to finish."""