From 803f99141076f338d81d53775d1d7a828e65048a Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 8 Aug 2023 11:25:36 +0200 Subject: [PATCH 1/9] gh-95065: Argument Clinic: Add functional tests of deprecated positionals Move the "deprecated positinal" tests from clinic.test.c to _testclinic.c. Mock PY_VERSION_HEX in order to prevent the generated compiler warnings/errors to trigger. Put clinic code for deprecated positionals in Modules/clinic/_testclinic_depr_star.c.h for easy inspection of the generated code. --- Lib/test/clinic.test.c | 963 ----------------------- Lib/test/test_clinic.py | 145 ++++ Modules/_testclinic.c | 197 +++++ Modules/clinic/_testclinic_depr_star.c.h | 858 ++++++++++++++++++++ 4 files changed, 1200 insertions(+), 963 deletions(-) create mode 100644 Modules/clinic/_testclinic_depr_star.c.h diff --git a/Lib/test/clinic.test.c b/Lib/test/clinic.test.c index 386d1dac3f115e..ea96bf6766bfb1 100644 --- a/Lib/test/clinic.test.c +++ b/Lib/test/clinic.test.c @@ -5465,966 +5465,3 @@ docstr_fallback_to_converter_default(PyObject *module, PyObject *const *args, Py static PyObject * docstr_fallback_to_converter_default_impl(PyObject *module, str a) /*[clinic end generated code: output=ae24a9c6f60ee8a6 input=0cbe6a4d24bc2274]*/ - - -/*[clinic input] -test_deprecate_positional_pos1_len1_optional - a: object - * [from 3.14] - b: object = None -[clinic start generated code]*/ - -PyDoc_STRVAR(test_deprecate_positional_pos1_len1_optional__doc__, -"test_deprecate_positional_pos1_len1_optional($module, /, a, b=None)\n" -"--\n" -"\n" -"Note: Passing 2 positional arguments to\n" -"test_deprecate_positional_pos1_len1_optional() is deprecated.\n" -"Parameter \'b\' will become a keyword-only parameter in Python 3.14.\n" -""); - -#define TEST_DEPRECATE_POSITIONAL_POS1_LEN1_OPTIONAL_METHODDEF \ - {"test_deprecate_positional_pos1_len1_optional", _PyCFunction_CAST(test_deprecate_positional_pos1_len1_optional), METH_FASTCALL|METH_KEYWORDS, test_deprecate_positional_pos1_len1_optional__doc__}, - -static PyObject * -test_deprecate_positional_pos1_len1_optional_impl(PyObject *module, - PyObject *a, PyObject *b); - -static PyObject * -test_deprecate_positional_pos1_len1_optional(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(a), &_Py_ID(b), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"a", "b", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "test_deprecate_positional_pos1_len1_optional", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - PyObject *a; - PyObject *b = Py_None; - - #if PY_VERSION_HEX >= 0x030e00C0 - # error \ - "In clinic.test.c, update parameter(s) 'b' in the clinic input of" \ - " 'test_deprecate_positional_pos1_len1_optional' to be " \ - "keyword-only." - #elif PY_VERSION_HEX >= 0x030e00A0 - # ifdef _MSC_VER - # pragma message ( \ - "In clinic.test.c, update parameter(s) 'b' in the clinic input of" \ - " 'test_deprecate_positional_pos1_len1_optional' to be " \ - "keyword-only.") - # else - # warning \ - "In clinic.test.c, update parameter(s) 'b' in the clinic input of" \ - " 'test_deprecate_positional_pos1_len1_optional' to be " \ - "keyword-only." - # endif - #endif - if (nargs == 2) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing 2 positional arguments to " - "test_deprecate_positional_pos1_len1_optional() is deprecated. " - "Parameter 'b' will become a keyword-only parameter in Python " - "3.14.", 1)) - { - goto exit; - } - } - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - a = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - b = args[1]; -skip_optional_pos: - return_value = test_deprecate_positional_pos1_len1_optional_impl(module, a, b); - -exit: - return return_value; -} - -static PyObject * -test_deprecate_positional_pos1_len1_optional_impl(PyObject *module, - PyObject *a, PyObject *b) -/*[clinic end generated code: output=6c0fd9d94fa1e765 input=89099f3dacd757da]*/ - - -/*[clinic input] -test_deprecate_positional_pos1_len1 - a: object - * [from 3.14] - b: object -[clinic start generated code]*/ - -PyDoc_STRVAR(test_deprecate_positional_pos1_len1__doc__, -"test_deprecate_positional_pos1_len1($module, /, a, b)\n" -"--\n" -"\n" -"Note: Passing 2 positional arguments to\n" -"test_deprecate_positional_pos1_len1() is deprecated. Parameter \'b\'\n" -"will become a keyword-only parameter in Python 3.14.\n" -""); - -#define TEST_DEPRECATE_POSITIONAL_POS1_LEN1_METHODDEF \ - {"test_deprecate_positional_pos1_len1", _PyCFunction_CAST(test_deprecate_positional_pos1_len1), METH_FASTCALL|METH_KEYWORDS, test_deprecate_positional_pos1_len1__doc__}, - -static PyObject * -test_deprecate_positional_pos1_len1_impl(PyObject *module, PyObject *a, - PyObject *b); - -static PyObject * -test_deprecate_positional_pos1_len1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(a), &_Py_ID(b), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"a", "b", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "test_deprecate_positional_pos1_len1", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - PyObject *a; - PyObject *b; - - #if PY_VERSION_HEX >= 0x030e00C0 - # error \ - "In clinic.test.c, update parameter(s) 'b' in the clinic input of" \ - " 'test_deprecate_positional_pos1_len1' to be keyword-only." - #elif PY_VERSION_HEX >= 0x030e00A0 - # ifdef _MSC_VER - # pragma message ( \ - "In clinic.test.c, update parameter(s) 'b' in the clinic input of" \ - " 'test_deprecate_positional_pos1_len1' to be keyword-only.") - # else - # warning \ - "In clinic.test.c, update parameter(s) 'b' in the clinic input of" \ - " 'test_deprecate_positional_pos1_len1' to be keyword-only." - # endif - #endif - if (nargs == 2) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing 2 positional arguments to " - "test_deprecate_positional_pos1_len1() is deprecated. Parameter " - "'b' will become a keyword-only parameter in Python 3.14.", 1)) - { - goto exit; - } - } - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - a = args[0]; - b = args[1]; - return_value = test_deprecate_positional_pos1_len1_impl(module, a, b); - -exit: - return return_value; -} - -static PyObject * -test_deprecate_positional_pos1_len1_impl(PyObject *module, PyObject *a, - PyObject *b) -/*[clinic end generated code: output=22821a0fa9945d0c input=1702bbab1e9b3b99]*/ - - -/*[clinic input] -test_deprecate_positional_pos1_len2_with_kwd - a: object - * [from 3.14] - b: object - c: object - * - d: object -[clinic start generated code]*/ - -PyDoc_STRVAR(test_deprecate_positional_pos1_len2_with_kwd__doc__, -"test_deprecate_positional_pos1_len2_with_kwd($module, /, a, b, c, *, d)\n" -"--\n" -"\n" -"Note: Passing more than 1 positional argument to\n" -"test_deprecate_positional_pos1_len2_with_kwd() is deprecated.\n" -"Parameters \'b\' and \'c\' will become keyword-only parameters in Python\n" -"3.14.\n" -""); - -#define TEST_DEPRECATE_POSITIONAL_POS1_LEN2_WITH_KWD_METHODDEF \ - {"test_deprecate_positional_pos1_len2_with_kwd", _PyCFunction_CAST(test_deprecate_positional_pos1_len2_with_kwd), METH_FASTCALL|METH_KEYWORDS, test_deprecate_positional_pos1_len2_with_kwd__doc__}, - -static PyObject * -test_deprecate_positional_pos1_len2_with_kwd_impl(PyObject *module, - PyObject *a, PyObject *b, - PyObject *c, PyObject *d); - -static PyObject * -test_deprecate_positional_pos1_len2_with_kwd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"a", "b", "c", "d", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "test_deprecate_positional_pos1_len2_with_kwd", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - PyObject *a; - PyObject *b; - PyObject *c; - PyObject *d; - - #if PY_VERSION_HEX >= 0x030e00C0 - # error \ - "In clinic.test.c, update parameter(s) 'b' and 'c' in the clinic " \ - "input of 'test_deprecate_positional_pos1_len2_with_kwd' to be " \ - "keyword-only." - #elif PY_VERSION_HEX >= 0x030e00A0 - # ifdef _MSC_VER - # pragma message ( \ - "In clinic.test.c, update parameter(s) 'b' and 'c' in the clinic " \ - "input of 'test_deprecate_positional_pos1_len2_with_kwd' to be " \ - "keyword-only.") - # else - # warning \ - "In clinic.test.c, update parameter(s) 'b' and 'c' in the clinic " \ - "input of 'test_deprecate_positional_pos1_len2_with_kwd' to be " \ - "keyword-only." - # endif - #endif - if (nargs > 1 && nargs <= 3) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing more than 1 positional argument to " - "test_deprecate_positional_pos1_len2_with_kwd() is deprecated. " - "Parameters 'b' and 'c' will become keyword-only parameters in " - "Python 3.14.", 1)) - { - goto exit; - } - } - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 1, argsbuf); - if (!args) { - goto exit; - } - a = args[0]; - b = args[1]; - c = args[2]; - d = args[3]; - return_value = test_deprecate_positional_pos1_len2_with_kwd_impl(module, a, b, c, d); - -exit: - return return_value; -} - -static PyObject * -test_deprecate_positional_pos1_len2_with_kwd_impl(PyObject *module, - PyObject *a, PyObject *b, - PyObject *c, PyObject *d) -/*[clinic end generated code: output=061d554ccc6b8f51 input=28cdb885f6c34eab]*/ - - -/*[clinic input] -test_deprecate_positional_pos0_len1 - * [from 3.14] - a: object -[clinic start generated code]*/ - -PyDoc_STRVAR(test_deprecate_positional_pos0_len1__doc__, -"test_deprecate_positional_pos0_len1($module, /, a)\n" -"--\n" -"\n" -"Note: Passing positional arguments to\n" -"test_deprecate_positional_pos0_len1() is deprecated. Parameter \'a\'\n" -"will become a keyword-only parameter in Python 3.14.\n" -""); - -#define TEST_DEPRECATE_POSITIONAL_POS0_LEN1_METHODDEF \ - {"test_deprecate_positional_pos0_len1", _PyCFunction_CAST(test_deprecate_positional_pos0_len1), METH_FASTCALL|METH_KEYWORDS, test_deprecate_positional_pos0_len1__doc__}, - -static PyObject * -test_deprecate_positional_pos0_len1_impl(PyObject *module, PyObject *a); - -static PyObject * -test_deprecate_positional_pos0_len1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(a), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"a", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "test_deprecate_positional_pos0_len1", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *a; - - #if PY_VERSION_HEX >= 0x030e00C0 - # error \ - "In clinic.test.c, update parameter(s) 'a' in the clinic input of" \ - " 'test_deprecate_positional_pos0_len1' to be keyword-only." - #elif PY_VERSION_HEX >= 0x030e00A0 - # ifdef _MSC_VER - # pragma message ( \ - "In clinic.test.c, update parameter(s) 'a' in the clinic input of" \ - " 'test_deprecate_positional_pos0_len1' to be keyword-only.") - # else - # warning \ - "In clinic.test.c, update parameter(s) 'a' in the clinic input of" \ - " 'test_deprecate_positional_pos0_len1' to be keyword-only." - # endif - #endif - if (nargs == 1) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing positional arguments to " - "test_deprecate_positional_pos0_len1() is deprecated. Parameter " - "'a' will become a keyword-only parameter in Python 3.14.", 1)) - { - goto exit; - } - } - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - a = args[0]; - return_value = test_deprecate_positional_pos0_len1_impl(module, a); - -exit: - return return_value; -} - -static PyObject * -test_deprecate_positional_pos0_len1_impl(PyObject *module, PyObject *a) -/*[clinic end generated code: output=3e512117a5eda970 input=678206db25c0652c]*/ - - -/*[clinic input] -test_deprecate_positional_pos0_len2 - * [from 3.14] - a: object - b: object -[clinic start generated code]*/ - -PyDoc_STRVAR(test_deprecate_positional_pos0_len2__doc__, -"test_deprecate_positional_pos0_len2($module, /, a, b)\n" -"--\n" -"\n" -"Note: Passing positional arguments to\n" -"test_deprecate_positional_pos0_len2() is deprecated. Parameters \'a\'\n" -"and \'b\' will become keyword-only parameters in Python 3.14.\n" -""); - -#define TEST_DEPRECATE_POSITIONAL_POS0_LEN2_METHODDEF \ - {"test_deprecate_positional_pos0_len2", _PyCFunction_CAST(test_deprecate_positional_pos0_len2), METH_FASTCALL|METH_KEYWORDS, test_deprecate_positional_pos0_len2__doc__}, - -static PyObject * -test_deprecate_positional_pos0_len2_impl(PyObject *module, PyObject *a, - PyObject *b); - -static PyObject * -test_deprecate_positional_pos0_len2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(a), &_Py_ID(b), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"a", "b", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "test_deprecate_positional_pos0_len2", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - PyObject *a; - PyObject *b; - - #if PY_VERSION_HEX >= 0x030e00C0 - # error \ - "In clinic.test.c, update parameter(s) 'a' and 'b' in the clinic " \ - "input of 'test_deprecate_positional_pos0_len2' to be " \ - "keyword-only." - #elif PY_VERSION_HEX >= 0x030e00A0 - # ifdef _MSC_VER - # pragma message ( \ - "In clinic.test.c, update parameter(s) 'a' and 'b' in the clinic " \ - "input of 'test_deprecate_positional_pos0_len2' to be " \ - "keyword-only.") - # else - # warning \ - "In clinic.test.c, update parameter(s) 'a' and 'b' in the clinic " \ - "input of 'test_deprecate_positional_pos0_len2' to be " \ - "keyword-only." - # endif - #endif - if (nargs > 0 && nargs <= 2) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing positional arguments to " - "test_deprecate_positional_pos0_len2() is deprecated. Parameters " - "'a' and 'b' will become keyword-only parameters in Python 3.14.", 1)) - { - goto exit; - } - } - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - a = args[0]; - b = args[1]; - return_value = test_deprecate_positional_pos0_len2_impl(module, a, b); - -exit: - return return_value; -} - -static PyObject * -test_deprecate_positional_pos0_len2_impl(PyObject *module, PyObject *a, - PyObject *b) -/*[clinic end generated code: output=d41da050a5b82dd0 input=fae0d0b1d480c939]*/ - - -/*[clinic input] -test_deprecate_positional_pos0_len3_with_kwdonly - * [from 3.14] - a: object - b: object - c: object - * - e: object -[clinic start generated code]*/ - -PyDoc_STRVAR(test_deprecate_positional_pos0_len3_with_kwdonly__doc__, -"test_deprecate_positional_pos0_len3_with_kwdonly($module, /, a, b, c,\n" -" *, e)\n" -"--\n" -"\n" -"Note: Passing positional arguments to\n" -"test_deprecate_positional_pos0_len3_with_kwdonly() is deprecated.\n" -"Parameters \'a\', \'b\' and \'c\' will become keyword-only parameters in\n" -"Python 3.14.\n" -""); - -#define TEST_DEPRECATE_POSITIONAL_POS0_LEN3_WITH_KWDONLY_METHODDEF \ - {"test_deprecate_positional_pos0_len3_with_kwdonly", _PyCFunction_CAST(test_deprecate_positional_pos0_len3_with_kwdonly), METH_FASTCALL|METH_KEYWORDS, test_deprecate_positional_pos0_len3_with_kwdonly__doc__}, - -static PyObject * -test_deprecate_positional_pos0_len3_with_kwdonly_impl(PyObject *module, - PyObject *a, - PyObject *b, - PyObject *c, - PyObject *e); - -static PyObject * -test_deprecate_positional_pos0_len3_with_kwdonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(e), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"a", "b", "c", "e", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "test_deprecate_positional_pos0_len3_with_kwdonly", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - PyObject *a; - PyObject *b; - PyObject *c; - PyObject *e; - - #if PY_VERSION_HEX >= 0x030e00C0 - # error \ - "In clinic.test.c, update parameter(s) 'a', 'b' and 'c' in the " \ - "clinic input of " \ - "'test_deprecate_positional_pos0_len3_with_kwdonly' to be " \ - "keyword-only." - #elif PY_VERSION_HEX >= 0x030e00A0 - # ifdef _MSC_VER - # pragma message ( \ - "In clinic.test.c, update parameter(s) 'a', 'b' and 'c' in the " \ - "clinic input of " \ - "'test_deprecate_positional_pos0_len3_with_kwdonly' to be " \ - "keyword-only.") - # else - # warning \ - "In clinic.test.c, update parameter(s) 'a', 'b' and 'c' in the " \ - "clinic input of " \ - "'test_deprecate_positional_pos0_len3_with_kwdonly' to be " \ - "keyword-only." - # endif - #endif - if (nargs > 0 && nargs <= 3) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing positional arguments to " - "test_deprecate_positional_pos0_len3_with_kwdonly() is " - "deprecated. Parameters 'a', 'b' and 'c' will become keyword-only" - " parameters in Python 3.14.", 1)) - { - goto exit; - } - } - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 1, argsbuf); - if (!args) { - goto exit; - } - a = args[0]; - b = args[1]; - c = args[2]; - e = args[3]; - return_value = test_deprecate_positional_pos0_len3_with_kwdonly_impl(module, a, b, c, e); - -exit: - return return_value; -} - -static PyObject * -test_deprecate_positional_pos0_len3_with_kwdonly_impl(PyObject *module, - PyObject *a, - PyObject *b, - PyObject *c, - PyObject *e) -/*[clinic end generated code: output=c5d7ddfc139ddf31 input=1b0121770c0c52e0]*/ - - -/*[clinic input] -test_deprecate_positional_pos2_len1 - a: object - b: object - * [from 3.14] - c: object -[clinic start generated code]*/ - -PyDoc_STRVAR(test_deprecate_positional_pos2_len1__doc__, -"test_deprecate_positional_pos2_len1($module, /, a, b, c)\n" -"--\n" -"\n" -"Note: Passing 3 positional arguments to\n" -"test_deprecate_positional_pos2_len1() is deprecated. Parameter \'c\'\n" -"will become a keyword-only parameter in Python 3.14.\n" -""); - -#define TEST_DEPRECATE_POSITIONAL_POS2_LEN1_METHODDEF \ - {"test_deprecate_positional_pos2_len1", _PyCFunction_CAST(test_deprecate_positional_pos2_len1), METH_FASTCALL|METH_KEYWORDS, test_deprecate_positional_pos2_len1__doc__}, - -static PyObject * -test_deprecate_positional_pos2_len1_impl(PyObject *module, PyObject *a, - PyObject *b, PyObject *c); - -static PyObject * -test_deprecate_positional_pos2_len1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"a", "b", "c", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "test_deprecate_positional_pos2_len1", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - PyObject *a; - PyObject *b; - PyObject *c; - - #if PY_VERSION_HEX >= 0x030e00C0 - # error \ - "In clinic.test.c, update parameter(s) 'c' in the clinic input of" \ - " 'test_deprecate_positional_pos2_len1' to be keyword-only." - #elif PY_VERSION_HEX >= 0x030e00A0 - # ifdef _MSC_VER - # pragma message ( \ - "In clinic.test.c, update parameter(s) 'c' in the clinic input of" \ - " 'test_deprecate_positional_pos2_len1' to be keyword-only.") - # else - # warning \ - "In clinic.test.c, update parameter(s) 'c' in the clinic input of" \ - " 'test_deprecate_positional_pos2_len1' to be keyword-only." - # endif - #endif - if (nargs == 3) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing 3 positional arguments to " - "test_deprecate_positional_pos2_len1() is deprecated. Parameter " - "'c' will become a keyword-only parameter in Python 3.14.", 1)) - { - goto exit; - } - } - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - a = args[0]; - b = args[1]; - c = args[2]; - return_value = test_deprecate_positional_pos2_len1_impl(module, a, b, c); - -exit: - return return_value; -} - -static PyObject * -test_deprecate_positional_pos2_len1_impl(PyObject *module, PyObject *a, - PyObject *b, PyObject *c) -/*[clinic end generated code: output=d80609e6b37ffb8a input=e1d129689e69ec7c]*/ - - -/*[clinic input] -test_deprecate_positional_pos2_len2 - a: object - b: object - * [from 3.14] - c: object - d: object -[clinic start generated code]*/ - -PyDoc_STRVAR(test_deprecate_positional_pos2_len2__doc__, -"test_deprecate_positional_pos2_len2($module, /, a, b, c, d)\n" -"--\n" -"\n" -"Note: Passing more than 2 positional arguments to\n" -"test_deprecate_positional_pos2_len2() is deprecated. Parameters \'c\'\n" -"and \'d\' will become keyword-only parameters in Python 3.14.\n" -""); - -#define TEST_DEPRECATE_POSITIONAL_POS2_LEN2_METHODDEF \ - {"test_deprecate_positional_pos2_len2", _PyCFunction_CAST(test_deprecate_positional_pos2_len2), METH_FASTCALL|METH_KEYWORDS, test_deprecate_positional_pos2_len2__doc__}, - -static PyObject * -test_deprecate_positional_pos2_len2_impl(PyObject *module, PyObject *a, - PyObject *b, PyObject *c, - PyObject *d); - -static PyObject * -test_deprecate_positional_pos2_len2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"a", "b", "c", "d", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "test_deprecate_positional_pos2_len2", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - PyObject *a; - PyObject *b; - PyObject *c; - PyObject *d; - - #if PY_VERSION_HEX >= 0x030e00C0 - # error \ - "In clinic.test.c, update parameter(s) 'c' and 'd' in the clinic " \ - "input of 'test_deprecate_positional_pos2_len2' to be " \ - "keyword-only." - #elif PY_VERSION_HEX >= 0x030e00A0 - # ifdef _MSC_VER - # pragma message ( \ - "In clinic.test.c, update parameter(s) 'c' and 'd' in the clinic " \ - "input of 'test_deprecate_positional_pos2_len2' to be " \ - "keyword-only.") - # else - # warning \ - "In clinic.test.c, update parameter(s) 'c' and 'd' in the clinic " \ - "input of 'test_deprecate_positional_pos2_len2' to be " \ - "keyword-only." - # endif - #endif - if (nargs > 2 && nargs <= 4) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing more than 2 positional arguments to " - "test_deprecate_positional_pos2_len2() is deprecated. Parameters " - "'c' and 'd' will become keyword-only parameters in Python 3.14.", 1)) - { - goto exit; - } - } - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 4, 0, argsbuf); - if (!args) { - goto exit; - } - a = args[0]; - b = args[1]; - c = args[2]; - d = args[3]; - return_value = test_deprecate_positional_pos2_len2_impl(module, a, b, c, d); - -exit: - return return_value; -} - -static PyObject * -test_deprecate_positional_pos2_len2_impl(PyObject *module, PyObject *a, - PyObject *b, PyObject *c, - PyObject *d) -/*[clinic end generated code: output=1c10d6197562319f input=0d53533463a12792]*/ - - -/*[clinic input] -test_deprecate_positional_pos2_len3_with_kwdonly - a: object - b: object - * [from 3.14] - c: object - d: object - * - e: object -[clinic start generated code]*/ - -PyDoc_STRVAR(test_deprecate_positional_pos2_len3_with_kwdonly__doc__, -"test_deprecate_positional_pos2_len3_with_kwdonly($module, /, a, b, c,\n" -" d, *, e)\n" -"--\n" -"\n" -"Note: Passing more than 2 positional arguments to\n" -"test_deprecate_positional_pos2_len3_with_kwdonly() is deprecated.\n" -"Parameters \'c\' and \'d\' will become keyword-only parameters in Python\n" -"3.14.\n" -""); - -#define TEST_DEPRECATE_POSITIONAL_POS2_LEN3_WITH_KWDONLY_METHODDEF \ - {"test_deprecate_positional_pos2_len3_with_kwdonly", _PyCFunction_CAST(test_deprecate_positional_pos2_len3_with_kwdonly), METH_FASTCALL|METH_KEYWORDS, test_deprecate_positional_pos2_len3_with_kwdonly__doc__}, - -static PyObject * -test_deprecate_positional_pos2_len3_with_kwdonly_impl(PyObject *module, - PyObject *a, - PyObject *b, - PyObject *c, - PyObject *d, - PyObject *e); - -static PyObject * -test_deprecate_positional_pos2_len3_with_kwdonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), &_Py_ID(e), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"a", "b", "c", "d", "e", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "test_deprecate_positional_pos2_len3_with_kwdonly", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - PyObject *a; - PyObject *b; - PyObject *c; - PyObject *d; - PyObject *e; - - #if PY_VERSION_HEX >= 0x030e00C0 - # error \ - "In clinic.test.c, update parameter(s) 'c' and 'd' in the clinic " \ - "input of 'test_deprecate_positional_pos2_len3_with_kwdonly' to " \ - "be keyword-only." - #elif PY_VERSION_HEX >= 0x030e00A0 - # ifdef _MSC_VER - # pragma message ( \ - "In clinic.test.c, update parameter(s) 'c' and 'd' in the clinic " \ - "input of 'test_deprecate_positional_pos2_len3_with_kwdonly' to " \ - "be keyword-only.") - # else - # warning \ - "In clinic.test.c, update parameter(s) 'c' and 'd' in the clinic " \ - "input of 'test_deprecate_positional_pos2_len3_with_kwdonly' to " \ - "be keyword-only." - # endif - #endif - if (nargs > 2 && nargs <= 4) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Passing more than 2 positional arguments to " - "test_deprecate_positional_pos2_len3_with_kwdonly() is " - "deprecated. Parameters 'c' and 'd' will become keyword-only " - "parameters in Python 3.14.", 1)) - { - goto exit; - } - } - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 4, 1, argsbuf); - if (!args) { - goto exit; - } - a = args[0]; - b = args[1]; - c = args[2]; - d = args[3]; - e = args[4]; - return_value = test_deprecate_positional_pos2_len3_with_kwdonly_impl(module, a, b, c, d, e); - -exit: - return return_value; -} - -static PyObject * -test_deprecate_positional_pos2_len3_with_kwdonly_impl(PyObject *module, - PyObject *a, - PyObject *b, - PyObject *c, - PyObject *d, - PyObject *e) -/*[clinic end generated code: output=d32375ffce63d3db input=154fd450448d8935]*/ diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index d13d8623f8093b..2940c478a93c77 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -2319,6 +2319,19 @@ class ClinicFunctionalTest(unittest.TestCase): locals().update((name, getattr(ac_tester, name)) for name in dir(ac_tester) if name.startswith('test_')) + def check_depr_star(self, fn, *, fname, pnames, ok_args, fail_args): + for args, kwds in ok_args: + fn(*args, **kwds) + regex = ( + f"Passing.*positional argument.*to {fname}.*is deprecated. " + f"Parameter.*{pnames} will become.*keyword-only parameter.*in Python 3.14" + ) + for args, kwds in fail_args: + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + fn(*args, **kwds) + self.assertTrue(cm.filename.endswith("test_clinic.py"), cm.filename) + fn(*args, **kwds) # No warning raised second time + def test_objects_converter(self): with self.assertRaises(TypeError): ac_tester.objects_converter() @@ -2783,6 +2796,138 @@ def test_cloned_func_with_converter_exception_message(self): func = getattr(ac_tester, name) self.assertEqual(func(), name) + def test_depr_star_pos0_len1(self): + fn = ac_tester.deprecate_positional_pos0_len1 + self.check_depr_star(fn, + fname="deprecate_positional_pos0_len1", + pnames="'a'", + ok_args=( + ((), {"a": None}), + ), + fail_args=( + ((None,), {}), + ) + ) + + def test_depr_star_pos0_len2(self): + fn = ac_tester.deprecate_positional_pos0_len2 + self.check_depr_star(fn, + fname="deprecate_positional_pos0_len2", + pnames="'a' and 'b'", + ok_args=( + ((), {"a": None, "b": None}), + ), + fail_args=( + ((None,), {"b": None}), + ) + ) + + def test_depr_star_pos0_len3_with_kwd(self): + fn = ac_tester.deprecate_positional_pos0_len3_with_kwd + self.check_depr_star(fn, + fname="deprecate_positional_pos0_len3_with_kwd", + pnames="'a', 'b' and 'c'", + ok_args=( + ((), {"a": None, "b": None, "c": None, "d": None}), + ), + fail_args=( + ((None,), {"b": None, "c": None, "d": None}), + ((None, None), {"c": None, "d": None}), + ((None, None, None), {"d": None}), + ) + ) + + def test_depr_star_pos1_len1_optional(self): + fn = ac_tester.deprecate_positional_pos1_len1_optional + self.check_depr_star(fn, + fname="deprecate_positional_pos1_len1_optional", + pnames="'b'", + ok_args=( + ((), {"a": None, "b": None}), + ((None,), {}), + ((None,), {"b": None}), + ), + fail_args=( + ((None, None), {}), + ) + ) + + def test_depr_star_pos1_len1(self): + fn = ac_tester.deprecate_positional_pos1_len1 + self.check_depr_star(fn, + fname="deprecate_positional_pos1_len1", + pnames="'b'", + ok_args=( + ((), {"a": None, "b": None}), + ((None,), {"b": None}), + ), + fail_args=( + ((None, None), {}), + ) + ) + + def test_depr_star_pos1_len2_with_kwd(self): + fn = ac_tester.deprecate_positional_pos1_len2_with_kwd + self.check_depr_star(fn, + fname="deprecate_positional_pos1_len2_with_kwd", + pnames="'b' and 'c'", + ok_args=( + ((), {"a": None, "b": None, "c": None, "d": None}), + ((None,), {"b": None, "c": None, "d": None}), + ), + fail_args=( + ((None, None), {"c": None, "d": None}), + ((None, None, None), {"d": None}), + ) + ) + + def test_depr_star_pos2_len1(self): + fn = ac_tester.deprecate_positional_pos2_len1 + self.check_depr_star(fn, + fname="deprecate_positional_pos2_len1", + pnames="'c'", + ok_args=( + ((), {"a": None, "b": None, "c": None}), + ((None,), {"b": None, "c": None}), + ((None, None), {"c": None}), + ), + fail_args=( + ((None, None, None), {}), + ) + ) + + def test_depr_star_pos2_len2(self): + fn = ac_tester.deprecate_positional_pos2_len2 + self.check_depr_star(fn, + fname="deprecate_positional_pos2_len2", + pnames="'c' and 'd'", + ok_args=( + ((), {"a": None, "b": None, "c": None, "d": None}), + ((None,), {"b": None, "c": None, "d": None}), + ((None, None), {"c": None, "d": None}), + ), + fail_args=( + ((None, None, None), {"d": None}), + ((None, None, None, None), {}), + ) + ) + + def test_depr_star_pos2_len3_with_kwd(self): + fn = ac_tester.deprecate_positional_pos2_len3_with_kwd + self.check_depr_star(fn, + fname="deprecate_positional_pos2_len3_with_kwd", + pnames="'c' and 'd'", + ok_args=( + ((), {"a": None, "b": None, "c": None, "d": None, "e": None}), + ((None,), {"b": None, "c": None, "d": None, "e": None}), + ((None, None), {"c": None, "d": None, "e": None}), + ), + fail_args=( + ((None, None, None), {"d": None, "e": None}), + ((None, None, None, None), {"e": None}), + ) + ) + class PermutationTests(unittest.TestCase): """Test permutation support functions.""" diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 8ba8f8ecadec7a..10f3d8f6a71240 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -1193,6 +1193,193 @@ clone_with_conv_f2_impl(PyObject *module, custom_t path) } +/*[clinic input] +output push +destination deprstar new file '{dirname}/clinic/_testclinic_depr_star.c.h' +output everything deprstar +output impl_definition block +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bc7f8fcde3a71485]*/ + + +// Mock Python version 3.8 +#define _SAVED_PY_VERSION PY_VERSION_HEX +#undef PY_VERSION_HEX +#define PY_VERSION_HEX 0x03080000 + + +#include "clinic/_testclinic_depr_star.c.h" + + +/*[clinic input] +deprecate_positional_pos0_len1 + * [from 3.14] + a: object +[clinic start generated code]*/ + +static PyObject * +deprecate_positional_pos0_len1_impl(PyObject *module, PyObject *a) +/*[clinic end generated code: output=d9108842c62d70f6 input=e4430c931ed3c0c9]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +deprecate_positional_pos0_len2 + * [from 3.14] + a: object + b: object +[clinic start generated code]*/ + +static PyObject * +deprecate_positional_pos0_len2_impl(PyObject *module, PyObject *a, + PyObject *b) +/*[clinic end generated code: output=555332d5ef96af2e input=e96ded10f82288b7]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +deprecate_positional_pos0_len3_with_kwd + * [from 3.14] + a: object + b: object + c: object + * + d: object +[clinic start generated code]*/ + +static PyObject * +deprecate_positional_pos0_len3_with_kwd_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, + PyObject *d) +/*[clinic end generated code: output=a37c65769a902cf9 input=b1339ff4e355e14d]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +deprecate_positional_pos1_len1_optional + a: object + * [from 3.14] + b: object = None +[clinic start generated code]*/ + +static PyObject * +deprecate_positional_pos1_len1_optional_impl(PyObject *module, PyObject *a, + PyObject *b) +/*[clinic end generated code: output=14f5720becfb664d input=1fc29f6adebceb7e]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +deprecate_positional_pos1_len1 + a: object + * [from 3.14] + b: object +[clinic start generated code]*/ + +static PyObject * +deprecate_positional_pos1_len1_impl(PyObject *module, PyObject *a, + PyObject *b) +/*[clinic end generated code: output=f59d6481bb9a76c0 input=c3f682707fa61515]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +deprecate_positional_pos1_len2_with_kwd + a: object + * [from 3.14] + b: object + c: object + * + d: object +[clinic start generated code]*/ + +static PyObject * +deprecate_positional_pos1_len2_with_kwd_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, + PyObject *d) +/*[clinic end generated code: output=19432d502b8f6574 input=9f0422971bc03495]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +deprecate_positional_pos2_len1 + a: object + b: object + * [from 3.14] + c: object +[clinic start generated code]*/ + +static PyObject * +deprecate_positional_pos2_len1_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c) +/*[clinic end generated code: output=a61f6e4bc2ef7759 input=2570ceea05b69ff3]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +deprecate_positional_pos2_len2 + a: object + b: object + * [from 3.14] + c: object + d: object +[clinic start generated code]*/ + +static PyObject * +deprecate_positional_pos2_len2_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, PyObject *d) +/*[clinic end generated code: output=0bf78b4d6a21ad5e input=6876773a37491125]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +deprecate_positional_pos2_len3_with_kwd + a: object + b: object + * [from 3.14] + c: object + d: object + * + e: object +[clinic start generated code]*/ + +static PyObject * +deprecate_positional_pos2_len3_with_kwd_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, + PyObject *d, PyObject *e) +/*[clinic end generated code: output=3893e0935eaa43a4 input=73f9e1a8fa3b6c54]*/ +{ + Py_RETURN_NONE; +} + + +// Reset PY_VERSION_HEX +#undef PY_VERSION_HEX +#define PY_VERSION_HEX _SAVED_PY_VERSION +#undef _SAVED_PY_VERSION + + +/*[clinic input] +output pop +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e7c7c42daced52b0]*/ + static PyMethodDef tester_methods[] = { TEST_EMPTY_FUNCTION_METHODDEF OBJECTS_CONVERTER_METHODDEF @@ -1248,6 +1435,16 @@ static PyMethodDef tester_methods[] = { CLONE_F2_METHODDEF CLONE_WITH_CONV_F1_METHODDEF CLONE_WITH_CONV_F2_METHODDEF + + DEPRECATE_POSITIONAL_POS0_LEN1_METHODDEF + DEPRECATE_POSITIONAL_POS0_LEN2_METHODDEF + DEPRECATE_POSITIONAL_POS0_LEN3_WITH_KWD_METHODDEF + DEPRECATE_POSITIONAL_POS1_LEN1_OPTIONAL_METHODDEF + DEPRECATE_POSITIONAL_POS1_LEN1_METHODDEF + DEPRECATE_POSITIONAL_POS1_LEN2_WITH_KWD_METHODDEF + DEPRECATE_POSITIONAL_POS2_LEN1_METHODDEF + DEPRECATE_POSITIONAL_POS2_LEN2_METHODDEF + DEPRECATE_POSITIONAL_POS2_LEN3_WITH_KWD_METHODDEF {NULL, NULL} }; diff --git a/Modules/clinic/_testclinic_depr_star.c.h b/Modules/clinic/_testclinic_depr_star.c.h new file mode 100644 index 00000000000000..836ecbf87b5bdd --- /dev/null +++ b/Modules/clinic/_testclinic_depr_star.c.h @@ -0,0 +1,858 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif + + +PyDoc_VAR(deprecate_positional_pos0_len1__doc__); + +PyDoc_STRVAR(deprecate_positional_pos0_len1__doc__, +"deprecate_positional_pos0_len1($module, /, a)\n" +"--\n" +"\n" +"Note: Passing positional arguments to deprecate_positional_pos0_len1()\n" +"is deprecated. Parameter \'a\' will become a keyword-only parameter in\n" +"Python 3.14.\n" +""); + +#define DEPRECATE_POSITIONAL_POS0_LEN1_METHODDEF \ + {"deprecate_positional_pos0_len1", _PyCFunction_CAST(deprecate_positional_pos0_len1), METH_FASTCALL|METH_KEYWORDS, deprecate_positional_pos0_len1__doc__}, + +static PyObject * +deprecate_positional_pos0_len1_impl(PyObject *module, PyObject *a); + +static PyObject * +deprecate_positional_pos0_len1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); + +static PyObject * +deprecate_positional_pos0_len1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "deprecate_positional_pos0_len1", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *a; + + #if PY_VERSION_HEX >= 0x030e00C0 + # error \ + "In _testclinic.c, update parameter(s) 'a' in the clinic input of" \ + " 'deprecate_positional_pos0_len1' to be keyword-only." + #elif PY_VERSION_HEX >= 0x030e00A0 + # ifdef _MSC_VER + # pragma message ( \ + "In _testclinic.c, update parameter(s) 'a' in the clinic input of" \ + " 'deprecate_positional_pos0_len1' to be keyword-only.") + # else + # warning \ + "In _testclinic.c, update parameter(s) 'a' in the clinic input of" \ + " 'deprecate_positional_pos0_len1' to be keyword-only." + # endif + #endif + if (nargs == 1) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing positional arguments to deprecate_positional_pos0_len1()" + " is deprecated. Parameter 'a' will become a keyword-only " + "parameter in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + return_value = deprecate_positional_pos0_len1_impl(module, a); + +exit: + return return_value; +} + +PyDoc_VAR(deprecate_positional_pos0_len2__doc__); + +PyDoc_STRVAR(deprecate_positional_pos0_len2__doc__, +"deprecate_positional_pos0_len2($module, /, a, b)\n" +"--\n" +"\n" +"Note: Passing positional arguments to deprecate_positional_pos0_len2()\n" +"is deprecated. Parameters \'a\' and \'b\' will become keyword-only\n" +"parameters in Python 3.14.\n" +""); + +#define DEPRECATE_POSITIONAL_POS0_LEN2_METHODDEF \ + {"deprecate_positional_pos0_len2", _PyCFunction_CAST(deprecate_positional_pos0_len2), METH_FASTCALL|METH_KEYWORDS, deprecate_positional_pos0_len2__doc__}, + +static PyObject * +deprecate_positional_pos0_len2_impl(PyObject *module, PyObject *a, + PyObject *b); + +static PyObject * +deprecate_positional_pos0_len2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); + +static PyObject * +deprecate_positional_pos0_len2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "deprecate_positional_pos0_len2", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + #if PY_VERSION_HEX >= 0x030e00C0 + # error \ + "In _testclinic.c, update parameter(s) 'a' and 'b' in the clinic " \ + "input of 'deprecate_positional_pos0_len2' to be keyword-only." + #elif PY_VERSION_HEX >= 0x030e00A0 + # ifdef _MSC_VER + # pragma message ( \ + "In _testclinic.c, update parameter(s) 'a' and 'b' in the clinic " \ + "input of 'deprecate_positional_pos0_len2' to be keyword-only.") + # else + # warning \ + "In _testclinic.c, update parameter(s) 'a' and 'b' in the clinic " \ + "input of 'deprecate_positional_pos0_len2' to be keyword-only." + # endif + #endif + if (nargs > 0 && nargs <= 2) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing positional arguments to deprecate_positional_pos0_len2()" + " is deprecated. Parameters 'a' and 'b' will become keyword-only " + "parameters in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = deprecate_positional_pos0_len2_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_VAR(deprecate_positional_pos0_len3_with_kwd__doc__); + +PyDoc_STRVAR(deprecate_positional_pos0_len3_with_kwd__doc__, +"deprecate_positional_pos0_len3_with_kwd($module, /, a, b, c, *, d)\n" +"--\n" +"\n" +"Note: Passing positional arguments to\n" +"deprecate_positional_pos0_len3_with_kwd() is deprecated. Parameters\n" +"\'a\', \'b\' and \'c\' will become keyword-only parameters in Python 3.14.\n" +""); + +#define DEPRECATE_POSITIONAL_POS0_LEN3_WITH_KWD_METHODDEF \ + {"deprecate_positional_pos0_len3_with_kwd", _PyCFunction_CAST(deprecate_positional_pos0_len3_with_kwd), METH_FASTCALL|METH_KEYWORDS, deprecate_positional_pos0_len3_with_kwd__doc__}, + +static PyObject * +deprecate_positional_pos0_len3_with_kwd_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, + PyObject *d); + +static PyObject * +deprecate_positional_pos0_len3_with_kwd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); + +static PyObject * +deprecate_positional_pos0_len3_with_kwd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "deprecate_positional_pos0_len3_with_kwd", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d; + + #if PY_VERSION_HEX >= 0x030e00C0 + # error \ + "In _testclinic.c, update parameter(s) 'a', 'b' and 'c' in the " \ + "clinic input of 'deprecate_positional_pos0_len3_with_kwd' to be " \ + "keyword-only." + #elif PY_VERSION_HEX >= 0x030e00A0 + # ifdef _MSC_VER + # pragma message ( \ + "In _testclinic.c, update parameter(s) 'a', 'b' and 'c' in the " \ + "clinic input of 'deprecate_positional_pos0_len3_with_kwd' to be " \ + "keyword-only.") + # else + # warning \ + "In _testclinic.c, update parameter(s) 'a', 'b' and 'c' in the " \ + "clinic input of 'deprecate_positional_pos0_len3_with_kwd' to be " \ + "keyword-only." + # endif + #endif + if (nargs > 0 && nargs <= 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing positional arguments to " + "deprecate_positional_pos0_len3_with_kwd() is deprecated. " + "Parameters 'a', 'b' and 'c' will become keyword-only parameters " + "in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + d = args[3]; + return_value = deprecate_positional_pos0_len3_with_kwd_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_VAR(deprecate_positional_pos1_len1_optional__doc__); + +PyDoc_STRVAR(deprecate_positional_pos1_len1_optional__doc__, +"deprecate_positional_pos1_len1_optional($module, /, a, b=None)\n" +"--\n" +"\n" +"Note: Passing 2 positional arguments to\n" +"deprecate_positional_pos1_len1_optional() is deprecated. Parameter \'b\'\n" +"will become a keyword-only parameter in Python 3.14.\n" +""); + +#define DEPRECATE_POSITIONAL_POS1_LEN1_OPTIONAL_METHODDEF \ + {"deprecate_positional_pos1_len1_optional", _PyCFunction_CAST(deprecate_positional_pos1_len1_optional), METH_FASTCALL|METH_KEYWORDS, deprecate_positional_pos1_len1_optional__doc__}, + +static PyObject * +deprecate_positional_pos1_len1_optional_impl(PyObject *module, PyObject *a, + PyObject *b); + +static PyObject * +deprecate_positional_pos1_len1_optional(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); + +static PyObject * +deprecate_positional_pos1_len1_optional(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "deprecate_positional_pos1_len1_optional", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + + #if PY_VERSION_HEX >= 0x030e00C0 + # error \ + "In _testclinic.c, update parameter(s) 'b' in the clinic input of" \ + " 'deprecate_positional_pos1_len1_optional' to be keyword-only." + #elif PY_VERSION_HEX >= 0x030e00A0 + # ifdef _MSC_VER + # pragma message ( \ + "In _testclinic.c, update parameter(s) 'b' in the clinic input of" \ + " 'deprecate_positional_pos1_len1_optional' to be keyword-only.") + # else + # warning \ + "In _testclinic.c, update parameter(s) 'b' in the clinic input of" \ + " 'deprecate_positional_pos1_len1_optional' to be keyword-only." + # endif + #endif + if (nargs == 2) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing 2 positional arguments to " + "deprecate_positional_pos1_len1_optional() is deprecated. " + "Parameter 'b' will become a keyword-only parameter in Python " + "3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + b = args[1]; +skip_optional_pos: + return_value = deprecate_positional_pos1_len1_optional_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_VAR(deprecate_positional_pos1_len1__doc__); + +PyDoc_STRVAR(deprecate_positional_pos1_len1__doc__, +"deprecate_positional_pos1_len1($module, /, a, b)\n" +"--\n" +"\n" +"Note: Passing 2 positional arguments to\n" +"deprecate_positional_pos1_len1() is deprecated. Parameter \'b\' will\n" +"become a keyword-only parameter in Python 3.14.\n" +""); + +#define DEPRECATE_POSITIONAL_POS1_LEN1_METHODDEF \ + {"deprecate_positional_pos1_len1", _PyCFunction_CAST(deprecate_positional_pos1_len1), METH_FASTCALL|METH_KEYWORDS, deprecate_positional_pos1_len1__doc__}, + +static PyObject * +deprecate_positional_pos1_len1_impl(PyObject *module, PyObject *a, + PyObject *b); + +static PyObject * +deprecate_positional_pos1_len1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); + +static PyObject * +deprecate_positional_pos1_len1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "deprecate_positional_pos1_len1", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + #if PY_VERSION_HEX >= 0x030e00C0 + # error \ + "In _testclinic.c, update parameter(s) 'b' in the clinic input of" \ + " 'deprecate_positional_pos1_len1' to be keyword-only." + #elif PY_VERSION_HEX >= 0x030e00A0 + # ifdef _MSC_VER + # pragma message ( \ + "In _testclinic.c, update parameter(s) 'b' in the clinic input of" \ + " 'deprecate_positional_pos1_len1' to be keyword-only.") + # else + # warning \ + "In _testclinic.c, update parameter(s) 'b' in the clinic input of" \ + " 'deprecate_positional_pos1_len1' to be keyword-only." + # endif + #endif + if (nargs == 2) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing 2 positional arguments to " + "deprecate_positional_pos1_len1() is deprecated. Parameter 'b' " + "will become a keyword-only parameter in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = deprecate_positional_pos1_len1_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_VAR(deprecate_positional_pos1_len2_with_kwd__doc__); + +PyDoc_STRVAR(deprecate_positional_pos1_len2_with_kwd__doc__, +"deprecate_positional_pos1_len2_with_kwd($module, /, a, b, c, *, d)\n" +"--\n" +"\n" +"Note: Passing more than 1 positional argument to\n" +"deprecate_positional_pos1_len2_with_kwd() is deprecated. Parameters\n" +"\'b\' and \'c\' will become keyword-only parameters in Python 3.14.\n" +""); + +#define DEPRECATE_POSITIONAL_POS1_LEN2_WITH_KWD_METHODDEF \ + {"deprecate_positional_pos1_len2_with_kwd", _PyCFunction_CAST(deprecate_positional_pos1_len2_with_kwd), METH_FASTCALL|METH_KEYWORDS, deprecate_positional_pos1_len2_with_kwd__doc__}, + +static PyObject * +deprecate_positional_pos1_len2_with_kwd_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, + PyObject *d); + +static PyObject * +deprecate_positional_pos1_len2_with_kwd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); + +static PyObject * +deprecate_positional_pos1_len2_with_kwd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "deprecate_positional_pos1_len2_with_kwd", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d; + + #if PY_VERSION_HEX >= 0x030e00C0 + # error \ + "In _testclinic.c, update parameter(s) 'b' and 'c' in the clinic " \ + "input of 'deprecate_positional_pos1_len2_with_kwd' to be " \ + "keyword-only." + #elif PY_VERSION_HEX >= 0x030e00A0 + # ifdef _MSC_VER + # pragma message ( \ + "In _testclinic.c, update parameter(s) 'b' and 'c' in the clinic " \ + "input of 'deprecate_positional_pos1_len2_with_kwd' to be " \ + "keyword-only.") + # else + # warning \ + "In _testclinic.c, update parameter(s) 'b' and 'c' in the clinic " \ + "input of 'deprecate_positional_pos1_len2_with_kwd' to be " \ + "keyword-only." + # endif + #endif + if (nargs > 1 && nargs <= 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 1 positional argument to " + "deprecate_positional_pos1_len2_with_kwd() is deprecated. " + "Parameters 'b' and 'c' will become keyword-only parameters in " + "Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + d = args[3]; + return_value = deprecate_positional_pos1_len2_with_kwd_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_VAR(deprecate_positional_pos2_len1__doc__); + +PyDoc_STRVAR(deprecate_positional_pos2_len1__doc__, +"deprecate_positional_pos2_len1($module, /, a, b, c)\n" +"--\n" +"\n" +"Note: Passing 3 positional arguments to\n" +"deprecate_positional_pos2_len1() is deprecated. Parameter \'c\' will\n" +"become a keyword-only parameter in Python 3.14.\n" +""); + +#define DEPRECATE_POSITIONAL_POS2_LEN1_METHODDEF \ + {"deprecate_positional_pos2_len1", _PyCFunction_CAST(deprecate_positional_pos2_len1), METH_FASTCALL|METH_KEYWORDS, deprecate_positional_pos2_len1__doc__}, + +static PyObject * +deprecate_positional_pos2_len1_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c); + +static PyObject * +deprecate_positional_pos2_len1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); + +static PyObject * +deprecate_positional_pos2_len1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", "c", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "deprecate_positional_pos2_len1", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + PyObject *a; + PyObject *b; + PyObject *c; + + #if PY_VERSION_HEX >= 0x030e00C0 + # error \ + "In _testclinic.c, update parameter(s) 'c' in the clinic input of" \ + " 'deprecate_positional_pos2_len1' to be keyword-only." + #elif PY_VERSION_HEX >= 0x030e00A0 + # ifdef _MSC_VER + # pragma message ( \ + "In _testclinic.c, update parameter(s) 'c' in the clinic input of" \ + " 'deprecate_positional_pos2_len1' to be keyword-only.") + # else + # warning \ + "In _testclinic.c, update parameter(s) 'c' in the clinic input of" \ + " 'deprecate_positional_pos2_len1' to be keyword-only." + # endif + #endif + if (nargs == 3) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing 3 positional arguments to " + "deprecate_positional_pos2_len1() is deprecated. Parameter 'c' " + "will become a keyword-only parameter in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + return_value = deprecate_positional_pos2_len1_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_VAR(deprecate_positional_pos2_len2__doc__); + +PyDoc_STRVAR(deprecate_positional_pos2_len2__doc__, +"deprecate_positional_pos2_len2($module, /, a, b, c, d)\n" +"--\n" +"\n" +"Note: Passing more than 2 positional arguments to\n" +"deprecate_positional_pos2_len2() is deprecated. Parameters \'c\' and \'d\'\n" +"will become keyword-only parameters in Python 3.14.\n" +""); + +#define DEPRECATE_POSITIONAL_POS2_LEN2_METHODDEF \ + {"deprecate_positional_pos2_len2", _PyCFunction_CAST(deprecate_positional_pos2_len2), METH_FASTCALL|METH_KEYWORDS, deprecate_positional_pos2_len2__doc__}, + +static PyObject * +deprecate_positional_pos2_len2_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, PyObject *d); + +static PyObject * +deprecate_positional_pos2_len2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); + +static PyObject * +deprecate_positional_pos2_len2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "deprecate_positional_pos2_len2", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d; + + #if PY_VERSION_HEX >= 0x030e00C0 + # error \ + "In _testclinic.c, update parameter(s) 'c' and 'd' in the clinic " \ + "input of 'deprecate_positional_pos2_len2' to be keyword-only." + #elif PY_VERSION_HEX >= 0x030e00A0 + # ifdef _MSC_VER + # pragma message ( \ + "In _testclinic.c, update parameter(s) 'c' and 'd' in the clinic " \ + "input of 'deprecate_positional_pos2_len2' to be keyword-only.") + # else + # warning \ + "In _testclinic.c, update parameter(s) 'c' and 'd' in the clinic " \ + "input of 'deprecate_positional_pos2_len2' to be keyword-only." + # endif + #endif + if (nargs > 2 && nargs <= 4) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 2 positional arguments to " + "deprecate_positional_pos2_len2() is deprecated. Parameters 'c' " + "and 'd' will become keyword-only parameters in Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 4, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + d = args[3]; + return_value = deprecate_positional_pos2_len2_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_VAR(deprecate_positional_pos2_len3_with_kwd__doc__); + +PyDoc_STRVAR(deprecate_positional_pos2_len3_with_kwd__doc__, +"deprecate_positional_pos2_len3_with_kwd($module, /, a, b, c, d, *, e)\n" +"--\n" +"\n" +"Note: Passing more than 2 positional arguments to\n" +"deprecate_positional_pos2_len3_with_kwd() is deprecated. Parameters\n" +"\'c\' and \'d\' will become keyword-only parameters in Python 3.14.\n" +""); + +#define DEPRECATE_POSITIONAL_POS2_LEN3_WITH_KWD_METHODDEF \ + {"deprecate_positional_pos2_len3_with_kwd", _PyCFunction_CAST(deprecate_positional_pos2_len3_with_kwd), METH_FASTCALL|METH_KEYWORDS, deprecate_positional_pos2_len3_with_kwd__doc__}, + +static PyObject * +deprecate_positional_pos2_len3_with_kwd_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, + PyObject *d, PyObject *e); + +static PyObject * +deprecate_positional_pos2_len3_with_kwd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); + +static PyObject * +deprecate_positional_pos2_len3_with_kwd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), &_Py_ID(e), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", "c", "d", "e", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "deprecate_positional_pos2_len3_with_kwd", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d; + PyObject *e; + + #if PY_VERSION_HEX >= 0x030e00C0 + # error \ + "In _testclinic.c, update parameter(s) 'c' and 'd' in the clinic " \ + "input of 'deprecate_positional_pos2_len3_with_kwd' to be " \ + "keyword-only." + #elif PY_VERSION_HEX >= 0x030e00A0 + # ifdef _MSC_VER + # pragma message ( \ + "In _testclinic.c, update parameter(s) 'c' and 'd' in the clinic " \ + "input of 'deprecate_positional_pos2_len3_with_kwd' to be " \ + "keyword-only.") + # else + # warning \ + "In _testclinic.c, update parameter(s) 'c' and 'd' in the clinic " \ + "input of 'deprecate_positional_pos2_len3_with_kwd' to be " \ + "keyword-only." + # endif + #endif + if (nargs > 2 && nargs <= 4) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Passing more than 2 positional arguments to " + "deprecate_positional_pos2_len3_with_kwd() is deprecated. " + "Parameters 'c' and 'd' will become keyword-only parameters in " + "Python 3.14.", 1)) + { + goto exit; + } + } + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 4, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + d = args[3]; + e = args[4]; + return_value = deprecate_positional_pos2_len3_with_kwd_impl(module, a, b, c, d, e); + +exit: + return return_value; +} +/*[clinic end generated code: output=8a26bcc46d538167 input=a9049054013a1b77]*/ From 61bef45a505ee4334210d94c9f20f7bef6da4a5a Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 8 Aug 2023 22:03:17 +0200 Subject: [PATCH 2/9] Readable tests --- Lib/test/test_clinic.py | 239 +++++++++++++++++----------------------- 1 file changed, 100 insertions(+), 139 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 9d4677a08047df..f575b7cea43db5 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -2319,14 +2319,19 @@ class ClinicFunctionalTest(unittest.TestCase): locals().update((name, getattr(ac_tester, name)) for name in dir(ac_tester) if name.startswith('test_')) - def check_depr_star(self, fn, *, regex, ok_args, fail_args): - for args, kwds in ok_args: - fn(*args, **kwds) - for args, kwds in fail_args: - with self.assertWarnsRegex(DeprecationWarning, re.escape(regex)) as cm: - fn(*args, **kwds) + def check_depr_star(self, *, fname, pnames, good_calls, bad_calls): + for call in good_calls: + call() + regex = ( + f"Passing.*positional argument.*to {fname}.*is deprecated. " + f"Parameter.*{pnames} will become.*keyword-only parameter.*in " + "Python 3.14" + ) + for call in bad_calls: + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + call() self.assertTrue(cm.filename.endswith("test_clinic.py"), cm.filename) - fn(*args, **kwds) # No warning raised second time + call() # No warning raised second time def test_objects_converter(self): with self.assertRaises(TypeError): @@ -2794,162 +2799,118 @@ def test_cloned_func_with_converter_exception_message(self): def test_depr_star_pos0_len1(self): fn = ac_tester.depr_star_pos0_len1 - self.check_depr_star(fn, - regex=( - "Passing positional arguments to depr_star_pos0_len1() " - "is deprecated. Parameter 'a' will become a keyword-only " - "parameter in Python 3.14" - ), - ok_args=( - ((), {"a": None}), - ), - fail_args=( - ((None,), {}), - ) - ) + self.check_depr_star( + fname="depr_star_pos0_len1", pnames="'a'", + good_calls=[ + lambda: fn(a=None), + ], + bad_calls=[ + lambda: fn(None), + ]) def test_depr_star_pos0_len2(self): fn = ac_tester.depr_star_pos0_len2 - self.check_depr_star(fn, - regex=( - "Passing positional arguments to depr_star_pos0_len2() " - "is deprecated. Parameters 'a' and 'b' will become " - "keyword-only parameters in Python 3.14" - ), - ok_args=( - ((), {"a": None, "b": None}), - ), - fail_args=( - ((None,), {"b": None}), - ) - ) + self.check_depr_star( + fname="depr_star_pos0_len2", pnames="'a' and 'b'", + good_calls=[ + lambda: fn(a=None, b=None), + ], + bad_calls=[ + lambda: fn(None, b=None), + lambda: fn(None, None), + ]) def test_depr_star_pos0_len3_with_kwd(self): fn = ac_tester.depr_star_pos0_len3_with_kwd - self.check_depr_star(fn, - regex=( - "Passing positional arguments to depr_star_pos0_len3_with_kwd() " - "is deprecated. Parameters 'a', 'b' and 'c' will become " - "keyword-only parameters in Python 3.14" - ), - ok_args=( - ((), {"a": None, "b": None, "c": None, "d": None}), - ), - fail_args=( - ((None,), {"b": None, "c": None, "d": None}), - ((None, None), {"c": None, "d": None}), - ((None, None, None), {"d": None}), - ) - ) + self.check_depr_star( + fname="depr_star_pos0_len3_with_kwd", pnames="'a', 'b' and 'c'", + good_calls=[ + lambda: fn(a=None, b=None, c=None, d=None), + ], + bad_calls=[ + lambda: fn(None, b=None, c=None, d=None), + lambda: fn(None, None, c=None, d=None), + lambda: fn(None, None, None, d=None), + ]) def test_depr_star_pos1_len1_opt(self): fn = ac_tester.depr_star_pos1_len1_opt - self.check_depr_star(fn, - regex=( - "Passing 2 positional arguments to depr_star_pos1_len1_opt() " - "is deprecated. Parameter 'b' will become a keyword-only " - "parameter in Python 3.14" - ), - ok_args=( - ((), {"a": None, "b": None}), - ((None,), {}), - ((None,), {"b": None}), - ), - fail_args=( - ((None, None), {}), - ) - ) + self.check_depr_star( + fname="depr_star_pos1_len1_opt", pnames="'b'", + good_calls=[ + lambda: fn(a=None, b=None), + lambda: fn(None, b=None), + lambda: fn(a=None), + ], + bad_calls=[ + lambda: fn(None, None), + ]) def test_depr_star_pos1_len1(self): fn = ac_tester.depr_star_pos1_len1 - self.check_depr_star(fn, - regex=( - "Passing 2 positional arguments to depr_star_pos1_len1() is " - "deprecated. Parameter 'b' will become a keyword-only " - "parameter in Python 3.14" - ), - ok_args=( - ((), {"a": None, "b": None}), - ((None,), {"b": None}), - ), - fail_args=( - ((None, None), {}), - ) - ) + self.check_depr_star( + fname="depr_star_pos1_len1", pnames="'b'", + good_calls=[ + lambda: fn(a=None, b=None), + lambda: fn(None, b=None), + ], + bad_calls=[ + lambda: fn(None, None), + ]) def test_depr_star_pos1_len2_with_kwd(self): fn = ac_tester.depr_star_pos1_len2_with_kwd - self.check_depr_star(fn, - regex=( - "Passing more than 1 positional argument to " - "depr_star_pos1_len2_with_kwd() is deprecated. Parameters 'b' " - "and 'c' will become keyword-only parameters in Python 3.14" - ), - ok_args=( - ((), {"a": None, "b": None, "c": None, "d": None}), - ((None,), {"b": None, "c": None, "d": None}), - ), - fail_args=( - ((None, None), {"c": None, "d": None}), - ((None, None, None), {"d": None}), - ) - ) + self.check_depr_star( + fname="depr_star_pos1_len2_with_kwd", pnames="'b' and 'c'", + good_calls=[ + lambda: fn(a=None, b=None, c=None, d=None), + lambda: fn(None, b=None, c=None, d=None), + ], + bad_calls=[ + lambda: fn(None, None, c=None, d=None), + lambda: fn(None, None, None, d=None), + ]) def test_depr_star_pos2_len1(self): fn = ac_tester.depr_star_pos2_len1 - self.check_depr_star(fn, - regex=( - "Passing 3 positional arguments to depr_star_pos2_len1() is " - "deprecated. Parameter 'c' will become a keyword-only " - "parameter in Python 3.14" - ), - ok_args=( - ((), {"a": None, "b": None, "c": None}), - ((None,), {"b": None, "c": None}), - ((None, None), {"c": None}), - ), - fail_args=( - ((None, None, None), {}), - ) - ) + self.check_depr_star( + fname="depr_star_pos2_len1", pnames="'c'", + good_calls=[ + lambda: fn(a=None, b=None, c=None), + lambda: fn(None, b=None, c=None), + lambda: fn(None, None, c=None), + ], + bad_calls=[ + lambda: fn(None, None, None), + ]) def test_depr_star_pos2_len2(self): fn = ac_tester.depr_star_pos2_len2 - self.check_depr_star(fn, - regex=( - "Passing more than 2 positional arguments to " - "depr_star_pos2_len2() is deprecated. Parameters 'c' and 'd' " - "will become keyword-only parameters in Python 3.14" - ), - ok_args=( - ((), {"a": None, "b": None, "c": None, "d": None}), - ((None,), {"b": None, "c": None, "d": None}), - ((None, None), {"c": None, "d": None}), - ), - fail_args=( - ((None, None, None), {"d": None}), - ((None, None, None, None), {}), - ) - ) + self.check_depr_star( + fname="depr_star_pos2_len2", pnames="'c' and 'd'", + good_calls=[ + lambda: fn(a=None, b=None, c=None, d=None), + lambda: fn(None, b=None, c=None, d=None), + lambda: fn(None, None, c=None, d=None), + ], + bad_calls=[ + lambda: fn(None, None, None, d=None), + lambda: fn(None, None, None, None), + ]) def test_depr_star_pos2_len2_with_kwd(self): fn = ac_tester.depr_star_pos2_len2_with_kwd - self.check_depr_star(fn, - regex=( - "Passing more than 2 positional arguments to " - "depr_star_pos2_len2_with_kwd() is deprecated. Parameters 'c' " - "and 'd' will become keyword-only parameters in Python 3.14" - ), - ok_args=( - ((), {"a": None, "b": None, "c": None, "d": None, "e": None}), - ((None,), {"b": None, "c": None, "d": None, "e": None}), - ((None, None), {"c": None, "d": None, "e": None}), - ), - fail_args=( - ((None, None, None), {"d": None, "e": None}), - ((None, None, None, None), {"e": None}), - ) - ) + self.check_depr_star( + fname="depr_star_pos2_len2", pnames="'c' and 'd'", + good_calls=[ + lambda: fn(a=None, b=None, c=None, d=None, e=None), + lambda: fn(None, b=None, c=None, d=None, e=None), + lambda: fn(None, None, c=None, d=None, e=None), + ], + bad_calls=[ + lambda: fn(None, None, None, d=None, e=None), + lambda: fn(None, None, None, None, e=None), + ]) class PermutationTests(unittest.TestCase): From 6559443c7b028fb309d800006f42cb3ce1f123ac Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 9 Aug 2023 13:44:06 +0200 Subject: [PATCH 3/9] Address review: greatly simplify tests --- Lib/test/test_clinic.py | 140 ++++++++++++---------------------------- 1 file changed, 41 insertions(+), 99 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 0b19779b5851ec..dca5f4c8c5e4b5 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -2423,19 +2423,15 @@ class ClinicFunctionalTest(unittest.TestCase): locals().update((name, getattr(ac_tester, name)) for name in dir(ac_tester) if name.startswith('test_')) - def check_depr_star(self, *, fname, pnames, good_calls, bad_calls): - for call in good_calls: - call() + def check_depr_star(self, fn, *args, **kwds): + pnames = ".*".join([repr(a) for a in args]) regex = ( - f"Passing.*positional argument.*to {fname}.*is deprecated. " - f"Parameter.*{pnames} will become.*keyword-only parameter.*in " - "Python 3.14" + f"Passing.*positional argument.*to {fn.__name__}.*is deprecated. " + f"Parameter.*{pnames} will become.*keyword-only parameter.*in Python 3.14" ) - for call in bad_calls: - with self.assertWarnsRegex(DeprecationWarning, regex) as cm: - call() - self.assertTrue(cm.filename.endswith("test_clinic.py"), cm.filename) - call() # No warning raised second time + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: + fn(*args, **kwds) + self.assertEqual(cm.filename, __file__) def test_objects_converter(self): with self.assertRaises(TypeError): @@ -2903,118 +2899,64 @@ def test_cloned_func_with_converter_exception_message(self): def test_depr_star_pos0_len1(self): fn = ac_tester.depr_star_pos0_len1 - self.check_depr_star( - fname="depr_star_pos0_len1", pnames="'a'", - good_calls=[ - lambda: fn(a=None), - ], - bad_calls=[ - lambda: fn(None), - ]) + fn(a=None) + self.check_depr_star(fn, "a") def test_depr_star_pos0_len2(self): fn = ac_tester.depr_star_pos0_len2 - self.check_depr_star( - fname="depr_star_pos0_len2", pnames="'a' and 'b'", - good_calls=[ - lambda: fn(a=None, b=None), - ], - bad_calls=[ - lambda: fn(None, b=None), - lambda: fn(None, None), - ]) + fn(a=0, b=0), + self.check_depr_star(fn, "a", b=0), + self.check_depr_star(fn, "a", "b"), def test_depr_star_pos0_len3_with_kwd(self): fn = ac_tester.depr_star_pos0_len3_with_kwd - self.check_depr_star( - fname="depr_star_pos0_len3_with_kwd", pnames="'a', 'b' and 'c'", - good_calls=[ - lambda: fn(a=None, b=None, c=None, d=None), - ], - bad_calls=[ - lambda: fn(None, b=None, c=None, d=None), - lambda: fn(None, None, c=None, d=None), - lambda: fn(None, None, None, d=None), - ]) + fn(a=0, b=0, c=0, d=0) + self.check_depr_star(fn, "a", b=0, c=0, d=0) + self.check_depr_star(fn, "a", "b", c=0, d=0) + self.check_depr_star(fn, "a", "b", "c", d=0) def test_depr_star_pos1_len1_opt(self): fn = ac_tester.depr_star_pos1_len1_opt - self.check_depr_star( - fname="depr_star_pos1_len1_opt", pnames="'b'", - good_calls=[ - lambda: fn(a=None, b=None), - lambda: fn(None, b=None), - lambda: fn(a=None), - ], - bad_calls=[ - lambda: fn(None, None), - ]) + fn(a=0, b=0) + fn("a", b=0) + fn(a=0) # b is optional + self.check_depr_star(fn, "a", "b") def test_depr_star_pos1_len1(self): fn = ac_tester.depr_star_pos1_len1 - self.check_depr_star( - fname="depr_star_pos1_len1", pnames="'b'", - good_calls=[ - lambda: fn(a=None, b=None), - lambda: fn(None, b=None), - ], - bad_calls=[ - lambda: fn(None, None), - ]) + fn(a=0, b=0) + fn("a", b=0) + self.check_depr_star(fn, "a", "b") def test_depr_star_pos1_len2_with_kwd(self): fn = ac_tester.depr_star_pos1_len2_with_kwd - self.check_depr_star( - fname="depr_star_pos1_len2_with_kwd", pnames="'b' and 'c'", - good_calls=[ - lambda: fn(a=None, b=None, c=None, d=None), - lambda: fn(None, b=None, c=None, d=None), - ], - bad_calls=[ - lambda: fn(None, None, c=None, d=None), - lambda: fn(None, None, None, d=None), - ]) + fn(a=0, b=0, c=0, d=0), + fn("a", b=0, c=0, d=0), + self.check_depr_star(fn, "a", "b", c=0, d=0), + self.check_depr_star(fn, "a", "b", "c", d=0), def test_depr_star_pos2_len1(self): fn = ac_tester.depr_star_pos2_len1 - self.check_depr_star( - fname="depr_star_pos2_len1", pnames="'c'", - good_calls=[ - lambda: fn(a=None, b=None, c=None), - lambda: fn(None, b=None, c=None), - lambda: fn(None, None, c=None), - ], - bad_calls=[ - lambda: fn(None, None, None), - ]) + fn(a=0, b=0, c=0) + fn("a", b=0, c=0) + fn("a", "b", c=0) + self.check_depr_star(fn, "a", "b", "c") def test_depr_star_pos2_len2(self): fn = ac_tester.depr_star_pos2_len2 - self.check_depr_star( - fname="depr_star_pos2_len2", pnames="'c' and 'd'", - good_calls=[ - lambda: fn(a=None, b=None, c=None, d=None), - lambda: fn(None, b=None, c=None, d=None), - lambda: fn(None, None, c=None, d=None), - ], - bad_calls=[ - lambda: fn(None, None, None, d=None), - lambda: fn(None, None, None, None), - ]) + fn(a=0, b=0, c=0, d=0) + fn("a", b=0, c=0, d=0) + fn("a", "b", c=0, d=0) + self.check_depr_star(fn, "a", "b", "c", d=0) + self.check_depr_star(fn, "a", "b", "c", "d") def test_depr_star_pos2_len2_with_kwd(self): fn = ac_tester.depr_star_pos2_len2_with_kwd - self.check_depr_star( - fname="depr_star_pos2_len2", pnames="'c' and 'd'", - good_calls=[ - lambda: fn(a=None, b=None, c=None, d=None, e=None), - lambda: fn(None, b=None, c=None, d=None, e=None), - lambda: fn(None, None, c=None, d=None, e=None), - ], - bad_calls=[ - lambda: fn(None, None, None, d=None, e=None), - lambda: fn(None, None, None, None, e=None), - ]) + fn(a=0, b=0, c=0, d=0, e=0) + fn("a", b=0, c=0, d=0, e=0) + fn("a", "b", c=0, d=0, e=0) + self.check_depr_star(fn, "a", "b", "c", d=0, e=0) + self.check_depr_star(fn, "a", "b", "c", "d", e=0) class PermutationTests(unittest.TestCase): From 194420bcd15db20e961352aa43fbc988dd1457b3 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 9 Aug 2023 14:02:51 +0200 Subject: [PATCH 4/9] More accurate regex; pass param names explicitly --- Lib/test/test_clinic.py | 48 ++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index dca5f4c8c5e4b5..163ae1dd13f9cd 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -2423,11 +2423,11 @@ class ClinicFunctionalTest(unittest.TestCase): locals().update((name, getattr(ac_tester, name)) for name in dir(ac_tester) if name.startswith('test_')) - def check_depr_star(self, fn, *args, **kwds): - pnames = ".*".join([repr(a) for a in args]) + def check_depr_star(self, pnames, fn, *args, **kwds): regex = ( - f"Passing.*positional argument.*to {fn.__name__}.*is deprecated. " - f"Parameter.*{pnames} will become.*keyword-only parameter.*in Python 3.14" + f"Passing( more than)?( [0-9]+)? positional argument(s)? to " + f"{fn.__name__}\(\) is deprecated. Parameter(s)? {pnames} will " + f"become( a)? keyword-only parameter(s)? in Python 3.14" ) with self.assertWarnsRegex(DeprecationWarning, regex) as cm: fn(*args, **kwds) @@ -2900,63 +2900,71 @@ def test_cloned_func_with_converter_exception_message(self): def test_depr_star_pos0_len1(self): fn = ac_tester.depr_star_pos0_len1 fn(a=None) - self.check_depr_star(fn, "a") + self.check_depr_star("'a'", fn, "a") def test_depr_star_pos0_len2(self): fn = ac_tester.depr_star_pos0_len2 - fn(a=0, b=0), - self.check_depr_star(fn, "a", b=0), - self.check_depr_star(fn, "a", "b"), + fn(a=0, b=0) + pnames = "'a' and 'b'" + self.check_depr_star(pnames, fn, "a", b=0), + self.check_depr_star(pnames, fn, "a", "b"), def test_depr_star_pos0_len3_with_kwd(self): fn = ac_tester.depr_star_pos0_len3_with_kwd fn(a=0, b=0, c=0, d=0) - self.check_depr_star(fn, "a", b=0, c=0, d=0) - self.check_depr_star(fn, "a", "b", c=0, d=0) - self.check_depr_star(fn, "a", "b", "c", d=0) + pnames = "'a', 'b' and 'c'" + self.check_depr_star(pnames, fn, "a", b=0, c=0, d=0) + self.check_depr_star(pnames, fn, "a", "b", c=0, d=0) + self.check_depr_star(pnames, fn, "a", "b", "c", d=0) def test_depr_star_pos1_len1_opt(self): fn = ac_tester.depr_star_pos1_len1_opt fn(a=0, b=0) fn("a", b=0) fn(a=0) # b is optional - self.check_depr_star(fn, "a", "b") + pnames = "'b'" + self.check_depr_star(pnames, fn, "a", "b") def test_depr_star_pos1_len1(self): fn = ac_tester.depr_star_pos1_len1 fn(a=0, b=0) fn("a", b=0) - self.check_depr_star(fn, "a", "b") + pnames = "'b'" + self.check_depr_star(pnames, fn, "a", "b") def test_depr_star_pos1_len2_with_kwd(self): fn = ac_tester.depr_star_pos1_len2_with_kwd fn(a=0, b=0, c=0, d=0), fn("a", b=0, c=0, d=0), - self.check_depr_star(fn, "a", "b", c=0, d=0), - self.check_depr_star(fn, "a", "b", "c", d=0), + pnames = "'b' and 'c'" + self.check_depr_star(pnames, fn, "a", "b", c=0, d=0), + self.check_depr_star(pnames, fn, "a", "b", "c", d=0), def test_depr_star_pos2_len1(self): fn = ac_tester.depr_star_pos2_len1 fn(a=0, b=0, c=0) fn("a", b=0, c=0) fn("a", "b", c=0) - self.check_depr_star(fn, "a", "b", "c") + pnames = "'c'" + self.check_depr_star(pnames, fn, "a", "b", "c") def test_depr_star_pos2_len2(self): fn = ac_tester.depr_star_pos2_len2 fn(a=0, b=0, c=0, d=0) fn("a", b=0, c=0, d=0) fn("a", "b", c=0, d=0) - self.check_depr_star(fn, "a", "b", "c", d=0) - self.check_depr_star(fn, "a", "b", "c", "d") + pnames = "'c' and 'd'" + self.check_depr_star(pnames, fn, "a", "b", "c", d=0) + self.check_depr_star(pnames, fn, "a", "b", "c", "d") def test_depr_star_pos2_len2_with_kwd(self): fn = ac_tester.depr_star_pos2_len2_with_kwd fn(a=0, b=0, c=0, d=0, e=0) fn("a", b=0, c=0, d=0, e=0) fn("a", "b", c=0, d=0, e=0) - self.check_depr_star(fn, "a", "b", "c", d=0, e=0) - self.check_depr_star(fn, "a", "b", "c", "d", e=0) + pnames = "'c' and 'd'" + self.check_depr_star(pnames, fn, "a", "b", "c", d=0, e=0) + self.check_depr_star(pnames, fn, "a", "b", "c", "d", e=0) class PermutationTests(unittest.TestCase): From 6875b2fcbe24796eda7004c366578ed8fc323643 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 9 Aug 2023 14:10:15 +0200 Subject: [PATCH 5/9] Even nicer --- Lib/test/test_clinic.py | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 163ae1dd13f9cd..1016881f36b39f 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -2,6 +2,7 @@ # Copyright 2012-2013 by Larry Hastings. # Licensed to the PSF under a contributor agreement. +from functools import partial from test import support, test_tools from test.support import os_helper from test.support.os_helper import TESTFN, unlink @@ -2905,66 +2906,66 @@ def test_depr_star_pos0_len1(self): def test_depr_star_pos0_len2(self): fn = ac_tester.depr_star_pos0_len2 fn(a=0, b=0) - pnames = "'a' and 'b'" - self.check_depr_star(pnames, fn, "a", b=0), - self.check_depr_star(pnames, fn, "a", "b"), + check = partial(self.check_depr_star, "'a' and 'b'", fn) + check("a", b=0) + check("a", "b") def test_depr_star_pos0_len3_with_kwd(self): fn = ac_tester.depr_star_pos0_len3_with_kwd fn(a=0, b=0, c=0, d=0) - pnames = "'a', 'b' and 'c'" - self.check_depr_star(pnames, fn, "a", b=0, c=0, d=0) - self.check_depr_star(pnames, fn, "a", "b", c=0, d=0) - self.check_depr_star(pnames, fn, "a", "b", "c", d=0) + check = partial(self.check_depr_star, "'a', 'b' and 'c'", fn) + check("a", b=0, c=0, d=0) + check("a", "b", c=0, d=0) + check("a", "b", "c", d=0) def test_depr_star_pos1_len1_opt(self): fn = ac_tester.depr_star_pos1_len1_opt fn(a=0, b=0) fn("a", b=0) fn(a=0) # b is optional - pnames = "'b'" - self.check_depr_star(pnames, fn, "a", "b") + check = partial(self.check_depr_star, "'b'", fn) + check("a", "b") def test_depr_star_pos1_len1(self): fn = ac_tester.depr_star_pos1_len1 fn(a=0, b=0) fn("a", b=0) - pnames = "'b'" - self.check_depr_star(pnames, fn, "a", "b") + check = partial(self.check_depr_star, "'b'", fn) + check("a", "b") def test_depr_star_pos1_len2_with_kwd(self): fn = ac_tester.depr_star_pos1_len2_with_kwd fn(a=0, b=0, c=0, d=0), fn("a", b=0, c=0, d=0), - pnames = "'b' and 'c'" - self.check_depr_star(pnames, fn, "a", "b", c=0, d=0), - self.check_depr_star(pnames, fn, "a", "b", "c", d=0), + check = partial(self.check_depr_star, "'b' and 'c'", fn) + check("a", "b", c=0, d=0), + check("a", "b", "c", d=0), def test_depr_star_pos2_len1(self): fn = ac_tester.depr_star_pos2_len1 fn(a=0, b=0, c=0) fn("a", b=0, c=0) fn("a", "b", c=0) - pnames = "'c'" - self.check_depr_star(pnames, fn, "a", "b", "c") + check = partial(self.check_depr_star, "'c'", fn) + check("a", "b", "c") def test_depr_star_pos2_len2(self): fn = ac_tester.depr_star_pos2_len2 fn(a=0, b=0, c=0, d=0) fn("a", b=0, c=0, d=0) fn("a", "b", c=0, d=0) - pnames = "'c' and 'd'" - self.check_depr_star(pnames, fn, "a", "b", "c", d=0) - self.check_depr_star(pnames, fn, "a", "b", "c", "d") + check = partial(self.check_depr_star, "'c' and 'd'", fn) + check("a", "b", "c", d=0) + check("a", "b", "c", "d") def test_depr_star_pos2_len2_with_kwd(self): fn = ac_tester.depr_star_pos2_len2_with_kwd fn(a=0, b=0, c=0, d=0, e=0) fn("a", b=0, c=0, d=0, e=0) fn("a", "b", c=0, d=0, e=0) - pnames = "'c' and 'd'" - self.check_depr_star(pnames, fn, "a", "b", "c", d=0, e=0) - self.check_depr_star(pnames, fn, "a", "b", "c", "d", e=0) + check = partial(self.check_depr_star, "'c' and 'd'", fn) + check("a", "b", "c", d=0, e=0) + check("a", "b", "c", "d", e=0) class PermutationTests(unittest.TestCase): From 9f40557514935c7d94f911c686f86e928af43d08 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 9 Aug 2023 15:13:17 +0200 Subject: [PATCH 6/9] Update Lib/test/test_clinic.py Co-authored-by: Alex Waygood --- Lib/test/test_clinic.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 512bba1424748a..9b0885ef61dc4f 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -2434,9 +2434,9 @@ class ClinicFunctionalTest(unittest.TestCase): def check_depr_star(self, pnames, fn, *args, **kwds): regex = ( - f"Passing( more than)?( [0-9]+)? positional argument(s)? to " - f"{fn.__name__}\(\) is deprecated. Parameter(s)? {pnames} will " - f"become( a)? keyword-only parameter(s)? in Python 3.14" + fr"Passing( more than)?( [0-9]+)? positional argument(s)? to " + fr"{fn.__name__}\(\) is deprecated. Parameter(s)? {pnames} will " + fr"become( a)? keyword-only parameter(s)? in Python 3.14" ) with self.assertWarnsRegex(DeprecationWarning, regex) as cm: fn(*args, **kwds) From cdf057442469080d48f51b01cb61e1706331a593 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 9 Aug 2023 23:48:15 +0200 Subject: [PATCH 7/9] Check the line number --- Lib/test/test_clinic.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index cb255f399cae40..51f787cfc98e17 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -2439,8 +2439,11 @@ def check_depr_star(self, pnames, fn, *args, **kwds): fr"become( a)? keyword-only parameter(s)? in Python 3.14" ) with self.assertWarnsRegex(DeprecationWarning, regex) as cm: - fn(*args, **kwds) + # Record the line number, so we're sure we've got the correct stack + # level on the deprecation warning. + _, lineno = fn(*args, **kwds), sys._getframe().f_lineno self.assertEqual(cm.filename, __file__) + self.assertEqual(cm.lineno, lineno) def test_objects_converter(self): with self.assertRaises(TypeError): From 9a4128df9a5178ccf1ae9aca87d0d4df6ed95eff Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 9 Aug 2023 23:53:11 +0200 Subject: [PATCH 8/9] Update globals-to-fix.tsv --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index dedcb3141457c0..28bd2a4430d14e 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -322,6 +322,8 @@ Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_Type - Modules/_testcapi/vectorcall.c - MethodDescriptor2_Type - +Modules/_testclinic.c - DeprStarInit - +Modules/_testclinic.c - DeprStarNew - ################################## From e56888c400d1edc0dd64f3a4c9f4c98f94d78663 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 10 Aug 2023 08:52:58 +0200 Subject: [PATCH 9/9] Apply suggestions from code review Co-authored-by: Serhiy Storchaka --- Lib/test/test_clinic.py | 8 +++++--- Modules/_testclinic.c | 6 +----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 51f787cfc98e17..a649b5fe2201c8 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -2436,7 +2436,7 @@ def check_depr_star(self, pnames, fn, *args, **kwds): regex = ( fr"Passing( more than)?( [0-9]+)? positional argument(s)? to " fr"{fn.__name__}\(\) is deprecated. Parameter(s)? {pnames} will " - fr"become( a)? keyword-only parameter(s)? in Python 3.14" + fr"become( a)? keyword-only parameter(s)? in Python 3\.14" ) with self.assertWarnsRegex(DeprecationWarning, regex) as cm: # Record the line number, so we're sure we've got the correct stack @@ -2915,8 +2915,9 @@ def test_depr_star_new(self): "deprecated. Parameter 'a' will become a keyword-only parameter " "in Python 3.14." ) - with self.assertWarnsRegex(DeprecationWarning, regex): + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: ac_tester.DeprStarNew(None) + self.assertEqual(cm.filename, __file__) def test_depr_star_init(self): regex = re.escape( @@ -2924,8 +2925,9 @@ def test_depr_star_init(self): "deprecated. Parameter 'a' will become a keyword-only parameter " "in Python 3.14." ) - with self.assertWarnsRegex(DeprecationWarning, regex): + with self.assertWarnsRegex(DeprecationWarning, regex) as cm: ac_tester.DeprStarInit(None) + self.assertEqual(cm.filename, __file__) def test_depr_star_pos0_len1(self): fn = ac_tester.depr_star_pos0_len1 diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index e1962d939a844a..8fa3cc83d871b1 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -1227,11 +1227,7 @@ static PyObject * depr_star_new_impl(PyTypeObject *type, PyObject *a) /*[clinic end generated code: output=bdbb36244f90cf46 input=f4ae7dafbc23c378]*/ { - PyObject *self = type->tp_alloc(type, 0); - if (self == NULL) { - return NULL; - } - return self; + return type->tp_alloc(type, 0); } static PyTypeObject DeprStarNew = {