Pickle Reductions

pcapkit.utilities.pickle holds the pickle reductions several pcapkit classes share, so each is written once (#2714). ReduceAsProtocol2 lets a typing.Generic subclass or a class with __slots__ pickle under protocol 0 and 1, on GraalPy as on CPython; ReduceToName reduces a singleton to the module-level name holding it; ReduceToItems reduces a multi-valued mapping to a call of its class on its item pairs; and reduce_to() makes one instance reduce to a call of a given function. A pickle a class wrote before it took one of these still loads, and one it writes with it loads where the class still reduces by its own.

class pcapkit.utilities.pickle.ReduceAsProtocol2[source]

Bases: object

Mixin reducing an instance under every pickle protocol as protocol 2 does.

Below protocol 2, object.__reduce_ex__() hands the instance to copyreg._reduce_ex, which walks type(self).__mro__ for the first base that is not a heap type and, unless that base is object, calls it on the instance. Generic is a heap type on CPython, so the walk passes it. GraalPy builds Generic as a built-in, so the walk stops there and raises TypeError: typing.Generic() takes no arguments for any generic class with no reduction of its own (#2714). The same walk refuses a class with __slots__ and no __getstate__ of its own on every interpreter.

Protocol 2’s reduction reads the class and the instance state without that walk, slots included, and protocol 0 and 1 write it as an ordinary call of copyreg.__newobj__, restoring the instance through __new__ as protocol 2 does. The next __reduce_ex__ in the MRO builds it, so a base with a reduction of its own keeps it, as OrderedMultiInfo keeps OrderedMultiDict’s, and a subclass overriding __reduce__ keeps its own.

It goes before Generic among the bases, as on Info, Schema, ReassemblyBase and Deferred.

Added in version 1.6.0.

__reduce_ex__(protocol)[source]

Reduce as protocol 2 does, or as protocol does if higher.

Parameters:

protocol (SupportsIndex) – Pickle protocol in use.

Return type:

str | tuple[Any, ...]

Returns:

The reduction for protocol, or for protocol 2 below it.

class pcapkit.utilities.pickle.ReduceToName[source]

Bases: object

Mixin reducing a singleton to the module-level name that holds it.

__reduce__() returns _name, as Ellipsis.__reduce__() returns 'Ellipsis', so pickle stores the instance as a reference to that name in the class’s module and loads it back as the same object, at every protocol. A class using it sets _name to that name.

It is shared by every Sentinel and by the missing-value marker of pcapkit.corekit.multidict.

Added in version 1.6.0.

__reduce__()[source]

Reduce to _name, which pickle stores as a global reference.

Return type:

str

class pcapkit.utilities.pickle.ReduceToItems[source]

Bases: object

Mixin reducing a multi-valued mapping to a call of its class on its item pairs.

__reduce_ex__() returns (type(self), (pairs,)), the pairs being list(self.items(multi=True)), under every protocol. Rebuilding through the class keeps the order of interleaved keys and builds whatever the class keeps beside the pairs, and needs no state to be restored afterwards, which an immutable class refuses.

It is shared by OrderedMultiDict and MultiInfo.

Added in version 1.6.0.

__reduce_ex__(protocol)[source]

Reduce to a call of the class on the item pairs, under every protocol.

Parameters:

protocol (SupportsIndex) – Pickle protocol in use, which does not change the reduction.

Return type:

str | tuple[Any, ...]

Returns:

(type(self), (list(self.items(multi=True)),)).

pcapkit.utilities.pickle.reduce_to(obj, rebuild, *args)[source]

Make obj reduce to rebuild(*args) under pickle and copy.

The reduction goes on the instance, as obj.__reduce_ex__, which both pickle and copy honour, since each fetches it with getattr() on the object. That suits an object whose type reduces it wrongly, as Enum.__reduce_ex__ reduces an unregistered member to the one value lookup it is absent from. functools.partial() rather than a closure keeps obj out of its own reducer, so being reducible does not put it in a reference cycle.

It is shared by EnumRegistry._make_reducible and EnumField._unregistered_member.

Parameters:
  • obj (_T) – The object to make reducible.

  • rebuild (Callable[..., Any]) – A module-level callable, which every pickle protocol can name, rebuilding an equivalent object from args.

  • *args (Any) – The arguments to rebuild.

Return type:

_T

Returns:

obj, for use as a return expression.

Added in version 1.6.0.

pcapkit.utilities.pickle._reduce_to(rebuild, args, protocol)[source]

The __reduce_ex__ reduce_to() installs, bound to its first two arguments.

Parameters:
  • rebuild (Callable[..., Any]) – The callable to rebuild through.

  • args (tuple[Any, ...]) – Its arguments.

  • protocol (int) – Pickle protocol in use, ignored; copy passes 4.

Return type:

tuple[Callable[..., Any], tuple[Any, ...]]

Returns:

(rebuild, args).