Skip to content

Commit e930d69

Browse files
committed
[server] setFilters implementation, bindings and test
* moved type conversion to conversions.sip (template) * added setFilters() to QgsServerInterface * added tests
1 parent 2301960 commit e930d69

9 files changed

+201
-126
lines changed

python/server/conversions.sip

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/***************************************************************************
2+
qgsserverinterface.sip
3+
4+
Class defining the interface made available to QGIS Server plugins.
5+
-------------------
6+
begin : 2015-08-06
7+
copyright : (C) 2015 by Alessandro Pasotti
8+
email : elpaso at itopen dot it
9+
***************************************************************************/
10+
11+
/***************************************************************************
12+
* *
13+
* This program is free software; you can redistribute it and/or modify *
14+
* it under the terms of the GNU General Public License as published by *
15+
* the Free Software Foundation; either version 2 of the License, or *
16+
* (at your option) any later version. *
17+
* *
18+
***************************************************************************/
19+
20+
21+
// Type conversion for QMultiMap<int, TYPE2*>
22+
23+
template<int, TYPE2*>
24+
%MappedType QMultiMap<int, TYPE2*>
25+
{
26+
%TypeHeaderCode
27+
#include <QMultiMap>
28+
%End
29+
30+
%ConvertFromTypeCode
31+
// Convert to Python: create the dictionary.
32+
PyObject *d = PyDict_New();
33+
34+
if (!d)
35+
{
36+
return NULL;
37+
}
38+
39+
// Set the dictionary elements.
40+
QMultiMap<int, TYPE2*>::iterator i = sipCpp->begin();
41+
42+
while (i != sipCpp->end())
43+
{
44+
45+
const int t1 = i.key();
46+
TYPE2 * t2 = i.value();
47+
PyObject *t1obj = PyInt_FromSize_t(t1);
48+
PyObject *t2obj = sipConvertFromType(t2, sipType_TYPE2, sipTransferObj);
49+
if (PyDict_GetItem(d, t1obj) == NULL)
50+
{
51+
PyObject *lst = PyList_New(0);
52+
PyDict_SetItem(d, t1obj, lst);
53+
if (lst)
54+
{
55+
Py_DECREF(lst);
56+
}
57+
}
58+
59+
if (t1obj == NULL || t2obj == NULL ||
60+
PyList_Append(PyDict_GetItem(d, t1obj), t2obj) < 0)
61+
{
62+
Py_DECREF(d);
63+
if (t1obj)
64+
{
65+
Py_DECREF(t1obj);
66+
}
67+
68+
if (t2obj)
69+
{
70+
Py_DECREF(t2obj);
71+
}
72+
73+
return NULL;
74+
}
75+
Py_DECREF(t1obj);
76+
Py_DECREF(t2obj);
77+
78+
++i;
79+
}
80+
81+
return d;
82+
%End
83+
84+
%ConvertToTypeCode
85+
// Convert from Python:
86+
PyObject *t1obj, *t2obj;
87+
#if PY_VERSION_HEX >= 0x02050000
88+
Py_ssize_t i = 0;
89+
#else
90+
int i = 0;
91+
#endif
92+
93+
// Check the type if that is all that is required.
94+
if (sipIsErr == NULL)
95+
{
96+
if (!PyDict_Check(sipPy))
97+
return 0;
98+
99+
while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
100+
{
101+
for (int i = 0; i < PyList_GET_SIZE(t2obj); ++i) {
102+
if (!sipCanConvertToType(PyList_GET_ITEM(t2obj, i),
103+
sipType_TYPE2, SIP_NOT_NONE))
104+
return 0;
105+
}
106+
}
107+
108+
return 1;
109+
}
110+
111+
QMultiMap<int, TYPE2*> *qm = new QMultiMap<int, TYPE2*>;
112+
while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
113+
{
114+
int state2;
115+
int k = (int) PyInt_AsLong(t1obj);
116+
for (int i = 0; i < PyList_GET_SIZE(t2obj); ++i)
117+
{
118+
TYPE2 *t2 =
119+
reinterpret_cast<TYPE2 *>(sipConvertToType(PyList_GET_ITEM(t2obj, i),
120+
sipType_TYPE2,
121+
sipTransferObj,
122+
SIP_NOT_NONE,
123+
&state2,
124+
sipIsErr));
125+
126+
if (*sipIsErr)
127+
{
128+
sipReleaseType(t2, sipType_TYPE2, state2);
129+
130+
delete qm;
131+
return 0;
132+
}
133+
134+
qm->insert(k, t2);
135+
136+
sipReleaseType(t2, sipType_TYPE2, state2);
137+
}
138+
}
139+
140+
*sipCppPtr = qm;
141+
142+
return sipGetState(sipTransferObj);
143+
%End
144+
};

