aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2011-04-15 16:39:33 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:15:21 -0300
commit04d571f872a8cada531646f15b2d4440b20d0d53 (patch)
treefda05f186dd0b2c758699003b77f75cb560eea22
parent4936232cec98614069cf72b55497c50b450a71e8 (diff)
Overload decisor was improved to consider PySequences on modified function signatures.
Unit tests were added as usual. Reviewer: Hugo Parente <hugo.lima@openbossa.org> Renato Araujo <renato.filho@openbossa.org>
-rw-r--r--generator/overloaddata.cpp26
-rw-r--r--tests/libsample/overload.h8
-rw-r--r--tests/samplebinding/overload_test.py68
-rw-r--r--tests/samplebinding/typesystem_sample.xml26
4 files changed, 116 insertions, 12 deletions
diff --git a/generator/overloaddata.cpp b/generator/overloaddata.cpp
index 7e3f608cd..1390eea08 100644
--- a/generator/overloaddata.cpp
+++ b/generator/overloaddata.cpp
@@ -156,6 +156,8 @@ void OverloadData::sortNextOverloads()
OverloadSortData sortData;
bool checkPyObject = false;
int pyobjectIndex = 0;
+ bool checkPySequence = false;
+ int pySeqIndex = 0;
bool checkQString = false;
int qstringIndex = 0;
bool checkQVariant = false;
@@ -188,6 +190,9 @@ void OverloadData::sortNextOverloads()
if (!checkPyObject && typeName.contains("PyObject")) {
checkPyObject = true;
pyobjectIndex = sortData.lastProcessedItemId();
+ } else if (!checkPySequence && typeName == "PySequence") {
+ checkPySequence = true;
+ pySeqIndex = sortData.lastProcessedItemId();
} else if (!checkQVariant && typeName == "QVariant") {
checkQVariant = true;
qvariantIndex = sortData.lastProcessedItemId();
@@ -238,6 +243,9 @@ void OverloadData::sortNextOverloads()
for (int i = 0; i < numPrimitives; ++i)
hasPrimitive[i] = sortData.map.contains(primitiveTypes[i]);
+ if (checkPySequence && checkPyObject)
+ graph.addEdge(pySeqIndex, pyobjectIndex);
+
QStringList classesWithIntegerImplicitConversion;
foreach(OverloadData* ov, m_nextOverloadData) {
@@ -305,13 +313,23 @@ void OverloadData::sortNextOverloads()
}
}
- /* Add dependency on PyObject, so its check is the last one (too generic) */
- if (checkPyObject && !targetTypeEntryName.contains("PyObject")) {
- graph.addEdge(targetTypeId, pyobjectIndex);
+
+ if ((checkPySequence || checkPyObject)
+ && !targetTypeEntryName.contains("PyObject")
+ && !targetTypeEntryName.contains("PySequence")) {
+ if (checkPySequence) {
+ // PySequence will be checked after all more specific types, but before PyObject.
+ graph.addEdge(targetTypeId, pySeqIndex);
+ } else {
+ // Add dependency on PyObject, so its check is the last one (too generic).
+ graph.addEdge(targetTypeId, pyobjectIndex);
+ }
} else if (checkQVariant && targetTypeEntryName != "QVariant") {
if (!graph.containsEdge(qvariantIndex, targetTypeId)) // Avoid cyclic dependency.
graph.addEdge(targetTypeId, qvariantIndex);
- } else if (checkQString && ov->argType()->indirections() > 0 && targetTypeEntryName != "QString" && targetTypeEntryName != "QByteArray") {
+ } else if (checkQString && ov->argType()->indirections() > 0
+ && targetTypeEntryName != "QString"
+ && targetTypeEntryName != "QByteArray") {
if (!graph.containsEdge(qstringIndex, targetTypeId)) // Avoid cyclic dependency.
graph.addEdge(targetTypeId, qstringIndex);
}
diff --git a/tests/libsample/overload.h b/tests/libsample/overload.h
index a0682fe18..bbac9afa4 100644
--- a/tests/libsample/overload.h
+++ b/tests/libsample/overload.h
@@ -106,6 +106,14 @@ public:
// Another simpler variant of the one similar to QPainter::drawText(...)
FunctionEnum drawText4(int a0, int a1, int a2) { return Function0; }
FunctionEnum drawText4(int a0, int a1, int a2, int a3, int a4) { return Function1; }
+
+ FunctionEnum acceptSequence() { return Function0; }
+ FunctionEnum acceptSequence(int a0, int a1) { return Function1; }
+ FunctionEnum acceptSequence(const Str& a0, ParamEnum a1 = Param0) { return Function2; }
+ FunctionEnum acceptSequence(const Size& a0) { return Function3; }
+ // The type must be changed to PySequence.
+ FunctionEnum acceptSequence(const char* const a0[]) { return Function4; }
+ FunctionEnum acceptSequence(void* a0) { return Function5; }
};
class LIBSAMPLE_API Overload2 : public Overload
diff --git a/tests/samplebinding/overload_test.py b/tests/samplebinding/overload_test.py
index e165ef854..3c3fa2751 100644
--- a/tests/samplebinding/overload_test.py
+++ b/tests/samplebinding/overload_test.py
@@ -27,9 +27,23 @@
'''Test cases for Overload class'''
import unittest
-
from sample import Echo, Overload, Point, PointF, Polygon, Rect, RectF, Size, Str
+
+def raisesWithErrorMessage(func, arguments, errorType, errorMsg):
+ '''NOTE: Using 'try' because assertRaisesRegexp is not available
+ to check the error message.'''
+ try:
+ func(*arguments)
+ return False
+ except Exception as err:
+ if type(err) != TypeError:
+ return False
+ if not errorMsg in str(err):
+ return False
+ return True
+
+
class OverloadTest(unittest.TestCase):
'''Test case for Overload class'''
@@ -133,19 +147,57 @@ class OverloadTest(unittest.TestCase):
def testDrawText3Exception(self):
overload = Overload()
- # NOTE: Using 'try' because assertRaisesRegexp is not available.
- # to check the error text.
- try:
- overload.drawText3(Str(), Str(), Str(), 4, 5)
- except Exception as err:
- self.assertEqual(type(err), TypeError)
- self.assertTrue('called with wrong argument types:' in str(err))
+ args = (Str(), Str(), Str(), 4, 5)
+ result = raisesWithErrorMessage(overload.drawText3, args,
+ TypeError, 'called with wrong argument types:')
+ self.assert_(result)
def testDrawText4(self):
overload = Overload()
self.assertEqual(overload.drawText4(1, 2, 3), Overload.Function0)
self.assertEqual(overload.drawText4(1, 2, 3, 4, 5), Overload.Function1)
+ def testAcceptSequence(self):
+ # Overload.acceptSequence()
+ overload = Overload()
+ self.assertEqual(overload.acceptSequence(), Overload.Function0)
+
+ def testAcceptSequenceIntInt(self):
+ # Overload.acceptSequence(int,int)
+ overload = Overload()
+ self.assertEqual(overload.acceptSequence(1, 2), Overload.Function1)
+
+ def testAcceptSequenceStrParamEnum(self):
+ # Overload.acceptSequence(Str,Overload::ParamEnum)
+ overload = Overload()
+ self.assertEqual(overload.acceptSequence(''), Overload.Function2)
+ self.assertEqual(overload.acceptSequence('', Overload.Param0), Overload.Function2)
+ self.assertEqual(overload.acceptSequence(Str('')), Overload.Function2)
+ self.assertEqual(overload.acceptSequence(Str(''), Overload.Param0), Overload.Function2)
+
+ def testAcceptSequenceSize(self):
+ # Overload.acceptSequence(Size)
+ overload = Overload()
+ self.assertEqual(overload.acceptSequence(Size()), Overload.Function3)
+
+ def testAcceptSequenceStringList(self):
+ # Overload.acceptSequence(const char**)
+ overload = Overload()
+ strings = ['line 1', 'line 2']
+ self.assertEqual(overload.acceptSequence(strings), Overload.Function4)
+ args = (['line 1', 2], )
+ result = raisesWithErrorMessage(overload.acceptSequence, args,
+ TypeError, 'The argument must be a sequence of strings.')
+ self.assert_(result)
+
+ def testAcceptSequencePyObject(self):
+ # Overload.acceptSequence(void*)
+ overload = Overload()
+ class Foo(object):
+ pass
+ foo = Foo()
+ self.assertEqual(overload.acceptSequence(foo), Overload.Function5)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml
index e1837bbd3..eeaf3c218 100644
--- a/tests/samplebinding/typesystem_sample.xml
+++ b/tests/samplebinding/typesystem_sample.xml
@@ -1203,6 +1203,32 @@
<define-ownership owner="c++"/>
</modify-argument>
</modify-function>
+ <modify-function signature="acceptSequence(const char**)">
+ <modify-argument index="1">
+ <replace-type modified-type="PySequence" />
+ <conversion-rule class="native">
+ {
+ Shiboken::AutoDecRef strList(PySequence_Fast(%PYARG_1, "The argument must be a sequence."));
+ int lineCount = PySequence_Fast_GET_SIZE(strList.object());
+ for (int line = 0; line &lt; lineCount; ++line) {
+ if (!PyString_Check(PySequence_Fast_GET_ITEM(strList.object(), line))) {
+ PyErr_SetString(PyExc_TypeError, "The argument must be a sequence of strings.");
+ break;
+ }
+ }
+ }
+ const char** %out = 0;
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="acceptSequence(void*)">
+ <modify-argument index="1">
+ <replace-type modified-type="PyObject" />
+ <conversion-rule class="native">
+ void* %out = 0;
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
<template name="buffer_argument">
unsigned char* %out;