summaryrefslogtreecommitdiffstats
path: root/Doc/library/pickle.rst
diff options
context:
space:
mode:
authorPierre Glaser <pierreglaser@msn.com>2019-05-08 21:08:25 (GMT)
committerAntoine Pitrou <antoine@python.org>2019-05-08 21:08:25 (GMT)
commit289f1f80ee87a4baf4567a86b3425fb3bf73291d (patch)
treeb8145681f26ca875572165d143c6f2e5bd1e8906 /Doc/library/pickle.rst
parent9a4135e939bc223f592045a38e0f927ba170da32 (diff)
downloadcpython-289f1f80ee87a4baf4567a86b3425fb3bf73291d.zip
cpython-289f1f80ee87a4baf4567a86b3425fb3bf73291d.tar.gz
cpython-289f1f80ee87a4baf4567a86b3425fb3bf73291d.tar.bz2
bpo-35900: Enable custom reduction callback registration in _pickle (GH-12499)
Enable custom reduction callback registration for functions and classes in _pickle.c, using the new Pickler's attribute ``reducer_override``.
Diffstat (limited to 'Doc/library/pickle.rst')
-rw-r--r--Doc/library/pickle.rst71
1 files changed, 71 insertions, 0 deletions
diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst
index 3d89536..55005f0 100644
--- a/Doc/library/pickle.rst
+++ b/Doc/library/pickle.rst
@@ -356,6 +356,18 @@ The :mod:`pickle` module exports two classes, :class:`Pickler` and
.. versionadded:: 3.3
+ .. method:: reducer_override(self, obj)
+
+ Special reducer that can be defined in :class:`Pickler` subclasses. This
+ method has priority over any reducer in the :attr:`dispatch_table`. It
+ should conform to the same interface as a :meth:`__reduce__` method, and
+ can optionally return ``NotImplemented`` to fallback on
+ :attr:`dispatch_table`-registered reducers to pickle ``obj``.
+
+ For a detailed example, see :ref:`reducer_override`.
+
+ .. versionadded:: 3.8
+
.. attribute:: fast
Deprecated. Enable fast mode if set to a true value. The fast mode
@@ -791,6 +803,65 @@ A sample usage might be something like this::
>>> new_reader.readline()
'3: Goodbye!'
+.. _reducer_override:
+
+Custom Reduction for Types, Functions, and Other Objects
+--------------------------------------------------------
+
+.. versionadded:: 3.8
+
+Sometimes, :attr:`~Pickler.dispatch_table` may not be flexible enough.
+In particular we may want to customize pickling based on another criterion
+than the object's type, or we may want to customize the pickling of
+functions and classes.
+
+For those cases, it is possible to subclass from the :class:`Pickler` class and
+implement a :meth:`~Pickler.reducer_override` method. This method can return an
+arbitrary reduction tuple (see :meth:`__reduce__`). It can alternatively return
+``NotImplemented`` to fallback to the traditional behavior.
+
+If both the :attr:`~Pickler.dispatch_table` and
+:meth:`~Pickler.reducer_override` are defined, then
+:meth:`~Pickler.reducer_override` method takes priority.
+
+.. Note::
+ For performance reasons, :meth:`~Pickler.reducer_override` may not be
+ called for the following objects: ``None``, ``True``, ``False``, and
+ exact instances of :class:`int`, :class:`float`, :class:`bytes`,
+ :class:`str`, :class:`dict`, :class:`set`, :class:`frozenset`, :class:`list`
+ and :class:`tuple`.
+
+Here is a simple example where we allow pickling and reconstructing
+a given class::
+
+ import io
+ import pickle
+
+ class MyClass:
+ my_attribute = 1
+
+ class MyPickler(pickle.Pickler):
+ def reducer_override(self, obj):
+ """Custom reducer for MyClass."""
+ if getattr(obj, "__name__", None) == "MyClass":
+ return type, (obj.__name__, obj.__bases__,
+ {'my_attribute': obj.my_attribute})
+ else:
+ # For any other object, fallback to usual reduction
+ return NotImplemented
+
+ f = io.BytesIO()
+ p = MyPickler(f)
+ p.dump(MyClass)
+
+ del MyClass
+
+ unpickled_class = pickle.loads(f.getvalue())
+
+ assert isinstance(unpickled_class, type)
+ assert unpickled_class.__name__ == "MyClass"
+ assert unpickled_class.my_attribute == 1
+
.. _pickle-restrict: