Commit d7fc44db authored by Stefan Behnel's avatar Stefan Behnel

handle Py2 compatibility case bytearray.append(pychar)

--HG--
extra : amend_source : f3b7f004f905c791e6ced2a5b27fffa21f9ceb08
parent 6b2cb1d4
......@@ -281,8 +281,6 @@ builtin_types_table = [
utility_code=UtilityCode.load("StringJoin", "StringTools.c")),
]),
("bytearray", "PyByteArray_Type", [
BuiltinMethod("append", "Tz", "r", "__Pyx_PyByteArray_Append",
utility_code=UtilityCode.load("ByteArrayAppend", "StringTools.c")),
]),
("bytes", "PyBytes_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"),
BuiltinMethod("join", "TO", "O", "__Pyx_PyBytes_Join",
......
......@@ -2379,6 +2379,53 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
utility_code=load_c_utility('append')
)
PyByteArray_Append_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_returncode_type, [
PyrexTypes.CFuncTypeArg("bytearray", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("value", PyrexTypes.c_int_type, None),
],
exception_value="-1")
PyByteArray_AppendObject_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_returncode_type, [
PyrexTypes.CFuncTypeArg("bytearray", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("value", PyrexTypes.py_object_type, None),
],
exception_value="-1")
def _handle_simple_method_bytearray_append(self, node, function, args, is_unbound_method):
if len(args) != 2:
return node
func_name = "__Pyx_PyByteArray_Append"
func_type = self.PyByteArray_Append_func_type
value = unwrap_coerced_node(args[1])
if value.type.is_int:
value = value.coerce_to(PyrexTypes.c_int_type, self.current_env())
utility_code = UtilityCode.load_cached("ByteArrayAppend", "StringTools.c")
elif value.is_string_literal:
if not value.can_coerce_to_char_literal():
return node
value = value.coerce_to(PyrexTypes.c_char_type, self.current_env())
utility_code = UtilityCode.load_cached("ByteArrayAppend", "StringTools.c")
elif value.type.is_pyobject:
func_name = "__Pyx_PyByteArray_AppendObject"
func_type = self.PyByteArray_AppendObject_func_type
utility_code = UtilityCode.load_cached("ByteArrayAppendObject", "StringTools.c")
else:
return node
new_node = ExprNodes.PythonCapiCallNode(
node.pos, func_name, func_type,
args=[args[0], value],
may_return_none=False,
is_temp=node.is_temp,
utility_code=utility_code,
)
if node.result_is_used:
new_node = new_node.coerce_to(node.type, self.current_env())
return new_node
PyObject_Pop_func_type = PyrexTypes.CFuncType(
PyrexTypes.py_object_type, [
PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None),
......
......@@ -680,25 +680,54 @@ static CYTHON_INLINE PyObject* __Pyx_PyBytes_Join(PyObject* sep, PyObject* value
#endif
//////////////////// ByteArrayAppendObject.proto ////////////////////
static CYTHON_INLINE int __Pyx_PyByteArray_AppendObject(PyObject* bytearray, PyObject* value);
//////////////////// ByteArrayAppendObject ////////////////////
//@requires: ByteArrayAppend
static CYTHON_INLINE int __Pyx_PyByteArray_AppendObject(PyObject* bytearray, PyObject* value) {
Py_ssize_t ival;
#if PY_MAJOR_VERSION < 3
if (unlikely(PyString_Check(value))) {
if (unlikely(PyString_GET_SIZE(value) != 1)) {
PyErr_SetString(PyExc_ValueError, "string must be of size 1");
return -1;
}
ival = PyString_AS_STRING(value)[0];
} else
#endif
{
ival = __Pyx_PyIndex_AsSsize_t(value);
if (unlikely(ival == -1 && PyErr_Occurred()))
return -1;
}
return __Pyx_PyByteArray_Append(bytearray, ival);
}
//////////////////// ByteArrayAppend.proto ////////////////////
static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, Py_ssize_t value);
static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, int value);
//////////////////// ByteArrayAppend ////////////////////
//@requires: ObjectHandling.c::PyObjectCallMethod
// signature uses Py_ssize_t to make coercions use PyNumber_Index(), as CPython does
static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, Py_ssize_t value) {
static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, int value) {
PyObject *pyval, *retval;
#if CYTHON_COMPILING_IN_CPYTHON
Py_ssize_t n = Py_SIZE(bytearray);
if (likely((value >= 0) & (value <= 255))) {
if (likely(n < PY_SSIZE_T_MAX)) {
Py_ssize_t n = Py_SIZE(bytearray);
if (likely(n != PY_SSIZE_T_MAX)) {
if (unlikely(PyByteArray_Resize(bytearray, n + 1) < 0))
return -1;
PyByteArray_AS_STRING(bytearray)[n] = value;
return 0;
}
} else {
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
return -1;
}
#endif
pyval = PyInt_FromLong(value);
......
import sys
IS_PY3 = sys.version_info[0] >= 3
cimport cython
b_a = bytearray(b'a')
......@@ -197,47 +201,52 @@ def bytearray_decode_unbound_method(bytearray s, start=None, stop=None):
def bytearray_append(bytearray b, char c, int i, object o):
"""
>>> b = bytearray('abc'.encode('ascii'))
>>> b = bytearray(b'abc')
>>> b = bytearray_append(b, ord('x'), ord('y'), ord('z'))
>>> print(b.decode('ascii'))
abcXxyz
>>> b = bytearray('abc'.encode('ascii'))
>>> b = bytearray(b'abc')
>>> b = bytearray_append(b, ord('x'), ord('y'), ord('z') if IS_PY3 else b'z')
>>> print(b.decode('ascii'))
abcXxyz
>>> b = bytearray(b'abc')
>>> b = bytearray_append(b, -1, ord('y'), ord('z')) # doctest: +ELLIPSIS
Traceback (most recent call last):
ValueError: ...
>>> print(b.decode('ascii'))
abcX
>>> b = bytearray('abc'.encode('ascii'))
>>> b = bytearray(b'abc')
>>> b = bytearray_append(b, ord('x'), -1, ord('z')) # doctest: +ELLIPSIS
Traceback (most recent call last):
ValueError: ...
>>> print(b.decode('ascii'))
abcXx
>>> b = bytearray('abc'.encode('ascii'))
>>> b = bytearray(b'abc')
>>> b = bytearray_append(b, ord('x'), 256, ord('z')) # doctest: +ELLIPSIS
Traceback (most recent call last):
ValueError: ...
>>> print(b.decode('ascii'))
abcXx
>>> b = bytearray('abc'.encode('ascii'))
>>> b = bytearray(b'abc')
>>> b = bytearray_append(b, ord('x'), ord('y'), -1) # doctest: +ELLIPSIS
Traceback (most recent call last):
ValueError: ...
>>> print(b.decode('ascii'))
abcXxy
>>> b = bytearray('abc'.encode('ascii'))
>>> b = bytearray(b'abc')
>>> b = bytearray_append(b, ord('x'), ord('y'), 256) # doctest: +ELLIPSIS
Traceback (most recent call last):
ValueError: ...
>>> print(b.decode('ascii'))
abcXxy
"""
b.append('X')
assert b.append('X') is None
b.append(c)
b.append(i)
b.append(o)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment