[Python-checkins] r57480 - python/branches/cpy_merge/Modules/_picklemodule.c
alexandre.vassalotti
python-checkins at python.org
Sat Aug 25 23:00:32 CEST 2007
Author: alexandre.vassalotti
Date: Sat Aug 25 23:00:32 2007
New Revision: 57480
Modified:
python/branches/cpy_merge/Modules/_picklemodule.c
Log:
Rename PdataType to Pdata_Type.
Fix a bug in write_file(), read_file(), and readline_file() which was
causing the interpreter to segfault if the given file object to
Unpickler/Pickler was closed after initializing Unpickler/Pickler.
Clean up global static string references for commonly used methods.
Move Unpickler/Pickler object initialization to
Pickler_init()/Unpickler_init().
Fix persistent_id in Pickler object.
Fix persistent_load in Unpickler object.
Remove code related to inst_persistent_id.
Modified: python/branches/cpy_merge/Modules/_picklemodule.c
==============================================================================
--- python/branches/cpy_merge/Modules/_picklemodule.c (original)
+++ python/branches/cpy_merge/Modules/_picklemodule.c Sat Aug 25 23:00:32 2007
@@ -2,7 +2,7 @@
#include "structmember.h"
PyDoc_STRVAR(pickle_module_documentation,
-"C implementation and optimization of the Python pickle module.");
+"Optimized C implementation for the Python pickle module.");
#define WRITE_BUF_SIZE 256
@@ -114,22 +114,12 @@
static PyObject *two_tuple;
#define INIT_STR(S) \
- if (!(S##_str = PyString_InternFromString(#S))) \
+ if (!(S = PyString_InternFromString(#S))) \
return -1;
-static PyObject \
- *__class___str,
- *__dict___str,
- *__setstate___str,
- *__name___str,
- *__reduce___str,
- *__reduce_ex___str,
- *write_str,
- *append_str,
- *read_str,
- *readline_str,
- *__main___str,
- *dispatch_table_str;
+/* Static reference to commonly used self's methods. */
+static PyObject *__class__, *__dict__, *__setstate__, *__name__, \
+ *__reduce__, *__reduce_ex__, *__main__;
/*************************************************************************
Internal Data type for pickle data. */
@@ -155,7 +145,7 @@
PyObject_Del(self);
}
-static PyTypeObject PdataType = {
+static PyTypeObject Pdata_Type = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"_pickle.Pdata", /*tp_name*/
@@ -169,7 +159,7 @@
{
Pdata *self;
- if (!(self = PyObject_New(Pdata, &PdataType)))
+ if (!(self = PyObject_New(Pdata, &Pdata_Type)))
return NULL;
self->size = 8;
self->length = 0;
@@ -337,7 +327,6 @@
PyObject *memo;
PyObject *arg;
PyObject *pers_func;
- PyObject *inst_pers_func;
/* pickle protocol number, >= 0 */
int proto;
@@ -431,6 +420,11 @@
{
size_t nbyteswritten;
+ if (self->fp == NULL) {
+ PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
+ return -1;
+ }
+
if (s == NULL) {
return 0;
}
@@ -455,7 +449,7 @@
static int
write_other(PicklerObject *self, const char *s, Py_ssize_t _n)
{
- PyObject *py_str, *result;
+ PyObject *py_str, *result = NULL;
int n;
if (_n > INT_MAX)
@@ -505,6 +499,11 @@
{
size_t nbytesread;
+ if (self->fp == NULL) {
+ PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
+ return -1;
+ }
+
if (self->buf_size == 0) {
int size;
@@ -550,6 +549,11 @@
{
int i;
+ if (self->fp == NULL) {
+ PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
+ return -1;
+ }
+
if (self->buf_size == 0) {
if (!(self->buf = (char *) malloc(40))) {
PyErr_NoMemory();
@@ -795,7 +799,7 @@
i = 0;
while ((j = PyDict_Next(modules_dict, &i, &name, &module))) {
- if (PyObject_Compare(name, __main___str) == 0)
+ if (PyObject_Compare(name, __main__) == 0)
continue;
global_name_attr = PyObject_GetAttr(module, global_name);
@@ -823,7 +827,7 @@
*/
if (!j) {
j = 1;
- name = __main___str;
+ name = __main__;
}
Py_INCREF(name);
@@ -1743,7 +1747,7 @@
Py_INCREF(global_name);
}
else {
- if (!(global_name = PyObject_GetAttr(args, __name___str)))
+ if (!(global_name = PyObject_GetAttr(args, __name__)))
goto finally;
}
@@ -1964,7 +1968,7 @@
* NEWOBJ. This consumes a lot of code.
*/
if (use_newobj) {
- PyObject *temp = PyObject_GetAttr(callable, __name___str);
+ PyObject *temp = PyObject_GetAttr(callable, __name__);
if (temp == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError))
@@ -2002,7 +2006,7 @@
if (ob != NULL) {
PyObject *ob_dot_class;
- ob_dot_class = PyObject_GetAttr(ob, __class___str);
+ ob_dot_class = PyObject_GetAttr(ob, __class__);
if (ob_dot_class == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear();
@@ -2079,6 +2083,7 @@
PyTypeObject *type;
PyObject *py_ob_id = 0, *__reduce__ = 0, *t = 0;
PyObject *arg_tup;
+ PyObject *pers_func = NULL;
int res = -1;
int tmp, size;
@@ -2088,8 +2093,12 @@
goto finally;
}
- if (!pers_save && self->pers_func) {
- if ((tmp = save_pers(self, args, self->pers_func)) != 0) {
+ pers_func = PyObject_GetAttrString((PyObject *)self, "persistent_id");
+ if (pers_func == NULL)
+ PyErr_Clear();
+
+ if (!pers_save && pers_func) {
+ if ((tmp = save_pers(self, args, pers_func)) != 0) {
res = tmp;
goto finally;
}
@@ -2225,13 +2234,6 @@
}
}
- if (!pers_save && self->inst_pers_func) {
- if ((tmp = save_pers(self, args, self->inst_pers_func)) != 0) {
- res = tmp;
- goto finally;
- }
- }
-
if (PyType_IsSubtype(type, &PyType_Type)) {
res = save_global(self, args, NULL);
goto finally;
@@ -2253,7 +2255,7 @@
}
else {
/* Check for a __reduce_ex__ method. */
- __reduce__ = PyObject_GetAttr(args, __reduce_ex___str);
+ __reduce__ = PyObject_GetAttr(args, __reduce_ex__);
if (__reduce__ != NULL) {
t = PyInt_FromLong(self->proto);
if (t != NULL) {
@@ -2271,7 +2273,7 @@
else
goto finally;
/* Check for a __reduce__ method. */
- __reduce__ = PyObject_GetAttr(args, __reduce___str);
+ __reduce__ = PyObject_GetAttr(args, __reduce__);
if (__reduce__ != NULL) {
t = PyObject_Call(__reduce__, empty_tuple, NULL);
}
@@ -2317,6 +2319,7 @@
finally:
self->nesting--;
+ Py_XDECREF(pers_func);
Py_XDECREF(py_ob_id);
Py_XDECREF(__reduce__);
Py_XDECREF(t);
@@ -2397,35 +2400,18 @@
static PyObject *
Pickler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = { "file", "protocol", NULL };
PicklerObject *self;
- PyObject *file;
- int proto = 0;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:Pickler",
- kwlist, &file, &proto))
- return NULL;
-
- if (proto < 0)
- proto = HIGHEST_PROTOCOL;
- if (proto > HIGHEST_PROTOCOL) {
- PyErr_Format(PyExc_ValueError, "pickle protocol must be <= %d",
- HIGHEST_PROTOCOL);
- return NULL;
- }
-
- self = PyObject_GC_New(PicklerObject, &Pickler_Type);
+ self = (PicklerObject *)type->tp_alloc(type, 0);
if (self == NULL)
return NULL;
- self->proto = proto;
- self->bin = proto > 0;
+ self->proto = 0;
+ self->bin = 0;
self->fp = NULL;
self->write = NULL;
self->memo = NULL;
self->arg = NULL;
- self->pers_func = NULL;
- self->inst_pers_func = NULL;
self->write_buf = NULL;
self->fast = 0;
self->nesting = 0;
@@ -2433,10 +2419,37 @@
self->fast_memo = NULL;
self->buf_size = 0;
self->dispatch_table = NULL;
+ self->pers_func = NULL;
self->memo = PyDict_New();
- if (self->memo == NULL)
- goto error;
+ if (self->memo == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ return (PyObject *)self;
+}
+
+static int
+Pickler_init(PicklerObject *self, PyObject *args, PyObject *kwds)
+{
+ static char *kwlist[] = {"file", "protocol", NULL, 0};
+ PyObject *file;
+ int proto = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:Pickler",
+ kwlist, &file, &proto))
+ return -1;
+
+ if (proto < 0)
+ proto = HIGHEST_PROTOCOL;
+ if (proto > HIGHEST_PROTOCOL) {
+ PyErr_Format(PyExc_ValueError, "pickle protocol must be <= %d",
+ HIGHEST_PROTOCOL);
+ return -1;
+ }
+ self->proto = proto;
+ self->bin = proto > 0;
Py_INCREF(dispatch_table);
self->dispatch_table = dispatch_table;
@@ -2445,37 +2458,35 @@
self->file = file;
if (PyFile_Check(file)) {
self->fp = PyFile_AsFile(file);
- if (self->fp == NULL) {
- PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
- goto error;
- }
self->write_func = write_file;
}
else {
- self->write = PyObject_GetAttr(file, write_str);
+ self->write = PyObject_GetAttrString(file, "write");
if (self->write == NULL) {
PyErr_Clear();
PyErr_SetString(PyExc_TypeError,
- "argument must have 'write' " "attribute");
- goto error;
+ "argument must have 'write' attribute");
+ return -1;
}
self->write_buf = (char *) PyMem_Malloc(WRITE_BUF_SIZE);
if (self->write_buf == NULL) {
PyErr_NoMemory();
- goto error;
+ return -1;
}
self->write_func = write_other;
}
- PyObject_GC_Track(self);
- return (PyObject *) self;
+ self->pers_func = NULL;
+ if (PyObject_HasAttrString((PyObject *)self, "persistent_id")) {
+ self->pers_func = PyObject_GetAttrString((PyObject *)self,
+ "persistent_id");
+ if (self->pers_func == NULL)
+ return -1;
+ }
- error:
- Py_DECREF(self);
- return NULL;
+ return 0;
}
-
static void
Pickler_dealloc(PicklerObject *self)
{
@@ -2486,10 +2497,9 @@
Py_XDECREF(self->fast_memo);
Py_XDECREF(self->arg);
Py_XDECREF(self->pers_func);
- Py_XDECREF(self->inst_pers_func);
Py_XDECREF(self->dispatch_table);
PyMem_Free(self->write_buf);
- self->ob_type->tp_free((PyObject *) self);
+ self->ob_type->tp_free((PyObject *)self);
}
static int
@@ -2500,7 +2510,6 @@
Py_VISIT(self->fast_memo);
Py_VISIT(self->arg);
Py_VISIT(self->pers_func);
- Py_VISIT(self->inst_pers_func);
Py_VISIT(self->dispatch_table);
return 0;
}
@@ -2513,50 +2522,11 @@
Py_CLEAR(self->fast_memo);
Py_CLEAR(self->arg);
Py_CLEAR(self->pers_func);
- Py_CLEAR(self->inst_pers_func);
Py_CLEAR(self->dispatch_table);
return 0;
}
static PyObject *
-Pickler_get_pers_func(PicklerObject *p)
-{
- if (p->pers_func == NULL)
- PyErr_SetString(PyExc_AttributeError, "persistent_id");
- else
- Py_INCREF(p->pers_func);
- return p->pers_func;
-}
-
-static int
-Pickler_set_pers_func(PicklerObject *p, PyObject *v)
-{
- if (v == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "attribute deletion is not supported");
- return -1;
- }
- Py_XDECREF(p->pers_func);
- Py_INCREF(v);
- p->pers_func = v;
- return 0;
-}
-
-static int
-Pickler_set_inst_pers_func(PicklerObject *p, PyObject *v)
-{
- if (v == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "attribute deletion is not supported");
- return -1;
- }
- Py_XDECREF(p->inst_pers_func);
- Py_INCREF(v);
- p->inst_pers_func = v;
- return 0;
-}
-
-static PyObject *
Pickler_get_memo(PicklerObject *p)
{
if (p->memo == NULL)
@@ -2591,10 +2561,7 @@
};
static PyGetSetDef Pickler_getsets[] = {
- {"persistent_id", (getter) Pickler_get_pers_func,
- (setter) Pickler_set_pers_func},
- {"inst_persistent_id", NULL, (setter) Pickler_set_inst_pers_func},
- {"memo", (getter) Pickler_get_memo, (setter) Pickler_set_memo},
+ {"memo", (getter)Pickler_get_memo, (setter)Pickler_set_memo},
{NULL}
};
@@ -2661,7 +2628,7 @@
0, /*tp_descr_get*/
0, /*tp_descr_set*/
0, /*tp_dictoffset*/
- 0, /*tp_init*/
+ (initproc)Pickler_init, /*tp_init*/
0, /*tp_alloc*/
Pickler_new, /*tp_new*/
0, /*tp_free*/
@@ -3489,7 +3456,6 @@
}
}
-
static int
load_pop(UnpicklerObject *self)
{
@@ -3784,8 +3750,12 @@
do_append(UnpicklerObject *self, int x)
{
PyObject *value = 0, *list = 0, *append_method = 0;
+ static PyObject *append = NULL;
int len, i;
+ if (append == NULL)
+ INIT_STR(append);
+
len = self->stack->length;
if (!(len >= x && x > 0))
return stackUnderflow();
@@ -3809,7 +3779,7 @@
}
else {
- if (!(append_method = PyObject_GetAttr(list, append_str)))
+ if (!(append_method = PyObject_GetAttr(list, append)))
return -1;
for (i = x; i < len; i++) {
@@ -3895,7 +3865,7 @@
load_build(UnpicklerObject *self)
{
PyObject *state, *inst, *slotstate;
- PyObject *__setstate__;
+ PyObject *setstate;
PyObject *d_key, *d_value;
Py_ssize_t i;
int res = -1;
@@ -3910,17 +3880,17 @@
return -1;
inst = self->stack->data[self->stack->length - 1];
- __setstate__ = PyObject_GetAttr(inst, __setstate___str);
- if (__setstate__ != NULL) {
+ setstate = PyObject_GetAttr(inst, __setstate__);
+ if (setstate != NULL) {
PyObject *junk = NULL;
/* The explicit __setstate__ is responsible for everything. */
ARG_TUP(self, state);
if (self->arg) {
- junk = PyObject_Call(__setstate__, self->arg, NULL);
+ junk = PyObject_Call(setstate, self->arg, NULL);
FREE_ARG_TUP(self);
}
- Py_DECREF(__setstate__);
+ Py_DECREF(setstate);
if (junk == NULL)
return -1;
Py_DECREF(junk);
@@ -3951,7 +3921,7 @@
PyErr_SetString(UnpicklingError, "state is not a " "dictionary");
goto finally;
}
- dict = PyObject_GetAttr(inst, __dict___str);
+ dict = PyObject_GetAttr(inst, __dict__);
if (dict == NULL)
goto finally;
@@ -4386,15 +4356,9 @@
static PyObject *
Unpickler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = { "file", NULL };
UnpicklerObject *self;
- PyObject *file;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Unpickler",
- kwlist, &file))
- return NULL;
- self = PyObject_GC_New(UnpicklerObject, &Unpickler_Type);
+ self = (UnpicklerObject *)type->tp_alloc(type, 0);
if (self == NULL)
return NULL;
@@ -4411,45 +4375,61 @@
self->find_class = NULL;
self->memo = PyDict_New();
- if (self->memo == NULL)
- goto error;
+ if (self->memo == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
- self->stack = (Pdata *) Pdata_New();
- if (self->stack == NULL)
- goto error;
+ self->stack = (Pdata *)Pdata_New();
+ if (self->stack == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ return (PyObject *)self;
+}
+
+static int
+Unpickler_init(UnpicklerObject *self, PyObject *args, PyObject *kwds)
+{
+ static char *kwlist[] = {"file", 0};
+ PyObject *file;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Unpickler",
+ kwlist, &file))
+ return -1;
Py_INCREF(file);
self->file = file;
/* Set read, readline based on type of file */
if (PyFile_Check(file)) {
self->fp = PyFile_AsFile(file);
- if (self->fp == NULL) {
- PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
- goto error;
- }
self->read_func = read_file;
self->readline_func = readline_file;
}
else {
- self->readline = PyObject_GetAttr(file, readline_str);
- self->read = PyObject_GetAttr(file, read_str);
+ self->readline = PyObject_GetAttrString(file, "readline");
+ self->read = PyObject_GetAttrString(file, "read");
if (self->readline == NULL || self->read == NULL) {
PyErr_Clear();
PyErr_SetString(PyExc_TypeError,
"argument must have 'read' and "
"'readline' attributes");
- goto error;
+ return -1;
}
self->read_func = read_other;
self->readline_func = readline_other;
}
- PyObject_GC_Track(self);
- return (PyObject *)self;
+ self->pers_func = NULL;
+ if (PyObject_HasAttrString((PyObject *)self, "persistent_load")) {
+ self->pers_func = PyObject_GetAttrString((PyObject *)self,
+ "persistent_load");
+ if (self->pers_func == NULL)
+ return -1;
+ }
- error:
- Py_DECREF(self);
- return NULL;
+ return 0;
}
static void
@@ -4510,7 +4490,7 @@
static PyObject *
Unpickler_getattr(UnpicklerObject *self, char *name)
{
- if (!strcmp(name, "persistent_load")) {
+ if (strcmp(name, "persistent_load") == 0) {
if (!self->pers_func) {
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
@@ -4520,7 +4500,7 @@
return self->pers_func;
}
- if (!strcmp(name, "find_global")) {
+ if (strcmp(name, "find_global") == 0) {
if (!self->find_class) {
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
@@ -4530,7 +4510,7 @@
return self->find_class;
}
- if (!strcmp(name, "memo")) {
+ if (strcmp(name, "memo") == 0) {
if (!self->memo) {
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
@@ -4539,28 +4519,29 @@
Py_INCREF(self->memo);
return self->memo;
}
-
- if (!strcmp(name, "UnpicklingError")) {
+
+ /* XXX Why this is there? */
+ if (strcmp(name, "UnpicklingError") == 0) {
Py_INCREF(UnpicklingError);
return UnpicklingError;
}
- return Py_FindMethod(Unpickler_methods, (PyObject *) self, name);
+ /* XXX To remove. Using tp_methods instead. */
+ return Py_FindMethod(Unpickler_methods, (PyObject *)self, name);
}
-
static int
Unpickler_setattr(UnpicklerObject *self, char *name, PyObject *value)
{
- if (!strcmp(name, "persistent_load")) {
+ if (strcmp(name, "persistent_load") == 0) {
Py_XDECREF(self->pers_func);
self->pers_func = value;
Py_XINCREF(value);
return 0;
}
- if (!strcmp(name, "find_global")) {
+ if (strcmp(name, "find_global") == 0) {
Py_XDECREF(self->find_class);
self->find_class = value;
Py_XINCREF(value);
@@ -4631,7 +4612,7 @@
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
- 0, /*tp_methods*/
+ Unpickler_methods, /*tp_methods*/
0, /*tp_members*/
0, /*tp_getset*/
0, /*tp_base*/
@@ -4639,7 +4620,7 @@
0, /*tp_descr_get*/
0, /*tp_descr_set*/
0, /*tp_dictoffset*/
- 0, /*tp_init*/
+ (initproc)Unpickler_init, /*tp_init*/
0, /*tp_alloc*/
Unpickler_new, /*tp_new*/
0, /*tp_free*/
@@ -4651,11 +4632,6 @@
{
PyObject *copy_reg, *t, *r;
- if (PyType_Ready(&Unpickler_Type) < 0)
- return -1;
- if (PyType_Ready(&Pickler_Type) < 0)
- return -1;
-
INIT_STR(__class__);
INIT_STR(__dict__);
INIT_STR(__setstate__);
@@ -4663,18 +4639,14 @@
INIT_STR(__main__);
INIT_STR(__reduce__);
INIT_STR(__reduce_ex__);
- INIT_STR(write);
- INIT_STR(append);
- INIT_STR(read);
- INIT_STR(readline);
- INIT_STR(dispatch_table);
- if (!(copy_reg = PyImport_ImportModule("copy_reg")))
+ copy_reg = PyImport_ImportModule("copy_reg");
+ if (!copy_reg)
return -1;
/* This is special because we want to use a different
* one in restricted mode. */
- dispatch_table = PyObject_GetAttr(copy_reg, dispatch_table_str);
+ dispatch_table = PyObject_GetAttrString(copy_reg, "dispatch_table");
if (!dispatch_table)
return -1;
@@ -4705,17 +4677,12 @@
*/
PyObject_GC_UnTrack(two_tuple);
- /* Ugh */
- if (!(t = PyImport_ImportModule("__builtin__")))
- return -1;
- if (PyDict_SetItemString(module_dict, "__builtins__", t) < 0)
- return -1;
-
if (!(t = PyDict_New()))
return -1;
- if (!(r = PyRun_String("def __str__(self):\n"
- " return self.args and ('%s' % self.args[0]) or ''\n",
- Py_file_input, module_dict, t)))
+ if (!(r = PyRun_String(
+ "def __str__(self):\n"
+ " return self.args and ('%s' % self.args[0]) or ''\n",
+ Py_file_input, module_dict, t)))
return -1;
Py_DECREF(r);
@@ -4730,19 +4697,9 @@
if (!PicklingError)
return -1;
- if (!(t = PyDict_New()))
- return -1;
- if (!(r = PyRun_String("def __str__(self):\n"
- " a=self.args\n"
- " a=a and type(a[0]) or ''\n"
- " return 'Cannot pickle %s objects' % a\n",
- Py_file_input, module_dict, t)))
- return -1;
- Py_DECREF(r);
- Py_DECREF(t);
-
- if (!(UnpicklingError = PyErr_NewException("pickle.UnpicklingError",
- PickleError, NULL)))
+ UnpicklingError = PyErr_NewException("pickle.UnpicklingError",
+ PickleError, NULL);
+ if (!UnpicklingError)
return -1;
if (PyDict_SetItemString(module_dict, "PickleError", PickleError) < 0)
@@ -4767,9 +4724,12 @@
PyObject *format_version;
PyObject *compatible_formats;
- Pickler_Type.ob_type = &PyType_Type;
- Unpickler_Type.ob_type = &PyType_Type;
- PdataType.ob_type = &PyType_Type;
+ if (PyType_Ready(&Unpickler_Type) < 0)
+ return;
+ if (PyType_Ready(&Pickler_Type) < 0)
+ return;
+ if (PyType_Ready(&Pdata_Type) < 0)
+ return;
/* Create the module and add the functions */
m = Py_InitModule3("_pickle", NULL, pickle_module_documentation);
More information about the Python-checkins
mailing list