Просмотр исходного кода

intermediate changes
ref:b4f892f3c2b06a356c155f73c27efc5661a7fb89

arcadia-devtools 2 лет назад
Родитель
Сommit
01fbacb386

+ 3 - 1
contrib/python/prompt-toolkit/py3/.dist-info/METADATA

@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: prompt-toolkit
-Version: 3.0.28
+Version: 3.0.29
 Summary: Library for building powerful interactive command lines in Python
 Home-page: https://github.com/prompt-toolkit/python-prompt-toolkit
 Author: Jonathan Slenders
@@ -21,6 +21,8 @@ Classifier: Programming Language :: Python
 Classifier: Topic :: Software Development
 Requires-Python: >=3.6.2
 Description-Content-Type: text/x-rst
+License-File: LICENSE
+License-File: AUTHORS.rst
 Requires-Dist: wcwidth
 
 Python Prompt Toolkit

+ 1 - 1
contrib/python/prompt-toolkit/py3/prompt_toolkit/__init__.py

@@ -18,7 +18,7 @@ from .formatted_text import ANSI, HTML
 from .shortcuts import PromptSession, print_formatted_text, prompt
 
 # Don't forget to update in `docs/conf.py`!
-__version__ = "3.0.28"
+__version__ = "3.0.29"
 
 # Version tuple.
 VERSION = tuple(__version__.split("."))

+ 6 - 3
contrib/python/prompt-toolkit/py3/prompt_toolkit/application/application.py

@@ -89,7 +89,6 @@ from prompt_toolkit.styles import (
 )
 from prompt_toolkit.utils import Event, in_main_thread
 
-from ..utils import is_windows
 from .current import get_app_session, set_app
 from .run_in_terminal import in_terminal, run_in_terminal
 
