https://github.com/python/cpython/commit/4fce98a920f47504e834057cd6606bad9b591ea9
commit: 4fce98a920f47504e834057cd6606bad9b591ea9
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-03-06T10:23:11+01:00
summary:
gh-141510: Change marshal version to 6 (#145551)
Fix SliceTestCase: test also that version 4 fails with ValueError.
files:
A Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst
M Doc/library/marshal.rst
M Include/cpython/marshal.h
M Lib/test/test_marshal.py
M Programs/_freeze_module.c
M Python/marshal.c
diff --git a/Doc/library/marshal.rst b/Doc/library/marshal.rst
index ed182ea24e8f3c..25902622b8730b 100644
--- a/Doc/library/marshal.rst
+++ b/Doc/library/marshal.rst
@@ -51,8 +51,9 @@ this module. The following types are supported:
* Strings (:class:`str`) and :class:`bytes`.
:term:`Bytes-like objects <bytes-like object>` like :class:`bytearray` are
marshalled as :class:`!bytes`.
-* Containers: :class:`tuple`, :class:`list`, :class:`set`, :class:`frozenset`,
- and (since :data:`version` 5), :class:`slice`.
+* Containers: :class:`tuple`, :class:`list`, :class:`dict`, :class:`frozendict`
+ (since :data:`version` 6), :class:`set`, :class:`frozenset`, and
+ :class:`slice` (since :data:`version` 5).
It should be understood that these are supported only if the values contained
therein are themselves supported.
Recursive containers are supported since :data:`version` 3.
@@ -71,6 +72,10 @@ this module. The following types are supported:
Added format version 5, which allows marshalling slices.
+.. versionchanged:: next
+
+ Added format version 6, which allows marshalling :class:`frozendict`.
+
The module defines these functions:
@@ -173,6 +178,8 @@ In addition, the following constants are defined:
4 Python 3.4 Efficient representation of short strings
------- --------------- ----------------------------------------------------
5 Python 3.14 Support for :class:`slice` objects
+ ------- --------------- ----------------------------------------------------
+ 6 Python 3.15 Support for :class:`frozendict` objects
======= =============== ====================================================
diff --git a/Include/cpython/marshal.h b/Include/cpython/marshal.h
index 6c1f7f96b6a2e8..159459fcaec3d9 100644
--- a/Include/cpython/marshal.h
+++ b/Include/cpython/marshal.h
@@ -6,7 +6,7 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(const
char *,
Py_ssize_t);
PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int);
-#define Py_MARSHAL_VERSION 5
+#define Py_MARSHAL_VERSION 6
PyAPI_FUNC(long) PyMarshal_ReadLongFromFile(FILE *);
PyAPI_FUNC(int) PyMarshal_ReadShortFromFile(FILE *);
diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py
index 28f24d0fc59cb0..78db4219e2997c 100644
--- a/Lib/test/test_marshal.py
+++ b/Lib/test/test_marshal.py
@@ -570,6 +570,15 @@ def testDict(self):
self.helper(dictobj)
self.helper3(dictobj)
+ def testFrozenDict(self):
+ for obj in self.keys:
+ dictobj = frozendict({"hello": obj, "goodbye": obj, obj: "hello"})
+ self.helper(dictobj)
+
+ for version in range(6):
+ with self.assertRaises(ValueError):
+ marshal.dumps(dictobj, version)
+
def testModule(self):
with open(__file__, "rb") as f:
code = f.read()
@@ -635,7 +644,7 @@ def test_slice(self):
with self.subTest(obj=str(obj)):
self.helper(obj)
- for version in range(4):
+ for version in range(5):
with self.assertRaises(ValueError):
marshal.dumps(obj, version)
diff --git
a/Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst
b/Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst
new file mode 100644
index 00000000000000..280a7b3632ddae
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst
@@ -0,0 +1,2 @@
+:mod:`marshal` now supports :class:`frozendict` objects. The marshal format
+version was increased to 6. Patch by Victor Stinner.
diff --git a/Programs/_freeze_module.c b/Programs/_freeze_module.c
index a5809b37b6b493..27a60171f3eca8 100644
--- a/Programs/_freeze_module.c
+++ b/Programs/_freeze_module.c
@@ -134,7 +134,7 @@ compile_and_marshal(const char *name, const char *text)
return NULL;
}
- assert(Py_MARSHAL_VERSION >= 5);
+ assert(Py_MARSHAL_VERSION >= 6);
PyObject *marshalled = PyMarshal_WriteObjectToString(code,
Py_MARSHAL_VERSION);
Py_CLEAR(code);
if (marshalled == NULL) {
diff --git a/Python/marshal.c b/Python/marshal.c
index a71909f103ebfc..59db6456552c35 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -580,6 +580,12 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
Py_ssize_t pos;
PyObject *key, *value;
if (PyFrozenDict_CheckExact(v)) {
+ if (p->version < 6) {
+ w_byte(TYPE_UNKNOWN, p);
+ p->error = WFERR_UNMARSHALLABLE;
+ return;
+ }
+
W_TYPE(TYPE_FROZENDICT, p);
}
else {
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]