Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-87390: Fix starred tuple equality and pickling #92249

Closed
wants to merge 5 commits into from

Conversation

mrahtz
Copy link
Contributor

@mrahtz mrahtz commented May 3, 2022

Hilariously, before this PR, it turned out that *tuple[int] was equal to tuple[int]. Fixing it, I realised that pickling was also broken: it didn't preserve gaobject.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? :)

@JelleZijlstra
Copy link
Member

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.

Copy link
Member

@JelleZijlstra JelleZijlstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@mrahtz
Copy link
Contributor Author

mrahtz commented May 3, 2022

I think this is worth a NEWS entry; it's been a while since we put the rest of this code into main.

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 genericaliasobject.c recently? (I had to check, but we did have something in the NEWS for 3.11.0a7 saying that we "Allow unpacking types.GenericAlias objects".)

@JelleZijlstra
Copy link
Member

I think this is worth a NEWS entry; it's been a while since we put the rest of this code into main.

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 genericaliasobject.c recently? (I had to check, but we did have something in the NEWS for 3.11.0a7 saying that we "Allow unpacking types.GenericAlias objects".)

Just for this change (the PR title would be good as a NEWS entry too).

Comment on lines +745 to +746
"must be a bool (since it's a flag controlling "
"whether the alias is unpacked)");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"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.

@JelleZijlstra JelleZijlstra self-assigned this May 3, 2022
Copy link
Member

@Fidget-Spinner Fidget-Spinner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! We're pretty close.

Comment on lines +610 to +616
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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

Suggested change
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

@@ -718,16 +727,33 @@ ga_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (!_PyArg_NoKeywords("GenericAlias", kwds)) {
return NULL;
}
if (!_PyArg_CheckPositional("GenericAlias", PyTuple_GET_SIZE(args), 2, 2)) {
if (!_PyArg_CheckPositional("GenericAlias", PyTuple_GET_SIZE(args), 2, 3)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines 734 to +736
PyObject *origin = PyTuple_GET_ITEM(args, 0);
PyObject *arguments = PyTuple_GET_ITEM(args, 1);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Argument clinic can also be used here.

"whether the alias is unpacked)");
return NULL;
}
starred = PyLong_AsLong(py_starred);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

@Fidget-Spinner
Copy link
Member

Azure pipelines patcheck fail is unrelated, I will fix it on main.

@Fidget-Spinner
Copy link
Member

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.

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not like an idea about extending GenericAlias() with the third parameter. It is a public API.

I'll provide an alternate PR.

@serhiy-storchaka
Copy link
Member

See #92337.

@carljm
Copy link
Member

carljm commented May 7, 2022

Looks like this can be closed since the alternative was already merged.

@carljm carljm closed this May 7, 2022
@mrahtz mrahtz deleted the unpacked-tuple-equality branch May 7, 2022 11:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants