diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -423,6 +423,9 @@ - Issue #19545: Avoid chained exceptions while passing stray % to time.strptime(). Initial patch by Claudiu Popa. +- Issue #20177: Use argument clinic to parse arguments in + timemodule.c. Patch by Nikolaus Rath. + IDLE ---- diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -49,6 +49,11 @@ static OSVERSIONINFOEX winver; #endif +/*[clinic input] +module time +[clinic start generated code]*/ +/*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ + static PyObject * time_time(PyObject *self, PyObject *unused) { @@ -157,16 +162,48 @@ #endif #ifdef HAVE_CLOCK_GETTIME +/*[clinic input] +time.clock_gettime + + clk_id: "i" + / + +Return the time of the specified clock clk_id +[clinic start generated code]*/ + +PyDoc_STRVAR(time_clock_gettime__doc__, +"clock_gettime(clk_id)\n" +"Return the time of the specified clock clk_id"); + +#define TIME_CLOCK_GETTIME_METHODDEF \ + {"clock_gettime", (PyCFunction)time_clock_gettime, METH_VARARGS, time_clock_gettime__doc__}, + static PyObject * -time_clock_gettime(PyObject *self, PyObject *args) +time_clock_gettime_impl(PyModuleDef *module, int clk_id); + +static PyObject * +time_clock_gettime(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int clk_id; + + if (!PyArg_ParseTuple(args, + "i:clock_gettime", + &clk_id)) + goto exit; + return_value = time_clock_gettime_impl(module, clk_id); + +exit: + return return_value; +} + +static PyObject * +time_clock_gettime_impl(PyModuleDef *module, int clk_id) +/*[clinic end generated code: checksum=cefaa34b15ff90542d1ee0847c40314c254b1d7b]*/ { int ret; - int clk_id; struct timespec tp; - if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) - return NULL; - ret = clock_gettime((clockid_t)clk_id, &tp); if (ret != 0) { PyErr_SetFromErrno(PyExc_IOError); @@ -175,24 +212,53 @@ return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); } -PyDoc_STRVAR(clock_gettime_doc, -"clock_gettime(clk_id) -> floating point number\n\ -\n\ -Return the time of the specified clock clk_id."); + +/*[clinic input] +time.clock_settime + + clk_id: "i" + obj: "O" + / + +Set the time of the specified clock clk_id. +[clinic start generated code]*/ + +PyDoc_STRVAR(time_clock_settime__doc__, +"clock_settime(clk_id, obj)\n" +"Set the time of the specified clock clk_id."); + +#define TIME_CLOCK_SETTIME_METHODDEF \ + {"clock_settime", (PyCFunction)time_clock_settime, METH_VARARGS, time_clock_settime__doc__}, static PyObject * -time_clock_settime(PyObject *self, PyObject *args) +time_clock_settime_impl(PyModuleDef *module, int clk_id, PyObject *obj); + +static PyObject * +time_clock_settime(PyModuleDef *module, PyObject *args) { + PyObject *return_value = NULL; int clk_id; PyObject *obj; + + if (!PyArg_ParseTuple(args, + "iO:clock_settime", + &clk_id, &obj)) + goto exit; + return_value = time_clock_settime_impl(module, clk_id, obj); + +exit: + return return_value; +} + +static PyObject * +time_clock_settime_impl(PyModuleDef *module, int clk_id, PyObject *obj) +/*[clinic end generated code: checksum=c2ad16097bd86c6e8926b01f2488dc3c2bf6d3f6]*/ +{ time_t tv_sec; long tv_nsec; struct timespec tp; int ret; - if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) - return NULL; - if (_PyTime_ObjectToTimespec(obj, &tv_sec, &tv_nsec) == -1) return NULL; tp.tv_sec = tv_sec; @@ -206,21 +272,49 @@ Py_RETURN_NONE; } -PyDoc_STRVAR(clock_settime_doc, -"clock_settime(clk_id, time)\n\ -\n\ -Set the time of the specified clock clk_id."); + +/*[clinic input] +time.clock_getres + + clk_id: "i" + / + +Return the resolution (precision) of the specified clock clk_id. +[clinic start generated code]*/ + +PyDoc_STRVAR(time_clock_getres__doc__, +"clock_getres(clk_id)\n" +"Return the resolution (precision) of the specified clock clk_id."); + +#define TIME_CLOCK_GETRES_METHODDEF \ + {"clock_getres", (PyCFunction)time_clock_getres, METH_VARARGS, time_clock_getres__doc__}, static PyObject * -time_clock_getres(PyObject *self, PyObject *args) +time_clock_getres_impl(PyModuleDef *module, int clk_id); + +static PyObject * +time_clock_getres(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int clk_id; + + if (!PyArg_ParseTuple(args, + "i:clock_getres", + &clk_id)) + goto exit; + return_value = time_clock_getres_impl(module, clk_id); + +exit: + return return_value; +} + +static PyObject * +time_clock_getres_impl(PyModuleDef *module, int clk_id) +/*[clinic end generated code: checksum=bbf728de562dbd7d909dc0f6396d8368d98c16c6]*/ { int ret; - int clk_id; struct timespec tp; - if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id)) - return NULL; - ret = clock_getres((clockid_t)clk_id, &tp); if (ret != 0) { PyErr_SetFromErrno(PyExc_IOError); @@ -229,19 +323,51 @@ return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); } - -PyDoc_STRVAR(clock_getres_doc, -"clock_getres(clk_id) -> floating point number\n\ -\n\ -Return the resolution (precision) of the specified clock clk_id."); #endif /* HAVE_CLOCK_GETTIME */ +/*[clinic input] +time.sleep + + secs: "d" + / + +Delay execution for a given number of seconds. + +The argument may be a floating point number for subsecond precision. +[clinic start generated code]*/ + +PyDoc_STRVAR(time_sleep__doc__, +"sleep(secs)\n" +"Delay execution for a given number of seconds.\n" +"\n" +"The argument may be a floating point number for subsecond precision."); + +#define TIME_SLEEP_METHODDEF \ + {"sleep", (PyCFunction)time_sleep, METH_VARARGS, time_sleep__doc__}, + static PyObject * -time_sleep(PyObject *self, PyObject *args) +time_sleep_impl(PyModuleDef *module, double secs); + +static PyObject * +time_sleep(PyModuleDef *module, PyObject *args) { + PyObject *return_value = NULL; double secs; - if (!PyArg_ParseTuple(args, "d:sleep", &secs)) - return NULL; + + if (!PyArg_ParseTuple(args, + "d:sleep", + &secs)) + goto exit; + return_value = time_sleep_impl(module, secs); + +exit: + return return_value; +} + +static PyObject * +time_sleep_impl(PyModuleDef *module, double secs) +/*[clinic end generated code: checksum=66cd8e8be8e7d3a8d1732ba218de5baf175c22dd]*/ +{ if (secs < 0) { PyErr_SetString(PyExc_ValueError, "sleep length must be non-negative"); @@ -253,11 +379,6 @@ return Py_None; } -PyDoc_STRVAR(sleep_doc, -"sleep(seconds)\n\ -\n\ -Delay execution for a given number of seconds. The argument may be\n\ -a floating point number for subsecond precision."); static PyStructSequence_Field struct_time_type_fields[] = { {"tm_year", "year, for example, 1993"}, @@ -565,10 +686,53 @@ #define time_strlen strlen #endif +/*[clinic input] +time.strftime + + format_arg: "U" + tup: "O"=None + / + +Convert a time tuple to a string according to a format specification. + +See the library reference manual for formatting codes. When the time tuple +is not present, current time as returned by localtime() is used. +[clinic start generated code]*/ + +PyDoc_STRVAR(time_strftime__doc__, +"strftime(format_arg, tup=None)\n" +"Convert a time tuple to a string according to a format specification.\n" +"\n" +"See the library reference manual for formatting codes. When the time tuple\n" +"is not present, current time as returned by localtime() is used."); + +#define TIME_STRFTIME_METHODDEF \ + {"strftime", (PyCFunction)time_strftime, METH_VARARGS, time_strftime__doc__}, + static PyObject * -time_strftime(PyObject *self, PyObject *args) +time_strftime_impl(PyModuleDef *module, PyObject *format_arg, PyObject *tup); + +static PyObject * +time_strftime(PyModuleDef *module, PyObject *args) { - PyObject *tup = NULL; + PyObject *return_value = NULL; + PyObject *format_arg; + PyObject *tup = Py_None; + + if (!PyArg_ParseTuple(args, + "U|O:strftime", + &format_arg, &tup)) + goto exit; + return_value = time_strftime_impl(module, format_arg, tup); + +exit: + return return_value; +} + +static PyObject * +time_strftime_impl(PyModuleDef *module, PyObject *format_arg, PyObject *tup) +/*[clinic end generated code: checksum=90fb8736ec1e85fe5dc7cbe259ce990e5ee8e35d]*/ +{ struct tm buf; const time_char *fmt; #ifdef HAVE_WCSFTIME @@ -576,7 +740,6 @@ #else PyObject *format; #endif - PyObject *format_arg; size_t fmtlen, buflen; time_char *outbuf = NULL; size_t i; @@ -584,12 +747,6 @@ memset((void *) &buf, '\0', sizeof(buf)); - /* Will always expect a unicode string to be passed as format. - Given that there's no str type anymore in py3k this seems safe. - */ - if (!PyArg_ParseTuple(args, "U|O:strftime", &format_arg, &tup)) - return NULL; - if (tup == NULL) { time_t tt = time(NULL); if (pylocaltime(&tt, &buf) == -1) @@ -717,13 +874,6 @@ #undef time_char #undef format_time -PyDoc_STRVAR(strftime_doc, -"strftime(format[, tuple]) -> string\n\ -\n\ -Convert a time tuple to a string according to a format specification.\n\ -See the library reference manual for formatting codes. When the time tuple\n\ -is not present, current time as returned by localtime() is used.\n\ -\n" STRFTIME_FORMAT_CODES); #endif /* HAVE_STRFTIME */ static PyObject * @@ -1396,11 +1546,11 @@ {"clock", time_clock, METH_NOARGS, clock_doc}, #endif #ifdef HAVE_CLOCK_GETTIME - {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, - {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, - {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc}, + TIME_CLOCK_GETTIME_METHODDEF + TIME_CLOCK_SETTIME_METHODDEF + TIME_CLOCK_GETRES_METHODDEF #endif - {"sleep", time_sleep, METH_VARARGS, sleep_doc}, + TIME_SLEEP_METHODDEF {"gmtime", time_gmtime, METH_VARARGS, gmtime_doc}, {"localtime", time_localtime, METH_VARARGS, localtime_doc}, {"asctime", time_asctime, METH_VARARGS, asctime_doc}, @@ -1409,7 +1559,7 @@ {"mktime", time_mktime, METH_O, mktime_doc}, #endif #ifdef HAVE_STRFTIME - {"strftime", time_strftime, METH_VARARGS, strftime_doc}, + TIME_STRFTIME_METHODDEF #endif {"strptime", time_strptime, METH_VARARGS, strptime_doc}, #ifdef HAVE_WORKING_TZSET