@@ -1706,8 +1706,15 @@ static PyObject *
1706
1706
gen_reduce (PyGenObject * gen )
1707
1707
{
1708
1708
PyObject * tup ;
1709
- PyObject * frame_reducer ;
1710
- frame_reducer = slp_reduce_frame (gen -> gi_frame );
1709
+ PyObject * frame_reducer = (PyObject * )gen -> gi_frame ;
1710
+ if (frame_reducer == NULL ) {
1711
+ /* Pickle NULL as None. See gen_setstate() for the corresponding
1712
+ * unpickling code. */
1713
+ Py_INCREF (Py_None );
1714
+ frame_reducer = Py_None ;
1715
+ } else {
1716
+ frame_reducer = slp_reduce_frame (gen -> gi_frame );
1717
+ }
1711
1718
if (frame_reducer == NULL )
1712
1719
return NULL ;
1713
1720
tup = Py_BuildValue ("(O()(OiOO))" ,
@@ -1742,6 +1749,7 @@ gen_setstate(PyObject *self, PyObject *args)
1742
1749
{
1743
1750
PyGenObject * gen = (PyGenObject * ) self ;
1744
1751
PyFrameObject * f ;
1752
+ PyObject * obj ;
1745
1753
int gi_running ;
1746
1754
PyObject * name = NULL ;
1747
1755
PyObject * qualname = NULL ;
@@ -1751,12 +1759,50 @@ gen_setstate(PyObject *self, PyObject *args)
1751
1759
if ((args = unwrap_frame_arg (args )) == NULL ) /* now args is a counted ref! */
1752
1760
return NULL ;
1753
1761
1754
- if (!PyArg_ParseTuple (args , "O!i |OO:generator" ,
1755
- & PyFrame_Type , & f , & gi_running , & name , & qualname )) {
1762
+ if (!PyArg_ParseTuple (args , "Oi |OO:generator" ,
1763
+ & obj , & gi_running , & name , & qualname )) {
1756
1764
Py_DECREF (args );
1757
1765
return NULL ;
1758
1766
}
1759
- Py_DECREF (args );
1767
+
1768
+ if (obj == Py_None ) {
1769
+ /* No frame, generator is exhausted */
1770
+ Py_CLEAR (gen -> gi_frame );
1771
+
1772
+ /* Even if gi_frame is NULL, gi_code is still valid. Therefore
1773
+ * I set it to the code of the exhausted frame singleton.
1774
+ */
1775
+ assert (gen_exhausted_frame != NULL );
1776
+ assert (PyFrame_Check (gen_exhausted_frame ));
1777
+ obj = (PyObject * )gen_exhausted_frame -> f_code ;
1778
+ Py_INCREF (obj );
1779
+ Py_SETREF (gen -> gi_code , obj );
1780
+
1781
+ gen -> gi_running = gi_running ;
1782
+ if (name == NULL ) {
1783
+ name = gen_exhausted_frame -> f_code -> co_name ;
1784
+ assert (name != NULL );
1785
+ }
1786
+ if (qualname == NULL ) {
1787
+ qualname = name ;
1788
+ }
1789
+ Py_INCREF (name );
1790
+ Py_SETREF (gen -> gi_name , name );
1791
+ Py_INCREF (qualname );
1792
+ Py_SETREF (gen -> gi_qualname , qualname );
1793
+ Py_TYPE (gen ) = Py_TYPE (gen )-> tp_base ;
1794
+ Py_INCREF (gen );
1795
+ Py_DECREF (args ); /* holds the obj ref */
1796
+ return (PyObject * )gen ;
1797
+ }
1798
+ if (!PyFrame_Check (obj )) {
1799
+ PyErr_SetString (PyExc_TypeError ,
1800
+ "invalid frame object for gen_setstate" );
1801
+ Py_DECREF (args ); /* holds the obj ref */
1802
+ return NULL ;
1803
+ }
1804
+ f = (PyFrameObject * )obj ;
1805
+ obj = NULL ;
1760
1806
1761
1807
if (name == NULL ) {
1762
1808
name = f -> f_code -> co_name ;
@@ -1774,6 +1820,7 @@ gen_setstate(PyObject *self, PyObject *args)
1774
1820
if ((tmpgen = (PyGenObject * )
1775
1821
PyGen_NewWithQualName (f , NULL , NULL )) == NULL ) {
1776
1822
Py_DECREF (f );
1823
+ Py_DECREF (args ); /* holds the frame and name refs */
1777
1824
return NULL ;
1778
1825
}
1779
1826
Py_INCREF (f );
@@ -1796,6 +1843,7 @@ gen_setstate(PyObject *self, PyObject *args)
1796
1843
}
1797
1844
else
1798
1845
gen = NULL ;
1846
+ Py_DECREF (args ); /* holds the frame and name refs */
1799
1847
return (PyObject * ) gen ;
1800
1848
}
1801
1849
@@ -1817,6 +1865,7 @@ gen_setstate(PyObject *self, PyObject *args)
1817
1865
Py_SETREF (gen -> gi_qualname , qualname );
1818
1866
Py_TYPE (gen ) = Py_TYPE (gen )-> tp_base ;
1819
1867
Py_INCREF (gen );
1868
+ Py_DECREF (args ); /* holds the frame and name refs */
1820
1869
return (PyObject * )gen ;
1821
1870
}
1822
1871
0 commit comments