[Python-checkins] gh-93649: Split getargs tests from _testcapimodule.c (#99346)

erlend-aasland webhook-mailer at python.org
Mon Nov 14 16:24:00 EST 2022


https://github.com/python/cpython/commit/3d9431983a89b14250716c1d227e2ce40b343bdd
commit: 3d9431983a89b14250716c1d227e2ce40b343bdd
branch: main
author: Erlend E. Aasland <erlend.aasland at protonmail.com>
committer: erlend-aasland <erlend.aasland at protonmail.com>
date: 2022-11-14T22:23:41+01:00
summary:

gh-93649: Split getargs tests from _testcapimodule.c (#99346)

files:
A Modules/_testcapi/getargs.c
M Modules/Setup.stdlib.in
M Modules/_testcapi/parts.h
M Modules/_testcapimodule.c
M PCbuild/_testcapi.vcxproj
M PCbuild/_testcapi.vcxproj.filters

diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in
index 74d222217980..b672ea908eec 100644
--- a/Modules/Setup.stdlib.in
+++ b/Modules/Setup.stdlib.in
@@ -169,7 +169,7 @@
 @MODULE__XXTESTFUZZ_TRUE at _xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
 @MODULE__TESTBUFFER_TRUE at _testbuffer _testbuffer.c
 @MODULE__TESTINTERNALCAPI_TRUE at _testinternalcapi _testinternalcapi.c
- at MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c
+ at MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c _testcapi/getargs.c
 
 # Some testing modules MUST be built as shared libraries.
 *shared*
diff --git a/Modules/_testcapi/getargs.c b/Modules/_testcapi/getargs.c
new file mode 100644
index 000000000000..25a8e5fe8b60
--- /dev/null
+++ b/Modules/_testcapi/getargs.c
@@ -0,0 +1,920 @@
+/*
+ * Tests for Python/getargs.c and Python/modsupport.c;
+ * APIs that parse and build arguments.
+ */
+
+#define PY_SSIZE_T_CLEAN
+
+#include "parts.h"
+
+static PyObject *
+parse_tuple_and_keywords(PyObject *self, PyObject *args)
+{
+    PyObject *sub_args;
+    PyObject *sub_kwargs;
+    const char *sub_format;
+    PyObject *sub_keywords;
+
+    double buffers[8][4]; /* double ensures alignment where necessary */
+    PyObject *converted[8];
+    char *keywords[8 + 1]; /* space for NULL at end */
+
+    PyObject *return_value = NULL;
+
+    if (!PyArg_ParseTuple(args, "OOsO:parse_tuple_and_keywords",
+                          &sub_args, &sub_kwargs, &sub_format, &sub_keywords))
+    {
+        return NULL;
+    }
+
+    if (!(PyList_CheckExact(sub_keywords) ||
+        PyTuple_CheckExact(sub_keywords)))
+    {
+        PyErr_SetString(PyExc_ValueError,
+            "parse_tuple_and_keywords: "
+            "sub_keywords must be either list or tuple");
+        return NULL;
+    }
+
+    memset(buffers, 0, sizeof(buffers));
+    memset(converted, 0, sizeof(converted));
+    memset(keywords, 0, sizeof(keywords));
+
+    Py_ssize_t size = PySequence_Fast_GET_SIZE(sub_keywords);
+    if (size > 8) {
+        PyErr_SetString(PyExc_ValueError,
+            "parse_tuple_and_keywords: too many keywords in sub_keywords");
+        goto exit;
+    }
+
+    for (Py_ssize_t i = 0; i < size; i++) {
+        PyObject *o = PySequence_Fast_GET_ITEM(sub_keywords, i);
+        if (!PyUnicode_FSConverter(o, (void *)(converted + i))) {
+            PyErr_Format(PyExc_ValueError,
+                "parse_tuple_and_keywords: "
+                "could not convert keywords[%zd] to narrow string", i);
+            goto exit;
+        }
+        keywords[i] = PyBytes_AS_STRING(converted[i]);
+    }
+
+    int result = PyArg_ParseTupleAndKeywords(sub_args, sub_kwargs,
+        sub_format, keywords,
+        buffers + 0, buffers + 1, buffers + 2, buffers + 3,
+        buffers + 4, buffers + 5, buffers + 6, buffers + 7);
+
+    if (result) {
+        return_value = Py_NewRef(Py_None);
+    }
+
+exit:
+    size = sizeof(converted) / sizeof(converted[0]);
+    for (Py_ssize_t i = 0; i < size; i++) {
+        Py_XDECREF(converted[i]);
+    }
+    return return_value;
+}
+
+static PyObject *
+get_args(PyObject *self, PyObject *args)
+{
+    if (args == NULL) {
+        args = Py_None;
+    }
+    return Py_NewRef(args);
+}
+
+static PyObject *
+get_kwargs(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    if (kwargs == NULL) {
+        kwargs = Py_None;
+    }
+    return Py_NewRef(kwargs);
+}
+
+static PyObject *
+getargs_w_star(PyObject *self, PyObject *args)
+{
+    Py_buffer buffer;
+
+    if (!PyArg_ParseTuple(args, "w*:getargs_w_star", &buffer)) {
+        return NULL;
+    }
+
+    if (2 <= buffer.len) {
+        char *str = buffer.buf;
+        str[0] = '[';
+        str[buffer.len-1] = ']';
+    }
+
+    PyObject *result = PyBytes_FromStringAndSize(buffer.buf, buffer.len);
+    PyBuffer_Release(&buffer);
+    return result;
+}
+
+static PyObject *
+test_empty_argparse(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    /* Test that formats can begin with '|'. See issue #4720. */
+    PyObject *dict = NULL;
+    static char *kwlist[] = {NULL};
+    PyObject *tuple = PyTuple_New(0);
+    if (!tuple) {
+        return NULL;
+    }
+    int result;
+    if (!(result = PyArg_ParseTuple(tuple, "|:test_empty_argparse"))) {
+        goto done;
+    }
+    dict = PyDict_New();
+    if (!dict) {
+        goto done;
+    }
+    result = PyArg_ParseTupleAndKeywords(tuple, dict, "|:test_empty_argparse",
+                                         kwlist);
+  done:
+    Py_DECREF(tuple);
+    Py_XDECREF(dict);
+    if (!result) {
+        return NULL;
+    }
+    Py_RETURN_NONE;
+}
+
+/* Test tuple argument processing */
+static PyObject *
+getargs_tuple(PyObject *self, PyObject *args)
+{
+    int a, b, c;
+    if (!PyArg_ParseTuple(args, "i(ii)", &a, &b, &c)) {
+        return NULL;
+    }
+    return Py_BuildValue("iii", a, b, c);
+}
+
+/* test PyArg_ParseTupleAndKeywords */
+static PyObject *
+getargs_keywords(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *keywords[] = {"arg1","arg2","arg3","arg4","arg5", NULL};
+    static const char fmt[] = "(ii)i|(i(ii))(iii)i";
+    int int_args[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, fmt, keywords,
+        &int_args[0], &int_args[1], &int_args[2], &int_args[3], &int_args[4],
+        &int_args[5], &int_args[6], &int_args[7], &int_args[8], &int_args[9]))
+    {
+        return NULL;
+    }
+    return Py_BuildValue("iiiiiiiiii",
+        int_args[0], int_args[1], int_args[2], int_args[3], int_args[4],
+        int_args[5], int_args[6], int_args[7], int_args[8], int_args[9]);
+}
+
+/* test PyArg_ParseTupleAndKeywords keyword-only arguments */
+static PyObject *
+getargs_keyword_only(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *keywords[] = {"required", "optional", "keyword_only", NULL};
+    int required = -1;
+    int optional = -1;
+    int keyword_only = -1;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i$i", keywords,
+                                     &required, &optional, &keyword_only))
+    {
+        return NULL;
+    }
+    return Py_BuildValue("iii", required, optional, keyword_only);
+}
+
+/* test PyArg_ParseTupleAndKeywords positional-only arguments */
+static PyObject *
+getargs_positional_only_and_keywords(PyObject *self, PyObject *args,
+                                     PyObject *kwargs)
+{
+    static char *keywords[] = {"", "", "keyword", NULL};
+    int required = -1;
+    int optional = -1;
+    int keyword = -1;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii", keywords,
+                                     &required, &optional, &keyword))
+    {
+        return NULL;
+    }
+    return Py_BuildValue("iii", required, optional, keyword);
+}
+
+/* Functions to call PyArg_ParseTuple with integer format codes,
+   and return the result.
+*/
+static PyObject *
+getargs_b(PyObject *self, PyObject *args)
+{
+    unsigned char value;
+    if (!PyArg_ParseTuple(args, "b", &value)) {
+        return NULL;
+    }
+    return PyLong_FromUnsignedLong((unsigned long)value);
+}
+
+static PyObject *
+getargs_B(PyObject *self, PyObject *args)
+{
+    unsigned char value;
+    if (!PyArg_ParseTuple(args, "B", &value)) {
+        return NULL;
+    }
+    return PyLong_FromUnsignedLong((unsigned long)value);
+}
+
+static PyObject *
+getargs_h(PyObject *self, PyObject *args)
+{
+    short value;
+    if (!PyArg_ParseTuple(args, "h", &value)) {
+        return NULL;
+    }
+    return PyLong_FromLong((long)value);
+}
+
+static PyObject *
+getargs_H(PyObject *self, PyObject *args)
+{
+    unsigned short value;
+    if (!PyArg_ParseTuple(args, "H", &value)) {
+        return NULL;
+    }
+    return PyLong_FromUnsignedLong((unsigned long)value);
+}
+
+static PyObject *
+getargs_I(PyObject *self, PyObject *args)
+{
+    unsigned int value;
+    if (!PyArg_ParseTuple(args, "I", &value)) {
+        return NULL;
+    }
+    return PyLong_FromUnsignedLong((unsigned long)value);
+}
+
+static PyObject *
+getargs_k(PyObject *self, PyObject *args)
+{
+    unsigned long value;
+    if (!PyArg_ParseTuple(args, "k", &value)) {
+        return NULL;
+    }
+    return PyLong_FromUnsignedLong(value);
+}
+
+static PyObject *
+getargs_i(PyObject *self, PyObject *args)
+{
+    int value;
+    if (!PyArg_ParseTuple(args, "i", &value)) {
+        return NULL;
+    }
+    return PyLong_FromLong((long)value);
+}
+
+static PyObject *
+getargs_l(PyObject *self, PyObject *args)
+{
+    long value;
+    if (!PyArg_ParseTuple(args, "l", &value)) {
+        return NULL;
+    }
+    return PyLong_FromLong(value);
+}
+
+static PyObject *
+getargs_n(PyObject *self, PyObject *args)
+{
+    Py_ssize_t value;
+    if (!PyArg_ParseTuple(args, "n", &value)) {
+        return NULL;
+    }
+    return PyLong_FromSsize_t(value);
+}
+
+static PyObject *
+getargs_p(PyObject *self, PyObject *args)
+{
+    int value;
+    if (!PyArg_ParseTuple(args, "p", &value)) {
+        return NULL;
+    }
+    return PyLong_FromLong(value);
+}
+
+static PyObject *
+getargs_L(PyObject *self, PyObject *args)
+{
+    long long value;
+    if (!PyArg_ParseTuple(args, "L", &value)) {
+        return NULL;
+    }
+    return PyLong_FromLongLong(value);
+}
+
+static PyObject *
+getargs_K(PyObject *self, PyObject *args)
+{
+    unsigned long long value;
+    if (!PyArg_ParseTuple(args, "K", &value)) {
+        return NULL;
+    }
+    return PyLong_FromUnsignedLongLong(value);
+}
+
+/* This function not only tests the 'k' getargs code, but also the
+   PyLong_AsUnsignedLongMask() function. */
+static PyObject *
+test_k_code(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *tuple, *num;
+    unsigned long value;
+
+    tuple = PyTuple_New(1);
+    if (tuple == NULL) {
+        return NULL;
+    }
+
+    /* a number larger than ULONG_MAX even on 64-bit platforms */
+    num = PyLong_FromString("FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16);
+    if (num == NULL) {
+        return NULL;
+    }
+
+    value = PyLong_AsUnsignedLongMask(num);
+    if (value != ULONG_MAX) {
+        PyErr_SetString(PyExc_AssertionError,
+            "test_k_code: "
+            "PyLong_AsUnsignedLongMask() returned wrong value for long 0xFFF...FFF");
+        return NULL;
+    }
+
+    PyTuple_SET_ITEM(tuple, 0, num);
+
+    value = 0;
+    if (!PyArg_ParseTuple(tuple, "k:test_k_code", &value)) {
+        return NULL;
+    }
+    if (value != ULONG_MAX) {
+        PyErr_SetString(PyExc_AssertionError,
+            "test_k_code: k code returned wrong value for long 0xFFF...FFF");
+        return NULL;
+    }
+
+    Py_DECREF(num);
+    num = PyLong_FromString("-FFFFFFFF000000000000000042", NULL, 16);
+    if (num == NULL) {
+        return NULL;
+    }
+
+    value = PyLong_AsUnsignedLongMask(num);
+    if (value != (unsigned long)-0x42) {
+        PyErr_SetString(PyExc_AssertionError,
+            "test_k_code: "
+            "PyLong_AsUnsignedLongMask() returned wrong value for long -0xFFF..000042");
+        return NULL;
+    }
+
+    PyTuple_SET_ITEM(tuple, 0, num);
+
+    value = 0;
+    if (!PyArg_ParseTuple(tuple, "k:test_k_code", &value)) {
+        return NULL;
+    }
+    if (value != (unsigned long)-0x42) {
+        PyErr_SetString(PyExc_AssertionError,
+            "test_k_code: k code returned wrong value for long -0xFFF..000042");
+        return NULL;
+    }
+
+    Py_DECREF(tuple);
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+getargs_f(PyObject *self, PyObject *args)
+{
+    float f;
+    if (!PyArg_ParseTuple(args, "f", &f)) {
+        return NULL;
+    }
+    return PyFloat_FromDouble(f);
+}
+
+static PyObject *
+getargs_d(PyObject *self, PyObject *args)
+{
+    double d;
+    if (!PyArg_ParseTuple(args, "d", &d)) {
+        return NULL;
+    }
+    return PyFloat_FromDouble(d);
+}
+
+static PyObject *
+getargs_D(PyObject *self, PyObject *args)
+{
+    Py_complex cval;
+    if (!PyArg_ParseTuple(args, "D", &cval)) {
+        return NULL;
+    }
+    return PyComplex_FromCComplex(cval);
+}
+
+static PyObject *
+getargs_S(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    if (!PyArg_ParseTuple(args, "S", &obj)) {
+        return NULL;
+    }
+    return Py_NewRef(obj);
+}
+
+static PyObject *
+getargs_Y(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    if (!PyArg_ParseTuple(args, "Y", &obj)) {
+        return NULL;
+    }
+    return Py_NewRef(obj);
+}
+
+static PyObject *
+getargs_U(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    if (!PyArg_ParseTuple(args, "U", &obj)) {
+        return NULL;
+    }
+    return Py_NewRef(obj);
+}
+
+static PyObject *
+getargs_c(PyObject *self, PyObject *args)
+{
+    char c;
+    if (!PyArg_ParseTuple(args, "c", &c)) {
+        return NULL;
+    }
+    return PyLong_FromLong((unsigned char)c);
+}
+
+static PyObject *
+getargs_C(PyObject *self, PyObject *args)
+{
+    int c;
+    if (!PyArg_ParseTuple(args, "C", &c)) {
+        return NULL;
+    }
+    return PyLong_FromLong(c);
+}
+
+static PyObject *
+getargs_s(PyObject *self, PyObject *args)
+{
+    char *str;
+    if (!PyArg_ParseTuple(args, "s", &str)) {
+        return NULL;
+    }
+    return PyBytes_FromString(str);
+}
+
+static PyObject *
+getargs_s_star(PyObject *self, PyObject *args)
+{
+    Py_buffer buffer;
+    PyObject *bytes;
+    if (!PyArg_ParseTuple(args, "s*", &buffer)) {
+        return NULL;
+    }
+    bytes = PyBytes_FromStringAndSize(buffer.buf, buffer.len);
+    PyBuffer_Release(&buffer);
+    return bytes;
+}
+
+static PyObject *
+getargs_s_hash(PyObject *self, PyObject *args)
+{
+    char *str;
+    Py_ssize_t size;
+    if (!PyArg_ParseTuple(args, "s#", &str, &size)) {
+        return NULL;
+    }
+    return PyBytes_FromStringAndSize(str, size);
+}
+
+static PyObject *
+getargs_z(PyObject *self, PyObject *args)
+{
+    char *str;
+    if (!PyArg_ParseTuple(args, "z", &str)) {
+        return NULL;
+    }
+    if (str != NULL) {
+        return PyBytes_FromString(str);
+    }
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+getargs_z_star(PyObject *self, PyObject *args)
+{
+    Py_buffer buffer;
+    PyObject *bytes;
+    if (!PyArg_ParseTuple(args, "z*", &buffer)) {
+        return NULL;
+    }
+    if (buffer.buf != NULL) {
+        bytes = PyBytes_FromStringAndSize(buffer.buf, buffer.len);
+    }
+    else {
+        bytes = Py_NewRef(Py_None);
+    }
+    PyBuffer_Release(&buffer);
+    return bytes;
+}
+
+static PyObject *
+getargs_z_hash(PyObject *self, PyObject *args)
+{
+    char *str;
+    Py_ssize_t size;
+    if (!PyArg_ParseTuple(args, "z#", &str, &size)) {
+        return NULL;
+    }
+    if (str != NULL) {
+        return PyBytes_FromStringAndSize(str, size);
+    }
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+getargs_y(PyObject *self, PyObject *args)
+{
+    char *str;
+    if (!PyArg_ParseTuple(args, "y", &str)) {
+        return NULL;
+    }
+    return PyBytes_FromString(str);
+}
+
+static PyObject *
+getargs_y_star(PyObject *self, PyObject *args)
+{
+    Py_buffer buffer;
+    if (!PyArg_ParseTuple(args, "y*", &buffer)) {
+        return NULL;
+    }
+    PyObject *bytes = PyBytes_FromStringAndSize(buffer.buf, buffer.len);
+    PyBuffer_Release(&buffer);
+    return bytes;
+}
+
+static PyObject *
+getargs_y_hash(PyObject *self, PyObject *args)
+{
+    char *str;
+    Py_ssize_t size;
+    if (!PyArg_ParseTuple(args, "y#", &str, &size)) {
+        return NULL;
+    }
+    return PyBytes_FromStringAndSize(str, size);
+}
+
+static PyObject *
+getargs_u(PyObject *self, PyObject *args)
+{
+    Py_UNICODE *str;
+    if (!PyArg_ParseTuple(args, "u", &str)) {
+        return NULL;
+    }
+    return PyUnicode_FromWideChar(str, -1);
+}
+
+static PyObject *
+getargs_u_hash(PyObject *self, PyObject *args)
+{
+    Py_UNICODE *str;
+    Py_ssize_t size;
+    if (!PyArg_ParseTuple(args, "u#", &str, &size)) {
+        return NULL;
+    }
+    return PyUnicode_FromWideChar(str, size);
+}
+
+static PyObject *
+getargs_Z(PyObject *self, PyObject *args)
+{
+    Py_UNICODE *str;
+    if (!PyArg_ParseTuple(args, "Z", &str)) {
+        return NULL;
+    }
+    if (str != NULL) {
+        return PyUnicode_FromWideChar(str, -1);
+    }
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+getargs_Z_hash(PyObject *self, PyObject *args)
+{
+    Py_UNICODE *str;
+    Py_ssize_t size;
+    if (!PyArg_ParseTuple(args, "Z#", &str, &size)) {
+        return NULL;
+    }
+    if (str != NULL) {
+        return PyUnicode_FromWideChar(str, size);
+    }
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+getargs_es(PyObject *self, PyObject *args)
+{
+    PyObject *arg;
+    const char *encoding = NULL;
+    char *str;
+
+    if (!PyArg_ParseTuple(args, "O|s", &arg, &encoding)) {
+        return NULL;
+    }
+    if (!PyArg_Parse(arg, "es", encoding, &str)) {
+        return NULL;
+    }
+    PyObject *result = PyBytes_FromString(str);
+    PyMem_Free(str);
+    return result;
+}
+
+static PyObject *
+getargs_et(PyObject *self, PyObject *args)
+{
+    PyObject *arg;
+    const char *encoding = NULL;
+    char *str;
+
+    if (!PyArg_ParseTuple(args, "O|s", &arg, &encoding)) {
+        return NULL;
+    }
+    if (!PyArg_Parse(arg, "et", encoding, &str)) {
+        return NULL;
+    }
+    PyObject *result = PyBytes_FromString(str);
+    PyMem_Free(str);
+    return result;
+}
+
+static PyObject *
+getargs_es_hash(PyObject *self, PyObject *args)
+{
+    PyObject *arg;
+    const char *encoding = NULL;
+    PyByteArrayObject *buffer = NULL;
+    char *str = NULL;
+    Py_ssize_t size;
+
+    if (!PyArg_ParseTuple(args, "O|sY", &arg, &encoding, &buffer)) {
+        return NULL;
+    }
+    if (buffer != NULL) {
+        str = PyByteArray_AS_STRING(buffer);
+        size = PyByteArray_GET_SIZE(buffer);
+    }
+    if (!PyArg_Parse(arg, "es#", encoding, &str, &size)) {
+        return NULL;
+    }
+    PyObject *result = PyBytes_FromStringAndSize(str, size);
+    if (buffer == NULL) {
+        PyMem_Free(str);
+    }
+    return result;
+}
+
+static PyObject *
+getargs_et_hash(PyObject *self, PyObject *args)
+{
+    PyObject *arg;
+    const char *encoding = NULL;
+    PyByteArrayObject *buffer = NULL;
+    char *str = NULL;
+    Py_ssize_t size;
+
+    if (!PyArg_ParseTuple(args, "O|sY", &arg, &encoding, &buffer)) {
+        return NULL;
+    }
+    if (buffer != NULL) {
+        str = PyByteArray_AS_STRING(buffer);
+        size = PyByteArray_GET_SIZE(buffer);
+    }
+    if (!PyArg_Parse(arg, "et#", encoding, &str, &size)) {
+        return NULL;
+    }
+    PyObject *result = PyBytes_FromStringAndSize(str, size);
+    if (buffer == NULL) {
+        PyMem_Free(str);
+    }
+    return result;
+}
+
+/* Test the L code for PyArg_ParseTuple.  This should deliver a long long
+   for both long and int arguments.  The test may leak a little memory if
+   it fails.
+*/
+static PyObject *
+test_L_code(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *tuple, *num;
+    long long value;
+
+    tuple = PyTuple_New(1);
+    if (tuple == NULL) {
+        return NULL;
+    }
+
+    num = PyLong_FromLong(42);
+    if (num == NULL) {
+        return NULL;
+    }
+
+    PyTuple_SET_ITEM(tuple, 0, num);
+
+    value = -1;
+    if (!PyArg_ParseTuple(tuple, "L:test_L_code", &value)) {
+        return NULL;
+    }
+    if (value != 42) {
+        PyErr_SetString(PyExc_AssertionError,
+            "test_L_code: L code returned wrong value for long 42");
+        return NULL;
+    }
+
+    Py_DECREF(num);
+    num = PyLong_FromLong(42);
+    if (num == NULL) {
+        return NULL;
+    }
+
+    PyTuple_SET_ITEM(tuple, 0, num);
+
+    value = -1;
+    if (!PyArg_ParseTuple(tuple, "L:test_L_code", &value)) {
+        return NULL;
+    }
+    if (value != 42) {
+        PyErr_SetString(PyExc_AssertionError,
+            "test_L_code: L code returned wrong value for int 42");
+        return NULL;
+    }
+
+    Py_DECREF(tuple);
+    Py_RETURN_NONE;
+}
+
+/* Test the s and z codes for PyArg_ParseTuple.
+*/
+static PyObject *
+test_s_code(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    /* Unicode strings should be accepted */
+    PyObject *tuple = PyTuple_New(1);
+    if (tuple == NULL) {
+        return NULL;
+    }
+
+    PyObject *obj = PyUnicode_Decode("t\xeate", strlen("t\xeate"),
+                                     "latin-1", NULL);
+    if (obj == NULL) {
+        return NULL;
+    }
+
+    PyTuple_SET_ITEM(tuple, 0, obj);
+
+    /* These two blocks used to raise a TypeError:
+     * "argument must be string without null bytes, not str"
+     */
+    char *value;
+    if (!PyArg_ParseTuple(tuple, "s:test_s_code1", &value)) {
+        return NULL;
+    }
+
+    if (!PyArg_ParseTuple(tuple, "z:test_s_code2", &value)) {
+        return NULL;
+    }
+
+    Py_DECREF(tuple);
+    Py_RETURN_NONE;
+}
+
+#undef PyArg_ParseTupleAndKeywords
+PyAPI_FUNC(int) PyArg_ParseTupleAndKeywords(PyObject *, PyObject *,
+                                            const char *, char **, ...);
+
+static PyObject *
+getargs_s_hash_int(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *keywords[] = {"", "", "x", NULL};
+    Py_buffer buf = {NULL};
+    const char *s;
+    int len;
+    int i = 0;
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "w*|s#i", keywords,
+                                     &buf, &s, &len, &i))
+    {
+        return NULL;
+    }
+    PyBuffer_Release(&buf);
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+getargs_s_hash_int2(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *keywords[] = {"", "", "x", NULL};
+    Py_buffer buf = {NULL};
+    const char *s;
+    int len;
+    int i = 0;
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "w*|(s#)i", keywords,
+                                     &buf, &s, &len, &i))
+    {
+        return NULL;
+    }
+    PyBuffer_Release(&buf);
+    Py_RETURN_NONE;
+}
+
+static PyMethodDef test_methods[] = {
+    {"get_args",                get_args,                        METH_VARARGS},
+    {"get_kwargs", _PyCFunction_CAST(get_kwargs), METH_VARARGS|METH_KEYWORDS},
+    {"getargs_B",               getargs_B,                       METH_VARARGS},
+    {"getargs_C",               getargs_C,                       METH_VARARGS},
+    {"getargs_D",               getargs_D,                       METH_VARARGS},
+    {"getargs_H",               getargs_H,                       METH_VARARGS},
+    {"getargs_I",               getargs_I,                       METH_VARARGS},
+    {"getargs_K",               getargs_K,                       METH_VARARGS},
+    {"getargs_L",               getargs_L,                       METH_VARARGS},
+    {"getargs_S",               getargs_S,                       METH_VARARGS},
+    {"getargs_U",               getargs_U,                       METH_VARARGS},
+    {"getargs_Y",               getargs_Y,                       METH_VARARGS},
+    {"getargs_Z",               getargs_Z,                       METH_VARARGS},
+    {"getargs_Z_hash",          getargs_Z_hash,                  METH_VARARGS},
+    {"getargs_b",               getargs_b,                       METH_VARARGS},
+    {"getargs_c",               getargs_c,                       METH_VARARGS},
+    {"getargs_d",               getargs_d,                       METH_VARARGS},
+    {"getargs_es",              getargs_es,                      METH_VARARGS},
+    {"getargs_es_hash",         getargs_es_hash,                 METH_VARARGS},
+    {"getargs_et",              getargs_et,                      METH_VARARGS},
+    {"getargs_et_hash",         getargs_et_hash,                 METH_VARARGS},
+    {"getargs_f",               getargs_f,                       METH_VARARGS},
+    {"getargs_h",               getargs_h,                       METH_VARARGS},
+    {"getargs_i",               getargs_i,                       METH_VARARGS},
+    {"getargs_k",               getargs_k,                       METH_VARARGS},
+    {"getargs_keyword_only", _PyCFunction_CAST(getargs_keyword_only), METH_VARARGS|METH_KEYWORDS},
+    {"getargs_keywords", _PyCFunction_CAST(getargs_keywords), METH_VARARGS|METH_KEYWORDS},
+    {"getargs_l",               getargs_l,                       METH_VARARGS},
+    {"getargs_n",               getargs_n,                       METH_VARARGS},
+    {"getargs_p",               getargs_p,                       METH_VARARGS},
+    {"getargs_positional_only_and_keywords", _PyCFunction_CAST(getargs_positional_only_and_keywords), METH_VARARGS|METH_KEYWORDS},
+    {"getargs_s",               getargs_s,                       METH_VARARGS},
+    {"getargs_s_hash",          getargs_s_hash,                  METH_VARARGS},
+    {"getargs_s_hash_int", _PyCFunction_CAST(getargs_s_hash_int), METH_VARARGS|METH_KEYWORDS},
+    {"getargs_s_hash_int2", _PyCFunction_CAST(getargs_s_hash_int2), METH_VARARGS|METH_KEYWORDS},
+    {"getargs_s_star",          getargs_s_star,                  METH_VARARGS},
+    {"getargs_tuple",           getargs_tuple,                   METH_VARARGS},
+    {"getargs_u",               getargs_u,                       METH_VARARGS},
+    {"getargs_u_hash",          getargs_u_hash,                  METH_VARARGS},
+    {"getargs_w_star",          getargs_w_star,                  METH_VARARGS},
+    {"getargs_y",               getargs_y,                       METH_VARARGS},
+    {"getargs_y_hash",          getargs_y_hash,                  METH_VARARGS},
+    {"getargs_y_star",          getargs_y_star,                  METH_VARARGS},
+    {"getargs_z",               getargs_z,                       METH_VARARGS},
+    {"getargs_z_hash",          getargs_z_hash,                  METH_VARARGS},
+    {"getargs_z_star",          getargs_z_star,                  METH_VARARGS},
+    {"parse_tuple_and_keywords", parse_tuple_and_keywords,       METH_VARARGS},
+    {"test_L_code",             test_L_code,                     METH_NOARGS},
+    {"test_empty_argparse",     test_empty_argparse,             METH_NOARGS},
+    {"test_k_code",             test_k_code,                     METH_NOARGS},
+    {"test_s_code",             test_s_code,                     METH_NOARGS},
+    {NULL},
+};
+
+int
+_PyTestCapi_Init_GetArgs(PyObject *mod)
+{
+    if (PyModule_AddFunctions(mod, test_methods) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h
index 304e5922c0d5..25ee0f76ec02 100644
--- a/Modules/_testcapi/parts.h
+++ b/Modules/_testcapi/parts.h
@@ -27,6 +27,7 @@
 int _PyTestCapi_Init_Vectorcall(PyObject *module);
 int _PyTestCapi_Init_Heaptype(PyObject *module);
 int _PyTestCapi_Init_Unicode(PyObject *module);
+int _PyTestCapi_Init_GetArgs(PyObject *module);
 
 #ifdef LIMITED_API_AVAILABLE
 int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 62fd1f6ec7aa..0ab0b846180f 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -949,52 +949,6 @@ test_long_as_double(PyObject *self, PyObject *Py_UNUSED(ignored))
     return Py_None;
 }
 
-/* Test the L code for PyArg_ParseTuple.  This should deliver a long long
-   for both long and int arguments.  The test may leak a little memory if
-   it fails.
-*/
-static PyObject *
-test_L_code(PyObject *self, PyObject *Py_UNUSED(ignored))
-{
-    PyObject *tuple, *num;
-    long long value;
-
-    tuple = PyTuple_New(1);
-    if (tuple == NULL)
-        return NULL;
-
-    num = PyLong_FromLong(42);
-    if (num == NULL)
-        return NULL;
-
-    PyTuple_SET_ITEM(tuple, 0, num);
-
-    value = -1;
-    if (!PyArg_ParseTuple(tuple, "L:test_L_code", &value)) {
-        return NULL;
-    }
-    if (value != 42)
-        return raiseTestError("test_L_code",
-            "L code returned wrong value for long 42");
-
-    Py_DECREF(num);
-    num = PyLong_FromLong(42);
-    if (num == NULL)
-        return NULL;
-
-    PyTuple_SET_ITEM(tuple, 0, num);
-
-    value = -1;
-    if (!PyArg_ParseTuple(tuple, "L:test_L_code", &value)) {
-        return NULL;
-    }
-    if (value != 42)
-        return raiseTestError("test_L_code",
-            "L code returned wrong value for int 42");
-
-    Py_DECREF(tuple);
-    Py_RETURN_NONE;
-}
 
 static PyObject *
 return_none(void *unused)
@@ -1234,699 +1188,6 @@ test_get_type_qualname(PyObject *self, PyObject *Py_UNUSED(ignored))
     Py_RETURN_NONE;
 }
 
-
-static PyObject *
-get_args(PyObject *self, PyObject *args)
-{
-    if (args == NULL) {
-        args = Py_None;
-    }
-    return Py_NewRef(args);
-}
-
-static PyObject *
-get_kwargs(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    if (kwargs == NULL) {
-        kwargs = Py_None;
-    }
-    return Py_NewRef(kwargs);
-}
-
-/* Test tuple argument processing */
-static PyObject *
-getargs_tuple(PyObject *self, PyObject *args)
-{
-    int a, b, c;
-    if (!PyArg_ParseTuple(args, "i(ii)", &a, &b, &c))
-        return NULL;
-    return Py_BuildValue("iii", a, b, c);
-}
-
-/* test PyArg_ParseTupleAndKeywords */
-static PyObject *
-getargs_keywords(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    static char *keywords[] = {"arg1","arg2","arg3","arg4","arg5", NULL};
-    static const char fmt[] = "(ii)i|(i(ii))(iii)i";
-    int int_args[10]={-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, fmt, keywords,
-        &int_args[0], &int_args[1], &int_args[2], &int_args[3], &int_args[4],
-        &int_args[5], &int_args[6], &int_args[7], &int_args[8], &int_args[9]))
-        return NULL;
-    return Py_BuildValue("iiiiiiiiii",
-        int_args[0], int_args[1], int_args[2], int_args[3], int_args[4],
-        int_args[5], int_args[6], int_args[7], int_args[8], int_args[9]);
-}
-
-/* test PyArg_ParseTupleAndKeywords keyword-only arguments */
-static PyObject *
-getargs_keyword_only(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    static char *keywords[] = {"required", "optional", "keyword_only", NULL};
-    int required = -1;
-    int optional = -1;
-    int keyword_only = -1;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i$i", keywords,
-                                     &required, &optional, &keyword_only))
-        return NULL;
-    return Py_BuildValue("iii", required, optional, keyword_only);
-}
-
-/* test PyArg_ParseTupleAndKeywords positional-only arguments */
-static PyObject *
-getargs_positional_only_and_keywords(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    static char *keywords[] = {"", "", "keyword", NULL};
-    int required = -1;
-    int optional = -1;
-    int keyword = -1;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii", keywords,
-                                     &required, &optional, &keyword))
-        return NULL;
-    return Py_BuildValue("iii", required, optional, keyword);
-}
-
-/* Functions to call PyArg_ParseTuple with integer format codes,
-   and return the result.
-*/
-static PyObject *
-getargs_b(PyObject *self, PyObject *args)
-{
-    unsigned char value;
-    if (!PyArg_ParseTuple(args, "b", &value))
-        return NULL;
-    return PyLong_FromUnsignedLong((unsigned long)value);
-}
-
-static PyObject *
-getargs_B(PyObject *self, PyObject *args)
-{
-    unsigned char value;
-    if (!PyArg_ParseTuple(args, "B", &value))
-        return NULL;
-    return PyLong_FromUnsignedLong((unsigned long)value);
-}
-
-static PyObject *
-getargs_h(PyObject *self, PyObject *args)
-{
-    short value;
-    if (!PyArg_ParseTuple(args, "h", &value))
-        return NULL;
-    return PyLong_FromLong((long)value);
-}
-
-static PyObject *
-getargs_H(PyObject *self, PyObject *args)
-{
-    unsigned short value;
-    if (!PyArg_ParseTuple(args, "H", &value))
-        return NULL;
-    return PyLong_FromUnsignedLong((unsigned long)value);
-}
-
-static PyObject *
-getargs_I(PyObject *self, PyObject *args)
-{
-    unsigned int value;
-    if (!PyArg_ParseTuple(args, "I", &value))
-        return NULL;
-    return PyLong_FromUnsignedLong((unsigned long)value);
-}
-
-static PyObject *
-getargs_k(PyObject *self, PyObject *args)
-{
-    unsigned long value;
-    if (!PyArg_ParseTuple(args, "k", &value))
-        return NULL;
-    return PyLong_FromUnsignedLong(value);
-}
-
-static PyObject *
-getargs_i(PyObject *self, PyObject *args)
-{
-    int value;
-    if (!PyArg_ParseTuple(args, "i", &value))
-        return NULL;
-    return PyLong_FromLong((long)value);
-}
-
-static PyObject *
-getargs_l(PyObject *self, PyObject *args)
-{
-    long value;
-    if (!PyArg_ParseTuple(args, "l", &value))
-        return NULL;
-    return PyLong_FromLong(value);
-}
-
-static PyObject *
-getargs_n(PyObject *self, PyObject *args)
-{
-    Py_ssize_t value;
-    if (!PyArg_ParseTuple(args, "n", &value))
-        return NULL;
-    return PyLong_FromSsize_t(value);
-}
-
-static PyObject *
-getargs_p(PyObject *self, PyObject *args)
-{
-    int value;
-    if (!PyArg_ParseTuple(args, "p", &value))
-        return NULL;
-    return PyLong_FromLong(value);
-}
-
-static PyObject *
-getargs_L(PyObject *self, PyObject *args)
-{
-    long long value;
-    if (!PyArg_ParseTuple(args, "L", &value))
-        return NULL;
-    return PyLong_FromLongLong(value);
-}
-
-static PyObject *
-getargs_K(PyObject *self, PyObject *args)
-{
-    unsigned long long value;
-    if (!PyArg_ParseTuple(args, "K", &value))
-        return NULL;
-    return PyLong_FromUnsignedLongLong(value);
-}
-
-/* This function not only tests the 'k' getargs code, but also the
-   PyLong_AsUnsignedLongMask() function. */
-static PyObject *
-test_k_code(PyObject *self, PyObject *Py_UNUSED(ignored))
-{
-    PyObject *tuple, *num;
-    unsigned long value;
-
-    tuple = PyTuple_New(1);
-    if (tuple == NULL)
-        return NULL;
-
-    /* a number larger than ULONG_MAX even on 64-bit platforms */
-    num = PyLong_FromString("FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16);
-    if (num == NULL)
-        return NULL;
-
-    value = PyLong_AsUnsignedLongMask(num);
-    if (value != ULONG_MAX)
-        return raiseTestError("test_k_code",
-            "PyLong_AsUnsignedLongMask() returned wrong value for long 0xFFF...FFF");
-
-    PyTuple_SET_ITEM(tuple, 0, num);
-
-    value = 0;
-    if (!PyArg_ParseTuple(tuple, "k:test_k_code", &value)) {
-        return NULL;
-    }
-    if (value != ULONG_MAX)
-        return raiseTestError("test_k_code",
-            "k code returned wrong value for long 0xFFF...FFF");
-
-    Py_DECREF(num);
-    num = PyLong_FromString("-FFFFFFFF000000000000000042", NULL, 16);
-    if (num == NULL)
-        return NULL;
-
-    value = PyLong_AsUnsignedLongMask(num);
-    if (value != (unsigned long)-0x42)
-        return raiseTestError("test_k_code",
-                              "PyLong_AsUnsignedLongMask() returned wrong "
-                              "value for long -0xFFF..000042");
-
-    PyTuple_SET_ITEM(tuple, 0, num);
-
-    value = 0;
-    if (!PyArg_ParseTuple(tuple, "k:test_k_code", &value)) {
-        return NULL;
-    }
-    if (value != (unsigned long)-0x42)
-        return raiseTestError("test_k_code",
-            "k code returned wrong value for long -0xFFF..000042");
-
-    Py_DECREF(tuple);
-    Py_RETURN_NONE;
-}
-
-static PyObject *
-getargs_f(PyObject *self, PyObject *args)
-{
-    float f;
-    if (!PyArg_ParseTuple(args, "f", &f))
-        return NULL;
-    return PyFloat_FromDouble(f);
-}
-
-static PyObject *
-getargs_d(PyObject *self, PyObject *args)
-{
-    double d;
-    if (!PyArg_ParseTuple(args, "d", &d))
-        return NULL;
-    return PyFloat_FromDouble(d);
-}
-
-static PyObject *
-getargs_D(PyObject *self, PyObject *args)
-{
-    Py_complex cval;
-    if (!PyArg_ParseTuple(args, "D", &cval))
-        return NULL;
-    return PyComplex_FromCComplex(cval);
-}
-
-static PyObject *
-getargs_S(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    if (!PyArg_ParseTuple(args, "S", &obj))
-        return NULL;
-    return Py_NewRef(obj);
-}
-
-static PyObject *
-getargs_Y(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    if (!PyArg_ParseTuple(args, "Y", &obj))
-        return NULL;
-    return Py_NewRef(obj);
-}
-
-static PyObject *
-getargs_U(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    if (!PyArg_ParseTuple(args, "U", &obj))
-        return NULL;
-    return Py_NewRef(obj);
-}
-
-static PyObject *
-getargs_c(PyObject *self, PyObject *args)
-{
-    char c;
-    if (!PyArg_ParseTuple(args, "c", &c))
-        return NULL;
-    return PyLong_FromLong((unsigned char)c);
-}
-
-static PyObject *
-getargs_C(PyObject *self, PyObject *args)
-{
-    int c;
-    if (!PyArg_ParseTuple(args, "C", &c))
-        return NULL;
-    return PyLong_FromLong(c);
-}
-
-static PyObject *
-getargs_s(PyObject *self, PyObject *args)
-{
-    char *str;
-    if (!PyArg_ParseTuple(args, "s", &str))
-        return NULL;
-    return PyBytes_FromString(str);
-}
-
-static PyObject *
-getargs_s_star(PyObject *self, PyObject *args)
-{
-    Py_buffer buffer;
-    PyObject *bytes;
-    if (!PyArg_ParseTuple(args, "s*", &buffer))
-        return NULL;
-    bytes = PyBytes_FromStringAndSize(buffer.buf, buffer.len);
-    PyBuffer_Release(&buffer);
-    return bytes;
-}
-
-static PyObject *
-getargs_s_hash(PyObject *self, PyObject *args)
-{
-    char *str;
-    Py_ssize_t size;
-    if (!PyArg_ParseTuple(args, "s#", &str, &size))
-        return NULL;
-    return PyBytes_FromStringAndSize(str, size);
-}
-
-static PyObject *
-getargs_z(PyObject *self, PyObject *args)
-{
-    char *str;
-    if (!PyArg_ParseTuple(args, "z", &str))
-        return NULL;
-    if (str != NULL)
-        return PyBytes_FromString(str);
-    else
-        Py_RETURN_NONE;
-}
-
-static PyObject *
-getargs_z_star(PyObject *self, PyObject *args)
-{
-    Py_buffer buffer;
-    PyObject *bytes;
-    if (!PyArg_ParseTuple(args, "z*", &buffer))
-        return NULL;
-    if (buffer.buf != NULL)
-        bytes = PyBytes_FromStringAndSize(buffer.buf, buffer.len);
-    else {
-        bytes = Py_NewRef(Py_None);
-    }
-    PyBuffer_Release(&buffer);
-    return bytes;
-}
-
-static PyObject *
-getargs_z_hash(PyObject *self, PyObject *args)
-{
-    char *str;
-    Py_ssize_t size;
-    if (!PyArg_ParseTuple(args, "z#", &str, &size))
-        return NULL;
-    if (str != NULL)
-        return PyBytes_FromStringAndSize(str, size);
-    else
-        Py_RETURN_NONE;
-}
-
-static PyObject *
-getargs_y(PyObject *self, PyObject *args)
-{
-    char *str;
-    if (!PyArg_ParseTuple(args, "y", &str))
-        return NULL;
-    return PyBytes_FromString(str);
-}
-
-static PyObject *
-getargs_y_star(PyObject *self, PyObject *args)
-{
-    Py_buffer buffer;
-    PyObject *bytes;
-    if (!PyArg_ParseTuple(args, "y*", &buffer))
-        return NULL;
-    bytes = PyBytes_FromStringAndSize(buffer.buf, buffer.len);
-    PyBuffer_Release(&buffer);
-    return bytes;
-}
-
-static PyObject *
-getargs_y_hash(PyObject *self, PyObject *args)
-{
-    char *str;
-    Py_ssize_t size;
-    if (!PyArg_ParseTuple(args, "y#", &str, &size))
-        return NULL;
-    return PyBytes_FromStringAndSize(str, size);
-}
-
-static PyObject *
-getargs_u(PyObject *self, PyObject *args)
-{
-    Py_UNICODE *str;
-    if (!PyArg_ParseTuple(args, "u", &str))
-        return NULL;
-    return PyUnicode_FromWideChar(str, -1);
-}
-
-static PyObject *
-getargs_u_hash(PyObject *self, PyObject *args)
-{
-    Py_UNICODE *str;
-    Py_ssize_t size;
-    if (!PyArg_ParseTuple(args, "u#", &str, &size))
-        return NULL;
-    return PyUnicode_FromWideChar(str, size);
-}
-
-static PyObject *
-getargs_Z(PyObject *self, PyObject *args)
-{
-    Py_UNICODE *str;
-    if (!PyArg_ParseTuple(args, "Z", &str))
-        return NULL;
-    if (str != NULL) {
-        return PyUnicode_FromWideChar(str, -1);
-    } else
-        Py_RETURN_NONE;
-}
-
-static PyObject *
-getargs_Z_hash(PyObject *self, PyObject *args)
-{
-    Py_UNICODE *str;
-    Py_ssize_t size;
-    if (!PyArg_ParseTuple(args, "Z#", &str, &size))
-        return NULL;
-    if (str != NULL)
-        return PyUnicode_FromWideChar(str, size);
-    else
-        Py_RETURN_NONE;
-}
-
-static PyObject *
-getargs_es(PyObject *self, PyObject *args)
-{
-    PyObject *arg, *result;
-    const char *encoding = NULL;
-    char *str;
-
-    if (!PyArg_ParseTuple(args, "O|s", &arg, &encoding))
-        return NULL;
-    if (!PyArg_Parse(arg, "es", encoding, &str))
-        return NULL;
-    result = PyBytes_FromString(str);
-    PyMem_Free(str);
-    return result;
-}
-
-static PyObject *
-getargs_et(PyObject *self, PyObject *args)
-{
-    PyObject *arg, *result;
-    const char *encoding = NULL;
-    char *str;
-
-    if (!PyArg_ParseTuple(args, "O|s", &arg, &encoding))
-        return NULL;
-    if (!PyArg_Parse(arg, "et", encoding, &str))
-        return NULL;
-    result = PyBytes_FromString(str);
-    PyMem_Free(str);
-    return result;
-}
-
-static PyObject *
-getargs_es_hash(PyObject *self, PyObject *args)
-{
-    PyObject *arg, *result;
-    const char *encoding = NULL;
-    PyByteArrayObject *buffer = NULL;
-    char *str = NULL;
-    Py_ssize_t size;
-
-    if (!PyArg_ParseTuple(args, "O|sY", &arg, &encoding, &buffer))
-        return NULL;
-    if (buffer != NULL) {
-        str = PyByteArray_AS_STRING(buffer);
-        size = PyByteArray_GET_SIZE(buffer);
-    }
-    if (!PyArg_Parse(arg, "es#", encoding, &str, &size))
-        return NULL;
-    result = PyBytes_FromStringAndSize(str, size);
-    if (buffer == NULL)
-        PyMem_Free(str);
-    return result;
-}
-
-static PyObject *
-getargs_et_hash(PyObject *self, PyObject *args)
-{
-    PyObject *arg, *result;
-    const char *encoding = NULL;
-    PyByteArrayObject *buffer = NULL;
-    char *str = NULL;
-    Py_ssize_t size;
-
-    if (!PyArg_ParseTuple(args, "O|sY", &arg, &encoding, &buffer))
-        return NULL;
-    if (buffer != NULL) {
-        str = PyByteArray_AS_STRING(buffer);
-        size = PyByteArray_GET_SIZE(buffer);
-    }
-    if (!PyArg_Parse(arg, "et#", encoding, &str, &size))
-        return NULL;
-    result = PyBytes_FromStringAndSize(str, size);
-    if (buffer == NULL)
-        PyMem_Free(str);
-    return result;
-}
-
-/* Test the s and z codes for PyArg_ParseTuple.
-*/
-static PyObject *
-test_s_code(PyObject *self, PyObject *Py_UNUSED(ignored))
-{
-    /* Unicode strings should be accepted */
-    PyObject *tuple, *obj;
-    char *value;
-
-    tuple = PyTuple_New(1);
-    if (tuple == NULL)
-    return NULL;
-
-    obj = PyUnicode_Decode("t\xeate", strlen("t\xeate"),
-                           "latin-1", NULL);
-    if (obj == NULL)
-    return NULL;
-
-    PyTuple_SET_ITEM(tuple, 0, obj);
-
-    /* These two blocks used to raise a TypeError:
-     * "argument must be string without null bytes, not str"
-     */
-    if (!PyArg_ParseTuple(tuple, "s:test_s_code1", &value)) {
-        return NULL;
-    }
-
-    if (!PyArg_ParseTuple(tuple, "z:test_s_code2", &value)) {
-        return NULL;
-    }
-
-    Py_DECREF(tuple);
-    Py_RETURN_NONE;
-}
-
-static PyObject *
-parse_tuple_and_keywords(PyObject *self, PyObject *args)
-{
-    PyObject *sub_args;
-    PyObject *sub_kwargs;
-    const char *sub_format;
-    PyObject *sub_keywords;
-
-    Py_ssize_t i, size;
-    char *keywords[8 + 1]; /* space for NULL at end */
-    PyObject *o;
-    PyObject *converted[8];
-
-    int result;
-    PyObject *return_value = NULL;
-
-    double buffers[8][4]; /* double ensures alignment where necessary */
-
-    if (!PyArg_ParseTuple(args, "OOsO:parse_tuple_and_keywords",
-        &sub_args, &sub_kwargs,
-        &sub_format, &sub_keywords))
-        return NULL;
-
-    if (!(PyList_CheckExact(sub_keywords) || PyTuple_CheckExact(sub_keywords))) {
-        PyErr_SetString(PyExc_ValueError,
-            "parse_tuple_and_keywords: sub_keywords must be either list or tuple");
-        return NULL;
-    }
-
-    memset(buffers, 0, sizeof(buffers));
-    memset(converted, 0, sizeof(converted));
-    memset(keywords, 0, sizeof(keywords));
-
-    size = PySequence_Fast_GET_SIZE(sub_keywords);
-    if (size > 8) {
-        PyErr_SetString(PyExc_ValueError,
-            "parse_tuple_and_keywords: too many keywords in sub_keywords");
-        goto exit;
-    }
-
-    for (i = 0; i < size; i++) {
-        o = PySequence_Fast_GET_ITEM(sub_keywords, i);
-        if (!PyUnicode_FSConverter(o, (void *)(converted + i))) {
-            PyErr_Format(PyExc_ValueError,
-                "parse_tuple_and_keywords: could not convert keywords[%zd] to narrow string", i);
-            goto exit;
-        }
-        keywords[i] = PyBytes_AS_STRING(converted[i]);
-    }
-
-    result = PyArg_ParseTupleAndKeywords(sub_args, sub_kwargs,
-        sub_format, keywords,
-        buffers + 0, buffers + 1, buffers + 2, buffers + 3,
-        buffers + 4, buffers + 5, buffers + 6, buffers + 7);
-
-    if (result) {
-        return_value = Py_NewRef(Py_None);
-    }
-
-exit:
-    size = sizeof(converted) / sizeof(converted[0]);
-    for (i = 0; i < size; i++) {
-        Py_XDECREF(converted[i]);
-    }
-    return return_value;
-}
-
-static PyObject *
-getargs_w_star(PyObject *self, PyObject *args)
-{
-    Py_buffer buffer;
-    PyObject *result;
-    char *str;
-
-    if (!PyArg_ParseTuple(args, "w*:getargs_w_star", &buffer))
-        return NULL;
-
-    if (2 <= buffer.len) {
-        str = buffer.buf;
-        str[0] = '[';
-        str[buffer.len-1] = ']';
-    }
-
-    result = PyBytes_FromStringAndSize(buffer.buf, buffer.len);
-    PyBuffer_Release(&buffer);
-    return result;
-}
-
-
-static PyObject *
-test_empty_argparse(PyObject *self, PyObject *Py_UNUSED(ignored))
-{
-    /* Test that formats can begin with '|'. See issue #4720. */
-    PyObject *tuple, *dict = NULL;
-    static char *kwlist[] = {NULL};
-    int result;
-    tuple = PyTuple_New(0);
-    if (!tuple)
-        return NULL;
-    if (!(result = PyArg_ParseTuple(tuple, "|:test_empty_argparse"))) {
-        goto done;
-    }
-    dict = PyDict_New();
-    if (!dict)
-        goto done;
-    result = PyArg_ParseTupleAndKeywords(tuple, dict, "|:test_empty_argparse", kwlist);
-  done:
-    Py_DECREF(tuple);
-    Py_XDECREF(dict);
-    if (!result) {
-        return NULL;
-    }
-    else {
-        Py_RETURN_NONE;
-    }
-}
-
 /* Simple test of _PyLong_NumBits and _PyLong_Sign. */
 static PyObject *
 test_long_numbits(PyObject *self, PyObject *Py_UNUSED(ignored))
@@ -6108,8 +5369,6 @@ unwatch_type(PyObject *self, PyObject *args)
 
 
 static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
-static PyObject *getargs_s_hash_int(PyObject *, PyObject *, PyObject*);
-static PyObject *getargs_s_hash_int2(PyObject *, PyObject *, PyObject*);
 
 static PyMethodDef TestMethods[] = {
     {"raise_exception",         raise_exception,                 METH_VARARGS},
@@ -6159,9 +5418,6 @@ static PyMethodDef TestMethods[] = {
     {"test_long_as_unsigned_long_long_mask",
         test_long_as_unsigned_long_long_mask, METH_NOARGS},
     {"test_long_numbits",       test_long_numbits,               METH_NOARGS},
-    {"test_k_code",             test_k_code,                     METH_NOARGS},
-    {"test_empty_argparse",     test_empty_argparse,             METH_NOARGS},
-    {"parse_tuple_and_keywords", parse_tuple_and_keywords, METH_VARARGS},
     {"pyobject_repr_from_null", pyobject_repr_from_null, METH_NOARGS},
     {"pyobject_str_from_null",  pyobject_str_from_null, METH_NOARGS},
     {"pyobject_bytes_from_null", pyobject_bytes_from_null, METH_NOARGS},
@@ -6177,66 +5433,11 @@ static PyMethodDef TestMethods[] = {
     {"PyBuffer_SizeFromFormat",  test_PyBuffer_SizeFromFormat,   METH_VARARGS},
     {"test_buildvalue_N",        test_buildvalue_N,              METH_NOARGS},
     {"test_buildvalue_issue38913", test_buildvalue_issue38913,   METH_NOARGS},
-    {"get_args",                  get_args,                      METH_VARARGS},
     {"test_get_statictype_slots", test_get_statictype_slots,     METH_NOARGS},
     {"test_get_type_name",        test_get_type_name,            METH_NOARGS},
     {"test_get_type_qualname",    test_get_type_qualname,        METH_NOARGS},
-    {"get_kwargs", _PyCFunction_CAST(get_kwargs),
-      METH_VARARGS|METH_KEYWORDS},
-    {"getargs_tuple",           getargs_tuple,                   METH_VARARGS},
-    {"getargs_keywords", _PyCFunction_CAST(getargs_keywords),
-      METH_VARARGS|METH_KEYWORDS},
-    {"getargs_keyword_only", _PyCFunction_CAST(getargs_keyword_only),
-      METH_VARARGS|METH_KEYWORDS},
-    {"getargs_positional_only_and_keywords",
-      _PyCFunction_CAST(getargs_positional_only_and_keywords),
-      METH_VARARGS|METH_KEYWORDS},
-    {"getargs_b",               getargs_b,                       METH_VARARGS},
-    {"getargs_B",               getargs_B,                       METH_VARARGS},
-    {"getargs_h",               getargs_h,                       METH_VARARGS},
-    {"getargs_H",               getargs_H,                       METH_VARARGS},
-    {"getargs_I",               getargs_I,                       METH_VARARGS},
-    {"getargs_k",               getargs_k,                       METH_VARARGS},
-    {"getargs_i",               getargs_i,                       METH_VARARGS},
-    {"getargs_l",               getargs_l,                       METH_VARARGS},
-    {"getargs_n",               getargs_n,                       METH_VARARGS},
-    {"getargs_p",               getargs_p,                       METH_VARARGS},
-    {"getargs_L",               getargs_L,                       METH_VARARGS},
-    {"getargs_K",               getargs_K,                       METH_VARARGS},
     {"test_longlong_api",       test_longlong_api,               METH_NOARGS},
     {"test_long_long_and_overflow",test_long_long_and_overflow,  METH_NOARGS},
-    {"test_L_code",             test_L_code,                     METH_NOARGS},
-    {"getargs_f",               getargs_f,                       METH_VARARGS},
-    {"getargs_d",               getargs_d,                       METH_VARARGS},
-    {"getargs_D",               getargs_D,                       METH_VARARGS},
-    {"getargs_S",               getargs_S,                       METH_VARARGS},
-    {"getargs_Y",               getargs_Y,                       METH_VARARGS},
-    {"getargs_U",               getargs_U,                       METH_VARARGS},
-    {"getargs_c",               getargs_c,                       METH_VARARGS},
-    {"getargs_C",               getargs_C,                       METH_VARARGS},
-    {"getargs_s",               getargs_s,                       METH_VARARGS},
-    {"getargs_s_star",          getargs_s_star,                  METH_VARARGS},
-    {"getargs_s_hash",          getargs_s_hash,                  METH_VARARGS},
-    {"getargs_s_hash_int",      _PyCFunction_CAST(getargs_s_hash_int),
-      METH_VARARGS|METH_KEYWORDS},
-    {"getargs_s_hash_int2",      _PyCFunction_CAST(getargs_s_hash_int2),
-      METH_VARARGS|METH_KEYWORDS},
-    {"getargs_z",               getargs_z,                       METH_VARARGS},
-    {"getargs_z_star",          getargs_z_star,                  METH_VARARGS},
-    {"getargs_z_hash",          getargs_z_hash,                  METH_VARARGS},
-    {"getargs_y",               getargs_y,                       METH_VARARGS},
-    {"getargs_y_star",          getargs_y_star,                  METH_VARARGS},
-    {"getargs_y_hash",          getargs_y_hash,                  METH_VARARGS},
-    {"getargs_u",               getargs_u,                       METH_VARARGS},
-    {"getargs_u_hash",          getargs_u_hash,                  METH_VARARGS},
-    {"getargs_Z",               getargs_Z,                       METH_VARARGS},
-    {"getargs_Z_hash",          getargs_Z_hash,                  METH_VARARGS},
-    {"getargs_w_star",          getargs_w_star,                  METH_VARARGS},
-    {"getargs_es",              getargs_es,                      METH_VARARGS},
-    {"getargs_et",              getargs_et,                      METH_VARARGS},
-    {"getargs_es_hash",         getargs_es_hash,                 METH_VARARGS},
-    {"getargs_et_hash",         getargs_et_hash,                 METH_VARARGS},
-    {"test_s_code",             test_s_code,                     METH_NOARGS},
     {"_test_thread_state",      test_thread_state,               METH_VARARGS},
     {"_pending_threadfunc",     pending_threadfunc,              METH_VARARGS},
 #ifdef HAVE_GETTIMEOFDAY
@@ -7227,6 +6428,9 @@ PyInit__testcapi(void)
     if (_PyTestCapi_Init_Unicode(m) < 0) {
         return NULL;
     }
+    if (_PyTestCapi_Init_GetArgs(m) < 0) {
+        return NULL;
+    }
 
 #ifndef LIMITED_API_AVAILABLE
     PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_False);
@@ -7284,35 +6488,3 @@ test_buildvalue_issue38913(PyObject *self, PyObject *Py_UNUSED(ignored))
 
     Py_RETURN_NONE;
 }
-
-#undef PyArg_ParseTupleAndKeywords
-PyAPI_FUNC(int) PyArg_ParseTupleAndKeywords(PyObject *, PyObject *,
-                                            const char *, char **, ...);
-
-static PyObject *
-getargs_s_hash_int(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    static char *keywords[] = {"", "", "x", NULL};
-    Py_buffer buf = {NULL};
-    const char *s;
-    int len;
-    int i = 0;
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "w*|s#i", keywords, &buf, &s, &len, &i))
-        return NULL;
-    PyBuffer_Release(&buf);
-    Py_RETURN_NONE;
-}
-
-static PyObject *
-getargs_s_hash_int2(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    static char *keywords[] = {"", "", "x", NULL};
-    Py_buffer buf = {NULL};
-    const char *s;
-    int len;
-    int i = 0;
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "w*|(s#)i", keywords, &buf, &s, &len, &i))
-        return NULL;
-    PyBuffer_Release(&buf);
-    Py_RETURN_NONE;
-}
diff --git a/PCbuild/_testcapi.vcxproj b/PCbuild/_testcapi.vcxproj
index b7d40c8cdc30..fc9e1591330f 100644
--- a/PCbuild/_testcapi.vcxproj
+++ b/PCbuild/_testcapi.vcxproj
@@ -94,6 +94,7 @@
   </PropertyGroup>
   <ItemGroup>
     <ClCompile Include="..\Modules\_testcapimodule.c" />
+    <ClCompile Include="..\Modules\_testcapi\getargs.c" />
     <ClCompile Include="..\Modules\_testcapi\vectorcall.c" />
     <ClCompile Include="..\Modules\_testcapi\vectorcall_limited.c" />
     <ClCompile Include="..\Modules\_testcapi\heaptype.c" />
diff --git a/PCbuild/_testcapi.vcxproj.filters b/PCbuild/_testcapi.vcxproj.filters
index fc2c4345fe14..fd936a69d284 100644
--- a/PCbuild/_testcapi.vcxproj.filters
+++ b/PCbuild/_testcapi.vcxproj.filters
@@ -12,6 +12,9 @@
     <ClCompile Include="..\Modules\_testcapimodule.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\Modules\_testcapi\getargs.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\Modules\_testcapi\vectorcall.c">
       <Filter>Source Files</Filter>
     </ClCompile>



More information about the Python-checkins mailing list