gh-87390: Fix starred tuple equality and pickling#92249
gh-87390: Fix starred tuple equality and pickling#92249mrahtz wants to merge 5 commits intopython:mainfrom
Conversation
b808ffd to
335747d
Compare
|
I think this is worth a NEWS entry; it's been a while since we put the rest of this code into main. I'll review the PR now. |
JelleZijlstra
left a comment
There was a problem hiding this comment.
Thanks! I'm a little unhappy about making unpacked a public argument to the constructor, but I'm not sure how else we'd get pickling to work.
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
I've added a NEWS entry for this specific change, but just to double check - were you thinking of this specific change, or the rest of the PEP 646-related changes we made to |
Just for this change (the PR title would be good as a NEWS entry too). |
| "must be a bool (since it's a flag controlling " | ||
| "whether the alias is unpacked)"); |
There was a problem hiding this comment.
| "must be a bool (since it's a flag controlling " | |
| "whether the alias is unpacked)"); | |
| "must be a bool"); |
We don't need the explanation.
Fidget-Spinner
left a comment
There was a problem hiding this comment.
Great work! We're pretty close.
| PyObject *starred = PyBool_FromLong(alias->starred); | ||
| PyObject *value = Py_BuildValue("O(OOO)", Py_TYPE(alias), | ||
| alias->origin, alias->args, starred); | ||
| // Avoid double increment of reference count on Py_True/Py_False - once from | ||
| // PyBool_FromLong, and once from Py_BuildValue. | ||
| Py_CLEAR(starred); | ||
| return value; |
There was a problem hiding this comment.
How about:
| PyObject *starred = PyBool_FromLong(alias->starred); | |
| PyObject *value = Py_BuildValue("O(OOO)", Py_TYPE(alias), | |
| alias->origin, alias->args, starred); | |
| // Avoid double increment of reference count on Py_True/Py_False - once from | |
| // PyBool_FromLong, and once from Py_BuildValue. | |
| Py_CLEAR(starred); | |
| return value; | |
| PyObject *starred = alias->starred ? Py_True : Py_False; | |
| return Py_BuildValue("O(OOO)", Py_TYPE(alias), | |
| alias->origin, alias->args, starred); | |
BTW, if you don't want to use the code above, you can avoid the double incref by using the format string O(OON). N doesn't incref. https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue
| return NULL; | ||
| } | ||
| if (!_PyArg_CheckPositional("GenericAlias", PyTuple_GET_SIZE(args), 2, 2)) { | ||
| if (!_PyArg_CheckPositional("GenericAlias", PyTuple_GET_SIZE(args), 2, 3)) { |
There was a problem hiding this comment.
Please update the creation signature in the docs https://docs.python.org/3/library/types.html#types.GenericAlias.
Also, this doesn't break backwards compatibility right? IIUC, the two-argument form will still work.
| PyObject *origin = PyTuple_GET_ITEM(args, 0); | ||
| PyObject *arguments = PyTuple_GET_ITEM(args, 1); | ||
|
|
There was a problem hiding this comment.
This code has gotten complex enough that I recommend using https://docs.python.org/3/c-api/arg.html#c.PyArg_ParseTuple or https://docs.python.org/3/c-api/arg.html#c.PyArg_UnpackTuple instead to parse our arguments for us.
The format value list is on that page. But off the top of my head, it should be OO|O:GenericAlias. Then you keep your bool checking/error raising code below.
There was a problem hiding this comment.
Argument clinic can also be used here.
| "whether the alias is unpacked)"); | ||
| return NULL; | ||
| } | ||
| starred = PyLong_AsLong(py_starred); |
There was a problem hiding this comment.
I'm surprised you don't need to cast to (bool) here (or maybe it's implicit, I don't remember how C treats this).
|
Azure pipelines patcheck fail is unrelated, I will fix it on main. |
Nevermind, it seems that 65f88a6 fixed the whitespace issues, so this just needs updating from main. |
serhiy-storchaka
left a comment
There was a problem hiding this comment.
I do not like an idea about extending GenericAlias() with the third parameter. It is a public API.
I'll provide an alternate PR.
|
See #92337. |
|
Looks like this can be closed since the alternative was already merged. |
Hilariously, before this PR, it turned out that
*tuple[int]was equal totuple[int]. Fixing it, I realised that pickling was also broken: it didn't preservegaobject.starred. This PR fixes both.I've tested for refleaks with
python3 -m test -v test_genericalias -R 3:3, and it came back clean, so I think we're good.@Fidget-Spinner I guess you're the one most familiar with this code? :)