diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index 65fda9e469b..77f3da40c06 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -667,10 +667,13 @@ class TestSetSubclass(TestSet): self = super().__new__(cls, arg) self.newarg = newarg return self - u = subclass_with_new([1, 2], newarg=3) + u = subclass_with_new([1, 2]) self.assertIs(type(u), subclass_with_new) self.assertEqual(set(u), {1, 2}) - self.assertEqual(u.newarg, 3) + self.assertIsNone(u.newarg) + # disallow kwargs in __new__ only (https://bugs.python.org/issue43413#msg402000) + with self.assertRaises(TypeError): + subclass_with_new([1, 2], newarg=3) class TestFrozenSet(TestJointOps, unittest.TestCase): diff --git a/Misc/NEWS.d/3.11.0a1.rst b/Misc/NEWS.d/3.11.0a1.rst index 28b81b75266..fa30c693c34 100644 --- a/Misc/NEWS.d/3.11.0a1.rst +++ b/Misc/NEWS.d/3.11.0a1.rst @@ -1140,7 +1140,7 @@ blocks. Patch by Pablo Galindo. Constructors of subclasses of some builtin classes (e.g. :class:`tuple`, :class:`list`, :class:`frozenset`) no longer accept arbitrary keyword -arguments. Subclass of :class:`set` can now define a ``__new__()`` method +arguments. [reverted in 3.11a4] Subclass of :class:`set` can now define a ``__new__()`` method with additional keyword parameters without overriding also ``__init__()``. .. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-05-30-16-37-47.bpo-43413.vYFPPC1.rst b/Misc/NEWS.d/next/Core and Builtins/2021-05-30-16-37-47.bpo-43413.vYFPPC1.rst new file mode 100644 index 00000000000..cf879eceeb7 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-05-30-16-37-47.bpo-43413.vYFPPC1.rst @@ -0,0 +1 @@ +Revert changes in ``set.__init__``. Subclass of :class:`set` needs to define a ``__init__()`` method if it defines a ``__new__()`` method with additional keyword parameters. diff --git a/Objects/setobject.c b/Objects/setobject.c index 0be067857d6..6e110ef196c 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1946,9 +1946,7 @@ set_init(PySetObject *self, PyObject *args, PyObject *kwds) { PyObject *iterable = NULL; - if ((Py_IS_TYPE(self, &PySet_Type) || - Py_TYPE(self)->tp_new == PySet_Type.tp_new) && - !_PyArg_NoKeywords("set", kwds)) + if (!_PyArg_NoKeywords("set", kwds)) return -1; if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable)) return -1;