Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/PC/_testconsole.c
12 views
1
/* Testing module for multi-phase initialization of extension modules (PEP 489)
2
*/
3
4
#ifndef Py_BUILD_CORE_BUILTIN
5
# define Py_BUILD_CORE_MODULE 1
6
#endif
7
8
#include "Python.h"
9
10
#ifdef MS_WINDOWS
11
12
#include "pycore_fileutils.h" // _Py_get_osfhandle()
13
#include "pycore_runtime.h" // _Py_ID()
14
15
#define WIN32_LEAN_AND_MEAN
16
#include <windows.h>
17
#include <fcntl.h>
18
19
/* The full definition is in iomodule. We reproduce
20
enough here to get the fd, which is all we want. */
21
typedef struct {
22
PyObject_HEAD
23
int fd;
24
} winconsoleio;
25
26
27
static int execfunc(PyObject *m)
28
{
29
return 0;
30
}
31
32
PyModuleDef_Slot testconsole_slots[] = {
33
{Py_mod_exec, execfunc},
34
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
35
{0, NULL},
36
};
37
38
/*[clinic input]
39
module _testconsole
40
41
_testconsole.write_input
42
file: object
43
s: PyBytesObject
44
45
Writes UTF-16-LE encoded bytes to the console as if typed by a user.
46
[clinic start generated code]*/
47
48
static PyObject *
49
_testconsole_write_input_impl(PyObject *module, PyObject *file,
50
PyBytesObject *s)
51
/*[clinic end generated code: output=48f9563db34aedb3 input=4c774f2d05770bc6]*/
52
{
53
INPUT_RECORD *rec = NULL;
54
55
PyTypeObject *winconsoleio_type = (PyTypeObject *)_PyImport_GetModuleAttr(
56
&_Py_ID(_io), &_Py_ID(_WindowsConsoleIO));
57
if (winconsoleio_type == NULL) {
58
return NULL;
59
}
60
int is_subclass = PyObject_TypeCheck(file, winconsoleio_type);
61
Py_DECREF(winconsoleio_type);
62
if (!is_subclass) {
63
PyErr_SetString(PyExc_TypeError, "expected raw console object");
64
return NULL;
65
}
66
67
const wchar_t *p = (const wchar_t *)PyBytes_AS_STRING(s);
68
DWORD size = (DWORD)PyBytes_GET_SIZE(s) / sizeof(wchar_t);
69
70
rec = (INPUT_RECORD*)PyMem_Calloc(size, sizeof(INPUT_RECORD));
71
if (!rec)
72
goto error;
73
74
INPUT_RECORD *prec = rec;
75
for (DWORD i = 0; i < size; ++i, ++p, ++prec) {
76
prec->EventType = KEY_EVENT;
77
prec->Event.KeyEvent.bKeyDown = TRUE;
78
prec->Event.KeyEvent.wRepeatCount = 1;
79
prec->Event.KeyEvent.uChar.UnicodeChar = *p;
80
}
81
82
HANDLE hInput = _Py_get_osfhandle(((winconsoleio*)file)->fd);
83
if (hInput == INVALID_HANDLE_VALUE)
84
goto error;
85
86
DWORD total = 0;
87
while (total < size) {
88
DWORD wrote;
89
if (!WriteConsoleInputW(hInput, &rec[total], (size - total), &wrote)) {
90
PyErr_SetFromWindowsErr(0);
91
goto error;
92
}
93
total += wrote;
94
}
95
96
PyMem_Free((void*)rec);
97
98
Py_RETURN_NONE;
99
error:
100
if (rec)
101
PyMem_Free((void*)rec);
102
return NULL;
103
}
104
105
/*[clinic input]
106
_testconsole.read_output
107
file: object
108
109
Reads a str from the console as written to stdout.
110
[clinic start generated code]*/
111
112
static PyObject *
113
_testconsole_read_output_impl(PyObject *module, PyObject *file)
114
/*[clinic end generated code: output=876310d81a73e6d2 input=b3521f64b1b558e3]*/
115
{
116
Py_RETURN_NONE;
117
}
118
119
#include "clinic\_testconsole.c.h"
120
121
PyMethodDef testconsole_methods[] = {
122
_TESTCONSOLE_WRITE_INPUT_METHODDEF
123
_TESTCONSOLE_READ_OUTPUT_METHODDEF
124
{NULL, NULL}
125
};
126
127
static PyModuleDef testconsole_def = {
128
PyModuleDef_HEAD_INIT, /* m_base */
129
"_testconsole", /* m_name */
130
PyDoc_STR("Test module for the Windows console"), /* m_doc */
131
0, /* m_size */
132
testconsole_methods, /* m_methods */
133
testconsole_slots, /* m_slots */
134
NULL, /* m_traverse */
135
NULL, /* m_clear */
136
NULL, /* m_free */
137
};
138
139
PyMODINIT_FUNC
140
PyInit__testconsole(PyObject *spec)
141
{
142
return PyModuleDef_Init(&testconsole_def);
143
}
144
145
#endif /* MS_WINDOWS */
146
147