Author: Armin Rigo <[email protected]>
Branch:
Changeset: r94527:d18c31e806d6
Date: 2018-05-12 09:47 +0200
http://bitbucket.org/pypy/pypy/changeset/d18c31e806d6/
Log: Issue #2823
Implement PyMarshal_ReadObjectFromString and
PyMarshal_WriteObjectToString
diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py
--- a/pypy/module/cpyext/__init__.py
+++ b/pypy/module/cpyext/__init__.py
@@ -77,6 +77,7 @@
import pypy.module.cpyext.pystrtod
import pypy.module.cpyext.pytraceback
import pypy.module.cpyext.methodobject
+import pypy.module.cpyext.marshal
# now that all rffi_platform.Struct types are registered, configure them
api.configure_types()
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -60,7 +60,7 @@
configure_eci = ExternalCompilationInfo(
include_dirs=include_dirs,
- includes=['Python.h', 'stdarg.h', 'structmember.h'],
+ includes=['Python.h', 'stdarg.h', 'structmember.h', 'marshal.h'],
compile_extra=['-DPy_BUILD_CORE'])
class CConfig:
@@ -118,6 +118,7 @@
pypy_decl = 'pypy_decl.h'
udir.join(pypy_decl).write("/* Will be filled later */\n")
udir.join('pypy_structmember_decl.h').write("/* Will be filled later */\n")
+udir.join('pypy_marshal_decl.h').write("/* Will be filled later */\n")
udir.join('pypy_macros.h').write("/* Will be filled later */\n")
constant_names = """
@@ -1221,14 +1222,11 @@
global_objects.append('PyTypeObject _PyExc_%s;' % name)
global_code = '\n'.join(global_objects)
- prologue = ("#include <Python.h>\n"
- "#include <structmember.h>\n"
+ prologue = ("#include <Python.h>\n" +
+ "#include <structmember.h>\n" +
+ "#include <marshal.h>\n" +
+ ("#include <pypy_numpy.h>\n" if use_micronumpy else "") +
"#include <src/thread.c>\n")
- if use_micronumpy:
- prologue = ("#include <Python.h>\n"
- "#include <structmember.h>\n"
- "#include <pypy_numpy.h>\n"
- "#include <src/thread.c>\n")
code = (prologue +
struct_declaration_code +
global_code +
diff --git a/pypy/module/cpyext/include/marshal.h
b/pypy/module/cpyext/include/marshal.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/marshal.h
@@ -0,0 +1,13 @@
+#ifndef Py_MARSHAL_H
+#define Py_MARSHAL_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define Py_MARSHAL_VERSION 2
+#include "pypy_marshal_decl.h"
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_MARSHAL_H */
diff --git a/pypy/module/cpyext/marshal.py b/pypy/module/cpyext/marshal.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/marshal.py
@@ -0,0 +1,17 @@
+from rpython.rtyper.lltypesystem import rffi, lltype
+from pypy.module.cpyext.api import cpython_api, Py_ssize_t
+from pypy.module.cpyext.pyobject import PyObject
+
+
+_HEADER = 'pypy_marshal_decl.h'
+
+@cpython_api([rffi.CCHARP, Py_ssize_t], PyObject, header=_HEADER)
+def PyMarshal_ReadObjectFromString(space, p, size):
+ from pypy.module.marshal.interp_marshal import loads
+ s = rffi.charpsize2str(p, size)
+ return loads(space, space.newbytes(s))
+
+@cpython_api([PyObject, rffi.INT_real], PyObject, header=_HEADER)
+def PyMarshal_WriteObjectToString(space, w_x, version):
+ from pypy.module.marshal.interp_marshal import dumps
+ return dumps(space, w_x, space.newint(version))
diff --git a/pypy/module/cpyext/test/test_marshal.py
b/pypy/module/cpyext/test/test_marshal.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_marshal.py
@@ -0,0 +1,33 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+
+class AppTestMarshal(AppTestCpythonExtensionBase):
+ def test_PyMarshal_ReadObjectFromString(self):
+ module = self.import_extension('foo', [
+ ("mloads", "METH_O",
+ """
+ char *input = PyString_AsString(args);
+ Py_ssize_t length = PyString_Size(args);
+ return PyMarshal_ReadObjectFromString(input, length);
+ """)],
+ prologue='#include <marshal.h>')
+ import marshal
+ assert module.mloads(marshal.dumps(42.5)) == 42.5
+ x = [None, True, (4, 5), b"adkj", u"\u1234"]
+ assert module.mloads(marshal.dumps(x)) == x
+
+ def test_PyMarshal_WriteObjectToString(self):
+ module = self.import_extension('foo', [
+ ("mdumps", "METH_VARARGS",
+ """
+ PyObject *obj;
+ int version;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &version))
+ return NULL;
+ return PyMarshal_WriteObjectToString(obj, version);
+ """)],
+ prologue='#include <marshal.h>')
+ import marshal
+ for x in [42, b"foo", u"\u2345", (4, None, False)]:
+ for version in [0, 1, 2]:
+ assert module.mdumps(x, version) == marshal.dumps(x, version)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit