50 lines
1.4 KiB
Python
50 lines
1.4 KiB
Python
import asyncio
|
|
from asyncio import Future
|
|
from typing import Any, Optional, TypeVar, cast
|
|
|
|
from reactivex import Observable, abc
|
|
from reactivex.disposable import Disposable
|
|
|
|
_T = TypeVar("_T")
|
|
|
|
|
|
def from_future_(future: "Future[_T]") -> Observable[_T]:
|
|
"""Converts a Future to an Observable sequence
|
|
|
|
Args:
|
|
future -- A Python 3 compatible future.
|
|
https://docs.python.org/3/library/asyncio-task.html#future
|
|
|
|
Returns:
|
|
An Observable sequence which wraps the existing future success
|
|
and failure.
|
|
"""
|
|
|
|
def subscribe(
|
|
observer: abc.ObserverBase[Any], scheduler: Optional[abc.SchedulerBase] = None
|
|
) -> abc.DisposableBase:
|
|
def done(future: "Future[_T]") -> None:
|
|
try:
|
|
value: Any = future.result()
|
|
except Exception as ex:
|
|
observer.on_error(ex)
|
|
except asyncio.CancelledError as ex: # pylint: disable=broad-except
|
|
# asyncio.CancelledError is a BaseException, so need to cast
|
|
observer.on_error(cast(Exception, ex))
|
|
else:
|
|
observer.on_next(value)
|
|
observer.on_completed()
|
|
|
|
future.add_done_callback(done)
|
|
|
|
def dispose() -> None:
|
|
if future:
|
|
future.cancel()
|
|
|
|
return Disposable(dispose)
|
|
|
|
return Observable(subscribe)
|
|
|
|
|
|
__all__ = ["from_future_"]
|