summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErlend E. Aasland <erlend.aasland@protonmail.com>2022-11-14 21:23:41 (GMT)
committerGitHub <noreply@github.com>2022-11-14 21:23:41 (GMT)
commit3d9431983a89b14250716c1d227e2ce40b343bdd (patch)
tree77bd8caeef1695e8daebfd44f9fc8aea2c2f308a
parenta088290f9d53a6bd078de6ee67b2fa296fc1cc14 (diff)
downloadcpython-3d9431983a89b14250716c1d227e2ce40b343bdd.zip
cpython-3d9431983a89b14250716c1d227e2ce40b343bdd.tar.gz
cpython-3d9431983a89b14250716c1d227e2ce40b343bdd.tar.bz2
gh-93649: Split getargs tests from _testcapimodule.c (#99346)
-rw-r--r--Modules/Setup.stdlib.in2
-rw-r--r--Modules/_testcapi/getargs.c920
-rw-r--r--Modules/_testcapi/parts.h1
-rw-r--r--Modules/_testcapimodule.c834
-rw-r--r--PCbuild/_testcapi.vcxproj1
-rw-r--r--PCbuild/_testcapi.vcxproj.filters3
6 files changed, 929 insertions, 832 deletions
diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in
index 74d2222..b672ea9 100644
--- a/Modules/Setup.stdlib.in
+++ b/Modules/Setup.stdlib.in
@@ -169,7 +169,7 @@
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c
-@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c
+@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 0000000..25a8e5f
--- /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 304e592..25ee0f7 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 62fd1f6..0ab0b84 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 b7d40c8..fc9e159 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 fc2c434..fd936a6 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>