mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Added offline editing WFS tests and debug info
This commit is contained in:
parent
1316d9c72c
commit
a058c36bce
@ -205,7 +205,9 @@ void QgsOfflineEditing::synchronize()
|
||||
// open logging db
|
||||
sqlite3* db = openLoggingDb();
|
||||
if ( !db )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
emit progressStarted();
|
||||
|
||||
@ -221,6 +223,7 @@ void QgsOfflineEditing::synchronize()
|
||||
}
|
||||
}
|
||||
|
||||
QgsDebugMsgLevel( QString( "Found %1 offline layers" ).arg( offlineLayers.count() ), 4 );
|
||||
for ( int l = 0; l < offlineLayers.count(); l++ )
|
||||
{
|
||||
QgsMapLayer* layer = offlineLayers[l];
|
||||
@ -265,8 +268,10 @@ void QgsOfflineEditing::synchronize()
|
||||
|
||||
// TODO: only get commitNos of this layer?
|
||||
int commitNo = getCommitNo( db );
|
||||
QgsDebugMsgLevel( QString( "Found %1 commits" ).arg( commitNo ), 4 );
|
||||
for ( int i = 0; i < commitNo; i++ )
|
||||
{
|
||||
QgsDebugMsgLevel( "Apply commits chronologically", 4 );
|
||||
// apply commits chronologically
|
||||
applyAttributesAdded( remoteLayer, db, layerId, i );
|
||||
applyAttributeValueChanges( offlineLayer, remoteLayer, db, layerId, i );
|
||||
@ -302,6 +307,10 @@ void QgsOfflineEditing::synchronize()
|
||||
showWarning( remoteLayer->commitErrors().join( "\n" ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( "Could not find the layer id in the edit logs!" );
|
||||
}
|
||||
// Invalidate the connection to force a reload if the project is put offline
|
||||
// again with the same path
|
||||
offlineLayer->dataProvider()->invalidateConnections( QgsDataSourceURI( offlineLayer->source() ).database() );
|
||||
@ -317,6 +326,10 @@ void QgsOfflineEditing::synchronize()
|
||||
QgsProject::instance()->removeEntry( PROJECT_ENTRY_SCOPE_OFFLINE, PROJECT_ENTRY_KEY_OFFLINE_DB_PATH );
|
||||
remoteLayer->reload(); //update with other changes
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( "Remote layer is not valid!" );
|
||||
}
|
||||
}
|
||||
|
||||
emit progressStopped();
|
||||
@ -477,7 +490,7 @@ QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlit
|
||||
return nullptr;
|
||||
|
||||
QString tableName = layer->id();
|
||||
QgsDebugMsg( QString( "Creating offline table %1 ..." ).arg( tableName ) );
|
||||
QgsDebugMsgLevel( QString( "Creating offline table %1 ..." ).arg( tableName ), 4 );
|
||||
|
||||
// create table
|
||||
QString sql = QString( "CREATE TABLE '%1' (" ).arg( tableName );
|
||||
@ -817,7 +830,7 @@ void QgsOfflineEditing::applyAttributeValueChanges( QgsVectorLayer* offlineLayer
|
||||
for ( int i = 0; i < values.size(); i++ )
|
||||
{
|
||||
QgsFeatureId fid = remoteFid( db, layerId, values.at( i ).fid );
|
||||
|
||||
QgsDebugMsgLevel( QString( "Offline changeAttributeValue %1 = %2" ).arg( QString( attrLookup[ values.at( i ).attr ] ), values.at( i ).value ), 4 );
|
||||
remoteLayer->changeAttributeValue( fid, attrLookup[ values.at( i ).attr ], values.at( i ).value );
|
||||
|
||||
emit progressUpdated( i + 1 );
|
||||
@ -932,11 +945,16 @@ sqlite3* QgsOfflineEditing::openLoggingDb()
|
||||
int rc = sqlite3_open( dbPath.toUtf8().constData(), &db );
|
||||
if ( rc != SQLITE_OK )
|
||||
{
|
||||
QgsDebugMsg( "Could not open the spatialite logging database" );
|
||||
showWarning( tr( "Could not open the spatialite logging database" ) );
|
||||
sqlite3_close( db );
|
||||
db = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( "dbPath is empty!" );
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
|
@ -132,4 +132,5 @@ IF (WITH_SERVER)
|
||||
ADD_PYTHON_TEST(PyQgsServer test_qgsserver.py)
|
||||
ADD_PYTHON_TEST(PyQgsServerAccessControl test_qgsserver_accesscontrol.py)
|
||||
ADD_PYTHON_TEST(PyQgsServerWFST test_qgsserver_wfst.py)
|
||||
ADD_PYTHON_TEST(PyQgsOfflineEditingWFS test_offline_editing_wfs.py)
|
||||
ENDIF (WITH_SERVER)
|
||||
|
178
tests/src/python/offlineditingtestbase.py
Normal file
178
tests/src/python/offlineditingtestbase.py
Normal file
@ -0,0 +1,178 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""QGIS Unit test utils for offline editing tests.
|
||||
|
||||
.. note:: 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.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from builtins import str
|
||||
from builtins import object
|
||||
__author__ = 'Alessandro Pasotti'
|
||||
__date__ = '2016-06-30'
|
||||
__copyright__ = 'Copyright 2016, The QGIS Project'
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
from time import sleep
|
||||
|
||||
from qgis.core import (
|
||||
QgsFeature,
|
||||
QgsGeometry,
|
||||
QgsPoint,
|
||||
QgsFeatureRequest,
|
||||
QgsExpression,
|
||||
QgsMapLayerRegistry,
|
||||
QgsOfflineEditing,
|
||||
)
|
||||
|
||||
|
||||
# Tet features, fields: [id, name, geometry]
|
||||
# "id" is used as a pk to retriev features by attribute
|
||||
TEST_FEATURES = [
|
||||
(1, 'name 1', QgsPoint(9, 45)),
|
||||
(2, 'name 2', QgsPoint(9.5, 45.5)),
|
||||
(3, 'name 3', QgsPoint(9.5, 46)),
|
||||
(4, 'name 4', QgsPoint(10, 46.5)),
|
||||
]
|
||||
|
||||
|
||||
class OfflineTestBase(object):
|
||||
|
||||
"""Generic test methods for all online providers"""
|
||||
|
||||
def _setUp(self):
|
||||
"""Called by setUp: run before each test."""
|
||||
# Setup: create some features for the test layer
|
||||
features = []
|
||||
layer = self._getLayer('test_point')
|
||||
for id, name, geom in TEST_FEATURES:
|
||||
f = QgsFeature(layer.pendingFields())
|
||||
f['id'] = id
|
||||
f['name'] = name
|
||||
f.setGeometry(QgsGeometry.fromPoint(geom))
|
||||
features.append(f)
|
||||
layer.dataProvider().addFeatures(features)
|
||||
# Add the remote layer
|
||||
self.registry = QgsMapLayerRegistry.instance()
|
||||
self.registry.removeAllMapLayers()
|
||||
assert self.registry.addMapLayer(self._getOnlineLayer('test_point')) is not None
|
||||
|
||||
def _tearDown(self):
|
||||
"""Called by tearDown: run after each test."""
|
||||
# Clear test layers
|
||||
self._clearLayer('test_point')
|
||||
|
||||
@classmethod
|
||||
def _compareFeature(cls, layer, attributes):
|
||||
"""Compare id, name and geometry"""
|
||||
f = cls._getFeatureByAttribute(layer, 'id', attributes[0])
|
||||
return f['name'] == attributes[1] and f.geometry().asPoint().toString() == attributes[2].toString()
|
||||
|
||||
@classmethod
|
||||
def _clearLayer(cls, layer_name):
|
||||
"""
|
||||
Delete all features from the backend layer
|
||||
"""
|
||||
layer = cls._getLayer(layer_name)
|
||||
layer.startEditing()
|
||||
layer.deleteFeatures([f.id() for f in layer.getFeatures()])
|
||||
layer.commitChanges()
|
||||
assert layer.featureCount() == 0
|
||||
|
||||
@classmethod
|
||||
def _getLayer(cls, layer_name):
|
||||
"""
|
||||
Layer factory (return the backend layer), provider specific
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def _getOnlineLayer(cls, type_name, layer_name=None):
|
||||
"""
|
||||
Layer factory (return the online layer), provider specific
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def _getFeatureByAttribute(cls, layer, attr_name, attr_value):
|
||||
"""
|
||||
Find the feature and return it, raise exception if not found
|
||||
"""
|
||||
request = QgsFeatureRequest(QgsExpression("%s=%s" % (attr_name,
|
||||
attr_value)))
|
||||
try:
|
||||
return next(layer.dataProvider().getFeatures(request))
|
||||
except StopIteration:
|
||||
raise Exception("Wrong attributes in WFS layer %s" %
|
||||
layer.name())
|
||||
|
||||
def test_offlineConversion(self):
|
||||
# goes offline
|
||||
ol = QgsOfflineEditing()
|
||||
online_layer = list(self.registry.mapLayers().values())[0]
|
||||
self.assertTrue(online_layer.hasGeometryType())
|
||||
# Check we have 3 features
|
||||
self.assertEqual(len([f for f in online_layer.getFeatures()]), len(TEST_FEATURES))
|
||||
self.assertTrue(ol.convertToOfflineProject(self.temp_path, 'offlineDbFile.sqlite', [online_layer.id()]))
|
||||
offline_layer = list(self.registry.mapLayers().values())[0]
|
||||
self.assertTrue(offline_layer.hasGeometryType())
|
||||
self.assertTrue(offline_layer.isValid())
|
||||
self.assertTrue(offline_layer.name().find('(offline)') > -1)
|
||||
self.assertEqual(len([f for f in offline_layer.getFeatures()]), len(TEST_FEATURES))
|
||||
# Edit feature 2
|
||||
feat2 = self._getFeatureByAttribute(offline_layer, 'name', "'name 2'")
|
||||
self.assertTrue(offline_layer.startEditing())
|
||||
self.assertTrue(offline_layer.changeAttributeValue(feat2.id(), offline_layer.fieldNameIndex('name'), 'name 2 edited'))
|
||||
self.assertTrue(offline_layer.changeGeometry(feat2.id(), QgsGeometry.fromPoint(QgsPoint(33.0, 60.0))))
|
||||
self.assertTrue(offline_layer.commitChanges())
|
||||
feat2 = self._getFeatureByAttribute(offline_layer, 'name', "'name 2 edited'")
|
||||
self.assertTrue(ol.isOfflineProject())
|
||||
# Sync
|
||||
ol.synchronize()
|
||||
# Does anybody know why the sleep is needed? Is that a threaded WFS consequence?
|
||||
sleep(1)
|
||||
online_layer = list(self.registry.mapLayers().values())[0]
|
||||
self.assertTrue(online_layer.isValid())
|
||||
self.assertFalse(online_layer.name().find('(offline)') > -1)
|
||||
self.assertEqual(len([f for f in online_layer.getFeatures()]), len(TEST_FEATURES))
|
||||
# Check that data have changed in the backend (raise exception if not found)
|
||||
feat2 = self._getFeatureByAttribute(self._getLayer('test_point'), 'name', "'name 2 edited'")
|
||||
feat2 = self._getFeatureByAttribute(online_layer, 'name', "'name 2 edited'")
|
||||
self.assertEqual(feat2.geometry().asPoint().toString(), QgsPoint(33.0, 60.0).toString())
|
||||
# Check that all other features have not changed
|
||||
layer = self._getLayer('test_point')
|
||||
self.assertTrue(self._compareFeature(layer, TEST_FEATURES[1 - 1]))
|
||||
self.assertTrue(self._compareFeature(layer, TEST_FEATURES[3 - 1]))
|
||||
self.assertTrue(self._compareFeature(layer, TEST_FEATURES[4 - 1]))
|
||||
|
||||
# Test for regression on double sync (it was a SEGFAULT)
|
||||
# goes offline
|
||||
ol = QgsOfflineEditing()
|
||||
offline_layer = list(self.registry.mapLayers().values())[0]
|
||||
# Edit feature 2
|
||||
feat2 = self._getFeatureByAttribute(offline_layer, 'name', "'name 2 edited'")
|
||||
self.assertTrue(offline_layer.startEditing())
|
||||
self.assertTrue(offline_layer.changeAttributeValue(feat2.id(), offline_layer.fieldNameIndex('name'), 'name 2'))
|
||||
self.assertTrue(offline_layer.changeGeometry(feat2.id(), QgsGeometry.fromPoint(TEST_FEATURES[1][2])))
|
||||
# Edit feat 4
|
||||
feat4 = self._getFeatureByAttribute(offline_layer, 'name', "'name 4'")
|
||||
self.assertTrue(offline_layer.changeAttributeValue(feat4.id(), offline_layer.fieldNameIndex('name'), 'name 4 edited'))
|
||||
self.assertTrue(offline_layer.commitChanges())
|
||||
# Sync
|
||||
ol.synchronize()
|
||||
# Does anybody knows why the sleep is needed? Is that a threaded WFS consequence?
|
||||
sleep(1)
|
||||
online_layer = list(self.registry.mapLayers().values())[0]
|
||||
layer = self._getLayer('test_point')
|
||||
# Check that data have changed in the backend (raise exception if not found)
|
||||
feat4 = self._getFeatureByAttribute(layer, 'name', "'name 4 edited'")
|
||||
feat4 = self._getFeatureByAttribute(online_layer, 'name', "'name 4 edited'")
|
||||
feat2 = self._getFeatureByAttribute(layer, 'name', "'name 2'")
|
||||
feat2 = self._getFeatureByAttribute(online_layer, 'name', "'name 2'")
|
||||
# Check that all other features have not changed
|
||||
layer = self._getLayer('test_point')
|
||||
self.assertTrue(self._compareFeature(layer, TEST_FEATURES[1 - 1]))
|
||||
self.assertTrue(self._compareFeature(layer, TEST_FEATURES[2 - 1]))
|
||||
self.assertTrue(self._compareFeature(layer, TEST_FEATURES[3 - 1]))
|
@ -10,6 +10,9 @@ 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.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from future import standard_library
|
||||
standard_library.install_aliases()
|
||||
|
||||
__author__ = 'Alessandro Pasotti'
|
||||
__date__ = '05/15/2016'
|
||||
@ -19,8 +22,8 @@ __revision__ = '$Format:%H$'
|
||||
|
||||
|
||||
import os
|
||||
import urlparse
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
||||
import urllib.parse
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
from qgis.server import QgsServer
|
||||
|
||||
try:
|
||||
@ -32,19 +35,19 @@ except KeyError:
|
||||
class Handler(BaseHTTPRequestHandler):
|
||||
|
||||
def do_GET(self):
|
||||
parsed_path = urlparse.urlparse(self.path)
|
||||
parsed_path = urllib.parse.urlparse(self.path)
|
||||
s = QgsServer()
|
||||
headers, body = s.handleRequest(parsed_path.query)
|
||||
self.send_response(200)
|
||||
for k, v in [h.split(':') for h in headers.split('\n') if h]:
|
||||
for k, v in [h.split(':') for h in headers.decode().split('\n') if h]:
|
||||
self.send_header(k, v)
|
||||
self.end_headers()
|
||||
self.wfile.write(body)
|
||||
return
|
||||
|
||||
def do_POST(self):
|
||||
content_len = int(self.headers.getheader('content-length', 0))
|
||||
post_body = self.rfile.read(content_len)
|
||||
content_len = int(self.headers.get('content-length', 0))
|
||||
post_body = self.rfile.read(content_len).decode()
|
||||
request = post_body[1:post_body.find(' ')]
|
||||
self.path = self.path + '&REQUEST_BODY=' + \
|
||||
post_body.replace('&', '') + '&REQUEST=' + request
|
||||
@ -53,6 +56,6 @@ class Handler(BaseHTTPRequestHandler):
|
||||
|
||||
if __name__ == '__main__':
|
||||
server = HTTPServer(('localhost', QGIS_SERVER_DEFAULT_PORT), Handler)
|
||||
print 'Starting server on localhost:%s, use <Ctrl-C> to stop' % \
|
||||
QGIS_SERVER_DEFAULT_PORT
|
||||
print('Starting server on localhost:%s, use <Ctrl-C> to stop' %
|
||||
QGIS_SERVER_DEFAULT_PORT)
|
||||
server.serve_forever()
|
||||
|
143
tests/src/python/test_offline_editing_wfs.py
Normal file
143
tests/src/python/test_offline_editing_wfs.py
Normal file
@ -0,0 +1,143 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Offline editing Tests.
|
||||
|
||||
WFS-T tests need using QGIS Server through
|
||||
qgis_wrapped_server.py.
|
||||
|
||||
This is an integration test for QGIS Desktop WFS-T provider and QGIS Server
|
||||
WFS-T that check if QGIS offline editing works with a WFS-T endpoint.
|
||||
|
||||
The test uses testdata/wfs_transactional/wfs_transactional.qgs and three
|
||||
initially empty shapefiles layers with points, lines and polygons.
|
||||
|
||||
The point layer is used in the test
|
||||
|
||||
From build dir, run: ctest -R PyQgsOfflineEditingWFS -V
|
||||
|
||||
.. note:: 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.
|
||||
"""
|
||||
from builtins import str
|
||||
|
||||
__author__ = 'Alessandro Pasotti'
|
||||
__date__ = '05/15/2016'
|
||||
__copyright__ = 'Copyright 2016, The QGIS Project'
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from shutil import copytree, rmtree
|
||||
import tempfile
|
||||
from time import sleep
|
||||
from utilities import unitTestDataPath
|
||||
from qgis.core import (
|
||||
QgsVectorLayer,
|
||||
QgsProject,
|
||||
)
|
||||
|
||||
from qgis.testing import (
|
||||
start_app,
|
||||
unittest,
|
||||
)
|
||||
|
||||
from offlineditingtestbase import OfflineTestBase
|
||||
|
||||
from qgis.PyQt.QtCore import QFileInfo
|
||||
|
||||
try:
|
||||
QGIS_SERVER_WFST_DEFAULT_PORT = os.environ['QGIS_SERVER_WFST_DEFAULT_PORT']
|
||||
except:
|
||||
QGIS_SERVER_WFST_DEFAULT_PORT = 8081
|
||||
|
||||
|
||||
qgis_app = start_app()
|
||||
|
||||
|
||||
class TestWFST(unittest.TestCase, OfflineTestBase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Run before all tests"""
|
||||
cls.port = QGIS_SERVER_WFST_DEFAULT_PORT
|
||||
# Create tmp folder
|
||||
cls.temp_path = tempfile.mkdtemp()
|
||||
cls.testdata_path = cls.temp_path + '/' + 'wfs_transactional' + '/'
|
||||
copytree(unitTestDataPath('wfs_transactional') + '/',
|
||||
cls.temp_path + '/' + 'wfs_transactional')
|
||||
cls.project_path = cls.temp_path + '/' + 'wfs_transactional' + '/' + \
|
||||
'wfs_transactional.qgs'
|
||||
assert os.path.exists(cls.project_path), "Project not found: %s" % \
|
||||
cls.project_path
|
||||
# Clean env just to be sure
|
||||
env_vars = ['QUERY_STRING', 'QGIS_PROJECT_FILE']
|
||||
for ev in env_vars:
|
||||
try:
|
||||
del os.environ[ev]
|
||||
except KeyError:
|
||||
pass
|
||||
# Clear all test layers
|
||||
cls._clearLayer('test_point')
|
||||
os.environ['QGIS_SERVER_DEFAULT_PORT'] = str(cls.port)
|
||||
server_path = os.path.dirname(os.path.realpath(__file__)) + \
|
||||
'/qgis_wrapped_server.py'
|
||||
cls.server = subprocess.Popen([sys.executable, server_path],
|
||||
env=os.environ)
|
||||
sleep(2)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
"""Run after all tests"""
|
||||
cls.server.terminate()
|
||||
del cls.server
|
||||
# Clear test layer
|
||||
cls._clearLayer('test_point')
|
||||
rmtree(cls.temp_path)
|
||||
|
||||
def setUp(self):
|
||||
"""Run before each test."""
|
||||
self._setUp()
|
||||
|
||||
def tearDown(self):
|
||||
"""Run after each test."""
|
||||
self._tearDown()
|
||||
|
||||
@classmethod
|
||||
def _getOnlineLayer(cls, type_name, layer_name=None):
|
||||
"""
|
||||
Layer factory (return the online layer), provider specific
|
||||
"""
|
||||
if layer_name is None:
|
||||
layer_name = 'wfs_' + type_name
|
||||
parms = {
|
||||
'srsname': 'EPSG:4326',
|
||||
'typename': type_name,
|
||||
'url': 'http://127.0.0.1:%s/?map=%s' % (cls.port,
|
||||
cls.project_path),
|
||||
'version': 'auto',
|
||||
'table': '',
|
||||
#'sql': '',
|
||||
}
|
||||
uri = ' '.join([("%s='%s'" % (k, v)) for k, v in parms.items()])
|
||||
wfs_layer = QgsVectorLayer(uri, layer_name, 'WFS')
|
||||
assert wfs_layer.isValid()
|
||||
return wfs_layer
|
||||
|
||||
@classmethod
|
||||
def _getLayer(cls, layer_name):
|
||||
"""
|
||||
Layer factory (return the backend layer), provider specific
|
||||
"""
|
||||
path = cls.testdata_path + layer_name + '.shp'
|
||||
layer = QgsVectorLayer(path, layer_name, "ogr")
|
||||
assert layer.isValid()
|
||||
return layer
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -35,6 +35,7 @@ __revision__ = '$Format:%H$'
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from shutil import copytree, rmtree
|
||||
import tempfile
|
||||
@ -69,7 +70,6 @@ class TestWFST(unittest.TestCase):
|
||||
def setUpClass(cls):
|
||||
"""Run before all tests"""
|
||||
cls.port = QGIS_SERVER_WFST_DEFAULT_PORT
|
||||
cls.testdata_path = unitTestDataPath('wfs_transactional') + '/'
|
||||
# Create tmp folder
|
||||
cls.temp_path = tempfile.mkdtemp()
|
||||
cls.testdata_path = cls.temp_path + '/' + 'wfs_transactional' + '/'
|
||||
@ -92,7 +92,7 @@ class TestWFST(unittest.TestCase):
|
||||
os.environ['QGIS_SERVER_DEFAULT_PORT'] = str(cls.port)
|
||||
server_path = os.path.dirname(os.path.realpath(__file__)) + \
|
||||
'/qgis_wrapped_server.py'
|
||||
cls.server = subprocess.Popen(['python', server_path],
|
||||
cls.server = subprocess.Popen([sys.executable, server_path],
|
||||
env=os.environ)
|
||||
sleep(2)
|
||||
|
||||
@ -152,7 +152,7 @@ class TestWFST(unittest.TestCase):
|
||||
'table': '',
|
||||
#'sql': '',
|
||||
}
|
||||
uri = ' '.join([("%s='%s'" % (k, v)) for k, v in parms.iteritems()])
|
||||
uri = ' '.join([("%s='%s'" % (k, v)) for k, v in parms.items()])
|
||||
wfs_layer = QgsVectorLayer(uri, layer_name, 'WFS')
|
||||
assert wfs_layer.isValid()
|
||||
return wfs_layer
|
||||
@ -165,7 +165,7 @@ class TestWFST(unittest.TestCase):
|
||||
request = QgsFeatureRequest(QgsExpression("%s=%s" % (attr_name,
|
||||
attr_value)))
|
||||
try:
|
||||
return layer.dataProvider().getFeatures(request).next()
|
||||
return next(layer.dataProvider().getFeatures(request))
|
||||
except StopIteration:
|
||||
raise Exception("Wrong attributes in WFS layer %s" %
|
||||
layer.name())
|
||||
|
Loading…
x
Reference in New Issue
Block a user