]> granicus.if.org Git - python/commitdiff
Taught cPickle how to read pickles containing NEWOBJ. This won't get
authorTim Peters <tim.peters@gmail.com>
Thu, 13 Feb 2003 18:24:14 +0000 (18:24 +0000)
committerTim Peters <tim.peters@gmail.com>
Thu, 13 Feb 2003 18:24:14 +0000 (18:24 +0000)
exercised by the test suite before cPickle knows how to create NEWOBJ
too.  For now, it was just tried once by hand (via loading a NEWOBJ
pickle created by pickle.py).

Modules/cPickle.c

index 17da7d7917d9d696a6aba9695041105f07b20cec..6601290f4c273060fa2629f8daaf8b7c626636f7 100644 (file)
@@ -3698,6 +3698,53 @@ load_inst(Unpicklerobject *self)
        return 0;
 }
 
+static int
+load_newobj(Unpicklerobject *self)
+{
+       PyObject *args = NULL;
+       PyObject *clsraw = NULL;
+       PyTypeObject *cls;      /* clsraw cast to its true type */
+       PyObject *obj;
+
+       /* Stack is ... cls argtuple, and we want to call
+        * cls.__new__(cls, *argtuple).
+        */
+       PDATA_POP(self->stack, args);
+       if (args == NULL) goto Fail;
+       if (! PyTuple_Check(args)) {
+               PyErr_SetString(UnpicklingError, "NEWOBJ expected an arg "
+                                                "tuple.");
+               goto Fail;
+       }
+
+       PDATA_POP(self->stack, clsraw);
+       cls = (PyTypeObject *)clsraw;
+       if (cls == NULL) goto Fail;
+       if (! PyType_Check(cls)) {
+               PyErr_SetString(UnpicklingError, "NEWOBJ class argument "
+                                                "isn't a type object");
+               goto Fail;
+       }
+       if (cls->tp_new == NULL) {
+               PyErr_SetString(UnpicklingError, "NEWOBJ class argument "
+                                                "has NULL tp_new");
+               goto Fail;
+       }
+
+       /* Call __new__. */
+       obj = cls->tp_new(cls, args, NULL);
+       if (obj == NULL) goto Fail;
+
+       Py_DECREF(args);
+       Py_DECREF(clsraw);
+       PDATA_PUSH(self->stack, obj, -1);
+       return 0;
+
+ Fail:
+       Py_XDECREF(args);
+       Py_XDECREF(clsraw);
+       return -1;
+}
 
 static int
 load_global(Unpicklerobject *self)
@@ -4461,6 +4508,11 @@ load(Unpicklerobject *self)
                                break;
                        continue;
 
+               case NEWOBJ:
+                       if (load_newobj(self) < 0)
+                               break;
+                       continue;
+
                case GLOBAL:
                        if (load_global(self) < 0)
                                break;
@@ -4638,10 +4690,27 @@ noload_inst(Unpicklerobject *self)
        Pdata_clear(self->stack, i);
        if (self->readline_func(self, &s) < 0) return -1;
        if (self->readline_func(self, &s) < 0) return -1;
-       PDATA_APPEND(self->stack, Py_None,-1);
+       PDATA_APPEND(self->stack, Py_None, -1);
        return 0;
 }
 
+static int
+noload_newobj(Unpicklerobject *self)
+{
+       PyObject *obj;
+
+       PDATA_POP(self->stack, obj);    /* pop argtuple */
+       if (obj == NULL) return -1;
+       Py_DECREF(obj);
+
+       PDATA_POP(self->stack, obj);    /* pop cls */
+       if (obj == NULL) return -1;
+       Py_DECREF(obj);
+
+       PDATA_APPEND(self->stack, Py_None, -1);
+       return 0;
+}
+
 static int
 noload_global(Unpicklerobject *self)
 {
@@ -4829,6 +4898,11 @@ noload(Unpicklerobject *self)
                                break;
                        continue;
 
+               case NEWOBJ:
+                       if (noload_newobj(self) < 0)
+                               break;
+                       continue;
+
                case GLOBAL:
                        if (noload_global(self) < 0)
                                break;