diff options
Diffstat (limited to 'tests/samplebinding')
-rw-r--r-- | tests/samplebinding/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/samplebinding/bytearray_bufferprotocol.cpp | 27 | ||||
-rw-r--r-- | tests/samplebinding/bytearray_conversions.h | 28 | ||||
-rw-r--r-- | tests/samplebinding/bytearray_test.py | 145 | ||||
-rw-r--r-- | tests/samplebinding/global.h | 1 | ||||
-rw-r--r-- | tests/samplebinding/typesystem_sample.xml | 104 |
6 files changed, 306 insertions, 0 deletions
diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index 23a3c456c..f63ecf981 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -14,6 +14,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/base4_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/base5_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/base6_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/blackbox_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/bytearray_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/bucket_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/collector_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/color_wrapper.cpp diff --git a/tests/samplebinding/bytearray_bufferprotocol.cpp b/tests/samplebinding/bytearray_bufferprotocol.cpp new file mode 100644 index 000000000..b3a6a83f4 --- /dev/null +++ b/tests/samplebinding/bytearray_bufferprotocol.cpp @@ -0,0 +1,27 @@ +#if PY_VERSION_HEX < 0x03000000 +// ByteArray buffer protocol functions +// See: http://www.python.org/dev/peps/pep-3118/ +extern "C" { +static Py_ssize_t SbkByteArray_segcountproc(PyObject* self, Py_ssize_t* lenp) +{ + if (lenp) + *lenp = self->ob_type->tp_as_sequence->sq_length(self); + return 1; +} +static Py_ssize_t SbkByteArray_readbufferproc(PyObject* self, Py_ssize_t segment, void** ptrptr) +{ + if (segment || !Shiboken::Object::isValid(self)) + return -1; + + ByteArray* cppSelf = Shiboken::Converter<ByteArray*>::toCpp(self); + *ptrptr = reinterpret_cast<void*>(const_cast<char*>(cppSelf->data())); + return cppSelf->size(); +} +PyBufferProcs SbkByteArrayBufferProc = { + /*bf_getreadbuffer*/ &SbkByteArray_readbufferproc, + /*bf_getwritebuffer*/ (writebufferproc)&SbkByteArray_readbufferproc, + /*bf_getsegcount*/ &SbkByteArray_segcountproc, + /*bf_getcharbuffer*/ (charbufferproc)&SbkByteArray_readbufferproc +}; +} +#endif diff --git a/tests/samplebinding/bytearray_conversions.h b/tests/samplebinding/bytearray_conversions.h new file mode 100644 index 000000000..79a070d7b --- /dev/null +++ b/tests/samplebinding/bytearray_conversions.h @@ -0,0 +1,28 @@ +namespace Shiboken { +inline bool Converter<ByteArray>::checkType(PyObject* pyObj) +{ + return ValueTypeConverter<ByteArray>::checkType(pyObj); +} +inline bool Converter<ByteArray>::isConvertible(PyObject* pyObj) +{ + if (ValueTypeConverter<ByteArray>::isConvertible(pyObj)) + return true; + SbkObjectType* shiboType = reinterpret_cast<SbkObjectType*>(SbkType<ByteArray>()); + return Shiboken::Converter<const char*>::checkType(pyObj) + || (ObjectType::isExternalConvertible(shiboType, pyObj)); +} +inline ByteArray Converter<ByteArray>::toCpp(PyObject* pyObj) +{ + if (pyObj == Py_None) + return ByteArray(); + else if (PyObject_TypeCheck(pyObj, SbkType<ByteArray>())) + return *Converter<ByteArray*>::toCpp(pyObj); + else if (PyString_Check(pyObj)) + return ByteArray(PyString_AS_STRING(pyObj), PyString_GET_SIZE(pyObj)); + return ValueTypeConverter<ByteArray>::toCpp(pyObj); +} +inline PyObject* Converter<ByteArray>::toPython(const ByteArray& cppObj) +{ + return ValueTypeConverter<ByteArray>::toPython(cppObj); +} +} diff --git a/tests/samplebinding/bytearray_test.py b/tests/samplebinding/bytearray_test.py new file mode 100644 index 000000000..2eb99601f --- /dev/null +++ b/tests/samplebinding/bytearray_test.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team <contact@pyside.org> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +import unittest +from os.path import isdir +from sample import ByteArray + + +class ByteArrayBufferProtocolTest(unittest.TestCase): + '''Tests ByteArray implementation of Python buffer protocol.''' + + def testByteArrayBufferProtocol(self): + # Tests ByteArray implementation of Python buffer protocol using the os.path.isdir + # function which an unicode object or other object implementing the Python buffer protocol. + isdir(ByteArray('/tmp')) + + +class ByteArrayConcatenationOperatorTest(unittest.TestCase): + '''Test cases for ByteArray concatenation with '+' operator.''' + + def testConcatByteArrayAndPythonString(self): + # Test concatenation of a ByteArray with a Python string, in this order. + ba = ByteArray('foo') + result = ba + '\x00bar' + self.assertEqual(type(result), ByteArray) + self.assertEqual(result, 'foo\x00bar') + + def testConcatPythonStringAndByteArray(self): + # Test concatenation of a Python string with a ByteArray, in this order. + concat_python_string_add_qbytearray_worked = True + ba = ByteArray('foo') + result = 'bar\x00' + ba + self.assertEqual(type(result), ByteArray) + self.assertEqual(result, 'bar\x00foo') + + +class ByteArrayOperatorEqual(unittest.TestCase): + '''TestCase for operator ByteArray == ByteArray.''' + + def testDefault(self): + # ByteArray() == ByteArray() + obj1 = ByteArray() + obj2 = ByteArray() + self.assertEqual(obj1, obj2) + + def testSimple(self): + # ByteArray(some_string) == ByteArray(some_string) + string = 'egg snakes' + self.assertEqual(ByteArray(string), ByteArray(string)) + + def testPyString(self): + # ByteArray(string) == string + string = 'my test string' + self.assertEqual(ByteArray(string), string) + + def testQString(self): + # ByteArray(string) == string + string = 'another test string' + self.assertEqual(ByteArray(string), string) + + +class ByteArrayOperatorAt(unittest.TestCase): + '''TestCase for operator ByteArray[]''' + + def testInRange(self): + # ByteArray[x] where x is a valid index. + string = 'abcdefgh' + obj = ByteArray(string) + for i in range(len(string)): + self.assertEqual(obj[i], string[i]) + + def testInRangeReverse(self): + # ByteArray[x] where x is a valid index (reverse order). + string = 'abcdefgh' + obj = ByteArray(string) + for i in range(len(string)-1, 0, -1): + self.assertEqual(obj[i], string[i]) + + def testOutOfRange(self): + # ByteArray[x] where x is out of index. + string = '1234567' + obj = ByteArray(string) + self.assertRaises(IndexError, lambda :obj[len(string)]) + + def testNullStrings(self): + ba = ByteArray('\x00') + self.assertEqual(ba.at(0), '\x00') + self.assertEqual(ba[0], '\x00') + + +class ByteArrayOperatorLen(unittest.TestCase): + '''Test case for __len__ operator of ByteArray''' + + def testBasic(self): + '''ByteArray __len__''' + self.assertEqual(len(ByteArray()), 0) + self.assertEqual(len(ByteArray('')), 0) + self.assertEqual(len(ByteArray(' ')), 1) + self.assertEqual(len(ByteArray('yabadaba')), 8) + + +class ByteArrayAndPythonStr(unittest.TestCase): + '''Test case for __str__ operator of ByteArray''' + + def testStrOperator(self): + '''ByteArray __str__''' + self.assertEqual(ByteArray().__str__(), '') + self.assertEqual(ByteArray('').__str__(), '') + self.assertEqual(ByteArray('aaa').__str__(), 'aaa') + + def testPythonStrAndNull(self): + s1 = "123\000321" + ba = ByteArray(s1) + s2 = ba.data() + self.assertEqual(s1, s2) + self.assertEqual(type(s1), type(s2)) + self.assertEqual(s1, ba) + self.assertNotEqual(type(s1), type(ba)) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index 08f45b1df..164e992a9 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -1,5 +1,6 @@ #include "abstract.h" #include "blackbox.h" +#include "bytearray.h" #include "bucket.h" #include "collector.h" #include "complex.h" diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 9624ba27a..547710a52 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -1422,6 +1422,110 @@ </modify-function> </value-type> + <value-type name="ByteArray" hash-function="ByteArray::hash"> + <conversion-rule file="bytearray_conversions.h"/> + <modify-function signature="ByteArray(const char*,int)" remove="all" /> + <modify-function signature="ByteArray(const char*)"> + <!-- Keep \x00 bytes passed in Python strings. --> + <modify-argument index="1"> + <replace-type modified-type="PyString"/> + </modify-argument> + <inject-code class="target" position="beginning"> + %0 = new %TYPE(PyString_AS_STRING(%PYARG_1), PyString_GET_SIZE(%PYARG_1)); + </inject-code> + </modify-function> + + <!-- buffer protocol --> + <inject-code class="native" position="beginning" file="bytearray_bufferprotocol.cpp" /> + <inject-code class="target" position="end"> + #if PY_VERSION_HEX < 0x03000000 + Shiboken::SbkType<ByteArray>()->tp_as_buffer = &SbkByteArrayBufferProc; + Shiboken::SbkType<ByteArray>()->tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER; + #endif + </inject-code> + + <modify-function signature="data() const"> + <inject-code class="target" position="beginning"> + %PYARG_0 = PyString_FromStringAndSize(%CPPSELF.%FUNCTION_NAME(), %CPPSELF.size()); + </inject-code> + </modify-function> + + <modify-function signature="hash(const ByteArray&)" remove="all" /> + <modify-function signature="append(const char*)" remove="all" /> + <modify-function signature="append(const char*,int)" remove="all" /> + <modify-function signature="operator==(const char*,ByteArray)" remove="all" /> + <modify-function signature="operator==(ByteArray,const char*)" remove="all" /> + <modify-function signature="operator!=(const char*,ByteArray)" remove="all" /> + <modify-function signature="operator!=(ByteArray,const char*)" remove="all" /> + <modify-function signature="operator+(ByteArray,const char*)" remove="all" /> + <modify-function signature="operator+(const char*,ByteArray)" remove="all" /> + <modify-function signature="operator+=(const char*)" remove="all" /> + <modify-function signature="operator[](int)const" remove="all"/> + + <add-function signature="operator+(PyUnicode)"> + <inject-code> + Shiboken::AutoDecRef data(PyUnicode_AsASCIIString(%PYARG_1)); + if (!data.isNull()) { + ByteArray ba(*%CPPSELF); + ba.append(PyString_AS_STRING(data.object()), PyString_GET_SIZE(data.object())); + %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba); + } + </inject-code> + </add-function> + <add-function signature="operator+(PyUnicode,ByteArray)"> + <inject-code> + Shiboken::AutoDecRef data(PyUnicode_AsASCIIString(%PYARG_1)); + if (!data.isNull()) { + ByteArray ba(PyString_AS_STRING(data.object()), PyString_GET_SIZE(data.object())); + ba.append(*%CPPSELF); + %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba); + } + </inject-code> + </add-function> + <add-function signature="operator+(PyString,ByteArray)"> + <inject-code> + ByteArray ba(PyString_AS_STRING(%PYARG_1), PyString_GET_SIZE(%PYARG_1)); + %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba + *%CPPSELF); + </inject-code> + </add-function> + + <add-function signature="__repr__" return-type="PyObject*"> + <inject-code class="target" position="beginning"> + ByteArray ba(((PyObject*)%PYSELF)->ob_type->tp_name); + ba += '('; + Shiboken::AutoDecRef contents(PyObject_Repr(PyString_FromStringAndSize(%CPPSELF.data(), %CPPSELF.size()))); + ba += PyString_AS_STRING(contents.object()); + ba += ")"; + %PYARG_0 = PyString_FromStringAndSize(ba.data(), ba.size()); + </inject-code> + </add-function> + + <add-function signature="__str__" return-type="PyString"> + <inject-code class="target" position="beginning"> + %PYARG_0 = PyString_FromStringAndSize(%CPPSELF.data(), %CPPSELF.size()); + </inject-code> + </add-function> + + <add-function signature="__len__"> + <inject-code class="target" position="beginning"> + return %CPPSELF.size(); + </inject-code> + </add-function> + <add-function signature="__getitem__"> + <inject-code class="target" position="beginning"> + if (_i < 0 || _i >= %CPPSELF.size()) { + PyErr_SetString(PyExc_IndexError, "index out of bounds"); + return 0; + } else { + char res[2]; + res[0] = %CPPSELF.at(_i); + res[1] = 0; + return PyString_FromStringAndSize(res, 1); + } + </inject-code> + </add-function> + </value-type> + <value-type name="StrList"> <add-function signature="__len__" > <inject-code class="target" position="end"> |