Skip to content

Commit 335747d

Browse files
committed
Fix starred tuple equality and pickling
1 parent b295a92 commit 335747d

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

Lib/test/test_genericalias.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,8 @@ def test_equality(self):
343343
self.assertEqual(list[int], list[int])
344344
self.assertEqual(dict[str, int], dict[str, int])
345345
self.assertEqual((*tuple[int],)[0], (*tuple[int],)[0])
346+
self.assertNotEqual(tuple[int], (*tuple[int],)[0])
347+
self.assertNotEqual(tuple[int], Unpack[tuple[int]])
346348
self.assertEqual(
347349
tuple[
348350
tuple( # Effectively the same as starring; TODO
@@ -394,6 +396,8 @@ def test_pickle(self):
394396
self.assertEqual(loaded.__origin__, alias.__origin__)
395397
self.assertEqual(loaded.__args__, alias.__args__)
396398
self.assertEqual(loaded.__parameters__, alias.__parameters__)
399+
if isinstance(alias, GenericAlias):
400+
self.assertEqual(loaded.__unpacked__, alias.__unpacked__)
397401

398402
def test_copy(self):
399403
class X(list):
@@ -419,11 +423,19 @@ def __deepcopy__(self, memo):
419423
self.assertEqual(copied.__parameters__, alias.__parameters__)
420424

421425
def test_unpack(self):
422-
alias = tuple[str, ...]
423-
self.assertIs(alias.__unpacked__, False)
424-
unpacked = (*alias,)[0]
426+
alias1 = tuple[str, ...]
427+
self.assertIs(alias1.__unpacked__, False)
428+
unpacked = (*alias1,)[0]
425429
self.assertIs(unpacked.__unpacked__, True)
426430

431+
# The third positional argument should control unpackedness.
432+
alias2 = GenericAlias(tuple, int)
433+
self.assertIs(alias2.__unpacked__, False)
434+
alias3 = GenericAlias(tuple, int, False)
435+
self.assertIs(alias3.__unpacked__, False)
436+
alias4 = GenericAlias(tuple, int, True)
437+
self.assertIs(alias4.__unpacked__, True)
438+
427439
def test_union(self):
428440
a = typing.Union[list[int], list[str]]
429441
self.assertEqual(a.__args__, (list[int], list[str]))

Objects/genericaliasobject.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,9 @@ ga_richcompare(PyObject *a, PyObject *b, int op)
567567

568568
gaobject *aa = (gaobject *)a;
569569
gaobject *bb = (gaobject *)b;
570+
if (aa->starred != bb->starred) {
571+
Py_RETURN_FALSE;
572+
}
570573
int eq = PyObject_RichCompareBool(aa->origin, bb->origin, Py_EQ);
571574
if (eq < 0) {
572575
return NULL;
@@ -604,8 +607,8 @@ static PyObject *
604607
ga_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
605608
{
606609
gaobject *alias = (gaobject *)self;
607-
return Py_BuildValue("O(OO)", Py_TYPE(alias),
608-
alias->origin, alias->args);
610+
return Py_BuildValue("O(OOb)", Py_TYPE(alias),
611+
alias->origin, alias->args, alias->starred);
609612
}
610613

611614
static PyObject *
@@ -685,7 +688,7 @@ static PyGetSetDef ga_properties[] = {
685688
* Returns 1 on success, 0 on failure.
686689
*/
687690
static inline int
688-
setup_ga(gaobject *alias, PyObject *origin, PyObject *args) {
691+
setup_ga(gaobject *alias, PyObject *origin, PyObject *args, bool starred) {
689692
if (!PyTuple_Check(args)) {
690693
args = PyTuple_Pack(1, args);
691694
if (args == NULL) {
@@ -700,6 +703,7 @@ setup_ga(gaobject *alias, PyObject *origin, PyObject *args) {
700703
alias->origin = origin;
701704
alias->args = args;
702705
alias->parameters = NULL;
706+
alias->starred = starred;
703707
alias->weakreflist = NULL;
704708

705709
if (PyVectorcall_Function(origin) != NULL) {
@@ -718,16 +722,26 @@ ga_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
718722
if (!_PyArg_NoKeywords("GenericAlias", kwds)) {
719723
return NULL;
720724
}
721-
if (!_PyArg_CheckPositional("GenericAlias", PyTuple_GET_SIZE(args), 2, 2)) {
725+
if (!_PyArg_CheckPositional("GenericAlias", PyTuple_GET_SIZE(args), 2, 3)) {
722726
return NULL;
723727
}
728+
724729
PyObject *origin = PyTuple_GET_ITEM(args, 0);
725730
PyObject *arguments = PyTuple_GET_ITEM(args, 1);
731+
732+
bool starred;
733+
if (PyTuple_Size(args) < 3) {
734+
starred = false;
735+
} else {
736+
PyObject *py_starred = PyTuple_GET_ITEM(args, 2);
737+
starred = PyLong_AsLong(py_starred);
738+
}
739+
726740
gaobject *self = (gaobject *)type->tp_alloc(type, 0);
727741
if (self == NULL) {
728742
return NULL;
729743
}
730-
if (!setup_ga(self, origin, arguments)) {
744+
if (!setup_ga(self, origin, arguments, starred)) {
731745
Py_DECREF(self);
732746
return NULL;
733747
}
@@ -837,7 +851,7 @@ Py_GenericAlias(PyObject *origin, PyObject *args)
837851
if (alias == NULL) {
838852
return NULL;
839853
}
840-
if (!setup_ga(alias, origin, args)) {
854+
if (!setup_ga(alias, origin, args, false)) {
841855
Py_DECREF(alias);
842856
return NULL;
843857
}

0 commit comments

Comments
 (0)