diff -r 6b37e6aff9ef Python/marshal.c --- a/Python/marshal.c Mon Jan 27 19:03:07 2014 -0700 +++ b/Python/marshal.c Tue Jan 28 17:29:02 2014 +0800 @@ -13,6 +13,11 @@ #include "code.h" #include "marshal.h" +/*[clinic input] +module marshal +[clinic start generated code]*/ +/*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ + #define ABS(x) ((x) < 0 ? -(x) : (x)) /* High water mark to determine when the marshalled object is dangerously deep @@ -1553,43 +1558,115 @@ } /* And an interface for Python programs... */ +/*[clinic input] +marshal.dump + + value: object + file: object + version: int(c_default="Py_MARSHAL_VERSION") = version + / + +Write the value on the open file. + +The value must be a supported type. The file must be an open file object such +as sys.stdout or returned by open() or os.popen(). It must be opened in binary +mode ('wb' or 'w+b'). + +If the value has (or contains an object that has) an unsupported type, a +ValueError exception is raised — but garbage data will also be written to the +file. The object will not be properly read back by load(). + +The version argument indicates the data format that dump should use. +[clinic start generated code]*/ + +PyDoc_STRVAR(marshal_dump__doc__, +"dump(module, value, file, version=version)\n" +"Write the value on the open file.\n" +"\n" +"The value must be a supported type. The file must be an open file object such\n" +"as sys.stdout or returned by open() or os.popen(). It must be opened in binary\n" +"mode (\'wb\' or \'w+b\').\n" +"\n" +"If the value has (or contains an object that has) an unsupported type, a\n" +"ValueError exception is raised — but garbage data will also be written to the\n" +"file. The object will not be properly read back by load().\n" +"\n" +"The version argument indicates the data format that dump should use."); + +#define MARSHAL_DUMP_METHODDEF \ + {"dump", (PyCFunction)marshal_dump, METH_VARARGS, marshal_dump__doc__}, static PyObject * -marshal_dump(PyObject *self, PyObject *args) +marshal_dump_impl(PyModuleDef *module, PyObject *value, PyObject *file, int version); + +static PyObject * +marshal_dump(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *value; + PyObject *file; + int version = Py_MARSHAL_VERSION; + + if (!PyArg_ParseTuple(args, + "OO|i:dump", + &value, &file, &version)) + goto exit; + return_value = marshal_dump_impl(module, value, file, version); + +exit: + return return_value; +} + +static PyObject * +marshal_dump_impl(PyModuleDef *module, PyObject *value, PyObject *file, int version) +/*[clinic end generated code: checksum=e778289143e47a8883b9a593e2d67d1d6c3379f7]*/ { /* XXX Quick hack -- need to do this differently */ - PyObject *x; - PyObject *f; - int version = Py_MARSHAL_VERSION; PyObject *s; PyObject *res; _Py_IDENTIFIER(write); - if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version)) - return NULL; - s = PyMarshal_WriteObjectToString(x, version); + s = PyMarshal_WriteObjectToString(value, version); if (s == NULL) return NULL; - res = _PyObject_CallMethodId(f, &PyId_write, "O", s); + res = _PyObject_CallMethodId(file, &PyId_write, "O", s); Py_DECREF(s); return res; } -PyDoc_STRVAR(dump_doc, -"dump(value, file[, version])\n\ -\n\ -Write the value on the open file. The value must be a supported type.\n\ -The file must be an open file object such as sys.stdout or returned by\n\ -open() or os.popen(). It must be opened in binary mode ('wb' or 'w+b').\n\ -\n\ -If the value has (or contains an object that has) an unsupported type, a\n\ -ValueError exception is raised — but garbage data will also be written\n\ -to the file. The object will not be properly read back by load()\n\ -\n\ -The version argument indicates the data format that dump should use."); +/*[clinic input] +marshal.load + + file: object + / + +Read one value from the open file and return it. + +If no valid value is read (e.g. because the data has a different Python +version’s incompatible marshal format), raise EOFError, ValueError or TypeError. +The file must be an open file object opened in binary mode ('rb' or 'r+b'). + +Note: If an object containing an unsupported type was marshalled with dump(), +load() will substitute None for the unmarshallable type. +[clinic start generated code]*/ + +PyDoc_STRVAR(marshal_load__doc__, +"load(module, file)\n" +"Read one value from the open file and return it.\n" +"\n" +"If no valid value is read (e.g. because the data has a different Python\n" +"version’s incompatible marshal format), raise EOFError, ValueError or TypeError.\n" +"The file must be an open file object opened in binary mode (\'rb\' or \'r+b\').\n" +"\n" +"Note: If an object containing an unsupported type was marshalled with dump(),\n" +"load() will substitute None for the unmarshallable type."); + +#define MARSHAL_LOAD_METHODDEF \ + {"load", (PyCFunction)marshal_load, METH_O, marshal_load__doc__}, static PyObject * -marshal_load(PyObject *self, PyObject *f) +marshal_load(PyModuleDef *module, PyObject *file) +/*[clinic end generated code: checksum=b0ec7c8f7e66132e86c1a02449daaace74fc7a57]*/ { PyObject *data, *result; _Py_IDENTIFIER(read); @@ -1602,19 +1679,19 @@ * This can be removed if we guarantee good error handling * for r_string() */ - data = _PyObject_CallMethodId(f, &PyId_read, "i", 0); + data = _PyObject_CallMethodId(file, &PyId_read, "i", 0); if (data == NULL) return NULL; if (!PyBytes_Check(data)) { PyErr_Format(PyExc_TypeError, - "f.read() returned not bytes but %.100s", + "file.read() returned not bytes but %.100s", data->ob_type->tp_name); result = NULL; } else { rf.depth = 0; rf.fp = NULL; - rf.readable = f; + rf.readable = file; rf.current_filename = NULL; rf.ptr = rf.end = NULL; rf.buf = NULL; @@ -1630,51 +1707,113 @@ return result; } -PyDoc_STRVAR(load_doc, -"load(file)\n\ -\n\ -Read one value from the open file and return it. If no valid value is\n\ -read (e.g. because the data has a different Python version’s\n\ -incompatible marshal format), raise EOFError, ValueError or TypeError.\n\ -The file must be an open file object opened in binary mode ('rb' or\n\ -'r+b').\n\ -\n\ -Note: If an object containing an unsupported type was marshalled with\n\ -dump(), load() will substitute None for the unmarshallable type."); +/*[clinic input] +marshal.dumps + value: object + version: int(c_default="Py_MARSHAL_VERSION") = version + / + +Return the string that would be written to a file by dump(value, file). + +The value must be a supported type. Raise a ValueError exception if +value has (or contains an object that has) an unsupported type. + +The version argument indicates the data format that dumps should use. +[clinic start generated code]*/ + +PyDoc_STRVAR(marshal_dumps__doc__, +"dumps(module, value, version=version)\n" +"Return the string that would be written to a file by dump(value, file)\n" +"\n" +"The value must be a supported type. Raise a ValueError exception if\n" +"value has (or contains an object that has) an unsupported type.\n" +"\n" +"The version argument indicates the data format that dumps should use."); + +#define MARSHAL_DUMPS_METHODDEF \ + {"dumps", (PyCFunction)marshal_dumps, METH_VARARGS, marshal_dumps__doc__}, static PyObject * -marshal_dumps(PyObject *self, PyObject *args) +marshal_dumps_impl(PyModuleDef *module, PyObject *value, int version); + +static PyObject * +marshal_dumps(PyModuleDef *module, PyObject *args) { - PyObject *x; + PyObject *return_value = NULL; + PyObject *value; int version = Py_MARSHAL_VERSION; - if (!PyArg_ParseTuple(args, "O|i:dumps", &x, &version)) - return NULL; - return PyMarshal_WriteObjectToString(x, version); + + if (!PyArg_ParseTuple(args, + "O|i:dumps", + &value, &version)) + goto exit; + return_value = marshal_dumps_impl(module, value, version); + +exit: + return return_value; } -PyDoc_STRVAR(dumps_doc, -"dumps(value[, version])\n\ -\n\ -Return the string that would be written to a file by dump(value, file).\n\ -The value must be a supported type. Raise a ValueError exception if\n\ -value has (or contains an object that has) an unsupported type.\n\ -\n\ -The version argument indicates the data format that dumps should use."); +static PyObject * +marshal_dumps_impl(PyModuleDef *module, PyObject *value, int version) +/*[clinic end generated code: checksum=1be5b7a9d5aed289b81c88063f98eeeded8a2776]*/ +{ + return PyMarshal_WriteObjectToString(value, version); +} +/*[clinic input] +marshal.loads + + bytes: Py_buffer + / + +Convert the bytes object to a value. + +If no valid value is found, raise EOFError, ValueError or TypeError. Extra +characters in the input are ignored. +[clinic start generated code]*/ + +PyDoc_STRVAR(marshal_loads__doc__, +"loads(module, bytes)\n" +"Convert the bytes object to a value.\n" +"\n" +"If no valid value is found, raise EOFError, ValueError or TypeError. Extra\n" +"characters in the input are ignored."); + +#define MARSHAL_LOADS_METHODDEF \ + {"loads", (PyCFunction)marshal_loads, METH_VARARGS, marshal_loads__doc__}, static PyObject * -marshal_loads(PyObject *self, PyObject *args) +marshal_loads_impl(PyModuleDef *module, Py_buffer *bytes); + +static PyObject * +marshal_loads(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer bytes = {NULL, NULL}; + + if (!PyArg_ParseTuple(args, + "y*:loads", + &bytes)) + goto exit; + return_value = marshal_loads_impl(module, &bytes); + +exit: + /* Cleanup for bytes */ + if (bytes.obj) + PyBuffer_Release(&bytes); + + return return_value; +} + +static PyObject * +marshal_loads_impl(PyModuleDef *module, Py_buffer *bytes) +/*[clinic end generated code: checksum=f9b970402356bbe55ec7ea8c15d0550988c27541]*/ { RFILE rf; - Py_buffer p; - char *s; - Py_ssize_t n; + char *s = bytes->buf; + Py_ssize_t n = bytes->len; PyObject* result; - if (!PyArg_ParseTuple(args, "y*:loads", &p)) - return NULL; - s = p.buf; - n = p.len; rf.fp = NULL; rf.readable = NULL; rf.current_filename = NULL; @@ -1684,23 +1823,15 @@ if ((rf.refs = PyList_New(0)) == NULL) return NULL; result = read_object(&rf); - PyBuffer_Release(&p); Py_DECREF(rf.refs); return result; } -PyDoc_STRVAR(loads_doc, -"loads(bytes)\n\ -\n\ -Convert the bytes object to a value. If no valid value is found, raise\n\ -EOFError, ValueError or TypeError. Extra characters in the input are\n\ -ignored."); - static PyMethodDef marshal_methods[] = { - {"dump", marshal_dump, METH_VARARGS, dump_doc}, - {"load", marshal_load, METH_O, load_doc}, - {"dumps", marshal_dumps, METH_VARARGS, dumps_doc}, - {"loads", marshal_loads, METH_VARARGS, loads_doc}, + MARSHAL_DUMP_METHODDEF + MARSHAL_LOAD_METHODDEF + MARSHAL_DUMPS_METHODDEF + MARSHAL_LOADS_METHODDEF {NULL, NULL} /* sentinel */ };