@@ -581,175 +581,6 @@ def __init__( # pylint: disable=too-many-arguments
581581 if auto_start :
582582 self .reset (start_delay = start_delay )
583583
584- # We need a noqa here because the docs have a Raises section but the documented
585- # exceptions are raised indirectly.
586- @classmethod
587- def timeout ( # noqa: DOC502
588- cls ,
589- delay : timedelta ,
590- / ,
591- * ,
592- auto_start : bool = True ,
593- start_delay : timedelta = timedelta (0 ),
594- loop : asyncio .AbstractEventLoop | None = None ,
595- ) -> Timer :
596- """Create a timer useful for tracking timeouts.
597-
598- A [timeout][frequenz.channels.timer.Timer.timeout] is
599- a [`Timer`][frequenz.channels.timer.Timer] that
600- [resets][frequenz.channels.timer.Timer.reset] automatically after it triggers,
601- so it will trigger again after the selected interval, no matter what the current
602- drift was. This means timeout timers will accumulate drift.
603-
604- Tip:
605- Timeouts are a shortcut to create
606- a [`Timer`][frequenz.channels.timer.Timer] with the
607- [`SkipMissedAndDrift`][frequenz.channels.timer.SkipMissedAndDrift] policy.
608-
609- Example: Timeout example
610- ```python
611- import asyncio
612- from datetime import timedelta
613-
614- from frequenz.channels import Anycast, select, selected_from
615- from frequenz.channels.timer import Timer
616-
617-
618- async def main() -> None:
619- channel = Anycast[int](name="data-channel")
620- data_receiver = channel.new_receiver()
621-
622- timer = Timer.timeout(timedelta(seconds=1.0))
623-
624- async for selected in select(data_receiver, timer):
625- if selected_from(selected, data_receiver):
626- print(f"Received data: {selected.value}")
627- elif selected_from(selected, timer):
628- drift = selected.value
629- print(f"No data received for {timer.interval + drift} seconds, giving up")
630- break
631-
632-
633- asyncio.run(main())
634- ```
635-
636- Args:
637- delay: The time until the timer ticks. Must be at least
638- 1 microsecond.
639- auto_start: Whether the timer should be started when the
640- instance is created. This can only be `True` if there is
641- already a running loop or an explicit `loop` that is running
642- was passed.
643- start_delay: The delay before the timer should start. If `auto_start` is
644- `False`, an exception is raised. This has microseconds resolution,
645- anything smaller than a microsecond means no delay.
646- loop: The event loop to use to track time. If `None`,
647- `asyncio.get_running_loop()` will be used.
648-
649- Returns:
650- The timer instance.
651-
652- Raises:
653- RuntimeError: if it was called without a loop and there is no
654- running loop.
655- ValueError: if `interval` is not positive or is smaller than 1
656- microsecond; if `start_delay` is negative or `start_delay` was specified
657- but `auto_start` is `False`.
658- """
659- return Timer (
660- delay ,
661- SkipMissedAndDrift (delay_tolerance = timedelta (0 )),
662- auto_start = auto_start ,
663- start_delay = start_delay ,
664- loop = loop ,
665- )
666-
667- # We need a noqa here because the docs have a Raises section but the documented
668- # exceptions are raised indirectly.
669- @classmethod
670- def periodic ( # noqa: DOC502 pylint: disable=too-many-arguments
671- cls ,
672- period : timedelta ,
673- / ,
674- * ,
675- skip_missed_ticks : bool = False ,
676- auto_start : bool = True ,
677- start_delay : timedelta = timedelta (0 ),
678- loop : asyncio .AbstractEventLoop | None = None ,
679- ) -> Timer :
680- """Create a periodic timer.
681-
682- A [periodic timer][frequenz.channels.timer.Timer.periodic] is
683- a [`Timer`][frequenz.channels.timer.Timer] that tries as hard as possible to
684- trigger at regular intervals. This means that if the timer is delayed for any
685- reason, it will trigger immediately and then try to catch up with the original
686- schedule.
687-
688- Optionally, a periodic timer can be configured to skip missed ticks and re-sync
689- with the original schedule (`skip_missed_ticks` argument). This could be useful
690- if you want the timer is as periodic as possible but if there are big delays you
691- don't end up with big bursts.
692-
693- Tip:
694- Periodic timers are a shortcut to create
695- a [`Timer`][frequenz.channels.timer.Timer] with either the
696- [`TriggerAllMissed`][frequenz.channels.timer.TriggerAllMissed] policy (when
697- `skip_missed_ticks` is `False`) or
698- [`SkipMissedAndResync`][frequenz.channels.timer.SkipMissedAndResync]
699- otherwise.
700-
701- Example:
702- ```python
703- import asyncio
704- from datetime import datetime, timedelta
705-
706- from frequenz.channels.timer import Timer
707-
708-
709- async def main() -> None:
710- async for drift in Timer.periodic(timedelta(seconds=1.0)):
711- print(f"The timer has triggered at {datetime.now()} with a drift of {drift}")
712-
713-
714- asyncio.run(main())
715- ```
716-
717- Args:
718- period: The time between timer ticks. Must be at least
719- 1 microsecond.
720- skip_missed_ticks: Whether to skip missed ticks or trigger them
721- all until it catches up.
722- auto_start: Whether the timer should be started when the
723- instance is created. This can only be `True` if there is
724- already a running loop or an explicit `loop` that is running
725- was passed.
726- start_delay: The delay before the timer should start. If `auto_start` is
727- `False`, an exception is raised. This has microseconds resolution,
728- anything smaller than a microsecond means no delay.
729- loop: The event loop to use to track time. If `None`,
730- `asyncio.get_running_loop()` will be used.
731-
732- Returns:
733- The timer instance.
734-
735- Raises:
736- RuntimeError: if it was called without a loop and there is no
737- running loop.
738- ValueError: if `interval` is not positive or is smaller than 1
739- microsecond; if `start_delay` is negative or `start_delay` was specified
740- but `auto_start` is `False`.
741- """
742- missed_tick_policy = (
743- SkipMissedAndResync () if skip_missed_ticks else TriggerAllMissed ()
744- )
745- return Timer (
746- period ,
747- missed_tick_policy ,
748- auto_start = auto_start ,
749- start_delay = start_delay ,
750- loop = loop ,
751- )
752-
753584 @property
754585 def interval (self ) -> timedelta :
755586 """The interval between timer ticks.
0 commit comments