Skip to content

Commit c422268

Browse files
committed
Fix extraction of ogr LayerName from multi-layer dataset URIs
Adds supports for "layerid" when present. Drop special handling for "table=" portions found in URI, making the code more generic. Includes testcase. Fixes #15698 - import geodatabase to postgis via processing
1 parent 167a5af commit c422268

File tree

3 files changed

+142
-14
lines changed

3 files changed

+142
-14
lines changed

python/plugins/processing/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ PLUGIN_INSTALL(processing tests/data ${TEST_DATA_FILES})
77
IF(ENABLE_TESTS)
88
INCLUDE(UsePythonTest)
99
ADD_PYTHON_TEST(ProcessingParametersTest ParametersTest.py)
10+
ADD_PYTHON_TEST(ProcessingToolsTest ToolsTest.py)
1011
ADD_PYTHON_TEST(ProcessingQgisAlgorithmsTest QgisAlgorithmsTest.py)
1112
ADD_PYTHON_TEST(ProcessingGdalAlgorithmsTest GdalAlgorithmsTest.py)
1213
ENDIF(ENABLE_TESTS)
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
ToolsTest
6+
---------------------
7+
Date : July 2017
8+
Copyright : (C) 2017 by Nyall Dawson
9+
Email : nyall dot dawson at gmail dot com
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
__author__ = 'Nyall Dawson'
21+
__date__ = 'July 2016'
22+
__copyright__ = '(C) 2016, Nyall Dawson'
23+
24+
# This will get replaced with a git SHA1 when you do a git archive
25+
26+
__revision__ = '$Format:%H$'
27+
28+
from qgis.testing import start_app, unittest
29+
from processing.tests.TestData import points2
30+
from processing.tools import vector
31+
from qgis.core import (QgsVectorLayer, QgsFeatureRequest)
32+
from processing.core.ProcessingConfig import ProcessingConfig
33+
34+
import os.path
35+
import errno
36+
import shutil
37+
38+
dataFolder = os.path.join(os.path.dirname(__file__), '../../../../tests/testdata/')
39+
tmpBaseFolder = os.path.join(os.sep, 'tmp', 'qgis_test', str(os.getpid()))
40+
41+
42+
def mkDirP(path):
43+
try:
44+
os.makedirs(path)
45+
except OSError as exc:
46+
if exc.errno == errno.EEXIST and os.path.isdir(path):
47+
pass
48+
else:
49+
raise
50+
51+
start_app()
52+
53+
54+
class VectorTest(unittest.TestCase):
55+
56+
@classmethod
57+
def setUpClass(cls):
58+
mkDirP(tmpBaseFolder)
59+
60+
@classmethod
61+
def tearDownClass(cls):
62+
shutil.rmtree(tmpBaseFolder)
63+
pass
64+
65+
# See http://hub.qgis.org/issues/15698
66+
def test_ogrLayerName(self):
67+
tmpdir = os.path.join(tmpBaseFolder, 'ogrLayerName')
68+
os.mkdir(tmpdir)
69+
70+
def linkTestfile(f, t):
71+
os.link(os.path.join(dataFolder, f), os.path.join(tmpdir, t))
72+
73+
linkTestfile('geom_data.csv', 'a.csv')
74+
name = vector.ogrLayerName(tmpdir)
75+
self.assertEqual(name, 'a')
76+
77+
linkTestfile('wkt_data.csv', 'b.csv')
78+
name = vector.ogrLayerName(tmpdir + '|layerid=0')
79+
self.assertEqual(name, 'a')
80+
name = vector.ogrLayerName(tmpdir + '|layerid=1')
81+
self.assertEqual(name, 'b')
82+
83+
name = vector.ogrLayerName(tmpdir + '|layerid=2')
84+
self.assertEqual(name, 'invalid-layerid')
85+
86+
name = vector.ogrLayerName(tmpdir + '|layername=f')
87+
self.assertEqual(name, 'f') # layername takes precedence
88+
89+
name = vector.ogrLayerName(tmpdir + '|layerid=0|layername=f2')
90+
self.assertEqual(name, 'f2') # layername takes precedence
91+
92+
name = vector.ogrLayerName(tmpdir + '|layername=f2|layerid=0')
93+
self.assertEqual(name, 'f2') # layername takes precedence
94+
95+
def testFeatures(self):
96+
ProcessingConfig.initialize()
97+
98+
test_data = points2()
99+
test_layer = QgsVectorLayer(test_data, 'test', 'ogr')
100+
101+
# test with all features
102+
features = vector.features(test_layer)
103+
self.assertEqual(len(features), 8)
104+
self.assertEqual(set([f.id() for f in features]), set([0, 1, 2, 3, 4, 5, 6, 7]))
105+
106+
previous_value = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
107+
108+
# using selected features, but no selection
109+
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, True)
110+
test_layer.removeSelection()
111+
features = vector.features(test_layer)
112+
self.assertEqual(len(features), 8)
113+
self.assertEqual(set([f.id() for f in features]), set([0, 1, 2, 3, 4, 5, 6, 7]))
114+
115+
ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)
116+
117+
118+
if __name__ == '__main__':
119+
unittest.main()

python/plugins/processing/tools/vector.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838

3939
from PyQt4 import QtSql
4040
from PyQt4.QtCore import QVariant, QSettings
41+
from osgeo import ogr
42+
4143
from qgis.core import (QGis, QgsFields, QgsField, QgsGeometry, QgsRectangle,
4244
QgsSpatialIndex, QgsMapLayerRegistry, QgsMapLayer, QgsVectorLayer,
4345
QgsVectorFileWriter, QgsDistanceArea, QgsDataSourceURI, QgsCredentials)
@@ -511,20 +513,26 @@ def ogrConnectionString(uri):
511513

512514

513515
def ogrLayerName(uri):
514-
if 'host' in uri:
515-
regex = re.compile('(table=")(.+?)(\.)(.+?)"')
516-
r = regex.search(uri)
517-
return '"' + r.groups()[1] + '.' + r.groups()[3] + '"'
518-
elif 'dbname' in uri:
519-
regex = re.compile('(table=")(.+?)"')
520-
r = regex.search(uri)
521-
return r.groups()[1]
522-
elif 'layername' in uri:
523-
regex = re.compile('(layername=)(.*)')
524-
r = regex.search(uri)
525-
return r.groups()[1]
526-
else:
527-
return os.path.basename(os.path.splitext(uri)[0])
516+
fields = uri.split('|')
517+
ogruri = fields[0]
518+
fields = fields[1:]
519+
layerid = 0
520+
for f in fields:
521+
if f.startswith('layername='):
522+
# Name encoded in uri, nothing more needed
523+
return f.split('=')[1]
524+
if f.startswith('layerid='):
525+
layerid = int(f.split('=')[1])
526+
# Last layerid= takes precedence, to allow of layername to
527+
# take precedence
528+
ds = ogr.Open(ogruri)
529+
if not ds:
530+
return "invalid-uri"
531+
ly = ds.GetLayer(layerid)
532+
if not ly:
533+
return "invalid-layerid"
534+
name = ly.GetName()
535+
return name
528536

529537

530538
class VectorWriter:

0 commit comments

Comments
 (0)