From: Stefan Behnel Date: Fri, 27 Dec 2013 16:12:09 +0000 (+0100) Subject: handle Py2 compatibility case bytearray.append(pychar) X-Git-Tag: 0.20b1~51^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d7fc44db1d3913148693cf3e0513f4360988634b;p=platform%2Fupstream%2Fpython-cython.git handle Py2 compatibility case bytearray.append(pychar) --HG-- extra : amend_source : f3b7f004f905c791e6ced2a5b27fffa21f9ceb08 --- diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py index 68a8f10..ecac9da 100644 --- a/Cython/Compiler/Builtin.py +++ b/Cython/Compiler/Builtin.py @@ -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", diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index c66ba20..ea2002c 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -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), diff --git a/Cython/Utility/StringTools.c b/Cython/Utility/StringTools.c index da71ef6..c8ea40c 100644 --- a/Cython/Utility/StringTools.c +++ b/Cython/Utility/StringTools.c @@ -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); diff --git a/tests/run/bytearraymethods.pyx b/tests/run/bytearraymethods.pyx index 6816972..16c9d5f 100644 --- a/tests/run/bytearraymethods.pyx +++ b/tests/run/bytearraymethods.pyx @@ -1,3 +1,7 @@ + +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)