def start(self): if not self.stopped: return super().start() mouse_source, keyboard_source, engagement_source = self.sources initial_keyboard_event = keyboard.KeyboardEvent(keyboard.KEY_UP, 0) initial_mouse_event = mouse.ButtonEvent(event_type=mouse.UP, button=0, time=time.time()) self.subscriptions = [ mouse_source.output.pipe( operators.start_with(initial_mouse_event)).pipe( operators.combine_latest( keyboard_source.output.pipe( operators.start_with(initial_keyboard_event)), engagement_source.output)).pipe( operators.throttle_first(0.1)) # in seconds .subscribe(self.update) ] if self.window is None: self.window = Window(points=self.points_in_buffer, toggle_callback=self.toggle_recording) self.window.show() self.window.activateWindow() self.window.raise_()
def main(): loop = asyncio.get_event_loop() io_scheduler = AsyncIOThreadSafeScheduler(loop=loop) scheduler = ThreadPoolScheduler(multiprocessing.cpu_count()) semaphore = Subject() semaphore_stream = semaphore.pipe( ops.flat_map(lambda _: rx.of(True).pipe( ops.delay(ARGS.block_time, scheduler=scheduler), ops.start_with(False))), ops.start_with(True)) video_stream_observable = rx.using( lambda: VideoStreamDisposable(), lambda d: rx.from_iterable(video_stream_iterable(d.cap))) gated_video_stream = video_stream_observable.pipe( ops.subscribe_on(scheduler), ops.sample(1 / ARGS.fps), # sample frames based on fps ops.combine_latest(semaphore_stream), ops.filter(lambda tup: tup[1]), # proceed only if semaphore allows ops.map(lambda tup: tup[0]) # take only frame ) disposable = gated_video_stream.pipe( ops.filter(has_face), # filter frames without faces ops.map(lambda frame: Image.fromarray( cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))), # map frame to PIL image ops.map(lambda img: img.resize( (640, 360))), # resize image (inference will be faster) ops.observe_on(io_scheduler), ops.map(lambda img: ImageFacesPair(img, analyse_frame(img)) ), # analyse frame for faces ops.filter(lambda img_faces_pair: any([ face.top_prediction.confidence > ARGS.threshold for face in img_faces_pair.faces ])), # proceed only if there is a known face in the frame ops.throttle_first(1), ops.flat_map(unlock_request), # unlock the door ops.do_action( on_next=lambda _: semaphore.on_next(True) ) # trigger semaphore which will block stream for "block-seconds" seconds (doors are unlocked for that long after unlock request) ).subscribe(on_error=lambda e: logger.exception(e)) try: loop.run_forever() except Exception as e: logger.exception(e) logger.info("Smart lock face recognition engine shutdown") disposable.dispose()
def _reduce(accumulator: Callable[[Any, Any], Any], seed: Any = NotSet) -> Callable[[Observable], Observable]: """Applies an accumulator function over an observable sequence, returning the result of the aggregation as a single element in the result sequence. The specified seed value is used as the initial accumulator value. For aggregation behavior with incremental intermediate results, see `scan()`. Examples: >>> res = reduce(lambda acc, x: acc + x) >>> res = reduce(lambda acc, x: acc + x, 0) Args: accumulator: An accumulator function to be invoked on each element. seed: Optional initial accumulator value. Returns: An operator function that takes an observable source and returns an observable sequence containing a single element with the final accumulator value. """ if seed is not NotSet: initial = ops.start_with(seed) scanner = ops.scan(accumulator, seed=seed) return pipe(scanner, initial, ops.last()) return pipe(ops.scan(accumulator), ops.last())
def value_for(button: MouseButton) -> Observable: code = codes[button] return self._activeInputs.pipe( ops.start_with({}), ops.map(lambda i: code in i and pressed(i[code])), ops.map(lambda v: button if v else 0))
def __init__(self, error_handler: ErrorHandler) -> None: if error_handler is None: raise ValueError("Argument 'error_handler' is required.") super().__init__() self._error_handler = error_handler self._added_window = Subject() self._removed_window = Subject() changed_window = rx.merge( self._added_window.pipe(ops.map(lambda v: (v, True))), self._removed_window.pipe(ops.map(lambda v: (v, False)))) def on_window_change(windows: Tuple[Window, ...], event: Tuple[Window, bool]): (window, added) = event if added and window not in windows: return windows + (window,) elif not added and window in windows: return tuple(c for c in windows if c is not window) # noinspection PyTypeChecker self.windows = changed_window.pipe( ops.scan(on_window_change, ()), ops.start_with(()), ops.distinct_until_changed())
def __init__(self, context: BlenderContext) -> None: super().__init__(context) self._activeInputs = Subject() # noinspection PyTypeChecker self.pressed = self._activeInputs.pipe( ops.start_with({}), ops.map(lambda s: set(s.keys())))
def __init__(self, context: Context, visible: bool = True) -> None: super().__init__(context, visible) # noinspection PyTypeChecker self.hover = rx.merge( self.on_mouse_over.pipe(ops.map(lambda _: True)), self.on_mouse_out.pipe(ops.map(lambda _: False))).pipe(ops.start_with(False)) mouse = MouseInput.input(self) # noinspection PyTypeChecker self.active = self.on_mouse_down.pipe( ops.filter(lambda e: e.button == MouseButton.LEFT), ops.map(lambda _: rx.concat(rx.of(True), mouse.on_button_release(MouseButton.LEFT).pipe( ops.take(1), ops.map(lambda _: False)))), ops.exclusive(), ops.start_with(False))
def _start_periodic_refresh(self) -> None: _LOG.debug("start refresh") self._composite_disposable.add( rx.interval(timedelta(milliseconds=999), scheduler=self._scheduler).pipe( operators.start_with(0), operators.subscribe_on(self._scheduler), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_next=self._on_periodic_refresh_tick, on_error=lambda e: _LOG.exception( f"Refresh error: {str(e)}")))
def _start_refresh(self) -> None: _LOG.debug("start refresh") refresh_interval = self._settings_interactor.get_int( 'settings_refresh_interval') self._composite_disposable.add( rx.interval(refresh_interval, scheduler=self._scheduler).pipe( operators.start_with(0), operators.subscribe_on(self._scheduler), operators.flat_map(lambda _: self._get_status()), operators.observe_on(GtkScheduler(GLib)), ).subscribe(on_next=self._update_status, on_error=self._handle_refresh_error))
def sequentialSocket(channel): scheduler = rx.scheduler.timeoutscheduler.TimeoutScheduler() stream = rx.interval(SOCKET_LIMIT_SEC-10, scheduler).pipe( ops.start_with('start'), ops.map(lambda _: temporarySocket(channel)), ops.switch_latest(), ops.filter(lambda res: res[:2] == '42'), ops.map(lambda res: json.loads(res[13:-1])), ops.map(Response.from_dict), ops.map(lambda res: res.message.data), ) return stream
def __init__(self, scheduler=None): self._observerable = rx.interval( ObserveConfig.interval, scheduler).pipe(ops.map(lambda dummy: get_merge_requests()), ops.retry(), ops.publish(), ops.ref_count()) self._ready_to_merge = self._observerable.pipe( ops.map(lambda requests: next((request for request in requests if is_ready_to_merge(request)), None)), ops.start_with(None), ops.distinct_until_changed()) self._ready_to_merge.subscribe(lambda ready_to_merge: logging.info( 'Ready to merge: ' + str(ready_to_merge))) voted_merge_requests = self._observerable.pipe( ops.map(_to_voted_merge_requests_set)) self._new_votes_merge_requests = voted_merge_requests.pipe( ops.skip(1), ops.zip(voted_merge_requests), ops.map(lambda zipped: zipped[0] - zipped[1]), ops.filter(len), ops.map(_to_merge_requests)) self._new_votes_merge_requests.pipe( ops.map(lambda diff_set: [merge_request.get_iid() for merge_request in diff_set]) ).subscribe( lambda ids: logging.info(f'New votes for merge requests: {ids}')) awards = self._new_votes_merge_requests.pipe(ops.map(_to_awards_set), ops.publish(), ops.ref_count(), ops.start_with(set())) self._new_awards = awards.pipe( ops.skip(1), ops.zip(awards), ops.map(lambda zipped: zipped[0] - zipped[1]), ops.filter(len), ops.flat_map(lambda diff_set: rx.from_iterable(diff_set)), ops.map(lambda award_key: award_key.award)) self._new_awards.subscribe( lambda new_award: logging.info('New award: ' + str(new_award)))
def observe_ve_property(self, service_name='*', object_path='*') -> rx.Observable: # TODO: constants, generics? prop = self.observe_signal(service_name, object_path, 'com.victronenergy.BusItem', 'PropertiesChanged') # TODO: behaviorSubject? replay? # prepend own exported properties, so the subscriber does't have to wait for first property changed own = [ p.to_ve_property() for ((sn, path), p) in self._ve_properties.items() if matches(sn, service_name) and matches(path, object_path) ] # TODO: request tree export and prepend matching, maybe this will obsolete the above return prop.pipe( op.map(VeProperty.parse), op.start_with(*own)) # TODO all ve_prop observable, publish
op.catch() op.retry() """Utility""" op.delay() op.materialize() op.time_interval() op.timeout() op.timestamp() """Conditional and Boolean""" op.all() op.contains() op.default_if_empty() op.sequence_equal() op.skip_until() op.skip_while() op.take_until() op.take_while() """Connectable""" op.publish() op.ref_count() op.replay() """Combining""" op.combine_latest() op.merge() op.start_with() op.zip()
tickerSocket = sequentialSocket(ch.ticker) transactionsSocket = sequentialSocket(ch.transactions) depthDiffSocket = sequentialSocket(ch.depth_diff) depthWholeSocket = sequentialSocket(ch.depth_whole) tickerStream = tickerSocket.pipe(ops.map(Ticker.from_dict)) transactionsStream = transactionsSocket.pipe( ops.map(TransactionsData.from_dict)) depthDiffStream = depthDiffSocket.pipe(ops.map(DepthDiff.from_dict)) depthWholeStream = depthWholeSocket.pipe(ops.map(DepthWhole.from_dict)) # API clockStream = rx.interval(10).pipe(ops.start_with('start')) # Public tickerAPI = clockStream.pipe(ops.map(bitbank.ticker)) depthAPI = clockStream.pipe(ops.map(bitbank.depth)) transactionsAPI = clockStream.pipe(ops.map(bitbank.transactions)) candlestickAPI = clockStream.pipe(ops.map(bitbank.candlestick)) statusesAPI = clockStream.pipe(ops.map(bitbank.statuses)) pairsAPI = clockStream.pipe(ops.map(bitbank.pairs)) # Private assetsAPI = clockStream.pipe(ops.map(bitbank.assets)) orderAPI = clockStream.pipe(ops.map(bitbank.order)) cancelOrderAPI = clockStream.pipe(ops.map(bitbank.cancel_order))
class Component(Drawable, StyleResolver, MouseEventHandler, EventDispatcher, ContextAware, ReactiveObject): visible: RP[bool] = rv.new_property() parent: RP[Maybe[Container]] = rv.from_value(Nothing) offset: RV[Point] = parent.as_view().map(lambda _, parent: parent.map( lambda p: rx.combine_latest(p.observe("offset"), p.observe("location")) .pipe(ops.map(lambda v: v[0] + v[1]))).or_else_call(lambda: rx.of( Point(0, 0)))).pipe(lambda _: (ops.exclusive(), )) _minimum_size: RP[Dimension] = rv.from_value(Dimension(0, 0)) _preferred_size: RP[Dimension] = rv.from_value(Dimension(0, 0)) minimum_size_override: RP[Maybe[Dimension]] = rv.from_value(Nothing) minimum_size: RV[Dimension] = rv.combine_latest( _minimum_size, minimum_size_override)(ops.pipe(ops.map(lambda v: v[1].value_or(v[0])), ops.distinct_until_changed())) preferred_size_override: RP[Maybe[Dimension]] = rv.from_value( Nothing).pipe(lambda o: (ops.combine_latest(o.observe("minimum_size")), ops.map(lambda t: t[0].map(lambda v: t[1].copy( width=max(v.width, t[1].width), height=max(v.height, t[1].height)))), ops.distinct_until_changed())) preferred_size: RV[Dimension] = rv.combine_latest( _preferred_size, preferred_size_override, minimum_size)(ops.pipe( ops.map(lambda v: (v[1].value_or(v[0]), v[2])), ops.map(lambda v: v[0].copy(width=max(v[0].width, v[1].width), height=max(v[0].height, v[1].height))), ops.distinct_until_changed())) bounds: RP[Bounds] = Bounded.bounds.pipe(lambda o: ( ops.combine_latest(o.observe("minimum_size")), ops.map(lambda v: v[0].copy(width=max(v[0].width, v[1].width), height=max(v[0].height, v[1].height))), ops.start_with(o.preferred_size))) def __init__(self, context: Context, visible: bool = True) -> None: if context is None: raise ValueError("Argument 'context' is required.") # noinspection PyTypeChecker self.visible = visible self._context = context self._valid = False self._ui = self.create_ui() assert self._ui is not None super().__init__() self.validate() self.ui \ .on_invalidate(self) \ .pipe(ops.take_until(self.on_dispose)) \ .subscribe(lambda _: self.invalidate(), on_error=self.error_handler) @property def context(self) -> Context: return self._context @property def ui(self) -> ComponentUI: return self._ui @property def look_and_feel(self) -> LookAndFeel: return self.context.look_and_feel def create_ui(self) -> ComponentUI: return self.context.look_and_feel.create_ui(self) def show(self) -> None: # noinspection PyTypeChecker self.visible = True def hide(self) -> None: # noinspection PyTypeChecker self.visible = False @property def valid(self) -> bool: return self._valid # noinspection PyTypeChecker def validate(self, force: bool = False) -> None: if self.visible and (not self.valid or force): self._minimum_size = self.ui.minimum_size(self) self._preferred_size = self.ui.preferred_size(self) self._valid = True self.parent.map(lambda p: p.request_layout()) def invalidate(self) -> None: self._valid = False self.parent.map(lambda p: p.invalidate()) def draw(self, g: Graphics) -> None: if self.visible: g.save() (dx, dy) = self.parent.map(lambda p: p.location).value_or(Point(0, 0)) (cx, cy, cw, ch) = self.ui.clip_bounds(self).tuple g.translate(dx, dy) g.rectangle(cx, cy, cw, ch) g.clip() try: self.draw_component(g) except BaseException as e: self.error_handler(e) g.restore() def draw_component(self, g: Graphics) -> None: self.ui.draw(g, self) def position_of(self, event: PositionalEvent) -> Point: if event is None: raise ValueError("Argument 'event' is required.") return event.position - self.offset @property def inputs(self) -> Mapping[str, Input]: return self.context.inputs @property def parent_dispatcher(self) -> Maybe[EventDispatcher]: # noinspection PyTypeChecker return self.parent def __repr__(self) -> Any: return str({"id": id(self), "type": type(self).__name__})
def _fetch_margin_accounts(_): group = Group.load(context) return MarginAccount.load_all_for_group_with_open_orders( context, context.program_id, group) return _fetch_margin_accounts liquidation_processor = LiquidationProcessor(default_context, NullAccountLiquidator(), NullWalletBalancer()) print("Starting margin account fetcher subscription") margin_account_interval = 60 margin_account_subscription = rx.interval(margin_account_interval).pipe( ops.subscribe_on(pool_scheduler), ops.start_with(-1), ops.map(fetch_margin_accounts(default_context)), ).subscribe( create_backpressure_skipping_observer( on_next=liquidation_processor.update_margin_accounts, on_error=log_subscription_error)) print("Starting price fetcher subscription") price_interval = 2 price_subscription = rx.interval(price_interval).pipe( ops.subscribe_on(pool_scheduler), ops.map(fetch_prices(default_context))).subscribe( create_backpressure_skipping_observer( on_next=liquidation_processor.update_prices, on_error=log_subscription_error))
def create(): return xs.pipe(_.start_with(42))
import rx from rx.operators import map, start_with from .streams import * myTradeStream = rx.combine_latest( rx.interval(0.01).pipe( map(lambda _: datetime.now().strftime('%Y-%m-%d %H:%M:%S')), ), PriceLastBuyStream.pipe(map(lambda res: 'last buy: ' + str(res)), start_with('waiting...')), PriceLastSellStream.pipe(map(lambda res: 'last sell: ' + str(res)), start_with('waiting...')), PriceMinAskStream.pipe(map(lambda res: 'min ask: ' + str(res)), start_with('waiting...')), PriceMaxBidStream.pipe(map(lambda res: 'max bid: ' + str(res)), start_with('waiting...')), )
def audio_encoder(sources): # Parse configuration parser = create_arg_parser() parsed_argv = sources.argv.argv.pipe( ops.skip(1), argparse.parse(parser), ops.filter(lambda i: i.key == 'config'), ops.subscribe_on(aio_scheduler), ops.share(), ) # monitor and parse config file monitor_init = parsed_argv.pipe( ops.flat_map(lambda i: rx.from_([ inotify.AddWatch( id='config', path=i.value, flags=aionotify.Flags.MODIFY), inotify.Start(), ]))) config_update = sources.inotify.response.pipe( ops.debounce(5.0, scheduler=aio_scheduler), ops.map(lambda i: True), ops.start_with(True), ) read_request, read_response = rx.combine_latest( parsed_argv, config_update).pipe( ops.starmap( lambda config, _: file.Read(id='config', path=config.value)), file.read(sources.file.response), ) config = read_response.pipe( ops.filter(lambda i: i.id == "config"), ops.flat_map(lambda i: i.data), parse_config, ) # Transcode request handling encode_init = config.pipe( ops.map(lambda i: i.encode), ops.distinct_until_changed(), ops.map(lambda i: encoder.Configure(samplerate=i.samplerate, bitdepth=i.bitdepth)), ) encode_request = sources.httpd.route.pipe( ops.filter(lambda i: i.id == 'flac_transcode'), ops.flat_map(lambda i: i.request), ops.flat_map(lambda i: rx.just(i, encode_scheduler)), ops.map(lambda i: encoder.EncodeMp3( id=i.context, data=i.data, key=i.match_info['key'])), ) encoder_request = rx.merge(encode_init, encode_request) # store encoded file store_requests = sources.encoder.response.pipe( ops.observe_on(s3_scheduler), ops.map(lambda i: s3.UploadObject( key=i.key + '.flac', data=i.data, id=i.id, )), ) # acknowledge http request http_response = sources.s3.response.pipe( ops.map(lambda i: httpd.Response( data='ok'.encode('utf-8'), context=i.id, ))) # http server http_init = config.pipe( ops.take(1), ops.flat_map(lambda i: rx.from_([ httpd.Initialize(request_max_size=0), httpd.AddRoute( methods=['POST'], path='/api/transcode/v1/flac/{key:[a-zA-Z0-9-\._]*}', id='flac_transcode', ), httpd.StartServer(host=i.server.http.host, port=i.server.http.port ), ])), ) http = rx.merge(http_init, http_response) # s3 database s3_init = config.pipe( ops.take(1), ops.map(lambda i: s3.Configure( access_key=i.s3.access_key, secret_key=i.s3.secret_key, bucket=i.s3.bucket, endpoint_url=i.s3.endpoint_url, region_name=i.s3.region_name, )), ) # merge sink requests file_requests = read_request s3_requests = rx.merge(s3_init, store_requests) return Sink( encoder=encoder.Sink(request=encoder_request), s3=s3.Sink(request=s3_requests), file=file.Sink(request=file_requests), httpd=httpd.Sink(control=http), inotify=inotify.Sink(request=monitor_init), )
def test_tuple_with_previous_using_scan(): rx.from_iterable(range(10)).pipe(ops.start_with((-1, -1)), ops.scan(lambda tup, y: (y, tup[0])), ops.skip(2)).subscribe(lambda x: print(x))
def prepend_current_list( scheduler: Scheduler = None) -> Observable[List[str]]: return service_added.pipe(op.start_with(self.current_services))