[pypy-commit] pypy py3k: Fix the cpyext module, at least py.py can import it without segfaulting

amauryfa noreply at buildbot.pypy.org
Sat Oct 22 00:28:36 CEST 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r48329:928a4651aa4e
Date: 2011-10-22 00:24 +0200
http://bitbucket.org/pypy/pypy/changeset/928a4651aa4e/

Log:	Fix the cpyext module, at least py.py can import it without
	segfaulting

diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py
--- a/pypy/module/cpyext/funcobject.py
+++ b/pypy/module/cpyext/funcobject.py
@@ -86,14 +86,13 @@
     w_code = space.wrap(func.code)
     return borrow_from(w_func, w_code)
 
- at cpython_api([PyObject, PyObject, PyObject], PyObject)
-def PyMethod_New(space, w_func, w_self, w_cls):
-    """Return a new method object, with func being any callable object; this is the
-    function that will be called when the method is called.  If this method should
-    be bound to an instance, self should be the instance and class should be the
-    class of self, otherwise self should be NULL and class should be the
-    class which provides the unbound method."""
-    return Method(space, w_func, w_self, w_cls)
+ at cpython_api([PyObject, PyObject], PyObject)
+def PyMethod_New(space, w_func, w_self):
+    """Return a new method object, with func being any callable object
+    and self the instance the method should be bound. func is the
+    function that will be called when the method is called. self must
+    not be NULL."""
+    return Method(space, w_func, w_self)
 
 @cpython_api([PyObject], PyObject)
 def PyMethod_Function(space, w_method):
diff --git a/pypy/module/cpyext/include/unicodeobject.h b/pypy/module/cpyext/include/unicodeobject.h
--- a/pypy/module/cpyext/include/unicodeobject.h
+++ b/pypy/module/cpyext/include/unicodeobject.h
@@ -22,6 +22,7 @@
     PyObject_HEAD
     Py_UNICODE *buffer;
     Py_ssize_t size;
+    char *utf8buffer;
 } PyUnicodeObject;
 
 
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -186,13 +186,10 @@
     return ret
 
 def cmethod_descr_get(space, w_function, w_obj, w_cls=None):
-    asking_for_bound = (space.is_w(w_cls, space.w_None) or
-                        not space.is_w(w_obj, space.w_None) or
-                        space.is_w(w_cls, space.type(space.w_None)))
-    if asking_for_bound:
-        return space.wrap(Method(space, w_function, w_obj, w_cls))
+    if w_obj is None or space.is_w(w_obj, space.w_None):
+        return w_function
     else:
