From ce616e4009af0766c2ed848c03a081f29630e807 Mon Sep 17 00:00:00 2001 From: Jeremy Hylton Date: Thu, 13 Aug 1998 23:13:52 +0000 Subject: Enter Jim Fulton's latest version. He writes: I had to make a slight diddle to work with Python 1.4, which we and some of our customers are still using. :( I've also made a few minor enhancements: - You can now both get and set the memo using a 'memo' attribute. This is handy for certain advanced applications that we have. - Added a 'binary' attribute to get and set the binary mode for a pickler. - Added a somewhat experimental 'fast' attribute. When this is set, objects are not placed in the memo during pickling. This should lead to faster pickling and smaller pickles in cases where: o you *know* there are no circular references, and o either you've: - preloaded the memo with class information by pickling classes in non-fast mode or by manipilating the memo directly, or - aren't pickling instances. --- Modules/cPickle.c | 100 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 20 deletions(-) diff --git a/Modules/cPickle.c b/Modules/cPickle.c index 3bb0c1f..bce3517 100644 --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -1,5 +1,5 @@ /* - cPickle.c,v 1.53 1998/05/05 15:41:31 jim Exp + cPickle.c,v 1.57 1998/08/12 12:13:28 jim Exp Copyright @@ -55,7 +55,7 @@ static char cPickle_module_documentation[] = "C implementation and optimization of the Python pickle module\n" "\n" -"cPickle.c,v 1.53 1998/05/05 15:41:31 jim Exp\n" +"cPickle.c,v 1.57 1998/08/12 12:13:28 jim Exp\n" ; #include "Python.h" @@ -147,6 +147,7 @@ typedef struct { PyObject *pers_func; PyObject *inst_pers_func; int bin; + int fast; /* Fast mode doesn't save in memo, don't use if circ ref */ int (*write_func)(); char *write_buf; int buf_size; @@ -507,8 +508,10 @@ get(Picklerobject *self, PyObject *id) { char s[30]; int len; - UNLESS(value = PyDict_GetItem(self->memo, id)) + UNLESS(value = PyDict_GetItem(self->memo, id)) { + PyErr_SetObject(PyExc_KeyError, id); return -1; + } UNLESS(value = PyTuple_GetItem(value, 0)) return -1; @@ -545,7 +548,7 @@ get(Picklerobject *self, PyObject *id) { static int put(Picklerobject *self, PyObject *ob) { - if (ob->ob_refcnt < 2) + if (ob->ob_refcnt < 2 || self->fast) return 0; return put2(self, ob); @@ -557,6 +560,9 @@ put2(Picklerobject *self, PyObject *ob) { char c_str[30]; int p, len, res = -1; PyObject *py_ob_id = 0, *memo_len = 0, *t = 0; + + if (self->fast) return 0; + if ((p = PyDict_Size(self->memo)) < 0) goto finally; @@ -675,10 +681,8 @@ whichmodule(PyObject *global, PyObject *global_name) { if (module) return module; PyErr_Clear(); - UNLESS(modules_dict = PySys_GetObject("modules")) { - PyErr_SetString(PyExc_SystemError, "lost sys.modules"); + UNLESS(modules_dict = PySys_GetObject("modules")) return NULL; - } i = 0; while ((j = PyDict_Next(modules_dict, &i, &name, &module))) { @@ -1762,6 +1766,7 @@ newPicklerobject(PyObject *file, int bin) { self->inst_pers_func = NULL; self->write_buf = NULL; self->bin = bin; + self->fast = 0; self->buf_size = 0; self->dispatch_table = NULL; @@ -1876,6 +1881,12 @@ Pickler_getattr(Picklerobject *self, char *name) { Py_INCREF(PicklingError); return PicklingError; } + + if(strcmp(name, "binary")==0) + return PyInt_FromLong(self->bin); + + if(strcmp(name, "fast")==0) + return PyInt_FromLong(self->fast); return Py_FindMethod(Pickler_methods, (PyObject *)self, name); } @@ -1883,6 +1894,13 @@ Pickler_getattr(Picklerobject *self, char *name) { int Pickler_setattr(Picklerobject *self, char *name, PyObject *value) { + + if(! value) { + PyErr_SetString(PyExc_TypeError, + "attribute deletion is not supported"); + return -1; + } + if (strcmp(name, "persistent_id") == 0) { Py_XDECREF(self->pers_func); self->pers_func = value; @@ -1897,6 +1915,27 @@ Pickler_setattr(Picklerobject *self, char *name, PyObject *value) { return 0; } + if (strcmp(name, "memo") == 0) { + if(! PyDict_Check(value)) { + PyErr_SetString(PyExc_TypeError, "memo must be a dictionary"); + return -1; + } + Py_XDECREF(self->memo); + self->memo = value; + Py_INCREF(value); + return 0; + } + + if(strcmp(name, "binary")==0) { + self->bin=PyObject_IsTrue(value); + return 0; + } + + if(strcmp(name, "fast")==0) { + self->fast=PyObject_IsTrue(value); + return 0; + } + PyErr_SetString(PyExc_AttributeError, name); return -1; } @@ -1952,15 +1991,14 @@ find_class(PyObject *py_module_name, PyObject *py_global_name) { if (global == NULL) { char buf[256 + 37]; sprintf(buf, "Failed to import class %.128s from moduile %.128s", - PyString_AS_STRING(py_global_name), - PyString_AS_STRING(py_module_name)); + PyString_AS_STRING((PyStringObject*)py_global_name), + PyString_AS_STRING((PyStringObject*)py_module_name)); PyErr_SetString(PyExc_SystemError, buf); return NULL; } return global; } - static int marker(Unpicklerobject *self) { if (self->num_marks < 1) { @@ -2539,8 +2577,8 @@ Instance_New(PyObject *cls, PyObject *args) { if (!has_key) if(!(safe = PyObject_GetAttr(cls, __safe_for_unpickling___str)) || !PyObject_IsTrue(safe)) { - cPickle_ErrFormat(UnpicklingError, - "%s is not safe for unpickling", "O", cls); + cPickle_ErrFormat(UnpicklingError, + "%s is not safe for unpickling", "O", cls); Py_XDECREF(safe); return NULL; } @@ -2864,8 +2902,10 @@ load_get(Unpicklerobject *self) { UNLESS(py_str = PyString_FromStringAndSize(s, len - 1)) goto finally; - UNLESS(value = PyDict_GetItem(self->memo, py_str)) + UNLESS(value = PyDict_GetItem(self->memo, py_str)) { + PyErr_SetObject(PyExc_KeyError, py_str); goto finally; + } if (PyList_Append(self->stack, value) < 0) goto finally; @@ -2894,8 +2934,10 @@ load_binget(Unpicklerobject *self) { UNLESS(py_key = PyInt_FromLong((long)key)) goto finally; - UNLESS(value = PyDict_GetItem(self->memo, py_key)) + UNLESS(value = PyDict_GetItem(self->memo, py_key)) { + PyErr_SetObject(PyExc_KeyError, py_key); goto finally; + } if (PyList_Append(self->stack, value) < 0) goto finally; @@ -2931,8 +2973,10 @@ load_long_binget(Unpicklerobject *self) { UNLESS(py_key = PyInt_FromLong(key)) goto finally; - UNLESS(value = PyDict_GetItem(self->memo, py_key)) + UNLESS(value = PyDict_GetItem(self->memo, py_key)) { + PyErr_SetObject(PyExc_KeyError, py_key); goto finally; + } if (PyList_Append(self->stack, value) < 0) goto finally; @@ -3507,8 +3551,7 @@ load(Unpicklerobject *self) { break; } - err = PyErr_Occurred(); - if (err && PyErr_ExceptionMatches(PyExc_EOFError)) { + if ((err = PyErr_Occurred()) == PyExc_EOFError) { PyErr_SetNone(PyExc_EOFError); goto err; } @@ -3805,8 +3848,7 @@ noload(Unpicklerobject *self) { break; } - err = PyErr_Occurred(); - if (err && PyErr_ExceptionMatches(PyExc_EOFError)) { + if ((err = PyErr_Occurred()) == PyExc_EOFError) { PyErr_SetNone(PyExc_EOFError); goto err; } @@ -4016,6 +4058,13 @@ Unpickler_getattr(Unpicklerobject *self, char *name) { static int Unpickler_setattr(Unpicklerobject *self, char *name, PyObject *value) { + + if(! value) { + PyErr_SetString(PyExc_TypeError, + "attribute deletion is not supported"); + return -1; + } + if (!strcmp(name, "persistent_load")) { Py_XDECREF(self->pers_func); self->pers_func = value; @@ -4023,6 +4072,17 @@ Unpickler_setattr(Unpicklerobject *self, char *name, PyObject *value) { return 0; } + if (strcmp(name, "memo") == 0) { + if(! PyDict_Check(value)) { + PyErr_SetString(PyExc_TypeError, "memo must be a dictionary"); + return -1; + } + Py_XDECREF(self->memo); + self->memo = value; + Py_INCREF(value); + return 0; + } + PyErr_SetString(PyExc_AttributeError, name); return -1; } @@ -4275,7 +4335,7 @@ init_stuff(PyObject *module, PyObject *module_dict) { void initcPickle() { PyObject *m, *d, *v; - char *rev="1.53"; + char *rev="1.57"; PyObject *format_version; PyObject *compatible_formats; -- cgit v0.12