@@ -663,7 +662,7 @@ class Application(Generic[_AppResult]):
         """
         assert not self._is_running, "Application is already running."
 
-        if not in_main_thread() or is_windows():
+        if not in_main_thread() or sys.platform == "win32":
             # Handling signals in other threads is not supported.
             # Also on Windows, `add_signal_handler(signal.SIGINT, ...)` raises
             # `NotImplementedError`.
@@ -935,7 +934,11 @@ class Application(Generic[_AppResult]):
             set_event_loop(loop)
 
         return loop.run_until_complete(
-            self.run_async(pre_run=pre_run, set_exception_handler=set_exception_handler)
+            self.run_async(
+                pre_run=pre_run,
+                set_exception_handler=set_exception_handler,
+                handle_sigint=handle_sigint,
+            )
         )
 
     def _handle_exception(

+ 17 - 12
contrib/python/prompt-toolkit/py3/prompt_toolkit/contrib/ssh/server.py

@@ -10,7 +10,7 @@ import asyncssh
 from prompt_toolkit.application.current import AppSession, create_app_session
 from prompt_toolkit.data_structures import Size
 from prompt_toolkit.eventloop import get_event_loop
-from prompt_toolkit.input import create_pipe_input
+from prompt_toolkit.input import PipeInput, create_pipe_input
 from prompt_toolkit.output.vt100 import Vt100_Output
 
 __all__ = ["PromptToolkitSSHSession", "PromptToolkitSSHServer"]
@@ -28,7 +28,7 @@ class PromptToolkitSSHSession(asyncssh.SSHServerSession):  # type: ignore
         # PipInput object, for sending input in the CLI.
         # (This is something that we can use in the prompt_toolkit event loop,
         # but still write date in manually.)
-        self._input = create_pipe_input()
+        self._input: Optional[PipeInput] = None
         self._output: Optional[Vt100_Output] = None
 
         # Output object. Don't render to the real stdout, but write everything
@@ -88,16 +88,17 @@ class PromptToolkitSSHSession(asyncssh.SSHServerSession):  # type: ignore
         self._output = Vt100_Output(
             self.stdout, self._get_size, term=term, write_binary=False
         )
-        with create_app_session(input=self._input, output=self._output) as session:
-            self.app_session = session
-            try:
-                await self.interact(self)
-            except BaseException:
-                traceback.print_exc()
-            finally:
-                # Close the connection.
-                self._chan.close()
-                self._input.close()
+        with create_pipe_input() as self._input:
+            with create_app_session(input=self._input, output=self._output) as session:
+                self.app_session = session
+                try:
+                    await self.interact(self)
+                except BaseException:
+                    traceback.print_exc()
+                finally:
+                    # Close the connection.
+                    self._chan.close()
+                    self._input.close()
 
     def terminal_size_changed(
         self, width: int, height: int, pixwidth: object, pixheight: object
@@ -107,6 +108,10 @@ class PromptToolkitSSHSession(asyncssh.SSHServerSession):  # type: ignore
             self.app_session.app._on_resize()
 
     def data_received(self, data: str, datatype: object) -> None:
+        if self._input is None:
+            # Should not happen.
+            return
+
         self._input.send_text(data)
 
 

+ 44 - 24
contrib/python/prompt-toolkit/py3/prompt_toolkit/contrib/telnet/server.py

@@ -11,7 +11,7 @@ from prompt_toolkit.application.run_in_terminal import run_in_terminal
 from prompt_toolkit.data_structures import Size
 from prompt_toolkit.eventloop import get_event_loop
 from prompt_toolkit.formatted_text import AnyFormattedText, to_formatted_text
-from prompt_toolkit.input import create_pipe_input
+from prompt_toolkit.input import PipeInput, create_pipe_input
 from prompt_toolkit.output.vt100 import Vt100_Output
 from prompt_toolkit.renderer import print_formatted_text as print_formatted_text
 from prompt_toolkit.styles import BaseStyle, DummyStyle
@@ -87,6 +87,7 @@ class _ConnectionStdout:
         self._connection = connection
         self._errors = "strict"
         self._buffer: List[bytes] = []
+        self._closed = False
 
     def write(self, data: str) -> None:
         data = data.replace("\n", "\r\n")
@@ -98,12 +99,16 @@ class _ConnectionStdout:
 
     def flush(self) -> None:
         try:
-            self._connection.send(b"".join(self._buffer))
+            if not self._closed:
+                self._connection.send(b"".join(self._buffer))
         except OSError as e:
             logger.warning("Couldn't send data over socket: %s" % e)
 
         self._buffer = []
 
+    def close(self) -> None:
+        self._closed = True
+
     @property
     def encoding(self) -> str:
         return self._encoding
@@ -126,6 +131,7 @@ class TelnetConnection:
         server: "TelnetServer",
         encoding: str,
         style: Optional[BaseStyle],
+        vt100_input: PipeInput,
     ) -> None:
 
         self.conn = conn
@@ -136,6 +142,7 @@ class TelnetConnection:
         self.style = style
         self._closed = False
         self._ready = asyncio.Event()
+        self.vt100_input = vt100_input
         self.vt100_output = None
 
         # Create "Output" object.
@@ -144,9 +151,6 @@ class TelnetConnection:
         # Initialize.
         _initialize_telnet(conn)
 
-        # Create input.
-        self.vt100_input = create_pipe_input()
-
         # Create output.
         def get_size() -> Size:
             return self.size
@@ -160,8 +164,8 @@ class TelnetConnection:
         def size_received(rows: int, columns: int) -> None:
             """TelnetProtocolParser 'size_received' callback"""
             self.size = Size(rows=rows, columns=columns)
-            if self.vt100_output is not None:
-                get_app()._on_resize()
+            if self.vt100_output is not None and self.context:
+                self.context.run(lambda: get_app()._on_resize())
 
         def ttype_received(ttype: str) -> None:
             """TelnetProtocolParser 'ttype_received' callback"""
@@ -197,12 +201,6 @@ class TelnetConnection:
             with create_app_session(input=self.vt100_input, output=self.vt100_output):
                 self.context = contextvars.copy_context()
                 await self.interact(self)
-        except Exception as e:
-            print("Got %s" % type(e).__name__, e)
-            import traceback
-
-            traceback.print_exc()
-            raise
         finally:
             self.close()
 
@@ -222,6 +220,7 @@ class TelnetConnection:
             self.vt100_input.close()
             get_event_loop().remove_reader(self.conn)
             self.conn.close()
+            self.stdout.close()
 
     def send(self, formatted_text: AnyFormattedText) -> None:
         """
@@ -336,22 +335,43 @@ class TelnetServer:
         conn, addr = self._listen_socket.accept()
         logger.info("New connection %r %r", *addr)
 
-        connection = TelnetConnection(
-            conn, addr, self.interact, self, encoding=self.encoding, style=self.style
-        )
-        self.connections.add(connection)
-
         # Run application for this connection.
         async def run() -> None:
-            logger.info("Starting interaction %r %r", *addr)
             try:
-                await connection.run_application()
-            except Exception as e:
-                print(e)
+                with create_pipe_input() as vt100_input:
+                    connection = TelnetConnection(
+                        conn,
+                        addr,
+                        self.interact,
+                        self,
+                        encoding=self.encoding,
+                        style=self.style,
+                        vt100_input=vt100_input,
+                    )
+                    self.connections.add(connection)
+
+                    logger.info("Starting interaction %r %r", *addr)
+                    try:
+                        await connection.run_application()
+                    finally:
+                        self.connections.remove(connection)
+                        logger.info("Stopping interaction %r %r", *addr)
+            except EOFError:
+                # Happens either when the connection is closed by the client
+                # (e.g., when the user types 'control-]', then 'quit' in the
+                # telnet client) or when the user types control-d in a prompt
+                # and this is not handled by the interact function.
+                logger.info("Unhandled EOFError in telnet application.")
+            except KeyboardInterrupt:
+                # Unhandled control-c propagated by a prompt.
+                logger.info("Unhandled KeyboardInterrupt in telnet application.")
+            except BaseException as e:
+                print("Got %s" % type(e).__name__, e)
+                import traceback
+
+                traceback.print_exc()
             finally:
