Skip to content

Commit aa66bc6

Browse files
committedMay 17, 2016
Merge pull request #3076 from rouault/delimitedtext_qt5_fix
Delimited text provider: fix parsing of subset URL parameter with QT 5 and fix tests
2 parents 8ee697b + 902953c commit aa66bc6

File tree

3 files changed

+76
-15
lines changed

3 files changed

+76
-15
lines changed
 

‎ci/travis/linux/qt5/blacklist.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
ProcessingGdalAlgorithmsTest
22
ProcessingQgisAlgorithmsTest
33
PyQgsComposerPicture
4-
PyQgsDelimitedTextProvider
54
PyQgsGeometryTest
65
PyQgsJSONUtils
76
PyQgsLocalServer

‎src/providers/delimitedtext/qgsdelimitedtextprovider.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
#include <QSettings>
2727
#include <QRegExp>
2828
#include <QUrl>
29+
#if QT_VERSION >= 0x050000
30+
#include <QUrlQuery>
31+
#endif
2932

3033
#include "qgsapplication.h"
3134
#include "qgsdataprovider.h"
@@ -152,7 +155,12 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( const QString& uri )
152155

153156
if ( url.hasQueryItem( "subset" ) )
154157
{
158+
#if QT_VERSION < 0x050000
155159
subset = url.queryItemValue( "subset" );
160+
#else
161+
// We need to specify FullyDecoded so that %25 is decoded as %
162+
subset = QUrlQuery( url ).queryItemValue( "subset" , QUrl::FullyDecoded );
163+
#endif
156164
QgsDebugMsg( "subset is: " + subset );
157165
}
158166

‎tests/src/python/test_qgsdelimitedtextprovider.py

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import re
3030
import tempfile
3131
import inspect
32+
import sys
3233
import time
3334
import test_qgsdelimitedtextprovider_wanted as want # NOQA
3435

@@ -57,6 +58,53 @@
5758
geomkey = "#geometry"
5859
fidkey = "#fid"
5960

61+
try:
62+
# Qt 5
63+
from qgis.PyQt.QtCore import QUrlQuery
64+
65+
class MyUrl:
66+
67+
def __init__(self, url):
68+
self.url = url
69+
self.query = QUrlQuery()
70+
71+
@classmethod
72+
def fromLocalFile(cls, filename):
73+
return cls(QUrl.fromLocalFile(filename))
74+
75+
def addQueryItem(self, k, v):
76+
self.query.addQueryItem(k, v)
77+
78+
def toString(self):
79+
urlstr = self.url.toString()
80+
querystr = self.query.toString(QUrl.FullyDecoded)
81+
if querystr != '':
82+
urlstr += '?'
83+
urlstr += querystr
84+
return urlstr
85+
except:
86+
MyUrl = QUrl
87+
88+
89+
def normalize_query_items_order(s):
90+
splitted_url = s.split('?')
91+
urlstr = splitted_url[0]
92+
if len(splitted_url) == 2:
93+
items_list = splitted_url[1].split('&')
94+
items_map = {}
95+
for item in items_list:
96+
splitted_item = item.split('=')
97+
items_map[splitted_item[0]] = splitted_item[1]
98+
first_arg = True
99+
for k in sorted(items_map.keys()):
100+
if first_arg:
101+
urlstr += '?'
102+
first_arg = False
103+
else:
104+
urlstr += '&'
105+
urlstr += k + '=' + items_map[k]
106+
return urlstr
107+
60108
# Thought we could connect to messageReceived signal but doesn't seem to be available
61109
# in python :-( Not sure why?
62110

@@ -77,7 +125,10 @@ def __exit__(self, type, value, traceback):
77125

78126
def logMessage(self, msg, tag, level):
79127
if tag == self.tag or not self.tag:
80-
self.log.append(unicode(msg))
128+
if sys.version_info.major == 2:
129+
self.log.append(unicode(msg))
130+
else:
131+
self.log.append(str(msg))
81132

82133
def messages(self):
83134
return self.log
@@ -92,7 +143,7 @@ def setUpClass(cls):
92143
srcpath = os.path.join(TEST_DATA_DIR, 'provider')
93144
cls.basetestfile = os.path.join(srcpath, 'delimited_xy.csv')
94145

95-
url = QUrl.fromLocalFile(cls.basetestfile)
146+
url = MyUrl.fromLocalFile(cls.basetestfile)
96147
url.addQueryItem("crs", "epsg:4326")
97148
url.addQueryItem("type", "csv")
98149
url.addQueryItem("xField", "X")
@@ -119,7 +170,7 @@ def setUpClass(cls):
119170
srcpath = os.path.join(TEST_DATA_DIR, 'provider')
120171
cls.basetestfile = os.path.join(srcpath, 'delimited_wkt.csv')
121172

