From cc0e9020787141bbe6e98eba6fa7b02f1ccf75fa Mon Sep 17 00:00:00 2001 From: Cody Maloney Date: Tue, 27 Oct 2026 19:18:45 -0700 Subject: [PATCH] gh-87613: Name the subclass in Argument Clinic `__new__` argument errors tp_new is inherited, so argument errors from a subclass named the base type. While `tp_name` would be slightly faster to use it includes the module name like `_thread.RLock()` which adds confusion. Use `_PyType_Name(type)` which returns `RLock()`. Include a test to check. _PyArg_NoPositional() only short-circuits when args is NULL, which tp_new never gets; use _PyArg_NoPositionalStack() to keep the name lookup off the success path. Co-Authored-By: Claude Opus 5.5 --- Lib/test/clinic.test.c | 14 +++---- Lib/test/test_clinic.py | 11 ++++++ ...6-10-27-19-26-26.gh-issue-87613.B-mZEA.rst | 2 + Modules/_sqlite/clinic/row.c.h | 6 +-- Modules/clinic/_bz2module.c.h | 10 ++--- Modules/clinic/_collectionsmodule.c.h | 6 +-- Modules/clinic/_csv.c.h | 6 +-- Modules/clinic/_queuemodule.c.h | 6 +-- Modules/clinic/_ssl.c.h | 10 ++--- Modules/clinic/_testclinic_kwds.c.h | 4 +- Modules/clinic/_threadmodule.c.h | 10 ++--- Modules/clinic/_zoneinfo.c.h | 4 +- Modules/clinic/itertoolsmodule.c.h | 38 +++++++++---------- Modules/clinic/selectmodule.c.h | 6 +-- Objects/clinic/classobject.c.h | 10 ++--- Objects/clinic/codeobject.c.h | 6 +-- Objects/clinic/enumobject.c.h | 8 ++-- Objects/clinic/floatobject.c.h | 8 ++-- Objects/clinic/namespaceobject.c.h | 6 +-- Objects/clinic/structseq.c.h | 4 +- Objects/clinic/tupleobject.c.h | 8 ++-- Objects/clinic/weakrefobject.c.h | 8 ++-- Python/clinic/instruction_sequence.c.h | 6 +-- Tools/clinic/libclinic/clanguage.py | 1 + Tools/clinic/libclinic/converters.py | 3 ++ Tools/clinic/libclinic/parse_args.py | 12 +++--- 26 files changed, 115 insertions(+), 98 deletions(-) create mode 100644 Misc/NEWS.d/next/Tools-Demos/2026-10-27-19-26-26.gh-issue-87613.B-mZEA.rst diff --git a/Lib/test/clinic.test.c b/Lib/test/clinic.test.c index 86b8f81776dfc3..d8dfb9af652102 100644 --- a/Lib/test/clinic.test.c +++ b/Lib/test/clinic.test.c @@ -4968,7 +4968,7 @@ Test___init__(PyObject *self, PyObject *args, PyObject *kwargs) if ((Py_IS_TYPE(self, base_tp) || Py_TYPE(self)->tp_new == base_tp->tp_new) && - !_PyArg_NoPositional("Test", args)) { + !_PyArg_NoPositionalStack("Test", PyTuple_GET_SIZE(args))) { goto exit; } if ((Py_IS_TYPE(self, base_tp) || @@ -5017,7 +5017,7 @@ Test_vectorcall(PyObject *type, PyObject *const *args, static int Test___init___impl(TestObj *self) -/*[clinic end generated code: output=ce04b9d7beacd894 input=645fe693f6c6b9b6]*/ +/*[clinic end generated code: output=62017ea6333c9634 input=645fe693f6c6b9b6]*/ /*[clinic input] @@ -5042,11 +5042,11 @@ Test(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyTypeObject *base_tp = TestType; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoPositional("Test", args)) { + !_PyArg_NoPositionalStack(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args))) { goto exit; } if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("Test", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } return_value = Test_impl(type); @@ -5057,7 +5057,7 @@ Test(PyTypeObject *type, PyObject *args, PyObject *kwargs) static PyObject * Test_impl(PyTypeObject *type) -/*[clinic end generated code: output=68a117adc057940f input=6fe98a19f097907f]*/ +/*[clinic end generated code: output=deab914e0af675ba input=6fe98a19f097907f]*/ /*[clinic input] @@ -5248,7 +5248,7 @@ Test(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *__clinic_args = NULL; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("Test", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } __clinic_args = Py_NewRef(args); @@ -5263,7 +5263,7 @@ Test(PyTypeObject *type, PyObject *args, PyObject *kwargs) static PyObject * Test_impl(PyTypeObject *type, PyObject *args) -/*[clinic end generated code: output=e6fba0c8951882fd input=8ce30adb836aeacb]*/ +/*[clinic end generated code: output=9e97b89fb3f12f76 input=8ce30adb836aeacb]*/ /*[clinic input] diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index e57f4c4a9d556a..454b655487aa36 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -5806,6 +5806,17 @@ def test_vc_new_base_subclass(self): self.assertIsInstance(obj, Sub) self.assertIsInstance(obj, ac_tester.VcNewBase) + def test_new_errors_name_subclass(self): + # tp_new is inherited, so its errors name the subclass; the + # vectorcall only sees the base type. + Sub = type('Sub', (float,), {}) + with self.assertRaisesRegex(TypeError, r'^float expected at most 1'): + float(1, 2) + with self.assertRaisesRegex(TypeError, r'^Sub expected at most 1'): + Sub(1, 2) + with self.assertRaisesRegex(TypeError, r'^Sub\(\) takes no keyword'): + Sub(x=1) + def test_vc_kwonly(self): # keyword-only 'b': vectorcall has no kwnames==NULL fast path, # so every call goes through the helper. diff --git a/Misc/NEWS.d/next/Tools-Demos/2026-10-27-19-26-26.gh-issue-87613.B-mZEA.rst b/Misc/NEWS.d/next/Tools-Demos/2026-10-27-19-26-26.gh-issue-87613.B-mZEA.rst new file mode 100644 index 00000000000000..cea84390729e3d --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2026-10-27-19-26-26.gh-issue-87613.B-mZEA.rst @@ -0,0 +1,2 @@ +Generate subclass names in Argument Clinic ``__new__`` error messages rather +than hardcoding the base type. diff --git a/Modules/_sqlite/clinic/row.c.h b/Modules/_sqlite/clinic/row.c.h index 068906744e445f..364849d7a6aeae 100644 --- a/Modules/_sqlite/clinic/row.c.h +++ b/Modules/_sqlite/clinic/row.c.h @@ -17,10 +17,10 @@ pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *data; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("Row", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("Row", PyTuple_GET_SIZE(args), 2, 2)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 2, 2)) { goto exit; } if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), clinic_state()->CursorType)) { @@ -56,4 +56,4 @@ pysqlite_row_keys(PyObject *self, PyObject *Py_UNUSED(ignored)) { return pysqlite_row_keys_impl((pysqlite_Row *)self); } -/*[clinic end generated code: output=6c1acbb48f386468 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=28333de748eac5f0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_bz2module.c.h b/Modules/clinic/_bz2module.c.h index 30f2c7965e73ae..86264d89e6e46f 100644 --- a/Modules/clinic/_bz2module.c.h +++ b/Modules/clinic/_bz2module.c.h @@ -90,10 +90,10 @@ _bz2_BZ2Compressor(PyTypeObject *type, PyObject *args, PyObject *kwargs) int compresslevel = 9; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("BZ2Compressor", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("BZ2Compressor", PyTuple_GET_SIZE(args), 0, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 0, 1)) { goto exit; } if (PyTuple_GET_SIZE(args) < 1) { @@ -226,11 +226,11 @@ _bz2_BZ2Decompressor(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyTypeObject *base_tp = clinic_state()->bz2_decompressor_type; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoPositional("BZ2Decompressor", args)) { + !_PyArg_NoPositionalStack(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args))) { goto exit; } if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("BZ2Decompressor", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } return_value = _bz2_BZ2Decompressor_impl(type); @@ -238,4 +238,4 @@ _bz2_BZ2Decompressor(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=1dce5396d592bad7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d1023f5202abb559 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_collectionsmodule.c.h b/Modules/clinic/_collectionsmodule.c.h index 2966d68aa3813b..bc7c74ca020851 100644 --- a/Modules/clinic/_collectionsmodule.c.h +++ b/Modules/clinic/_collectionsmodule.c.h @@ -683,10 +683,10 @@ tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *doc; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("_tuplegetter", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("_tuplegetter", PyTuple_GET_SIZE(args), 2, 2)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 2, 2)) { goto exit; } { @@ -707,4 +707,4 @@ tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=de400069cf6f11a4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d4adff4f2e5225fa input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_csv.c.h b/Modules/clinic/_csv.c.h index df3bdbadf29aed..b93dbc3c71576d 100644 --- a/Modules/clinic/_csv.c.h +++ b/Modules/clinic/_csv.c.h @@ -7,7 +7,7 @@ preserve # include "pycore_runtime.h" // _Py_ID() #endif #include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() -#include "pycore_modsupport.h" // _PyArg_NoPositional() +#include "pycore_modsupport.h" // _PyArg_NoPositionalStack() PyDoc_STRVAR(_csv_Dialect___reduce____doc__, "__reduce__($self, /)\n" @@ -67,7 +67,7 @@ _csv_Dialect___replace__(PyObject *self, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; PyObject *changes = NULL; - if (!_PyArg_NoPositional("__replace__", args)) { + if (!_PyArg_NoPositionalStack("__replace__", PyTuple_GET_SIZE(args))) { goto exit; } if (kwargs == NULL) { @@ -465,4 +465,4 @@ _csv_field_size_limit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=7e3a92d524d88023 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b8df53e492d886fc input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_queuemodule.c.h b/Modules/clinic/_queuemodule.c.h index b67dd23f260c9e..d52545e21e834d 100644 --- a/Modules/clinic/_queuemodule.c.h +++ b/Modules/clinic/_queuemodule.c.h @@ -25,11 +25,11 @@ simplequeue_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyTypeObject *base_tp = simplequeue_get_state_by_type(type)->SimpleQueueType; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoPositional("SimpleQueue", args)) { + !_PyArg_NoPositionalStack(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args))) { goto exit; } if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("SimpleQueue", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } return_value = simplequeue_new_impl(type); @@ -390,4 +390,4 @@ _queue_SimpleQueue___sizeof__(PyObject *self, PyObject *Py_UNUSED(ignored)) exit: return return_value; } -/*[clinic end generated code: output=8219fe2f2ed5f068 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=08c05ea087ebf9fc input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 98a929b33def82..2d3d40937e88c2 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -974,10 +974,10 @@ _ssl__SSLContext(PyTypeObject *type, PyObject *args, PyObject *kwargs) int proto_version; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("_SSLContext", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("_SSLContext", PyTuple_GET_SIZE(args), 1, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 1, 1)) { goto exit; } proto_version = PyLong_AsInt(PyTuple_GET_ITEM(args, 0)); @@ -2619,11 +2619,11 @@ _ssl_MemoryBIO(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyTypeObject *base_tp = get_state_type(type)->PySSLMemoryBIO_Type; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoPositional("MemoryBIO", args)) { + !_PyArg_NoPositionalStack(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args))) { goto exit; } if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("MemoryBIO", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } Py_BEGIN_CRITICAL_SECTION(type); @@ -3373,4 +3373,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #define _SSL_SSLSESSION_HAS_TICKET_GETSETDEF {"has_ticket", (getter)_ssl_SSLSession_has_ticket_get, (setter)NULL, _ssl_SSLSession_has_ticket__doc__}, -/*[clinic end generated code: output=fb3476aa2f825376 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c6dc4754db666467 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_testclinic_kwds.c.h b/Modules/clinic/_testclinic_kwds.c.h index faae3f3d0c2658..837e78ccb67668 100644 --- a/Modules/clinic/_testclinic_kwds.c.h +++ b/Modules/clinic/_testclinic_kwds.c.h @@ -30,7 +30,7 @@ lone_kwds(PyObject *module, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; PyObject *__clinic_kwds = NULL; - if (!_PyArg_NoPositional("lone_kwds", args)) { + if (!_PyArg_NoPositionalStack("lone_kwds", PyTuple_GET_SIZE(args))) { goto exit; } if (kwargs == NULL) { @@ -230,4 +230,4 @@ kwds_with_pos_only_and_stararg(PyObject *module, PyObject *args, PyObject *kwarg return return_value; } -/*[clinic end generated code: output=27a7ba9440b9a884 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d44b2cff182e5203 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_threadmodule.c.h b/Modules/clinic/_threadmodule.c.h index 090fdee8f6593e..d99fe725f75dbb 100644 --- a/Modules/clinic/_threadmodule.c.h +++ b/Modules/clinic/_threadmodule.c.h @@ -396,11 +396,11 @@ lock_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyTypeObject *base_tp = clinic_state()->lock_type; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoPositional("lock", args)) { + !_PyArg_NoPositionalStack(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args))) { goto exit; } if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("lock", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } return_value = lock_new_impl(type); @@ -678,11 +678,11 @@ rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyTypeObject *base_tp = clinic_state()->rlock_type; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoPositional("RLock", args)) { + !_PyArg_NoPositionalStack(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args))) { goto exit; } if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("RLock", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } return_value = rlock_new_impl(type); @@ -1272,4 +1272,4 @@ _thread_set_name(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb #endif /* !defined(_THREAD_SET_NAME_METHODDEF) */ #define _THREAD__THREADHANDLE_IDENT_GETSETDEF {"ident", (getter)_thread__ThreadHandle_ident_get, (setter)NULL, NULL}, -/*[clinic end generated code: output=3bfc76a318c6579d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ba04c5cc1126016c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_zoneinfo.c.h b/Modules/clinic/_zoneinfo.c.h index 5d13e5b745562c..a37d33dd5cce3b 100644 --- a/Modules/clinic/_zoneinfo.c.h +++ b/Modules/clinic/_zoneinfo.c.h @@ -422,7 +422,7 @@ zoneinfo_ZoneInfo___init_subclass__(PyObject *type, PyObject *args, PyObject *kw PyObject *return_value = NULL; PyObject *__clinic_kwargs = NULL; - if (!_PyArg_NoPositional("__init_subclass__", args)) { + if (!_PyArg_NoPositionalStack("__init_subclass__", PyTuple_GET_SIZE(args))) { goto exit; } if (kwargs == NULL) { @@ -442,4 +442,4 @@ zoneinfo_ZoneInfo___init_subclass__(PyObject *type, PyObject *args, PyObject *kw return return_value; } -/*[clinic end generated code: output=d7aeeec4b950fc35 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4b98cad1ebcd1b85 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index d6365b46f04b26..48277e59ed91ea 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -125,10 +125,10 @@ pairwise_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *iterable; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("pairwise", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("pairwise", PyTuple_GET_SIZE(args), 1, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 1, 1)) { goto exit; } iterable = PyTuple_GET_ITEM(args, 0); @@ -222,10 +222,10 @@ itertools__grouper(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *tgtkey; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("_grouper", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("_grouper", PyTuple_GET_SIZE(args), 2, 2)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 2, 2)) { goto exit; } if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), clinic_state_by_cls()->groupby_type)) { @@ -260,10 +260,10 @@ itertools_teedataobject(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *next; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("teedataobject", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("teedataobject", PyTuple_GET_SIZE(args), 3, 3)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 3, 3)) { goto exit; } it = PyTuple_GET_ITEM(args, 0); @@ -296,10 +296,10 @@ itertools__tee(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *iterable; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("_tee", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("_tee", PyTuple_GET_SIZE(args), 1, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 1, 1)) { goto exit; } iterable = PyTuple_GET_ITEM(args, 0); @@ -376,10 +376,10 @@ itertools_cycle(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *iterable; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("cycle", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("cycle", PyTuple_GET_SIZE(args), 1, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 1, 1)) { goto exit; } iterable = PyTuple_GET_ITEM(args, 0); @@ -409,10 +409,10 @@ itertools_dropwhile(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *seq; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("dropwhile", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("dropwhile", PyTuple_GET_SIZE(args), 2, 2)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 2, 2)) { goto exit; } func = PyTuple_GET_ITEM(args, 0); @@ -441,10 +441,10 @@ itertools_takewhile(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *seq; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("takewhile", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("takewhile", PyTuple_GET_SIZE(args), 2, 2)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 2, 2)) { goto exit; } func = PyTuple_GET_ITEM(args, 0); @@ -473,10 +473,10 @@ itertools_starmap(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *seq; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("starmap", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("starmap", PyTuple_GET_SIZE(args), 2, 2)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 2, 2)) { goto exit; } func = PyTuple_GET_ITEM(args, 0); @@ -981,10 +981,10 @@ itertools_filterfalse(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *seq; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("filterfalse", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("filterfalse", PyTuple_GET_SIZE(args), 2, 2)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 2, 2)) { goto exit; } func = PyTuple_GET_ITEM(args, 0); @@ -1086,4 +1086,4 @@ zip_longest_next(PyObject *self) return return_value; } -/*[clinic end generated code: output=4b55088ac24582b7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c60b17786144ab31 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/selectmodule.c.h b/Modules/clinic/selectmodule.c.h index c1c8ad40e724f5..743d2f3c73d9dd 100644 --- a/Modules/clinic/selectmodule.c.h +++ b/Modules/clinic/selectmodule.c.h @@ -1149,11 +1149,11 @@ select_kqueue(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyTypeObject *base_tp = _selectstate_by_type(type)->kqueue_queue_Type; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoPositional("kqueue", args)) { + !_PyArg_NoPositionalStack(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args))) { goto exit; } if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("kqueue", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } return_value = select_kqueue_impl(type); @@ -1400,4 +1400,4 @@ select_kqueue_control(PyObject *self, PyObject *const *args, Py_ssize_t nargs) #ifndef SELECT_KQUEUE_CONTROL_METHODDEF #define SELECT_KQUEUE_CONTROL_METHODDEF #endif /* !defined(SELECT_KQUEUE_CONTROL_METHODDEF) */ -/*[clinic end generated code: output=a1ac666294fd14bd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e1883916be3e7127 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/classobject.c.h b/Objects/clinic/classobject.c.h index 5934f1c2a41669..fa62e88d697028 100644 --- a/Objects/clinic/classobject.c.h +++ b/Objects/clinic/classobject.c.h @@ -39,10 +39,10 @@ method_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *instance; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("method", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("method", PyTuple_GET_SIZE(args), 2, 2)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 2, 2)) { goto exit; } function = PyTuple_GET_ITEM(args, 0); @@ -70,10 +70,10 @@ instancemethod_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *function; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("instancemethod", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("instancemethod", PyTuple_GET_SIZE(args), 1, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 1, 1)) { goto exit; } function = PyTuple_GET_ITEM(args, 0); @@ -82,4 +82,4 @@ instancemethod_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=ab546abf90aac94e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3a9a7cb0e1c14f7f input=a9049054013a1b77]*/ diff --git a/Objects/clinic/codeobject.c.h b/Objects/clinic/codeobject.c.h index 88333e9d3363eb..19ade00c6b225e 100644 --- a/Objects/clinic/codeobject.c.h +++ b/Objects/clinic/codeobject.c.h @@ -51,10 +51,10 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *cellvars = NULL; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("code", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("code", PyTuple_GET_SIZE(args), 16, 18)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 16, 18)) { goto exit; } argcount = PyLong_AsInt(PyTuple_GET_ITEM(args, 0)); @@ -471,4 +471,4 @@ code__varname_from_oparg(PyObject *self, PyObject *const *args, Py_ssize_t nargs exit: return return_value; } -/*[clinic end generated code: output=5c22e29e430401b4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=44dbdb061a019754 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/enumobject.c.h b/Objects/clinic/enumobject.c.h index 9b8a25a60b571e..44ea50d92ddc86 100644 --- a/Objects/clinic/enumobject.c.h +++ b/Objects/clinic/enumobject.c.h @@ -136,10 +136,10 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *seq; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("reversed", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("reversed", PyTuple_GET_SIZE(args), 1, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 1, 1)) { goto exit; } seq = PyTuple_GET_ITEM(args, 0); @@ -164,7 +164,7 @@ reversed_vectorcall(PyObject *type, PyObject *const *args, if (!_PyArg_NoKwnames("reversed", kwnames)) { goto exit; } - if (!_PyArg_CheckPositional("reversed", nargs, 1, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), nargs, 1, 1)) { goto exit; } seq = args[0]; @@ -173,4 +173,4 @@ reversed_vectorcall(PyObject *type, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=b97e8b89ca97ba64 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b9227ab338450a2d input=a9049054013a1b77]*/ diff --git a/Objects/clinic/floatobject.c.h b/Objects/clinic/floatobject.c.h index 9c71663a1503ac..c5acf43d965bfc 100644 --- a/Objects/clinic/floatobject.c.h +++ b/Objects/clinic/floatobject.c.h @@ -224,10 +224,10 @@ float_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *x = NULL; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("float", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("float", PyTuple_GET_SIZE(args), 0, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 0, 1)) { goto exit; } if (PyTuple_GET_SIZE(args) < 1) { @@ -256,7 +256,7 @@ float_vectorcall(PyObject *type, PyObject *const *args, if (!_PyArg_NoKwnames("float", kwnames)) { goto exit; } - if (!_PyArg_CheckPositional("float", nargs, 0, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), nargs, 0, 1)) { goto exit; } if (nargs < 1) { @@ -378,4 +378,4 @@ float___format__(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=d1198594a76a4638 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c5511b44a220dbd0 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/namespaceobject.c.h b/Objects/clinic/namespaceobject.c.h index cdd9ef586c79ec..ea3a52ed9beabf 100644 --- a/Objects/clinic/namespaceobject.c.h +++ b/Objects/clinic/namespaceobject.c.h @@ -2,7 +2,7 @@ preserve [clinic start generated code]*/ -#include "pycore_modsupport.h" // _PyArg_NoPositional() +#include "pycore_modsupport.h" // _PyArg_NoPositionalStack() PyDoc_STRVAR(namespace___replace____doc__, "__replace__($self, /, **changes)\n" @@ -22,7 +22,7 @@ namespace___replace__(PyObject *self, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; PyObject *changes = NULL; - if (!_PyArg_NoPositional("__replace__", args)) { + if (!_PyArg_NoPositionalStack("__replace__", PyTuple_GET_SIZE(args))) { goto exit; } if (kwargs == NULL) { @@ -42,4 +42,4 @@ namespace___replace__(PyObject *self, PyObject *args, PyObject *kwargs) return return_value; } -/*[clinic end generated code: output=67b5fcb6a6aee559 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=400d63b6be3c43d7 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/structseq.c.h b/Objects/clinic/structseq.c.h index f115f8ddcf490c..c5db48f2ef5031 100644 --- a/Objects/clinic/structseq.c.h +++ b/Objects/clinic/structseq.c.h @@ -84,7 +84,7 @@ structseq___replace__(PyObject *self, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; PyObject *changes = NULL; - if (!_PyArg_NoPositional("__replace__", args)) { + if (!_PyArg_NoPositionalStack("__replace__", PyTuple_GET_SIZE(args))) { goto exit; } if (kwargs == NULL) { @@ -104,4 +104,4 @@ structseq___replace__(PyObject *self, PyObject *args, PyObject *kwargs) return return_value; } -/*[clinic end generated code: output=18fcf88e5df26774 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e9b5cfc2dde26993 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/tupleobject.c.h b/Objects/clinic/tupleobject.c.h index 9d6a3edf60bb24..491f8d16179d48 100644 --- a/Objects/clinic/tupleobject.c.h +++ b/Objects/clinic/tupleobject.c.h @@ -94,10 +94,10 @@ tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *iterable = NULL; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("tuple", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("tuple", PyTuple_GET_SIZE(args), 0, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 0, 1)) { goto exit; } if (PyTuple_GET_SIZE(args) < 1) { @@ -126,7 +126,7 @@ tuple_vectorcall(PyObject *type, PyObject *const *args, if (!_PyArg_NoKwnames("tuple", kwnames)) { goto exit; } - if (!_PyArg_CheckPositional("tuple", nargs, 0, 1)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), nargs, 0, 1)) { goto exit; } if (nargs < 1) { @@ -156,4 +156,4 @@ tuple___getnewargs__(PyObject *self, PyObject *Py_UNUSED(ignored)) { return tuple___getnewargs___impl((PyTupleObject *)self); } -/*[clinic end generated code: output=1bc2bfc233992933 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ecab99656007f6b2 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/weakrefobject.c.h b/Objects/clinic/weakrefobject.c.h index b014b14217c96c..d809042e8ccd37 100644 --- a/Objects/clinic/weakrefobject.c.h +++ b/Objects/clinic/weakrefobject.c.h @@ -43,10 +43,10 @@ weakref_ref_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *callback = NULL; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("ReferenceType", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } - if (!_PyArg_CheckPositional("ReferenceType", PyTuple_GET_SIZE(args), 1, 2)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args), 1, 2)) { goto exit; } object = PyTuple_GET_ITEM(args, 0); @@ -77,7 +77,7 @@ weakref_ref_vectorcall(PyObject *type, PyObject *const *args, if (!_PyArg_NoKwnames("ReferenceType", kwnames)) { goto exit; } - if (!_PyArg_CheckPositional("ReferenceType", nargs, 1, 2)) { + if (!_PyArg_CheckPositional(_PyType_Name(_PyType_CAST(type)), nargs, 1, 2)) { goto exit; } object = args[0]; @@ -123,4 +123,4 @@ weakref_ref_init(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=774282aa1017bab5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f783886de559e8b3 input=a9049054013a1b77]*/ diff --git a/Python/clinic/instruction_sequence.c.h b/Python/clinic/instruction_sequence.c.h index f780627bae6ed8..29fb889b376013 100644 --- a/Python/clinic/instruction_sequence.c.h +++ b/Python/clinic/instruction_sequence.c.h @@ -24,11 +24,11 @@ inst_seq_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyTypeObject *base_tp = &_PyInstructionSequence_Type; if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoPositional("InstructionSequenceType", args)) { + !_PyArg_NoPositionalStack(_PyType_Name(_PyType_CAST(type)), PyTuple_GET_SIZE(args))) { goto exit; } if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("InstructionSequenceType", kwargs)) { + !_PyArg_NoKeywords(_PyType_Name(_PyType_CAST(type)), kwargs)) { goto exit; } return_value = inst_seq_new_impl(type); @@ -310,4 +310,4 @@ InstructionSequenceType_get_instructions(PyObject *self, PyObject *Py_UNUSED(ign { return InstructionSequenceType_get_instructions_impl((_PyInstructionSequence *)self); } -/*[clinic end generated code: output=c80501a59a1a1103 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=fe6c75d705dd0d40 input=a9049054013a1b77]*/ diff --git a/Tools/clinic/libclinic/clanguage.py b/Tools/clinic/libclinic/clanguage.py index f8ab2fd2515461..737bff01c9c387 100644 --- a/Tools/clinic/libclinic/clanguage.py +++ b/Tools/clinic/libclinic/clanguage.py @@ -391,6 +391,7 @@ def render_function( full_name = f.full_name template_dict = {'full_name': full_name} template_dict['name'] = f.displayname + template_dict['error_name'] = f'"{f.displayname}"' if f.kind in ACCESSORS: # The accessors of the same attribute are rendered into a single # PyGetSetDef entry, which is identified by the Python name. diff --git a/Tools/clinic/libclinic/converters.py b/Tools/clinic/libclinic/converters.py index c54dab302b6658..69eedf60f6f670 100644 --- a/Tools/clinic/libclinic/converters.py +++ b/Tools/clinic/libclinic/converters.py @@ -1314,6 +1314,9 @@ def set_template_dict(self, template_dict: TemplateDict) -> None: type_check = ( '({0} == base_tp || {0}->tp_init == base_tp->tp_init)' ).format(self.name) + # tp_new is inherited: name the type actually called. + template_dict['error_name'] = ( + f'_PyType_Name(_PyType_CAST({self.name}))') else: type_check = ('(Py_IS_TYPE({0}, base_tp) ||\n ' ' Py_TYPE({0})->tp_new == base_tp->tp_new)' diff --git a/Tools/clinic/libclinic/parse_args.py b/Tools/clinic/libclinic/parse_args.py index 703fa4e94ad5bf..d8664d6931d304 100644 --- a/Tools/clinic/libclinic/parse_args.py +++ b/Tools/clinic/libclinic/parse_args.py @@ -952,7 +952,7 @@ def _check_positional(self, nargs: str, *, self.codegen.add_include('pycore_modsupport.h', '_PyArg_CheckPositional()') return [libclinic.normalize_snippet(f""" - if (!_PyArg_CheckPositional("{{name}}", {nargs}, {self.min_pos}, {max_args})) {{{{ + if (!_PyArg_CheckPositional({{error_name}}, {nargs}, {self.min_pos}, {max_args})) {{{{ goto exit; }}}} """, indent=indent)] @@ -1119,9 +1119,9 @@ def parse_var_keyword(self) -> None: parser_code = [] if self.varpos is None and self.min_pos == self.max_pos == 0: self.codegen.add_include('pycore_modsupport.h', - '_PyArg_NoPositional()') + '_PyArg_NoPositionalStack()') parser_code.append(libclinic.normalize_snippet(""" - if (!_PyArg_NoPositional("{name}", args)) {{ + if (!_PyArg_NoPositionalStack({error_name}, PyTuple_GET_SIZE(args))) {{ goto exit; }} """, indent=4)) @@ -1492,15 +1492,15 @@ def _new_or_init_parser_body(self) -> None: self.codegen.add_include('pycore_modsupport.h', '_PyArg_NoKeywords()') fields.insert(0, libclinic.normalize_snippet(""" - if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs)) {{ + if ({self_type_check}!_PyArg_NoKeywords({error_name}, kwargs)) {{ goto exit; }} """, indent=4)) if not parses_positional: self.codegen.add_include('pycore_modsupport.h', - '_PyArg_NoPositional()') + '_PyArg_NoPositionalStack()') fields.insert(0, libclinic.normalize_snippet(""" - if ({self_type_check}!_PyArg_NoPositional("{name}", args)) {{ + if ({self_type_check}!_PyArg_NoPositionalStack({error_name}, PyTuple_GET_SIZE(args))) {{ goto exit; }} """, indent=4))