From bd0c7a12d9e28ce74bfc16244d7694aca906838c Mon Sep 17 00:00:00 2001 From: Dino Viehland Date: Tue, 10 Sep 2019 11:33:30 +0100 Subject: [PATCH] bpo-38071: Make termios PEP-384 compatible (GH-15785) Make the termios module PEP-384 compatible. --- .../2019-09-09-14-44-17.bpo-38071.bLwkBJ.rst | 1 + Modules/termios.c | 71 +++++++++++++------ 2 files changed, 50 insertions(+), 22 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-09-09-14-44-17.bpo-38071.bLwkBJ.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-09-09-14-44-17.bpo-38071.bLwkBJ.rst b/Misc/NEWS.d/next/Core and Builtins/2019-09-09-14-44-17.bpo-38071.bLwkBJ.rst new file mode 100644 index 00000000000..327bf73bfd4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-09-09-14-44-17.bpo-38071.bLwkBJ.rst @@ -0,0 +1 @@ +Make termios extension module PEP-384 compatible \ No newline at end of file diff --git a/Modules/termios.c b/Modules/termios.c index aee7f12c57c..b3b8c72bf6b 100644 --- a/Modules/termios.c +++ b/Modules/termios.c @@ -39,7 +39,11 @@ All functions in this module take a file descriptor fd as their first\n\ argument. This can be an integer file descriptor, such as returned by\n\ sys.stdin.fileno(), or a file object, such as sys.stdin itself."); -static PyObject *TermiosError; +typedef struct { + PyObject *TermiosError; +} termiosmodulestate; +#define modulestate(o) ((termiosmodulestate *)PyModule_GetState(o)) +#define modulestate_global modulestate(PyState_FindModule(&termiosmodule)) static int fdconv(PyObject* obj, void* p) { @@ -53,6 +57,8 @@ static int fdconv(PyObject* obj, void* p) return 0; } +static struct PyModuleDef termiosmodule; + PyDoc_STRVAR(termios_tcgetattr__doc__, "tcgetattr(fd) -> list_of_attrs\n\ \n\ @@ -80,7 +86,7 @@ termios_tcgetattr(PyObject *self, PyObject *args) return NULL; if (tcgetattr(fd, &mode) == -1) - return PyErr_SetFromErrno(TermiosError); + return PyErr_SetFromErrno(modulestate_global->TermiosError); ispeed = cfgetispeed(&mode); ospeed = cfgetospeed(&mode); @@ -160,8 +166,9 @@ termios_tcsetattr(PyObject *self, PyObject *args) } /* Get the old mode, in case there are any hidden fields... */ + termiosmodulestate *state = modulestate_global; if (tcgetattr(fd, &mode) == -1) - return PyErr_SetFromErrno(TermiosError); + return PyErr_SetFromErrno(state->TermiosError); mode.c_iflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 0)); mode.c_oflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 1)); mode.c_cflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 2)); @@ -194,11 +201,11 @@ termios_tcsetattr(PyObject *self, PyObject *args) } if (cfsetispeed(&mode, (speed_t) ispeed) == -1) - return PyErr_SetFromErrno(TermiosError); + return PyErr_SetFromErrno(state->TermiosError); if (cfsetospeed(&mode, (speed_t) ospeed) == -1) - return PyErr_SetFromErrno(TermiosError); + return PyErr_SetFromErrno(state->TermiosError); if (tcsetattr(fd, when, &mode) == -1) - return PyErr_SetFromErrno(TermiosError); + return PyErr_SetFromErrno(state->TermiosError); Py_RETURN_NONE; } @@ -219,7 +226,7 @@ termios_tcsendbreak(PyObject *self, PyObject *args) fdconv, &fd, &duration)) return NULL; if (tcsendbreak(fd, duration) == -1) - return PyErr_SetFromErrno(TermiosError); + return PyErr_SetFromErrno(modulestate_global->TermiosError); Py_RETURN_NONE; } @@ -238,7 +245,7 @@ termios_tcdrain(PyObject *self, PyObject *args) fdconv, &fd)) return NULL; if (tcdrain(fd) == -1) - return PyErr_SetFromErrno(TermiosError); + return PyErr_SetFromErrno(modulestate_global->TermiosError); Py_RETURN_NONE; } @@ -260,7 +267,7 @@ termios_tcflush(PyObject *self, PyObject *args) fdconv, &fd, &queue)) return NULL; if (tcflush(fd, queue) == -1) - return PyErr_SetFromErrno(TermiosError); + return PyErr_SetFromErrno(modulestate_global->TermiosError); Py_RETURN_NONE; } @@ -282,7 +289,7 @@ termios_tcflow(PyObject *self, PyObject *args) fdconv, &fd, &action)) return NULL; if (tcflow(fd, action) == -1) - return PyErr_SetFromErrno(TermiosError); + return PyErr_SetFromErrno(modulestate_global->TermiosError); Py_RETURN_NONE; } @@ -935,17 +942,30 @@ static struct constant { {NULL, 0} }; +static int termiosmodule_traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(modulestate(m)->TermiosError); + return 0; +} + +static int termiosmodule_clear(PyObject *m) { + Py_CLEAR(modulestate(m)->TermiosError); + return 0; +} + +static void termiosmodule_free(void *m) { + termiosmodule_clear((PyObject *)m); +} static struct PyModuleDef termiosmodule = { PyModuleDef_HEAD_INIT, "termios", termios__doc__, - -1, + sizeof(termiosmodulestate), termios_methods, NULL, - NULL, - NULL, - NULL + termiosmodule_traverse, + termiosmodule_clear, + termiosmodule_free, }; PyMODINIT_FUNC @@ -954,15 +974,22 @@ PyInit_termios(void) PyObject *m; struct constant *constant = termios_constants; - m = PyModule_Create(&termiosmodule); - if (m == NULL) - return NULL; - - if (TermiosError == NULL) { - TermiosError = PyErr_NewException("termios.error", NULL, NULL); + if ((m = PyState_FindModule(&termiosmodule)) != NULL) { + Py_INCREF(m); + return m; } - Py_INCREF(TermiosError); - PyModule_AddObject(m, "error", TermiosError); + + if ((m = PyModule_Create(&termiosmodule)) == NULL) { + return NULL; + } + + termiosmodulestate *state = PyModule_GetState(m); + state->TermiosError = PyErr_NewException("termios.error", NULL, NULL); + if (state->TermiosError == NULL) { + return NULL; + } + Py_INCREF(state->TermiosError); + PyModule_AddObject(m, "error", state->TermiosError); while (constant->name != NULL) { PyModule_AddIntConstant(m, constant->name, constant->value);