Skip to main content

Lib/copyreg.py

Source:

cpython 3.14 @ ab2d84fe1023/Lib/copyreg.py

copyreg provides the global dispatch table that pickle uses for extension types. It is the registration point for C extension types that need custom __reduce__ behavior. The module is small (94 lines) but central to the pickle protocol.

Map

LinesSymbolRole
1-25dispatch_table, _reconstructorGlobal dispatch table and default reconstructor
26-50pickleRegister a reduce function for a type
51-70constructorValidate and register a callable as a constructor
71-94__newobj__, __newobj_ex__Protocol 2/4 constructors

Reading

dispatch_table

dispatch_table is a dict mapping type objects to reduce functions. pickle.Pickler checks this table (and the object's own dispatch_table attribute) before calling __reduce_ex__.

# CPython: Lib/copyreg.py:12 dispatch_table
dispatch_table = {}

pickle

Registers a reduce function for a type. The reduce function must accept one argument (the object) and return a tuple in the __reduce__ protocol format.

# CPython: Lib/copyreg.py:31 pickle
def pickle(ob_type, pickle_function, constructor_ob=None):
if constructor_ob is not None:
constructor(constructor_ob)
dispatch_table[ob_type] = pickle_function

__newobj__ and __newobj_ex__

Used by pickle.Pickler to reconstruct objects using __new__ rather than __init__. Protocol 2 introduced __newobj__; protocol 4 introduced __newobj_ex__ which passes keyword arguments.

# CPython: Lib/copyreg.py:80 __newobj__
def __newobj__(cls, *args):
return cls.__new__(cls, *args)

def __newobj_ex__(cls, args, kwargs):
return cls.__new__(cls, *args, **kwargs)

When Pickler sees a __reduce_ex__ return value using __newobj__, it emits the NEWOBJ opcode, which calls cls.__new__(cls, *args) directly without going through Python dispatch during unpickling, making reconstruction faster.

_reconstructor

The fallback for old-style class reconstruction used when pickling instances that don't define __reduce__:

# CPython: Lib/copyreg.py:24 _reconstructor
def _reconstructor(cls, base, state):
if base is object:
obj = object.__new__(cls)
else:
obj = base.__new__(cls, state)
if base.__init__ != object.__init__:
base.__init__(obj, state)
return obj

gopy notes

Status: not yet ported. dispatch_table in gopy would be a map[*py.Type]py.Object (function). __newobj__ and __newobj_ex__ are simple wrappers and need to be registered as built-in functions visible to the pickle opcode decoder.