From 33cbe220963df8620c3573165a89f94cb33b359b Mon Sep 17 00:00:00 2001 From: elpaso Date: Mon, 7 Sep 2015 09:57:32 +0200 Subject: [PATCH] Convert to type works for QPair of QByteArray --- python/server/qgsserver.sip | 106 +++++++++++++++++++++++++++-- src/server/qgsserver.cpp | 16 +++-- src/server/qgsserver.h | 3 + tests/src/python/test_qgsserver.py | 9 ++- 4 files changed, 122 insertions(+), 12 deletions(-) diff --git a/python/server/qgsserver.sip b/python/server/qgsserver.sip index fdeb46f7c5c..00139ac5b85 100644 --- a/python/server/qgsserver.sip +++ b/python/server/qgsserver.sip @@ -36,6 +36,7 @@ static PyObject *QByteArrayToPyStr(QByteArray *ba) return SIPBytes_FromStringAndSize(data, ba->size()); return SIPBytes_FromString(""); } + %End @@ -45,18 +46,110 @@ static PyObject *QByteArrayToPyStr(QByteArray *ba) %End %ConvertToTypeCode - // Check the type if that is all that is required. - if (sipIsErr == NULL) - return (PyTuple_Size(sipPy) == 2); + + // See if we are just being asked to check the type of the Python + // object. + if (!sipIsErr) + { + // Checking whether or not None has been passed instead of a list + // has already been done. + if (!PyTuple_Check(sipPy) || PyTuple_Size(sipPy) != 2) + return 0; + + // Check the type of each element. We specify SIP_NOT_NONE to + // disallow None because it is a list of QPoint, not of a pointer + // to a QPoint, so None isn't appropriate. + for (int i = 0; i < PyTuple_Size(sipPy); ++i) + if (!sipCanConvertToType(PyTuple_GET_ITEM(sipPy, i), + sipType_QByteArray, SIP_NOT_NONE)) + return 0; + + // The type is valid. + return 1; + } + + // Create the instance on the heap. QPair *qp = new QPair; - qp->first = SIPLong_AsLong(PyTuple_GET_ITEM(sipPy, 0)); - qp->second = SIPLong_AsLong(PyTuple_GET_ITEM(sipPy, 1)); + QByteArray *qba1; + int state; + // Get the address of the element's C++ instance. Note that, in + // this case, we don't apply any ownership changes to the list + // elements, only to the list itself. + qba1 = reinterpret_cast(sipConvertToType( + PyTuple_GET_ITEM(sipPy, 0), + sipType_QByteArray, 0, + SIP_NOT_NONE, + &state, sipIsErr)); + + // Deal with any errors. + if (*sipIsErr) + { + sipReleaseType(qba1, sipType_QByteArray, state); + + // Tidy up. + delete qp; + + // There is no temporary instance. + return 0; + } + + qp->first = *qba1; + + // A copy of the QByteArray was assigned to the pair so we no longer + // need it. It may be a temporary instance that should be + // destroyed, or a wrapped instance that should not be destroyed. + // sipReleaseType() will do the right thing. + //sipReleaseType(qba1, sipType_QByteArray, state); + + ///////////////////////////////////////////// + // Second item + + QByteArray *qba2; + + // Get the address of the element's C++ instance. Note that, in + // this case, we don't apply any ownership changes to the list + // elements, only to the list itself. + qba2 = reinterpret_cast(sipConvertToType( + PyTuple_GET_ITEM(sipPy, 1), + sipType_QByteArray, 0, + SIP_NOT_NONE, + &state, sipIsErr)); + + // Deal with any errors. + if (*sipIsErr) + { + sipReleaseType(qba1, sipType_QByteArray, state); + sipReleaseType(qba2, sipType_QByteArray, state); + + // Tidy up. + delete qp; + + // There is no temporary instance. + return 0; + } + + qp->second = *qba2; + + + // A copy of the QByteArray was assigned to the pair so we no longer + // need it. It may be a temporary instance that should be + // destroyed, or a wrapped instance that should not be destroyed. + // sipReleaseType() will do the right thing. + //sipReleaseType(qba2, sipType_QByteArray, state); + + + // Return the instance. *sipCppPtr = qp; + // The instance should be regarded as temporary (and be destroyed as + // soon as it has been used) unless it has been transferred from + // Python. sipGetState() is a convenience function that implements + // this common transfer behaviour. return sipGetState(sipTransferObj); + %End }; @@ -74,6 +167,9 @@ class QgsServer // init for python bindings: void init( ); QPair handleRequest( const QString queryString = QString( ) ); + /* The following code was used to test type conversion in python bindings + QPair testQPair( QPair pair ); + */ %If (HAVE_SERVER_PYTHON_PLUGINS) QgsServerInterface* serverInterface( ); %End diff --git a/src/server/qgsserver.cpp b/src/server/qgsserver.cpp index cf0d4a6d091..506915a603b 100644 --- a/src/server/qgsserver.cpp +++ b/src/server/qgsserver.cpp @@ -407,7 +407,7 @@ bool QgsServer::init( int & argc, char ** argv ) /** * @brief Handles the request * @param queryString - * @return response body and headers + * @return response headers and body */ QPair QgsServer::handleRequest( const QString queryString /*= QString( )*/ ) { @@ -468,7 +468,6 @@ QPair QgsServer::handleRequest( const QString queryStrin //Pass the filters to the requestHandler, this is needed for the following reasons: // 1. allow core services to access plugin filters and implement thir own plugin hooks // 2. allow requestHandler to call sendResponse plugin hook - theRequestHandler->setPluginFilters( mServerInterface->filters() ); #endif @@ -567,10 +566,15 @@ QPair QgsServer::handleRequest( const QString queryStrin if ( logLevel < 1 ) { QgsMessageLog::logMessage( "Request finished in " + QString::number( time.elapsed() ) + " ms", "Server", QgsMessageLog::INFO ); - } - // TODO: if HAVE_SERVER_PYTHON - // Returns the response bytestream + } + // Returns the header and response bytestreams return theRequestHandler->getResponse( ); - } +/* The following code was used to test type conversion in python bindings +QPair QgsServer::testQPair(QPair pair) +{ + return pair; +} +*/ + diff --git a/src/server/qgsserver.h b/src/server/qgsserver.h index 1012ea7bb85..bc01f5a9ad3 100644 --- a/src/server/qgsserver.h +++ b/src/server/qgsserver.h @@ -70,6 +70,9 @@ class SERVER_EXPORT QgsServer * @return the response headers and body QPair of QByteArray if called from python bindings, empty otherwise */ QPair handleRequest( const QString queryString = QString( ) ); + /* The following code was used to test type conversion in python bindings + QPair testQPair( QPair pair ); + */ /** Returns a pointer to the server interface */ #ifdef HAVE_SERVER_PYTHON_PLUGINS diff --git a/tests/src/python/test_qgsserver.py b/tests/src/python/test_qgsserver.py index 36af946c9a3..abe26e58ddd 100644 --- a/tests/src/python/test_qgsserver.py +++ b/tests/src/python/test_qgsserver.py @@ -148,7 +148,7 @@ class TestQgsServer(unittest.TestCase): f = open(self.testdata_path + request.lower() + '.txt') expected = f.read() f.close() - # Store for debug or to regenerate the reference documents: + # Store the output for debug or to regenerate the reference documents: """ f = open(os.path.dirname(__file__) + '/expected.txt', 'w+') f.write(expected) @@ -166,6 +166,13 @@ class TestQgsServer(unittest.TestCase): for request in ('GetCapabilities', 'GetProjectSettings'): self.wms_request_compare(request) + # The following code was used to test type conversion in python bindings + #def test_qpair(self): + # """Test QPair bindings""" + # f, s = self.server.testQPair(('First', 'Second')) + # self.assertEqual(f, 'First') + # self.assertEqual(s, 'Second') + if __name__ == '__main__': unittest.main()