Kaydet (Commit) ce616e40 authored tarafından Jeremy Hylton's avatar Jeremy Hylton

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.
üst 7cfca6de
/* /*
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 Copyright
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
static char cPickle_module_documentation[] = static char cPickle_module_documentation[] =
"C implementation and optimization of the Python pickle module\n" "C implementation and optimization of the Python pickle module\n"
"\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" #include "Python.h"
...@@ -147,6 +147,7 @@ typedef struct { ...@@ -147,6 +147,7 @@ typedef struct {
PyObject *pers_func; PyObject *pers_func;
PyObject *inst_pers_func; PyObject *inst_pers_func;
int bin; int bin;
int fast; /* Fast mode doesn't save in memo, don't use if circ ref */
int (*write_func)(); int (*write_func)();
char *write_buf; char *write_buf;
int buf_size; int buf_size;
...@@ -507,8 +508,10 @@ get(Picklerobject *self, PyObject *id) { ...@@ -507,8 +508,10 @@ get(Picklerobject *self, PyObject *id) {
char s[30]; char s[30];
int len; int len;
UNLESS(value = PyDict_GetItem(self->memo, id)) UNLESS(value = PyDict_GetItem(self->memo, id)) {
PyErr_SetObject(PyExc_KeyError, id);
return -1; return -1;
}
UNLESS(value = PyTuple_GetItem(value, 0)) UNLESS(value = PyTuple_GetItem(value, 0))
return -1; return -1;
...@@ -545,7 +548,7 @@ get(Picklerobject *self, PyObject *id) { ...@@ -545,7 +548,7 @@ get(Picklerobject *self, PyObject *id) {
static int static int
put(Picklerobject *self, PyObject *ob) { put(Picklerobject *self, PyObject *ob) {
if (ob->ob_refcnt < 2) if (ob->ob_refcnt < 2 || self->fast)
return 0; return 0;
return put2(self, ob); return put2(self, ob);
...@@ -557,6 +560,9 @@ put2(Picklerobject *self, PyObject *ob) { ...@@ -557,6 +560,9 @@ put2(Picklerobject *self, PyObject *ob) {
char c_str[30]; char c_str[30];
int p, len, res = -1; int p, len, res = -1;
PyObject *py_ob_id = 0, *memo_len = 0, *t = 0; PyObject *py_ob_id = 0, *memo_len = 0, *t = 0;
if (self->fast) return 0;
if ((p = PyDict_Size(self->memo)) < 0) if ((p = PyDict_Size(self->memo)) < 0)
goto finally; goto finally;
...@@ -675,10 +681,8 @@ whichmodule(PyObject *global, PyObject *global_name) { ...@@ -675,10 +681,8 @@ whichmodule(PyObject *global, PyObject *global_name) {
if (module) return module; if (module) return module;
PyErr_Clear(); PyErr_Clear();
UNLESS(modules_dict = PySys_GetObject("modules")) { UNLESS(modules_dict = PySys_GetObject("modules"))
PyErr_SetString(PyExc_SystemError, "lost sys.modules");
return NULL; return NULL;
}
i = 0; i = 0;
while ((j = PyDict_Next(modules_dict, &i, &name, &module))) { while ((j = PyDict_Next(modules_dict, &i, &name, &module))) {
...@@ -1762,6 +1766,7 @@ newPicklerobject(PyObject *file, int bin) { ...@@ -1762,6 +1766,7 @@ newPicklerobject(PyObject *file, int bin) {
self->inst_pers_func = NULL; self->inst_pers_func = NULL;
self->write_buf = NULL; self->write_buf = NULL;
self->bin = bin; self->bin = bin;
self->fast = 0;
self->buf_size = 0; self->buf_size = 0;
self->dispatch_table = NULL; self->dispatch_table = NULL;
...@@ -1876,6 +1881,12 @@ Pickler_getattr(Picklerobject *self, char *name) { ...@@ -1876,6 +1881,12 @@ Pickler_getattr(Picklerobject *self, char *name) {
Py_INCREF(PicklingError); Py_INCREF(PicklingError);
return 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); return Py_FindMethod(Pickler_methods, (PyObject *)self, name);
} }
...@@ -1883,6 +1894,13 @@ Pickler_getattr(Picklerobject *self, char *name) { ...@@ -1883,6 +1894,13 @@ Pickler_getattr(Picklerobject *self, char *name) {
int int
Pickler_setattr(Picklerobject *self, char *name, PyObject *value) { 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) { if (strcmp(name, "persistent_id") == 0) {
Py_XDECREF(self->pers_func); Py_XDECREF(self->pers_func);
self->pers_func = value; self->pers_func = value;
...@@ -1897,6 +1915,27 @@ Pickler_setattr(Picklerobject *self, char *name, PyObject *value) { ...@@ -1897,6 +1915,27 @@ Pickler_setattr(Picklerobject *self, char *name, PyObject *value) {
return 0; 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); PyErr_SetString(PyExc_AttributeError, name);
return -1; return -1;
} }
...@@ -1952,15 +1991,14 @@ find_class(PyObject *py_module_name, PyObject *py_global_name) { ...@@ -1952,15 +1991,14 @@ find_class(PyObject *py_module_name, PyObject *py_global_name) {
if (global == NULL) { if (global == NULL) {
char buf[256 + 37]; char buf[256 + 37];
sprintf(buf, "Failed to import class %.128s from moduile %.128s", sprintf(buf, "Failed to import class %.128s from moduile %.128s",
PyString_AS_STRING(py_global_name), PyString_AS_STRING((PyStringObject*)py_global_name),
PyString_AS_STRING(py_module_name)); PyString_AS_STRING((PyStringObject*)py_module_name));
PyErr_SetString(PyExc_SystemError, buf); PyErr_SetString(PyExc_SystemError, buf);
return NULL; return NULL;
} }
return global; return global;
} }
static int static int
marker(Unpicklerobject *self) { marker(Unpicklerobject *self) {
if (self->num_marks < 1) { if (self->num_marks < 1) {
...@@ -2539,8 +2577,8 @@ Instance_New(PyObject *cls, PyObject *args) { ...@@ -2539,8 +2577,8 @@ Instance_New(PyObject *cls, PyObject *args) {
if (!has_key) if (!has_key)
if(!(safe = PyObject_GetAttr(cls, __safe_for_unpickling___str)) || if(!(safe = PyObject_GetAttr(cls, __safe_for_unpickling___str)) ||
!PyObject_IsTrue(safe)) { !PyObject_IsTrue(safe)) {
cPickle_ErrFormat(UnpicklingError, cPickle_ErrFormat(UnpicklingError,
"%s is not safe for unpickling", "O", cls); "%s is not safe for unpickling", "O", cls);
Py_XDECREF(safe); Py_XDECREF(safe);
return NULL; return NULL;
} }
...@@ -2864,8 +2902,10 @@ load_get(Unpicklerobject *self) { ...@@ -2864,8 +2902,10 @@ load_get(Unpicklerobject *self) {
UNLESS(py_str = PyString_FromStringAndSize(s, len - 1)) UNLESS(py_str = PyString_FromStringAndSize(s, len - 1))
goto finally; 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; goto finally;
}
if (PyList_Append(self->stack, value) < 0) if (PyList_Append(self->stack, value) < 0)
goto finally; goto finally;
...@@ -2894,8 +2934,10 @@ load_binget(Unpicklerobject *self) { ...@@ -2894,8 +2934,10 @@ load_binget(Unpicklerobject *self) {
UNLESS(py_key = PyInt_FromLong((long)key)) UNLESS(py_key = PyInt_FromLong((long)key))
goto finally; 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; goto finally;
}
if (PyList_Append(self->stack, value) < 0) if (PyList_Append(self->stack, value) < 0)
goto finally; goto finally;
...@@ -2931,8 +2973,10 @@ load_long_binget(Unpicklerobject *self) { ...@@ -2931,8 +2973,10 @@ load_long_binget(Unpicklerobject *self) {
UNLESS(py_key = PyInt_FromLong(key)) UNLESS(py_key = PyInt_FromLong(key))
goto finally; 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; goto finally;
}
if (PyList_Append(self->stack, value) < 0) if (PyList_Append(self->stack, value) < 0)
goto finally; goto finally;
...@@ -3507,8 +3551,7 @@ load(Unpicklerobject *self) { ...@@ -3507,8 +3551,7 @@ load(Unpicklerobject *self) {
break; break;
} }
err = PyErr_Occurred(); if ((err = PyErr_Occurred()) == PyExc_EOFError) {
if (err && PyErr_ExceptionMatches(PyExc_EOFError)) {
PyErr_SetNone(PyExc_EOFError); PyErr_SetNone(PyExc_EOFError);
goto err; goto err;
} }
...@@ -3805,8 +3848,7 @@ noload(Unpicklerobject *self) { ...@@ -3805,8 +3848,7 @@ noload(Unpicklerobject *self) {
break; break;
} }
err = PyErr_Occurred(); if ((err = PyErr_Occurred()) == PyExc_EOFError) {
if (err && PyErr_ExceptionMatches(PyExc_EOFError)) {
PyErr_SetNone(PyExc_EOFError); PyErr_SetNone(PyExc_EOFError);
goto err; goto err;
} }
...@@ -4016,6 +4058,13 @@ Unpickler_getattr(Unpicklerobject *self, char *name) { ...@@ -4016,6 +4058,13 @@ Unpickler_getattr(Unpicklerobject *self, char *name) {
static int static int
Unpickler_setattr(Unpicklerobject *self, char *name, PyObject *value) { 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")) { if (!strcmp(name, "persistent_load")) {
Py_XDECREF(self->pers_func); Py_XDECREF(self->pers_func);
self->pers_func = value; self->pers_func = value;
...@@ -4023,6 +4072,17 @@ Unpickler_setattr(Unpicklerobject *self, char *name, PyObject *value) { ...@@ -4023,6 +4072,17 @@ Unpickler_setattr(Unpicklerobject *self, char *name, PyObject *value) {
return 0; 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); PyErr_SetString(PyExc_AttributeError, name);
return -1; return -1;
} }
...@@ -4275,7 +4335,7 @@ init_stuff(PyObject *module, PyObject *module_dict) { ...@@ -4275,7 +4335,7 @@ init_stuff(PyObject *module, PyObject *module_dict) {
void void
initcPickle() { initcPickle() {
PyObject *m, *d, *v; PyObject *m, *d, *v;
char *rev="1.53"; char *rev="1.57";
PyObject *format_version; PyObject *format_version;
PyObject *compatible_formats; PyObject *compatible_formats;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment