def handle_websocket(): wsock = request.environ.get("wsgi.websocket") if not wsock: abort(400, "Expected WebSocket request.") stream = Subject() query = ( stream.map(lambda x: x["term"]).filter(lambda text: len( text) > 2) # Only if text is longer than 2 characters .debounce(0.750, scheduler=scheduler) # Pause for 750ms .distinct_until_changed()) # Only if the value has changed searcher = query.flat_map_latest(lambda term: WikiFinder(term)) def send_response(x): wsock.on_next(x) def on_error(ex): print(ex) searcher.subscribe(send_response, on_error) while True: try: message = wsock.receive() # like {'term': '<current textbox val>'} obj = json.loads(message) stream.on_next(obj) except WebSocketError: break
class Window(QWidget): def __init__(self): QWidget.__init__(self) self.setWindowTitle("Rx for Python rocks") self.resize(600, 600) self.setMouseTracking(True) # This Subject is used to transmit mouse moves to labels self.mousemove = Subject() def mouseMoveEvent(self, event): self.mousemove.on_next((event.x(), event.y()))
class Window(Gtk.Window): def __init__(self): super().__init__() self.resize(600, 600) self.add_events(Gdk.EventMask.POINTER_MOTION_MASK) self.connect("motion-notify-event", self.on_mouse_move) self.mousemove = Subject() def on_mouse_move(self, widget, event): self.mousemove.on_next((event.x, event.y))
class Frame(wx.Frame): def __init__(self): super(Frame, self).__init__(None) self.SetTitle("Rx for Python rocks") self.SetSize((600, 600)) # This Subject is used to transmit mouse moves to labels self.mousemove = Subject() self.Bind(wx.EVT_MOTION, self.OnMotion) def OnMotion(self, event): self.mousemove.on_next((event.GetX(), event.GetY()))
def main(): pygame.init() size = 500, 500 screen = pygame.display.set_mode(size) pygame.display.set_caption("Rx for Python rocks") black = 0, 0, 0 background = pygame.Surface(screen.get_size()) background.fill(black) # fill the background black background = background.convert() # prepare for faster blitting scheduler = PyGameScheduler(pygame) mousemove = Subject() color = "white" base = dirname(__file__) files = [ join(base, img % color) for img in [ "chess_rook_%s.png", "chess_knight_%s.png", "chess_bishop_%s.png", "chess_king_%s.png", "chess_queen_%s.png", "chess_bishop_%s.png", "chess_knight_%s.png", "chess_rook_%s.png", ] ] images = [pygame.image.load(image).convert_alpha() for image in files] old = [None] * len(images) draw = [] erase = [] def handle_image(i, image): imagerect = image.get_rect() def on_next(ev): imagerect.top = ev[1] imagerect.left = ev[0] + i * 32 if old[i]: erase.append(old[i]) old[i] = imagerect.copy() draw.append((image, imagerect.copy())) def on_error(err): print("Got error: %s" % err) sys.exit() mousemove.pipe(ops.delay(0.1 * i, scheduler=scheduler)).subscribe( on_next, on_error=on_error) for i, image in enumerate(images): handle_image(i, image) while True: for event in pygame.event.get(): if event.type == pygame.MOUSEMOTION: pos = event.pos mousemove.on_next(pos) elif event.type == pygame.QUIT: sys.exit() if len(draw): update = [] for rect in erase: screen.blit(background, (rect.x, rect.y), rect) update.append(rect) for image, rect in draw: screen.blit(image, rect) update.append(rect) pygame.display.update(update) pygame.display.flip() draw = [] erase = [] scheduler.run()
class _RxWriter(object): success_count = 0 failed_count = 0 raise_retry_exception = 0 def __init__(self) -> None: self._subject = Subject() self._scheduler = ThreadPoolScheduler(max_workers=1) obs = self._subject.pipe(ops.observe_on(self._scheduler)) self._disposable = obs \ .pipe(ops.window_with_time_or_count(count=5, timespan=datetime.timedelta(milliseconds=10_000)), ops.flat_map(lambda x: self._window_to_group(x)), ops.map(mapper=lambda x: self._retryable(data=x, delay=self._jitter_delay(jitter_interval=1000))), ops.merge_all()) \ .subscribe(self._result, self._error, self._on_complete) pass def close(self): self.__del__() def __del__(self): if self._subject: self._subject.on_completed() self._subject.dispose() self._subject = None while not self._disposable.is_disposed: time.sleep(0.1) if self._disposable: self._disposable = None pass def _window_to_group(self, value): return value.pipe( ops.to_iterable(), ops.map( lambda x: rx.from_iterable(x).pipe(ops.group_by( _group_by), ops.map(_group_to_batch), ops.merge_all())), ops.merge_all()) def _retryable(self, data: str, delay: datetime.timedelta): return rx.of(data).pipe( ops.delay(duetime=delay, scheduler=self._scheduler), ops.map(lambda x: self._http(x)), ops.catch(handler=lambda exception, source: self._retry_handler( exception, source, data)), ) def _http(self, data: str): if "gamma" in data: print('bad request[{}]: {}'.format(current_thread().name, data)) raise Exception('unexpected token: {}'.format(data)) pass if "alpha" in data: if self.raise_retry_exception < 2: self.raise_retry_exception += 1 print( 'server is temporarily unavailable to accept writes[{}]: {}' .format(current_thread().name, data)) raise Exception( 'server is temporarily unavailable to accept writes: {}'. format(data)) else: print("server is OK: {}".format(datetime.datetime.now())) pass print("http[" + current_thread().name + "]: " + data) return _Notification(data=data) def write(self, data: str): print("write[" + current_thread().name + "]") self._subject.on_next(data) pass def _result(self, data: _Notification): print("result[" + current_thread().name + "]: " + str(data)) if data.exception: self.failed_count += 1 else: self.success_count += 1 pass def _error(self, error): print(error) def _on_complete(self): self._disposable.dispose() print("on complete") def _jitter_delay(self, jitter_interval=0): _jitter = datetime.timedelta(milliseconds=random() * jitter_interval) print('jitter: {}'.format(_jitter)) return _jitter def _retry_handler(self, exception, source, data): print('retry_handler: {}, source: {}'.format(exception, source)) if "server is temporarily" in str(exception): print("RETRY!!!: {}".format(datetime.datetime.now())) return self._retryable(data, delay=datetime.timedelta(seconds=2)) notification = _Notification(exception=exception, data=data) return rx.just(notification)