Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[server] setFilters implementation, bindings and test
* moved type conversion to conversions.sip (template)
* added setFilters() to QgsServerInterface
* added tests
  • Loading branch information
elpaso committed Aug 6, 2015
1 parent 2301960 commit e930d69
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 126 deletions.
144 changes: 144 additions & 0 deletions python/server/conversions.sip
@@ -0,0 +1,144 @@
/***************************************************************************
qgsserverinterface.sip

Class defining the interface made available to QGIS Server plugins.
-------------------
begin : 2015-08-06
copyright : (C) 2015 by Alessandro Pasotti
email : elpaso at itopen dot it
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/


// Type conversion for QMultiMap<int, TYPE2*>

template<int, TYPE2*>
%MappedType QMultiMap<int, TYPE2*>
{
%TypeHeaderCode
#include <QMultiMap>
%End

%ConvertFromTypeCode
// Convert to Python: create the dictionary.
PyObject *d = PyDict_New();

if (!d)
{
return NULL;
}

// Set the dictionary elements.
QMultiMap<int, TYPE2*>::iterator i = sipCpp->begin();

while (i != sipCpp->end())
{

const int t1 = i.key();
TYPE2 * t2 = i.value();
PyObject *t1obj = PyInt_FromSize_t(t1);
PyObject *t2obj = sipConvertFromType(t2, sipType_TYPE2, sipTransferObj);
if (PyDict_GetItem(d, t1obj) == NULL)
{
PyObject *lst = PyList_New(0);
PyDict_SetItem(d, t1obj, lst);
if (lst)
{
Py_DECREF(lst);
}
}

if (t1obj == NULL || t2obj == NULL ||
PyList_Append(PyDict_GetItem(d, t1obj), t2obj) < 0)
{
Py_DECREF(d);
if (t1obj)
{
Py_DECREF(t1obj);
}

if (t2obj)
{
Py_DECREF(t2obj);
}

return NULL;
}
Py_DECREF(t1obj);
Py_DECREF(t2obj);

++i;
}

return d;
%End

%ConvertToTypeCode
// Convert from Python:
PyObject *t1obj, *t2obj;
#if PY_VERSION_HEX >= 0x02050000
Py_ssize_t i = 0;
#else
int i = 0;
#endif

// Check the type if that is all that is required.
if (sipIsErr == NULL)
{
if (!PyDict_Check(sipPy))
return 0;

while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
{
for (int i = 0; i < PyList_GET_SIZE(t2obj); ++i) {
if (!sipCanConvertToType(PyList_GET_ITEM(t2obj, i),
sipType_TYPE2, SIP_NOT_NONE))
return 0;
}
}

return 1;
}

QMultiMap<int, TYPE2*> *qm = new QMultiMap<int, TYPE2*>;
while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
{
int state2;
int k = (int) PyInt_AsLong(t1obj);
for (int i = 0; i < PyList_GET_SIZE(t2obj); ++i)
{
TYPE2 *t2 =
reinterpret_cast<TYPE2 *>(sipConvertToType(PyList_GET_ITEM(t2obj, i),
sipType_TYPE2,
sipTransferObj,
SIP_NOT_NONE,
&state2,
sipIsErr));

if (*sipIsErr)
{
sipReleaseType(t2, sipType_TYPE2, state2);

delete qm;
return 0;
}

qm->insert(k, t2);

sipReleaseType(t2, sipType_TYPE2, state2);
}
}

*sipCppPtr = qm;

return sipGetState(sipTransferObj);
%End
};
1 change: 0 additions & 1 deletion python/server/qgsrequesthandler.sip
Expand Up @@ -68,7 +68,6 @@ class QgsRequestHandler
QString infoFormat() const;
/** Return true if the HTTP headers were already sent to the client*/
bool headersSent();

private:
/** Parses the input and creates a request neutral Parameter/Value map*/
virtual void parseInput() = 0;
Expand Down
123 changes: 1 addition & 122 deletions python/server/qgsserverinterface.sip
Expand Up @@ -33,128 +33,6 @@ typedef QMultiMap<int, QgsServerFilter*> QgsServerFiltersMap;



