Skip to content

Automate positional arguments in clinic code #117868

Description

@nineteendo

Feature or enhancement

Problem:

It looks like we often forget to mark arguments as positional only in clinic input:

cpython/Modules/posixmodule.c

Lines 5470 to 5476 in 8fc953f

/*[clinic input]
os._path_normpath
path: object
Basic path normalization.
[clinic start generated code]*/

This causes a lot of overhead with no practical benefit (this function is even private):

#define OS__PATH_NORMPATH_METHODDEF \
{"_path_normpath", _PyCFunction_CAST(os__path_normpath), METH_FASTCALL|METH_KEYWORDS, os__path_normpath__doc__},
static PyObject *
os__path_normpath_impl(PyObject *module, PyObject *path);
static PyObject *
os__path_normpath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(path), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"path", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "_path_normpath",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *path;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
path = args[0];
return_value = os__path_normpath_impl(module, path);
exit:
return return_value;
}

If we wrote this instead:

/*[clinic input]
os._path_normpath

    path: object
    /

Basic path normalization.
[clinic start generated code]*/

The overhead is gone:

#define OS__PATH_NORMPATH_METHODDEF    \
    {"_path_normpath", (PyCFunction)os__path_normpath, METH_O, os__path_normpath__doc__},

No, I didn't forget to include the rest of the code, this is all the code!

Proposal:

Instead of manually updating all clinic input, we should modify clinic.py to do this automatically for functions without keyword arguments. If the old behaviour is desired, you should explicitly tell clinic.py that you want to support keyword arguments at the cost of performance:

/*[clinic input]
os._path_normpath

    /
    path: object

Basic path normalization.
[clinic start generated code]*/

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

No response

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions