]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-108996: fix and enable test_msvcrt (#109226)
authorAN Long <aisk@users.noreply.github.com>
Fri, 22 Sep 2023 00:19:48 +0000 (08:19 +0800)
committerGitHub <noreply@github.com>
Fri, 22 Sep 2023 00:19:48 +0000 (02:19 +0200)
* Add _testconsole.flush_console_input_buffer() function.
* test_kbhit(), test_getwch() and test_getwche() now call
  flush_console_input_buffer().
* Don't override sys.stdin anymore (not needed).

Lib/test/test_msvcrt.py
Misc/NEWS.d/next/Tests/2023-09-10-23-05-50.gh-issue-108996.tJBru6.rst [new file with mode: 0644]
PC/_testconsole.c
PC/clinic/_testconsole.c.h

index 3a63de351e095d4d9514f111bf1096c0fe09a60e..81ec13026014e6fbf214a896b5b8680fcb4a0fbd 100644 (file)
@@ -2,8 +2,6 @@ import os
 import sys
 import unittest
 
-raise unittest.SkipTest("FIXME! broken test see: https://github.com/python/cpython/pull/109004")
-
 from test.support import os_helper
 from test.support.os_helper import TESTFN, TESTFN_ASCII
 
@@ -13,7 +11,7 @@ if sys.platform != "win32":
 import _winapi
 import msvcrt;
 
-from _testconsole import write_input
+from _testconsole import write_input, flush_console_input_buffer
 
 
 class TestFileOperations(unittest.TestCase):
@@ -64,6 +62,8 @@ c_encoded = b'\x57\x5b' # utf-16-le (which windows internally used) encoded char
 
 class TestConsoleIO(unittest.TestCase):
     def test_kbhit(self):
+        h = msvcrt.get_osfhandle(sys.stdin.fileno())
+        flush_console_input_buffer(h)
         self.assertEqual(msvcrt.kbhit(), 0)
 
     def test_getch(self):
@@ -71,28 +71,24 @@ class TestConsoleIO(unittest.TestCase):
         self.assertEqual(msvcrt.getch(), b'c')
 
     def test_getwch(self):
-        stdin = open('CONIN$', 'r')
-        old_stdin = sys.stdin
-        try:
-            sys.stdin = stdin
-            write_input(stdin.buffer.raw, c_encoded)
+        with open('CONIN$', 'rb', buffering=0) as stdin:
+            h = msvcrt.get_osfhandle(stdin.fileno())
+            flush_console_input_buffer(h)
+
+            write_input(stdin, c_encoded)
             self.assertEqual(msvcrt.getwch(), c)
-        finally:
-            sys.stdin = old_stdin
 
     def test_getche(self):
         msvcrt.ungetch(b'c')
         self.assertEqual(msvcrt.getche(), b'c')
 
     def test_getwche(self):
-        stdin = open('CONIN$', 'r')
-        old_stdin = sys.stdin
-        try:
-            sys.stdin = stdin
-            write_input(stdin.buffer.raw, c_encoded)
+        with open('CONIN$', 'rb', buffering=0) as stdin:
+            h = msvcrt.get_osfhandle(stdin.fileno())
+            flush_console_input_buffer(h)
+
+            write_input(stdin, c_encoded)
             self.assertEqual(msvcrt.getwche(), c)
-        finally:
-            sys.stdin = old_stdin
 
     def test_putch(self):
         msvcrt.putch(b'c')
diff --git a/Misc/NEWS.d/next/Tests/2023-09-10-23-05-50.gh-issue-108996.tJBru6.rst b/Misc/NEWS.d/next/Tests/2023-09-10-23-05-50.gh-issue-108996.tJBru6.rst
new file mode 100644 (file)
index 0000000..ab6b5b5
--- /dev/null
@@ -0,0 +1 @@
+Fix and enable ``test_msvcrt``.\r
index 3221b985d01ba0c2ffaa9f32d19a7fd70115c155..5e5a771b96bfecee03857c3a4a9bd090fece0ce6 100644 (file)
@@ -35,6 +35,23 @@ PyModuleDef_Slot testconsole_slots[] = {
     {0, NULL},
 };
 
+/*[python input]
+class HANDLE_converter(CConverter):
+    type = 'void *'
+    format_unit = '"_Py_PARSE_UINTPTR"'
+
+    def parse_arg(self, argname, displayname, *, limited_capi):
+        return self.format_code("""
+            {paramname} = PyLong_AsVoidPtr({argname});
+            if (!{paramname} && PyErr_Occurred()) {{{{
+                goto exit;
+            }}}}
+            """,
+            argname=argname)
+[python start generated code]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=380aa5c91076742b]*/
+/*[python end generated code:]*/
+
 /*[clinic input]
 module _testconsole
 
@@ -116,11 +133,31 @@ _testconsole_read_output_impl(PyObject *module, PyObject *file)
     Py_RETURN_NONE;
 }
 
+/*[clinic input]
+_testconsole.flush_console_input_buffer
+    handle: HANDLE
+
+Flushes the console input buffer.
+
+All input records currently in the input buffer are discarded.
+[clinic start generated code]*/
+
+static PyObject *
+_testconsole_flush_console_input_buffer_impl(PyObject *module, void *handle)
+/*[clinic end generated code: output=1f923a81331465ce input=be8203ae84a288f5]*/
+/*[clinic end generated code:]*/
+{
+    FlushConsoleInputBuffer(handle);
+
+    Py_RETURN_NONE;
+}
+
 #include "clinic\_testconsole.c.h"
 
 PyMethodDef testconsole_methods[] = {
     _TESTCONSOLE_WRITE_INPUT_METHODDEF
     _TESTCONSOLE_READ_OUTPUT_METHODDEF
+    _TESTCONSOLE_FLUSH_CONSOLE_INPUT_BUFFER_METHODDEF
     {NULL, NULL}
 };
 
index 99cd302ff34698b0ec838bcfa10a7179beadbba2..b76588909782ea37425dfa1629dbab0ddac1c221 100644 (file)
@@ -132,6 +132,70 @@ exit:
 
 #endif /* defined(MS_WINDOWS) */
 
+#if defined(MS_WINDOWS)
+
+PyDoc_STRVAR(_testconsole_flush_console_input_buffer__doc__,
+"flush_console_input_buffer($module, /, handle)\n"
+"--\n"
+"\n"
+"Flushes the console input buffer.\n"
+"\n"
+"All input records currently in the input buffer are discarded.");
+
+#define _TESTCONSOLE_FLUSH_CONSOLE_INPUT_BUFFER_METHODDEF    \
+    {"flush_console_input_buffer", _PyCFunction_CAST(_testconsole_flush_console_input_buffer), METH_FASTCALL|METH_KEYWORDS, _testconsole_flush_console_input_buffer__doc__},
+
+static PyObject *
+_testconsole_flush_console_input_buffer_impl(PyObject *module, void *handle);
+
+static PyObject *
+_testconsole_flush_console_input_buffer(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+    #define NUM_KEYWORDS 1
+    static struct {
+        PyGC_Head _this_is_not_used;
+        PyObject_VAR_HEAD
+        PyObject *ob_item[NUM_KEYWORDS];
+    } _kwtuple = {
+        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+        .ob_item = { &_Py_ID(handle), },
+    };
+    #undef NUM_KEYWORDS
+    #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+    #else  // !Py_BUILD_CORE
+    #  define KWTUPLE NULL
+    #endif  // !Py_BUILD_CORE
+
+    static const char * const _keywords[] = {"handle", NULL};
+    static _PyArg_Parser _parser = {
+        .keywords = _keywords,
+        .fname = "flush_console_input_buffer",
+        .kwtuple = KWTUPLE,
+    };
+    #undef KWTUPLE
+    PyObject *argsbuf[1];
+    void *handle;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    handle = PyLong_AsVoidPtr(args[0]);
+    if (!handle && PyErr_Occurred()) {
+        goto exit;
+    }
+    return_value = _testconsole_flush_console_input_buffer_impl(module, handle);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(MS_WINDOWS) */
+
 #ifndef _TESTCONSOLE_WRITE_INPUT_METHODDEF
     #define _TESTCONSOLE_WRITE_INPUT_METHODDEF
 #endif /* !defined(_TESTCONSOLE_WRITE_INPUT_METHODDEF) */
@@ -139,4 +203,8 @@ exit:
 #ifndef _TESTCONSOLE_READ_OUTPUT_METHODDEF
     #define _TESTCONSOLE_READ_OUTPUT_METHODDEF
 #endif /* !defined(_TESTCONSOLE_READ_OUTPUT_METHODDEF) */
-/*[clinic end generated code: output=f59fe72cd4e73704 input=a9049054013a1b77]*/
+
+#ifndef _TESTCONSOLE_FLUSH_CONSOLE_INPUT_BUFFER_METHODDEF
+    #define _TESTCONSOLE_FLUSH_CONSOLE_INPUT_BUFFER_METHODDEF
+#endif /* !defined(_TESTCONSOLE_FLUSH_CONSOLE_INPUT_BUFFER_METHODDEF) */
+/*[clinic end generated code: output=5d488564f2500dd9 input=a9049054013a1b77]*/