From 1bcaa81e520e30f920bd69e46fbf1d67a9107ce1 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 18 Oct 2020 17:54:06 +0300 Subject: [PATCH] bpo-20184: Convert termios to Argument Clinic. (GH-22693) --- Modules/clinic/termios.c.h | 225 +++++++++++++++++++++++++++++++++++++ Modules/termios.c | 202 +++++++++++++++++---------------- 2 files changed, 328 insertions(+), 99 deletions(-) create mode 100644 Modules/clinic/termios.c.h diff --git a/Modules/clinic/termios.c.h b/Modules/clinic/termios.c.h new file mode 100644 index 00000000000..a45c1f64262 --- /dev/null +++ b/Modules/clinic/termios.c.h @@ -0,0 +1,225 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(termios_tcgetattr__doc__, +"tcgetattr($module, fd, /)\n" +"--\n" +"\n" +"Get the tty attributes for file descriptor fd.\n" +"\n" +"Returns a list [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]\n" +"where cc is a list of the tty special characters (each a string of\n" +"length 1, except the items with indices VMIN and VTIME, which are\n" +"integers when these fields are defined). The interpretation of the\n" +"flags and the speeds as well as the indexing in the cc array must be\n" +"done using the symbolic constants defined in this module."); + +#define TERMIOS_TCGETATTR_METHODDEF \ + {"tcgetattr", (PyCFunction)termios_tcgetattr, METH_O, termios_tcgetattr__doc__}, + +static PyObject * +termios_tcgetattr_impl(PyObject *module, int fd); + +static PyObject * +termios_tcgetattr(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { + goto exit; + } + return_value = termios_tcgetattr_impl(module, fd); + +exit: + return return_value; +} + +PyDoc_STRVAR(termios_tcsetattr__doc__, +"tcsetattr($module, fd, when, attributes, /)\n" +"--\n" +"\n" +"Set the tty attributes for file descriptor fd.\n" +"\n" +"The attributes to be set are taken from the attributes argument, which\n" +"is a list like the one returned by tcgetattr(). The when argument\n" +"determines when the attributes are changed: termios.TCSANOW to\n" +"change immediately, termios.TCSADRAIN to change after transmitting all\n" +"queued output, or termios.TCSAFLUSH to change after transmitting all\n" +"queued output and discarding all queued input."); + +#define TERMIOS_TCSETATTR_METHODDEF \ + {"tcsetattr", (PyCFunction)(void(*)(void))termios_tcsetattr, METH_FASTCALL, termios_tcsetattr__doc__}, + +static PyObject * +termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term); + +static PyObject * +termios_tcsetattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int when; + PyObject *term; + + if (!_PyArg_CheckPositional("tcsetattr", nargs, 3, 3)) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + when = _PyLong_AsInt(args[1]); + if (when == -1 && PyErr_Occurred()) { + goto exit; + } + term = args[2]; + return_value = termios_tcsetattr_impl(module, fd, when, term); + +exit: + return return_value; +} + +PyDoc_STRVAR(termios_tcsendbreak__doc__, +"tcsendbreak($module, fd, duration, /)\n" +"--\n" +"\n" +"Send a break on file descriptor fd.\n" +"\n" +"A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n" +"has a system dependent meaning."); + +#define TERMIOS_TCSENDBREAK_METHODDEF \ + {"tcsendbreak", (PyCFunction)(void(*)(void))termios_tcsendbreak, METH_FASTCALL, termios_tcsendbreak__doc__}, + +static PyObject * +termios_tcsendbreak_impl(PyObject *module, int fd, int duration); + +static PyObject * +termios_tcsendbreak(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int duration; + + if (!_PyArg_CheckPositional("tcsendbreak", nargs, 2, 2)) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + duration = _PyLong_AsInt(args[1]); + if (duration == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = termios_tcsendbreak_impl(module, fd, duration); + +exit: + return return_value; +} + +PyDoc_STRVAR(termios_tcdrain__doc__, +"tcdrain($module, fd, /)\n" +"--\n" +"\n" +"Wait until all output written to file descriptor fd has been transmitted."); + +#define TERMIOS_TCDRAIN_METHODDEF \ + {"tcdrain", (PyCFunction)termios_tcdrain, METH_O, termios_tcdrain__doc__}, + +static PyObject * +termios_tcdrain_impl(PyObject *module, int fd); + +static PyObject * +termios_tcdrain(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { + goto exit; + } + return_value = termios_tcdrain_impl(module, fd); + +exit: + return return_value; +} + +PyDoc_STRVAR(termios_tcflush__doc__, +"tcflush($module, fd, queue, /)\n" +"--\n" +"\n" +"Discard queued data on file descriptor fd.\n" +"\n" +"The queue selector specifies which queue: termios.TCIFLUSH for the input\n" +"queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n" +"both queues."); + +#define TERMIOS_TCFLUSH_METHODDEF \ + {"tcflush", (PyCFunction)(void(*)(void))termios_tcflush, METH_FASTCALL, termios_tcflush__doc__}, + +static PyObject * +termios_tcflush_impl(PyObject *module, int fd, int queue); + +static PyObject * +termios_tcflush(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int queue; + + if (!_PyArg_CheckPositional("tcflush", nargs, 2, 2)) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + queue = _PyLong_AsInt(args[1]); + if (queue == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = termios_tcflush_impl(module, fd, queue); + +exit: + return return_value; +} + +PyDoc_STRVAR(termios_tcflow__doc__, +"tcflow($module, fd, action, /)\n" +"--\n" +"\n" +"Suspend or resume input or output on file descriptor fd.\n" +"\n" +"The action argument can be termios.TCOOFF to suspend output,\n" +"termios.TCOON to restart output, termios.TCIOFF to suspend input,\n" +"or termios.TCION to restart input."); + +#define TERMIOS_TCFLOW_METHODDEF \ + {"tcflow", (PyCFunction)(void(*)(void))termios_tcflow, METH_FASTCALL, termios_tcflow__doc__}, + +static PyObject * +termios_tcflow_impl(PyObject *module, int fd, int action); + +static PyObject * +termios_tcflow(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int action; + + if (!_PyArg_CheckPositional("tcflow", nargs, 2, 2)) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + action = _PyLong_AsInt(args[1]); + if (action == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = termios_tcflow_impl(module, fd, action); + +exit: + return return_value; +} +/*[clinic end generated code: output=a129179f1e2545cc input=a9049054013a1b77]*/ diff --git a/Modules/termios.c b/Modules/termios.c index 79b60ffaaba..a6649598ec1 100644 --- a/Modules/termios.c +++ b/Modules/termios.c @@ -29,6 +29,13 @@ #include #endif +/*[clinic input] +module termios +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=01105c85d0ca7252]*/ + +#include "clinic/termios.c.h" + PyDoc_STRVAR(termios__doc__, "This module provides an interface to the Posix calls for tty I/O control.\n\ For a complete description of these calls, see the Posix or Unix manual\n\ @@ -53,26 +60,26 @@ get_termios_state(PyObject *module) static struct PyModuleDef termiosmodule; -PyDoc_STRVAR(termios_tcgetattr__doc__, -"tcgetattr(fd) -> list_of_attrs\n\ -\n\ -Get the tty attributes for file descriptor fd, as follows:\n\ -[iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\ -of the tty special characters (each a string of length 1, except the items\n\ -with indices VMIN and VTIME, which are integers when these fields are\n\ -defined). The interpretation of the flags and the speeds as well as the\n\ -indexing in the cc array must be done using the symbolic constants defined\n\ -in this module."); +/*[clinic input] +termios.tcgetattr + + fd: fildes + / + +Get the tty attributes for file descriptor fd. + +Returns a list [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] +where cc is a list of the tty special characters (each a string of +length 1, except the items with indices VMIN and VTIME, which are +integers when these fields are defined). The interpretation of the +flags and the speeds as well as the indexing in the cc array must be +done using the symbolic constants defined in this module. +[clinic start generated code]*/ static PyObject * -termios_tcgetattr(PyObject *module, PyObject *args) +termios_tcgetattr_impl(PyObject *module, int fd) +/*[clinic end generated code: output=2b3da39db870e629 input=54dad9779ebe74b1]*/ { - int fd; - if (!PyArg_ParseTuple(args, "O&:tcgetattr", - _PyLong_FileDescriptor_Converter, (void*)&fd)) { - return NULL; - } - termiosmodulestate *state = PyModule_GetState(module); struct termios mode; if (tcgetattr(fd, &mode) == -1) { @@ -131,27 +138,28 @@ termios_tcgetattr(PyObject *module, PyObject *args) return NULL; } -PyDoc_STRVAR(termios_tcsetattr__doc__, -"tcsetattr(fd, when, attributes) -> None\n\ -\n\ -Set the tty attributes for file descriptor fd.\n\ -The attributes to be set are taken from the attributes argument, which\n\ -is a list like the one returned by tcgetattr(). The when argument\n\ -determines when the attributes are changed: termios.TCSANOW to\n\ -change immediately, termios.TCSADRAIN to change after transmitting all\n\ -queued output, or termios.TCSAFLUSH to change after transmitting all\n\ -queued output and discarding all queued input. "); +/*[clinic input] +termios.tcsetattr + + fd: fildes + when: int + attributes as term: object + / + +Set the tty attributes for file descriptor fd. + +The attributes to be set are taken from the attributes argument, which +is a list like the one returned by tcgetattr(). The when argument +determines when the attributes are changed: termios.TCSANOW to +change immediately, termios.TCSADRAIN to change after transmitting all +queued output, or termios.TCSAFLUSH to change after transmitting all +queued output and discarding all queued input. +[clinic start generated code]*/ static PyObject * -termios_tcsetattr(PyObject *module, PyObject *args) +termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term) +/*[clinic end generated code: output=bcd2b0a7b98a4bf5 input=5dafabdd5a08f018]*/ { - int fd, when; - PyObject *term; - if (!PyArg_ParseTuple(args, "O&iO:tcsetattr", - _PyLong_FileDescriptor_Converter, &fd, &when, &term)) { - return NULL; - } - if (!PyList_Check(term) || PyList_Size(term) != 7) { PyErr_SetString(PyExc_TypeError, "tcsetattr, arg 3: must be 7 element list"); @@ -209,22 +217,23 @@ termios_tcsetattr(PyObject *module, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(termios_tcsendbreak__doc__, -"tcsendbreak(fd, duration) -> None\n\ -\n\ -Send a break on file descriptor fd.\n\ -A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n\ -has a system dependent meaning."); +/*[clinic input] +termios.tcsendbreak + + fd: fildes + duration: int + / + +Send a break on file descriptor fd. + +A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration +has a system dependent meaning. +[clinic start generated code]*/ static PyObject * -termios_tcsendbreak(PyObject *module, PyObject *args) +termios_tcsendbreak_impl(PyObject *module, int fd, int duration) +/*[clinic end generated code: output=5945f589b5d3ac66 input=dc2f32417691f8ed]*/ { - int fd, duration; - if (!PyArg_ParseTuple(args, "O&i:tcsendbreak", - _PyLong_FileDescriptor_Converter, &fd, &duration)) { - return NULL; - } - termiosmodulestate *state = PyModule_GetState(module); if (tcsendbreak(fd, duration) == -1) { return PyErr_SetFromErrno(state->TermiosError); @@ -233,20 +242,19 @@ termios_tcsendbreak(PyObject *module, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(termios_tcdrain__doc__, -"tcdrain(fd) -> None\n\ -\n\ -Wait until all output written to file descriptor fd has been transmitted."); +/*[clinic input] +termios.tcdrain + + fd: fildes + / + +Wait until all output written to file descriptor fd has been transmitted. +[clinic start generated code]*/ static PyObject * -termios_tcdrain(PyObject *module, PyObject *args) +termios_tcdrain_impl(PyObject *module, int fd) +/*[clinic end generated code: output=5fd86944c6255955 input=c99241b140b32447]*/ { - int fd; - if (!PyArg_ParseTuple(args, "O&:tcdrain", - _PyLong_FileDescriptor_Converter, &fd)) { - return NULL; - } - termiosmodulestate *state = PyModule_GetState(module); if (tcdrain(fd) == -1) { return PyErr_SetFromErrno(state->TermiosError); @@ -255,23 +263,24 @@ termios_tcdrain(PyObject *module, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(termios_tcflush__doc__, -"tcflush(fd, queue) -> None\n\ -\n\ -Discard queued data on file descriptor fd.\n\ -The queue selector specifies which queue: termios.TCIFLUSH for the input\n\ -queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n\ -both queues. "); +/*[clinic input] +termios.tcflush + + fd: fildes + queue: int + / + +Discard queued data on file descriptor fd. + +The queue selector specifies which queue: termios.TCIFLUSH for the input +queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for +both queues. +[clinic start generated code]*/ static PyObject * -termios_tcflush(PyObject *module, PyObject *args) +termios_tcflush_impl(PyObject *module, int fd, int queue) +/*[clinic end generated code: output=2424f80312ec2f21 input=0f7d08122ddc07b5]*/ { - int fd, queue; - if (!PyArg_ParseTuple(args, "O&i:tcflush", - _PyLong_FileDescriptor_Converter, &fd, &queue)) { - return NULL; - } - termiosmodulestate *state = PyModule_GetState(module); if (tcflush(fd, queue) == -1) { return PyErr_SetFromErrno(state->TermiosError); @@ -280,23 +289,24 @@ termios_tcflush(PyObject *module, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(termios_tcflow__doc__, -"tcflow(fd, action) -> None\n\ -\n\ -Suspend or resume input or output on file descriptor fd.\n\ -The action argument can be termios.TCOOFF to suspend output,\n\ -termios.TCOON to restart output, termios.TCIOFF to suspend input,\n\ -or termios.TCION to restart input."); +/*[clinic input] +termios.tcflow + + fd: fildes + action: int + / + +Suspend or resume input or output on file descriptor fd. + +The action argument can be termios.TCOOFF to suspend output, +termios.TCOON to restart output, termios.TCIOFF to suspend input, +or termios.TCION to restart input. +[clinic start generated code]*/ static PyObject * -termios_tcflow(PyObject *module, PyObject *args) +termios_tcflow_impl(PyObject *module, int fd, int action) +/*[clinic end generated code: output=afd10928e6ea66eb input=c6aff0640b6efd9c]*/ { - int fd, action; - if (!PyArg_ParseTuple(args, "O&i:tcflow", - _PyLong_FileDescriptor_Converter, &fd, &action)) { - return NULL; - } - termiosmodulestate *state = PyModule_GetState(module); if (tcflow(fd, action) == -1) { return PyErr_SetFromErrno(state->TermiosError); @@ -307,18 +317,12 @@ termios_tcflow(PyObject *module, PyObject *args) static PyMethodDef termios_methods[] = { - {"tcgetattr", termios_tcgetattr, - METH_VARARGS, termios_tcgetattr__doc__}, - {"tcsetattr", termios_tcsetattr, - METH_VARARGS, termios_tcsetattr__doc__}, - {"tcsendbreak", termios_tcsendbreak, - METH_VARARGS, termios_tcsendbreak__doc__}, - {"tcdrain", termios_tcdrain, - METH_VARARGS, termios_tcdrain__doc__}, - {"tcflush", termios_tcflush, - METH_VARARGS, termios_tcflush__doc__}, - {"tcflow", termios_tcflow, - METH_VARARGS, termios_tcflow__doc__}, + TERMIOS_TCGETATTR_METHODDEF + TERMIOS_TCSETATTR_METHODDEF + TERMIOS_TCSENDBREAK_METHODDEF + TERMIOS_TCDRAIN_METHODDEF + TERMIOS_TCFLUSH_METHODDEF + TERMIOS_TCFLOW_METHODDEF {NULL, NULL} };