def run_reporter(self): " Buffer text changed. " if not self._reporter_is_running: self._reporter_is_running = True text = self.buffer.text self.report_errors = [] # Don't run reporter when we don't have a location. (We need to # know the filetype, actually.) if self.location is None: return # Better not to access the document in an executor. document = self.buffer.document def in_executor(): # Call reporter report_errors = report(self.location, document) def ready(): self._reporter_is_running = False # If the text has not been changed yet in the meantime, set # reporter errors. (We were running in another thread.) if text == self.buffer.text: self.report_errors = report_errors get_app().invalidate() else: # Restart reporter when the text was changed. self.run_reporter() call_from_executor(ready) run_in_executor(in_executor)
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 _start_timeout(self): """ Start auto flush timeout. Similar to Vim's `timeoutlen` option. Start a background thread with a timer. When this timeout expires and no key was pressed in the meantime, we flush all data in the queue and call the appropriate key binding handlers. """ timeout = get_app().timeoutlen if timeout is None: return counter = self._keys_pressed def wait(): " Wait for timeout. " time.sleep(timeout) if len(self.key_buffer) > 0 and counter == self._keys_pressed: # (No keys pressed in the meantime.) call_from_executor(flush_keys) def flush_keys(): " Flush keys. " self.feed(_Flush) self.process_keys() # Automatically flush keys. # (_daemon needs to be set, otherwise, this will hang the # application for .5 seconds before exiting.) run_in_executor(wait, _daemon=True)
def async_6(): " Create a `Future` and call `set_exception` later on. " f = Future() def in_executor(): time.sleep(.2) f.set_exception(Exception('Failure from async_6')) run_in_executor(in_executor) return f
def async_5(): " Create a `Future` and call `set_result` later on. " f = Future() def in_executor(): time.sleep(.2) f.set_result('Hello from async_5') run_in_executor(in_executor) return f
def progress_dialog(title='', text='', run_callback=None, style=None, async_=False): """ :param run_callback: A function that receives as input a `set_percentage` function and it does the work. """ assert callable(run_callback) progressbar = ProgressBar() text_area = TextArea( focusable=False, # Prefer this text area as big as possible, to avoid having a window # that keeps resizing when we add text to it. height=D(preferred=10**10)) dialog = Dialog(body=HSplit([ Box(Label(text=text)), Box(text_area, padding=D.exact(1)), progressbar, ]), title=title, with_background=True) app = _create_app(dialog, style) def set_percentage(value): progressbar.percentage = int(value) app.invalidate() def log_text(text): text_area.buffer.insert_text(text) app.invalidate() # Run the callback in the executor. When done, set a return value for the # UI, so that it quits. def start(): try: run_callback(set_percentage, log_text) finally: app.exit() run_in_executor(start) if async_: return app.run_async() else: return app.run()
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 progress_dialog(title='', text='', run_callback=None, style=None, async_=False): """ :param run_callback: A function that receives as input a `set_percentage` function and it does the work. """ assert callable(run_callback) progressbar = ProgressBar() text_area = TextArea( focusable=False, # Prefer this text area as big as possible, to avoid having a window # that keeps resizing when we add text to it. height=D(preferred=10**10)) dialog = Dialog( body=HSplit([ Box(Label(text=text)), Box(text_area, padding=D.exact(1)), progressbar, ]), title=title, with_background=True) app = _create_app(dialog, style) def set_percentage(value): progressbar.percentage = int(value) app.invalidate() def log_text(text): text_area.buffer.insert_text(text) app.invalidate() # Run the callback in the executor. When done, set a return value for the # UI, so that it quits. def start(): try: run_callback(set_percentage, log_text) finally: app.exit() run_in_executor(start) if async_: return app.run_async() else: return app.run()
def invalidate(self): """ Thread safe way of sending a repaint trigger to the input event loop. """ # Never schedule a second redraw, when a previous one has not yet been # executed. (This should protect against other threads calling # 'invalidate' many times, resulting in 100% CPU.) if self._invalidated: return else: self._invalidated = True # Trigger event. self.on_invalidate.fire() def redraw(): self._invalidated = False self._redraw() def schedule_redraw(): # Call redraw in the eventloop (thread safe). # Usually with the high priority, in order to make the application # feel responsive, but this can be tuned by changing the value of # `max_render_postpone_time`. if self.max_render_postpone_time: _max_postpone_until = time.time( ) + self.max_render_postpone_time else: _max_postpone_until = None call_from_executor(redraw, _max_postpone_until=_max_postpone_until) if self.min_redraw_interval: # When a minimum redraw interval is set, wait minimum this amount # of time between redraws. diff = time.time() - self._last_redraw_time if diff < self.min_redraw_interval: def redraw_in_future(): time.sleep(self.min_redraw_interval - diff) schedule_redraw() run_in_executor(redraw_in_future) else: schedule_redraw() else: schedule_redraw()
def async_1(): """ Runs some code in an executor (other thread). """ def in_executor(): time.sleep(1) return 'Hello from async_1' return run_in_executor(in_executor)
def async_2(): """ Raise an exception in the executor. """ def in_executor(): time.sleep(.2) raise Exception('Failure from async_2') return run_in_executor(in_executor)
def invalidate(self): """ Thread safe way of sending a repaint trigger to the input event loop. """ # Never schedule a second redraw, when a previous one has not yet been # executed. (This should protect against other threads calling # 'invalidate' many times, resulting in 100% CPU.) if self._invalidated: return else: self._invalidated = True # Trigger event. self.on_invalidate.fire() def redraw(): self._invalidated = False self._redraw() def schedule_redraw(): # Call redraw in the eventloop (thread safe). # Usually with the high priority, in order to make the application # feel responsive, but this can be tuned by changing the value of # `max_render_postpone_time`. if self.max_render_postpone_time: _max_postpone_until = time.time() + self.max_render_postpone_time else: _max_postpone_until = None call_from_executor( redraw, _max_postpone_until=_max_postpone_until) if self.min_redraw_interval: # When a minimum redraw interval is set, wait minimum this amount # of time between redraws. diff = time.time() - self._last_redraw_time if diff < self.min_redraw_interval: def redraw_in_future(): time.sleep(self.min_redraw_interval - diff) schedule_redraw() run_in_executor(redraw_in_future) else: schedule_redraw() else: schedule_redraw()
def __init__(self, mic, recognizer): self.future = future = Future() def listen(): with mic as source: recognizer.adjust_for_ambient_noise(source, 0.5) audio = recognizer.listen(source) future.set_result(audio) run_in_executor(listen) self.dialog = Dialog(title='LISTENING', body=HSplit([ TextArea(text='', multiline=False, read_only=True), ]), width=D(preferred=80), modal=True)
def run_shell_command(command): def run_command(): if not command: sys.stdout.write("\n") return try: if sys.platform.startswith('win'): cmd_list = command.strip().split(" ", 1) else: cmd_list = shlex.split(command) except Exception as e: print(e) sys.stdout.write("\n") return if cmd_list[0] == "cd": if len(cmd_list) != 2: sys.stdout.write("cd method takes one argument\n\n") return try: path = cmd_list[1].strip() if path == "-": oldpwd = os.environ[ "OLDPWD"] if "OLDPWD" in os.environ else os.getcwd() os.environ["OLDPWD"] = os.getcwd() os.chdir(oldpwd) else: if sys.platform.startswith('win'): path = path.replace("\\", "/") if path.startswith('"') and path.endswith('"'): path = path[1:-1] path = os.path.expanduser(path) path = os.path.expandvars(path) os.environ["OLDPWD"] = os.getcwd() os.chdir(path) sys.stdout.write(os.getcwd()) sys.stdout.write("\n\n") except Exception as e: print(e) sys.stdout.write("\n") return else: if sys.platform.startswith('win'): p = subprocess.Popen(command, shell=True, stdin=sys.stdin, stdout=sys.stdout) else: shell = os.path.basename(os.environ.get("SHELL", "/bin/sh")) p = subprocess.Popen([shell, "-c", command], stdin=sys.stdin, stdout=sys.stdout) p.wait() sys.stdout.write("\n") return run_coroutine_in_terminal(lambda: run_in_executor(run_command))
def async_func(): f = run_in_executor(func) return f