-        return w_function
+        return space.wrap(Method(space, w_function, w_obj))
 
 
 W_PyCFunctionObject.typedef = TypeDef(
diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
--- a/pypy/module/cpyext/stringobject.py
+++ b/pypy/module/cpyext/stringobject.py
@@ -73,8 +73,8 @@
     interpreter object.  The buffer may be mutated, until string_realize() is
     called.
     """
-    typedescr = get_typedescr(space.w_str.instancetypedef)
-    py_obj = typedescr.allocate(space, space.w_str)
+    typedescr = get_typedescr(space.w_bytes.instancetypedef)
+    py_obj = typedescr.allocate(space, space.w_bytes)
     py_str = rffi.cast(PyStringObject, py_obj)
 
     buflen = length + 1
@@ -89,7 +89,7 @@
     buffer must not be modified.
     """
     py_str = rffi.cast(PyStringObject, py_obj)
-    py_str.c_size = len(space.str_w(w_obj))
+    py_str.c_size = len(space.bytes_w(w_obj))
     py_str.c_buffer = lltype.nullptr(rffi.CCHARP.TO)
 
 def string_realize(space, py_obj):
@@ -119,14 +119,14 @@
 def PyString_FromStringAndSize(space, char_p, length):
     if char_p:
         s = rffi.charpsize2str(char_p, length)
-        return make_ref(space, space.wrap(s))
+        return make_ref(space, space.wrapbytes(s))
     else:
         return rffi.cast(PyObject, new_empty_str(space, length))
 
 @cpython_api([CONST_STRING], PyObject)
 def PyString_FromString(space, char_p):
     s = rffi.charp2str(char_p)
-    return space.wrap(s)
+    return space.wrapbytes(s)
 
 @cpython_api([PyObject], rffi.CCHARP, error=0)
 def PyString_AsString(space, ref):
@@ -134,7 +134,7 @@
     if not ref_str.c_buffer:
         # copy string buffer
         w_str = from_ref(space, ref)
-        s = space.str_w(w_str)
+        s = space.bytes_w(w_str)
         ref_str.c_buffer = rffi.str2charp(s)
     return ref_str.c_buffer
 
@@ -147,7 +147,7 @@
     if not ref_str.c_buffer:
         # copy string buffer
         w_str = from_ref(space, ref)
-        s = space.str_w(w_str)
+        s = space.bytes_w(w_str)
         ref_str.c_buffer = rffi.str2charp(s)
     buffer[0] = ref_str.c_buffer
     if length:
@@ -235,12 +235,6 @@
     PyString_Concat(space, ref, newpart)
     Py_DecRef(space, newpart)
 
- at cpython_api([PyObject, PyObject], PyObject)
-def PyString_Format(space, w_format, w_args):
-    """Return a new string object from format and args. Analogous to format %
-    args.  The args argument must be a tuple."""
-    return space.mod(w_format, w_args)
-
 @cpython_api([CONST_STRING], PyObject)
 def PyString_InternFromString(space, string):
     """A combination of PyString_FromString() and
@@ -250,25 +244,6 @@
     s = rffi.charp2str(string)
     return space.new_interned_str(s)
 
- at cpython_api([PyObject, rffi.CCHARP, rffi.CCHARP], PyObject)
-def PyString_AsEncodedObject(space, w_str, encoding, errors):
-    """Encode a string object using the codec registered for encoding and return
-    the result as Python object. encoding and errors have the same meaning as
-    the parameters of the same name in the string encode() method. The codec to
-    be used is looked up using the Python codec registry. Return NULL if an
-    exception was raised by the codec.
-
-    This function is not available in 3.x and does not have a PyBytes alias."""
-    if not PyString_Check(space, w_str):
-        PyErr_BadArgument(space)
-
-    w_encoding = w_errors = space.w_None
-    if encoding:
-        w_encoding = space.wrap(rffi.charp2str(encoding))
-    if errors:
-        w_errors = space.wrap(rffi.charp2str(errors))
-    return space.call_method(w_str, 'encode', w_encoding, w_errors)
-
 @cpython_api([PyObject, PyObject], PyObject)
 def _PyString_Join(space, w_sep, w_seq):
     return space.call_method(w_sep, 'join', w_seq)
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -203,6 +203,9 @@
         if filename is None, the module name will be used to construct the
         filename.
         """
+        name = name.encode()
+        init = init.encode()
+        body = body.encode()
         if init is not None:
             code = """
             #include <Python.h>
diff --git a/pypy/module/cpyext/test/test_funcobject.py b/pypy/module/cpyext/test/test_funcobject.py
--- a/pypy/module/cpyext/test/test_funcobject.py
+++ b/pypy/module/cpyext/test/test_funcobject.py
@@ -31,13 +31,11 @@
 
         w_function = space.getattr(w_method, space.wrap("im_func"))
         w_self = space.getattr(w_method, space.wrap("im_self"))
-        w_class = space.getattr(w_method, space.wrap("im_class"))
 
         assert space.is_w(api.PyMethod_Function(w_method), w_function)
         assert space.is_w(api.PyMethod_Self(w_method), w_self)
-        assert space.is_w(api.PyMethod_Class(w_method), w_class)
 
-        w_method2 = api.PyMethod_New(w_function, w_self, w_class)
+        w_method2 = api.PyMethod_New(w_function, w_self)
         assert space.eq_w(w_method, w_method2)
 
     def test_getcode(self, space, api):
@@ -67,7 +65,6 @@
             api.Py_DecRef(ref)
             return co_flags
         assert get_flags("x") == CO_NESTED | CO_OPTIMIZED | CO_NEWLOCALS
-        assert get_flags("x", "exec x") == CO_NESTED | CO_NEWLOCALS
         assert get_flags("x, *args") & CO_VARARGS
         assert get_flags("x, **kw") & CO_VARKEYWORDS
         assert get_flags("x", "yield x") & CO_GENERATOR
diff --git a/pypy/module/cpyext/test/test_stringobject.py b/pypy/module/cpyext/test/test_stringobject.py
--- a/pypy/module/cpyext/test/test_stringobject.py
+++ b/pypy/module/cpyext/test/test_stringobject.py
@@ -45,12 +45,12 @@
              """
                 return PyBool_FromLong(PyString_Check(PyTuple_GetItem(args, 0)));
              """)])
-        assert module.get_hello1() == 'Hello world'
-        assert module.get_hello2() == 'Hello world'
+        assert module.get_hello1() == b'Hello world'
+        assert module.get_hello2() == b'Hello world'
         assert module.test_Size()
         raises(TypeError, module.test_Size_exception)
 
-        assert module.test_is_string("")
+        assert module.test_is_string(b"")
         assert not module.test_is_string(())
 
     def test_string_buffer_init(self):
@@ -93,7 +93,7 @@
              """),
             ])
         s = module.getstring()
