Repository: ReactiveX/RxPY (Python)

Issue:
from_marbles never returns when using Observable.__await__
The following code waits forever,
```python
import asyncio
import rx
import rx.operators as op
import time


source1: rx.Observable = rx.from_marbles('a-b-3-4-|', )

async def main(loop):
    x = source1.subscribe(
        on_next = lambda i: print("1: {0}".format(i)),
        on_error = lambda e: print("Error Occurred: {0}".format(e)),
        on_completed = lambda: print("1 Done!"),
    )
    await source1


loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
loop.close()
print('end')
```
but replacing `await source1` with `source1.run()` works as expected.
This problem occurs only with `rx.from_marbles` and `rx.hot`, 
the following code works as expected
```python
import asyncio
import rx
import rx.operators as op
import time
from rx.scheduler import ThreadPoolScheduler, NewThreadScheduler

scheduler = ThreadPoolScheduler(2)
scheduler = NewThreadScheduler()

def emitter(observer: rx.typing.Observer, _):
    observer.on_next('a')
    time.sleep(.2)
    observer.on_next('b')
    observer.on_completed()

source2 = rx.create(emitter)

async def main(loop):
    x = source2.subscribe(
        on_next = lambda i: print("2: {0}".format(i)),
        on_error = lambda e: print("Error Occurred: {0}".format(e)),
        on_completed = lambda: print("2 Done!"),
        # scheduler=scheduler,
    )
    await source2


loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
loop.close()
print('end')
```
Using python 3.7.2 and `rx==3.0.1`


Discussion:
Hi,
I've investigated a bit this issue and I'm pretty sure that it fails when using any operator that is based on relative scheduling, i.e.: 
```python
source1 = rx.from_marbles('a-b-3-4-|',  )
source1 = rx.interval(0.2).pipe(op.take(5))
source1 = rx.generate_with_relative_time(0, lambda x: x <5, lambda x: x+1, lambda x: 0.050)
source1 = rx.range(0, 5).pipe(op.delay(0.5))
```

I'm not familliar with Asyncio, but it seems to work by specifying as a source parameter an AsyncIOScheduler bound to the current asyncio loop. So that might be a short term solution for you.

``` python
import asyncio
import rx
from rx.scheduler.eventloop import AsyncIOScheduler

loop = asyncio.get_event_loop()
scheduler = AsyncIOScheduler(loop)
source1: rx.Observable = rx.from_marbles('a-b-3-4-|',  scheduler=scheduler)

async def main(loop):
    x = source1.subscribe(
        on_next = lambda i: print("1: {0}".format(i)),
        on_error = lambda e: print("Error Occurred: {0}".format(e)),
        on_completed = lambda: print("1 Done!"),
        )
    await source1

loop.run_until_complete(main(loop))
loop.close()
print('end')
```

Also, @MainRo @dbrattli  , I've tryied to add an operator using relative scheduling (`delay`) in 'await' example, and it fails to terminate. So there should be something wrong here with asyncio? I guess this is because `await` does not give any scheduler to the subscription?

```python
import asyncio
import rx
import rx.operators as ops

stream = rx.just("Hello, world!").pipe(ops.delay(0.5))


async def hello_world():
    n = await stream
    print(n)

loop = asyncio.get_event_loop()
# Blocking call which returns when the hello_world() coroutine is done
loop.run_until_complete(hello_world())
loop.close()
```


When using asyncio you have to use an AsyncIOScheduler for any operation that involves io or time. So you have to provide an AsyncioScheduler to the from_marble call.
Note that this scheduler is automatically forwarded if it is provided as a parameter to subscribe. However when using await, the subscription is done with no scheduler. So in the first example, from_marbles uses a NewThreadScheduler to delay the item emission. On the other side, the future created to wait in _await_ is an asyncio future, meaning that it is an error to call its set_result method from another thread than the event loop. So when from_marble tries to emit an item, an exception is thrown. You can see it be enabling the debug of the event loop:

