def if_then(cls, condition, then_source, else_source=None, scheduler=None): """Determines whether an observable collection contains values. Example: 1 - res = rx.Observable.if(condition, obs1) 2 - res = rx.Observable.if(condition, obs1, obs2) 3 - res = rx.Observable.if(condition, obs1, scheduler=scheduler) Keyword parameters: condition -- {Function} The condition which determines if the then_source or else_source will be run. then_source -- {Observable} The observable sequence or Promise that will be run if the condition function returns true. else_source -- {Observable} [Optional] The observable sequence or Promise that will be run if the condition function returns False. If this is not provided, it defaults to Rx.Observabe.Empty scheduler -- [Optional] Scheduler to use. Returns an observable {Observable} sequence which is either the then_source or else_source.""" else_source = else_source or Observable.empty(scheduler=scheduler) then_source = Observable.from_future(then_source) else_source = Observable.from_future(else_source) def factory(): return then_source if condition() else else_source return Observable.defer(factory)
def test_example(self): future = self.loop.create_future() expected_result = [42] expected_error = None actual_result = [] actual_error = None def on_next(i): actual_result.append(i) def on_error(e): nonlocal actual_error actual_error = e def on_completed(): self.loop.stop() Observable.from_future(future).subscribe(on_next=on_next, on_error=on_error, on_completed=on_completed) self.assertEqual([], actual_result) self.loop.call_soon(lambda: future.set_result(42)) self.loop.run_forever() self.assertEqual(expected_result, actual_result)
def connect(self): def on_connect(conn): self.conn = conn self.opened.on_next(conn) self.opened.on_completed() self.opened.dispose() future = websocket_connect( self._url, on_message_callback=lambda mess: self.messages.on_next(mess)) Observable.from_future(future).subscribe(on_connect)
def resolve_items(root, info) -> Observable: ''' Returns subscription updates with the following shape: { changeType: one of Initial, Add, Mod, Remove value: of type item_class } Create a field with MakeSubscriptionWithChangeType(type) :param info: :return: ''' async def iterable_to_items(): async with ReDBConnection().get_async_connection() as conn: table = db.table(table_name) changes = await table.pluck(*item_class._meta.fields.keys()).changes(include_types=True, include_initial=True).run(conn) while True: change = await changes.next() if not change: break if change['type'] == 'remove': value = change['old_val'] else: value = change['new_val'] value = item_class(**value) yield MakeSubscriptionWithChangeType(item_class)(change_type=str_to_changetype(change['type']), value=value) return Observable.from_future(iterable_to_items())
def projection(x, i): selector_result = selector(x, i) if isinstance(selector_result, collections.Iterable): result = Observable.from_(selector_result) else: result = Observable.from_future(selector_result) return result
def _fetch_hub_detail_and_unpack_to_caps(self, hub_url) -> Observable: def on_error(e): logger.error("fail to fetch nodes by url: %s, %s", hub_url, str(e)) return Observable.empty() @on_exception_return(on_error) def unpack_node(node): appium_netloc = self._get_base_url(node['id']) hub_netloc = self._get_base_url(hub_url) malform_dto = node['protocols']['web_driver']['browsers'][''] if 'name' in malform_dto: del malform_dto['name'] if 'version' in malform_dto: del malform_dto['version'] cap_lists = malform_dto.values() # list of cap_lists return Observable.from_(cap_lists) \ .flat_map(lambda cap_list: Observable.from_(cap_list)) \ .map(lambda cap: {**cap, 'appium_url': appium_netloc, 'hub_url': hub_netloc}) @on_exception_return(on_error) def unpack_hub(hub_detail): return Observable.from_(hub_detail['nodes']) future = convert_yielded( self._selenium_grid_client.get_devices_by_hub_url_async(hub_url)) return Observable.from_future(future) \ .map(lambda res: json.loads(res.body)) \ .catch_exception(handler=on_error) \ .flat_map(unpack_hub) \ .flat_map(unpack_node)
def resolve_item(root, info, **args) -> Observable: ''' Create a field with MakeSubscription(type) :param root: :param info: :param args: :return: ''' async def iterable_to_item(): async with ReDBConnection().get_async_connection() as conn: key = args.get(key_name, None) if not key: yield None return table = db.table(table_name) changes = await table.get_all(key) \ .pluck(*item_class._meta.fields)\ .changes(include_types=True, include_initial=True).run(conn) while True: change = await changes.next() if not change: break if change['type'] == 'remove' or change['new_val'] is None: yield None continue else: value = change['new_val'] yield item_class(**value) return Observable.from_future(iterable_to_item())
def connect_to_server(self, host, port): def on_connect(conn): self.matching_server_connection = conn print("Connected to matching server") def on_message_callback(message): if message is None: self.matching_server_connection = None self.connect_to_server() else: self.message.on_next(message) future = websocket_connect( 'ws://{}:{}/exchange'.format(host, port), on_message_callback=on_message_callback ) Observable.from_future(future).subscribe(on_connect, lambda error: self.connect_to_next_server())
def factory(): try: result = sources[selector()] except KeyError: result = default_source result = Observable.from_future(result) return result
def connect(self): def on_connect(conn): print('on_connect') self.conn = conn self.opened.on_next(conn) self.opened.on_completed() self.opened.dispose() def on_message_callback(message): # print('on_message_callback') self.messages.on_next(message) print('connect to server') future = websocket_connect( self._url, on_message_callback=on_message_callback, ) Observable.from_future(future).subscribe(on_connect)
def exec(self, func, items): observables = [] with concurrent.futures.ProcessPoolExecutort() as executor: for item in items.values(): _future = executor.submit(func, item) observables.append(Observable.from_future(_future)) all_observables = Observable.merge(observables) all_observables.subscribe(self._on_success, self._on_error, self._on_complete)
def _fetch_appium_sessions(self, appium_url) -> Observable: def on_error(e): logger.error("fail to fetch appium sessions by url: %s, %s", appium_url, str(e)) return Observable.empty() future = convert_yielded(self._appium_client.get_sessions(appium_url)) return Observable.from_future(future) \ .map(lambda res: json.loads(res.body)) \ .catch_exception(handler=on_error) \ .flat_map(lambda data: Observable.from_(data['value'])) \ .map(lambda cap: (appium_url, cap))
def handle(self, request, next_handlers): # use asyncio event loop & coroutine to process requests async def process(content: bytes) -> HttpResponse: logger.debug('start processing %s', content) await asyncio.sleep(1) logger.debug('end processing %s', content) return HttpResponse(200, b'OK', content=b'[' + (content or b'-empty-') + b']') return self.load_content(request) \ .flat_map(lambda content: Observable.from_future(self.loop.create_task(process(content))))
def go(): future = Future() future.set_result(42) source = Observable.from_future(future) def on_next(x): success[0] = 42 == x def on_error(err): success[1] = False def on_completed(): success[2] = True subscription = source.subscribe(on_next, on_error, on_completed)
def get_data(self, query): # Observable создается из списка url return Observable.from_list( self.urls ).flat_map( # Для каждого url создается observable, который загружает данные lambda url: Observable.from_future(self.get_rss(url)) ).flat_map( # Полученные данные парсятся, из них создается observable lambda x: Observable.from_list( feedparser.parse(x.body)['entries'] ).filter( # Фильтрует по вхождению запроса в заголовок или текст новости lambda val, i: query in val.title or query in val.summary ).take(5) # Берем только по 5 новостей по каждому url ).map(lambda x: {'title': x.title, 'link': x.link, 'published': x.published, 'summary': x.summary})
def go(): error = Exception('woops') future = Future() future.set_exception(error) source = Observable.from_future(future) def on_next(x): success[0] = False def on_error(err): success[1] = str(err) == str(error) def on_completed(): success[2] = False subscription = source.subscribe(on_next, on_error, on_completed)
def get_data(self, query): # Observable создается из списка url return Observable.from_list(self.urls).flat_map( # Для каждого url создается observable, который загружает данные lambda url: Observable.from_future(self.get_rss(url)) ).flat_map( # Полученные данные парсятся, из них создается observable lambda x: Observable. from_list(feedparser.parse(x.body)['entries']).filter( # Фильтрует по вхождению запроса в заголовок или текст новости lambda val, i: query in val.title or query in val.summary ).take(5) # Берем только по 5 новостей по каждому url ).map( lambda x: { 'title': x.title, 'link': x.link, 'published': x.published, 'summary': x.summary })
def get_data(self, query): """ query the data to the API and return the contet filtered""" return Observable.from_list(self.orgs).flat_map( lambda name: Observable.from_future(self.get_org_repos(name)) ).flat_map(lambda x: Observable.from_list( self.get_info(x) #transform the response to a json list ).filter(lambda val: (val.get("description") is not None and (val.get( "description").lower()).find(query.lower()) != -1) or (val.get("language") is not None and (val.get("language").lower()).find(query.lower()) != -1)). take(10) #just take 10 repos from each org ).map( lambda x: { 'name': x.get("name"), 'stars': str(x.get("stargazers_count")), 'link': x.get("svn_url"), 'description': x.get("description"), 'language': x.get("language") })
def get_data(self,query): """ query the data to the API and return the contet filtered""" return Observable.from_list( self.orgs ).flat_map( lambda name: Observable.from_future(self.get_org_repos(name)) ).flat_map( lambda x: Observable.from_list( self.get_info(x) #transform the response to a json list ).filter( lambda val: (val.get("description") is not None and (val.get("description").lower()).find(query.lower())!= -1) or (val.get("language") is not None and (val.get("language").lower()).find(query.lower())!= -1) ).take(10) #just take 10 repos from each org ).map(lambda x: {'name': x.get("name"), 'stars': str(x.get("stargazers_count")), 'link': x.get("svn_url"),'description': x.get("description"), 'language': x.get("language")})
def projection(x, i): selector_result = selector(x, i) result = Observable.from_future(selector_result) return result.map(lambda y: result_selector(x, y, i))
def __amb(self, right_source): """Propagates the observable sequence that reacts first. right_source Second observable sequence. returns an observable sequence that surfaces either of the given sequences, whichever reacted first. """ left_source = self right_source = Observable.from_future(right_source) def subscribe(observer): choice = [None] left_choice = 'L' right_choice = 'R', left_subscription = SingleAssignmentDisposable() right_subscription = SingleAssignmentDisposable() def choice_left(): if not choice[0]: choice[0] = left_choice right_subscription.dispose() def choice_right(): if not choice[0]: choice[0] = right_choice left_subscription.dispose() def on_next_left(value): with self.lock: choice_left() if choice[0] == left_choice: observer.on_next(value) def on_error_left(err): with self.lock: choice_left() if choice[0] == left_choice: observer.on_error(err) def on_completed_left(): with self.lock: choice_left() if choice[0] == left_choice: observer.on_completed() ld = left_source.subscribe(on_next_left, on_error_left, on_completed_left) left_subscription.disposable = ld def on_next_right(value): with self.lock: choice_right() if choice[0] == right_choice: observer.on_next(value) def on_error_right(err): with self.lock: choice_right() if choice[0] == right_choice: observer.on_error(err) def on_completed_right(): with self.lock: choice_right() if choice[0] == right_choice: observer.on_completed() rd = right_source.subscribe(on_next_right, on_error_right, on_completed_right) right_subscription.disposable = rd return CompositeDisposable(left_subscription, right_subscription) return AnonymousObservable(subscribe)
def request(method, url, **kw): future = asyncio.ensure_future(aiohttp.request(method, url, **kw)) return Observable.from_future(future)
def projection(x, i): result = selector(x, i) return Observable.from_future(result)
def amb(self, right_source): """Propagates the observable sequence that reacts first. right_source Second observable sequence. returns an observable sequence that surfaces either of the given sequences, whichever reacted first. """ left_source = self right_source = Observable.from_future(right_source) def subscribe(observer): choice = [None] left_choice = 'L' right_choice = 'R', left_subscription = SingleAssignmentDisposable() right_subscription = SingleAssignmentDisposable() def choice_left(): if not choice[0]: choice[0] = left_choice right_subscription.dispose() def choice_right(): if not choice[0]: choice[0] = right_choice left_subscription.dispose() def on_next_left(value): with self.lock: choice_left() if choice[0] == left_choice: observer.on_next(value) def on_error_left(err): with self.lock: choice_left() if choice[0] == left_choice: observer.on_error(err) def on_completed_left(): with self.lock: choice_left() if choice[0] == left_choice: observer.on_completed() ld = left_source.subscribe(on_next_left, on_error_left, on_completed_left) left_subscription.disposable = ld def on_next_right(value): with self.lock: choice_right() if choice[0] == right_choice: observer.on_next(value) def on_error_right(err): with self.lock: choice_right() if choice[0] == right_choice: observer.on_error(err) def on_completed_right(): with self.lock: choice_right() if choice[0] == right_choice: observer.on_completed() rd = right_source.subscribe(on_next_right, on_error_right, on_completed_right) right_subscription.disposable = rd return CompositeDisposable(left_subscription, right_subscription) return AnonymousObservable(subscribe)
from rx import Observable import asyncio async def foo(future): await asyncio.sleep(1) future.set_result(2) loop = asyncio.get_event_loop() done = loop.create_future() asyncio.ensure_future(foo(done)) number = Observable.from_future(done) print("subscribing...") number.subscribe( lambda i: print("on_next: {}".format(i)), lambda e: print("on_error: {}".format(e)), lambda: print("on_completed") ) print("staring mainloop") loop.run_until_complete(done) loop.close()