22import asyncio
33import logging
44import sys
5- from asyncio .locks import Event
6- from contextlib import AsyncExitStack , ExitStack
75from datetime import tzinfo
86from functools import wraps
97from time import monotonic , perf_counter
108from types import TracebackType
119from typing import (
1210 Any ,
13- AsyncContextManager ,
1411 AsyncIterator ,
1512 Awaitable ,
1613 Callable ,
1714 ClassVar ,
1815 ContextManager ,
19- Coroutine ,
2016 Dict ,
17+ Generator ,
2118 Iterable ,
2219 List ,
2320 Mapping ,
3330
3431from .timers import Timer
3532from .types import DiagT , ServiceT
33+ from .utils .contexts import AsyncExitStack , ExitStack
3634from .utils .cron import secs_for_next
35+ from .utils .locks import Event
3736from .utils .logging import CompositeLogger , get_logger , level_number
3837from .utils .objects import iter_mro_reversed , qualname
3938from .utils .text import maybecat
4039from .utils .times import Seconds , want_seconds
4140from .utils .tracebacks import format_task_stack
4241from .utils .trees import Node
4342from .utils .types .trees import NodeT
43+ from .utils .typing import AsyncContextManager
4444
45- __all__ = ["ServiceBase" , "Service" , "Diag" , "task" , "timer" , "crontab" ]
45+ __all__ = [
46+ "ServiceBase" ,
47+ "Service" ,
48+ "Diag" ,
49+ "task" ,
50+ "timer" ,
51+ ]
4652
4753ClockArg = Callable [[], float ]
4854
4955#: Future type: Different types of awaitables.
50- FutureT = Union [asyncio .Future , Coroutine [Any , None , Any ], Awaitable ]
56+ FutureT = Union [asyncio .Future , Generator [Any , None , Any ], Awaitable ]
5157
5258#: Argument type for ``Service.wait(*events)``
5359#: Wait can take any number of futures or events to wait for.
54- WaitArgT = Union [FutureT , Event ]
60+ WaitArgT = Union [FutureT , asyncio .Event , Event ]
61+
62+ EVENT_TYPES = (asyncio .Event , Event )
5563
5664
5765class WaitResults (NamedTuple ):
@@ -88,10 +96,10 @@ class ServiceBase(ServiceT):
8896 # the None to logger.
8997 logger : logging .Logger = cast (logging .Logger , None )
9098
91- def __init_subclass__ (cls ) -> None :
92- if cls .abstract :
93- cls .abstract = False
94- cls ._init_subclass_logger ()
99+ def __init_subclass__ (self ) -> None :
100+ if self .abstract :
101+ self .abstract = False
102+ self ._init_subclass_logger ()
95103
96104 @classmethod
97105 def _init_subclass_logger (cls ) -> None :
@@ -138,11 +146,11 @@ def _repr_name(self) -> str:
138146 @property
139147 def loop (self ) -> asyncio .AbstractEventLoop :
140148 if self ._loop is None :
141- self ._loop = asyncio .get_event_loop_policy (). get_event_loop ()
149+ self ._loop = asyncio .get_event_loop ()
142150 return self ._loop
143151
144152 @loop .setter
145- def loop (self , loop : asyncio .AbstractEventLoop ) -> None :
153+ def loop (self , loop : Optional [ asyncio .AbstractEventLoop ] ) -> None :
146154 self ._loop = loop
147155
148156
@@ -223,7 +231,7 @@ class ServiceCallbacks:
223231
224232 When calling ``await service.start()`` this happens:
225233
226- .. code-block :: text
234+ .. sourcecode :: text
227235
228236 +--------------------+
229237 | INIT (not started) |
@@ -247,7 +255,7 @@ class ServiceCallbacks:
247255
248256 When stopping and ``wait_for_shutdown`` is unset, this happens:
249257
250- .. code-block :: text
258+ .. sourcecode :: text
251259
252260 .-----------------------.
253261 / await service.stop() |
@@ -264,7 +272,7 @@ class ServiceCallbacks:
264272 When stopping and ``wait_for_shutdown`` is set, the stop operation
265273 will wait for something to set the shutdown flag ``self.set_shutdown()``:
266274
267- .. code-block :: text
275+ .. sourcecode :: text
268276
269277 .-----------------------.
270278 / await service.stop() |
@@ -285,7 +293,7 @@ class ServiceCallbacks:
285293 When restarting the order is as follows (assuming
286294 ``wait_for_shutdown`` unset):
287295
288- .. code-block :: text
296+ .. sourcecode :: text
289297
290298 .-------------------------.
291299 / await service.restart() |
@@ -503,13 +511,13 @@ async def _and_transition(self: ServiceT, *args: Any, **kwargs: Any) -> Any:
503511
504512 return _decorate
505513
506- def __init_subclass__ (cls ) -> None :
514+ def __init_subclass__ (self ) -> None :
507515 # Every new subclass adds @Service.task decorated methods
508516 # to the class-local `_tasks` list.
509- if cls .abstract :
510- cls .abstract = False
511- cls ._init_subclass_logger ()
512- cls ._init_subclass_tasks ()
517+ if self .abstract :
518+ self .abstract = False
519+ self ._init_subclass_logger ()
520+ self ._init_subclass_tasks ()
513521
514522 @classmethod
515523 def _init_subclass_tasks (cls ) -> None :
@@ -632,7 +640,7 @@ def add_future(self, coro: Awaitable) -> asyncio.Future:
632640 """
633641 fut = asyncio .ensure_future (self ._execute_task (coro ), loop = self .loop )
634642 try :
635- fut .set_name (repr (coro ))
643+ fut .set_name (repr (coro )) # type: ignore
636644 except AttributeError :
637645 pass
638646 fut .__wrapped__ = coro # type: ignore
@@ -690,7 +698,9 @@ async def join_services(self, services: Sequence[ServiceT]) -> None:
690698 for service in reversed (services ):
691699 await service .stop ()
692700
693- async def sleep (self , n : Seconds ) -> None :
701+ async def sleep (
702+ self , n : Seconds , * , loop : asyncio .AbstractEventLoop = None
703+ ) -> None :
694704 """Sleep for ``n`` seconds, or until service stopped."""
695705 try :
696706 await asyncio .wait_for (
@@ -739,7 +749,7 @@ async def wait_first(
739749
740750 futures = {
741751 coro : asyncio .ensure_future (
742- coro if isinstance (coro , Awaitable ) else coro . wait ( ),
752+ ( coro . wait () if isinstance (coro , EVENT_TYPES ) else coro ),
743753 loop = loop ,
744754 )
745755 for coro in coros
0 commit comments