summaryrefslogtreecommitdiffstats
path: root/Python/getargs.c
diff options
context:
space:
mode:
authorLarry Hastings <larry@hastings.org>2012-03-20 20:06:16 (GMT)
committerLarry Hastings <larry@hastings.org>2012-03-20 20:06:16 (GMT)
commit83a9f4869958f992b2964404f43dcc596c5a7892 (patch)
tree2fcd7a09a5b14d67ead54dd827872d9cecff75b5 /Python/getargs.c
parent2a886412ba8d7a197c55b15aa2d89530c0a2f68a (diff)
downloadcpython-83a9f4869958f992b2964404f43dcc596c5a7892.zip
cpython-83a9f4869958f992b2964404f43dcc596c5a7892.tar.gz
cpython-83a9f4869958f992b2964404f43dcc596c5a7892.tar.bz2
Issue #14328: Add keyword-only parameters to PyArg_ParseTupleAndKeywords.
They're optional-only for now (unlike in pure Python) but that's all I needed. The syntax can easily be relaxed if we want to support required keyword-only arguments for extension types in the future.
Diffstat (limited to 'Python/getargs.c')
-rw-r--r--Python/getargs.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/Python/getargs.c b/Python/getargs.c
index 38c9dde..8ec7110 100644
--- a/Python/getargs.c
+++ b/Python/getargs.c
@@ -1403,6 +1403,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
int levels[32];
const char *fname, *msg, *custom_msg, *keyword;
int min = INT_MAX;
+ int max = INT_MAX;
int i, len, nargs, nkeywords;
PyObject *current_arg;
freelist_t freelist = {0, NULL};
@@ -1452,8 +1453,39 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
for (i = 0; i < len; i++) {
keyword = kwlist[i];
if (*format == '|') {
+ if (min != INT_MAX) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Invalid format string (| specified twice)");
+ return cleanreturn(0, &freelist);
+ }
+
min = i;
format++;
+
+ if (max != INT_MAX) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Invalid format string ($ before |)");
+ return cleanreturn(0, &freelist);
+ }
+ }
+ if (*format == '$') {
+ if (max != INT_MAX) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Invalid format string ($ specified twice)");
+ return cleanreturn(0, &freelist);
+ }
+
+ max = i;
+ format++;
+
+ if (max < nargs) {
+ PyErr_Format(PyExc_TypeError,
+ "Function takes %s %d positional arguments"
+ " (%d given)",
+ (min != INT_MAX) ? "at most" : "exactly",
+ max, nargs);
+ return cleanreturn(0, &freelist);
+ }
}
if (IS_END_OF_FORMAT(*format)) {
PyErr_Format(PyExc_RuntimeError,
@@ -1514,7 +1546,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
}
}
- if (!IS_END_OF_FORMAT(*format) && *format != '|') {
+ if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) {
PyErr_Format(PyExc_RuntimeError,
"more argument specifiers than keyword list entries "
"(remaining format:'%s')", format);