def read_message_bytes_from_pipe(pipe_handle): """ (coroutine) Read message from this pipe. Return bytes. """ overlapped = OVERLAPPED() overlapped.hEvent = create_event() try: buff = create_string_buffer(BUFSIZE + 1) c_read = DWORD() success = windll.kernel32.ReadFile(pipe_handle, buff, DWORD(BUFSIZE), byref(c_read), byref(overlapped)) if success: buff[c_read.value] = b'\0' raise Return(buff.value) error_code = windll.kernel32.GetLastError() if error_code == ERROR_IO_PENDING: yield From(wait_for_event(overlapped.hEvent)) success = windll.kernel32.GetOverlappedResult( pipe_handle, byref(overlapped), byref(c_read), BOOL(False)) if success: buff[c_read.value] = b'\0' raise Return(buff.value) else: error_code = windll.kernel32.GetLastError() if error_code == ERROR_BROKEN_PIPE: raise BrokenPipeError elif error_code == ERROR_MORE_DATA: more_data = yield From( read_message_bytes_from_pipe(pipe_handle)) raise Return(buff.value + more_data) else: raise Exception( 'reading overlapped IO failed. error_code=%r' % error_code) elif error_code == ERROR_BROKEN_PIPE: raise BrokenPipeError elif error_code == ERROR_MORE_DATA: more_data = yield From(read_message_bytes_from_pipe(pipe_handle)) raise Return(buff.value + more_data) else: raise Exception('Reading pipe failed, error_code=%s' % error_code) finally: windll.kernel32.CloseHandle(overlapped.hEvent)
def _run_in_t(): " Coroutine. " # Wait for the previous `run_in_terminal` to finish. if previous_run_in_terminal_f is not None: yield previous_run_in_terminal_f # Draw interface in 'done' state, or erase. if render_cli_done: app._redraw(render_as_done=True) else: app.renderer.erase() # Disable rendering. app._running_in_terminal = True # Detach input. try: with app.input.detach(): with app.input.cooked_mode(): result = yield From(async_func()) raise Return(result) # Same as: "return result" finally: # Redraw interface again. try: app._running_in_terminal = False app.renderer.reset() app._request_absolute_cursor_position() app._redraw() finally: new_run_in_terminal_f.set_result(None)
def read_message(self): """ (coroutine) Read one single message from the pipe and return as text. """ message = yield From(read_message_from_pipe(self.pipe_handle)) raise Return(message)
def run_async(): with self._auto_refresh_context(): try: self.default_buffer.reset(Document(self.default)) result = yield From(self.app.run_async(pre_run=pre_run)) raise Return(result) finally: restore()
def read_message_from_pipe(pipe_handle): """ (coroutine) Read message from this pipe. Return text. """ data = yield From(read_message_bytes_from_pipe(pipe_handle)) assert isinstance(data, bytes) raise Return(data.decode('utf-8', 'ignore'))
def _run_async2(): self._is_running = True with set_app(self): try: f = From(_run_async()) result = yield f finally: assert not self._is_running raise Return(result)
def _run_async2(): self._is_running = True with set_app(self): try: f = From(_run_async()) result = yield f finally: # Set the `_is_running` flag to `False`. Normally this # happened already in the finally block in `run_async` # above, but in case of exceptions, that's not always the # case. self._is_running = False raise Return(result)
def show_dialog(dialog): " Coroutine. " app = get_app() float_ = Float(content=dialog) app.layout.container.floats.insert(0, float_) focused_before = app.layout.current_window app.layout.focus(dialog) result = yield dialog.future app.layout.focus(focused_before) if float_ in app.layout.container.floats: app.layout.container.floats.remove(float_) raise Return(result)
def read(self): """ (coroutine) Read a single message from the pipe. (Return as text.) """ if self.done_f.done(): raise BrokenPipeError try: result = yield From( read_message_from_pipe(self.pipe_instance.pipe_handle)) raise Return(result) except BrokenPipeError: self.done_f.set_result(None) raise
def read(self): r""" Coroutine that reads the next packet. (Packets are \0 separated.) """ # Read until we have a \0 in our buffer. while b'\0' not in self._recv_buffer: self._recv_buffer += yield From( _read_chunk_from_socket(self.socket)) # Split on the first separator. pos = self._recv_buffer.index(b'\0') packet = self._recv_buffer[:pos] self._recv_buffer = self._recv_buffer[pos + 1:] raise Return(packet)
def my_coroutine(): """ A coroutine example. "yield-from" is used to wait for a `Future` or another coroutine. """ # Wait for first future. value = yield From(async_1()) print('async_1 returned: ', value) # Wait for second future. try: value = yield From(async_2()) except Exception as e: print('async_2 raised: ', e) else: print('async_2 returned: ', value) # Wait for third future. value = yield From(async_3()) print('async_3 returned: ', value) # Wait for fourth future. try: value = yield From(async_4()) except Exception as e: print('async_4 raised: ', e) else: print('async_4 returned: ', value) # Wait for fifth future. value = yield From(async_5()) print('async_5 returned: ', value) # Wait for sixth future. try: value = yield From(async_6()) except Exception as e: print('async_6 raised: ', e) else: print('async_6 returned: ', value) # Wait for another coroutine. value = yield From(other_coroutine()) print('other_coroutine returned: ', value) raise Return('result')
def _run_in_t(): " Coroutine. " # Wait for the previous `run_in_terminal` to finish. if previous_run_in_terminal_f is not None: yield previous_run_in_terminal_f # Wait for all CPRs to arrive. We don't want to detach the input until # all cursor position responses have been arrived. Otherwise, the tty # will echo its input and can show stuff like ^[[39;1R. if app.input.responds_to_cpr: yield From(app.renderer.wait_for_cpr_responses()) # Draw interface in 'done' state, or erase. if render_cli_done: app._redraw(render_as_done=True) else: app.renderer.erase() # Disable rendering. app._running_in_terminal = True # Detach input. try: with app.input.detach(): with app.input.cooked_mode(): result = yield From(async_func()) raise Return(result) # Same as: "return result" finally: # Redraw interface again. try: app._running_in_terminal = False app.renderer.reset() app._request_absolute_cursor_position() app._redraw() finally: new_run_in_terminal_f.set_result(None)
def _run_async(): " Coroutine. " loop = get_event_loop() f = loop.create_future() self.future = f # XXX: make sure to set this before calling '_redraw'. # Counter for cancelling 'flush' timeouts. Every time when a key is # pressed, we start a 'flush' timer for flushing our escape key. But # when any subsequent input is received, a new timer is started and # the current timer will be ignored. flush_counter = [0] # Non local. # Reset. self.reset() self._pre_run(pre_run) # Feed type ahead input first. self.key_processor.feed_multiple(get_typeahead(self.input)) self.key_processor.process_keys() def read_from_input(): # Ignore when we aren't running anymore. This callback will # removed from the loop next time. (It could be that it was # still in the 'tasks' list of the loop.) # Except: if we need to process incoming CPRs. if not self._is_running and not self.renderer.waiting_for_cpr: return # Get keys from the input object. keys = self.input.read_keys() # Feed to key processor. self.key_processor.feed_multiple(keys) self.key_processor.process_keys() # Quit when the input stream was closed. if self.input.closed: f.set_exception(EOFError) else: # Increase this flush counter. flush_counter[0] += 1 counter = flush_counter[0] # Automatically flush keys. # (_daemon needs to be set, otherwise, this will hang the # application for .5 seconds before exiting.) run_in_executor( lambda: auto_flush_input(counter), _daemon=True) def auto_flush_input(counter): # Flush input after timeout. # (Used for flushing the enter key.) time.sleep(self.ttimeoutlen) if flush_counter[0] == counter: call_from_executor(flush_input) def flush_input(): if not self.is_done: # Get keys, and feed to key processor. keys = self.input.flush_keys() self.key_processor.feed_multiple(keys) self.key_processor.process_keys() if self.input.closed: f.set_exception(EOFError) # Enter raw mode. with self.input.raw_mode(): with self.input.attach(read_from_input): # Draw UI. self._request_absolute_cursor_position() self._redraw() has_sigwinch = hasattr(signal, 'SIGWINCH') and in_main_thread() if has_sigwinch: previous_winch_handler = loop.add_signal_handler( signal.SIGWINCH, self._on_resize) # Wait for UI to finish. try: result = yield From(f) finally: # In any case, when the application finishes. (Successful, # or because of an error.) try: self._redraw(render_as_done=True) finally: # _redraw has a good chance to fail if it calls widgets # with bad code. Make sure to reset the renderer anyway. self.renderer.reset() # Unset `is_running`, this ensures that possibly # scheduled draws won't paint during the following # yield. self._is_running = False # Detach event handlers for invalidate events. # (Important when a UIControl is embedded in # multiple applications, like ptterm in pymux. An # invalidate should not trigger a repaint in # terminated applications.) for ev in self._invalidate_events: ev -= self.invalidate self._invalidate_events = [] # Wait for CPR responses. if self.input.responds_to_cpr: yield From(self.renderer.wait_for_cpr_responses()) if has_sigwinch: loop.add_signal_handler(signal.SIGWINCH, previous_winch_handler) # Wait for the run-in-terminals to terminate. previous_run_in_terminal_f = self._running_in_terminal_f if previous_run_in_terminal_f: yield From(previous_run_in_terminal_f) # Store unprocessed input as typeahead for next time. store_typeahead(self.input, self.key_processor.empty_queue()) raise Return(result)
def other_coroutine(): value = yield From(Future.succeed(True)) value = yield From(Future.succeed(True)) raise Return('Result from coroutine.')