-                self.connections.remove(connection)
                 self._application_tasks.remove(task)
-                logger.info("Stopping interaction %r %r", *addr)
 
         task = get_event_loop().create_task(run())
         self._application_tasks.append(task)

+ 2 - 3
contrib/python/prompt-toolkit/py3/prompt_toolkit/eventloop/inputhook.py

@@ -26,13 +26,12 @@ import asyncio
 import os
 import select
 import selectors
+import sys
 import threading
 from asyncio import AbstractEventLoop
 from selectors import BaseSelector, SelectorKey
 from typing import TYPE_CHECKING, Any, Callable, List, Mapping, Optional, Tuple
 
-from prompt_toolkit.utils import is_windows
-
 from .utils import get_event_loop
 
 __all__ = [
@@ -141,7 +140,7 @@ class InputHookSelector(BaseSelector):
             #       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():
+            if sys.platform != "win32":
                 select.select([self._r], [], [], None)
 
             os.read(self._r, 1024)

+ 4 - 0
contrib/python/prompt-toolkit/py3/prompt_toolkit/eventloop/win32.py

@@ -1,3 +1,7 @@
+import sys
+
+assert sys.platform == "win32"
+
 from ctypes import pointer
 
 from ..utils import SPHINX_AUTODOC_RUNNING

+ 2 - 1
contrib/python/prompt-toolkit/py3/prompt_toolkit/input/__init__.py

@@ -1,9 +1,10 @@
-from .base import DummyInput, Input
+from .base import DummyInput, Input, PipeInput
 from .defaults import create_input, create_pipe_input
 
 __all__ = [
     # Base.
     "Input",
+    "PipeInput",
     "DummyInput",
     # Defaults.
     "create_input",

+ 6 - 0
contrib/python/prompt-toolkit/py3/prompt_toolkit/input/base.py

@@ -9,6 +9,7 @@ from prompt_toolkit.key_binding import KeyPress
 
 __all__ = [
     "Input",
+    "PipeInput",
     "DummyInput",
 ]
 
@@ -104,6 +105,9 @@ class PipeInput(Input):
 class DummyInput(Input):
     """
     Input for use in a `DummyApplication`
+
+    If used in an actual application, it will make the application render
+    itself once and exit immediately, due to an `EOFError`.
     """
 
     def fileno(self) -> int:
@@ -117,6 +121,8 @@ class DummyInput(Input):
 
     @property
     def closed(self) -> bool:
+        # This needs to be true, so that the dummy input will trigger an
+        # `EOFError` immediately in the application.
         return True
 
     def raw_mode(self) -> ContextManager[None]:

+ 14 - 8
contrib/python/prompt-toolkit/py3/prompt_toolkit/input/defaults.py

@@ -1,7 +1,5 @@
 import sys
-from typing import Optional, TextIO
-
-from prompt_toolkit.utils import is_windows
+from typing import ContextManager, Optional, TextIO
 
 from .base import DummyInput, Input, PipeInput
 
@@ -23,7 +21,7 @@ def create_input(
         `sys.stdin`. (We can open `stdout` or `stderr` for reading, this is how
         a `$PAGER` works.)
     """
-    if is_windows():
+    if sys.platform == "win32":
         from .win32 import Win32Input
 
         # If `stdin` was assigned `None` (which happens with pythonw.exe), use
@@ -48,16 +46,24 @@ def create_input(
         return Vt100Input(stdin)
 
 
-def create_pipe_input() -> PipeInput:
+def create_pipe_input() -> ContextManager[PipeInput]:
     """
     Create an input pipe.
     This is mostly useful for unit testing.
+
+    Usage::
+
+        with create_pipe_input() as input:
+            input.send_text('inputdata')
+
+    Breaking change: In prompt_toolkit 3.0.28 and earlier, this was returning
+    the `PipeInput` directly, rather than through a context manager.
     """
-    if is_windows():
+    if sys.platform == "win32":
         from .win32_pipe import Win32PipeInput
 
-        return Win32PipeInput()
+        return Win32PipeInput.create()
     else:
         from .posix_pipe import PosixPipeInput
 
-        return PosixPipeInput()
+        return PosixPipeInput.create()

Некоторые файлы не были показаны из-за большого количества измененных файлов