Files
Solax/myenv/lib/python3.12/site-packages/reactivex/testing/testscheduler.py
2024-09-13 09:46:28 +02:00

166 lines
5.8 KiB
Python

from typing import Any, Callable, List, Optional, TypeVar, Union, cast
import reactivex
from reactivex import Observable, abc, typing
from reactivex.disposable import Disposable
from reactivex.scheduler import VirtualTimeScheduler
from reactivex.testing.recorded import Recorded
from .coldobservable import ColdObservable
from .hotobservable import HotObservable
from .mockobserver import MockObserver
from .reactivetest import ReactiveTest
_T = TypeVar("_T")
_TState = TypeVar("_TState")
class TestScheduler(VirtualTimeScheduler):
"""Test time scheduler used for testing applications and libraries
built using Reactive Extensions. All time, both absolute and relative is
specified as integer ticks"""
__test__ = False
def schedule_absolute(
self,
duetime: typing.AbsoluteTime,
action: typing.ScheduledAction[_TState],
state: _TState = None,
) -> abc.DisposableBase:
"""Schedules an action to be executed at the specified virtual
time.
Args:
duetime: Absolute virtual time at which to execute the
action.
action: Action to be executed.
state: State passed to the action to be executed.
Returns:
Disposable object used to cancel the scheduled action
(best effort).
"""
duetime = duetime if isinstance(duetime, float) else self.to_seconds(duetime)
return super().schedule_absolute(duetime, action, state)
def start(
self,
create: Optional[Callable[[], Observable[_T]]] = None,
created: Optional[float] = None,
subscribed: Optional[float] = None,
disposed: Optional[float] = None,
) -> MockObserver[_T]:
"""Starts the test scheduler and uses the specified virtual
times to invoke the factory function, subscribe to the
resulting sequence, and dispose the subscription.
Args:
create: Factory method to create an observable sequence.
created: Virtual time at which to invoke the factory to
create an observable sequence.
subscribed: Virtual time at which to subscribe to the
created observable sequence.
disposed: Virtual time at which to dispose the
subscription.
Returns:
Observer with timestamped recordings of notification
messages that were received during the virtual time window
when the subscription to the source sequence was active.
"""
# Defaults
created = created or ReactiveTest.created
subscribed = subscribed or ReactiveTest.subscribed
disposed = disposed or ReactiveTest.disposed
observer = self.create_observer()
subscription: Optional[abc.DisposableBase] = None
source: Optional[abc.ObservableBase[_T]] = None
def action_create(
scheduler: abc.SchedulerBase, state: Any = None
) -> abc.DisposableBase:
"""Called at create time. Defaults to 100"""
nonlocal source
source = create() if create is not None else reactivex.never()
return Disposable()
self.schedule_absolute(created, action_create)
def action_subscribe(
scheduler: abc.SchedulerBase, state: Any = None
) -> abc.DisposableBase:
"""Called at subscribe time. Defaults to 200"""
nonlocal subscription
if source:
subscription = source.subscribe(observer, scheduler=scheduler)
return Disposable()
self.schedule_absolute(subscribed, action_subscribe)
def action_dispose(
scheduler: abc.SchedulerBase, state: Any = None
) -> abc.DisposableBase:
"""Called at dispose time. Defaults to 1000"""
if subscription:
subscription.dispose()
return Disposable()
self.schedule_absolute(disposed, action_dispose)
super().start()
return observer
def create_hot_observable(
self, *args: Union[Recorded[_T], List[Recorded[_T]]]
) -> HotObservable[_T]:
"""Creates a hot observable using the specified timestamped
notification messages either as a list or by multiple arguments.
Args:
messages: Notifications to surface through the created sequence at
their specified absolute virtual times.
Returns hot observable sequence that can be used to assert the timing
of subscriptions and notifications.
"""
if args and isinstance(args[0], List):
messages = args[0]
else:
messages = cast(List[Recorded[_T]], list(args))
return HotObservable(self, messages)
def create_cold_observable(
self, *args: Union[Recorded[_T], List[Recorded[_T]]]
) -> ColdObservable[_T]:
"""Creates a cold observable using the specified timestamped
notification messages either as an array or arguments.
Args:
args: Notifications to surface through the created sequence
at their specified virtual time offsets from the
sequence subscription time.
Returns:
Cold observable sequence that can be used to assert the
timing of subscriptions and notifications.
"""
if args and isinstance(args[0], list):
messages = args[0]
else:
messages = cast(List[Recorded[_T]], list(args))
return ColdObservable(self, messages)
def create_observer(self) -> MockObserver[Any]:
"""Creates an observer that records received notification messages and
timestamps those. Return an Observer that can be used to assert the
timing of received notifications.
"""
return MockObserver(self)