[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.126.4.2,2.126.4.3

Michael Hudson mwh@users.sourceforge.net
Sat, 16 Mar 2002 09:56:53 -0800


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv22040

Modified Files:
      Tag: release22-maint
	typeobject.c 
Log Message:
backport gvanrossum's checkin of
    revision 2.129 of typeobject.c

"Fix" for SF bug #520644: __slots__ are not pickled.

As promised in my response to the bug report, I'm not really fixing
it; in fact, one could argule over what the proper fix should do.
Instead, I'm adding a little magic that raises TypeError if you try to
pickle an instance of a class that has __slots__ but doesn't define or
override __getstate__.  This is done by adding a bozo __getstate__
that always raises TypeError.


Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.126.4.2
retrieving revision 2.126.4.3
diff -C2 -d -r2.126.4.2 -r2.126.4.3
*** typeobject.c	11 Mar 2002 10:19:48 -0000	2.126.4.2
--- typeobject.c	16 Mar 2002 17:56:51 -0000	2.126.4.3
***************
*** 851,854 ****
--- 851,869 ----
  };
  
+ /* bozo: __getstate__ that raises TypeError */
+ 
+ static PyObject *
+ bozo_func(PyObject *self, PyObject *args)
+ {
+ 	PyErr_SetString(PyExc_TypeError,
+ 			"a class that defines __slots__ without "
+ 			"defining __getstate__ cannot be pickled");
+ 	return NULL;
+ }
+ 
+ static PyMethodDef bozo_ml = {"__getstate__", bozo_func};
+ 
+ static PyObject *bozo_obj = NULL;
+ 
  static PyObject *
  type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
***************
*** 974,977 ****
--- 989,1013 ----
  		}
  	}
+ 	if (slots != NULL) {
+ 		/* See if *this* class defines __getstate__ */
+ 		PyObject *getstate = PyDict_GetItemString(dict,
+ 							  "__getstate__");
+ 		if (getstate == NULL) {
+ 			/* If not, provide a bozo that raises TypeError */
+ 			if (bozo_obj == NULL) {
+ 				bozo_obj = PyCFunction_New(&bozo_ml, NULL);
+ 				if (bozo_obj == NULL) {
+ 					/* XXX decref various things */
+ 					return NULL;
+ 				}
+ 			}
+ 			if (PyDict_SetItemString(dict,
+ 						 "__getstate__",
+ 						 bozo_obj) < 0) {
+ 				/* XXX decref various things */
+ 				return NULL;
+ 			}
+ 		}
+ 	}
  	if (slots == NULL && base->tp_dictoffset == 0 &&
  	    (base->tp_setattro == PyObject_GenericSetAttr ||
***************
*** 1655,1659 ****
  		if (descr == NULL)
  			return -1;
! 		if (PyDict_SetItemString(dict,meth->ml_name,descr) < 0)
  			return -1;
  		Py_DECREF(descr);
--- 1691,1695 ----
  		if (descr == NULL)
  			return -1;
! 		if (PyDict_SetItemString(dict,meth->ml_name, descr) < 0)
  			return -1;
  		Py_DECREF(descr);