def embed(globals=None, locals=None, vi_mode=False, history_filename=None, no_colors=False, startup_paths=None, patch_stdout=False, return_asyncio_coroutine=False): """ Call this to embed Python shell at the current point in your program. It's similar to `IPython.embed` and `bpython.embed`. :: from prompt_toolkit.contrib.repl import embed embed(globals(), locals(), vi_mode=False) :param vi_mode: Boolean. Use Vi instead of Emacs key bindings. """ globals = globals or {} locals = locals or globals def get_globals(): return globals def get_locals(): return locals # Create eventloop. if return_asyncio_coroutine: eventloop = create_asyncio_eventloop() else: eventloop = create_eventloop() # Create REPL. repl = PythonRepl(eventloop, get_globals, get_locals, vi_mode=vi_mode, history_filename=history_filename, style=(None if no_colors else PythonStyle)) # Start repl. patch_context = repl.cli.patch_stdout_context( ) if patch_stdout else DummyContext() if return_asyncio_coroutine: def coroutine(): with patch_context: for future in repl.asyncio_start_repl(): yield future return coroutine() else: with patch_context: repl.start_repl(startup_paths=startup_paths)
def shell(globals_, locals_): """ Customized pypython.repl. """ # Create REPL. repl = PythonRepl( get_globals=lambda: globals_, get_locals=lambda: locals_, history_filename=os.path.expanduser("~/.pyhistory.shell"), ) run_config(repl) with DummyContext(): repl.run()
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 embed(globals=None, locals=None, configure=None, vi_mode=False, history_filename=None, title=None, startup_paths=None, patch_stdout=False, return_asyncio_coroutine=False): """ Call this to embed Python shell at the current point in your program. It's similar to `IPython.embed` and `bpython.embed`. :: from prompt_toolkit.contrib.repl import embed embed(globals(), locals()) :param vi_mode: Boolean. Use Vi instead of Emacs key bindings. :param configure: Callable that will be called with the `PythonRepl` as a first argument, to trigger configuration. :param title: Title to be displayed in the terminal titlebar. (None or string.) """ assert configure is None or callable(configure) # Default globals/locals if globals is None: globals = { '__name__': '__main__', '__package__': None, '__doc__': None, '__builtins__': six.moves.builtins, } locals = locals or globals def get_globals(): return globals def get_locals(): return locals # Create eventloop. if return_asyncio_coroutine: eventloop = create_asyncio_eventloop() else: eventloop = create_eventloop() # Create REPL. repl = PythonRepl(get_globals, get_locals, vi_mode=vi_mode, history_filename=history_filename, startup_paths=startup_paths) if title: repl.terminal_title = title if configure: configure(repl) cli = PythonCommandLineInterface(python_input=repl, eventloop=eventloop) # Start repl. patch_context = cli.patch_stdout_context( ) if patch_stdout else DummyContext() if return_asyncio_coroutine: def coroutine(): with patch_context: for future in cli.run_async(): yield future return coroutine() else: with patch_context: cli.run()
def embed( globals=None, locals=None, configure: Optional[Callable[[PythonRepl], None]] = None, vi_mode: bool = False, history_filename: Optional[str] = None, title: Optional[str] = None, startup_paths=None, patch_stdout: bool = False, return_asyncio_coroutine: bool = False, ) -> None: """ Call this to embed Python shell at the current point in your program. It's similar to `IPython.embed` and `bpython.embed`. :: from prompt_toolkit.contrib.repl import embed embed(globals(), locals()) :param vi_mode: Boolean. Use Vi instead of Emacs key bindings. :param configure: Callable that will be called with the `PythonRepl` as a first argument, to trigger configuration. :param title: Title to be displayed in the terminal titlebar. (None or string.) :param patch_stdout: When true, patch `sys.stdout` so that background threads that are printing will print nicely above the prompt. """ # Default globals/locals if globals is None: globals = { "__name__": "__main__", "__package__": None, "__doc__": None, "__builtins__": builtins, } locals = locals or globals def get_globals(): return globals def get_locals(): return locals # Create REPL. repl = PythonRepl( get_globals=get_globals, get_locals=get_locals, vi_mode=vi_mode, history_filename=history_filename, startup_paths=startup_paths, ) if title: repl.terminal_title = title if configure: configure(repl) # Start repl. patch_context: ContextManager = (patch_stdout_context() if patch_stdout else DummyContext()) if return_asyncio_coroutine: async def coroutine(): with patch_context: await repl.run_async() return coroutine() else: with patch_context: repl.run()
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 prompt(self, message='', **kwargs): """Get input from the user and return it. This is a wrapper around a lot of prompt_toolkit functionality and can be a replacement for raw_input. (or GNU readline.) If you want to keep your history across several calls, create one `~prompt_toolkit.history.History instance and pass it every time. This function accepts many keyword arguments. Except for the following. they are a proxy to the arguments of create_prompt_application(). Parameters ---------- patch_stdout : file-like, optional Replace ``sys.stdout`` by a proxy that ensures that print statements from other threads won't destroy the prompt. (They will be printed above the prompt instead.) return_asyncio_coroutine : bool, optional When True, return a asyncio coroutine. (Python >3.3) Notes ----- This method was forked from the mainline prompt-toolkit repo. Copyright (c) 2014, Jonathan Slenders, All rights reserved. """ patch_stdout = kwargs.pop('patch_stdout', False) return_asyncio_coroutine = kwargs.pop('return_asyncio_coroutine', False) if return_asyncio_coroutine: eventloop = create_asyncio_eventloop() else: eventloop = kwargs.pop('eventloop', None) or create_eventloop() # Create CommandLineInterface. if self.cli is None: if self.major_minor < (0, 57): kwargs.pop('reserve_space_for_menu', None) if self.major_minor <= (0, 57): kwargs.pop('get_rprompt_tokens', None) kwargs.pop('get_continuation_tokens', None) # VI_Mode handling changed in prompt_toolkit v1.0 if self.major_minor >= (1, 0): from prompt_toolkit.enums import EditingMode if builtins.__xonsh_env__.get('VI_MODE'): editing_mode = EditingMode.VI else: editing_mode = EditingMode.EMACS kwargs['editing_mode'] = editing_mode kwargs['vi_mode'] = builtins.__xonsh_env__.get('VI_MODE') cli = CommandLineInterface(application=create_prompt_application( message, **kwargs), eventloop=eventloop, output=create_output()) self.cli = cli else: cli = self.cli # Replace stdout. patch_context = cli.patch_stdout_context( ) if patch_stdout else DummyContext() # Read input and return it. if return_asyncio_coroutine: # Create an asyncio coroutine and call it. exec_context = {'patch_context': patch_context, 'cli': cli} exec( textwrap.dedent(''' import asyncio @asyncio.coroutine def prompt_coro(): with patch_context: document = yield from cli.run_async(reset_current_buffer=False) if document: return document.text '''), exec_context) return exec_context['prompt_coro']() else: # Note: We pass `reset_current_buffer=False`, because that way # it's easy to give DEFAULT_BUFFER a default value, without it # getting erased. We don't have to reset anyway, because this is # the first and only time that this CommandLineInterface will run. try: with patch_context: document = cli.run(reset_current_buffer=False) if document: return document.text finally: eventloop.close()
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 embed(globals=None, locals=None, configure=None, vi_mode=False, history_filename=None, title=None, startup_paths=None, patch_stdout=False, return_asyncio_coroutine=False): """ Call this to embed Python shell at the current point in your program. It's similar to `IPython.embed` and `bpython.embed`. :: from prompt_toolkit.contrib.repl import embed embed(globals(), locals()) :param vi_mode: Boolean. Use Vi instead of Emacs key bindings. :param configure: Callable that will be called with the `PythonRepl` as a first argument, to trigger configuration. :param title: Title to be displayed in the terminal titlebar. (None or string.) """ assert configure is None or callable(configure) # Default globals/locals if globals is None: globals = { '__name__': '__main__', '__package__': None, '__doc__': None, '__builtins__': six.moves.builtins, } locals = locals or globals def get_globals(): return globals def get_locals(): return locals # Create eventloop. if return_asyncio_coroutine: use_asyncio_event_loop() # Create REPL. repl = PythonRepl(get_globals=get_globals, get_locals=get_locals, vi_mode=vi_mode, history_filename=history_filename, startup_paths=startup_paths) if title: repl.terminal_title = title if configure: configure(repl) app = repl.app # Start repl. patch_context = patch_stdout_context() if patch_stdout else DummyContext() if return_asyncio_coroutine: # XXX def coroutine(): with patch_context: while True: iterator = iter(app.run_async().to_asyncio_future()) try: while True: yield next(iterator) except StopIteration as exc: text = exc.args[0] repl._process_text(text) return coroutine() else: with patch_context: repl.run()
def prompt(self, message="", **kwargs): """Get input from the user and return it. This is a wrapper around a lot of prompt_toolkit functionality and can be a replacement for raw_input. (or GNU readline.) If you want to keep your history across several calls, create one `~prompt_toolkit.history.History instance and pass it every time. This function accepts many keyword arguments. Except for the following. they are a proxy to the arguments of create_prompt_application(). Parameters ---------- patch_stdout : file-like, optional Replace ``sys.stdout`` by a proxy that ensures that print statements from other threads won't destroy the prompt. (They will be printed above the prompt instead.) return_asyncio_coroutine : bool, optional When True, return a asyncio coroutine. (Python >3.3) Notes ----- This method was forked from the mainline prompt-toolkit repo. Copyright (c) 2014, Jonathan Slenders, All rights reserved. """ patch_stdout = kwargs.pop("patch_stdout", False) return_asyncio_coroutine = kwargs.pop("return_asyncio_coroutine", False) if return_asyncio_coroutine: eventloop = create_asyncio_eventloop() else: eventloop = kwargs.pop("eventloop", None) or create_eventloop() # Create CommandLineInterface. if self.cli is None: if builtins.__xonsh_env__.get("VI_MODE"): editing_mode = EditingMode.VI else: editing_mode = EditingMode.EMACS kwargs["editing_mode"] = editing_mode cli = CommandLineInterface( application=create_prompt_application(message, **kwargs), eventloop=eventloop, output=create_output(), ) self.cli = cli else: cli = self.cli # Replace stdout. patch_context = cli.patch_stdout_context( ) if patch_stdout else DummyContext() # Read input and return it. if return_asyncio_coroutine: # Create an asyncio coroutine and call it. exec_context = {"patch_context": patch_context, "cli": cli} exec( textwrap.dedent(""" import asyncio @asyncio.coroutine def prompt_coro(): with patch_context: document = yield from cli.run_async(reset_current_buffer=False) if document: return document.text """), exec_context, ) return exec_context["prompt_coro"]() else: # Note: We pass `reset_current_buffer=False`, because that way # it's easy to give DEFAULT_BUFFER a default value, without it # getting erased. We don't have to reset anyway, because this is # the first and only time that this CommandLineInterface will run. try: with patch_context: document = cli.run(reset_current_buffer=False) if document: return document.text except Exception: xt.print_exception() # return something to prevent xonsh crash when any # exceptions raise return "" finally: eventloop.close()