]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-155218: Generate the option group flags in a stable order (GH-155219)
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 5 Aug 2026 08:31:11 +0000 (11:31 +0300)
committerGitHub <noreply@github.com>
Wed, 5 Aug 2026 08:31:11 +0000 (08:31 +0000)
They were emitted in the iteration order of a set of group identifiers.
The identifiers of the groups before the required parameters are small
negative integers, -1 and -2 have the same hash, so their order depended
on the size of Py_hash_t, and the code generated on a 32-bit platform
differed from the checked in one.

They are now emitted in the order of the parameters.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Misc/NEWS.d/next/Tools-Demos/2026-08-05-14-02-55.gh-issue-155218.Nq4xZv.rst [new file with mode: 0644]
Modules/clinic/_cursesmodule.c.h
Tools/clinic/libclinic/clanguage.py

diff --git a/Misc/NEWS.d/next/Tools-Demos/2026-08-05-14-02-55.gh-issue-155218.Nq4xZv.rst b/Misc/NEWS.d/next/Tools-Demos/2026-08-05-14-02-55.gh-issue-155218.Nq4xZv.rst
new file mode 100644 (file)
index 0000000..909efc5
--- /dev/null
@@ -0,0 +1,2 @@
+Fix Argument Clinic generating the flags of the optional groups in
+different order on 32-bit and 64-bit platforms.
index dfd589ba45089e79e5ffdca7ecb37966553eb159..58087416796f8fc46dc8381233e7d208dba7c716 100644 (file)
@@ -247,8 +247,8 @@ _curses_window_addch(PyObject *self, PyObject *args)
             if (!PyArg_ParseTuple(args, "iiOO&:addch", &y, &x, &ch, attr_converter, &attr)) {
                 goto exit;
             }
-            group_right_1 = 1;
             group_left_1 = 1;
+            group_right_1 = 1;
             break;
         default:
             PyErr_SetString(PyExc_TypeError, "_curses.window.addch requires 1 to 4 arguments");
@@ -319,8 +319,8 @@ _curses_window_addstr(PyObject *self, PyObject *args)
             if (!PyArg_ParseTuple(args, "iiOO&:addstr", &y, &x, &str, attr_converter, &attr)) {
                 goto exit;
             }
-            group_right_1 = 1;
             group_left_1 = 1;
+            group_right_1 = 1;
             break;
         default:
             PyErr_SetString(PyExc_TypeError, "_curses.window.addstr requires 1 to 4 arguments");
@@ -394,8 +394,8 @@ _curses_window_addnstr(PyObject *self, PyObject *args)
             if (!PyArg_ParseTuple(args, "iiOiO&:addnstr", &y, &x, &str, &n, attr_converter, &attr)) {
                 goto exit;
             }
-            group_right_1 = 1;
             group_left_1 = 1;
+            group_right_1 = 1;
             break;
         default:
             PyErr_SetString(PyExc_TypeError, "_curses.window.addnstr requires 2 to 5 arguments");
@@ -1451,8 +1451,8 @@ _curses_window_hline(PyObject *self, PyObject *args)
             if (!PyArg_ParseTuple(args, "iiOiO&:hline", &y, &x, &ch, &n, attr_converter, &attr)) {
                 goto exit;
             }
-            group_right_1 = 1;
             group_left_1 = 1;
+            group_right_1 = 1;
             break;
         default:
             PyErr_SetString(PyExc_TypeError, "_curses.window.hline requires 2 to 5 arguments");
@@ -1521,8 +1521,8 @@ _curses_window_insch(PyObject *self, PyObject *args)
             if (!PyArg_ParseTuple(args, "iiOO&:insch", &y, &x, &ch, attr_converter, &attr)) {
                 goto exit;
             }
-            group_right_1 = 1;
             group_left_1 = 1;
+            group_right_1 = 1;
             break;
         default:
             PyErr_SetString(PyExc_TypeError, "_curses.window.insch requires 1 to 4 arguments");
@@ -1640,8 +1640,8 @@ _curses_window_insstr(PyObject *self, PyObject *args)
             if (!PyArg_ParseTuple(args, "iiOO&:insstr", &y, &x, &str, attr_converter, &attr)) {
                 goto exit;
             }
-            group_right_1 = 1;
             group_left_1 = 1;
+            group_right_1 = 1;
             break;
         default:
             PyErr_SetString(PyExc_TypeError, "_curses.window.insstr requires 1 to 4 arguments");
@@ -1717,8 +1717,8 @@ _curses_window_insnstr(PyObject *self, PyObject *args)
             if (!PyArg_ParseTuple(args, "iiOiO&:insnstr", &y, &x, &str, &n, attr_converter, &attr)) {
                 goto exit;
             }
-            group_right_1 = 1;
             group_left_1 = 1;
+            group_right_1 = 1;
             break;
         default:
             PyErr_SetString(PyExc_TypeError, "_curses.window.insnstr requires 2 to 5 arguments");
@@ -2328,8 +2328,8 @@ _curses_window_vline(PyObject *self, PyObject *args)
             if (!PyArg_ParseTuple(args, "iiOiO&:vline", &y, &x, &ch, &n, attr_converter, &attr)) {
                 goto exit;
             }
-            group_right_1 = 1;
             group_left_1 = 1;
+            group_right_1 = 1;
             break;
         default:
             PyErr_SetString(PyExc_TypeError, "_curses.window.vline requires 2 to 5 arguments");
@@ -6234,4 +6234,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored
 #ifndef _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
     #define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
 #endif /* !defined(_CURSES_ASSUME_DEFAULT_COLORS_METHODDEF) */
-/*[clinic end generated code: output=cb5525c88ae5c440 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=c1f85ec415c303bf input=a9049054013a1b77]*/
index a76fddb7602001e10664d9b762c3f349cf0310c2..3ee06307441fac4564fafc26332c0ec69f344d01 100644 (file)
@@ -341,7 +341,9 @@ class CLanguage(Language):
 """)
                 continue
 
-            group_ids = {p.group for p in subset}  # eliminate duplicates
+            # A set would eliminate duplicates too, but the iteration
+            # order of small negative integers depends on the platform.
+            group_ids = dict.fromkeys(p.group for p in subset)
             d: dict[str, str | int] = {}
             d['count'] = count
             d['name'] = f.name
@@ -356,7 +358,7 @@ class CLanguage(Language):
                 p.converter.parse_argument(parse_arguments)
             d['parse_arguments'] = ", ".join(parse_arguments)
 
-            group_ids.discard(0)
+            group_ids.pop(0, None)
             lines = "\n".join([
                 self.group_to_variable_name(g) + " = 1;"
                 for g in group_ids