-        assert s == 'test'
+        assert s == b'test'
 
     def test_py_string_as_string(self):
         module = self.import_extension('foo', [
@@ -103,7 +103,7 @@
                        PyTuple_GetItem(args, 0)), 4);
              '''
             )])
-        assert module.string_as_string("huheduwe") == "huhe"
+        assert module.string_as_string(b"huheduwe") == b"huhe"
 
     def test_AsStringAndSize(self):
         module = self.import_extension('foo', [
@@ -150,7 +150,7 @@
               return res;
             }
             ''')
-        res = module.test_string_format_v(1, "xyz")
+        res = module.test_string_format_v(1, b"xyz")
         assert res == "bla 1 ble xyz\n"
 
     def test_format(self):
@@ -163,7 +163,7 @@
              '''
              )
             ])
-        res = module.test_string_format(1, "xyz")
+        res = module.test_string_format(1, b"xyz")
         assert res == "bla 1 ble xyz\n"
 
 class TestString(BaseApiTest):
@@ -205,41 +205,37 @@
         Py_DecRef(space, py_obj)
 
     def test_Concat(self, space, api):
-        ref = make_ref(space, space.wrap('abc'))
+        ref = make_ref(space, space.wrapbytes('abc'))
         ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
         ptr[0] = ref
-        api.PyString_Concat(ptr, space.wrap('def'))
-        assert space.str_w(from_ref(space, ptr[0])) == 'abcdef'
+        api.PyString_Concat(ptr, space.wrapbytes('def'))
+        assert space.bytes_w(from_ref(space, ptr[0])) == 'abcdef'
         api.PyString_Concat(ptr, space.w_None)
         assert not ptr[0]
         ptr[0] = lltype.nullptr(PyObject.TO)
-        api.PyString_Concat(ptr, space.wrap('def')) # should not crash
+        api.PyString_Concat(ptr, space.wrapbytes('def')) # should not crash
         lltype.free(ptr, flavor='raw')
 
     def test_ConcatAndDel(self, space, api):
-        ref1 = make_ref(space, space.wrap('abc'))
-        ref2 = make_ref(space, space.wrap('def'))
+        ref1 = make_ref(space, space.wrapbytes('abc'))
+        ref2 = make_ref(space, space.wrapbytes('def'))
         ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
         ptr[0] = ref1
         api.PyString_ConcatAndDel(ptr, ref2)
-        assert space.str_w(from_ref(space, ptr[0])) == 'abcdef'
+        assert space.bytes_w(from_ref(space, ptr[0])) == 'abcdef'
         assert ref2.c_ob_refcnt == 0
         Py_DecRef(space, ptr[0])
         ptr[0] = lltype.nullptr(PyObject.TO)
-        ref2 = make_ref(space, space.wrap('foo'))
+        ref2 = make_ref(space, space.wrapbytes('foo'))
         api.PyString_ConcatAndDel(ptr, ref2) # should not crash
         assert ref2.c_ob_refcnt == 0
         lltype.free(ptr, flavor='raw')
 
-    def test_format(self, space, api):
-        assert "1 2" == space.unwrap(
-            api.PyString_Format(space.wrap('%s %d'), space.wrap((1, 2))))
-
     def test_asbuffer(self, space, api):
         bufp = lltype.malloc(rffi.CCHARPP.TO, 1, flavor='raw')
         lenp = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
 
-        w_text = space.wrap("text")
+        w_text = space.wrapbytes("text")
         assert api.PyObject_AsCharBuffer(w_text, bufp, lenp) == 0
         assert lenp[0] == 4
         assert rffi.charp2str(bufp[0]) == 'text'
@@ -254,42 +250,12 @@
         rffi.free_charp(buf)
         assert w_s1 is w_s2
 
-    def test_AsEncodedObject(self, space, api):
-        ptr = space.wrap('abc')
-
-        errors = rffi.str2charp("strict")
-
-        encoding = rffi.str2charp("hex")
-        res = api.PyString_AsEncodedObject(
-            ptr, encoding, errors)
-        assert space.unwrap(res) == "616263"
-
-        res = api.PyString_AsEncodedObject(
-            ptr, encoding, lltype.nullptr(rffi.CCHARP.TO))
-        assert space.unwrap(res) == "616263"
-        rffi.free_charp(encoding)
-
-        encoding = rffi.str2charp("unknown_encoding")
-        self.raises(space, api, LookupError, api.PyString_AsEncodedObject,
-                    ptr, encoding, errors)
-        rffi.free_charp(encoding)
-
-        rffi.free_charp(errors)
-
-        res = api.PyString_AsEncodedObject(
-            ptr, lltype.nullptr(rffi.CCHARP.TO), lltype.nullptr(rffi.CCHARP.TO))
-        assert space.unwrap(res) == "abc"
-
-        self.raises(space, api, TypeError, api.PyString_AsEncodedObject,
-            space.wrap(2), lltype.nullptr(rffi.CCHARP.TO), lltype.nullptr(rffi.CCHARP.TO)
-        )
-
     def test_eq(self, space, api):
-        assert 1 == api._PyString_Eq(space.wrap("hello"), space.wrap("hello"))
-        assert 0 == api._PyString_Eq(space.wrap("hello"), space.wrap("world"))
+        assert 1 == api._PyString_Eq(space.wrapbytes("hello"), space.wrapbytes("hello"))
+        assert 0 == api._PyString_Eq(space.wrapbytes("hello"), space.wrapbytes("world"))
 
     def test_join(self, space, api):
-        w_sep = space.wrap('<sep>')
-        w_seq = space.wrap(['a', 'b'])
+        w_sep = space.wrapbytes('<sep>')
+        w_seq = space.newtuple([space.wrapbytes('a'), space.wrapbytes('b')])
         w_joined = api._PyString_Join(w_sep, w_seq)
-        assert space.unwrap(w_joined) == 'a<sep>b'
+        assert space.bytes_w(w_joined) == 'a<sep>b'
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -493,8 +493,8 @@
         w_typename = space.getattr(w_type, space.wrap('__name__'))
         heaptype = rffi.cast(PyHeapTypeObject, pto)
         heaptype.c_ht_name = make_ref(space, w_typename)
-        from pypy.module.cpyext.stringobject import PyString_AsString
-        pto.c_tp_name = PyString_AsString(space, heaptype.c_ht_name)
+        from pypy.module.cpyext.unicodeobject import _PyUnicode_AsString
+        pto.c_tp_name = _PyUnicode_AsString(space, heaptype.c_ht_name)
     else:
         pto.c_tp_name = rffi.str2charp(w_type.getname(space))
     pto.c_tp_basicsize = -1 # hopefully this makes malloc bail out
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -21,7 +21,8 @@
 PyUnicodeObjectStruct = lltype.ForwardReference()
 PyUnicodeObject = lltype.Ptr(PyUnicodeObjectStruct)
 PyUnicodeObjectFields = (PyObjectFields +
-    (("buffer", rffi.CWCHARP), ("size", Py_ssize_t)))
+    (("buffer", rffi.CWCHARP), ("size", Py_ssize_t),
+     ("utf8buffer", rffi.CCHARP)))
 cpython_struct("PyUnicodeObject", PyUnicodeObjectFields, PyUnicodeObjectStruct)
 
 @bootstrap_function
@@ -79,6 +80,8 @@
     py_unicode = rffi.cast(PyUnicodeObject, py_obj)
     if py_unicode.c_buffer:
         lltype.free(py_unicode.c_buffer, flavor="raw")
+    if py_unicode.c_utf8buffer:
+        lltype.free(py_unicode.c_utf8buffer, flavor="raw")
     from pypy.module.cpyext.object import PyObject_dealloc
     PyObject_dealloc(space, py_obj)
 
@@ -196,6 +199,17 @@
                              space.wrap("expected unicode object"))
     return PyUnicode_AS_UNICODE(space, ref)
 
+ at cpython_api([PyObject], rffi.CCHARP)
+def _PyUnicode_AsString(space, ref):
+    ref_unicode = rffi.cast(PyUnicodeObject, ref)
+    if not ref_unicode.c_utf8buffer:
+        # Copy unicode buffer
+        w_unicode = from_ref(space, ref)
+        w_encoded = unicodetype.encode_object(space, w_unicode, "utf-8", "strict")
+        s = space.bytes_w(w_encoded)
+        ref_unicode.c_utf8buffer = rffi.str2charp(s)
+    return ref_unicode.c_utf8buffer
+
 @cpython_api([PyObject], Py_ssize_t, error=-1)
 def PyUnicode_GetSize(space, ref):
     if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_unicode:


More information about the pypy-commit mailing list