@@ -1700,8 +1700,15 @@ static PyObject *
1700
1700
gen_reduce (PyGenObject * gen )
1701
1701
{
1702
1702
PyObject * tup ;
1703
- PyObject * frame_reducer ;
1704
- frame_reducer = slp_reduce_frame (gen -> gi_frame );
1703
+ PyObject * frame_reducer = (PyObject * )gen -> gi_frame ;
1704
+ if (frame_reducer == NULL ) {
1705
+ /* Pickle NULL as None. See gen_setstate() for the corresponding
1706
+ * unpickling code. */
1707
+ Py_INCREF (Py_None );
1708
+ frame_reducer = Py_None ;
1709
+ } else {
1710
+ frame_reducer = slp_reduce_frame (gen -> gi_frame );
1711
+ }
1705
1712
if (frame_reducer == NULL )
1706
1713
return NULL ;
1707
1714
tup = Py_BuildValue ("(O()(OiOO))" ,
@@ -1736,6 +1743,7 @@ gen_setstate(PyObject *self, PyObject *args)
1736
1743
{
1737
1744
PyGenObject * gen = (PyGenObject * ) self ;
1738
1745
PyFrameObject * f ;
1746
+ PyObject * obj ;
1739
1747
int gi_running ;
1740
1748
PyObject * name = NULL ;
1741
1749
PyObject * qualname = NULL ;
@@ -1745,12 +1753,50 @@ gen_setstate(PyObject *self, PyObject *args)
1745
1753
if ((args = unwrap_frame_arg (args )) == NULL ) /* now args is a counted ref! */
1746
1754
return NULL ;
1747
1755
1748
- if (!PyArg_ParseTuple (args , "O!i |OO:generator" ,
1749
- & PyFrame_Type , & f , & gi_running , & name , & qualname )) {
1756
+ if (!PyArg_ParseTuple (args , "Oi |OO:generator" ,
1757
+ & obj , & gi_running , & name , & qualname )) {
1750
1758
Py_DECREF (args );
1751
1759
return NULL ;
1752
1760
}
1753
- Py_DECREF (args );
1761
+
1762
+ if (obj == Py_None ) {
1763
+ /* No frame, generator is exhausted */
1764
+ Py_CLEAR (gen -> gi_frame );
1765
+
1766
+ /* Even if gi_frame is NULL, gi_code is still valid. Therefore
1767
+ * I set it to the code of the exhausted frame singleton.
1768
+ */
1769
+ assert (gen_exhausted_frame != NULL );
1770
+ assert (PyFrame_Check (gen_exhausted_frame ));
1771
+ obj = (PyObject * )gen_exhausted_frame -> f_code ;
1772
+ Py_INCREF (obj );
1773
+ Py_SETREF (gen -> gi_code , obj );
1774
+
1775
+ gen -> gi_running = gi_running ;
1776
+ if (name == NULL ) {
1777
+ name = gen_exhausted_frame -> f_code -> co_name ;
1778
+ assert (name != NULL );
1779
+ }
1780
+ if (qualname == NULL ) {
1781
+ qualname = name ;
1782
+ }
1783
+ Py_INCREF (name );
1784
+ Py_SETREF (gen -> gi_name , name );
1785
+ Py_INCREF (qualname );
1786
+ Py_SETREF (gen -> gi_qualname , qualname );
1787
+ Py_TYPE (gen ) = Py_TYPE (gen )-> tp_base ;
1788
+ Py_INCREF (gen );
<
8000
/td>
1789
+ Py_DECREF (args ); /* holds the obj ref */
1790
+ return (PyObject * )gen ;
1791
+ }
1792
+ if (!PyFrame_Check (obj )) {
1793
+ PyErr_SetString (PyExc_TypeError ,
1794
+ "invalid frame object for gen_setstate" );
1795
+ Py_DECREF (args ); /* holds the obj ref */
1796
+ return NULL ;
1797
+ }
1798
+ f = (PyFrameObject * )obj ;
1799
+ obj = NULL ;
1754
1800
1755
1801
if (name == NULL ) {
1756
1802
name = f -> f_code -> co_name ;
@@ -1768,6 +1814,7 @@ gen_setstate(PyObject *self, PyObject *args)
1768
1814
if ((tmpgen = (PyGenObject * )
1769
1815
PyGen_NewWithQualName (f , NULL , NULL )) == NULL ) {
1770
1816
Py_DECREF (f );
1817
+ Py_DECREF (args ); /* holds the frame and name refs */
1771
1818
return NULL ;
1772
1819
}
1773
1820
Py_INCREF (f );
@@ -1790,6 +1837,7 @@ gen_setstate(PyObject *self, PyObject *args)
1790
1837
}
1791
1838
else
1792
1839
gen = NULL ;
1840
+ Py_DECREF (args ); /* holds the frame and name refs */
1793
1841
return (PyObject * ) gen ;
1794
1842
}
1795
1843
@@ -1811,6 +1859,7 @@ gen_setstate(PyObject *self, PyObject *args)
1811
1859
Py_SETREF (gen -> gi_qualname , qualname );
1812
1860
Py_TYPE (gen ) = Py_TYPE (gen )-> tp_base ;
1813
1861
Py_INCREF (gen );
1862
+ Py_DECREF (args ); /* holds the frame and name refs */
1814
1863
return (PyObject * )gen ;
1815
1864
}
1816
1865
0 commit comments