mirror of https://github.com/python/cpython
gh-85283: Build _testconsole extension with limited C API (#117125)
This commit is contained in:
parent
8bea6c411d
commit
abdd1f938f
|
@ -1527,7 +1527,7 @@ Build Changes
|
||||||
* The ``errno``, ``fcntl``, ``grp``, ``md5``, ``pwd``, ``resource``,
|
* The ``errno``, ``fcntl``, ``grp``, ``md5``, ``pwd``, ``resource``,
|
||||||
``termios``, ``winsound``,
|
``termios``, ``winsound``,
|
||||||
``_ctypes_test``, ``_multiprocessing.posixshmem``, ``_scproxy``, ``_stat``,
|
``_ctypes_test``, ``_multiprocessing.posixshmem``, ``_scproxy``, ``_stat``,
|
||||||
``_statistics``, ``_testimportmultiple`` and ``_uuid``
|
``_statistics``, ``_testconsole``, ``_testimportmultiple`` and ``_uuid``
|
||||||
C extensions are now built with the
|
C extensions are now built with the
|
||||||
:ref:`limited C API <limited-c-api>`.
|
:ref:`limited C API <limited-c-api>`.
|
||||||
(Contributed by Victor Stinner in :gh:`85283`.)
|
(Contributed by Victor Stinner in :gh:`85283`.)
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
The ``fcntl``, ``grp``, ``pwd``, ``termios`` and ``_statistics`` C extensions are now
|
The ``fcntl``, ``grp``, ``pwd``, ``termios``, ``_statistics`` and
|
||||||
built with the :ref:`limited C API <limited-c-api>`. Patch by Victor Stinner.
|
``_testconsole`` C extensions are now built with the :ref:`limited C API
|
||||||
|
<limited-c-api>`. Patch by Victor Stinner.
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
/* Testing module for multi-phase initialization of extension modules (PEP 489)
|
/* Testing module for multi-phase initialization of extension modules (PEP 489)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef Py_BUILD_CORE_BUILTIN
|
// Need limited C API version 3.12 for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED
|
||||||
# define Py_BUILD_CORE_MODULE 1
|
#include "pyconfig.h" // Py_GIL_DISABLED
|
||||||
|
#ifndef Py_GIL_DISABLED
|
||||||
|
# define Py_LIMITED_API 0x030c0000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
|
||||||
#include "pycore_fileutils.h" // _Py_get_osfhandle()
|
|
||||||
#include "pycore_runtime.h" // _Py_ID()
|
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -57,20 +56,24 @@ module _testconsole
|
||||||
|
|
||||||
_testconsole.write_input
|
_testconsole.write_input
|
||||||
file: object
|
file: object
|
||||||
s: PyBytesObject
|
s: Py_buffer
|
||||||
|
|
||||||
Writes UTF-16-LE encoded bytes to the console as if typed by a user.
|
Writes UTF-16-LE encoded bytes to the console as if typed by a user.
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_testconsole_write_input_impl(PyObject *module, PyObject *file,
|
_testconsole_write_input_impl(PyObject *module, PyObject *file, Py_buffer *s)
|
||||||
PyBytesObject *s)
|
/*[clinic end generated code: output=58631a8985426ad3 input=68062f1bb2e52206]*/
|
||||||
/*[clinic end generated code: output=48f9563db34aedb3 input=4c774f2d05770bc6]*/
|
|
||||||
{
|
{
|
||||||
INPUT_RECORD *rec = NULL;
|
INPUT_RECORD *rec = NULL;
|
||||||
|
|
||||||
PyTypeObject *winconsoleio_type = (PyTypeObject *)_PyImport_GetModuleAttr(
|
PyObject *mod = PyImport_ImportModule("_io");
|
||||||
&_Py_ID(_io), &_Py_ID(_WindowsConsoleIO));
|
if (mod == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyTypeObject *winconsoleio_type = (PyTypeObject *)PyObject_GetAttrString(mod, "_WindowsConsoleIO");
|
||||||
|
Py_DECREF(mod);
|
||||||
if (winconsoleio_type == NULL) {
|
if (winconsoleio_type == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -81,8 +84,8 @@ _testconsole_write_input_impl(PyObject *module, PyObject *file,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wchar_t *p = (const wchar_t *)PyBytes_AS_STRING(s);
|
const wchar_t *p = (const wchar_t *)s->buf;
|
||||||
DWORD size = (DWORD)PyBytes_GET_SIZE(s) / sizeof(wchar_t);
|
DWORD size = (DWORD)s->len / sizeof(wchar_t);
|
||||||
|
|
||||||
rec = (INPUT_RECORD*)PyMem_Calloc(size, sizeof(INPUT_RECORD));
|
rec = (INPUT_RECORD*)PyMem_Calloc(size, sizeof(INPUT_RECORD));
|
||||||
if (!rec)
|
if (!rec)
|
||||||
|
@ -96,9 +99,11 @@ _testconsole_write_input_impl(PyObject *module, PyObject *file,
|
||||||
prec->Event.KeyEvent.uChar.UnicodeChar = *p;
|
prec->Event.KeyEvent.uChar.UnicodeChar = *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE hInput = _Py_get_osfhandle(((winconsoleio*)file)->fd);
|
HANDLE hInput = (HANDLE)_get_osfhandle(((winconsoleio*)file)->fd);
|
||||||
if (hInput == INVALID_HANDLE_VALUE)
|
if (hInput == INVALID_HANDLE_VALUE) {
|
||||||
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
DWORD total = 0;
|
DWORD total = 0;
|
||||||
while (total < size) {
|
while (total < size) {
|
||||||
|
|
|
@ -2,12 +2,6 @@
|
||||||
preserve
|
preserve
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
|
||||||
# include "pycore_gc.h" // PyGC_Head
|
|
||||||
# include "pycore_runtime.h" // _Py_ID()
|
|
||||||
#endif
|
|
||||||
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
|
|
||||||
|
|
||||||
#if defined(MS_WINDOWS)
|
#if defined(MS_WINDOWS)
|
||||||
|
|
||||||
PyDoc_STRVAR(_testconsole_write_input__doc__,
|
PyDoc_STRVAR(_testconsole_write_input__doc__,
|
||||||
|
@ -17,58 +11,30 @@ PyDoc_STRVAR(_testconsole_write_input__doc__,
|
||||||
"Writes UTF-16-LE encoded bytes to the console as if typed by a user.");
|
"Writes UTF-16-LE encoded bytes to the console as if typed by a user.");
|
||||||
|
|
||||||
#define _TESTCONSOLE_WRITE_INPUT_METHODDEF \
|
#define _TESTCONSOLE_WRITE_INPUT_METHODDEF \
|
||||||
{"write_input", _PyCFunction_CAST(_testconsole_write_input), METH_FASTCALL|METH_KEYWORDS, _testconsole_write_input__doc__},
|
{"write_input", (PyCFunction)(void(*)(void))_testconsole_write_input, METH_VARARGS|METH_KEYWORDS, _testconsole_write_input__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_testconsole_write_input_impl(PyObject *module, PyObject *file,
|
_testconsole_write_input_impl(PyObject *module, PyObject *file, Py_buffer *s);
|
||||||
PyBytesObject *s);
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_testconsole_write_input(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
_testconsole_write_input(PyObject *module, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
static char *_keywords[] = {"file", "s", NULL};
|
||||||
|
|
||||||
#define NUM_KEYWORDS 2
|
|
||||||
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(file), &_Py_ID(s), },
|
|
||||||
};
|
|
||||||
#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[] = {"file", "s", NULL};
|
|
||||||
static _PyArg_Parser _parser = {
|
|
||||||
.keywords = _keywords,
|
|
||||||
.fname = "write_input",
|
|
||||||
.kwtuple = KWTUPLE,
|
|
||||||
};
|
|
||||||
#undef KWTUPLE
|
|
||||||
PyObject *argsbuf[2];
|
|
||||||
PyObject *file;
|
PyObject *file;
|
||||||
PyBytesObject *s;
|
Py_buffer s = {NULL, NULL};
|
||||||
|
|
||||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oy*:write_input", _keywords,
|
||||||
if (!args) {
|
&file, &s))
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
return_value = _testconsole_write_input_impl(module, file, &s);
|
||||||
file = args[0];
|
|
||||||
if (!PyBytes_Check(args[1])) {
|
|
||||||
_PyArg_BadArgument("write_input", "argument 's'", "bytes", args[1]);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
s = (PyBytesObject *)args[1];
|
|
||||||
return_value = _testconsole_write_input_impl(module, file, s);
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
/* Cleanup for s */
|
||||||
|
if (s.obj) {
|
||||||
|
PyBuffer_Release(&s);
|
||||||
|
}
|
||||||
|
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,48 +49,21 @@ PyDoc_STRVAR(_testconsole_read_output__doc__,
|
||||||
"Reads a str from the console as written to stdout.");
|
"Reads a str from the console as written to stdout.");
|
||||||
|
|
||||||
#define _TESTCONSOLE_READ_OUTPUT_METHODDEF \
|
#define _TESTCONSOLE_READ_OUTPUT_METHODDEF \
|
||||||
{"read_output", _PyCFunction_CAST(_testconsole_read_output), METH_FASTCALL|METH_KEYWORDS, _testconsole_read_output__doc__},
|
{"read_output", (PyCFunction)(void(*)(void))_testconsole_read_output, METH_VARARGS|METH_KEYWORDS, _testconsole_read_output__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_testconsole_read_output_impl(PyObject *module, PyObject *file);
|
_testconsole_read_output_impl(PyObject *module, PyObject *file);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_testconsole_read_output(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
_testconsole_read_output(PyObject *module, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
static char *_keywords[] = {"file", NULL};
|
||||||
|
|
||||||
#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(file), },
|
|
||||||
};
|
|
||||||
#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[] = {"file", NULL};
|
|
||||||
static _PyArg_Parser _parser = {
|
|
||||||
.keywords = _keywords,
|
|
||||||
.fname = "read_output",
|
|
||||||
.kwtuple = KWTUPLE,
|
|
||||||
};
|
|
||||||
#undef KWTUPLE
|
|
||||||
PyObject *argsbuf[1];
|
|
||||||
PyObject *file;
|
PyObject *file;
|
||||||
|
|
||||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:read_output", _keywords,
|
||||||
if (!args) {
|
&file))
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
|
||||||
file = args[0];
|
|
||||||
return_value = _testconsole_read_output_impl(module, file);
|
return_value = _testconsole_read_output_impl(module, file);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
@ -140,4 +79,4 @@ exit:
|
||||||
#ifndef _TESTCONSOLE_READ_OUTPUT_METHODDEF
|
#ifndef _TESTCONSOLE_READ_OUTPUT_METHODDEF
|
||||||
#define _TESTCONSOLE_READ_OUTPUT_METHODDEF
|
#define _TESTCONSOLE_READ_OUTPUT_METHODDEF
|
||||||
#endif /* !defined(_TESTCONSOLE_READ_OUTPUT_METHODDEF) */
|
#endif /* !defined(_TESTCONSOLE_READ_OUTPUT_METHODDEF) */
|
||||||
/*[clinic end generated code: output=08a1c844b3657272 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=d60ce07157e3741a input=a9049054013a1b77]*/
|
||||||
|
|
Loading…
Reference in New Issue