| /* Testing module for multi-phase initialization of extension modules (PEP 489) | |
| */ | |
| // Need limited C API version 3.13 for Py_mod_gil | |
| #include "pyconfig.h" // Py_GIL_DISABLED | |
| #ifndef Py_GIL_DISABLED | |
| # define Py_LIMITED_API 0x030d0000 | |
| #endif | |
| #include "Python.h" | |
| #ifdef MS_WINDOWS | |
| #define WIN32_LEAN_AND_MEAN | |
| #include <windows.h> | |
| #include <fcntl.h> | |
| /* The full definition is in iomodule. We reproduce | |
| enough here to get the fd, which is all we want. */ | |
| typedef struct { | |
| PyObject_HEAD | |
| int fd; | |
| } winconsoleio; | |
| static int execfunc(PyObject *m) | |
| { | |
| return 0; | |
| } | |
| PyModuleDef_Slot testconsole_slots[] = { | |
| {Py_mod_exec, execfunc}, | |
| {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, | |
| {Py_mod_gil, Py_MOD_GIL_NOT_USED}, | |
| {0, NULL}, | |
| }; | |
| /*[python end generated code:]*/ | |
| /*[clinic input] | |
| module _testconsole | |
| _testconsole.write_input | |
| file: object | |
| s: Py_buffer | |
| 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, Py_buffer *s) | |
| /*[clinic end generated code: output=58631a8985426ad3 input=68062f1bb2e52206]*/ | |
| { | |
| INPUT_RECORD *rec = NULL; | |
| PyObject *mod = PyImport_ImportModule("_io"); | |
| if (mod == NULL) { | |
| return NULL; | |
| } | |
| PyTypeObject *winconsoleio_type = (PyTypeObject *)PyObject_GetAttrString(mod, "_WindowsConsoleIO"); | |
| Py_DECREF(mod); | |
| if (winconsoleio_type == NULL) { | |
| return NULL; | |
| } | |
| int is_subclass = PyObject_TypeCheck(file, winconsoleio_type); | |
| Py_DECREF(winconsoleio_type); | |
| if (!is_subclass) { | |
| PyErr_SetString(PyExc_TypeError, "expected raw console object"); | |
| return NULL; | |
| } | |
| const wchar_t *p = (const wchar_t *)s->buf; | |
| DWORD size = (DWORD)s->len / sizeof(wchar_t); | |
| rec = (INPUT_RECORD*)PyMem_Calloc(size, sizeof(INPUT_RECORD)); | |
| if (!rec) | |
| goto error; | |
| 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 = 1; | |
| prec->Event.KeyEvent.uChar.UnicodeChar = *p; | |
| } | |
| HANDLE hInput = (HANDLE)_get_osfhandle(((winconsoleio*)file)->fd); | |
| if (hInput == INVALID_HANDLE_VALUE) { | |
| PyErr_SetFromErrno(PyExc_OSError); | |
| goto error; | |
| } | |
| 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(void) | |
| { | |
| return PyModuleDef_Init(&testconsole_def); | |
| } | |
| #endif /* MS_WINDOWS */ |