Example #1
0
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)
Example #2
0
    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)
Example #3
0
 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)
Example #4
0
 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()
Example #5
0
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)
Example #7
0
 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)
Example #8
0
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)
Example #9
0
    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
Example #10
0
    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)
Example #11
0
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')
Example #12
0
    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)
Example #14
0
def other_coroutine():
    value = yield From(Future.succeed(True))
    value = yield From(Future.succeed(True))
    raise Return('Result from coroutine.')