]> granicus.if.org Git - python/commitdiff
bpo-38071: Make termios PEP-384 compatible (GH-15785)
authorDino Viehland <dinoviehland@gmail.com>
Tue, 10 Sep 2019 10:33:30 +0000 (11:33 +0100)
committerT. Wouters <thomas@python.org>
Tue, 10 Sep 2019 10:33:30 +0000 (03:33 -0700)
Make the termios module PEP-384 compatible.

Misc/NEWS.d/next/Core and Builtins/2019-09-09-14-44-17.bpo-38071.bLwkBJ.rst [new file with mode: 0644]
Modules/termios.c

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 (file)
index 0000000..327bf73
--- /dev/null
@@ -0,0 +1 @@
+Make termios extension module PEP-384 compatible
\ No newline at end of file
index aee7f12c57cab5757e7c23eb06d6eeb06d6f3faa..b3b8c72bf6b84c797928c2b07d8db0a7838c0adb 100644 (file)
@@ -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)
+    if ((m = PyState_FindModule(&termiosmodule)) != NULL) {
+        Py_INCREF(m);
+        return m;
+    }
+
+    if ((m = PyModule_Create(&termiosmodule)) == NULL) {
         return NULL;
+    }
 
-    if (TermiosError == NULL) {
-        TermiosError = PyErr_NewException("termios.error", NULL, NULL);
+    termiosmodulestate *state = PyModule_GetState(m);
+    state->TermiosError = PyErr_NewException("termios.error", NULL, NULL);
+    if (state->TermiosError == NULL) {
+        return NULL;
     }
-    Py_INCREF(TermiosError);
-    PyModule_AddObject(m, "error", TermiosError);
+    Py_INCREF(state->TermiosError);
+    PyModule_AddObject(m, "error", state->TermiosError);
 
     while (constant->name != NULL) {
         PyModule_AddIntConstant(m, constant->name, constant->value);