Files
onepilot/frogpilot/third_party/reactivex/operators/_join.py
T
firestar5683 d0e1db6766 StarPilot
2026-03-22 03:15:05 -05:00

145 lines
4.5 KiB
Python

from collections import OrderedDict
from typing import Any, Callable, Optional, Tuple, TypeVar
from reactivex import Observable, abc
from reactivex.disposable import CompositeDisposable, SingleAssignmentDisposable
from reactivex.internal import noop
from reactivex.operators import take
_T1 = TypeVar("_T1")
_T2 = TypeVar("_T2")
def join_(
right: Observable[_T2],
left_duration_mapper: Callable[[Any], Observable[Any]],
right_duration_mapper: Callable[[Any], Observable[Any]],
) -> Callable[[Observable[_T1]], Observable[Tuple[_T1, _T2]]]:
def join(source: Observable[_T1]) -> Observable[Tuple[_T1, _T2]]:
"""Correlates the elements of two sequences based on
overlapping durations.
Args:
source: Source observable.
Return:
An observable sequence that contains elements
combined into a tuple from source elements that have an overlapping
duration.
"""
left = source
def subscribe(
observer: abc.ObserverBase[Tuple[_T1, _T2]],
scheduler: Optional[abc.SchedulerBase] = None,
) -> abc.DisposableBase:
group = CompositeDisposable()
left_done = False
left_map: OrderedDict[int, _T1] = OrderedDict()
left_id = 0
right_done = False
right_map: OrderedDict[int, _T2] = OrderedDict()
right_id = 0
def on_next_left(value: _T1):
nonlocal left_id
duration = None
current_id = left_id
left_id += 1
md = SingleAssignmentDisposable()
left_map[current_id] = value
group.add(md)
def expire():
if current_id in left_map:
del left_map[current_id]
if not len(left_map) and left_done:
observer.on_completed()
group.remove(md)
try:
duration = left_duration_mapper(value)
except Exception as exception:
observer.on_error(exception)
return
md.disposable = duration.pipe(take(1)).subscribe(
noop, observer.on_error, lambda: expire(), scheduler=scheduler
)
for val in right_map.values():
result = (value, val)
observer.on_next(result)
def on_completed_left() -> None:
nonlocal left_done
left_done = True
if right_done or not len(left_map):
observer.on_completed()
group.add(
left.subscribe(
on_next_left,
observer.on_error,
on_completed_left,
scheduler=scheduler,
)
)
def on_next_right(value: _T2):
nonlocal right_id
duration = None
current_id = right_id
right_id += 1
md = SingleAssignmentDisposable()
right_map[current_id] = value
group.add(md)
def expire():
if current_id in right_map:
del right_map[current_id]
if not len(right_map) and right_done:
observer.on_completed()
group.remove(md)
try:
duration = right_duration_mapper(value)
except Exception as exception:
observer.on_error(exception)
return
md.disposable = duration.pipe(take(1)).subscribe(
noop, observer.on_error, lambda: expire(), scheduler=scheduler
)
for val in left_map.values():
result = (val, value)
observer.on_next(result)
def on_completed_right():
nonlocal right_done
right_done = True
if left_done or not len(right_map):
observer.on_completed()
group.add(
right.subscribe(
on_next_right,
observer.on_error,
on_completed_right,
scheduler=scheduler,
)
)
return group
return Observable(subscribe)
return join
__all__ = ["join_"]