diff options
author | Larry Hastings <larry@hastings.org> | 2012-03-20 20:06:16 (GMT) |
---|---|---|
committer | Larry Hastings <larry@hastings.org> | 2012-03-20 20:06:16 (GMT) |
commit | 83a9f4869958f992b2964404f43dcc596c5a7892 (patch) | |
tree | 2fcd7a09a5b14d67ead54dd827872d9cecff75b5 /Python/getargs.c | |
parent | 2a886412ba8d7a197c55b15aa2d89530c0a2f68a (diff) | |
download | cpython-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.c | 34 |
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); |