[pypy-commit] pypy py3k: The Grand renaming: PyString->PyBytes
amauryfa
noreply at buildbot.pypy.org
Thu Nov 22 23:50:09 CET 2012
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r59059:53ef7831e3c4
Date: 2012-11-22 23:28 +0100
http://bitbucket.org/pypy/pypy/changeset/53ef7831e3c4/
Log: The Grand renaming: PyString->PyBytes
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
@@ -36,7 +36,6 @@
import pypy.module.cpyext.pyerrors
import pypy.module.cpyext.typeobject
import pypy.module.cpyext.object
-import pypy.module.cpyext.stringobject
import pypy.module.cpyext.bytesobject
import pypy.module.cpyext.tupleobject
import pypy.module.cpyext.setobject
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
@@ -356,7 +356,6 @@
'Py_FatalError', 'PyOS_snprintf', 'PyOS_vsnprintf', 'PyArg_Parse',
'PyArg_ParseTuple', 'PyArg_UnpackTuple', 'PyArg_ParseTupleAndKeywords',
'PyArg_VaParse', 'PyArg_VaParseTupleAndKeywords', '_PyArg_NoKeywords',
- 'PyString_FromFormat', 'PyString_FromFormatV',
'PyUnicode_FromFormat', 'PyUnicode_FromFormatV', 'PyUnicode_AsWideCharString',
'PyModule_AddObject', 'PyModule_AddIntConstant', 'PyModule_AddStringConstant',
'Py_BuildValue', 'Py_VaBuildValue', 'PyTuple_Pack',
diff --git a/pypy/module/cpyext/bytesobject.py b/pypy/module/cpyext/bytesobject.py
--- a/pypy/module/cpyext/bytesobject.py
+++ b/pypy/module/cpyext/bytesobject.py
@@ -1,5 +1,251 @@
-from pypy.module.cpyext.pyobject import PyObject
-from pypy.module.cpyext.api import cpython_api
+from pypy.interpreter.error import OperationError
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.module.cpyext.api import (
+ cpython_api, cpython_struct, bootstrap_function, build_type_checkers,
+ PyObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL)
+from pypy.module.cpyext.pyerrors import PyErr_BadArgument
+from pypy.module.cpyext.pyobject import (
+ PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
+ make_typedescr, get_typedescr)
+
+
+##
+## Implementation of PyBytesObject
+## ================================
+##
+## The problem
+## -----------
+##
+## PyBytes_AsString() must return a (non-movable) pointer to the underlying
+## buffer, whereas pypy strings are movable. C code may temporarily store
+## this address and use it, as long as it owns a reference to the PyObject.
+## There is no "release" function to specify that the pointer is not needed
+## any more.
+##
+## Also, the pointer may be used to fill the initial value of string. This is
+## valid only when the string was just allocated, and is not used elsewhere.
+##
+## Solution
+## --------
+##
+## PyBytesObject contains two additional members: the size and a pointer to a
+## char buffer; it may be NULL.
+##
+## - A string allocated by pypy will be converted into a PyBytesObject with a
+## NULL buffer. The first time PyBytes_AsString() is called, memory is
+## allocated (with flavor='raw') and content is copied.
+##
+## - A string allocated with PyBytes_FromStringAndSize(NULL, size) will
+## allocate a PyBytesObject structure, and a buffer with the specified
+## size, but the reference won't be stored in the global map; there is no
+## corresponding object in pypy. When from_ref() or Py_INCREF() is called,
+## the pypy string is created, and added to the global map of tracked
+## objects. The buffer is then supposed to be immutable.
+##
+## - _PyBytes_Resize() works only on not-yet-pypy'd strings, and returns a
+## similar object.
+##
+## - PyBytes_Size() doesn't need to force the object.
+##
+## - There could be an (expensive!) check in from_ref() that the buffer still
+## corresponds to the pypy gc-managed string.
+##
+
+PyBytesObjectStruct = lltype.ForwardReference()
+PyBytesObject = lltype.Ptr(PyBytesObjectStruct)
+PyBytesObjectFields = PyObjectFields + \
+ (("buffer", rffi.CCHARP), ("size", Py_ssize_t))
+cpython_struct("PyBytesObject", PyBytesObjectFields, PyBytesObjectStruct)
+
+ at bootstrap_function
+def init_bytesobject(space):
+ "Type description of PyBytesObject"
+ make_typedescr(space.w_str.instancetypedef,
+ basestruct=PyBytesObject.TO,
+ attach=bytes_attach,
+ dealloc=bytes_dealloc,
+ realize=bytes_realize)
+
+PyBytes_Check, PyBytes_CheckExact = build_type_checkers("Bytes", "w_bytes")
+
+def new_empty_str(space, length):
+ """
+ Allocates a PyBytesObject and its buffer, but without a corresponding
+ interpreter object. The buffer may be mutated, until bytes_realize() is
+ called.
+ """
+ typedescr = get_typedescr(space.w_bytes.instancetypedef)
+ py_obj = typedescr.allocate(space, space.w_bytes)
+ py_str = rffi.cast(PyBytesObject, py_obj)
+
+ buflen = length + 1
+ py_str.c_size = length
+ py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen,
+ flavor='raw', zero=True)
+ return py_str
+
+def bytes_attach(space, py_obj, w_obj):
+ """
+ Fills a newly allocated PyBytesObject with the given string object. The
+ buffer must not be modified.
+ """
+ py_str = rffi.cast(PyBytesObject, py_obj)
+ py_str.c_size = len(space.bytes_w(w_obj))
+ py_str.c_buffer = lltype.nullptr(rffi.CCHARP.TO)
+
+def bytes_realize(space, py_obj):
+ """
+ Creates the string in the interpreter. The PyBytesObject buffer must not
+ be modified after this call.
+ """
+ py_str = rffi.cast(PyBytesObject, py_obj)
+ s = rffi.charpsize2str(py_str.c_buffer, py_str.c_size)
+ w_obj = space.wrap(s)
+ track_reference(space, py_obj, w_obj)
+ return w_obj
+
+ at cpython_api([PyObject], lltype.Void, external=False)
+def bytes_dealloc(space, py_obj):
+ """Frees allocated PyBytesObject resources.
+ """
+ py_str = rffi.cast(PyBytesObject, py_obj)
+ if py_str.c_buffer:
+ lltype.free(py_str.c_buffer, flavor="raw")
+ from pypy.module.cpyext.object import PyObject_dealloc
+ PyObject_dealloc(space, py_obj)
+
+#_______________________________________________________________________
+
+ at cpython_api([CONST_STRING, Py_ssize_t], PyObject)
+def PyBytes_FromStringAndSize(space, char_p, length):
+ if char_p:
+ s = rffi.charpsize2str(char_p, length)
+ return make_ref(space, space.wrapbytes(s))
+ else:
+ return rffi.cast(PyObject, new_empty_str(space, length))
+
+ at cpython_api([CONST_STRING], PyObject)
+def PyBytes_FromString(space, char_p):
+ s = rffi.charp2str(char_p)
+ return space.wrapbytes(s)
+
+ at cpython_api([PyObject], rffi.CCHARP, error=0)
+def PyBytes_AsString(space, ref):
+ if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
+ pass # typecheck returned "ok" without forcing 'ref' at all
+ elif not PyBytes_Check(space, ref): # otherwise, use the alternate way
+ raise OperationError(space.w_TypeError, space.wrap(
+ "PyBytes_AsString only support strings"))
+ ref_str = rffi.cast(PyBytesObject, ref)
+ if not ref_str.c_buffer:
+ # copy string buffer
+ w_str = from_ref(space, ref)
+ s = space.bytes_w(w_str)
+ ref_str.c_buffer = rffi.str2charp(s)
+ return ref_str.c_buffer
+
+#_______________________________________________________________________
+
+ at cpython_api([PyObject, rffi.CCHARPP, rffi.CArrayPtr(Py_ssize_t)], rffi.INT_real, error=-1)
+def PyBytes_AsStringAndSize(space, ref, buffer, length):
+ if not PyBytes_Check(space, ref):
+ raise OperationError(space.w_TypeError, space.wrap(
+ "PyBytes_AsStringAndSize only support strings"))
+ ref_str = rffi.cast(PyBytesObject, ref)
+ if not ref_str.c_buffer:
+ # copy string buffer
+ w_str = from_ref(space, ref)
+ s = space.bytes_w(w_str)
+ ref_str.c_buffer = rffi.str2charp(s)
+ buffer[0] = ref_str.c_buffer
+ if length:
+ length[0] = ref_str.c_size
+ else:
+ i = 0
+ while ref_str.c_buffer[i] != '\0':
+ i += 1
+ if i != ref_str.c_size:
+ raise OperationError(space.w_TypeError, space.wrap(
+ "expected string without null bytes"))
+ return 0
+
+ at cpython_api([PyObject], Py_ssize_t, error=-1)
+def PyBytes_Size(space, ref):
+ if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
+ ref = rffi.cast(PyBytesObject, ref)
+ return ref.c_size
+ else:
+ w_obj = from_ref(space, ref)
+ return space.len_w(w_obj)
+
+ at cpython_api([PyObjectP, Py_ssize_t], rffi.INT_real, error=-1)
+def _PyBytes_Resize(space, ref, newsize):
+ """A way to resize a string object even though it is "immutable". Only use this to
+ build up a brand new string object; don't use this if the string may already be
+ known in other parts of the code. It is an error to call this function if the
+ refcount on the input string object is not one. Pass the address of an existing
+ string object as an lvalue (it may be written into), and the new size desired.
+ On success, *string holds the resized string object and 0 is returned;
+ the address in *string may differ from its input value. If the reallocation
+ fails, the original string object at *string is deallocated, *string is
+ set to NULL, a memory exception is set, and -1 is returned.
+ """
+ # XXX always create a new string so far
+ py_str = rffi.cast(PyBytesObject, ref[0])
+ if not py_str.c_buffer:
+ raise OperationError(space.w_SystemError, space.wrap(
+ "_PyBytes_Resize called on already created string"))
+ try:
+ py_newstr = new_empty_str(space, newsize)
+ except MemoryError:
+ Py_DecRef(space, ref[0])
+ ref[0] = lltype.nullptr(PyObject.TO)
+ raise
+ to_cp = newsize
+ oldsize = py_str.c_size
+ if oldsize < newsize:
+ to_cp = oldsize
+ for i in range(to_cp):
+ py_newstr.c_buffer[i] = py_str.c_buffer[i]
+ Py_DecRef(space, ref[0])
+ ref[0] = rffi.cast(PyObject, py_newstr)
+ return 0
+
+ at cpython_api([PyObject, PyObject], rffi.INT, error=CANNOT_FAIL)
+def _PyBytes_Eq(space, w_str1, w_str2):
+ return space.eq_w(w_str1, w_str2)
+
+ at cpython_api([PyObjectP, PyObject], lltype.Void)
+def PyBytes_Concat(space, ref, w_newpart):
+ """Create a new string object in *string containing the contents of newpart
+ appended to string; the caller will own the new reference. The reference to
+ the old value of string will be stolen. If the new string cannot be created,
+ the old reference to string will still be discarded and the value of
+ *string will be set to NULL; the appropriate exception will be set."""
+
+ if not ref[0]:
+ return
+
+ if w_newpart is None or not PyBytes_Check(space, ref[0]) or \
+ not PyBytes_Check(space, w_newpart):
+ Py_DecRef(space, ref[0])
+ ref[0] = lltype.nullptr(PyObject.TO)
+ return
+ w_str = from_ref(space, ref[0])
+ w_newstr = space.add(w_str, w_newpart)
+ Py_DecRef(space, ref[0])
+ ref[0] = make_ref(space, w_newstr)
+
+ at cpython_api([PyObjectP, PyObject], lltype.Void)
+def PyBytes_ConcatAndDel(space, ref, newpart):
+ """Create a new string object in *string containing the contents of newpart
+ appended to string. This version decrements the reference count of newpart."""
+ PyBytes_Concat(space, ref, newpart)
+ Py_DecRef(space, newpart)
+
+ at cpython_api([PyObject, PyObject], PyObject)
+def _PyBytes_Join(space, w_sep, w_seq):
+ return space.call_method(w_sep, 'join', w_seq)
@cpython_api([PyObject], PyObject)
def PyBytes_FromObject(space, w_obj):
diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -104,7 +104,6 @@
#include "pythonrun.h"
#include "pyerrors.h"
#include "sysmodule.h"
-#include "stringobject.h"
#include "descrobject.h"
#include "tupleobject.h"
#include "dictobject.h"
diff --git a/pypy/module/cpyext/include/bytesobject.h b/pypy/module/cpyext/include/bytesobject.h
--- a/pypy/module/cpyext/include/bytesobject.h
+++ b/pypy/module/cpyext/include/bytesobject.h
@@ -1,30 +1,25 @@
-#define PyBytesObject PyStringObject
-#define PyBytes_Type PyString_Type
-#define PyBytes_Check PyString_Check
-#define PyBytes_CheckExact PyString_CheckExact
-#define PyBytes_CHECK_INTERNED PyString_CHECK_INTERNED
-#define PyBytes_AS_STRING PyString_AS_STRING
-#define PyBytes_GET_SIZE PyString_GET_SIZE
-#define Py_TPFLAGS_BYTES_SUBCLASS Py_TPFLAGS_STRING_SUBCLASS
+/* String object interface */
-#define PyBytes_FromStringAndSize PyString_FromStringAndSize
-#define PyBytes_FromString PyString_FromString
-#define PyBytes_FromFormatV PyString_FromFormatV
-#define PyBytes_FromFormat PyString_FromFormat
-#define PyBytes_Size PyString_Size
-#define PyBytes_AsString PyString_AsString
-#define PyBytes_Repr PyString_Repr
-#define PyBytes_Concat PyString_Concat
-#define PyBytes_ConcatAndDel PyString_ConcatAndDel
-#define _PyBytes_Resize _PyString_Resize
-#define _PyBytes_Eq _PyString_Eq
-#define PyBytes_Format PyString_Format
-#define _PyBytes_FormatLong _PyString_FormatLong
-#define PyBytes_DecodeEscape PyString_DecodeEscape
-#define _PyBytes_Join _PyString_Join
-#define PyBytes_AsStringAndSize PyString_AsStringAndSize
-#define _PyBytes_InsertThousandsGrouping _PyString_InsertThousandsGrouping
+#ifndef Py_BYTESOBJECT_H
+#define Py_BYTESOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PyBytes_GET_SIZE(op) PyBytes_Size(op)
+#define PyBytes_AS_STRING(op) PyBytes_AsString(op)
+
+typedef struct {
+ PyObject_HEAD
+ char* buffer;
+ Py_ssize_t size;
+} PyBytesObject;
#define PyByteArray_Check(obj) \
PyObject_IsInstance(obj, (PyObject *)&PyByteArray_Type)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/pypy/module/cpyext/include/stringobject.h b/pypy/module/cpyext/include/stringobject.h
deleted file mode 100644
--- a/pypy/module/cpyext/include/stringobject.h
+++ /dev/null
@@ -1,22 +0,0 @@
-
-/* String object interface */
-
-#ifndef Py_STRINGOBJECT_H
-#define Py_STRINGOBJECT_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define PyString_GET_SIZE(op) PyString_Size(op)
-#define PyString_AS_STRING(op) PyString_AsString(op)
-
-typedef struct {
- PyObject_HEAD
- char* buffer;
- Py_ssize_t size;
-} PyStringObject;
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -303,7 +303,7 @@
def from_ref(space, ref):
"""
Finds the interpreter object corresponding to the given reference. If the
- object is not yet realized (see stringobject.py), creates it.
+ object is not yet realized (see bytesobject.py), creates it.
"""
assert lltype.typeOf(ref) == PyObject
if not ref:
diff --git a/pypy/module/cpyext/sliceobject.py b/pypy/module/cpyext/sliceobject.py
--- a/pypy/module/cpyext/sliceobject.py
+++ b/pypy/module/cpyext/sliceobject.py
@@ -38,7 +38,7 @@
@cpython_api([PyObject], lltype.Void, external=False)
def slice_dealloc(space, py_obj):
- """Frees allocated PyStringObject resources.
+ """Frees allocated PySliceObject resources.
"""
py_slice = rffi.cast(PySliceObject, py_obj)
Py_DecRef(space, py_slice.c_start)
diff --git a/pypy/module/cpyext/src/getargs.c b/pypy/module/cpyext/src/getargs.c
--- a/pypy/module/cpyext/src/getargs.c
+++ b/pypy/module/cpyext/src/getargs.c
@@ -1592,6 +1592,7 @@
case 'z': /* string or None */
case 'y': /* bytes */
case 'u': /* unicode string */
+ case 'Z': /* unicode string or None */
case 'w': /* buffer, read-write */
{
(void) va_arg(*p_va, char **);
@@ -1683,6 +1684,7 @@
assert(min >= 0);
assert(min <= max);
if (!PyTuple_Check(args)) {
+ va_end(vargs);
PyErr_SetString(PyExc_SystemError,
"PyArg_UnpackTuple() argument list is not a tuple");
return 0;
diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
deleted file mode 100644
--- a/pypy/module/cpyext/stringobject.py
+++ /dev/null
@@ -1,274 +0,0 @@
-from pypy.interpreter.error import OperationError
-from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import (
- cpython_api, cpython_struct, bootstrap_function, build_type_checkers,
- PyObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL)
-from pypy.module.cpyext.pyerrors import PyErr_BadArgument
-from pypy.module.cpyext.pyobject import (
- PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
- make_typedescr, get_typedescr)
-
-##
-## Implementation of PyStringObject
-## ================================
-##
-## The problem
-## -----------
-##
-## PyString_AsString() must return a (non-movable) pointer to the underlying
-## buffer, whereas pypy strings are movable. C code may temporarily store
-## this address and use it, as long as it owns a reference to the PyObject.
-## There is no "release" function to specify that the pointer is not needed
-## any more.
-##
-## Also, the pointer may be used to fill the initial value of string. This is
-## valid only when the string was just allocated, and is not used elsewhere.
-##
-## Solution
-## --------
-##
-## PyStringObject contains two additional members: the size and a pointer to a
-## char buffer; it may be NULL.
-##
-## - A string allocated by pypy will be converted into a PyStringObject with a
-## NULL buffer. The first time PyString_AsString() is called, memory is
-## allocated (with flavor='raw') and content is copied.
-##
-## - A string allocated with PyString_FromStringAndSize(NULL, size) will
-## allocate a PyStringObject structure, and a buffer with the specified
-## size, but the reference won't be stored in the global map; there is no
-## corresponding object in pypy. When from_ref() or Py_INCREF() is called,
-## the pypy string is created, and added to the global map of tracked
-## objects. The buffer is then supposed to be immutable.
-##
-## - _PyString_Resize() works only on not-yet-pypy'd strings, and returns a
-## similar object.
-##
-## - PyString_Size() doesn't need to force the object.
-##
-## - There could be an (expensive!) check in from_ref() that the buffer still
-## corresponds to the pypy gc-managed string.
-##
-
-PyStringObjectStruct = lltype.ForwardReference()
-PyStringObject = lltype.Ptr(PyStringObjectStruct)
-PyStringObjectFields = PyObjectFields + \
- (("buffer", rffi.CCHARP), ("size", Py_ssize_t))
-cpython_struct("PyStringObject", PyStringObjectFields, PyStringObjectStruct)
-
- at bootstrap_function
-def init_stringobject(space):
- "Type description of PyStringObject"
- make_typedescr(space.w_str.instancetypedef,
- basestruct=PyStringObject.TO,
- attach=string_attach,
- dealloc=string_dealloc,
- realize=string_realize)
-
-PyString_Check, PyString_CheckExact = build_type_checkers("String", "w_str")
-
-def new_empty_str(space, length):
- """
- Allocatse a PyStringObject and its buffer, but without a corresponding
- interpreter object. The buffer may be mutated, until string_realize() is
- called.
- """
- 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
- py_str.c_size = length
- py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen,
- flavor='raw', zero=True)
- return py_str
-
-def string_attach(space, py_obj, w_obj):
- """
- Fills a newly allocated PyStringObject with the given string object. The
- buffer must not be modified.
- """
- py_str = rffi.cast(PyStringObject, py_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):
- """
- Creates the string in the interpreter. The PyStringObject buffer must not
- be modified after this call.
- """
- py_str = rffi.cast(PyStringObject, py_obj)
- s = rffi.charpsize2str(py_str.c_buffer, py_str.c_size)
- w_obj = space.wrap(s)
- track_reference(space, py_obj, w_obj)
- return w_obj
-
- at cpython_api([PyObject], lltype.Void, external=False)
-def string_dealloc(space, py_obj):
- """Frees allocated PyStringObject resources.
- """
- py_str = rffi.cast(PyStringObject, py_obj)
- if py_str.c_buffer:
- lltype.free(py_str.c_buffer, flavor="raw")
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
-
-#_______________________________________________________________________
-
- at cpython_api([CONST_STRING, Py_ssize_t], PyObject)
-def PyString_FromStringAndSize(space, char_p, length):
- if char_p:
- s = rffi.charpsize2str(char_p, length)
- return make_ref(space, space.wrapbytes(s))
- else:
- return rffi.cast(PyObject, new_empty_str(space, length))
-
- at cpython_api([CONST_STRING], PyObject)
-def PyString_FromString(space, char_p):
- s = rffi.charp2str(char_p)
- return space.wrapbytes(s)
-
- at cpython_api([PyObject], rffi.CCHARP, error=0)
-def PyString_AsString(space, ref):
- if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
- pass # typecheck returned "ok" without forcing 'ref' at all
- elif not PyString_Check(space, ref): # otherwise, use the alternate way
- raise OperationError(space.w_TypeError, space.wrap(
- "PyString_AsString only support strings"))
- ref_str = rffi.cast(PyStringObject, ref)
- if not ref_str.c_buffer:
- # copy string buffer
- w_str = from_ref(space, ref)
- s = space.bytes_w(w_str)
- ref_str.c_buffer = rffi.str2charp(s)
- return ref_str.c_buffer
-
- at cpython_api([PyObject, rffi.CCHARPP, rffi.CArrayPtr(Py_ssize_t)], rffi.INT_real, error=-1)
-def PyString_AsStringAndSize(space, ref, buffer, length):
- if not PyString_Check(space, ref):
- raise OperationError(space.w_TypeError, space.wrap(
- "PyString_AsStringAndSize only support strings"))
- ref_str = rffi.cast(PyStringObject, ref)
- if not ref_str.c_buffer:
- # copy string buffer
- w_str = from_ref(space, ref)
- s = space.bytes_w(w_str)
- ref_str.c_buffer = rffi.str2charp(s)
- buffer[0] = ref_str.c_buffer
- if length:
- length[0] = ref_str.c_size
- else:
- i = 0
- while ref_str.c_buffer[i] != '\0':
- i += 1
- if i != ref_str.c_size:
- raise OperationError(space.w_TypeError, space.wrap(
- "expected string without null bytes"))
- return 0
-
- at cpython_api([PyObject], Py_ssize_t, error=-1)
-def PyString_Size(space, ref):
- if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
- ref = rffi.cast(PyStringObject, ref)
- return ref.c_size
- else:
- w_obj = from_ref(space, ref)
- return space.len_w(w_obj)
-
- at cpython_api([PyObjectP, Py_ssize_t], rffi.INT_real, error=-1)
-def _PyString_Resize(space, ref, newsize):
- """A way to resize a string object even though it is "immutable". Only use this to
- build up a brand new string object; don't use this if the string may already be
- known in other parts of the code. It is an error to call this function if the
- refcount on the input string object is not one. Pass the address of an existing
- string object as an lvalue (it may be written into), and the new size desired.
- On success, *string holds the resized string object and 0 is returned;
- the address in *string may differ from its input value. If the reallocation
- fails, the original string object at *string is deallocated, *string is
- set to NULL, a memory exception is set, and -1 is returned.
- """
- # XXX always create a new string so far
- py_str = rffi.cast(PyStringObject, ref[0])
- if not py_str.c_buffer:
- raise OperationError(space.w_SystemError, space.wrap(
- "_PyString_Resize called on already created string"))
- try:
- py_newstr = new_empty_str(space, newsize)
- except MemoryError:
- Py_DecRef(space, ref[0])
- ref[0] = lltype.nullptr(PyObject.TO)
- raise
- to_cp = newsize
- oldsize = py_str.c_size
- if oldsize < newsize:
- to_cp = oldsize
- for i in range(to_cp):
- py_newstr.c_buffer[i] = py_str.c_buffer[i]
- Py_DecRef(space, ref[0])
- ref[0] = rffi.cast(PyObject, py_newstr)
- return 0
-
- at cpython_api([PyObject, PyObject], rffi.INT, error=CANNOT_FAIL)
-def _PyString_Eq(space, w_str1, w_str2):
- return space.eq_w(w_str1, w_str2)
-
- at cpython_api([PyObjectP, PyObject], lltype.Void)
-def PyString_Concat(space, ref, w_newpart):
- """Create a new string object in *string containing the contents of newpart
- appended to string; the caller will own the new reference. The reference to
- the old value of string will be stolen. If the new string cannot be created,
- the old reference to string will still be discarded and the value of
- *string will be set to NULL; the appropriate exception will be set."""
-
- if not ref[0]:
- return
-
- if w_newpart is None or not PyString_Check(space, ref[0]) or \
- not PyString_Check(space, w_newpart):
- Py_DecRef(space, ref[0])
- ref[0] = lltype.nullptr(PyObject.TO)
- return
- w_str = from_ref(space, ref[0])
- w_newstr = space.add(w_str, w_newpart)
- Py_DecRef(space, ref[0])
- ref[0] = make_ref(space, w_newstr)
-
- at cpython_api([PyObjectP, PyObject], lltype.Void)
-def PyString_ConcatAndDel(space, ref, newpart):
- """Create a new string object in *string containing the contents of newpart
- appended to string. This version decrements the reference count of newpart."""
- PyString_Concat(space, ref, newpart)
- Py_DecRef(space, newpart)
-
- at cpython_api([CONST_STRING], PyObject)
-def PyString_InternFromString(space, string):
- """A combination of PyString_FromString() and
- PyString_InternInPlace(), returning either a new string object that has
- been interned, or a new ("owned") reference to an earlier interned string
- object with the same value."""
- s = rffi.charp2str(string)
- return space.new_interned_str(s)
-
- at cpython_api([PyObjectP], lltype.Void)
-def PyString_InternInPlace(space, string):
- """Intern the argument *string in place. The argument must be the
- address of a pointer variable pointing to a Python string object.
- If there is an existing interned string that is the same as
- *string, it sets *string to it (decrementing the reference count
- of the old string object and incrementing the reference count of
- the interned string object), otherwise it leaves *string alone and
- interns it (incrementing its reference count). (Clarification:
- even though there is a lot of talk about reference counts, think
- of this function as reference-count-neutral; you own the object
- after the call if and only if you owned it before the call.)
-
- This function is not available in 3.x and does not have a PyBytes
- alias."""
- w_str = from_ref(space, string[0])
- w_str = space.new_interned_w_str(w_str)
- Py_DecRef(space, string[0])
- string[0] = make_ref(space, w_str)
-
- at 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_bytesobject.py b/pypy/module/cpyext/test/test_bytesobject.py
--- a/pypy/module/cpyext/test/test_bytesobject.py
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -1,6 +1,217 @@
+from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.bytesobject import new_empty_str, PyBytesObject
+from pypy.module.cpyext.api import PyObjectP, PyObject, Py_ssize_tP
+from pypy.module.cpyext.pyobject import Py_DecRef, from_ref, make_ref
+
+import py
+import sys
+
+class AppTestBytesObject(AppTestCpythonExtensionBase):
+ def test_bytesobject(self):
+ module = self.import_extension('foo', [
+ ("get_hello1", "METH_NOARGS",
+ """
+ return PyBytes_FromStringAndSize(
+ "Hello world<should not be included>", 11);
+ """),
+ ("get_hello2", "METH_NOARGS",
+ """
+ return PyBytes_FromString("Hello world");
+ """),
+ ("test_Size", "METH_NOARGS",
+ """
+ PyObject* s = PyBytes_FromString("Hello world");
+ int result = 0;
+
+ if(PyBytes_Size(s) == 11) {
+ result = 1;
+ }
+ if(s->ob_type->tp_basicsize != sizeof(void*)*4)
+ result = 0;
+ Py_DECREF(s);
+ return PyBool_FromLong(result);
+ """),
+ ("test_Size_exception", "METH_NOARGS",
+ """
+ PyObject* f = PyFloat_FromDouble(1.0);
+ Py_ssize_t size = PyBytes_Size(f);
+
+ Py_DECREF(f);
+ return NULL;
+ """),
+ ("test_is_bytes", "METH_VARARGS",
+ """
+ return PyBool_FromLong(PyBytes_Check(PyTuple_GetItem(args, 0)));
+ """)])
+ 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_bytes(b"")
+ assert not module.test_is_bytes(())
+
+ def test_bytes_buffer_init(self):
+ module = self.import_extension('foo', [
+ ("getbytes", "METH_NOARGS",
+ """
+ PyObject *s, *t;
+ char* c;
+ Py_ssize_t len;
+
+ s = PyBytes_FromStringAndSize(NULL, 4);
+ if (s == NULL)
+ return NULL;
+ t = PyBytes_FromStringAndSize(NULL, 3);
+ if (t == NULL)
+ return NULL;
+ Py_DECREF(t);
+ c = PyBytes_AsString(s);
+ c[0] = 'a';
+ c[1] = 'b';
+ c[3] = 'c';
+ return s;
+ """),
+ ])
+ s = module.getbytes()
+ assert len(s) == 4
+ assert s == 'ab\x00c'
+
+
+
+ def test_AsString(self):
+ module = self.import_extension('foo', [
+ ("getbytes", "METH_NOARGS",
+ """
+ PyObject* s1 = PyBytes_FromStringAndSize("test", 4);
+ char* c = PyBytes_AsString(s1);
+ PyObject* s2 = PyBytes_FromStringAndSize(c, 4);
+ Py_DECREF(s1);
+ return s2;
+ """),
+ ])
+ s = module.getbytes()
+ assert s == b'test'
+
+ def test_py_bytes_as_string(self):
+ module = self.import_extension('foo', [
+ ("bytes_as_string", "METH_VARARGS",
+ '''
+ return PyBytes_FromStringAndSize(PyBytes_AsString(
+ PyTuple_GetItem(args, 0)), 4);
+ '''
+ )])
+ assert module.bytes_as_string(b"huheduwe") == b"huhe"
+
+ def test_py_bytes_as_string_None(self):
+ module = self.import_extension('foo', [
+ ("string_None", "METH_VARARGS",
+ '''
+ return PyBytes_AsString(Py_None);
+ '''
+ )])
+ raises(TypeError, module.string_None)
+
+ def test_AsStringAndSize(self):
+ module = self.import_extension('foo', [
+ ("getbytes", "METH_NOARGS",
+ """
+ PyObject* s1 = PyBytes_FromStringAndSize("te\\0st", 5);
+ char *buf;
+ Py_ssize_t len;
+ if (PyBytes_AsStringAndSize(s1, &buf, &len) < 0)
+ return NULL;
+ if (len != 5) {
+ PyErr_SetString(PyExc_AssertionError, "Bad Length");
+ return NULL;
+ }
+ if (PyBytes_AsStringAndSize(s1, &buf, NULL) >= 0) {
+ PyErr_SetString(PyExc_AssertionError, "Should Have failed");
+ return NULL;
+ }
+ PyErr_Clear();
+ Py_DECREF(s1);
+ Py_INCREF(Py_None);
+ return Py_None;
+ """),
+ ])
+ module.getbytes()
+
class TestBytes(BaseApiTest):
+ def test_bytes_resize(self, space, api):
+ py_str = new_empty_str(space, 10)
+ ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+ py_str.c_buffer[0] = 'a'
+ py_str.c_buffer[1] = 'b'
+ py_str.c_buffer[2] = 'c'
+ ar[0] = rffi.cast(PyObject, py_str)
+ api._PyBytes_Resize(ar, 3)
+ py_str = rffi.cast(PyBytesObject, ar[0])
+ assert py_str.c_size == 3
+ assert py_str.c_buffer[1] == 'b'
+ assert py_str.c_buffer[3] == '\x00'
+ # the same for growing
+ ar[0] = rffi.cast(PyObject, py_str)
+ api._PyBytes_Resize(ar, 10)
+ py_str = rffi.cast(PyBytesObject, ar[0])
+ assert py_str.c_size == 10
+ assert py_str.c_buffer[1] == 'b'
+ assert py_str.c_buffer[10] == '\x00'
+ Py_DecRef(space, ar[0])
+ lltype.free(ar, flavor='raw')
+
+ def test_Concat(self, space, api):
+ ref = make_ref(space, space.wrapbytes('abc'))
+ ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+ ptr[0] = ref
+ api.PyBytes_Concat(ptr, space.wrapbytes('def'))
+ assert space.bytes_w(from_ref(space, ptr[0])) == 'abcdef'
+ api.PyBytes_Concat(ptr, space.w_None)
+ assert not ptr[0]
+ ptr[0] = lltype.nullptr(PyObject.TO)
+ api.PyBytes_Concat(ptr, space.wrapbytes('def')) # should not crash
+ lltype.free(ptr, flavor='raw')
+
+ def test_ConcatAndDel(self, space, api):
+ 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.PyBytes_ConcatAndDel(ptr, ref2)
+ 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.wrapbytes('foo'))
+ api.PyBytes_ConcatAndDel(ptr, ref2) # should not crash
+ assert ref2.c_ob_refcnt == 0
+ lltype.free(ptr, flavor='raw')
+
+ 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.wrapbytes("text")
+ assert api.PyObject_AsCharBuffer(w_text, bufp, lenp) == 0
+ assert lenp[0] == 4
+ assert rffi.charp2str(bufp[0]) == 'text'
+
+ lltype.free(bufp, flavor='raw')
+ lltype.free(lenp, flavor='raw')
+
+ def test_eq(self, space, api):
+ assert 1 == api._PyBytes_Eq(space.wrapbytes("hello"), space.wrapbytes("hello"))
+ assert 0 == api._PyBytes_Eq(space.wrapbytes("hello"), space.wrapbytes("world"))
+
+ def test_join(self, space, api):
+ w_sep = space.wrapbytes('<sep>')
+ w_seq = space.newtuple([space.wrapbytes('a'), space.wrapbytes('b')])
+ w_joined = api._PyBytes_Join(w_sep, w_seq)
+ assert space.bytes_w(w_joined) == 'a<sep>b'
+
def test_FromObject(self, space, api):
w_obj = space.wrapbytes("test")
assert space.eq_w(w_obj, api.PyBytes_FromObject(w_obj))
diff --git a/pypy/module/cpyext/test/test_floatobject.py b/pypy/module/cpyext/test/test_floatobject.py
--- a/pypy/module/cpyext/test/test_floatobject.py
+++ b/pypy/module/cpyext/test/test_floatobject.py
@@ -36,7 +36,7 @@
module = self.import_extension('foo', [
("from_string", "METH_NOARGS",
"""
- PyObject* str = PyString_FromString("1234.56");
+ PyObject* str = PyUnicode_FromString("1234.56");
PyObject* res = PyFloat_FromString(str, NULL);
Py_DECREF(str);
return res;
diff --git a/pypy/module/cpyext/test/test_frameobject.py b/pypy/module/cpyext/test/test_frameobject.py
--- a/pypy/module/cpyext/test/test_frameobject.py
+++ b/pypy/module/cpyext/test/test_frameobject.py
@@ -9,7 +9,7 @@
PyObject *py_srcfile = PyUnicode_FromString("filename");
PyObject *py_funcname = PyUnicode_FromString("funcname");
PyObject *py_globals = PyDict_New();
- PyObject *empty_bytes = PyString_FromString("");
+ PyObject *empty_bytes = PyBytes_FromString("");
PyObject *empty_tuple = PyTuple_New(0);
PyCodeObject *py_code;
PyFrameObject *py_frame;
diff --git a/pypy/module/cpyext/test/test_getargs.py b/pypy/module/cpyext/test/test_getargs.py
--- a/pypy/module/cpyext/test/test_getargs.py
+++ b/pypy/module/cpyext/test/test_getargs.py
@@ -122,7 +122,7 @@
if (!PyArg_ParseTuple(args, "s*", &buf)) {
return NULL;
}
- result = PyString_FromStringAndSize(buf.buf, buf.len);
+ result = PyBytes_FromStringAndSize(buf.buf, buf.len);
PyBuffer_Release(&buf);
return result;
''')
@@ -164,7 +164,7 @@
if (!PyArg_ParseTuple(args, "s#", &buf, &len)) {
return NULL;
}
- return PyString_FromStringAndSize(buf, len);
+ return PyBytes_FromStringAndSize(buf, len);
''')
raises(TypeError, "charbuf(10)")
assert b'foo\0bar\0baz' == charbuf(b'foo\0bar\0baz')
diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -229,16 +229,16 @@
("fillinfo", "METH_VARARGS",
"""
Py_buffer buf;
- PyObject *str = PyString_FromString("hello, world.");
+ PyObject *str = PyBytes_FromString("hello, world.");
PyObject *result;
- if (PyBuffer_FillInfo(&buf, NULL, PyString_AsString(str), 13, 0, 0)) {
+ if (PyBuffer_FillInfo(&buf, NULL, PyBytes_AsString(str), 13, 0, 0)) {
return NULL;
}
/* Check a few things we want to have happened.
*/
- if (buf.buf != PyString_AsString(str)) {
+ if (buf.buf != PyBytes_AsString(str)) {
PyErr_SetString(PyExc_ValueError, "buf field not initialized");
return NULL;
}
@@ -256,7 +256,7 @@
/* Give back a new string to the caller, constructed from data in the
* Py_buffer.
*/
- if (!(result = PyString_FromStringAndSize(buf.buf, buf.len))) {
+ if (!(result = PyBytes_FromStringAndSize(buf.buf, buf.len))) {
return NULL;
}
@@ -281,10 +281,10 @@
("fillinfo", "METH_VARARGS",
"""
Py_buffer buf;
- PyObject *str = PyString_FromString("hello, world.");
+ PyObject *str = PyBytes_FromString("hello, world.");
PyObject *result;
- if (PyBuffer_FillInfo(&buf, str, PyString_AsString(str), 13, 0, 0)) {
+ if (PyBuffer_FillInfo(&buf, str, PyBytes_AsString(str), 13, 0, 0)) {
return NULL;
}
@@ -296,7 +296,7 @@
/* Give back a new string to the caller, constructed from data in the
* Py_buffer. It better still be valid.
*/
- if (!(result = PyString_FromStringAndSize(buf.buf, buf.len))) {
+ if (!(result = PyBytes_FromStringAndSize(buf.buf, buf.len))) {
return NULL;
}
@@ -327,10 +327,10 @@
("fillinfo", "METH_VARARGS",
"""
Py_buffer buf;
- PyObject *str = PyString_FromString("hello, world.");
+ PyObject *str = PyBytes_FromString("hello, world.");
PyObject *result;
- if (PyBuffer_FillInfo(&buf, str, PyString_AsString(str), 13,
+ if (PyBuffer_FillInfo(&buf, str, PyBytes_AsString(str), 13,
1, PyBUF_WRITABLE)) {
Py_DECREF(str);
return NULL;
@@ -355,9 +355,9 @@
("release", "METH_VARARGS",
"""
Py_buffer buf;
- buf.obj = PyString_FromString("release me!");
- buf.buf = PyString_AsString(buf.obj);
- buf.len = PyString_Size(buf.obj);
+ buf.obj = PyBytes_FromString("release me!");
+ buf.buf = PyBytes_AsString(buf.obj);
+ buf.len = PyBytes_Size(buf.obj);
/* The Py_buffer owns the only reference to that string. Release the
* Py_buffer and the string should be released as well.
diff --git a/pypy/module/cpyext/test/test_stringobject.py b/pypy/module/cpyext/test/test_stringobject.py
deleted file mode 100644
--- a/pypy/module/cpyext/test/test_stringobject.py
+++ /dev/null
@@ -1,233 +0,0 @@
-from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.test.test_api import BaseApiTest
-from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
-from pypy.module.cpyext.stringobject import new_empty_str, PyStringObject
-from pypy.module.cpyext.api import PyObjectP, PyObject, Py_ssize_tP
-from pypy.module.cpyext.pyobject import Py_DecRef, from_ref, make_ref
-
-import py
-import sys
-
-class AppTestStringObject(AppTestCpythonExtensionBase):
- def test_stringobject(self):
- module = self.import_extension('foo', [
- ("get_hello1", "METH_NOARGS",
- """
- return PyString_FromStringAndSize(
- "Hello world<should not be included>", 11);
- """),
- ("get_hello2", "METH_NOARGS",
- """
- return PyString_FromString("Hello world");
- """),
- ("test_Size", "METH_NOARGS",
- """
- PyObject* s = PyString_FromString("Hello world");
- int result = 0;
-
- if(PyString_Size(s) == 11) {
- result = 1;
- }
- if(s->ob_type->tp_basicsize != sizeof(void*)*4)
- result = 0;
- Py_DECREF(s);
- return PyBool_FromLong(result);
- """),
- ("test_Size_exception", "METH_NOARGS",
- """
- PyObject* f = PyFloat_FromDouble(1.0);
- Py_ssize_t size = PyString_Size(f);
-
- Py_DECREF(f);
- return NULL;
- """),
- ("test_is_string", "METH_VARARGS",
- """
- return PyBool_FromLong(PyString_Check(PyTuple_GetItem(args, 0)));
- """)])
- 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(b"")
- assert not module.test_is_string(())
-
- def test_string_buffer_init(self):
- module = self.import_extension('foo', [
- ("getstring", "METH_NOARGS",
- """
- PyObject *s, *t;
- char* c;
- Py_ssize_t len;
-
- s = PyString_FromStringAndSize(NULL, 4);
- if (s == NULL)
- return NULL;
- t = PyString_FromStringAndSize(NULL, 3);
- if (t == NULL)
- return NULL;
- Py_DECREF(t);
- c = PyString_AsString(s);
- c[0] = 'a';
- c[1] = 'b';
- c[3] = 'c';
- return s;
- """),
- ])
- s = module.getstring()
- assert len(s) == 4
- assert s == 'ab\x00c'
-
-
-
- def test_AsString(self):
- module = self.import_extension('foo', [
- ("getstring", "METH_NOARGS",
- """
- PyObject* s1 = PyString_FromStringAndSize("test", 4);
- char* c = PyString_AsString(s1);
- PyObject* s2 = PyString_FromStringAndSize(c, 4);
- Py_DECREF(s1);
- return s2;
- """),
- ])
- s = module.getstring()
- assert s == b'test'
-
- def test_py_string_as_string(self):
- module = self.import_extension('foo', [
- ("string_as_string", "METH_VARARGS",
- '''
- return PyString_FromStringAndSize(PyString_AsString(
- PyTuple_GetItem(args, 0)), 4);
- '''
- )])
- assert module.string_as_string(b"huheduwe") == b"huhe"
-
- def test_py_string_as_string_None(self):
- module = self.import_extension('foo', [
- ("string_None", "METH_VARARGS",
- '''
- return PyString_AsString(Py_None);
- '''
- )])
- raises(TypeError, module.string_None)
-
- def test_AsStringAndSize(self):
- module = self.import_extension('foo', [
- ("getstring", "METH_NOARGS",
- """
- PyObject* s1 = PyString_FromStringAndSize("te\\0st", 5);
- char *buf;
- Py_ssize_t len;
- if (PyString_AsStringAndSize(s1, &buf, &len) < 0)
- return NULL;
- if (len != 5) {
- PyErr_SetString(PyExc_AssertionError, "Bad Length");
- return NULL;
- }
- if (PyString_AsStringAndSize(s1, &buf, NULL) >= 0) {
- PyErr_SetString(PyExc_AssertionError, "Should Have failed");
- return NULL;
- }
- PyErr_Clear();
- Py_DECREF(s1);
- Py_INCREF(Py_None);
- return Py_None;
- """),
- ])
- module.getstring()
-
- def test_intern_inplace(self):
- module = self.import_extension('foo', [
- ("test_intern_inplace", "METH_O",
- '''
- PyObject *s = args;
- Py_INCREF(s);
- PyString_InternInPlace(&s);
- return s;
- '''
- )
- ])
- # This does not test much, but at least the refcounts are checked.
- assert module.test_intern_inplace('s') == 's'
-
-class TestString(BaseApiTest):
- def test_string_resize(self, space, api):
- py_str = new_empty_str(space, 10)
- ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
- py_str.c_buffer[0] = 'a'
- py_str.c_buffer[1] = 'b'
- py_str.c_buffer[2] = 'c'
- ar[0] = rffi.cast(PyObject, py_str)
- api._PyString_Resize(ar, 3)
- py_str = rffi.cast(PyStringObject, ar[0])
- assert py_str.c_size == 3
- assert py_str.c_buffer[1] == 'b'
- assert py_str.c_buffer[3] == '\x00'
- # the same for growing
- ar[0] = rffi.cast(PyObject, py_str)
- api._PyString_Resize(ar, 10)
- py_str = rffi.cast(PyStringObject, ar[0])
- assert py_str.c_size == 10
- assert py_str.c_buffer[1] == 'b'
- assert py_str.c_buffer[10] == '\x00'
- Py_DecRef(space, ar[0])
- lltype.free(ar, flavor='raw')
-
- def test_Concat(self, space, api):
- ref = make_ref(space, space.wrapbytes('abc'))
- ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
- ptr[0] = ref
- 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.wrapbytes('def')) # should not crash
- lltype.free(ptr, flavor='raw')
-
- def test_ConcatAndDel(self, space, api):
- 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.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.wrapbytes('foo'))
- api.PyString_ConcatAndDel(ptr, ref2) # should not crash
- assert ref2.c_ob_refcnt == 0
- lltype.free(ptr, flavor='raw')
-
- 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.wrapbytes("text")
- assert api.PyObject_AsCharBuffer(w_text, bufp, lenp) == 0
- assert lenp[0] == 4
- assert rffi.charp2str(bufp[0]) == 'text'
-
- lltype.free(bufp, flavor='raw')
- lltype.free(lenp, flavor='raw')
-
- def test_intern(self, space, api):
- buf = rffi.str2charp("test")
- w_s1 = api.PyString_InternFromString(buf)
- w_s2 = api.PyString_InternFromString(buf)
- rffi.free_charp(buf)
- assert w_s1 is w_s2
-
- def test_eq(self, space, api):
- 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.wrapbytes('<sep>')
- w_seq = space.newtuple([space.wrapbytes('a'), space.wrapbytes('b')])
- w_joined = api._PyString_Join(w_sep, w_seq)
- assert space.bytes_w(w_joined) == 'a<sep>b'
diff --git a/pypy/module/cpyext/test/test_structseq.py b/pypy/module/cpyext/test/test_structseq.py
--- a/pypy/module/cpyext/test/test_structseq.py
+++ b/pypy/module/cpyext/test/test_structseq.py
@@ -35,8 +35,8 @@
if (!seq) return NULL;
PyStructSequence_SET_ITEM(seq, 0, PyInt_FromLong(42));
PyStructSequence_SET_ITEM(seq, 1, PyInt_FromLong(43));
- PyStructSequence_SET_ITEM(seq, 2, PyString_FromString("hello"));
- PyStructSequence_SET_ITEM(seq, 3, PyString_FromString("other"));
+ PyStructSequence_SET_ITEM(seq, 2, PyUnicode_FromString("hello"));
+ PyStructSequence_SET_ITEM(seq, 3, PyUnicode_FromString("other"));
Py_DECREF(&PyDatatype);
return seq;
""")])
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
@@ -388,19 +388,19 @@
@cpython_api([PyObject, lltype.Ptr(Py_buffer), rffi.INT_real], rffi.INT_real,
external=False, error=-1)
-def str_getbuffer(space, w_str, view, flags):
- from pypy.module.cpyext.stringobject import PyString_AsString
+def bytes_getbuffer(space, w_str, view, flags):
+ from pypy.module.cpyext.bytesobject import PyBytes_AsString
view.c_obj = make_ref(space, w_str)
- view.c_buf = rffi.cast(rffi.VOIDP, PyString_AsString(space, view.c_obj))
+ view.c_buf = rffi.cast(rffi.VOIDP, PyBytes_AsString(space, view.c_obj))
view.c_len = space.len_w(w_str)
return 0
-def setup_string_buffer_procs(space, pto):
+def setup_bytes_buffer_procs(space, pto):
c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
lltype.render_immortal(c_buf)
c_buf.c_bf_getbuffer = llhelper(
- str_getbuffer.api_func.functype,
- str_getbuffer.api_func.get_wrapper(space))
+ bytes_getbuffer.api_func.functype,
+ bytes_getbuffer.api_func.get_wrapper(space))
pto.c_tp_as_buffer = c_buf
pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
@@ -458,7 +458,7 @@
pto.c_tp_dealloc = typedescr.get_dealloc(space)
# buffer protocol
if space.is_w(w_type, space.w_str):
- setup_string_buffer_procs(space, pto)
+ setup_bytes_buffer_procs(space, pto)
pto.c_tp_free = llhelper(PyObject_Del.api_func.functype,
PyObject_Del.api_func.get_wrapper(space))
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
@@ -10,8 +10,7 @@
from pypy.module.cpyext.pyobject import (
PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
make_typedescr, get_typedescr)
-from pypy.module.cpyext.stringobject import PyString_Check
-from pypy.module.cpyext.bytesobject import PyBytes_FromObject
+from pypy.module.cpyext.bytesobject import PyBytes_Check, PyBytes_FromObject
from pypy.module._codecs.interp_codecs import CodecState
from pypy.module.posix.interp_posix import fsencode, fsdecode
from pypy.objspace.std import unicodeobject, unicodetype, stringtype
@@ -19,7 +18,7 @@
from pypy.tool.sourcetools import func_renamer
import sys
-## See comment in stringobject.py.
+## See comment in bytesobject.py.
PyUnicodeObjectStruct = lltype.ForwardReference()
PyUnicodeObject = lltype.Ptr(PyUnicodeObjectStruct)
@@ -310,9 +309,9 @@
the Python codec registry. Return NULL if an exception was raised by the
codec."""
w_str = PyUnicode_AsEncodedObject(space, w_unicode, llencoding, llerrors)
- if not PyString_Check(space, w_str):
+ if not PyBytes_Check(space, w_str):
raise OperationError(space.w_TypeError, space.wrap(
- "encoder did not return a string object"))
+ "encoder did not return a bytes object"))
return w_str
@cpython_api([PyObject], PyObject)
More information about the pypy-commit
mailing list