diff --git a/Lib/test/test_msvcrt.py b/Lib/test/test_msvcrt.py index 3a63de351e095d..81ec13026014e6 100644 --- a/Lib/test/test_msvcrt.py +++ b/Lib/test/test_msvcrt.py @@ -2,8 +2,6 @@ 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 @@ 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 @@ def test_get_osfhandle(self): 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 @@ def test_getch(self): 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 index 00000000000000..ab6b5b5952b044 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2023-09-10-23-05-50.gh-issue-108996.tJBru6.rst @@ -0,0 +1 @@ +Fix and enable ``test_msvcrt``. diff --git a/PC/_testconsole.c b/PC/_testconsole.c index 3221b985d01ba0..5e5a771b96bfec 100644 --- a/PC/_testconsole.c +++ b/PC/_testconsole.c @@ -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} }; diff --git a/PC/clinic/_testconsole.c.h b/PC/clinic/_testconsole.c.h index 99cd302ff34698..b76588909782ea 100644 --- a/PC/clinic/_testconsole.c.h +++ b/PC/clinic/_testconsole.c.h @@ -132,6 +132,70 @@ _testconsole_read_output(PyObject *module, PyObject *const *args, Py_ssize_t nar #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 @@ _testconsole_read_output(PyObject *module, PyObject *const *args, Py_ssize_t nar #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]*/