aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Python/getargs.c
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.com>2024-02-12 07:53:52 +0300
committershadchin <shadchin@yandex-team.com>2024-02-12 08:07:36 +0300
commitce1b7ca3171f9158180640c6a02a74b4afffedea (patch)
treee47c1e8391b1b0128262c1e9b1e6ed4c8fff2348 /contrib/tools/python3/src/Python/getargs.c
parent57350d96f030db90f220ce50ee591d5c5d403df7 (diff)
downloadydb-ce1b7ca3171f9158180640c6a02a74b4afffedea.tar.gz
Update Python from 3.11.8 to 3.12.2
Diffstat (limited to 'contrib/tools/python3/src/Python/getargs.c')
-rw-r--r--contrib/tools/python3/src/Python/getargs.c326
1 files changed, 172 insertions, 154 deletions
diff --git a/contrib/tools/python3/src/Python/getargs.c b/contrib/tools/python3/src/Python/getargs.c
index e18d771992..066739f21f 100644
--- a/contrib/tools/python3/src/Python/getargs.c
+++ b/contrib/tools/python3/src/Python/getargs.c
@@ -1012,58 +1012,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
break;
}
- case 'u': /* raw unicode buffer (Py_UNICODE *) */
- case 'Z': /* raw unicode buffer or None */
- {
- if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
- "getargs: The '%c' format is deprecated. Use 'U' instead.", c)) {
- RETURN_ERR_OCCURRED;
- }
-_Py_COMP_DIAG_PUSH
-_Py_COMP_DIAG_IGNORE_DEPR_DECLS
- Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **);
-
- if (*format == '#') {
- /* "u#" or "Z#" */
- REQUIRE_PY_SSIZE_T_CLEAN;
- Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);
-
- if (c == 'Z' && arg == Py_None) {
- *p = NULL;
- *psize = 0;
- }
- else if (PyUnicode_Check(arg)) {
- Py_ssize_t len;
- *p = PyUnicode_AsUnicodeAndSize(arg, &len);
- if (*p == NULL)
- RETURN_ERR_OCCURRED;
- *psize = len;
- }
- else
- return converterr(c == 'Z' ? "str or None" : "str",
- arg, msgbuf, bufsize);
- format++;
- } else {
- /* "u" or "Z" */
- if (c == 'Z' && arg == Py_None)
- *p = NULL;
- else if (PyUnicode_Check(arg)) {
- Py_ssize_t len;
- *p = PyUnicode_AsUnicodeAndSize(arg, &len);
- if (*p == NULL)
- RETURN_ERR_OCCURRED;
- if (wcslen(*p) != (size_t)len) {
- PyErr_SetString(PyExc_ValueError, "embedded null character");
- RETURN_ERR_OCCURRED;
- }
- } else
- return converterr(c == 'Z' ? "str or None" : "str",
- arg, msgbuf, bufsize);
- }
- break;
-_Py_COMP_DIAG_POP
- }
-
case 'e': {/* encoded string */
char **buffer;
const char *encoding;
@@ -1098,8 +1046,7 @@ _Py_COMP_DIAG_POP
/* Encode object */
if (!recode_strings &&
(PyBytes_Check(arg) || PyByteArray_Check(arg))) {
- s = arg;
- Py_INCREF(s);
+ s = Py_NewRef(arg);
if (PyBytes_Check(arg)) {
size = PyBytes_GET_SIZE(s);
ptr = PyBytes_AS_STRING(s);
@@ -1899,133 +1846,214 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
}
-/* List of static parsers. */
-static struct _PyArg_Parser *static_arg_parsers = NULL;
-
static int
-parser_init(struct _PyArg_Parser *parser)
+scan_keywords(const char * const *keywords, int *ptotal, int *pposonly)
{
- const char * const *keywords;
- const char *format, *msg;
- int i, len, min, max, nkw;
- PyObject *kwtuple;
-
- assert(parser->keywords != NULL);
- if (parser->kwtuple != NULL) {
- return 1;
- }
-
- keywords = parser->keywords;
/* scan keywords and count the number of positional-only parameters */
+ int i;
for (i = 0; keywords[i] && !*keywords[i]; i++) {
}
- parser->pos = i;
+ *pposonly = i;
+
/* scan keywords and get greatest possible nbr of args */
for (; keywords[i]; i++) {
if (!*keywords[i]) {
PyErr_SetString(PyExc_SystemError,
"Empty keyword parameter name");
- return 0;
+ return -1;
}
}
- len = i;
+ *ptotal = i;
+ return 0;
+}
- format = parser->format;
- if (format) {
- /* grab the function name or custom error msg first (mutually exclusive) */
- parser->fname = strchr(parser->format, ':');
- if (parser->fname) {
- parser->fname++;
- parser->custom_msg = NULL;
+static int
+parse_format(const char *format, int total, int npos,
+ const char **pfname, const char **pcustommsg,
+ int *pmin, int *pmax)
+{
+ /* grab the function name or custom error msg first (mutually exclusive) */
+ const char *custommsg;
+ const char *fname = strchr(format, ':');
+ if (fname) {
+ fname++;
+ custommsg = NULL;
+ }
+ else {
+ custommsg = strchr(format,';');
+ if (custommsg) {
+ custommsg++;
}
- else {
- parser->custom_msg = strchr(parser->format,';');
- if (parser->custom_msg)
- parser->custom_msg++;
- }
-
- min = max = INT_MAX;
- for (i = 0; i < len; i++) {
- if (*format == '|') {
- if (min != INT_MAX) {
- PyErr_SetString(PyExc_SystemError,
- "Invalid format string (| specified twice)");
- return 0;
- }
- if (max != INT_MAX) {
- PyErr_SetString(PyExc_SystemError,
- "Invalid format string ($ before |)");
- return 0;
- }
- min = i;
- format++;
+ }
+
+ int min = INT_MAX;
+ int max = INT_MAX;
+ for (int i = 0; i < total; i++) {
+ if (*format == '|') {
+ if (min != INT_MAX) {
+ PyErr_SetString(PyExc_SystemError,
+ "Invalid format string (| specified twice)");
+ return -1;
}
- if (*format == '$') {
- if (max != INT_MAX) {
- PyErr_SetString(PyExc_SystemError,
- "Invalid format string ($ specified twice)");
- return 0;
- }
- if (i < parser->pos) {
- PyErr_SetString(PyExc_SystemError,
- "Empty parameter name after $");
- return 0;
- }
- max = i;
- format++;
+ if (max != INT_MAX) {
+ PyErr_SetString(PyExc_SystemError,
+ "Invalid format string ($ before |)");
+ return -1;
}
- if (IS_END_OF_FORMAT(*format)) {
- PyErr_Format(PyExc_SystemError,
- "More keyword list entries (%d) than "
- "format specifiers (%d)", len, i);
- return 0;
+ min = i;
+ format++;
+ }
+ if (*format == '$') {
+ if (max != INT_MAX) {
+ PyErr_SetString(PyExc_SystemError,
+ "Invalid format string ($ specified twice)");
+ return -1;
}
-
- msg = skipitem(&format, NULL, 0);
- if (msg) {
- PyErr_Format(PyExc_SystemError, "%s: '%s'", msg,
- format);
- return 0;
+ if (i < npos) {
+ PyErr_SetString(PyExc_SystemError,
+ "Empty parameter name after $");
+ return -1;
}
+ max = i;
+ format++;
}
- parser->min = Py_MIN(min, len);
- parser->max = Py_MIN(max, len);
-
- if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) {
+ if (IS_END_OF_FORMAT(*format)) {
PyErr_Format(PyExc_SystemError,
- "more argument specifiers than keyword list entries "
- "(remaining format:'%s')", format);
- return 0;
+ "More keyword list entries (%d) than "
+ "format specifiers (%d)", total, i);
+ return -1;
+ }
+
+ const char *msg = skipitem(&format, NULL, 0);
+ if (msg) {
+ PyErr_Format(PyExc_SystemError, "%s: '%s'", msg,
+ format);
+ return -1;
}
}
+ min = Py_MIN(min, total);
+ max = Py_MIN(max, total);
- nkw = len - parser->pos;
- kwtuple = PyTuple_New(nkw);
+ if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) {
+ PyErr_Format(PyExc_SystemError,
+ "more argument specifiers than keyword list entries "
+ "(remaining format:'%s')", format);
+ return -1;
+ }
+
+ *pfname = fname;
+ *pcustommsg = custommsg;
+ *pmin = min;
+ *pmax = max;
+ return 0;
+}
+
+static PyObject *
+new_kwtuple(const char * const *keywords, int total, int pos)
+{
+ int nkw = total - pos;
+ PyObject *kwtuple = PyTuple_New(nkw);
if (kwtuple == NULL) {
- return 0;
+ return NULL;
}
- keywords = parser->keywords + parser->pos;
- for (i = 0; i < nkw; i++) {
+ keywords += pos;
+ for (int i = 0; i < nkw; i++) {
PyObject *str = PyUnicode_FromString(keywords[i]);
if (str == NULL) {
Py_DECREF(kwtuple);
- return 0;
+ return NULL;
}
PyUnicode_InternInPlace(&str);
PyTuple_SET_ITEM(kwtuple, i, str);
}
+ return kwtuple;
+}
+
+static int
+_parser_init(struct _PyArg_Parser *parser)
+{
+ const char * const *keywords = parser->keywords;
+ assert(keywords != NULL);
+ assert(parser->pos == 0 &&
+ (parser->format == NULL || parser->fname == NULL) &&
+ parser->custom_msg == NULL &&
+ parser->min == 0 &&
+ parser->max == 0);
+
+ int len, pos;
+ if (scan_keywords(keywords, &len, &pos) < 0) {
+ return 0;
+ }
+
+ const char *fname, *custommsg = NULL;
+ int min = 0, max = 0;
+ if (parser->format) {
+ assert(parser->fname == NULL);
+ if (parse_format(parser->format, len, pos,
+ &fname, &custommsg, &min, &max) < 0) {
+ return 0;
+ }
+ }
+ else {
+ assert(parser->fname != NULL);
+ fname = parser->fname;
+ }
+
+ int owned;
+ PyObject *kwtuple = parser->kwtuple;
+ if (kwtuple == NULL) {
+ kwtuple = new_kwtuple(keywords, len, pos);
+ if (kwtuple == NULL) {
+ return 0;
+ }
+ owned = 1;
+ }
+ else {
+ owned = 0;
+ }
+
+ parser->pos = pos;
+ parser->fname = fname;
+ parser->custom_msg = custommsg;
+ parser->min = min;
+ parser->max = max;
parser->kwtuple = kwtuple;
+ parser->initialized = owned ? 1 : -1;
assert(parser->next == NULL);
- parser->next = static_arg_parsers;
- static_arg_parsers = parser;
+ parser->next = _PyRuntime.getargs.static_parsers;
+ _PyRuntime.getargs.static_parsers = parser;
return 1;
}
+static int
+parser_init(struct _PyArg_Parser *parser)
+{
+ // volatile as it can be modified by other threads
+ // and should not be optimized or reordered by compiler
+ if (*((volatile int *)&parser->initialized)) {
+ assert(parser->kwtuple != NULL);
+ return 1;
+ }
+ PyThread_acquire_lock(_PyRuntime.getargs.mutex, WAIT_LOCK);
+ // Check again if another thread initialized the parser
+ // while we were waiting for the lock.
+ if (*((volatile int *)&parser->initialized)) {
+ assert(parser->kwtuple != NULL);
+ PyThread_release_lock(_PyRuntime.getargs.mutex);
+ return 1;
+ }
+ int ret = _parser_init(parser);
+ PyThread_release_lock(_PyRuntime.getargs.mutex);
+ return ret;
+}
+
static void
parser_clear(struct _PyArg_Parser *parser)
{
- Py_CLEAR(parser->kwtuple);
+ if (parser->initialized == 1) {
+ Py_CLEAR(parser->kwtuple);
+ }
}
static PyObject*
@@ -2152,6 +2180,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,
}
format = parser->format;
+ assert(format != NULL || len == 0);
/* convert tuple args and keyword args in same loop, using kwtuple to drive process */
for (i = 0; i < len; i++) {
if (*format == '|') {
@@ -2542,8 +2571,7 @@ _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs,
/* copy tuple args */
for (i = 0; i < nargs; i++) {
if (i >= vararg) {
- Py_INCREF(args[i]);
- PyTuple_SET_ITEM(buf[vararg], i - vararg, args[i]);
+ PyTuple_SET_ITEM(buf[vararg], i - vararg, Py_NewRef(args[i]));
continue;
}
else {
@@ -2675,8 +2703,6 @@ skipitem(const char **p_format, va_list *p_va, int flags)
case 's': /* string */
case 'z': /* string or None */
case 'y': /* bytes */
- case 'u': /* unicode string */
- case 'Z': /* unicode string or None */
case 'w': /* buffer, read-write */
{
if (p_va != NULL) {
@@ -2834,11 +2860,7 @@ PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t m
stack = _PyTuple_ITEMS(args);
nargs = PyTuple_GET_SIZE(args);
-#ifdef HAVE_STDARG_PROTOTYPES
va_start(vargs, max);
-#else
- va_start(vargs);
-#endif
retval = unpack_stack(stack, nargs, name, min, max, vargs);
va_end(vargs);
return retval;
@@ -2851,11 +2873,7 @@ _PyArg_UnpackStack(PyObject *const *args, Py_ssize_t nargs, const char *name,
int retval;
va_list vargs;
-#ifdef HAVE_STDARG_PROTOTYPES
va_start(vargs, max);
-#else
- va_start(vargs);
-#endif
retval = unpack_stack(args, nargs, name, min, max, vargs);
va_end(vargs);
return retval;
@@ -2927,14 +2945,14 @@ _PyArg_NoKwnames(const char *funcname, PyObject *kwnames)
void
_PyArg_Fini(void)
{
- struct _PyArg_Parser *tmp, *s = static_arg_parsers;
+ struct _PyArg_Parser *tmp, *s = _PyRuntime.getargs.static_parsers;
while (s) {
tmp = s->next;
s->next = NULL;
parser_clear(s);
s = tmp;
}
- static_arg_parsers = NULL;
+ _PyRuntime.getargs.static_parsers = NULL;
}
#ifdef __cplusplus