-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
C API: Support "nullable" parameter types in PyArg_Parse* #112068
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
It turned out, that it is much more simpler to implement this as a prefix operator than a suffix. It can even be more efficient in future. So the above example looks: int dir_fd = AT_FDCWD;
Py_ssize_t size = PY_SSIZE_T_MAX;
double speed = 0.0;
int sep = EOF;
int flag = -1;
if (!PyArg_ParseTuple(args, "?i?n?d?C?p", &dir_fd, &size, &speed, &sep, &flag)) {
return NULL;
} |
I feel suffixes are easier to understand and many languages use the |
I created a PoC a long time ago, but had doubts about prefix vs suffix. Prefix only requires adding several lines of code in one place: if (*format == '?') {
format++;
if (arg == Py_None) {
msg = skipitem(&format, p_va, flags);
if (msg == NULL) {
*p_format = format;
}
else {
levels[0] = 0;
}
return msg;
}
flags |= FLAG_NULLABLE;
} and simple changes in 30+ other places are only needed to make the error messages better. Suffix requires to make additional complex changes in 20-40 places. |
#121303 is an alternative implementation of |
The discussion in the linked issue showed that this feature was highly controversial. What changed that made this non-controversial? |
To me, it is two things:
The rest of the discussion looks to me as a pure bikeshedding -- whether it should be called "nullable" or "Noneable" or whatever. |
Feature or enhancement
Some builtin functions accept None as a special value in addition to values that should have the specified type. For example
start
andstop
indices inindex()
,size
inread()
,dir_fd
in manyos
functions, and numerous string parameters, e.g.encoding
anderrors
.There are special format units in
PyArg_Parse*
functions for "string or None":z
,z*
,z#
. There is half-public converter_PyEval_SliceIndex
for indices, and several more private converters. But while NULL can non-ambiguously represent None in C, there is no single integer value for None. In many cases it is -1, but it is 0 andPy_SIZE(self)
for indices,AT_FDCWD
fordir_fd
parameter, etc. This is why_PyEval_SliceIndex
keeps the value of the C variable unchanged when the argument is None.I propose to generalize it to all types. Add the
?
modifier. If it occurs after the format unit, and the argument is None, it keeps the initial value of the C variable, like if the argument was optional and missed. For example:The code accepts two integers, a float, a character, and an arbitrary object (as boolean), but any of 5 arguments can also be
None
, in which case the corresponding variable keeps its initial value.There was a similar proposition for Argument Clinic: #64540. But this proposition works not only with Argument Clinic, therefore it can be used in third-party code. It works not only with integers, but with all types, including custom converters. It is more convenient, because do not need to use a special structure. I believe that it covers most of use cases, and in few remaining cases you still can handle it manually, as before.
After implementing this for
PyArg_Parse*
I will add support in Argument Clinic.Linked PRs
The text was updated successfully, but these errors were encountered: