From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:45:03 +0000 (+0000) Subject: gh-145118: Add `frozendict` support to `type()` (#145124) X-Git-Tag: v3.15.0a7~99 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f8d2f9fe67f8ab279cf7c5f6fa6a4feb588ce8f0;p=thirdparty%2FPython%2Fcpython.git gh-145118: Add `frozendict` support to `type()` (#145124) --- diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 7b69374b1868..eabfdcd447f2 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -2993,6 +2993,12 @@ class TestType(unittest.TestCase): A.__doc__ = doc self.assertEqual(A.__doc__, doc) + def test_type_frozendict(self): + A = type('A', (), frozendict({'x': 4, 'y': 2})) + self.assertEqual(A.x, 4) + self.assertEqual(A.y, 2) + self.assertEqual(A.__name__, 'A') + def test_bad_args(self): with self.assertRaises(TypeError): type() diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-19-05-03.gh-issue-145118.bU6Sic.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-19-05-03.gh-issue-145118.bU6Sic.rst new file mode 100644 index 000000000000..24507d4a411f --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-19-05-03.gh-issue-145118.bU6Sic.rst @@ -0,0 +1 @@ +:func:`type` now accepts :class:`frozendict` as an argument. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index ad26339c9c34..d77d981085f4 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4872,9 +4872,21 @@ type_new_get_slots(type_new_ctx *ctx, PyObject *dict) static PyTypeObject* type_new_init(type_new_ctx *ctx) { - PyObject *dict = PyDict_Copy(ctx->orig_dict); - if (dict == NULL) { - goto error; + PyObject *dict; + if (PyFrozenDict_Check(ctx->orig_dict)) { + dict = PyDict_New(); + if (dict == NULL) { + goto error; + } + if (PyDict_Merge(dict, ctx->orig_dict, 1) < 0) { + goto error; + } + } + else { + dict = PyDict_Copy(ctx->orig_dict); + if (dict == NULL) { + goto error; + } } if (type_new_get_slots(ctx, dict) < 0) { @@ -5037,13 +5049,19 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) /* Parse arguments: (name, bases, dict) */ PyObject *name, *bases, *orig_dict; - if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", + if (!PyArg_ParseTuple(args, "UO!O:type.__new__", &name, &PyTuple_Type, &bases, - &PyDict_Type, &orig_dict)) + &orig_dict)) { return NULL; } + if (!PyAnyDict_Check(orig_dict)) { + PyErr_Format(PyExc_TypeError, + "type.__new__() argument 3 must be dict or frozendict, not %T", + orig_dict); + return NULL; + } type_new_ctx ctx = { .metatype = metatype,