gh-141510: Change marshal version to 6 (#145551)

Fix SliceTestCase: test also that version 4 fails with ValueError.
This commit is contained in:
Victor Stinner 2026-03-06 10:23:11 +01:00 committed by GitHub
parent c3fb0d9d96
commit 4fce98a920
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 29 additions and 5 deletions

View file

@ -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
======= =============== ====================================================

View file

@ -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 *);

View file

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

View file

@ -0,0 +1,2 @@
:mod:`marshal` now supports :class:`frozendict` objects. The marshal format
version was increased to 6. Patch by Victor Stinner.

View file

@ -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) {

View file

@ -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 {