template<int, TYPE2*>
%MappedType QMultiMap<int, TYPE2*>
{
%TypeHeaderCode
#include <QMultiMap>
%End

%ConvertFromTypeCode
// Create the dictionary.
PyObject *d = PyDict_New();

if (!d)
return NULL;

// Set the dictionary elements.
QMultiMap<int, TYPE2*>::iterator i = sipCpp->begin();

while (i != sipCpp->end())
{

const int t1 = i.key();
TYPE2 * t2 = i.value();
PyObject *t1obj = PyInt_FromSize_t(t1);
PyObject *t2obj = sipConvertFromType(t2, sipType_TYPE2, sipTransferObj);
///////PyObject *t2obj = sipConvertFromNewType(t2, sipType_TYPE2, sipTransferObj);
if (PyDict_GetItem(d, t1obj) == NULL) {
PyObject *lst = PyList_New(0);
PyDict_SetItem(d, t1obj, lst);
if (lst)
{
Py_DECREF(lst);
}
}

if (t1obj == NULL || t2obj == NULL ||
PyList_Append(PyDict_GetItem(d, t1obj), t2obj) < 0)
{
Py_DECREF(d);
if (t1obj)
{
Py_DECREF(t1obj);
}

if (t2obj)
{
Py_DECREF(t2obj);
}

return NULL;
}
Py_DECREF(t1obj);
Py_DECREF(t2obj);

++i;
}

return d;
%End

%ConvertToTypeCode
PyObject *t1obj, *t2obj;
#if PY_VERSION_HEX >= 0x02050000
Py_ssize_t i = 0;
#else
int i = 0;
#endif

// Check the type if that is all that is required.
if (sipIsErr == NULL)
{
if (!PyDict_Check(sipPy))
return 0;

while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
{
for (int i = 0; i < PyList_GET_SIZE(t2obj); ++i) {
if (!sipCanConvertToType(PyList_GET_ITEM(t2obj, i),
sipType_TYPE2, SIP_NOT_NONE))
return 0;
}
}

return 1;
}

QMultiMap<int, TYPE2*> *qm = new QMultiMap<int, TYPE2*>;
while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
{
int state2;
int k = (int) PyInt_AsLong(t1obj);
for (int i = 0; i < PyList_GET_SIZE(t2obj); ++i) {
TYPE2 *t2 =
reinterpret_cast<TYPE2 *>(sipConvertToType(PyList_GET_ITEM(t2obj, i),
sipType_TYPE2,
sipTransferObj,
SIP_NOT_NONE,
&state2,
sipIsErr));

if (*sipIsErr)
{
sipReleaseType(t2, sipType_TYPE2, state2);

delete qm;
return 0;
}

qm->insert(k, t2);

sipReleaseType(t2, sipType_TYPE2, state2);
}
}

*sipCppPtr = qm;

return sipGetState(sipTransferObj);
%End
};




