Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
26
venv/Lib/site-packages/prompt_toolkit/eventloop/__init__.py
Normal file
26
venv/Lib/site-packages/prompt_toolkit/eventloop/__init__.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
from .async_generator import generator_to_async_generator
|
||||
from .inputhook import (
|
||||
InputHookContext,
|
||||
InputHookSelector,
|
||||
new_eventloop_with_inputhook,
|
||||
set_eventloop_with_inputhook,
|
||||
)
|
||||
from .utils import (
|
||||
call_soon_threadsafe,
|
||||
get_traceback_from_context,
|
||||
run_in_executor_with_context,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# Async generator
|
||||
"generator_to_async_generator",
|
||||
# Utils.
|
||||
"run_in_executor_with_context",
|
||||
"call_soon_threadsafe",
|
||||
"get_traceback_from_context",
|
||||
# Inputhooks.
|
||||
"new_eventloop_with_inputhook",
|
||||
"set_eventloop_with_inputhook",
|
||||
"InputHookSelector",
|
||||
"InputHookContext",
|
||||
]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,124 @@
|
|||
"""
|
||||
@asynccontextmanager code, copied from Python 3.7's contextlib.
|
||||
For usage in Python 3.6.
|
||||
"""
|
||||
import abc
|
||||
from functools import wraps
|
||||
|
||||
import _collections_abc
|
||||
|
||||
__all__ = ["asynccontextmanager"]
|
||||
|
||||
|
||||
class AbstractAsyncContextManager(abc.ABC):
|
||||
|
||||
"""An abstract base class for asynchronous context managers."""
|
||||
|
||||
async def __aenter__(self):
|
||||
"""Return `self` upon entering the runtime context."""
|
||||
return self
|
||||
|
||||
@abc.abstractmethod
|
||||
async def __aexit__(self, exc_type, exc_value, traceback):
|
||||
"""Raise any exception triggered within the runtime context."""
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def __subclasshook__(cls, C):
|
||||
if cls is AbstractAsyncContextManager:
|
||||
return _collections_abc._check_methods(C, "__aenter__", "__aexit__")
|
||||
return NotImplemented
|
||||
|
||||
|
||||
class _GeneratorContextManagerBase:
|
||||
"""Shared functionality for @contextmanager and @asynccontextmanager."""
|
||||
|
||||
def __init__(self, func, args, kwds):
|
||||
self.gen = func(*args, **kwds)
|
||||
self.func, self.args, self.kwds = func, args, kwds
|
||||
# Issue 19330: ensure context manager instances have good docstrings
|
||||
doc = getattr(func, "__doc__", None)
|
||||
if doc is None:
|
||||
doc = type(self).__doc__
|
||||
self.__doc__ = doc
|
||||
# Unfortunately, this still doesn't provide good help output when
|
||||
# inspecting the created context manager instances, since pydoc
|
||||
# currently bypasses the instance docstring and shows the docstring
|
||||
# for the class instead.
|
||||
# See http://bugs.python.org/issue19404 for more details.
|
||||
|
||||
|
||||
class _AsyncGeneratorContextManager(
|
||||
_GeneratorContextManagerBase, AbstractAsyncContextManager
|
||||
):
|
||||
"""Helper for @asynccontextmanager."""
|
||||
|
||||
async def __aenter__(self):
|
||||
try:
|
||||
return await self.gen.__anext__()
|
||||
except StopAsyncIteration:
|
||||
raise RuntimeError("generator didn't yield") from None
|
||||
|
||||
async def __aexit__(self, typ, value, traceback):
|
||||
if typ is None:
|
||||
try:
|
||||
await self.gen.__anext__()
|
||||
except StopAsyncIteration:
|
||||
return
|
||||
else:
|
||||
raise RuntimeError("generator didn't stop")
|
||||
else:
|
||||
if value is None:
|
||||
value = typ()
|
||||
# See _GeneratorContextManager.__exit__ for comments on subtleties
|
||||
# in this implementation
|
||||
try:
|
||||
await self.gen.athrow(typ, value, traceback)
|
||||
raise RuntimeError("generator didn't stop after athrow()")
|
||||
except StopAsyncIteration as exc:
|
||||
return exc is not value
|
||||
except RuntimeError as exc:
|
||||
if exc is value:
|
||||
return False
|
||||
# Avoid suppressing if a StopIteration exception
|
||||
# was passed to throw() and later wrapped into a RuntimeError
|
||||
# (see PEP 479 for sync generators; async generators also
|
||||
# have this behavior). But do this only if the exception wrapped
|
||||
# by the RuntimeError is actully Stop(Async)Iteration (see
|
||||
# issue29692).
|
||||
if isinstance(value, (StopIteration, StopAsyncIteration)):
|
||||
if exc.__cause__ is value:
|
||||
return False
|
||||
raise
|
||||
except BaseException as exc:
|
||||
if exc is not value:
|
||||
raise
|
||||
|
||||
|
||||
def asynccontextmanager(func):
|
||||
"""@asynccontextmanager decorator.
|
||||
Typical usage:
|
||||
@asynccontextmanager
|
||||
async def some_async_generator(<arguments>):
|
||||
<setup>
|
||||
try:
|
||||
yield <value>
|
||||
finally:
|
||||
<cleanup>
|
||||
This makes this:
|
||||
async with some_async_generator(<arguments>) as <variable>:
|
||||
<body>
|
||||
equivalent to this:
|
||||
<setup>
|
||||
try:
|
||||
<variable> = <value>
|
||||
<body>
|
||||
finally:
|
||||
<cleanup>
|
||||
"""
|
||||
|
||||
@wraps(func)
|
||||
def helper(*args, **kwds):
|
||||
return _AsyncGeneratorContextManager(func, args, kwds)
|
||||
|
||||
return helper
|
|
@ -0,0 +1,67 @@
|
|||
"""
|
||||
Implementation for async generators.
|
||||
"""
|
||||
from asyncio import Queue, get_event_loop
|
||||
from typing import AsyncGenerator, Callable, Iterable, TypeVar, Union
|
||||
|
||||
from .utils import run_in_executor_with_context
|
||||
|
||||
__all__ = [
|
||||
"generator_to_async_generator",
|
||||
]
|
||||
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
class _Done:
|
||||
pass
|
||||
|
||||
|
||||
async def generator_to_async_generator(
|
||||
get_iterable: Callable[[], Iterable[_T]]
|
||||
) -> AsyncGenerator[_T, None]:
|
||||
"""
|
||||
Turn a generator or iterable into an async generator.
|
||||
|
||||
This works by running the generator in a background thread.
|
||||
|
||||
:param get_iterable: Function that returns a generator or iterable when
|
||||
called.
|
||||
"""
|
||||
quitting = False
|
||||
_done = _Done()
|
||||
q: Queue[Union[_T, _Done]] = Queue()
|
||||
loop = get_event_loop()
|
||||
|
||||
def runner() -> None:
|
||||
"""
|
||||
Consume the generator in background thread.
|
||||
When items are received, they'll be pushed to the queue.
|
||||
"""
|
||||
try:
|
||||
for item in get_iterable():
|
||||
loop.call_soon_threadsafe(q.put_nowait, item)
|
||||
|
||||
# When this async generator was cancelled (closed), stop this
|
||||
# thread.
|
||||
if quitting:
|
||||
break
|
||||
|
||||
finally:
|
||||
loop.call_soon_threadsafe(q.put_nowait, _done)
|
||||
|
||||
# Start background thread.
|
||||
run_in_executor_with_context(runner)
|
||||
|
||||
try:
|
||||
while True:
|
||||
item = await q.get()
|
||||
if isinstance(item, _Done):
|
||||
break
|
||||
else:
|
||||
yield item
|
||||
finally:
|
||||
# When this async generator is closed (GeneratorExit exception, stop
|
||||
# the background thread as well. - we don't need that anymore.)
|
||||
quitting = True
|
|
@ -0,0 +1,46 @@
|
|||
"""
|
||||
Dummy contextvars implementation, to make prompt_toolkit work on Python 3.6.
|
||||
|
||||
As long as there is only one application running at a time, we don't need the
|
||||
real contextvars. So, stuff like the telnet-server and so on requires 3.7.
|
||||
"""
|
||||
from typing import Any, Callable, Generic, Optional, TypeVar
|
||||
|
||||
|
||||
def copy_context() -> "Context":
|
||||
return Context()
|
||||
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
class Context:
|
||||
def run(self, callable: Callable[..., _T], *args: Any, **kwargs: Any) -> _T:
|
||||
return callable(*args, **kwargs)
|
||||
|
||||
|
||||
class Token(Generic[_T]):
|
||||
pass
|
||||
|
||||
|
||||
class ContextVar(Generic[_T]):
|
||||
def __init__(self, name: str, *, default: Optional[_T] = None) -> None:
|
||||
self._name = name
|
||||
self._value = default
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._name
|
||||
|
||||
def get(self, default: Optional[_T] = None) -> _T:
|
||||
result = self._value or default
|
||||
if result is None:
|
||||
raise LookupError
|
||||
return result
|
||||
|
||||
def set(self, value: _T) -> Token[_T]:
|
||||
self._value = value
|
||||
return Token()
|
||||
|
||||
def reset(self, token: Token[_T]) -> None:
|
||||
pass
|
170
venv/Lib/site-packages/prompt_toolkit/eventloop/inputhook.py
Normal file
170
venv/Lib/site-packages/prompt_toolkit/eventloop/inputhook.py
Normal file
|
@ -0,0 +1,170 @@
|
|||
"""
|
||||
Similar to `PyOS_InputHook` of the Python API, we can plug in an input hook in
|
||||
the asyncio event loop.
|
||||
|
||||
The way this works is by using a custom 'selector' that runs the other event
|
||||
loop until the real selector is ready.
|
||||
|
||||
It's the responsibility of this event hook to return when there is input ready.
|
||||
There are two ways to detect when input is ready:
|
||||
|
||||
The inputhook itself is a callable that receives an `InputHookContext`. This
|
||||
callable should run the other event loop, and return when the main loop has
|
||||
stuff to do. There are two ways to detect when to return:
|
||||
|
||||
- Call the `input_is_ready` method periodically. Quit when this returns `True`.
|
||||
|
||||
- Add the `fileno` as a watch to the external eventloop. Quit when file descriptor
|
||||
becomes readable. (But don't read from it.)
|
||||
|
||||
Note that this is not the same as checking for `sys.stdin.fileno()`. The
|
||||
eventloop of prompt-toolkit allows thread-based executors, for example for
|
||||
asynchronous autocompletion. When the completion for instance is ready, we
|
||||
also want prompt-toolkit to gain control again in order to display that.
|
||||
"""
|
||||
import asyncio
|
||||
import os
|
||||
import select
|
||||
import selectors
|
||||
import threading
|
||||
from asyncio import AbstractEventLoop, get_event_loop
|
||||
from selectors import BaseSelector
|
||||
from typing import Callable
|
||||
|
||||
from prompt_toolkit.utils import is_windows
|
||||
|
||||
__all__ = [
|
||||
"new_eventloop_with_inputhook",
|
||||
"set_eventloop_with_inputhook",
|
||||
"InputHookSelector",
|
||||
"InputHookContext",
|
||||
]
|
||||
|
||||
|
||||
def new_eventloop_with_inputhook(
|
||||
inputhook: Callable[["InputHookContext"], None]
|
||||
) -> AbstractEventLoop:
|
||||
"""
|
||||
Create a new event loop with the given inputhook.
|
||||
"""
|
||||
selector = InputHookSelector(selectors.DefaultSelector(), inputhook)
|
||||
loop = asyncio.SelectorEventLoop(selector)
|
||||
return loop
|
||||
|
||||
|
||||
def set_eventloop_with_inputhook(
|
||||
inputhook: Callable[["InputHookContext"], None]
|
||||
) -> AbstractEventLoop:
|
||||
"""
|
||||
Create a new event loop with the given inputhook, and activate it.
|
||||
"""
|
||||
loop = new_eventloop_with_inputhook(inputhook)
|
||||
asyncio.set_event_loop(loop)
|
||||
return loop
|
||||
|
||||
|
||||
class InputHookSelector(BaseSelector):
|
||||
"""
|
||||
Usage:
|
||||
|
||||
selector = selectors.SelectSelector()
|
||||
loop = asyncio.SelectorEventLoop(InputHookSelector(selector, inputhook))
|
||||
asyncio.set_event_loop(loop)
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, selector: BaseSelector, inputhook: Callable[["InputHookContext"], None]
|
||||
) -> None:
|
||||
self.selector = selector
|
||||
self.inputhook = inputhook
|
||||
self._r, self._w = os.pipe()
|
||||
|
||||
def register(self, fileobj, events, data=None):
|
||||
return self.selector.register(fileobj, events, data=data)
|
||||
|
||||
def unregister(self, fileobj):
|
||||
return self.selector.unregister(fileobj)
|
||||
|
||||
def modify(self, fileobj, events, data=None):
|
||||
return self.selector.modify(fileobj, events, data=None)
|
||||
|
||||
def select(self, timeout=None):
|
||||
# If there are tasks in the current event loop,
|
||||
# don't run the input hook.
|
||||
if len(get_event_loop()._ready) > 0:
|
||||
return self.selector.select(timeout=timeout)
|
||||
|
||||
ready = False
|
||||
result = None
|
||||
|
||||
# Run selector in other thread.
|
||||
def run_selector() -> None:
|
||||
nonlocal ready, result
|
||||
result = self.selector.select(timeout=timeout)
|
||||
os.write(self._w, b"x")
|
||||
ready = True
|
||||
|
||||
th = threading.Thread(target=run_selector)
|
||||
th.start()
|
||||
|
||||
def input_is_ready() -> bool:
|
||||
return ready
|
||||
|
||||
# Call inputhook.
|
||||
# The inputhook function is supposed to return when our selector
|
||||
# becomes ready. The inputhook can do that by registering the fd in its
|
||||
# own loop, or by checking the `input_is_ready` function regularly.
|
||||
self.inputhook(InputHookContext(self._r, input_is_ready))
|
||||
|
||||
# Flush the read end of the pipe.
|
||||
try:
|
||||
# Before calling 'os.read', call select.select. This is required
|
||||
# when the gevent monkey patch has been applied. 'os.read' is never
|
||||
# monkey patched and won't be cooperative, so that would block all
|
||||
# other select() calls otherwise.
|
||||
# See: http://www.gevent.org/gevent.os.html
|
||||
|
||||
# Note: On Windows, this is apparently not an issue.
|
||||
# However, if we would ever want to add a select call, it
|
||||
# should use `windll.kernel32.WaitForMultipleObjects`,
|
||||
# because `select.select` can't wait for a pipe on Windows.
|
||||
if not is_windows():
|
||||
select.select([self._r], [], [], None)
|
||||
|
||||
os.read(self._r, 1024)
|
||||
except OSError:
|
||||
# This happens when the window resizes and a SIGWINCH was received.
|
||||
# We get 'Error: [Errno 4] Interrupted system call'
|
||||
# Just ignore.
|
||||
pass
|
||||
|
||||
# Wait for the real selector to be done.
|
||||
th.join()
|
||||
return result
|
||||
|
||||
def close(self) -> None:
|
||||
"""
|
||||
Clean up resources.
|
||||
"""
|
||||
if self._r:
|
||||
os.close(self._r)
|
||||
os.close(self._w)
|
||||
|
||||
self._r = self._w = -1
|
||||
self.selector.close()
|
||||
|
||||
def get_map(self):
|
||||
return self.selector.get_map()
|
||||
|
||||
|
||||
class InputHookContext:
|
||||
"""
|
||||
Given as a parameter to the inputhook.
|
||||
"""
|
||||
|
||||
def __init__(self, fileno: int, input_is_ready: Callable[[], bool]) -> None:
|
||||
self._fileno = fileno
|
||||
self.input_is_ready = input_is_ready
|
||||
|
||||
def fileno(self) -> int:
|
||||
return self._fileno
|
100
venv/Lib/site-packages/prompt_toolkit/eventloop/utils.py
Normal file
100
venv/Lib/site-packages/prompt_toolkit/eventloop/utils.py
Normal file
|
@ -0,0 +1,100 @@
|
|||
import sys
|
||||
import time
|
||||
from asyncio import AbstractEventLoop, get_event_loop
|
||||
from types import TracebackType
|
||||
from typing import Any, Awaitable, Callable, Dict, Optional, TypeVar
|
||||
|
||||
try:
|
||||
import contextvars
|
||||
except ImportError:
|
||||
from . import dummy_contextvars as contextvars # type: ignore
|
||||
|
||||
__all__ = [
|
||||
"run_in_executor_with_context",
|
||||
"call_soon_threadsafe",
|
||||
"get_traceback_from_context",
|
||||
]
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
def run_in_executor_with_context(
|
||||
func: Callable[..., _T], *args: Any, loop: Optional[AbstractEventLoop] = None
|
||||
) -> Awaitable[_T]:
|
||||
"""
|
||||
Run a function in an executor, but make sure it uses the same contextvars.
|
||||
This is required so that the function will see the right application.
|
||||
|
||||
See also: https://bugs.python.org/issue34014
|
||||
"""
|
||||
loop = loop or get_event_loop()
|
||||
ctx: contextvars.Context = contextvars.copy_context()
|
||||
|
||||
return loop.run_in_executor(None, ctx.run, func, *args)
|
||||
|
||||
|
||||
def call_soon_threadsafe(
|
||||
func: Callable[[], None],
|
||||
max_postpone_time: Optional[float] = None,
|
||||
loop: Optional[AbstractEventLoop] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Wrapper around asyncio's `call_soon_threadsafe`.
|
||||
|
||||
This takes a `max_postpone_time` which can be used to tune the urgency of
|
||||
the method.
|
||||
|
||||
Asyncio runs tasks in first-in-first-out. However, this is not what we
|
||||
want for the render function of the prompt_toolkit UI. Rendering is
|
||||
expensive, but since the UI is invalidated very often, in some situations
|
||||
we render the UI too often, so much that the rendering CPU usage slows down
|
||||
the rest of the processing of the application. (Pymux is an example where
|
||||
we have to balance the CPU time spend on rendering the UI, and parsing
|
||||
process output.)
|
||||
However, we want to set a deadline value, for when the rendering should
|
||||
happen. (The UI should stay responsive).
|
||||
"""
|
||||
loop2 = loop or get_event_loop()
|
||||
|
||||
# If no `max_postpone_time` has been given, schedule right now.
|
||||
if max_postpone_time is None:
|
||||
loop2.call_soon_threadsafe(func)
|
||||
return
|
||||
|
||||
max_postpone_until = time.time() + max_postpone_time
|
||||
|
||||
def schedule() -> None:
|
||||
# When there are no other tasks scheduled in the event loop. Run it
|
||||
# now.
|
||||
# Notice: uvloop doesn't have this _ready attribute. In that case,
|
||||
# always call immediately.
|
||||
if not getattr(loop2, "_ready", []): # type: ignore
|
||||
func()
|
||||
return
|
||||
|
||||
# If the timeout expired, run this now.
|
||||
if time.time() > max_postpone_until:
|
||||
func()
|
||||
return
|
||||
|
||||
# Schedule again for later.
|
||||
loop2.call_soon_threadsafe(schedule)
|
||||
|
||||
loop2.call_soon_threadsafe(schedule)
|
||||
|
||||
|
||||
def get_traceback_from_context(context: Dict[str, Any]) -> Optional[TracebackType]:
|
||||
"""
|
||||
Get the traceback object from the context.
|
||||
"""
|
||||
exception = context.get("exception")
|
||||
if exception:
|
||||
if hasattr(exception, "__traceback__"):
|
||||
return exception.__traceback__
|
||||
else:
|
||||
# call_exception_handler() is usually called indirectly
|
||||
# from an except block. If it's not the case, the traceback
|
||||
# is undefined...
|
||||
return sys.exc_info()[2]
|
||||
|
||||
return None
|
61
venv/Lib/site-packages/prompt_toolkit/eventloop/win32.py
Normal file
61
venv/Lib/site-packages/prompt_toolkit/eventloop/win32.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
from ctypes import pointer, windll
|
||||
from ctypes.wintypes import BOOL, DWORD, HANDLE
|
||||
from typing import List, Optional
|
||||
|
||||
from prompt_toolkit.win32_types import SECURITY_ATTRIBUTES
|
||||
|
||||
__all__ = ["wait_for_handles", "create_win32_event"]
|
||||
|
||||
|
||||
WAIT_TIMEOUT = 0x00000102
|
||||
INFINITE = -1
|
||||
|
||||
|
||||
def wait_for_handles(
|
||||
handles: List[HANDLE], timeout: int = INFINITE
|
||||
) -> Optional[HANDLE]:
|
||||
"""
|
||||
Waits for multiple handles. (Similar to 'select') Returns the handle which is ready.
|
||||
Returns `None` on timeout.
|
||||
http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx
|
||||
|
||||
Note that handles should be a list of `HANDLE` objects, not integers. See
|
||||
this comment in the patch by @quark-zju for the reason why:
|
||||
|
||||
''' Make sure HANDLE on Windows has a correct size
|
||||
|
||||
Previously, the type of various HANDLEs are native Python integer
|
||||
types. The ctypes library will treat them as 4-byte integer when used
|
||||
in function arguments. On 64-bit Windows, HANDLE is 8-byte and usually
|
||||
a small integer. Depending on whether the extra 4 bytes are zero-ed out
|
||||
or not, things can happen to work, or break. '''
|
||||
|
||||
This function returns either `None` or one of the given `HANDLE` objects.
|
||||
(The return value can be tested with the `is` operator.)
|
||||
"""
|
||||
arrtype = HANDLE * len(handles)
|
||||
handle_array = arrtype(*handles)
|
||||
|
||||
ret = windll.kernel32.WaitForMultipleObjects(
|
||||
len(handle_array), handle_array, BOOL(False), DWORD(timeout)
|
||||
)
|
||||
|
||||
if ret == WAIT_TIMEOUT:
|
||||
return None
|
||||
else:
|
||||
return handles[ret]
|
||||
|
||||
|
||||
def create_win32_event() -> HANDLE:
|
||||
"""
|
||||
Creates a Win32 unnamed Event .
|
||||
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx
|
||||
"""
|
||||
return HANDLE(
|
||||
windll.kernel32.CreateEventA(
|
||||
pointer(SECURITY_ATTRIBUTES()),
|
||||
BOOL(True), # Manual reset event.
|
||||
BOOL(False), # Initial state.
|
||||
None, # Unnamed event object.
|
||||
)
|
||||
)
|
Loading…
Add table
Add a link
Reference in a new issue