From bfefa956a7a39ac736a8895c045492194c9fe989 Mon Sep 17 00:00:00 2001 From: Oleg Iarygin Date: Wed, 11 May 2022 09:20:54 +0300 Subject: [PATCH 1/6] Port 8-argument _warnings.warn_explicit to Argument Clinic The generated version: - replaces METH_VARARGS with METH_FASTCALL - replaces PyArg_ParseTupleAndKeywords with _PyArg_UnpackKeywords - stresses that warn_explicit() differs object=Py_None and object=NULL --- ...2-05-11-09-16-54.gh-issue-91102.lenv9h.rst | 8 ++ Python/_warnings.c | 45 +++++----- Python/clinic/_warnings.c.h | 83 ++++++++++++++++++- 3 files changed, 112 insertions(+), 24 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst b/Misc/NEWS.d/next/Core and Builtins/2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst new file mode 100644 index 00000000000000..5d531fac08c413 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst @@ -0,0 +1,8 @@ +8-argument :meth:`_warnings.warn_explicit` is ported to Argument Clinic. +Benefits: + +1. :c:data:`METH_VARARGS` calling convention is replaced with + a little faster :c:data:`METH_FASTCALL` (no extra tuple creation) +2. :c:func:`PyArg_ParseTupleAndKeywords` call is replaced with + :c:func:`_PyArg_UnpackKeywords` and a tailored parser generated specially + for the ported function. diff --git a/Python/_warnings.c b/Python/_warnings.c index 942308b357e338..2363ef795c76a8 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1031,28 +1031,31 @@ get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno return source_line; } +/*[clinic input] +warn_explicit as warnings_warn_explicit + + message: object + category: object + filename: unicode + lineno: int + mod: object = NULL + registry: object = None + module_globals: object = None + source as sourceobj: object = None + +Issue a warning, or maybe ignore it or raise an exception. +[clinic start generated code]*/ + static PyObject * -warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) +warnings_warn_explicit_impl(PyObject *module, PyObject *message, + PyObject *category, PyObject *filename, + int lineno, PyObject *mod, PyObject *registry, + PyObject *module_globals, PyObject *sourceobj) +/*[clinic end generated code: output=c49c62b15a49a186 input=81e348c13d2f0cda]*/ { - static char *kwd_list[] = {"message", "category", "filename", "lineno", - "module", "registry", "module_globals", - "source", 0}; - PyObject *message; - PyObject *category; - PyObject *filename; - int lineno; - PyObject *module = NULL; - PyObject *registry = NULL; - PyObject *module_globals = NULL; - PyObject *sourceobj = NULL; PyObject *source_line = NULL; PyObject *returned; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOUi|OOOO:warn_explicit", - kwd_list, &message, &category, &filename, &lineno, &module, - ®istry, &module_globals, &sourceobj)) - return NULL; - PyThreadState *tstate = get_current_tstate(); if (tstate == NULL) { return NULL; @@ -1071,7 +1074,7 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } } - returned = warn_explicit(tstate, category, message, filename, lineno, module, + returned = warn_explicit(tstate, category, message, filename, lineno, mod, registry, source_line, sourceobj); Py_XDECREF(source_line); return returned; @@ -1348,13 +1351,9 @@ _PyErr_WarnUnawaitedCoroutine(PyObject *coro) } } -PyDoc_STRVAR(warn_explicit_doc, -"Low-level interface to warnings functionality."); - static PyMethodDef warnings_functions[] = { WARNINGS_WARN_METHODDEF - {"warn_explicit", _PyCFunction_CAST(warnings_warn_explicit), - METH_VARARGS | METH_KEYWORDS, warn_explicit_doc}, + WARNINGS_WARN_EXPLICIT_METHODDEF {"_filters_mutated", _PyCFunction_CAST(warnings_filters_mutated), METH_NOARGS, NULL}, /* XXX(brett.cannon): add showwarning? */ diff --git a/Python/clinic/_warnings.c.h b/Python/clinic/_warnings.c.h index aa85c2a0d4d920..0d7d68f67eff74 100644 --- a/Python/clinic/_warnings.c.h +++ b/Python/clinic/_warnings.c.h @@ -66,4 +66,85 @@ warnings_warn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=0435c68611fa2fe9 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(warnings_warn_explicit__doc__, +"warn_explicit($module, /, message, category, filename, lineno,\n" +" mod=, registry=None,\n" +" module_globals=None, source=None)\n" +"--\n" +"\n" +"Issue a warning, or maybe ignore it or raise an exception."); + +#define WARNINGS_WARN_EXPLICIT_METHODDEF \ + {"warn_explicit", _PyCFunction_CAST(warnings_warn_explicit), METH_FASTCALL|METH_KEYWORDS, warnings_warn_explicit__doc__}, + +static PyObject * +warnings_warn_explicit_impl(PyObject *module, PyObject *message, + PyObject *category, PyObject *filename, + int lineno, PyObject *mod, PyObject *registry, + PyObject *module_globals, PyObject *sourceobj); + +static PyObject * +warnings_warn_explicit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"message", "category", "filename", "lineno", "mod", "registry", "module_globals", "source", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "warn_explicit", 0}; + PyObject *argsbuf[8]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4; + PyObject *message; + PyObject *category; + PyObject *filename; + int lineno; + PyObject *mod = NULL; + PyObject *registry = Py_None; + PyObject *module_globals = Py_None; + PyObject *sourceobj = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 8, 0, argsbuf); + if (!args) { + goto exit; + } + message = args[0]; + category = args[1]; + if (!PyUnicode_Check(args[2])) { + _PyArg_BadArgument("warn_explicit", "argument 'filename'", "str", args[2]); + goto exit; + } + if (PyUnicode_READY(args[2]) == -1) { + goto exit; + } + filename = args[2]; + lineno = _PyLong_AsInt(args[3]); + if (lineno == -1 && PyErr_Occurred()) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[4]) { + mod = args[4]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[5]) { + registry = args[5]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[6]) { + module_globals = args[6]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + sourceobj = args[7]; +skip_optional_pos: + return_value = warnings_warn_explicit_impl(module, message, category, filename, lineno, mod, registry, module_globals, sourceobj); + +exit: + return return_value; +} +/*[clinic end generated code: output=c987f4f834a6930e input=a9049054013a1b77]*/ From b3ebb1951d2e5a75703a1c3503b8019185df0e86 Mon Sep 17 00:00:00 2001 From: Oleg Iarygin Date: Fri, 24 Jun 2022 23:51:46 +0300 Subject: [PATCH 2/6] Return an original `module` argument --- Python/_warnings.c | 13 +++++++------ Python/clinic/_warnings.c.h | 18 +++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Python/_warnings.c b/Python/_warnings.c index c763dbed18825c..03897959181f94 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1033,11 +1033,12 @@ get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno /*[clinic input] warn_explicit as warnings_warn_explicit + _module: self(type="PyObject *") message: object category: object filename: unicode lineno: int - mod: object = NULL + module: object = NULL registry: object = None module_globals: object = None source as sourceobj: object = None @@ -1046,11 +1047,11 @@ Issue a warning, or maybe ignore it or raise an exception. [clinic start generated code]*/ static PyObject * -warnings_warn_explicit_impl(PyObject *module, PyObject *message, +warnings_warn_explicit_impl(PyObject *_module, PyObject *message, PyObject *category, PyObject *filename, - int lineno, PyObject *mod, PyObject *registry, + int lineno, PyObject *module, PyObject *registry, PyObject *module_globals, PyObject *sourceobj) -/*[clinic end generated code: output=c49c62b15a49a186 input=81e348c13d2f0cda]*/ +/*[clinic end generated code: output=724ff9da85258808 input=b2771a0c4840a660]*/ { PyObject *source_line = NULL; PyObject *returned; @@ -1073,8 +1074,8 @@ warnings_warn_explicit_impl(PyObject *module, PyObject *message, return NULL; } } - returned = warn_explicit(tstate, category, message, filename, lineno, mod, - registry, source_line, sourceobj); + returned = warn_explicit(tstate, category, message, filename, lineno, + module, registry, source_line, sourceobj); Py_XDECREF(source_line); return returned; } diff --git a/Python/clinic/_warnings.c.h b/Python/clinic/_warnings.c.h index 0d7d68f67eff74..10f149c858c162 100644 --- a/Python/clinic/_warnings.c.h +++ b/Python/clinic/_warnings.c.h @@ -69,7 +69,7 @@ warnings_warn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec PyDoc_STRVAR(warnings_warn_explicit__doc__, "warn_explicit($module, /, message, category, filename, lineno,\n" -" mod=, registry=None,\n" +" module=, registry=None,\n" " module_globals=None, source=None)\n" "--\n" "\n" @@ -79,16 +79,16 @@ PyDoc_STRVAR(warnings_warn_explicit__doc__, {"warn_explicit", _PyCFunction_CAST(warnings_warn_explicit), METH_FASTCALL|METH_KEYWORDS, warnings_warn_explicit__doc__}, static PyObject * -warnings_warn_explicit_impl(PyObject *module, PyObject *message, +warnings_warn_explicit_impl(PyObject *_module, PyObject *message, PyObject *category, PyObject *filename, - int lineno, PyObject *mod, PyObject *registry, + int lineno, PyObject *module, PyObject *registry, PyObject *module_globals, PyObject *sourceobj); static PyObject * -warnings_warn_explicit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +warnings_warn_explicit(PyObject *_module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"message", "category", "filename", "lineno", "mod", "registry", "module_globals", "source", NULL}; + static const char * const _keywords[] = {"message", "category", "filename", "lineno", "module", "registry", "module_globals", "source", NULL}; static _PyArg_Parser _parser = {NULL, _keywords, "warn_explicit", 0}; PyObject *argsbuf[8]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4; @@ -96,7 +96,7 @@ warnings_warn_explicit(PyObject *module, PyObject *const *args, Py_ssize_t nargs PyObject *category; PyObject *filename; int lineno; - PyObject *mod = NULL; + PyObject *module = NULL; PyObject *registry = Py_None; PyObject *module_globals = Py_None; PyObject *sourceobj = Py_None; @@ -123,7 +123,7 @@ warnings_warn_explicit(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto skip_optional_pos; } if (args[4]) { - mod = args[4]; + module = args[4]; if (!--noptargs) { goto skip_optional_pos; } @@ -142,9 +142,9 @@ warnings_warn_explicit(PyObject *module, PyObject *const *args, Py_ssize_t nargs } sourceobj = args[7]; skip_optional_pos: - return_value = warnings_warn_explicit_impl(module, message, category, filename, lineno, mod, registry, module_globals, sourceobj); + return_value = warnings_warn_explicit_impl(_module, message, category, filename, lineno, module, registry, module_globals, sourceobj); exit: return return_value; } -/*[clinic end generated code: output=c987f4f834a6930e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=68443ff7e840bc8c input=a9049054013a1b77]*/ From c85bbfbe6cc858003987df8ae548e96e30a4a91e Mon Sep 17 00:00:00 2001 From: Oleg Iarygin Date: Fri, 1 Jul 2022 13:27:55 +0300 Subject: [PATCH 3/6] Redefine `module` parameter as proposed in gh-94431 --- Python/_warnings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/_warnings.c b/Python/_warnings.c index 03897959181f94..45ea1cc3d0fda4 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1033,7 +1033,7 @@ get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno /*[clinic input] warn_explicit as warnings_warn_explicit - _module: self(type="PyObject *") + module as _module message: object category: object filename: unicode From 598a7a4778f2a1066644a1ff7846ea0635c0e89c Mon Sep 17 00:00:00 2001 From: Oleg Iarygin Date: Fri, 1 Jul 2022 13:33:38 +0300 Subject: [PATCH 4/6] Restore an object parameter type (instead of `self`) --- Python/_warnings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/_warnings.c b/Python/_warnings.c index 45ea1cc3d0fda4..8afabe0d3b3577 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1033,7 +1033,7 @@ get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno /*[clinic input] warn_explicit as warnings_warn_explicit - module as _module + module as _module: object message: object category: object filename: unicode From 7e2227aaf3980af07f0036ae8a99e497734b2f94 Mon Sep 17 00:00:00 2001 From: Oleg Iarygin Date: Thu, 7 Jul 2022 12:56:53 +0300 Subject: [PATCH 5/6] Apply Kumar's suggestion --- Python/_warnings.c | 11 +++++------ Python/clinic/_warnings.c.h | 14 +++++++------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Python/_warnings.c b/Python/_warnings.c index 8afabe0d3b3577..1b9e107ea30b13 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1033,12 +1033,11 @@ get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno /*[clinic input] warn_explicit as warnings_warn_explicit - module as _module: object message: object category: object filename: unicode lineno: int - module: object = NULL + module as mod: object = NULL registry: object = None module_globals: object = None source as sourceobj: object = None @@ -1047,11 +1046,11 @@ Issue a warning, or maybe ignore it or raise an exception. [clinic start generated code]*/ static PyObject * -warnings_warn_explicit_impl(PyObject *_module, PyObject *message, +warnings_warn_explicit_impl(PyObject *module, PyObject *message, PyObject *category, PyObject *filename, - int lineno, PyObject *module, PyObject *registry, + int lineno, PyObject *mod, PyObject *registry, PyObject *module_globals, PyObject *sourceobj) -/*[clinic end generated code: output=724ff9da85258808 input=b2771a0c4840a660]*/ +/*[clinic end generated code: output=c49c62b15a49a186 input=df6eeb8b45e712f1]*/ { PyObject *source_line = NULL; PyObject *returned; @@ -1075,7 +1074,7 @@ warnings_warn_explicit_impl(PyObject *_module, PyObject *message, } } returned = warn_explicit(tstate, category, message, filename, lineno, - module, registry, source_line, sourceobj); + mod, registry, source_line, sourceobj); Py_XDECREF(source_line); return returned; } diff --git a/Python/clinic/_warnings.c.h b/Python/clinic/_warnings.c.h index 10f149c858c162..926fb32e7c261e 100644 --- a/Python/clinic/_warnings.c.h +++ b/Python/clinic/_warnings.c.h @@ -79,13 +79,13 @@ PyDoc_STRVAR(warnings_warn_explicit__doc__, {"warn_explicit", _PyCFunction_CAST(warnings_warn_explicit), METH_FASTCALL|METH_KEYWORDS, warnings_warn_explicit__doc__}, static PyObject * -warnings_warn_explicit_impl(PyObject *_module, PyObject *message, +warnings_warn_explicit_impl(PyObject *module, PyObject *message, PyObject *category, PyObject *filename, - int lineno, PyObject *module, PyObject *registry, + int lineno, PyObject *mod, PyObject *registry, PyObject *module_globals, PyObject *sourceobj); static PyObject * -warnings_warn_explicit(PyObject *_module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +warnings_warn_explicit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"message", "category", "filename", "lineno", "module", "registry", "module_globals", "source", NULL}; @@ -96,7 +96,7 @@ warnings_warn_explicit(PyObject *_module, PyObject *const *args, Py_ssize_t narg PyObject *category; PyObject *filename; int lineno; - PyObject *module = NULL; + PyObject *mod = NULL; PyObject *registry = Py_None; PyObject *module_globals = Py_None; PyObject *sourceobj = Py_None; @@ -123,7 +123,7 @@ warnings_warn_explicit(PyObject *_module, PyObject *const *args, Py_ssize_t narg goto skip_optional_pos; } if (args[4]) { - module = args[4]; + mod = args[4]; if (!--noptargs) { goto skip_optional_pos; } @@ -142,9 +142,9 @@ warnings_warn_explicit(PyObject *_module, PyObject *const *args, Py_ssize_t narg } sourceobj = args[7]; skip_optional_pos: - return_value = warnings_warn_explicit_impl(_module, message, category, filename, lineno, module, registry, module_globals, sourceobj); + return_value = warnings_warn_explicit_impl(module, message, category, filename, lineno, mod, registry, module_globals, sourceobj); exit: return return_value; } -/*[clinic end generated code: output=68443ff7e840bc8c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=596b370838b95386 input=a9049054013a1b77]*/ From d5528cb22aae668d3640fe28c98d14f5430bd798 Mon Sep 17 00:00:00 2001 From: Oleg Iarygin Date: Thu, 7 Jul 2022 13:11:33 +0300 Subject: [PATCH 6/6] Remove sales pitch from the NEWS entry --- .../2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst b/Misc/NEWS.d/next/Core and Builtins/2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst index 5d531fac08c413..b2bdf9d5322f37 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst @@ -1,8 +1 @@ -8-argument :meth:`_warnings.warn_explicit` is ported to Argument Clinic. -Benefits: - -1. :c:data:`METH_VARARGS` calling convention is replaced with - a little faster :c:data:`METH_FASTCALL` (no extra tuple creation) -2. :c:func:`PyArg_ParseTupleAndKeywords` call is replaced with - :c:func:`_PyArg_UnpackKeywords` and a tailored parser generated specially - for the ported function. +:meth:`_warnings.warn_explicit` is ported to Argument Clinic.