@@ -119,14 +119,9 @@ static PyObject *extension_cache;
119119/* For looking up name pairs in copy_reg._extension_registry. */
120120static PyObject * two_tuple ;
121121
122- /* object.__reduce__, the default reduce callable. */
123- static PyObject * object_reduce ;
124-
125- /* copy_reg._better_reduce, the protocol 2 reduction function. */
126- static PyObject * better_reduce ;
127-
128122static PyObject * __class___str , * __getinitargs___str , * __dict___str ,
129123 * __getstate___str , * __setstate___str , * __name___str , * __reduce___str ,
124+ * __reduce_ex___str ,
130125 * write_str , * append_str ,
131126 * read_str , * readline_str , * __main___str , * __basicnew___str ,
132127 * copy_reg_str , * dispatch_table_str ;
@@ -2505,48 +2500,50 @@ save(Picklerobject *self, PyObject *args, int pers_save)
25052500 goto finally ;
25062501 }
25072502
2508- /* Get a reduction callable. This may come from
2509- * copy_reg.dispatch_table, the object's __reduce__ method,
2510- * the default object. __reduce__, or copy_reg._better_reduce .
2503+ /* Get a reduction callable, and call it . This may come from
2504+ * copy_reg.dispatch_table, the object's __reduce_ex__ method,
2505+ * or the object's __reduce__ method .
25112506 */
25122507 __reduce__ = PyDict_GetItem (dispatch_table , (PyObject * )type );
25132508 if (__reduce__ != NULL ) {
25142509 Py_INCREF (__reduce__ );
2510+ Py_INCREF (args );
2511+ ARG_TUP (self , args );
2512+ if (self -> arg ) {
2513+ t = PyObject_Call (__reduce__ , self -> arg , NULL );
2514+ FREE_ARG_TUP (self );
2515+ }
25152516 }
25162517 else {
2517- /* Check for a __reduce__ method.
2518- * Subtle: get the unbound method from the class, so that
2519- * protocol 2 can override the default __reduce__ that all
2520- * classes inherit from object.
2521- * XXX object.__reduce__ should really be rewritten so that
2522- * XXX we don't need to call back into Python code here
2523- * XXX (better_reduce), but no time to do that.
2524- */
2525- __reduce__ = PyObject_GetAttr ((PyObject * )type ,
2526- __reduce___str );
2527- if (__reduce__ == NULL ) {
2528- PyErr_Clear ();
2529- PyErr_SetObject (UnpickleableError , args );
2530- goto finally ;
2518+ /* Check for a __reduce_ex__ method. */
2519+ __reduce__ = PyObject_GetAttr (args , __reduce_ex___str );
2520+ if (__reduce__ != NULL ) {
2521+ t = PyInt_FromLong (self -> proto );
2522+ if (t != NULL ) {
2523+ ARG_TUP (self , t );
2524+ t = NULL ;
2525+ if (self -> arg ) {
2526+ t = PyObject_Call (__reduce__ ,
2527+ self -> arg , NULL );
2528+ FREE_ARG_TUP (self );
2529+ }
2530+ }
25312531 }
2532-
2533- if (self -> proto >= 2 && __reduce__ == object_reduce ) {
2534- /* Proto 2 can do better than the default. */
2535- Py_DECREF (__reduce__ );
2536- Py_INCREF (better_reduce );
2537- __reduce__ = better_reduce ;
2532+ else {
2533+ PyErr_Clear ();
2534+ /* Check for a __reduce__ method. */
2535+ __reduce__ = PyObject_GetAttr (args , __reduce___str );
2536+ if (__reduce__ != NULL ) {
2537+ t = PyObject_Call (__reduce__ ,
2538+ empty_tuple , NULL );
2539+ }
2540+ else {
2541+ PyErr_SetObject (UnpickleableError , args );
2542+ goto finally ;
2543+ }
25382544 }
25392545 }
25402546
2541- /* Call the reduction callable, setting t to the result. */
2542- assert (__reduce__ != NULL );
2543- assert (t == NULL );
2544- Py_INCREF (args );
2545- ARG_TUP (self , args );
2546- if (self -> arg ) {
2547- t = PyObject_Call (__reduce__ , self -> arg , NULL );
2548- FREE_ARG_TUP (self );
2549- }
25502547 if (t == NULL )
25512548 goto finally ;
25522549
@@ -5590,6 +5587,7 @@ init_stuff(PyObject *module_dict)
55905587 INIT_STR (__name__ );
55915588 INIT_STR (__main__ );
55925589 INIT_STR (__reduce__ );
5590+ INIT_STR (__reduce_ex__ );
55935591 INIT_STR (write );
55945592 INIT_STR (append );
55955593 INIT_STR (read );
@@ -5618,15 +5616,8 @@ init_stuff(PyObject *module_dict)
56185616 "_extension_cache" );
56195617 if (!extension_cache ) return -1 ;
56205618
5621- better_reduce = PyObject_GetAttrString (copy_reg , "_better_reduce" );
5622- if (!better_reduce ) return -1 ;
5623-
56245619 Py_DECREF (copy_reg );
56255620
5626- object_reduce = PyObject_GetAttrString ((PyObject * )& PyBaseObject_Type ,
5627- "__reduce__" );
5628- if (object_reduce == NULL ) return -1 ;
5629-
56305621 if (!(empty_tuple = PyTuple_New (0 )))
56315622 return -1 ;
56325623
0 commit comments