```
loop = asyncio.get_event_loop()
loop.set_debug(enabled=True)
source1: rx.Observable = rx.from_marbles('a-b-3-4-|')
``` 

The example using run seems to work but in fact it blocks the event loop until the observable completes. Moreover run returns a value not a future, so you cannot _await_ it. You can also see this error with a set_debug.

It is strange that these errors are ignored by asyncio when debugging is disabled.

So for me the code works as expected. We may improve things by using an AsyncIOScheduler in Observable.\_\_await\_\_ Your example would work by subscribing with an AsyncioScheduler on the current event loop.

Also note that the example subscribes twice to the observable: The first time on the x.subscribe call, and the second time on the await call.
tagging this as a bug: I think that await should subscribe with an AsyncioScheduler so that the await keyword works directly on an Observable.



Patch:
diff --git a/rx/core/observable/observable.py b/rx/core/observable/observable.py
index 11ba9a693..f3f0be898 100644
--- a/rx/core/observable/observable.py
+++ b/rx/core/observable/observable.py
@@ -1,9 +1,11 @@
 # By design, pylint: disable=C0302
 import threading
+import asyncio
 from typing import Any, Callable, Optional, Union, TypeVar, cast, overload
 
 from rx.disposable import Disposable
 from rx.scheduler import CurrentThreadScheduler
+from rx.scheduler.eventloop import AsyncIOScheduler
 
 from ..observer import AutoDetachObserver
 from .. import typing, abc
@@ -290,7 +292,8 @@ def __await__(self) -> Any:
             The last item of the observable sequence.
         """
         from ..operators.tofuture import _to_future
-        return iter(self.pipe(_to_future()))
+        loop = asyncio.get_event_loop()
+        return iter(self.pipe(_to_future(scheduler=AsyncIOScheduler(loop=loop))))
 
     def __add__(self, other) -> 'Observable':
         """Pythonic version of :func:`concat <rx.concat>`.
diff --git a/rx/core/operators/tofuture.py b/rx/core/operators/tofuture.py
index ef3516ac0..d9cad7a76 100644
--- a/rx/core/operators/tofuture.py
+++ b/rx/core/operators/tofuture.py
@@ -1,11 +1,13 @@
 from typing import Callable, Optional
 from asyncio import Future
 
+from .. import typing
 from rx.core import Observable
 from rx.internal.exceptions import SequenceContainsNoElementsError
 
 
-def _to_future(future_ctor: Optional[Callable[[], Future]] = None) -> Callable[[Observable], Future]:
+def _to_future(future_ctor: Optional[Callable[[], Future]] = None,
+               scheduler: Optional[typing.Scheduler] = None) -> Callable[[Observable], Future]:
     future_ctor = future_ctor or Future
     future = future_ctor()
 
@@ -44,7 +46,7 @@ def on_completed():
             else:
                 future.set_exception(SequenceContainsNoElementsError())
 
-        source.subscribe_(on_next, on_error, on_completed)
+        source.subscribe_(on_next, on_error, on_completed, scheduler=scheduler)
 
         # No cancellation can be done
         return future


Test patch:
diff --git a/tests/test_observable/test_tofuture.py b/tests/test_observable/test_tofuture.py
index a8122dc85..679c92a23 100644
--- a/tests/test_observable/test_tofuture.py
+++ b/tests/test_observable/test_tofuture.py
@@ -3,6 +3,7 @@
 import asyncio
 
 import rx
+import rx.operators as ops
 from rx.internal.exceptions import SequenceContainsNoElementsError
 from rx.testing import ReactiveTest
 
@@ -66,3 +67,15 @@ async def go():
             result = await source
 
         self.assertRaises(SequenceContainsNoElementsError, loop.run_until_complete, go())
+
+    def test_await_with_delay(self):
+        loop = asyncio.get_event_loop()
+        result = None
+
+        async def go():
+            nonlocal result
+            source = rx.return_value(42).pipe(ops.delay(0.1))
+            result = await source
+
+        loop.run_until_complete(go())
+        assert result == 42