[Python-checkins] gh-93202: Always use %zd printf formatter (#93201)

vstinner webhook-mailer at python.org
Wed May 25 08:21:54 EDT 2022


https://github.com/python/cpython/commit/71d8775feeb647ae5003cfd466de7b58cd1bf269
commit: 71d8775feeb647ae5003cfd466de7b58cd1bf269
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2022-05-25T14:21:36+02:00
summary:

gh-93202: Always use %zd printf formatter (#93201)

Python now always use the ``%zu`` and ``%zd`` printf formats to
format a size_t or Py_ssize_t number. Building Python 3.12 requires a
C11 compiler, so these printf formats are now always supported.

* PyObject_Print() and _PyObject_Dump() now use the printf %zd format
  to display an object reference count.
* Update PY_FORMAT_SIZE_T comment.
* Remove outdated notes about the %zd format in PyBytes_FromFormat()
  and PyUnicode_FromFormat() documentations.
* configure no longer checks for the %zd format and no longer defines
  PY_FORMAT_SIZE_T macro in pyconfig.h.
* pymacconfig.h no longer undefines PY_FORMAT_SIZE_T: macOS 10.4 is
  no longer supported. Python 3.12 now requires macOS 10.6 (Snow
  Leopard) or newer.

files:
A Misc/NEWS.d/next/Build/2022-05-25-05-46-00.gh-issue-93202.T37jtj.rst
M Doc/c-api/bytes.rst
M Doc/c-api/unicode.rst
M Include/pymacconfig.h
M Include/pyport.h
M Modules/_ctypes/_ctypes.c
M Objects/object.c
M configure
M configure.ac
M pyconfig.h.in

diff --git a/Doc/c-api/bytes.rst b/Doc/c-api/bytes.rst
index 7617487a462d3..d62962cab45f6 100644
--- a/Doc/c-api/bytes.rst
+++ b/Doc/c-api/bytes.rst
@@ -58,9 +58,6 @@ called with a non-bytes parameter.
 
    .. % XXX: This should be exactly the same as the table in PyErr_Format.
    .. % One should just refer to the other.
-   .. % XXX: The descriptions for %zd and %zu are wrong, but the truth is complicated
-   .. % because not all compilers support the %z width modifier -- we fake it
-   .. % when necessary via interpolating PY_FORMAT_SIZE_T.
 
    .. tabularcolumns:: |l|l|L|
 
diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
index abcf0cd6c8790..5d420bfa93cb2 100644
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -397,10 +397,6 @@ APIs:
    ASCII-encoded string. The following format characters are allowed:
 
    .. % This should be exactly the same as the table in PyErr_Format.
-   .. % The descriptions for %zd and %zu are wrong, but the truth is complicated
-   .. % because not all compilers support the %z width modifier -- we fake it
-   .. % when necessary via interpolating PY_FORMAT_SIZE_T.
-   .. % Similar comments apply to the %ll width modifier and
 
    .. tabularcolumns:: |l|l|L|
 
diff --git a/Include/pymacconfig.h b/Include/pymacconfig.h
index 9dde11bd58e21..00459a03b980b 100644
--- a/Include/pymacconfig.h
+++ b/Include/pymacconfig.h
@@ -84,18 +84,6 @@
 # define HAVE_GCC_ASM_FOR_X87
 #endif
 
-    /*
-     * The definition in pyconfig.h is only valid on the OS release
-     * where configure ran on and not necessarily for all systems where
-     * the executable can be used on.
-     *
-     * Specifically: OSX 10.4 has limited supported for '%zd', while
-     * 10.5 has full support for '%zd'. A binary built on 10.5 won't
-     * work properly on 10.4 unless we suppress the definition
-     * of PY_FORMAT_SIZE_T
-     */
-#undef  PY_FORMAT_SIZE_T
-
 
 #endif /* defined(_APPLE__) */
 
diff --git a/Include/pyport.h b/Include/pyport.h
index 086ed4204e4ff..8e6763789115e 100644
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -186,32 +186,10 @@ typedef Py_ssize_t Py_ssize_clean_t;
 /* Largest possible value of size_t. */
 #define PY_SIZE_MAX SIZE_MAX
 
-/* Macro kept for backward compatibility: use "z" in new code.
+/* Macro kept for backward compatibility: use directly "z" in new code.
  *
- * PY_FORMAT_SIZE_T is a platform-specific modifier for use in a printf
- * format to convert an argument with the width of a size_t or Py_ssize_t.
- * C99 introduced "z" for this purpose, but old MSVCs had not supported it.
- * Since MSVC supports "z" since (at least) 2015, we can just use "z"
- * for new code.
- *
- * These "high level" Python format functions interpret "z" correctly on
- * all platforms (Python interprets the format string itself, and does whatever
- * the platform C requires to convert a size_t/Py_ssize_t argument):
- *
- *     PyBytes_FromFormat
- *     PyErr_Format
- *     PyBytes_FromFormatV
- *     PyUnicode_FromFormatV
- *
- * Lower-level uses require that you interpolate the correct format modifier
- * yourself (e.g., calling printf, fprintf, sprintf, PyOS_snprintf); for
- * example,
- *
- *     Py_ssize_t index;
- *     fprintf(stderr, "index %" PY_FORMAT_SIZE_T "d sucks\n", index);
- *
- * That will expand to %zd or to something else correct for a Py_ssize_t on
- * the platform.
+ * PY_FORMAT_SIZE_T is a modifier for use in a printf format to convert an
+ * argument with the width of a size_t or Py_ssize_t: "z" (C99).
  */
 #ifndef PY_FORMAT_SIZE_T
 #   define PY_FORMAT_SIZE_T "z"
diff --git a/Misc/NEWS.d/next/Build/2022-05-25-05-46-00.gh-issue-93202.T37jtj.rst b/Misc/NEWS.d/next/Build/2022-05-25-05-46-00.gh-issue-93202.T37jtj.rst
new file mode 100644
index 0000000000000..6018e400c15d9
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2022-05-25-05-46-00.gh-issue-93202.T37jtj.rst
@@ -0,0 +1,4 @@
+Python now always use the ``%zu`` and ``%zd`` printf formats to format a
+``size_t`` or ``Py_ssize_t`` number. Building Python 3.12 requires a C11
+compiler, so these printf formats are now always supported. Patch by Victor
+Stinner.
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index d6fa11d348130..2c629d76beb3b 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -396,9 +396,9 @@ _ctypes_alloc_format_string_with_shape(int ndim, const Py_ssize_t *shape,
         strcat(new_prefix, "(");
         for (k = 0; k < ndim; ++k) {
             if (k < ndim-1) {
-                sprintf(buf, "%"PY_FORMAT_SIZE_T"d,", shape[k]);
+                sprintf(buf, "%zd,", shape[k]);
             } else {
-                sprintf(buf, "%"PY_FORMAT_SIZE_T"d)", shape[k]);
+                sprintf(buf, "%zd)", shape[k]);
             }
             strcat(new_prefix, buf);
         }
diff --git a/Objects/object.c b/Objects/object.c
index 95045ed03d5db..49b1cba89b1d6 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -274,11 +274,8 @@ PyObject_Print(PyObject *op, FILE *fp, int flags)
     }
     else {
         if (Py_REFCNT(op) <= 0) {
-            /* XXX(twouters) cast refcount to long until %zd is
-               universally available */
             Py_BEGIN_ALLOW_THREADS
-            fprintf(fp, "<refcnt %ld at %p>",
-                (long)Py_REFCNT(op), (void *)op);
+            fprintf(fp, "<refcnt %zd at %p>", Py_REFCNT(op), (void *)op);
             Py_END_ALLOW_THREADS
         }
         else {
@@ -371,9 +368,7 @@ _PyObject_Dump(PyObject* op)
 
     /* first, write fields which are the least likely to crash */
     fprintf(stderr, "object address  : %p\n", (void *)op);
-    /* XXX(twouters) cast refcount to long until %zd is
-       universally available */
-    fprintf(stderr, "object refcount : %ld\n", (long)Py_REFCNT(op));
+    fprintf(stderr, "object refcount : %zd\n", Py_REFCNT(op));
     fflush(stderr);
 
     PyTypeObject *type = Py_TYPE(op);
diff --git a/configure b/configure
index 6fa4051310b12..c72fc4afdb9e6 100755
--- a/configure
+++ b/configure
@@ -21150,72 +21150,6 @@ then
 	LIBS="$LIBS -framework CoreFoundation"
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for %zd printf() format support" >&5
-$as_echo_n "checking for %zd printf() format support... " >&6; }
-if ${ac_cv_have_size_t_format+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  ac_cv_have_size_t_format="cross -- assuming yes"
-
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-#include <stdio.h>
-#include <stddef.h>
-#include <string.h>
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_SSIZE_T
-typedef ssize_t Py_ssize_t;
-#elif SIZEOF_VOID_P == SIZEOF_LONG
-typedef long Py_ssize_t;
-#else
-typedef int Py_ssize_t;
-#endif
-
-int main()
-{
-    char buffer[256];
-
-    if(sprintf(buffer, "%zd", (size_t)123) < 0)
-       	return 1;
-
-    if (strcmp(buffer, "123"))
-	return 1;
-
-    if (sprintf(buffer, "%zd", (Py_ssize_t)-123) < 0)
-       	return 1;
-
-    if (strcmp(buffer, "-123"))
-	return 1;
-
-    return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  ac_cv_have_size_t_format=yes
-else
-  ac_cv_have_size_t_format=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_size_t_format" >&5
-$as_echo "$ac_cv_have_size_t_format" >&6; }
-if test "$ac_cv_have_size_t_format" != no ; then
-
-$as_echo "#define PY_FORMAT_SIZE_T \"z\"" >>confdefs.h
-
-fi
-
 ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
diff --git a/configure.ac b/configure.ac
index bef4904325b52..a8d499df2f16d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6004,52 +6004,6 @@ then
 	LIBS="$LIBS -framework CoreFoundation"
 fi
 
-AC_CACHE_CHECK([for %zd printf() format support], ac_cv_have_size_t_format, [dnl
-AC_RUN_IFELSE([AC_LANG_SOURCE([[
-#include <stdio.h>
-#include <stddef.h>
-#include <string.h>
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_SSIZE_T
-typedef ssize_t Py_ssize_t;
-#elif SIZEOF_VOID_P == SIZEOF_LONG
-typedef long Py_ssize_t;
-#else
-typedef int Py_ssize_t;
-#endif
-
-int main()
-{
-    char buffer[256];
-
-    if(sprintf(buffer, "%zd", (size_t)123) < 0)
-       	return 1;
-
-    if (strcmp(buffer, "123"))
-	return 1;
-
-    if (sprintf(buffer, "%zd", (Py_ssize_t)-123) < 0)
-       	return 1;
-
-    if (strcmp(buffer, "-123"))
-	return 1;
-
-    return 0;
-}
-]])],
-  [ac_cv_have_size_t_format=yes],
-  [ac_cv_have_size_t_format=no],
-  [ac_cv_have_size_t_format="cross -- assuming yes"
-])])
-if test "$ac_cv_have_size_t_format" != no ; then
-  AC_DEFINE(PY_FORMAT_SIZE_T, "z",
-  [Define to printf format modifier for Py_ssize_t])
-fi
-
 AC_CHECK_TYPE(socklen_t,,
   AC_DEFINE(socklen_t,int,
             [Define to `int' if <sys/socket.h> does not define.]),[
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 383fd47dd43c8..b244ed233d63a 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -1506,9 +1506,6 @@
 /* Define if you want to coerce the C locale to a UTF-8 based locale */
 #undef PY_COERCE_C_LOCALE
 
-/* Define to printf format modifier for Py_ssize_t */
-#undef PY_FORMAT_SIZE_T
-
 /* Define to 1 to build the sqlite module with loadable extensions support. */
 #undef PY_SQLITE_ENABLE_LOAD_EXTENSION
 



More information about the Python-checkins mailing list