mirror of
https://github.com/python/cpython.git
synced 2025-11-02 19:12:55 +00:00
bpo-1635741: Port the termios to multi-phase init (PEP 489) (GH-22139)
This commit is contained in:
parent
b0ac5d75a5
commit
15dcdb2113
2 changed files with 106 additions and 84 deletions
|
|
@ -0,0 +1,2 @@
|
||||||
|
Port the :mod:`termios` extension module to multi-phase initialization
|
||||||
|
(:pep:`489`).
|
||||||
|
|
@ -51,8 +51,6 @@ get_termios_state(PyObject *module)
|
||||||
return (termiosmodulestate *)state;
|
return (termiosmodulestate *)state;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define modulestate_global get_termios_state(PyState_FindModule(&termiosmodule))
|
|
||||||
|
|
||||||
static int fdconv(PyObject* obj, void* p)
|
static int fdconv(PyObject* obj, void* p)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
@ -79,31 +77,32 @@ indexing in the cc array must be done using the symbolic constants defined\n\
|
||||||
in this module.");
|
in this module.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
termios_tcgetattr(PyObject *self, PyObject *args)
|
termios_tcgetattr(PyObject *module, PyObject *args)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
if (!PyArg_ParseTuple(args, "O&:tcgetattr",
|
||||||
|
fdconv, (void*)&fd)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
termiosmodulestate *state = PyModule_GetState(module);
|
||||||
struct termios mode;
|
struct termios mode;
|
||||||
PyObject *cc;
|
if (tcgetattr(fd, &mode) == -1) {
|
||||||
speed_t ispeed, ospeed;
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
|
speed_t ispeed = cfgetispeed(&mode);
|
||||||
|
speed_t ospeed = cfgetospeed(&mode);
|
||||||
|
|
||||||
|
PyObject *cc = PyList_New(NCCS);
|
||||||
|
if (cc == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *v;
|
PyObject *v;
|
||||||
int i;
|
int i;
|
||||||
char ch;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O&:tcgetattr",
|
|
||||||
fdconv, (void*)&fd))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (tcgetattr(fd, &mode) == -1)
|
|
||||||
return PyErr_SetFromErrno(modulestate_global->TermiosError);
|
|
||||||
|
|
||||||
ispeed = cfgetispeed(&mode);
|
|
||||||
ospeed = cfgetospeed(&mode);
|
|
||||||
|
|
||||||
cc = PyList_New(NCCS);
|
|
||||||
if (cc == NULL)
|
|
||||||
return NULL;
|
|
||||||
for (i = 0; i < NCCS; i++) {
|
for (i = 0; i < NCCS; i++) {
|
||||||
ch = (char)mode.c_cc[i];
|
char ch = (char)mode.c_cc[i];
|
||||||
v = PyBytes_FromStringAndSize(&ch, 1);
|
v = PyBytes_FromStringAndSize(&ch, 1);
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -156,17 +155,15 @@ queued output, or termios.TCSAFLUSH to change after transmitting all\n\
|
||||||
queued output and discarding all queued input. ");
|
queued output and discarding all queued input. ");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
termios_tcsetattr(PyObject *self, PyObject *args)
|
termios_tcsetattr(PyObject *module, PyObject *args)
|
||||||
{
|
{
|
||||||
int fd, when;
|
int fd, when;
|
||||||
struct termios mode;
|
PyObject *term;
|
||||||
speed_t ispeed, ospeed;
|
|
||||||
PyObject *term, *cc, *v;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O&iO:tcsetattr",
|
if (!PyArg_ParseTuple(args, "O&iO:tcsetattr",
|
||||||
fdconv, &fd, &when, &term))
|
fdconv, &fd, &when, &term)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!PyList_Check(term) || PyList_Size(term) != 7) {
|
if (!PyList_Check(term) || PyList_Size(term) != 7) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"tcsetattr, arg 3: must be 7 element list");
|
"tcsetattr, arg 3: must be 7 element list");
|
||||||
|
|
@ -174,18 +171,22 @@ termios_tcsetattr(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the old mode, in case there are any hidden fields... */
|
/* Get the old mode, in case there are any hidden fields... */
|
||||||
termiosmodulestate *state = modulestate_global;
|
termiosmodulestate *state = PyModule_GetState(module);
|
||||||
if (tcgetattr(fd, &mode) == -1)
|
struct termios mode;
|
||||||
|
if (tcgetattr(fd, &mode) == -1) {
|
||||||
return PyErr_SetFromErrno(state->TermiosError);
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
mode.c_iflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 0));
|
mode.c_iflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 0));
|
||||||
mode.c_oflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 1));
|
mode.c_oflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 1));
|
||||||
mode.c_cflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 2));
|
mode.c_cflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 2));
|
||||||
mode.c_lflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 3));
|
mode.c_lflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 3));
|
||||||
ispeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 4));
|
speed_t ispeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 4));
|
||||||
ospeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 5));
|
speed_t ospeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 5));
|
||||||
cc = PyList_GetItem(term, 6);
|
PyObject *cc = PyList_GetItem(term, 6);
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
|
if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
|
@ -194,6 +195,8 @@ termios_tcsetattr(PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
PyObject *v;
|
||||||
for (i = 0; i < NCCS; i++) {
|
for (i = 0; i < NCCS; i++) {
|
||||||
v = PyList_GetItem(cc, i);
|
v = PyList_GetItem(cc, i);
|
||||||
|
|
||||||
|
|
@ -226,15 +229,18 @@ A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n\
|
||||||
has a system dependent meaning.");
|
has a system dependent meaning.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
termios_tcsendbreak(PyObject *self, PyObject *args)
|
termios_tcsendbreak(PyObject *module, PyObject *args)
|
||||||
{
|
{
|
||||||
int fd, duration;
|
int fd, duration;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O&i:tcsendbreak",
|
if (!PyArg_ParseTuple(args, "O&i:tcsendbreak",
|
||||||
fdconv, &fd, &duration))
|
fdconv, &fd, &duration)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
if (tcsendbreak(fd, duration) == -1)
|
}
|
||||||
return PyErr_SetFromErrno(modulestate_global->TermiosError);
|
|
||||||
|
termiosmodulestate *state = PyModule_GetState(module);
|
||||||
|
if (tcsendbreak(fd, duration) == -1) {
|
||||||
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
@ -245,15 +251,18 @@ PyDoc_STRVAR(termios_tcdrain__doc__,
|
||||||
Wait until all output written to file descriptor fd has been transmitted.");
|
Wait until all output written to file descriptor fd has been transmitted.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
termios_tcdrain(PyObject *self, PyObject *args)
|
termios_tcdrain(PyObject *module, PyObject *args)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O&:tcdrain",
|
if (!PyArg_ParseTuple(args, "O&:tcdrain",
|
||||||
fdconv, &fd))
|
fdconv, &fd)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
if (tcdrain(fd) == -1)
|
}
|
||||||
return PyErr_SetFromErrno(modulestate_global->TermiosError);
|
|
||||||
|
termiosmodulestate *state = PyModule_GetState(module);
|
||||||
|
if (tcdrain(fd) == -1) {
|
||||||
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
@ -267,15 +276,18 @@ queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n\
|
||||||
both queues. ");
|
both queues. ");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
termios_tcflush(PyObject *self, PyObject *args)
|
termios_tcflush(PyObject *module, PyObject *args)
|
||||||
{
|
{
|
||||||
int fd, queue;
|
int fd, queue;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O&i:tcflush",
|
if (!PyArg_ParseTuple(args, "O&i:tcflush",
|
||||||
fdconv, &fd, &queue))
|
fdconv, &fd, &queue)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
if (tcflush(fd, queue) == -1)
|
}
|
||||||
return PyErr_SetFromErrno(modulestate_global->TermiosError);
|
|
||||||
|
termiosmodulestate *state = PyModule_GetState(module);
|
||||||
|
if (tcflush(fd, queue) == -1) {
|
||||||
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
@ -289,15 +301,18 @@ termios.TCOON to restart output, termios.TCIOFF to suspend input,\n\
|
||||||
or termios.TCION to restart input.");
|
or termios.TCION to restart input.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
termios_tcflow(PyObject *self, PyObject *args)
|
termios_tcflow(PyObject *module, PyObject *args)
|
||||||
{
|
{
|
||||||
int fd, action;
|
int fd, action;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O&i:tcflow",
|
if (!PyArg_ParseTuple(args, "O&i:tcflow",
|
||||||
fdconv, &fd, &action))
|
fdconv, &fd, &action)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
if (tcflow(fd, action) == -1)
|
}
|
||||||
return PyErr_SetFromErrno(modulestate_global->TermiosError);
|
|
||||||
|
termiosmodulestate *state = PyModule_GetState(module);
|
||||||
|
if (tcflow(fd, action) == -1) {
|
||||||
|
return PyErr_SetFromErrno(state->TermiosError);
|
||||||
|
}
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
@ -997,44 +1012,49 @@ static void termiosmodule_free(void *m) {
|
||||||
termiosmodule_clear((PyObject *)m);
|
termiosmodule_clear((PyObject *)m);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct PyModuleDef termiosmodule = {
|
static int
|
||||||
PyModuleDef_HEAD_INIT,
|
termios_exec(PyObject *mod)
|
||||||
"termios",
|
|
||||||
termios__doc__,
|
|
||||||
sizeof(termiosmodulestate),
|
|
||||||
termios_methods,
|
|
||||||
NULL,
|
|
||||||
termiosmodule_traverse,
|
|
||||||
termiosmodule_clear,
|
|
||||||
termiosmodule_free,
|
|
||||||
};
|
|
||||||
|
|
||||||
PyMODINIT_FUNC
|
|
||||||
PyInit_termios(void)
|
|
||||||
{
|
{
|
||||||
PyObject *m;
|
|
||||||
struct constant *constant = termios_constants;
|
struct constant *constant = termios_constants;
|
||||||
|
termiosmodulestate *state = get_termios_state(mod);
|
||||||
if ((m = PyState_FindModule(&termiosmodule)) != NULL) {
|
|
||||||
Py_INCREF(m);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m = PyModule_Create(&termiosmodule)) == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
termiosmodulestate *state = get_termios_state(m);
|
|
||||||
state->TermiosError = PyErr_NewException("termios.error", NULL, NULL);
|
state->TermiosError = PyErr_NewException("termios.error", NULL, NULL);
|
||||||
if (state->TermiosError == NULL) {
|
if (state->TermiosError == NULL) {
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
Py_INCREF(state->TermiosError);
|
Py_INCREF(state->TermiosError);
|
||||||
PyModule_AddObject(m, "error", state->TermiosError);
|
if (PyModule_AddObject(mod, "error", state->TermiosError) < 0) {
|
||||||
|
Py_DECREF(state->TermiosError);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
while (constant->name != NULL) {
|
while (constant->name != NULL) {
|
||||||
PyModule_AddIntConstant(m, constant->name, constant->value);
|
if (PyModule_AddIntConstant(
|
||||||
|
mod, constant->name, constant->value) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
++constant;
|
++constant;
|
||||||
}
|
}
|
||||||
return m;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyModuleDef_Slot termios_slots[] = {
|
||||||
|
{Py_mod_exec, termios_exec},
|
||||||
|
{0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct PyModuleDef termiosmodule = {
|
||||||
|
PyModuleDef_HEAD_INIT,
|
||||||
|
.m_name = "termios",
|
||||||
|
.m_doc = termios__doc__,
|
||||||
|
.m_size = sizeof(termiosmodulestate),
|
||||||
|
.m_methods = termios_methods,
|
||||||
|
.m_slots = termios_slots,
|
||||||
|
.m_traverse = termiosmodule_traverse,
|
||||||
|
.m_clear = termiosmodule_clear,
|
||||||
|
.m_free = termiosmodule_free,
|
||||||
|
};
|
||||||
|
|
||||||
|
PyMODINIT_FUNC PyInit_termios(void)
|
||||||
|
{
|
||||||
|
return PyModuleDef_Init(&termiosmodule);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue