def run(): with context() as ctx_id: self._context_id = ctx_id # Set input/output for all application running in this context. set_default_input(self.vt100_input) set_default_output(self.vt100_output) # Add reader. loop = get_event_loop() loop.add_reader(self.conn, handle_incoming_data) try: obj = self.interact(self) if _is_coroutine(obj): # Got an asyncio coroutine. import asyncio f = asyncio.ensure_future(obj) yield From(Future.from_asyncio_future(f)) else: # Got a prompt_toolkit coroutine. yield From(obj) except Exception as e: print('Got %s' % type(e).__name__, e) import traceback traceback.print_exc() raise finally: self.close()
def run(): # Try to use the same input/output file descriptors as the one, # used to run this application. try: input_fd = self.input.fileno() except AttributeError: input_fd = sys.stdin.fileno() try: output_fd = self.output.fileno() except AttributeError: output_fd = sys.stdout.fileno() # Run sub process. def run_command(): self.print_text(display_before_text) p = Popen(command, shell=True, stdin=input_fd, stdout=output_fd) p.wait() yield run_in_executor(run_command) # Wait for the user to press enter. if wait_for_enter: yield From(_do_wait_for_enter(wait_text))
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 run_async(): with self._auto_refresh_context(): try: self.default_buffer.reset(Document(self.default)) result = yield From(self.app.run_async()) raise Return(result) finally: restore()
def print_exception(): # Print output. Similar to 'loop.default_exception_handler', # but don't use logger. (This works better on Python 2.) print('\nUnhandled exception in event loop:') print(formatted_tb) print('Exception %s' % (context.get('exception'), )) yield From(_do_wait_for_enter('Press ENTER to continue...'))
def run(): logger.info('Starting interaction %r %r', *addr) try: yield From(connection.run_application()) except Exception as e: print(e) finally: self.connections.remove(connection) logger.info('Stopping interaction %r %r', *addr)
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 _do_wait_for_enter(wait_text): """ Create a sub application to wait for the enter key press. This has two advantages over using 'input'/'raw_input': - This will share the same input/output I/O. - This doesn't block the event loop. """ from polymorph.deps.prompt_toolkit.shortcuts import PromptSession key_bindings = KeyBindings() @key_bindings.add('enter') def _(event): event.app.exit() @key_bindings.add(Keys.Any) def _(event): " Disallow typing. " pass session = PromptSession(message=wait_text, key_bindings=key_bindings) yield From(session.app.run_async())
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 # 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 wait_for_responses(): for response_f in cpr_futures: yield From(response_f) if not f.done(): f.set_result(None)