Browse Source
Issue #28217: Adds _testconsole module to test console input. Fixes some issues found by the tests.
pull/9921/head
Issue #28217: Adds _testconsole module to test console input. Fixes some issues found by the tests.
pull/9921/head
11 changed files with 460 additions and 21 deletions
-
70Lib/test/test_winconsoleio.py
-
4Misc/NEWS
-
3Modules/_io/_iomodule.h
-
54Modules/_io/winconsoleio.c
-
131PC/_testconsole.c
-
82PC/clinic/_testconsole.c.h
-
83PCbuild/_testconsole.vcxproj
-
22PCbuild/_testconsole.vcxproj.filters
-
2PCbuild/pcbuild.proj
-
18PCbuild/pcbuild.sln
-
12Tools/msi/test/test_files.wxs
@ -0,0 +1,131 @@ |
|||
|
|||
/* Testing module for multi-phase initialization of extension modules (PEP 489) |
|||
*/ |
|||
|
|||
#include "Python.h" |
|||
|
|||
#ifdef MS_WINDOWS |
|||
|
|||
#include "..\modules\_io\_iomodule.h" |
|||
|
|||
#define WIN32_LEAN_AND_MEAN |
|||
#include <windows.h> |
|||
#include <fcntl.h> |
|||
|
|||
/* The full definition is in iomodule. We reproduce |
|||
enough here to get the handle, which is all we want. */ |
|||
typedef struct { |
|||
PyObject_HEAD |
|||
HANDLE handle; |
|||
} winconsoleio; |
|||
|
|||
|
|||
static int execfunc(PyObject *m) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
PyModuleDef_Slot testconsole_slots[] = { |
|||
{Py_mod_exec, execfunc}, |
|||
{0, NULL}, |
|||
}; |
|||
|
|||
/*[clinic input] |
|||
module _testconsole |
|||
|
|||
_testconsole.write_input |
|||
file: object |
|||
s: PyBytesObject |
|||
|
|||
Writes UTF-16-LE encoded bytes to the console as if typed by a user. |
|||
[clinic start generated code]*/ |
|||
|
|||
static PyObject * |
|||
_testconsole_write_input_impl(PyObject *module, PyObject *file, |
|||
PyBytesObject *s) |
|||
/*[clinic end generated code: output=48f9563db34aedb3 input=4c774f2d05770bc6]*/ |
|||
{ |
|||
INPUT_RECORD *rec = NULL; |
|||
|
|||
if (!PyWindowsConsoleIO_Check(file)) { |
|||
PyErr_SetString(PyExc_TypeError, "expected raw console object"); |
|||
return NULL; |
|||
} |
|||
|
|||
const wchar_t *p = (const wchar_t *)PyBytes_AS_STRING(s); |
|||
DWORD size = (DWORD)PyBytes_GET_SIZE(s) / sizeof(wchar_t); |
|||
|
|||
rec = (INPUT_RECORD*)PyMem_Malloc(sizeof(INPUT_RECORD) * size); |
|||
if (!rec) |
|||
goto error; |
|||
memset(rec, 0, sizeof(INPUT_RECORD) * size); |
|||
|
|||
INPUT_RECORD *prec = rec; |
|||
for (DWORD i = 0; i < size; ++i, ++p, ++prec) { |
|||
prec->EventType = KEY_EVENT; |
|||
prec->Event.KeyEvent.bKeyDown = TRUE; |
|||
prec->Event.KeyEvent.wRepeatCount = 10; |
|||
prec->Event.KeyEvent.uChar.UnicodeChar = *p; |
|||
} |
|||
|
|||
HANDLE hInput = ((winconsoleio*)file)->handle; |
|||
DWORD total = 0; |
|||
while (total < size) { |
|||
DWORD wrote; |
|||
if (!WriteConsoleInputW(hInput, &rec[total], (size - total), &wrote)) { |
|||
PyErr_SetFromWindowsErr(0); |
|||
goto error; |
|||
} |
|||
total += wrote; |
|||
} |
|||
|
|||
PyMem_Free((void*)rec); |
|||
|
|||
Py_RETURN_NONE; |
|||
error: |
|||
if (rec) |
|||
PyMem_Free((void*)rec); |
|||
return NULL; |
|||
} |
|||
|
|||
/*[clinic input] |
|||
_testconsole.read_output |
|||
file: object |
|||
|
|||
Reads a str from the console as written to stdout. |
|||
[clinic start generated code]*/ |
|||
|
|||
static PyObject * |
|||
_testconsole_read_output_impl(PyObject *module, PyObject *file) |
|||
/*[clinic end generated code: output=876310d81a73e6d2 input=b3521f64b1b558e3]*/ |
|||
{ |
|||
Py_RETURN_NONE; |
|||
} |
|||
|
|||
#include "clinic\_testconsole.c.h" |
|||
|
|||
PyMethodDef testconsole_methods[] = { |
|||
_TESTCONSOLE_WRITE_INPUT_METHODDEF |
|||
_TESTCONSOLE_READ_OUTPUT_METHODDEF |
|||
{NULL, NULL} |
|||
}; |
|||
|
|||
static PyModuleDef testconsole_def = { |
|||
PyModuleDef_HEAD_INIT, /* m_base */ |
|||
"_testconsole", /* m_name */ |
|||
PyDoc_STR("Test module for the Windows console"), /* m_doc */ |
|||
0, /* m_size */ |
|||
testconsole_methods, /* m_methods */ |
|||
testconsole_slots, /* m_slots */ |
|||
NULL, /* m_traverse */ |
|||
NULL, /* m_clear */ |
|||
NULL, /* m_free */ |
|||
}; |
|||
|
|||
PyMODINIT_FUNC |
|||
PyInit__testconsole(PyObject *spec) |
|||
{ |
|||
return PyModuleDef_Init(&testconsole_def); |
|||
} |
|||
|
|||
#endif /* MS_WINDOWS */ |
|||
@ -0,0 +1,82 @@ |
|||
/*[clinic input] |
|||
preserve |
|||
[clinic start generated code]*/ |
|||
|
|||
#if defined(MS_WINDOWS) |
|||
|
|||
PyDoc_STRVAR(_testconsole_write_input__doc__, |
|||
"write_input($module, /, file, s)\n" |
|||
"--\n" |
|||
"\n" |
|||
"Writes UTF-16-LE encoded bytes to the console as if typed by a user."); |
|||
|
|||
#define _TESTCONSOLE_WRITE_INPUT_METHODDEF \ |
|||
{"write_input", (PyCFunction)_testconsole_write_input, METH_FASTCALL, _testconsole_write_input__doc__}, |
|||
|
|||
static PyObject * |
|||
_testconsole_write_input_impl(PyObject *module, PyObject *file, |
|||
PyBytesObject *s); |
|||
|
|||
static PyObject * |
|||
_testconsole_write_input(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) |
|||
{ |
|||
PyObject *return_value = NULL; |
|||
static const char * const _keywords[] = {"file", "s", NULL}; |
|||
static _PyArg_Parser _parser = {"OS:write_input", _keywords, 0}; |
|||
PyObject *file; |
|||
PyBytesObject *s; |
|||
|
|||
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser, |
|||
&file, &s)) { |
|||
goto exit; |
|||
} |
|||
return_value = _testconsole_write_input_impl(module, file, s); |
|||
|
|||
exit: |
|||
return return_value; |
|||
} |
|||
|
|||
#endif /* defined(MS_WINDOWS) */ |
|||
|
|||
#if defined(MS_WINDOWS) |
|||
|
|||
PyDoc_STRVAR(_testconsole_read_output__doc__, |
|||
"read_output($module, /, file)\n" |
|||
"--\n" |
|||
"\n" |
|||
"Reads a str from the console as written to stdout."); |
|||
|
|||
#define _TESTCONSOLE_READ_OUTPUT_METHODDEF \ |
|||
{"read_output", (PyCFunction)_testconsole_read_output, METH_FASTCALL, _testconsole_read_output__doc__}, |
|||
|
|||
static PyObject * |
|||
_testconsole_read_output_impl(PyObject *module, PyObject *file); |
|||
|
|||
static PyObject * |
|||
_testconsole_read_output(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) |
|||
{ |
|||
PyObject *return_value = NULL; |
|||
static const char * const _keywords[] = {"file", NULL}; |
|||
static _PyArg_Parser _parser = {"O:read_output", _keywords, 0}; |
|||
PyObject *file; |
|||
|
|||
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser, |
|||
&file)) { |
|||
goto exit; |
|||
} |
|||
return_value = _testconsole_read_output_impl(module, file); |
|||
|
|||
exit: |
|||
return return_value; |
|||
} |
|||
|
|||
#endif /* defined(MS_WINDOWS) */ |
|||
|
|||
#ifndef _TESTCONSOLE_WRITE_INPUT_METHODDEF |
|||
#define _TESTCONSOLE_WRITE_INPUT_METHODDEF |
|||
#endif /* !defined(_TESTCONSOLE_WRITE_INPUT_METHODDEF) */ |
|||
|
|||
#ifndef _TESTCONSOLE_READ_OUTPUT_METHODDEF |
|||
#define _TESTCONSOLE_READ_OUTPUT_METHODDEF |
|||
#endif /* !defined(_TESTCONSOLE_READ_OUTPUT_METHODDEF) */ |
|||
/*[clinic end generated code: output=3a8dc0c421807c41 input=a9049054013a1b77]*/ |
|||
@ -0,0 +1,83 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup Label="ProjectConfigurations"> |
|||
<ProjectConfiguration Include="Debug|Win32"> |
|||
<Configuration>Debug</Configuration> |
|||
<Platform>Win32</Platform> |
|||
</ProjectConfiguration> |
|||
<ProjectConfiguration Include="Debug|x64"> |
|||
<Configuration>Debug</Configuration> |
|||
<Platform>x64</Platform> |
|||
</ProjectConfiguration> |
|||
<ProjectConfiguration Include="PGInstrument|Win32"> |
|||
<Configuration>PGInstrument</Configuration> |
|||
<Platform>Win32</Platform> |
|||
</ProjectConfiguration> |
|||
<ProjectConfiguration Include="PGInstrument|x64"> |
|||
<Configuration>PGInstrument</Configuration> |
|||
<Platform>x64</Platform> |
|||
</ProjectConfiguration> |
|||
<ProjectConfiguration Include="PGUpdate|Win32"> |
|||
<Configuration>PGUpdate</Configuration> |
|||
<Platform>Win32</Platform> |
|||
</ProjectConfiguration> |
|||
<ProjectConfiguration Include="PGUpdate|x64"> |
|||
<Configuration>PGUpdate</Configuration> |
|||
<Platform>x64</Platform> |
|||
</ProjectConfiguration> |
|||
<ProjectConfiguration Include="Release|Win32"> |
|||
<Configuration>Release</Configuration> |
|||
<Platform>Win32</Platform> |
|||
</ProjectConfiguration> |
|||
<ProjectConfiguration Include="Release|x64"> |
|||
<Configuration>Release</Configuration> |
|||
<Platform>x64</Platform> |
|||
</ProjectConfiguration> |
|||
</ItemGroup> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>{B244E787-C445-441C-BDF4-5A4F1A3A1E51}</ProjectGuid> |
|||
<Keyword>Win32Proj</Keyword> |
|||
<RootNamespace>_testconsole</RootNamespace> |
|||
<SupportPGO>false</SupportPGO> |
|||
</PropertyGroup> |
|||
<Import Project="python.props" /> |
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
|||
<PropertyGroup Label="Configuration"> |
|||
<ConfigurationType>DynamicLibrary</ConfigurationType> |
|||
<CharacterSet>NotSet</CharacterSet> |
|||
</PropertyGroup> |
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
|||
<PropertyGroup> |
|||
<TargetExt>.pyd</TargetExt> |
|||
</PropertyGroup> |
|||
<ImportGroup Label="ExtensionSettings"> |
|||
</ImportGroup> |
|||
<ImportGroup Label="PropertySheets"> |
|||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
|||
<Import Project="pyproject.props" /> |
|||
</ImportGroup> |
|||
<PropertyGroup Label="UserMacros" /> |
|||
<ItemDefinitionGroup> |
|||
<ClCompile> |
|||
<PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
|||
</ClCompile> |
|||
<Link> |
|||
<SubSystem>Console</SubSystem> |
|||
</Link> |
|||
</ItemDefinitionGroup> |
|||
<ItemGroup> |
|||
<ClCompile Include="..\PC\_testconsole.c" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ResourceCompile Include="..\PC\python_nt.rc" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="pythoncore.vcxproj"> |
|||
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project> |
|||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly> |
|||
</ProjectReference> |
|||
</ItemGroup> |
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
|||
<ImportGroup Label="ExtensionTargets"> |
|||
</ImportGroup> |
|||
</Project> |
|||
@ -0,0 +1,22 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup> |
|||
<Filter Include="Source Files"> |
|||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> |
|||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> |
|||
</Filter> |
|||
<Filter Include="Header Files"> |
|||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> |
|||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> |
|||
</Filter> |
|||
<Filter Include="Resource Files"> |
|||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> |
|||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> |
|||
</Filter> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ClCompile Include="..\Modules\_testmultiphase.c"> |
|||
<Filter>Source Files</Filter> |
|||
</ClCompile> |
|||
</ItemGroup> |
|||
</Project> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue