Skip to content

Commit bd0c7a1

Browse files
DinoVYhg1s
authored andcommitted
bpo-38071: Make termios PEP-384 compatible (GH-15785)
Make the termios module PEP-384 compatible.
1 parent 40a5313 commit bd0c7a1

File tree

2 files changed

+48
-20
lines changed

2 files changed

+48
-20
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Make termios extension module PEP-384 compatible

Modules/termios.c

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ All functions in this module take a file descriptor fd as their first\n\
3939
argument. This can be an integer file descriptor, such as returned by\n\
4040
sys.stdin.fileno(), or a file object, such as sys.stdin itself.");
4141

42-
static PyObject *TermiosError;
42+
typedef struct {
43+
PyObject *TermiosError;
44+
} termiosmodulestate;
45+
#define modulestate(o) ((termiosmodulestate *)PyModule_GetState(o))
46+
#define modulestate_global modulestate(PyState_FindModule(&termiosmodule))
4347

4448
static int fdconv(PyObject* obj, void* p)
4549
{
@@ -53,6 +57,8 @@ static int fdconv(PyObject* obj, void* p)
5357
return 0;
5458
}
5559

60+
static struct PyModuleDef termiosmodule;
61+
5662
PyDoc_STRVAR(termios_tcgetattr__doc__,
5763
"tcgetattr(fd) -> list_of_attrs\n\
5864
\n\
@@ -80,7 +86,7 @@ termios_tcgetattr(PyObject *self, PyObject *args)
8086
return NULL;
8187

8288
if (tcgetattr(fd, &mode) == -1)
83-
return PyErr_SetFromErrno(TermiosError);
89+
return PyErr_SetFromErrno(modulestate_global->TermiosError);
8490

8591
ispeed = cfgetispeed(&mode);
8692
ospeed = cfgetospeed(&mode);
@@ -160,8 +166,9 @@ termios_tcsetattr(PyObject *self, PyObject *args)
160166
}
161167

162168
/* Get the old mode, in case there are any hidden fields... */
169+
termiosmodulestate *state = modulestate_global;
163170
if (tcgetattr(fd, &mode) == -1)
164-
return PyErr_SetFromErrno(TermiosError);
171+
return PyErr_SetFromErrno(state->TermiosError);
165172
mode.c_iflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 0));
166173
mode.c_oflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 1));
167174
mode.c_cflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 2));
@@ -194,11 +201,11 @@ termios_tcsetattr(PyObject *self, PyObject *args)
194201
}
195202

196203
if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
197-
return PyErr_SetFromErrno(TermiosError);
204+
return PyErr_SetFromErrno(state->TermiosError);
198205
if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
199-
return PyErr_SetFromErrno(TermiosError);
206+
return PyErr_SetFromErrno(state->TermiosError);
200207
if (tcsetattr(fd, when, &mode) == -1)
201-
return PyErr_SetFromErrno(TermiosError);
208+
return PyErr_SetFromErrno(state->TermiosError);
202209

203210
Py_RETURN_NONE;
204211
}
@@ -219,7 +226,7 @@ termios_tcsendbreak(PyObject *self, PyObject *args)
219226
fdconv, &fd, &duration))
220227
return NULL;
221228
if (tcsendbreak(fd, duration) == -1)
222-
return PyErr_SetFromErrno(TermiosError);
229+
return PyErr_SetFromErrno(modulestate_global->TermiosError);
223230

224231
Py_RETURN_NONE;
225232
}
@@ -238,7 +245,7 @@ termios_tcdrain(PyObject *self, PyObject *args)
238245
fdconv, &fd))
239246
return NULL;
240247
if (tcdrain(fd) == -1)
241-
return PyErr_SetFromErrno(TermiosError);
248+
return PyErr_SetFromErrno(modulestate_global->TermiosError);
242249

243250
Py_RETURN_NONE;
244251
}
@@ -260,7 +267,7 @@ termios_tcflush(PyObject *self, PyObject *args)
260267
fdconv, &fd, &queue))
261268
return NULL;
262269
if (tcflush(fd, queue) == -1)
263-
return PyErr_SetFromErrno(TermiosError);
270+
return PyErr_SetFromErrno(modulestate_global->TermiosError);
264271

265272
Py_RETURN_NONE;
266273
}
@@ -282,7 +289,7 @@ termios_tcflow(PyObject *self, PyObject *args)
282289
fdconv, &fd, &action))
283290
return NULL;
284291
if (tcflow(fd, action) == -1)
285-
return PyErr_SetFromErrno(TermiosError);
292+
return PyErr_SetFromErrno(modulestate_global->TermiosError);
286293

287294
Py_RETURN_NONE;
288295
}
@@ -935,17 +942,30 @@ static struct constant {
935942
{NULL, 0}
936943
};
937944

945+
static int termiosmodule_traverse(PyObject *m, visitproc visit, void *arg) {
946+
Py_VISIT(modulestate(m)->TermiosError);
947+
return 0;
948+
}
949+
950+
static int termiosmodule_clear(PyObject *m) {
951+
Py_CLEAR(modulestate(m)->TermiosError);
952+
return 0;
953+
}
954+
955+
static void termiosmodule_free(void *m) {
956+
termiosmodule_clear((PyObject *)m);
957+
}
938958

939959
static struct PyModuleDef termiosmodule = {
940960
PyModuleDef_HEAD_INIT,
941961
"termios",
942962
termios__doc__,
943-
-1,
963+
sizeof(termiosmodulestate),
944964
termios_methods,
945965
NULL,
946-
NULL,
947-
NULL,
948-
NULL
966+
termiosmodule_traverse,
967+
termiosmodule_clear,
968+
termiosmodule_free,
949969
};
950970

951971
PyMODINIT_FUNC
@@ -954,15 +974,22 @@ PyInit_termios(void)
954974
PyObject *m;
955975
struct constant *constant = termios_constants;
956976

957-
m = PyModule_Create(&termiosmodule);
958-
if (m == NULL)
977+
if ((m = PyState_FindModule(&termiosmodule)) != NULL) {
978+
Py_INCREF(m);
979+
return m;
980+
}
981+
982+
if ((m = PyModule_Create(&termiosmodule)) == NULL) {
959983
return NULL;
984+
}
960985

961-
if (TermiosError == NULL) {
962-
TermiosError = PyErr_NewException("termios.error", NULL, NULL);
986+
termiosmodulestate *state = PyModule_GetState(m);
987+
state->TermiosError = PyErr_NewException("termios.error", NULL, NULL);
988+
if (state->TermiosError == NULL) {
989+
return NULL;
963990
}
964-
Py_INCREF(TermiosError);
965-
PyModule_AddObject(m, "error", TermiosError);
991+
Py_INCREF(state->TermiosError);
992+
PyModule_AddObject(m, "error", state->TermiosError);
966993

967994
while (constant->name != NULL) {
968995
PyModule_AddIntConstant(m, constant->name, constant->value);

0 commit comments

Comments
 (0)