bpo-35900: Add a state_setter arg to save_reduce (GH-12588) · python/cpython@65d98d0 (original) (raw)

`@@ -3662,6 +3662,7 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)

`

3662

3662

`PyObject *state = NULL;

`

3663

3663

`PyObject *listitems = Py_None;

`

3664

3664

`PyObject *dictitems = Py_None;

`

``

3665

`+

PyObject *state_setter = Py_None;

`

3665

3666

`PickleState *st = _Pickle_GetGlobalState();

`

3666

3667

`Py_ssize_t size;

`

3667

3668

`int use_newobj = 0, use_newobj_ex = 0;

`

`@@ -3672,14 +3673,15 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)

`

3672

3673

`const char newobj_ex_op = NEWOBJ_EX;

`

3673

3674

``

3674

3675

`size = PyTuple_Size(args);

`

3675

``

`-

if (size < 2 || size > 5) {

`

``

3676

`+

if (size < 2 || size > 6) {

`

3676

3677

`PyErr_SetString(st->PicklingError, "tuple returned by "

`

3677

``

`-

"reduce must contain 2 through 5 elements");

`

``

3678

`+

"reduce must contain 2 through 6 elements");

`

3678

3679

`return -1;

`

3679

3680

` }

`

3680

3681

``

3681

``

`-

if (!PyArg_UnpackTuple(args, "save_reduce", 2, 5,

`

3682

``

`-

&callable, &argtup, &state, &listitems, &dictitems))

`

``

3682

`+

if (!PyArg_UnpackTuple(args, "save_reduce", 2, 6,

`

``

3683

`+

&callable, &argtup, &state, &listitems, &dictitems,

`

``

3684

`+

&state_setter))

`

3683

3685

`return -1;

`

3684

3686

``

3685

3687

`if (!PyCallable_Check(callable)) {

`

`@@ -3714,6 +3716,15 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)

`

3714

3716

`return -1;

`

3715

3717

` }

`

3716

3718

``

``

3719

`+

if (state_setter == Py_None)

`

``

3720

`+

state_setter = NULL;

`

``

3721

`+

else if (!PyCallable_Check(state_setter)) {

`

``

3722

`+

PyErr_Format(st->PicklingError, "sixth element of the tuple "

`

``

3723

`+

"returned by reduce must be a function, not %s",

`

``

3724

`+

Py_TYPE(state_setter)->tp_name);

`

``

3725

`+

return -1;

`

``

3726

`+

}

`

``

3727

+

3717

3728

`if (self->proto >= 2) {

`

3718

3729

`PyObject *name;

`

3719

3730

`_Py_IDENTIFIER(name);

`

`@@ -3933,11 +3944,32 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)

`

3933

3944

`return -1;

`

3934

3945

``

3935

3946

`if (state) {

`

3936

``

`-

if (save(self, state, 0) < 0 ||

`

3937

``

`-

_Pickler_Write(self, &build_op, 1) < 0)

`

3938

``

`-

return -1;

`

3939

``

`-

}

`

``

3947

`+

if (state_setter == NULL) {

`

``

3948

`+

if (save(self, state, 0) < 0 ||

`

``

3949

`+

_Pickler_Write(self, &build_op, 1) < 0)

`

``

3950

`+

return -1;

`

``

3951

`+

}

`

``

3952

`+

else {

`

``

3953

+

``

3954

`+

/* If a state_setter is specified, call it instead of load_build to

`

``

3955

`+

`

``

3956

`+

`

``

3957

`+

`

``

3958

`+

`

``

3959

`+

`

``

3960

`+

`

``

3961

`+

`

3940

3962

``

``

3963

`+

const char tupletwo_op = TUPLE2;

`

``

3964

`+

const char pop_op = POP;

`

``

3965

`+

if (save(self, state_setter, 0) < 0 ||

`

``

3966

`+

save(self, obj, 0) < 0 || save(self, state, 0) < 0 ||

`

``

3967

`+

_Pickler_Write(self, &tupletwo_op, 1) < 0 ||

`

``

3968

`+

_Pickler_Write(self, &reduce_op, 1) < 0 ||

`

``

3969

`+

_Pickler_Write(self, &pop_op, 1) < 0)

`

``

3970

`+

return -1;

`

``

3971

`+

}

`

``

3972

`+

}

`

3941

3973

`return 0;

`

3942

3974

`}

`

3943

3975

``