python/server/qgsrequesthandler.sip

-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ class QgsRequestHandler
6868
QString infoFormat() const;
6969
/** Return true if the HTTP headers were already sent to the client*/
7070
bool headersSent();
71-
7271
private:
7372
/** Parses the input and creates a request neutral Parameter/Value map*/
7473
virtual void parseInput() = 0;

python/server/qgsserverinterface.sip

+1-122
Original file line numberDiff line numberDiff line change
@@ -33,128 +33,6 @@ typedef QMultiMap<int, QgsServerFilter*> QgsServerFiltersMap;
3333

3434

3535

36-
template<int, TYPE2*>
37-
%MappedType QMultiMap<int, TYPE2*>
38-
{
39-
%TypeHeaderCode
40-
#include <QMultiMap>
41-
%End
42-
43-
%ConvertFromTypeCode
44-
// Create the dictionary.
45-
PyObject *d = PyDict_New();
46-
47-
if (!d)
48-
return NULL;
49-
50-
// Set the dictionary elements.
51-
QMultiMap<int, TYPE2*>::iterator i = sipCpp->begin();
52-
53-
while (i != sipCpp->end())
54-
{
55-
56-
const int t1 = i.key();
57-
TYPE2 * t2 = i.value();
58-
PyObject *t1obj = PyInt_FromSize_t(t1);
59-
PyObject *t2obj = sipConvertFromType(t2, sipType_TYPE2, sipTransferObj);
60-
///////PyObject *t2obj = sipConvertFromNewType(t2, sipType_TYPE2, sipTransferObj);
61-
if (PyDict_GetItem(d, t1obj) == NULL) {
62-
PyObject *lst = PyList_New(0);
63-
PyDict_SetItem(d, t1obj, lst);
64-
if (lst)
65-
{
66-
Py_DECREF(lst);
67-
}
68-
}
69-
70-
if (t1obj == NULL || t2obj == NULL ||
71-
PyList_Append(PyDict_GetItem(d, t1obj), t2obj) < 0)
72-
{
73-
Py_DECREF(d);
74-
if (t1obj)
75-
{
76-
Py_DECREF(t1obj);
77-
}
78-
79-
if (t2obj)
80-
{
81-
Py_DECREF(t2obj);
82-
}
83-
84-
return NULL;
85-
}
86-
Py_DECREF(t1obj);
87-
Py_DECREF(t2obj);
88-
89-
++i;
90-
}
91-
92-
return d;
93-
%End
94-
95-
%ConvertToTypeCode
96-
PyObject *t1obj, *t2obj;
97-
#if PY_VERSION_HEX >= 0x02050000
98-
Py_ssize_t i = 0;
99-
#else
100-
int i = 0;
101-
#endif
102-
103-
// Check the type if that is all that is required.
104-
if (sipIsErr == NULL)
105-
{
106-
if (!PyDict_Check(sipPy))
107-
return 0;
108-
109-
while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
110-
{
111-
for (int i = 0; i < PyList_GET_SIZE(t2obj); ++i) {
112-
if (!sipCanConvertToType(PyList_GET_ITEM(t2obj, i),
113-
sipType_TYPE2, SIP_NOT_NONE))
114-
return 0;
115-
}
116-
}
117-
118-
return 1;
119-
}
120-
121-
QMultiMap<int, TYPE2*> *qm = new QMultiMap<int, TYPE2*>;
122-
while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
123-
{
124-
int state2;
125-
int k = (int) PyInt_AsLong(t1obj);
126-
for (int i = 0; i < PyList_GET_SIZE(t2obj); ++i) {
127-
TYPE2 *t2 =
128-
reinterpret_cast<TYPE2 *>(sipConvertToType(PyList_GET_ITEM(t2obj, i),
129-
sipType_TYPE2,
130-
sipTransferObj,
131-
SIP_NOT_NONE,
132-
&state2,
133-
sipIsErr));
134-
135-
if (*sipIsErr)
136-
{
137-
sipReleaseType(t2, sipType_TYPE2, state2);
138-
139-
delete qm;
140-
return 0;
141-
}
142-
143-
qm->insert(k, t2);
144-
145-
sipReleaseType(t2, sipType_TYPE2, state2);
146-
}
147-
}
148-
149-
*sipCppPtr = qm;
150-
151-
return sipGetState(sipTransferObj);
152-
%End
153-
};
154-
155-
156-
157-
15836
class QgsServerInterface
15937
{
16038
%TypeHeaderCode
@@ -170,6 +48,7 @@ class QgsServerInterface
17048
/** Register a filter with the given priority. The filter's requestReady()
17149
* and responseReady() methods will be called from the loop*/
17250
virtual void registerFilter( QgsServerFilter* filter /Transfer/, int priority = 0 ) = 0;
51+
virtual void setFilters( QgsServerFiltersMap* filters /Transfer/) = 0;
17352
/** Return an environment variable set by FCGI*/
17453
virtual QString getEnv(const QString& name ) const = 0;
17554
// Commented because of problems with typedef QgsServerFiltersMap, provided

python/server/server.sip

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
%Import QtGui/QtGuimod.sip
88
%Import QtXml/QtXmlmod.sip
99

10+
11+
%Include conversions.sip
12+
1013
%Import core/core.sip
1114

1215
%Feature HAVE_SERVER_PYTHON_PLUGINS

src/server/qgsrequesthandler.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ class QgsRequestHandler
108108
/** Return true if the HTTP headers were already sent to the client*/
109109
bool headersSent() { return mHeadersSent; }
110110
#ifdef HAVE_SERVER_PYTHON_PLUGINS
111-
/** Allow core services to call plugin hooks through sendResponse() */
111+
/** Allow core services to call plugin hooks through sendResponse()
112+
* @note: not in the bindings
113+
*/
112114
virtual void setPluginFilters( QgsServerFiltersMap pluginFilters ) = 0;
113115
#endif
114116
// TODO: if HAVE_SERVER_PYTHON

src/server/qgsserverinterface.h

+6
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ class SERVER_EXPORT QgsServerInterface
7474
*/
7575
virtual void registerFilter( QgsServerFilter* filter, int priority = 0 ) = 0;
7676

77+
/**
78+
* Set the filters map
79+
* @param filters the QgsServerFiltersMap
80+
*/
81+
virtual void setFilters( QgsServerFiltersMap* filters ) = 0;
82+
7783
/**
7884
* Return the list of current QgsServerFilter
7985
* @return QgsServerFiltersMap list of QgsServerFilter

src/server/qgsserverinterfaceimpl.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,8 @@ void QgsServerInterfaceImpl::registerFilter( QgsServerFilter *filter, int priori
5858
{
5959
mFilters.insert( priority, filter );
6060
}
61+
62+
void QgsServerInterfaceImpl::setFilters( QgsServerFiltersMap* filters )
63+
{
64+
mFilters = *filters;
65+
}

src/server/qgsserverinterfaceimpl.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ class QgsServerInterfaceImpl : public QgsServerInterface
5555
QString configFilePath( ) override { return mConfigFilePath; }
5656
void setConfigFilePath( QString configFilePath ) override;
5757

58-
private:
58+
void setFilters(QgsServerFiltersMap *filters) override;
59+
private:
5960

6061
QString mConfigFilePath;
6162
QgsServerFiltersMap mFilters;

tests/src/python/test_qgsserver.py

+37-1
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,46 @@ def responseComplete(self):
9999
serverIface.registerFilter(filter, 100 )
100100
# Get registered filters
101101
self.assertEqual(filter, serverIface.filters()[100][0])
102+
103+
# Register some more filters
104+
class Filter1(QgsServerFilter):
105+
def responseComplete(self):
106+
request = self.serverInterface().requestHandler()
107+
params = request.parameterMap()
108+
if params.get('SERVICE', '').upper() == 'SIMPLE':
109+
request.appendBody('Hello from Filter1!')
110+
111+
class Filter2(QgsServerFilter):
112+
def responseComplete(self):
113+
request = self.serverInterface().requestHandler()
114+
params = request.parameterMap()
115+
if params.get('SERVICE', '').upper() == 'SIMPLE':
116+
request.appendBody('Hello from Filter2!')
117+
118+
filter1 = Filter1(serverIface)
119+
filter2 = Filter2(serverIface)
120+
serverIface.registerFilter(filter1, 101)
121+
serverIface.registerFilter(filter2, 200 )
122+
serverIface.registerFilter(filter2, 100 )
123+
self.assertTrue(filter2 in serverIface.filters()[100])
124+
self.assertEqual(filter1, serverIface.filters()[101][0])
125+
self.assertEqual(filter2, serverIface.filters()[200][0])
102126
response = str(self.server.handleRequest('service=simple'))
103-
expected = 'Content-type: text/plain\n\nHello from SimpleServer!'
127+
expected = 'Content-type: text/plain\n\nHello from SimpleServer!Hello from Filter1!Hello from Filter2!'
104128
self.assertEqual(response, expected)
105129

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

107143
## WMS tests
108144
def wms_request_compare(self, request):

0 commit comments

Comments
 (0)