Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
|
@ -0,0 +1,28 @@
|
|||
from .application import Application
|
||||
from .current import (
|
||||
AppSession,
|
||||
create_app_session,
|
||||
get_app,
|
||||
get_app_or_none,
|
||||
get_app_session,
|
||||
set_app,
|
||||
)
|
||||
from .dummy import DummyApplication
|
||||
from .run_in_terminal import in_terminal, run_in_terminal
|
||||
|
||||
__all__ = [
|
||||
# Application.
|
||||
"Application",
|
||||
# Current.
|
||||
"AppSession",
|
||||
"get_app_session",
|
||||
"create_app_session",
|
||||
"get_app",
|
||||
"get_app_or_none",
|
||||
"set_app",
|
||||
# Dummy.
|
||||
"DummyApplication",
|
||||
# Run_in_terminal
|
||||
"in_terminal",
|
||||
"run_in_terminal",
|
||||
]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
1224
venv/Lib/site-packages/prompt_toolkit/application/application.py
Normal file
1224
venv/Lib/site-packages/prompt_toolkit/application/application.py
Normal file
File diff suppressed because it is too large
Load diff
170
venv/Lib/site-packages/prompt_toolkit/application/current.py
Normal file
170
venv/Lib/site-packages/prompt_toolkit/application/current.py
Normal file
|
@ -0,0 +1,170 @@
|
|||
import sys
|
||||
from contextlib import contextmanager
|
||||
from typing import TYPE_CHECKING, Any, Generator, Optional
|
||||
|
||||
try:
|
||||
from contextvars import ContextVar
|
||||
except ImportError:
|
||||
from prompt_toolkit.eventloop.dummy_contextvars import ContextVar # type: ignore
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from prompt_toolkit.input.defaults import Input
|
||||
from prompt_toolkit.output.defaults import Output
|
||||
|
||||
from .application import Application
|
||||
|
||||
__all__ = [
|
||||
"AppSession",
|
||||
"get_app_session",
|
||||
"get_app",
|
||||
"get_app_or_none",
|
||||
"set_app",
|
||||
"create_app_session",
|
||||
]
|
||||
|
||||
|
||||
class AppSession:
|
||||
"""
|
||||
An AppSession is an interactive session, usually connected to one terminal.
|
||||
Within one such session, interaction with many applications can happen, one
|
||||
after the other.
|
||||
|
||||
The input/output device is not supposed to change during one session.
|
||||
|
||||
Warning: Always use the `create_app_session` function to create an
|
||||
instance, so that it gets activated correctly.
|
||||
|
||||
:param input: Use this as a default input for all applications
|
||||
running in this session, unless an input is passed to the `Application`
|
||||
explicitely.
|
||||
:param output: Use this as a default output.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, input: Optional["Input"] = None, output: Optional["Output"] = None
|
||||
) -> None:
|
||||
|
||||
self._input = input
|
||||
self._output = output
|
||||
|
||||
# The application will be set dynamically by the `set_app` context
|
||||
# manager. This is called in the application itself.
|
||||
self.app: Optional["Application[Any]"] = None
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "AppSession(app=%r)" % (self.app,)
|
||||
|
||||
@property
|
||||
def input(self) -> "Input":
|
||||
if self._input is None:
|
||||
from prompt_toolkit.input.defaults import create_input
|
||||
|
||||
self._input = create_input()
|
||||
return self._input
|
||||
|
||||
@property
|
||||
def output(self) -> "Output":
|
||||
if self._output is None:
|
||||
from prompt_toolkit.output.defaults import create_output
|
||||
|
||||
self._output = create_output()
|
||||
return self._output
|
||||
|
||||
|
||||
_current_app_session: ContextVar["AppSession"] = ContextVar(
|
||||
"_current_app_session", default=AppSession()
|
||||
)
|
||||
|
||||
|
||||
def get_app_session() -> AppSession:
|
||||
return _current_app_session.get()
|
||||
|
||||
|
||||
def get_app() -> "Application[Any]":
|
||||
"""
|
||||
Get the current active (running) Application.
|
||||
An :class:`.Application` is active during the
|
||||
:meth:`.Application.run_async` call.
|
||||
|
||||
We assume that there can only be one :class:`.Application` active at the
|
||||
same time. There is only one terminal window, with only one stdin and
|
||||
stdout. This makes the code significantly easier than passing around the
|
||||
:class:`.Application` everywhere.
|
||||
|
||||
If no :class:`.Application` is running, then return by default a
|
||||
:class:`.DummyApplication`. For practical reasons, we prefer to not raise
|
||||
an exception. This way, we don't have to check all over the place whether
|
||||
an actual `Application` was returned.
|
||||
|
||||
(For applications like pymux where we can have more than one `Application`,
|
||||
we'll use a work-around to handle that.)
|
||||
"""
|
||||
session = _current_app_session.get()
|
||||
if session.app is not None:
|
||||
return session.app
|
||||
|
||||
from .dummy import DummyApplication
|
||||
|
||||
return DummyApplication()
|
||||
|
||||
|
||||
def get_app_or_none() -> Optional["Application[Any]"]:
|
||||
"""
|
||||
Get the current active (running) Application, or return `None` if no
|
||||
application is running.
|
||||
"""
|
||||
session = _current_app_session.get()
|
||||
return session.app
|
||||
|
||||
|
||||
@contextmanager
|
||||
def set_app(app: "Application[Any]") -> Generator[None, None, None]:
|
||||
"""
|
||||
Context manager that sets the given :class:`.Application` active in an
|
||||
`AppSession`.
|
||||
|
||||
This should only be called by the `Application` itself.
|
||||
The application will automatically be active while its running. If you want
|
||||
the application to be active in other threads/coroutines, where that's not
|
||||
the case, use `contextvars.copy_context()`, or use `Application.context` to
|
||||
run it in the appropriate context.
|
||||
"""
|
||||
session = _current_app_session.get()
|
||||
|
||||
previous_app = session.app
|
||||
session.app = app
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
session.app = previous_app
|
||||
|
||||
|
||||
@contextmanager
|
||||
def create_app_session(
|
||||
input: Optional["Input"] = None, output: Optional["Output"] = None
|
||||
) -> Generator[AppSession, None, None]:
|
||||
"""
|
||||
Create a separate AppSession.
|
||||
|
||||
This is useful if there can be multiple individual `AppSession`s going on.
|
||||
Like in the case of an Telnet/SSH server. This functionality uses
|
||||
contextvars and requires at least Python 3.7.
|
||||
"""
|
||||
if sys.version_info <= (3, 6):
|
||||
raise RuntimeError("Application sessions require Python 3.7.")
|
||||
|
||||
# If no input/output is specified, fall back to the current input/output,
|
||||
# whatever that is.
|
||||
if input is None:
|
||||
input = get_app_session().input
|
||||
if output is None:
|
||||
output = get_app_session().output
|
||||
|
||||
# Create new `AppSession` and activate.
|
||||
session = AppSession(input=input, output=output)
|
||||
|
||||
token = _current_app_session.set(session)
|
||||
try:
|
||||
yield session
|
||||
finally:
|
||||
_current_app_session.reset(token)
|
47
venv/Lib/site-packages/prompt_toolkit/application/dummy.py
Normal file
47
venv/Lib/site-packages/prompt_toolkit/application/dummy.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
from typing import Callable, Optional
|
||||
|
||||
from prompt_toolkit.formatted_text import AnyFormattedText
|
||||
from prompt_toolkit.input import DummyInput
|
||||
from prompt_toolkit.output import DummyOutput
|
||||
|
||||
from .application import Application
|
||||
|
||||
__all__ = [
|
||||
"DummyApplication",
|
||||
]
|
||||
|
||||
|
||||
class DummyApplication(Application[None]):
|
||||
"""
|
||||
When no :class:`.Application` is running,
|
||||
:func:`.get_app` will run an instance of this :class:`.DummyApplication` instead.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__(output=DummyOutput(), input=DummyInput())
|
||||
|
||||
def run(
|
||||
self,
|
||||
pre_run: Optional[Callable[[], None]] = None,
|
||||
set_exception_handler: bool = True,
|
||||
) -> None:
|
||||
raise NotImplementedError("A DummyApplication is not supposed to run.")
|
||||
|
||||
async def run_async(
|
||||
self,
|
||||
pre_run: Optional[Callable[[], None]] = None,
|
||||
set_exception_handler: bool = True,
|
||||
) -> None:
|
||||
raise NotImplementedError("A DummyApplication is not supposed to run.")
|
||||
|
||||
async def run_system_command(
|
||||
self,
|
||||
command: str,
|
||||
wait_for_enter: bool = True,
|
||||
display_before_text: AnyFormattedText = "",
|
||||
wait_text: str = "",
|
||||
) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def suspend_to_background(self, suspend_group: bool = True) -> None:
|
||||
raise NotImplementedError
|
|
@ -0,0 +1,116 @@
|
|||
"""
|
||||
Tools for running functions on the terminal above the current application or prompt.
|
||||
"""
|
||||
from asyncio import Future, ensure_future
|
||||
from typing import AsyncGenerator, Awaitable, Callable, TypeVar
|
||||
|
||||
from prompt_toolkit.eventloop import run_in_executor_with_context
|
||||
|
||||
from .current import get_app_or_none
|
||||
|
||||
try:
|
||||
from contextlib import asynccontextmanager # type: ignore
|
||||
except ImportError:
|
||||
from prompt_toolkit.eventloop.async_context_manager import asynccontextmanager
|
||||
|
||||
|
||||
__all__ = [
|
||||
"run_in_terminal",
|
||||
"in_terminal",
|
||||
]
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
def run_in_terminal(
|
||||
func: Callable[[], _T], render_cli_done: bool = False, in_executor: bool = False
|
||||
) -> Awaitable[_T]:
|
||||
"""
|
||||
Run function on the terminal above the current application or prompt.
|
||||
|
||||
What this does is first hiding the prompt, then running this callable
|
||||
(which can safely output to the terminal), and then again rendering the
|
||||
prompt which causes the output of this function to scroll above the
|
||||
prompt.
|
||||
|
||||
``func`` is supposed to be a synchronous function. If you need an
|
||||
asynchronous version of this function, use the ``in_terminal`` context
|
||||
manager directly.
|
||||
|
||||
:param func: The callable to execute.
|
||||
:param render_cli_done: When True, render the interface in the
|
||||
'Done' state first, then execute the function. If False,
|
||||
erase the interface first.
|
||||
:param in_executor: When True, run in executor. (Use this for long
|
||||
blocking functions, when you don't want to block the event loop.)
|
||||
|
||||
:returns: A `Future`.
|
||||
"""
|
||||
|
||||
async def run() -> _T:
|
||||
async with in_terminal(render_cli_done=render_cli_done):
|
||||
if in_executor:
|
||||
return await run_in_executor_with_context(func)
|
||||
else:
|
||||
return func()
|
||||
|
||||
return ensure_future(run())
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def in_terminal(render_cli_done: bool = False) -> AsyncGenerator[None, None]:
|
||||
"""
|
||||
Asynchronous context manager that suspends the current application and runs
|
||||
the body in the terminal.
|
||||
|
||||
.. code::
|
||||
|
||||
async def f():
|
||||
async with in_terminal():
|
||||
call_some_function()
|
||||
await call_some_async_function()
|
||||
"""
|
||||
app = get_app_or_none()
|
||||
if app is None or not app._is_running:
|
||||
yield
|
||||
return
|
||||
|
||||
# When a previous `run_in_terminal` call was in progress. Wait for that
|
||||
# to finish, before starting this one. Chain to previous call.
|
||||
previous_run_in_terminal_f = app._running_in_terminal_f
|
||||
new_run_in_terminal_f: Future[None] = Future()
|
||||
app._running_in_terminal_f = new_run_in_terminal_f
|
||||
|
||||
# Wait for the previous `run_in_terminal` to finish.
|
||||
if previous_run_in_terminal_f is not None:
|
||||
await 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.output.responds_to_cpr:
|
||||
await 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():
|
||||
yield
|
||||
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)
|
Loading…
Add table
Add a link
Reference in a new issue