mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-20185: Convert the marshal module to Argument Clinic. (#541)
Based on patch by Vajrasky Kok.
This commit is contained in:
		
							parent
							
								
									c611a5b1d4
								
							
						
					
					
						commit
						0767ad40bf
					
				
					 2 changed files with 229 additions and 67 deletions
				
			
		
							
								
								
									
										145
									
								
								Python/clinic/marshal.c.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								Python/clinic/marshal.c.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,145 @@ | |||
| /*[clinic input]
 | ||||
| preserve | ||||
| [clinic start generated code]*/ | ||||
| 
 | ||||
| PyDoc_STRVAR(marshal_dump__doc__, | ||||
| "dump($module, value, file, version=version, /)\n" | ||||
| "--\n" | ||||
| "\n" | ||||
| "Write the value on the open file.\n" | ||||
| "\n" | ||||
| "  value\n" | ||||
| "    Must be a supported type.\n" | ||||
| "  file\n" | ||||
| "    Must be a writeable binary file.\n" | ||||
| "  version\n" | ||||
| "    Indicates the data format that dump should use.\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()."); | ||||
| 
 | ||||
| #define MARSHAL_DUMP_METHODDEF    \ | ||||
|     {"dump", (PyCFunction)marshal_dump, METH_FASTCALL, marshal_dump__doc__}, | ||||
| 
 | ||||
| static PyObject * | ||||
| marshal_dump_impl(PyObject *module, PyObject *value, PyObject *file, | ||||
|                   int version); | ||||
| 
 | ||||
| static PyObject * | ||||
| marshal_dump(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) | ||||
| { | ||||
|     PyObject *return_value = NULL; | ||||
|     PyObject *value; | ||||
|     PyObject *file; | ||||
|     int version = Py_MARSHAL_VERSION; | ||||
| 
 | ||||
|     if (!_PyArg_ParseStack(args, nargs, "OO|i:dump", | ||||
|         &value, &file, &version)) { | ||||
|         goto exit; | ||||
|     } | ||||
| 
 | ||||
|     if (!_PyArg_NoStackKeywords("dump", kwnames)) { | ||||
|         goto exit; | ||||
|     } | ||||
|     return_value = marshal_dump_impl(module, value, file, version); | ||||
| 
 | ||||
| exit: | ||||
|     return return_value; | ||||
| } | ||||
| 
 | ||||
| PyDoc_STRVAR(marshal_load__doc__, | ||||
| "load($module, file, /)\n" | ||||
| "--\n" | ||||
| "\n" | ||||
| "Read one value from the open file and return it.\n" | ||||
| "\n" | ||||
| "  file\n" | ||||
| "    Must be readable binary file.\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\n" | ||||
| "TypeError.\n" | ||||
| "\n" | ||||
| "Note: If an object containing an unsupported type was marshalled with\n" | ||||
| "dump(), load() will substitute None for the unmarshallable type."); | ||||
| 
 | ||||
| #define MARSHAL_LOAD_METHODDEF    \ | ||||
|     {"load", (PyCFunction)marshal_load, METH_O, marshal_load__doc__}, | ||||
| 
 | ||||
| PyDoc_STRVAR(marshal_dumps__doc__, | ||||
| "dumps($module, value, version=version, /)\n" | ||||
| "--\n" | ||||
| "\n" | ||||
| "Return the bytes object that would be written to a file by dump(value, file).\n" | ||||
| "\n" | ||||
| "  value\n" | ||||
| "    Must be a supported type.\n" | ||||
| "  version\n" | ||||
| "    Indicates the data format that dumps should use.\n" | ||||
| "\n" | ||||
| "Raise a ValueError exception if value has (or contains an object that has) an\n" | ||||
| "unsupported type."); | ||||
| 
 | ||||
| #define MARSHAL_DUMPS_METHODDEF    \ | ||||
|     {"dumps", (PyCFunction)marshal_dumps, METH_FASTCALL, marshal_dumps__doc__}, | ||||
| 
 | ||||
| static PyObject * | ||||
| marshal_dumps_impl(PyObject *module, PyObject *value, int version); | ||||
| 
 | ||||
| static PyObject * | ||||
| marshal_dumps(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) | ||||
| { | ||||
|     PyObject *return_value = NULL; | ||||
|     PyObject *value; | ||||
|     int version = Py_MARSHAL_VERSION; | ||||
| 
 | ||||
|     if (!_PyArg_ParseStack(args, nargs, "O|i:dumps", | ||||
|         &value, &version)) { | ||||
|         goto exit; | ||||
|     } | ||||
| 
 | ||||
|     if (!_PyArg_NoStackKeywords("dumps", kwnames)) { | ||||
|         goto exit; | ||||
|     } | ||||
|     return_value = marshal_dumps_impl(module, value, version); | ||||
| 
 | ||||
| exit: | ||||
|     return return_value; | ||||
| } | ||||
| 
 | ||||
| PyDoc_STRVAR(marshal_loads__doc__, | ||||
| "loads($module, bytes, /)\n" | ||||
| "--\n" | ||||
| "\n" | ||||
| "Convert the bytes-like object to a value.\n" | ||||
| "\n" | ||||
| "If no valid value is found, raise EOFError, ValueError or TypeError.  Extra\n" | ||||
| "bytes in the input are ignored."); | ||||
| 
 | ||||
| #define MARSHAL_LOADS_METHODDEF    \ | ||||
|     {"loads", (PyCFunction)marshal_loads, METH_O, marshal_loads__doc__}, | ||||
| 
 | ||||
| static PyObject * | ||||
| marshal_loads_impl(PyObject *module, Py_buffer *bytes); | ||||
| 
 | ||||
| static PyObject * | ||||
| marshal_loads(PyObject *module, PyObject *arg) | ||||
| { | ||||
|     PyObject *return_value = NULL; | ||||
|     Py_buffer bytes = {NULL, NULL}; | ||||
| 
 | ||||
|     if (!PyArg_Parse(arg, "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; | ||||
| } | ||||
| /*[clinic end generated code: output=9dec2158b8c5d975 input=a9049054013a1b77]*/ | ||||
							
								
								
									
										151
									
								
								Python/marshal.c
									
										
									
									
									
								
							
							
						
						
									
										151
									
								
								Python/marshal.c
									
										
									
									
									
								
							|  | @ -14,6 +14,13 @@ | |||
| #include "marshal.h" | ||||
| #include "../Modules/hashtable.h" | ||||
| 
 | ||||
| /*[clinic input]
 | ||||
| module marshal | ||||
| [clinic start generated code]*/ | ||||
| /*[clinic end generated code: output=da39a3ee5e6b4b0d input=c982b7930dee17db]*/ | ||||
| 
 | ||||
| #include "clinic/marshal.c.h" | ||||
| 
 | ||||
| /* High water mark to determine when the marshalled object is dangerously deep
 | ||||
|  * and risks coring the interpreter.  When the object stack gets this deep, | ||||
|  * raise an exception instead of continuing. | ||||
|  | @ -1632,42 +1639,62 @@ PyMarshal_WriteObjectToString(PyObject *x, int version) | |||
| } | ||||
| 
 | ||||
| /* And an interface for Python programs... */ | ||||
| /*[clinic input]
 | ||||
| marshal.dump | ||||
| 
 | ||||
|     value: object | ||||
|         Must be a supported type. | ||||
|     file: object | ||||
|         Must be a writeable binary file. | ||||
|     version: int(c_default="Py_MARSHAL_VERSION") = version | ||||
|         Indicates the data format that dump should use. | ||||
|     / | ||||
| 
 | ||||
| Write the value on the open file. | ||||
| 
 | ||||
| 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(). | ||||
| [clinic start generated code]*/ | ||||
| 
 | ||||
| static PyObject * | ||||
| marshal_dump(PyObject *self, PyObject *args) | ||||
| marshal_dump_impl(PyObject *module, PyObject *value, PyObject *file, | ||||
|                   int version) | ||||
| /*[clinic end generated code: output=aaee62c7028a7cb2 input=6c7a3c23c6fef556]*/ | ||||
| { | ||||
|     /* 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_CallMethodIdObjArgs(f, &PyId_write, s, NULL); | ||||
|     res = _PyObject_CallMethodIdObjArgs(file, &PyId_write, s, NULL); | ||||
|     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 a writeable binary file.\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 | ||||
|         Must be readable binary file. | ||||
|     / | ||||
| 
 | ||||
| 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. | ||||
| 
 | ||||
| Note: If an object containing an unsupported type was marshalled with | ||||
| dump(), load() will substitute None for the unmarshallable type. | ||||
| [clinic start generated code]*/ | ||||
| 
 | ||||
| static PyObject * | ||||
| marshal_load(PyObject *self, PyObject *f) | ||||
| marshal_load(PyObject *module, PyObject *file) | ||||
| /*[clinic end generated code: output=f8e5c33233566344 input=c85c2b594cd8124a]*/ | ||||
| { | ||||
|     PyObject *data, *result; | ||||
|     _Py_IDENTIFIER(read); | ||||
|  | @ -1680,19 +1707,19 @@ marshal_load(PyObject *self, PyObject *f) | |||
|      * 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; | ||||
|  | @ -1708,50 +1735,48 @@ marshal_load(PyObject *self, PyObject *f) | |||
|     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 a readable binary file.\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 | ||||
|         Must be a supported type. | ||||
|     version: int(c_default="Py_MARSHAL_VERSION") = version | ||||
|         Indicates the data format that dumps should use. | ||||
|     / | ||||
| 
 | ||||
| Return the bytes object that would be written to a file by dump(value, file). | ||||
| 
 | ||||
| Raise a ValueError exception if value has (or contains an object that has) an | ||||
| unsupported type. | ||||
| [clinic start generated code]*/ | ||||
| 
 | ||||
| static PyObject * | ||||
| marshal_dumps(PyObject *self, PyObject *args) | ||||
| marshal_dumps_impl(PyObject *module, PyObject *value, int version) | ||||
| /*[clinic end generated code: output=9c200f98d7256cad input=a2139ea8608e9b27]*/ | ||||
| { | ||||
|     PyObject *x; | ||||
|     int version = Py_MARSHAL_VERSION; | ||||
|     if (!PyArg_ParseTuple(args, "O|i:dumps", &x, &version)) | ||||
|         return NULL; | ||||
|     return PyMarshal_WriteObjectToString(x, version); | ||||
|     return PyMarshal_WriteObjectToString(value, version); | ||||
| } | ||||
| 
 | ||||
| PyDoc_STRVAR(dumps_doc, | ||||
| "dumps(value[, version])\n\
 | ||||
| \n\ | ||||
| Return the bytes object 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."); | ||||
| /*[clinic input]
 | ||||
| marshal.loads | ||||
| 
 | ||||
|     bytes: Py_buffer | ||||
|     / | ||||
| 
 | ||||
| Convert the bytes-like object to a value. | ||||
| 
 | ||||
| If no valid value is found, raise EOFError, ValueError or TypeError.  Extra | ||||
| bytes in the input are ignored. | ||||
| [clinic start generated code]*/ | ||||
| 
 | ||||
| static PyObject * | ||||
| marshal_loads(PyObject *self, PyObject *args) | ||||
| marshal_loads_impl(PyObject *module, Py_buffer *bytes) | ||||
| /*[clinic end generated code: output=9fc65985c93d1bb1 input=6f426518459c8495]*/ | ||||
| { | ||||
|     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; | ||||
|  | @ -1761,23 +1786,15 @@ marshal_loads(PyObject *self, PyObject *args) | |||
|     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-like object to a value. If no valid value is found,\n\ | ||||
| raise EOFError, ValueError or TypeError. Extra bytes 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 */ | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Serhiy Storchaka
						Serhiy Storchaka