Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
_winconsole.py280 linesDownload Raw Back to click
1# This module is based on the excellent work by Adam Bartoš who2# provided a lot of what went into the implementation here in3# the discussion to issue1602 in the Python bug tracker.4#5# There are some general differences in regards to how this works6# compared to the original patches as we do not need to patch7# the entire interpreter but just work in our little world of8# echo and prompt.9import io10import sys11import time12import typing as t13from ctypes import byref14from ctypes import c_char15from ctypes import c_char_p16from ctypes import c_int17from ctypes import c_ssize_t18from ctypes import c_ulong19from ctypes import c_void_p20from ctypes import POINTER21from ctypes import py_object22from ctypes import Structure23from ctypes.wintypes import DWORD24from ctypes.wintypes import HANDLE25from ctypes.wintypes import LPCWSTR26from ctypes.wintypes import LPWSTR27 28from ._compat import _NonClosingTextIOWrapper29 30assert sys.platform == "win32"31import msvcrt  # noqa: E40232from ctypes import windll  # noqa: E40233from ctypes import WINFUNCTYPE  # noqa: E40234 35c_ssize_p = POINTER(c_ssize_t)36 37kernel32 = windll.kernel3238GetStdHandle = kernel32.GetStdHandle39ReadConsoleW = kernel32.ReadConsoleW40WriteConsoleW = kernel32.WriteConsoleW41GetConsoleMode = kernel32.GetConsoleMode42GetLastError = kernel32.GetLastError43GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32))44CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))(45    ("CommandLineToArgvW", windll.shell32)46)47LocalFree = WINFUNCTYPE(c_void_p, c_void_p)(("LocalFree", windll.kernel32))48 49STDIN_HANDLE = GetStdHandle(-10)50STDOUT_HANDLE = GetStdHandle(-11)51STDERR_HANDLE = GetStdHandle(-12)52 53PyBUF_SIMPLE = 054PyBUF_WRITABLE = 155 56ERROR_SUCCESS = 057ERROR_NOT_ENOUGH_MEMORY = 858ERROR_OPERATION_ABORTED = 99559 60STDIN_FILENO = 061STDOUT_FILENO = 162STDERR_FILENO = 263 64EOF = b"\x1a"65MAX_BYTES_WRITTEN = 3276766 67try:68    from ctypes import pythonapi69except ImportError:70    # On PyPy we cannot get buffers so our ability to operate here is71    # severely limited.72    get_buffer = None73else:74 75    class Py_buffer(Structure):76        _fields_ = [77            ("buf", c_void_p),78            ("obj", py_object),79            ("len", c_ssize_t),80            ("itemsize", c_ssize_t),81            ("readonly", c_int),82            ("ndim", c_int),83            ("format", c_char_p),84            ("shape", c_ssize_p),85            ("strides", c_ssize_p),86            ("suboffsets", c_ssize_p),87            ("internal", c_void_p),88        ]89 90    PyObject_GetBuffer = pythonapi.PyObject_GetBuffer91    PyBuffer_Release = pythonapi.PyBuffer_Release92 93    def get_buffer(obj, writable=False):94        buf = Py_buffer()95        flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE96        PyObject_GetBuffer(py_object(obj), byref(buf), flags)97 98        try:99            buffer_type = c_char * buf.len100            return buffer_type.from_address(buf.buf)101        finally:102            PyBuffer_Release(byref(buf))103 104 105class _WindowsConsoleRawIOBase(io.RawIOBase):106    def __init__(self, handle):107        self.handle = handle108 109    def isatty(self):110        super().isatty()111        return True112 113 114class _WindowsConsoleReader(_WindowsConsoleRawIOBase):115    def readable(self):116        return True117 118    def readinto(self, b):119        bytes_to_be_read = len(b)120        if not bytes_to_be_read:121            return 0122        elif bytes_to_be_read % 2:123            raise ValueError(124                "cannot read odd number of bytes from UTF-16-LE encoded console"125            )126 127        buffer = get_buffer(b, writable=True)128        code_units_to_be_read = bytes_to_be_read // 2129        code_units_read = c_ulong()130 131        rv = ReadConsoleW(132            HANDLE(self.handle),133            buffer,134            code_units_to_be_read,135            byref(code_units_read),136            None,137        )138        if GetLastError() == ERROR_OPERATION_ABORTED:139            # wait for KeyboardInterrupt140            time.sleep(0.1)141        if not rv:142            raise OSError(f"Windows error: {GetLastError()}")143 144        if buffer[0] == EOF:145            return 0146        return 2 * code_units_read.value147 148 149class _WindowsConsoleWriter(_WindowsConsoleRawIOBase):150    def writable(self):151        return True152 153    @staticmethod154    def _get_error_message(errno):155        if errno == ERROR_SUCCESS:156            return "ERROR_SUCCESS"157        elif errno == ERROR_NOT_ENOUGH_MEMORY:158            return "ERROR_NOT_ENOUGH_MEMORY"159        return f"Windows error {errno}"160 161    def write(self, b):162        bytes_to_be_written = len(b)163        buf = get_buffer(b)164        code_units_to_be_written = min(bytes_to_be_written, MAX_BYTES_WRITTEN) // 2165        code_units_written = c_ulong()166 167        WriteConsoleW(168            HANDLE(self.handle),169            buf,170            code_units_to_be_written,171            byref(code_units_written),172            None,173        )174        bytes_written = 2 * code_units_written.value175 176        if bytes_written == 0 and bytes_to_be_written > 0:177            raise OSError(self._get_error_message(GetLastError()))178        return bytes_written179 180 181class ConsoleStream:182    def __init__(self, text_stream: t.TextIO, byte_stream: t.BinaryIO) -> None:183        self._text_stream = text_stream184        self.buffer = byte_stream185 186    @property187    def name(self) -> str:188        return self.buffer.name189 190    def write(self, x: t.AnyStr) -> int:191        if isinstance(x, str):192            return self._text_stream.write(x)193        try:194            self.flush()195        except Exception:196            pass197        return self.buffer.write(x)198 199    def writelines(self, lines: t.Iterable[t.AnyStr]) -> None:200        for line in lines:201            self.write(line)202 203    def __getattr__(self, name: str) -> t.Any:204        return getattr(self._text_stream, name)205 206    def isatty(self) -> bool:207        return self.buffer.isatty()208 209    def __repr__(self):210        return f"<ConsoleStream name={self.name!r} encoding={self.encoding!r}>"211 212 213def _get_text_stdin(buffer_stream: t.BinaryIO) -> t.TextIO:214    text_stream = _NonClosingTextIOWrapper(215        io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)),216        "utf-16-le",217        "strict",218        line_buffering=True,219    )220    return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream))221 222 223def _get_text_stdout(buffer_stream: t.BinaryIO) -> t.TextIO:224    text_stream = _NonClosingTextIOWrapper(225        io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)),226        "utf-16-le",227        "strict",228        line_buffering=True,229    )230    return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream))231 232 233def _get_text_stderr(buffer_stream: t.BinaryIO) -> t.TextIO:234    text_stream = _NonClosingTextIOWrapper(235        io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)),236        "utf-16-le",237        "strict",238        line_buffering=True,239    )240    return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream))241 242 243_stream_factories: t.Mapping[int, t.Callable[[t.BinaryIO], t.TextIO]] = {244    0: _get_text_stdin,245    1: _get_text_stdout,246    2: _get_text_stderr,247}248 249 250def _is_console(f: t.TextIO) -> bool:251    if not hasattr(f, "fileno"):252        return False253 254    try:255        fileno = f.fileno()256    except (OSError, io.UnsupportedOperation):257        return False258 259    handle = msvcrt.get_osfhandle(fileno)260    return bool(GetConsoleMode(handle, byref(DWORD())))261 262 263def _get_windows_console_stream(264    f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str]265) -> t.Optional[t.TextIO]:266    if (267        get_buffer is not None268        and encoding in {"utf-16-le", None}269        and errors in {"strict", None}270        and _is_console(f)271    ):272        func = _stream_factories.get(f.fileno())273        if func is not None:274            b = getattr(f, "buffer", None)275 276            if b is None:277                return None278 279            return func(b)280 
codekingpro/portable-devtools · Team Ai