class QgsServerInterface
{
%TypeHeaderCode
Expand All @@ -170,6 +48,7 @@ class QgsServerInterface
/** Register a filter with the given priority. The filter's requestReady()
* and responseReady() methods will be called from the loop*/
virtual void registerFilter( QgsServerFilter* filter /Transfer/, int priority = 0 ) = 0;
virtual void setFilters( QgsServerFiltersMap* filters /Transfer/) = 0;
/** Return an environment variable set by FCGI*/
virtual QString getEnv(const QString& name ) const = 0;
// Commented because of problems with typedef QgsServerFiltersMap, provided
Expand Down
3 changes: 3 additions & 0 deletions python/server/server.sip
Expand Up @@ -7,6 +7,9 @@
%Import QtGui/QtGuimod.sip
%Import QtXml/QtXmlmod.sip


%Include conversions.sip

%Import core/core.sip

%Feature HAVE_SERVER_PYTHON_PLUGINS
Expand Down
4 changes: 3 additions & 1 deletion src/server/qgsrequesthandler.h
Expand Up @@ -108,7 +108,9 @@ class QgsRequestHandler
/** Return true if the HTTP headers were already sent to the client*/
bool headersSent() { return mHeadersSent; }
#ifdef HAVE_SERVER_PYTHON_PLUGINS
/** Allow core services to call plugin hooks through sendResponse() */
/** Allow core services to call plugin hooks through sendResponse()
* @note: not in the bindings
*/
virtual void setPluginFilters( QgsServerFiltersMap pluginFilters ) = 0;
#endif
// TODO: if HAVE_SERVER_PYTHON
Expand Down
6 changes: 6 additions & 0 deletions src/server/qgsserverinterface.h
Expand Up @@ -74,6 +74,12 @@ class SERVER_EXPORT QgsServerInterface
*/
virtual void registerFilter( QgsServerFilter* filter, int priority = 0 ) = 0;

/**
* Set the filters map
* @param filters the QgsServerFiltersMap
*/
virtual void setFilters( QgsServerFiltersMap* filters ) = 0;

/**
* Return the list of current QgsServerFilter
* @return QgsServerFiltersMap list of QgsServerFilter
Expand Down
5 changes: 5 additions & 0 deletions src/server/qgsserverinterfaceimpl.cpp
Expand Up @@ -58,3 +58,8 @@ void QgsServerInterfaceImpl::registerFilter( QgsServerFilter *filter, int priori
{
mFilters.insert( priority, filter );
}

void QgsServerInterfaceImpl::setFilters( QgsServerFiltersMap* filters )
{
mFilters = *filters;
}
3 changes: 2 additions & 1 deletion src/server/qgsserverinterfaceimpl.h
Expand Up @@ -55,7 +55,8 @@ class QgsServerInterfaceImpl : public QgsServerInterface
QString configFilePath( ) override { return mConfigFilePath; }
void setConfigFilePath( QString configFilePath ) override;

private:
void setFilters(QgsServerFiltersMap *filters) override;
private:

QString mConfigFilePath;
QgsServerFiltersMap mFilters;
Expand Down
38 changes: 37 additions & 1 deletion tests/src/python/test_qgsserver.py
Expand Up @@ -99,10 +99,46 @@ def responseComplete(self):
serverIface.registerFilter(filter, 100 )
# Get registered filters
self.assertEqual(filter, serverIface.filters()[100][0])

# Register some more filters
class Filter1(QgsServerFilter):
def responseComplete(self):
request = self.serverInterface().requestHandler()
params = request.parameterMap()
if params.get('SERVICE', '').upper() == 'SIMPLE':
request.appendBody('Hello from Filter1!')

class Filter2(QgsServerFilter):
def responseComplete(self):
request = self.serverInterface().requestHandler()
params = request.parameterMap()
if params.get('SERVICE', '').upper() == 'SIMPLE':
request.appendBody('Hello from Filter2!')

filter1 = Filter1(serverIface)
filter2 = Filter2(serverIface)
serverIface.registerFilter(filter1, 101)
serverIface.registerFilter(filter2, 200 )
serverIface.registerFilter(filter2, 100 )
self.assertTrue(filter2 in serverIface.filters()[100])
self.assertEqual(filter1, serverIface.filters()[101][0])
self.assertEqual(filter2, serverIface.filters()[200][0])
response = str(self.server.handleRequest('service=simple'))
expected = 'Content-type: text/plain\n\nHello from SimpleServer!'
expected = 'Content-type: text/plain\n\nHello from SimpleServer!Hello from Filter1!Hello from Filter2!'
self.assertEqual(response, expected)

# Test that the bindings for complex type QgsServerFiltersMap are working
filters = { 100: [filter, filter2], 101: [filter1], 200: [filter2] }
serverIface.setFilters(filters)
self.assertTrue(filter in serverIface.filters()[100])
self.assertTrue(filter2 in serverIface.filters()[100])
self.assertEqual(filter1, serverIface.filters()[101][0])
self.assertEqual(filter2, serverIface.filters()[200][0])
response = str(self.server.handleRequest('service=simple'))
expected = 'Content-type: text/plain\n\nHello from SimpleServer!Hello from Filter1!Hello from Filter2!'
self.assertEqual(response, expected)



## WMS tests
def wms_request_compare(self, request):
Expand Down

0 comments on commit e930d69

Please sign in to comment.