def main(): stream = InputStream(callback) with raw_mode(sys.stdin.fileno()): while True: c = sys.stdin.read(1) stream.feed(c)
def setUp(self): class _ProcessorMock(object): def __init__(self): self.keys = [] def feed_key(self, key_press): self.keys.append(key_press) self.processor = _ProcessorMock() self.stream = InputStream(self.processor.feed_key)
def __init__(self, pymux, connection, client_address): self.pymux = pymux self.connection = connection self.client_address = client_address self.size = Size(rows=20, columns=80) self._closed = False self._recv_buffer = b'' self.cli = None self._inputstream = InputStream( lambda key: self.cli.input_processor.feed_key(key)) pymux.eventloop.add_reader(connection.fileno(), self._recv)
def set_application(self, app, callback=None): """ Set ``CommandLineInterface`` instance for this connection. (This can be replaced any time.) :param cli: CommandLineInterface instance. :param callback: Callable that takes the result of the CLI. """ assert isinstance(app, Application) assert callback is None or callable(callback) self.cli = CommandLineInterface(application=app, eventloop=self.eventloop, output=self.vt100_output) self.callback = callback # Create a parser, and parser callbacks. cb = self.cli.create_eventloop_callbacks() inputstream = InputStream(cb.feed_key) # Input decoder for stdin. (Required when working with multibyte # characters, like chinese input.) stdin_decoder_cls = getincrementaldecoder(self.encoding) stdin_decoder = [stdin_decoder_cls()] # nonlocal # Tell the CLI that it's running. We don't start it through the run() # call, but will still want _redraw() to work. self.cli._is_running = True def data_received(data): """ TelnetProtocolParser 'data_received' callback """ assert isinstance(data, binary_type) try: result = stdin_decoder[0].decode(data) inputstream.feed(result) except UnicodeDecodeError: stdin_decoder[0] = stdin_decoder_cls() return '' def size_received(rows, columns): """ TelnetProtocolParser 'size_received' callback """ self.size = Size(rows=rows, columns=columns) cb.terminal_size_changed() self.parser = TelnetProtocolParser(data_received, size_received)
def set_cli(self, cli, callback=None): """ Set ``CommandLineInterface`` instance for this connection. (This can be replaced any time.) :param cli: CommandLineInterface instance. :param callback: Callable that takes the result of the CLI. """ assert isinstance(cli, CommandLineInterface) assert callback is None or callable(callback) self.cli = cli self.callback = callback # Replace the eventloop and renderer to integrate with the # telnet server. cli.eventloop = self.eventloop cli.renderer = Renderer(output=self.vt100_output) # Create a parser, and parser callbacks. cb = self.cli.create_eventloop_callbacks() inputstream = InputStream(cb.feed_key) # Input decoder for stdin. (Required when working with multibyte # characters, like chinese input.) stdin_decoder_cls = getincrementaldecoder(self.encoding) stdin_decoder = [stdin_decoder_cls()] # nonlocal def data_received(data): """ TelnetProtocolParser 'data_received' callback """ assert isinstance(data, binary_type) try: result = stdin_decoder[0].decode(data) inputstream.feed(result) except UnicodeDecodeError: stdin_decoder[0] = stdin_decoder_cls() return '' def size_received(rows, columns): """ TelnetProtocolParser 'size_received' callback """ self.size = Size(rows=rows, columns=columns) cb.terminal_size_changed() self.parser = TelnetProtocolParser(data_received, size_received)
def run(self, stdin, callbacks): inputstream = InputStream(callbacks.feed_key) stdin_reader = PosixStdinReader(stdin.fileno()) self._callbacks = callbacks if in_main_thread(): ctx = call_on_sigwinch(self.received_winch) else: ctx = DummyContext() select_timeout = INPUT_TIMEOUT with ctx: while self._running: r, _, _ = select.select( [stdin.fileno(), self._schedule_pipe_read], [], [], select_timeout) if stdin.fileno() in r: select_timeout = INPUT_TIMEOUT data = stdin_reader.read() inputstream.feed(data) if stdin_reader.closed: break elif self._schedule_pipe_read in r: os.read(self._schedule_pipe_read, 8192) while True: try: task = self._calls_from_executor.pop(0) except IndexError: break else: task() else: # timeout inputstream.flush() callbacks.input_timeout() select_timeout = None self._callbacks = None
def run(self, stdin, callbacks): """ The input 'event loop'. """ assert isinstance(stdin, Input) assert isinstance(callbacks, EventLoopCallbacks) assert not self._running if self.closed: raise Exception('Event loop already closed.') self._running = True self._callbacks = callbacks inputstream = InputStream(callbacks.feed_key) current_timeout = [INPUT_TIMEOUT] # Nonlocal # Create reader class. stdin_reader = PosixStdinReader(stdin.fileno()) # Only attach SIGWINCH signal handler in main thread. # (It's not possible to attach signal handlers in other threads. In # that case we should rely on a the main thread to call this manually # instead.) if in_main_thread(): ctx = call_on_sigwinch(self.received_winch) else: ctx = DummyContext() def read_from_stdin(): " Read user input. " # Feed input text. data = stdin_reader.read() inputstream.feed(data) # Set timeout again. current_timeout[0] = INPUT_TIMEOUT # Quit when the input stream was closed. if stdin_reader.closed: self.stop() self.add_reader(stdin, read_from_stdin) self.add_reader(self._schedule_pipe[0], None) with ctx: while self._running: # Call inputhook. with TimeIt() as inputhook_timer: if self._inputhook_context: def ready(wait): " True when there is input ready. The inputhook should return control. " return self._ready_for_reading( current_timeout[0] if wait else 0) != [] self._inputhook_context.call_inputhook(ready) # Calculate remaining timeout. (The inputhook consumed some of the time.) if current_timeout[0] is None: remaining_timeout = None else: remaining_timeout = max( 0, current_timeout[0] - inputhook_timer.duration) # Wait until input is ready. fds = self._ready_for_reading(remaining_timeout) # When any of the FDs are ready. Call the appropriate callback. if fds: # Create lists of high/low priority tasks. The main reason # for this is to allow painting the UI to happen as soon as # possible, but when there are many events happening, we # don't want to call the UI renderer 1000x per second. If # the eventloop is completely saturated with many CPU # intensive tasks (like processing input/output), we say # that drawing the UI can be postponed a little, to make # CPU available. This will be a low priority task in that # case. tasks = [] low_priority_tasks = [] now = _now() for fd in fds: # For the 'call_from_executor' fd, put each pending # item on either the high or low priority queue. if fd == self._schedule_pipe[0]: for c, max_postpone_until in self._calls_from_executor: if max_postpone_until is None or max_postpone_until < now: tasks.append(c) else: low_priority_tasks.append( (c, max_postpone_until)) self._calls_from_executor = [] # Flush all the pipe content. os.read(self._schedule_pipe[0], 1024) else: handler = self._read_fds.get(fd) if handler: tasks.append(handler) # Handle everything in random order. (To avoid starvation.) random.shuffle(tasks) random.shuffle(low_priority_tasks) # When there are high priority tasks, run all these. # Schedule low priority tasks for the next iteration. if tasks: for t in tasks: t() # Postpone low priority tasks. for t, max_postpone_until in low_priority_tasks: self.call_from_executor( t, _max_postpone_until=max_postpone_until) else: # Currently there are only low priority tasks -> run them right now. for t, _ in low_priority_tasks: t() else: # Flush all pending keys on a timeout. (This is most # important to flush the vt100 'Escape' key early when # nothing else follows.) inputstream.flush() # Fire input timeout event. callbacks.input_timeout() current_timeout[0] = None self.remove_reader(stdin) self.remove_reader(self._schedule_pipe[0]) self._callbacks = None
def run(self, stdin, callbacks): """ The input 'event loop'. """ assert isinstance(stdin, Input) assert isinstance(callbacks, EventLoopCallbacks) assert not self._running if self.closed: raise Exception('Event loop already closed.') self._running = True self._callbacks = callbacks inputstream = InputStream(callbacks.feed_key) current_timeout = INPUT_TIMEOUT # Create reader class. stdin_reader = PosixStdinReader(stdin.fileno()) # Only attach SIGWINCH signal handler in main thread. # (It's not possible to attach signal handlers in other threads. In # that case we should rely on a the main thread to call this manually # instead.) if in_main_thread(): ctx = call_on_sigwinch(self.received_winch) else: ctx = DummyContext() with ctx: while self._running: # Call inputhook. with TimeIt() as inputhook_timer: if self._inputhook_context: def ready(wait): " True when there is input ready. The inputhook should return control. " return self._ready_for_reading( stdin, current_timeout if wait else 0) != [] self._inputhook_context.call_inputhook(ready) # Calculate remaining timeout. (The inputhook consumed some of the time.) if current_timeout is None: remaining_timeout = None else: remaining_timeout = max( 0, current_timeout - inputhook_timer.duration) # Wait until input is ready. r = self._ready_for_reading(stdin, remaining_timeout) # If we got a character, feed it to the input stream. If we got # none, it means we got a repaint request. if stdin in r: # Feed input text. data = stdin_reader.read() inputstream.feed(data) # Set timeout again. current_timeout = INPUT_TIMEOUT # When any of the registered read pipes are ready. Call the # appropriate callback. elif set(r) & set(self._read_fds): for fd in r: handler = self._read_fds.get(fd) if handler: handler() # If we receive something on our "call_from_executor" pipe, process # these callbacks in a thread safe way. elif self._schedule_pipe[0] in r: # Flush all the pipe content. os.read(self._schedule_pipe[0], 1024) # Process calls from executor. calls_from_executor, self._calls_from_executor = self._calls_from_executor, [] for c in calls_from_executor: c() else: # Flush all pending keys on a timeout. (This is most # important to flush the vt100 'Escape' key early when # nothing else follows.) inputstream.flush() # Fire input timeout event. callbacks.input_timeout() current_timeout = None self._callbacks = None
def stream(processor): return InputStream(processor.feed_key)
def stream(processor): from prompt_toolkit.terminal.vt100_input import InputStream return InputStream(processor.feed_key)