]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-129813, PEP 782: Use PyBytesWriter in fcntl (#138921)
authorVictor Stinner <vstinner@python.org>
Mon, 15 Sep 2025 14:21:43 +0000 (15:21 +0100)
committerGitHub <noreply@github.com>
Mon, 15 Sep 2025 14:21:43 +0000 (16:21 +0200)
Replace PyBytes_FromStringAndSize(NULL, size) with the new public
PyBytesWriter API.

Don't build the fcntl with the limited C API anymore, since
the PyBytesWriter API is not part of the limited C API.

Modules/clinic/fcntlmodule.c.h
Modules/fcntlmodule.c

index 005e9b9e12afd92737d1f35662874d45ff5574f3..2b61d9f87083f08e3c6d1c5470a8f124f9953355 100644 (file)
@@ -2,6 +2,8 @@
 preserve
 [clinic start generated code]*/
 
+#include "pycore_modsupport.h"    // _PyArg_CheckPositional()
+
 PyDoc_STRVAR(fcntl_fcntl__doc__,
 "fcntl($module, fd, cmd, arg=0, /)\n"
 "--\n"
@@ -19,7 +21,7 @@ PyDoc_STRVAR(fcntl_fcntl__doc__,
 "corresponding to the return value of the fcntl call in the C code.");
 
 #define FCNTL_FCNTL_METHODDEF    \
-    {"fcntl", (PyCFunction)(void(*)(void))fcntl_fcntl, METH_FASTCALL, fcntl_fcntl__doc__},
+    {"fcntl", _PyCFunction_CAST(fcntl_fcntl), METH_FASTCALL, fcntl_fcntl__doc__},
 
 static PyObject *
 fcntl_fcntl_impl(PyObject *module, int fd, int code, PyObject *arg);
@@ -32,12 +34,7 @@ fcntl_fcntl(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     int code;
     PyObject *arg = NULL;
 
-    if (nargs < 2) {
-        PyErr_Format(PyExc_TypeError, "fcntl expected at least 2 arguments, got %zd", nargs);
-        goto exit;
-    }
-    if (nargs > 3) {
-        PyErr_Format(PyExc_TypeError, "fcntl expected at most 3 arguments, got %zd", nargs);
+    if (!_PyArg_CheckPositional("fcntl", nargs, 2, 3)) {
         goto exit;
     }
     fd = PyObject_AsFileDescriptor(args[0]);
@@ -93,7 +90,7 @@ PyDoc_STRVAR(fcntl_ioctl__doc__,
 "code.");
 
 #define FCNTL_IOCTL_METHODDEF    \
-    {"ioctl", (PyCFunction)(void(*)(void))fcntl_ioctl, METH_FASTCALL, fcntl_ioctl__doc__},
+    {"ioctl", _PyCFunction_CAST(fcntl_ioctl), METH_FASTCALL, fcntl_ioctl__doc__},
 
 static PyObject *
 fcntl_ioctl_impl(PyObject *module, int fd, unsigned long code, PyObject *arg,
@@ -108,12 +105,7 @@ fcntl_ioctl(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     PyObject *arg = NULL;
     int mutate_arg = 1;
 
-    if (nargs < 2) {
-        PyErr_Format(PyExc_TypeError, "ioctl expected at least 2 arguments, got %zd", nargs);
-        goto exit;
-    }
-    if (nargs > 4) {
-        PyErr_Format(PyExc_TypeError, "ioctl expected at most 4 arguments, got %zd", nargs);
+    if (!_PyArg_CheckPositional("ioctl", nargs, 2, 4)) {
         goto exit;
     }
     fd = PyObject_AsFileDescriptor(args[0]);
@@ -121,7 +113,7 @@ fcntl_ioctl(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
         goto exit;
     }
     if (!PyIndex_Check(args[1])) {
-        PyErr_Format(PyExc_TypeError, "ioctl() argument 2 must be int, not %T", args[1]);
+        _PyArg_BadArgument("ioctl", "argument 2", "int", args[1]);
         goto exit;
     }
     {
@@ -168,7 +160,7 @@ PyDoc_STRVAR(fcntl_flock__doc__,
 "function is emulated using fcntl()).");
 
 #define FCNTL_FLOCK_METHODDEF    \
-    {"flock", (PyCFunction)(void(*)(void))fcntl_flock, METH_FASTCALL, fcntl_flock__doc__},
+    {"flock", _PyCFunction_CAST(fcntl_flock), METH_FASTCALL, fcntl_flock__doc__},
 
 static PyObject *
 fcntl_flock_impl(PyObject *module, int fd, int code);
@@ -180,8 +172,7 @@ fcntl_flock(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     int fd;
     int code;
 
-    if (nargs != 2) {
-        PyErr_Format(PyExc_TypeError, "flock expected 2 arguments, got %zd", nargs);
+    if (!_PyArg_CheckPositional("flock", nargs, 2, 2)) {
         goto exit;
     }
     fd = PyObject_AsFileDescriptor(args[0]);
@@ -226,7 +217,7 @@ PyDoc_STRVAR(fcntl_lockf__doc__,
 "    2 - relative to the end of the file (SEEK_END)");
 
 #define FCNTL_LOCKF_METHODDEF    \
-    {"lockf", (PyCFunction)(void(*)(void))fcntl_lockf, METH_FASTCALL, fcntl_lockf__doc__},
+    {"lockf", _PyCFunction_CAST(fcntl_lockf), METH_FASTCALL, fcntl_lockf__doc__},
 
 static PyObject *
 fcntl_lockf_impl(PyObject *module, int fd, int code, PyObject *lenobj,
@@ -242,12 +233,7 @@ fcntl_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     PyObject *startobj = NULL;
     int whence = 0;
 
-    if (nargs < 2) {
-        PyErr_Format(PyExc_TypeError, "lockf expected at least 2 arguments, got %zd", nargs);
-        goto exit;
-    }
-    if (nargs > 5) {
-        PyErr_Format(PyExc_TypeError, "lockf expected at most 5 arguments, got %zd", nargs);
+    if (!_PyArg_CheckPositional("lockf", nargs, 2, 5)) {
         goto exit;
     }
     fd = PyObject_AsFileDescriptor(args[0]);
@@ -279,4 +265,4 @@ skip_optional:
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=bf84289b741e7cf6 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=9773e44da302dc7c input=a9049054013a1b77]*/
index e49bf81b61f3bedb183a944ca4d0d788815c8276..df2c9994127997a72c8267ef6c1b0ef681707b76 100644 (file)
@@ -1,9 +1,8 @@
 /* fcntl module */
 
-// Need limited C API version 3.14 for PyLong_AsNativeBytes() in AC code
-#include "pyconfig.h"   // Py_GIL_DISABLED
-#ifndef Py_GIL_DISABLED
-#  define Py_LIMITED_API 0x030e0000
+// Argument Clinic uses the internal C API
+#ifndef Py_BUILD_CORE_BUILTIN
+#  define Py_BUILD_CORE_MODULE 1
 #endif
 
 #include "Python.h"
@@ -113,12 +112,12 @@ fcntl_fcntl_impl(PyObject *module, int fd, int code, PyObject *arg)
             return PyBytes_FromStringAndSize(buf, len);
         }
         else {
-            PyObject *result = PyBytes_FromStringAndSize(NULL, len);
-            if (result == NULL) {
+            PyBytesWriter *writer = PyBytesWriter_Create(len);
+            if (writer == NULL) {
                 PyBuffer_Release(&view);
                 return NULL;
             }
-            char *ptr = PyBytes_AsString(result);
+            char *ptr = PyBytesWriter_GetData(writer);
             memcpy(ptr, view.buf, len);
             PyBuffer_Release(&view);
 
@@ -131,15 +130,15 @@ fcntl_fcntl_impl(PyObject *module, int fd, int code, PyObject *arg)
                 if (!async_err) {
                     PyErr_SetFromErrno(PyExc_OSError);
                 }
-                Py_DECREF(result);
+                PyBytesWriter_Discard(writer);
                 return NULL;
             }
             if (ptr[len] != '\0') {
                 PyErr_SetString(PyExc_SystemError, "buffer overflow");
-                Py_DECREF(result);
+                PyBytesWriter_Discard(writer);
                 return NULL;
             }
-            return result;
+            return PyBytesWriter_Finish(writer);
         }
 #undef FCNTL_BUFSZ
     }
@@ -297,12 +296,12 @@ fcntl_ioctl_impl(PyObject *module, int fd, unsigned long code, PyObject *arg,
             return PyBytes_FromStringAndSize(buf, len);
         }
         else {
-            PyObject *result = PyBytes_FromStringAndSize(NULL, len);
-            if (result == NULL) {
+            PyBytesWriter *writer = PyBytesWriter_Create(len);
+            if (writer == NULL) {
                 PyBuffer_Release(&view);
                 return NULL;
             }
-            char *ptr = PyBytes_AsString(result);
+            char *ptr = PyBytesWriter_GetData(writer);
             memcpy(ptr, view.buf, len);
             PyBuffer_Release(&view);
 
@@ -315,15 +314,15 @@ fcntl_ioctl_impl(PyObject *module, int fd, unsigned long code, PyObject *arg,
                 if (!async_err) {
                     PyErr_SetFromErrno(PyExc_OSError);
                 }
-                Py_DECREF(result);
+                PyBytesWriter_Discard(writer);
                 return NULL;
             }
             if (ptr[len] != '\0') {
                 PyErr_SetString(PyExc_SystemError, "buffer overflow");
-                Py_DECREF(result);
+                PyBytesWriter_Discard(writer);
                 return NULL;
             }
-            return result;
+            return PyBytesWriter_Finish(writer);
         }
 #undef IOCTL_BUFSZ
     }