122-
url = QUrl.fromLocalFile(cls.basetestfile)
173+
url = MyUrl.fromLocalFile(cls.basetestfile)
123174
url.addQueryItem("crs", "epsg:4326")
124175
url.addQueryItem("type", "csv")
125176
url.addQueryItem("wktField", "wkt")
@@ -133,7 +184,7 @@ def setUpClass(cls):
133184

134185
cls.basetestpolyfile = os.path.join(srcpath, 'delimited_wkt_poly.csv')
135186

136-
url = QUrl.fromLocalFile(cls.basetestpolyfile)
187+
url = MyUrl.fromLocalFile(cls.basetestpolyfile)
137188
url.addQueryItem("crs", "epsg:4326")
138189
url.addQueryItem("type", "csv")
139190
url.addQueryItem("wktField", "wkt")
@@ -188,7 +239,10 @@ def layerData(self, layer, request={}, offset=0):
188239
for field in f.fields():
189240
fields.append(str(field.name()))
190241
fieldTypes.append(str(field.typeName()))
191-
fielddata = dict((name, unicode(f[name])) for name in fields)
242+
if sys.version_info.major == 2:
243+
fielddata = dict((name, unicode(f[name])) for name in fields)
244+
else:
245+
fielddata = dict((name, str(f[name])) for name in fields)
192246
g = f.constGeometry()
193247
if g:
194248
fielddata[geomkey] = str(g.exportToWkt())
@@ -216,7 +270,7 @@ def delimitedTextData(self, testname, filename, requests, verbose, **params):
216270
# and return the data for the layer (fields, data)
217271

218272
filepath = os.path.join(unitTestDataPath("delimitedtext"), filename)
219-
url = QUrl.fromLocalFile(filepath)
273+
url = MyUrl.fromLocalFile(filepath)
220274
if not requests:
221275
requests = [{}]
222276
for k in params.keys():
@@ -227,7 +281,7 @@ def delimitedTextData(self, testname, filename, requests, verbose, **params):
227281
if verbose:
228282
print(testname)
229283
layer = QgsVectorLayer(urlstr, 'test', 'delimitedtext')
230-
uri = unicode(layer.dataProvider().dataSourceUri())
284+
uri = layer.dataProvider().dataSourceUri()
231285
if verbose:
232286
print(uri)
233287
basename = os.path.basename(filepath)
@@ -318,20 +372,20 @@ def runTest(self, file, requests, **params):
318372
print("Running test:", testname)
319373
result = self.delimitedTextData(testname, file, requests, verbose, **params)
320374
if rebuildTests:
321-
printWanted(testname, result)
375+
self.printWanted(testname, result)
322376
assert False, "Test not run - being rebuilt"
323377
try:
324378
wanted = eval('want.{0}()'.format(testname))
325379
except:
326-
printWanted(testname, result)
380+
self.printWanted(testname, result)
327381
assert False, "Test results not available for {0}".format(testname)
328382

329383
data = result['data']
330384
log = result['log']
331385
failures = []
332-
if result['uri'] != wanted['uri']:
386+
if normalize_query_items_order(result['uri']) != normalize_query_items_order(wanted['uri']):
333387
msg = "Layer Uri ({0}) doesn't match expected ({1})".format(
334-
result['uri'], wanted['uri'])
388+
normalize_query_items_order(result['uri']), normalize_query_items_order(wanted['uri']))
335389
print(' ' + msg)
336390
failures.append(msg)
337391
if result['fieldTypes'] != wanted['fieldTypes']:
@@ -381,7 +435,7 @@ def runTest(self, file, requests, **params):
381435
print(' Message log correct: Passed')
382436

383437
if failures:
384-
printWanted(testname, result)
438+
self.printWanted(testname, result)
385439

386440
assert len(failures) == 0, "\n".join(failures)
387441

@@ -604,14 +658,14 @@ def test_029_file_watcher(self):
604658
f.write("id,name\n1,rabbit\n2,pooh\n")
605659

606660
def appendfile(layer):
607-
with file(filename, 'a') as f:
661+
with open(filename, 'a') as f:
608662
f.write('3,tigger\n')
609663
# print "Appended to file - sleeping"
610664
time.sleep(1)
611665
QCoreApplication.instance().processEvents()
612666

613667
def rewritefile(layer):
614-
with file(filename, 'w') as f:
668+
with open(filename, 'w') as f:
615669
f.write("name,size,id\ntoad,small,5\nmole,medium,6\nbadger,big,7\n")
616670
# print "Rewritten file - sleeping"
617671
time.sleep(1)

0 commit comments

Comments
 (0)
Please sign in to comment.