mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-24 00:05:18 -05:00
[server] setFilters implementation, bindings and test
* moved type conversion to conversions.sip (template) * added setFilters() to QgsServerInterface * added tests
This commit is contained in:
parent
230196071a
commit
e930d696fa
144
python/server/conversions.sip
Normal file
144
python/server/conversions.sip
Normal file
@ -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
|
||||
};
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -7,6 +7,9 @@
|
||||
%Import QtGui/QtGuimod.sip
|
||||
%Import QtXml/QtXmlmod.sip
|
||||
|
||||
|
||||
%Include conversions.sip
|
||||
|
||||
%Import core/core.sip
|
||||
|
||||
%Feature HAVE_SERVER_PYTHON_PLUGINS
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -58,3 +58,8 @@ void QgsServerInterfaceImpl::registerFilter( QgsServerFilter *filter, int priori
|
||||
{
|
||||
mFilters.insert( priority, filter );
|
||||
}
|
||||
|
||||
void QgsServerInterfaceImpl::setFilters( QgsServerFiltersMap* filters )
|
||||
{
|
||||
mFilters = *filters;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -99,10 +99,46 @@ class TestQgsServer(unittest.TestCase):
|
||||
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):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user