mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-15 00:02:52 -04:00
[ogr] Handle auto addition of vsizip prefix for vsicurl archives
Fixes #61561
This commit is contained in:
parent
2d41b76b7e
commit
e9a0bd332e
@ -790,7 +790,8 @@ QList<QgsProviderSublayerDetails> QgsOgrProviderMetadata::querySublayers( const
|
|||||||
|
|
||||||
// Try to open using VSIFileHandler
|
// Try to open using VSIFileHandler
|
||||||
const QString vsiPrefix = QgsGdalUtils::vsiPrefixForPath( uriParts.value( QStringLiteral( "path" ) ).toString() );
|
const QString vsiPrefix = QgsGdalUtils::vsiPrefixForPath( uriParts.value( QStringLiteral( "path" ) ).toString() );
|
||||||
if ( !vsiPrefix.isEmpty() && uriParts.value( QStringLiteral( "vsiPrefix" ) ).toString().isEmpty() )
|
if ( !vsiPrefix.isEmpty() && ( uriParts.value( QStringLiteral( "vsiPrefix" ) ).toString().isEmpty()
|
||||||
|
|| ( QgsGdalUtils::isVsiArchivePrefix( vsiPrefix ) && uriParts.value( QStringLiteral( "vsiPrefix" ) ).toString() != vsiPrefix ) ) )
|
||||||
{
|
{
|
||||||
if ( !uri.startsWith( vsiPrefix ) )
|
if ( !uri.startsWith( vsiPrefix ) )
|
||||||
{
|
{
|
||||||
|
@ -952,7 +952,14 @@ QList<QgsGdalUtils::VsiNetworkFileSystemDetails> QgsGdalUtils::vsiNetworkFileSys
|
|||||||
|
|
||||||
bool QgsGdalUtils::isVsiArchivePrefix( const QString &prefix )
|
bool QgsGdalUtils::isVsiArchivePrefix( const QString &prefix )
|
||||||
{
|
{
|
||||||
return vsiArchivePrefixes().contains( prefix );
|
const QStringList prefixes = vsiArchivePrefixes();
|
||||||
|
for ( const QString &archivePrefix : prefixes )
|
||||||
|
{
|
||||||
|
// catch chained prefixes, eg "/vsizip/vsicurl"
|
||||||
|
if ( prefix.contains( archivePrefix ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList QgsGdalUtils::vsiArchiveFileExtensions()
|
QStringList QgsGdalUtils::vsiArchiveFileExtensions()
|
||||||
|
@ -17,6 +17,12 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import math
|
import math
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import http.server
|
||||||
|
import os
|
||||||
|
import socketserver
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
import shutil
|
||||||
|
|
||||||
from osgeo import gdal, ogr # NOQA
|
from osgeo import gdal, ogr # NOQA
|
||||||
from qgis.PyQt.QtCore import QByteArray, QTemporaryDir, QVariant
|
from qgis.PyQt.QtCore import QByteArray, QTemporaryDir, QVariant
|
||||||
@ -119,6 +125,19 @@ class PyQgsOGRProvider(QgisTestCase):
|
|||||||
|
|
||||||
cls.dirs_to_cleanup = [cls.basetestpath]
|
cls.dirs_to_cleanup = [cls.basetestpath]
|
||||||
|
|
||||||
|
# Bring up a simple HTTP server, for vsicurl tests
|
||||||
|
os.chdir(unitTestDataPath() + "")
|
||||||
|
|
||||||
|
cls.httpd = socketserver.TCPServer(
|
||||||
|
("localhost", 0), http.server.SimpleHTTPRequestHandler
|
||||||
|
)
|
||||||
|
cls.port = cls.httpd.server_address[1]
|
||||||
|
cls.port = cls.httpd.server_address[1]
|
||||||
|
|
||||||
|
cls.httpd_thread = threading.Thread(target=cls.httpd.serve_forever)
|
||||||
|
cls.httpd_thread.daemon = True
|
||||||
|
cls.httpd_thread.start()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
"""Run after all tests"""
|
"""Run after all tests"""
|
||||||
@ -661,6 +680,11 @@ class PyQgsOGRProvider(QgisTestCase):
|
|||||||
self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXY"), "myproxyhostname.com")
|
self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXY"), "myproxyhostname.com")
|
||||||
self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXYUSERPWD"), "username")
|
self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXYUSERPWD"), "username")
|
||||||
|
|
||||||
|
settings.setValue("proxy/proxyEnabled", False)
|
||||||
|
QgsNetworkAccessManager.instance().setupDefaultProxyAndCache()
|
||||||
|
gdal.SetConfigOption("GDAL_HTTP_PROXY", "")
|
||||||
|
gdal.SetConfigOption("GDAL_HTTP_PROXYUSERPWD", "")
|
||||||
|
|
||||||
def testEditGeoJsonRemoveField(self):
|
def testEditGeoJsonRemoveField(self):
|
||||||
"""Test bugfix of https://github.com/qgis/QGIS/issues/26484 (deleting an existing field)"""
|
"""Test bugfix of https://github.com/qgis/QGIS/issues/26484 (deleting an existing field)"""
|
||||||
|
|
||||||
@ -3271,6 +3295,72 @@ class PyQgsOGRProvider(QgisTestCase):
|
|||||||
for feature in layer.getFeatures():
|
for feature in layer.getFeatures():
|
||||||
self.assertEqual(feature.geometry().wkbType(), QgsWkbTypes.MultiPolygon)
|
self.assertEqual(feature.geometry().wkbType(), QgsWkbTypes.MultiPolygon)
|
||||||
|
|
||||||
|
# vsicurl
|
||||||
|
res = metadata.querySublayers(
|
||||||
|
f"/vsicurl/http://localhost:{self.port}/polys.shp"
|
||||||
|
)
|
||||||
|
self.assertEqual(len(res), 1)
|
||||||
|
self.assertEqual(res[0].layerNumber(), 0)
|
||||||
|
self.assertEqual(res[0].name(), "polys")
|
||||||
|
self.assertEqual(res[0].description(), "")
|
||||||
|
self.assertEqual(
|
||||||
|
res[0].uri(),
|
||||||
|
f"/vsicurl/http://localhost:{self.port}/polys.shp|layername=polys",
|
||||||
|
)
|
||||||
|
self.assertEqual(res[0].providerKey(), "ogr")
|
||||||
|
self.assertEqual(res[0].type(), QgsMapLayerType.VectorLayer)
|
||||||
|
self.assertEqual(res[0].featureCount(), Qgis.FeatureCountState.Uncounted)
|
||||||
|
self.assertEqual(res[0].wkbType(), QgsWkbTypes.Type.Polygon)
|
||||||
|
self.assertEqual(res[0].geometryColumnName(), "")
|
||||||
|
self.assertEqual(res[0].driverName(), "ESRI Shapefile")
|
||||||
|
vl = res[0].toLayer(options)
|
||||||
|
self.assertTrue(vl.isValid())
|
||||||
|
self.assertEqual(vl.wkbType(), QgsWkbTypes.Type.MultiPolygon)
|
||||||
|
|
||||||
|
# vsicurl with zip
|
||||||
|
res = metadata.querySublayers(
|
||||||
|
f"/vsicurl/http://localhost:{self.port}/zip/points2.zip"
|
||||||
|
)
|
||||||
|
self.assertEqual(len(res), 1)
|
||||||
|
self.assertEqual(res[0].layerNumber(), 0)
|
||||||
|
self.assertEqual(res[0].name(), "points.shp")
|
||||||
|
self.assertEqual(res[0].description(), "")
|
||||||
|
self.assertEqual(
|
||||||
|
res[0].uri(),
|
||||||
|
f"/vsizip//vsicurl/http://localhost:{self.port}/zip/points2.zip/points.shp|layername=points",
|
||||||
|
)
|
||||||
|
self.assertEqual(res[0].providerKey(), "ogr")
|
||||||
|
self.assertEqual(res[0].type(), QgsMapLayerType.VectorLayer)
|
||||||
|
self.assertEqual(res[0].featureCount(), Qgis.FeatureCountState.Uncounted)
|
||||||
|
self.assertEqual(res[0].wkbType(), QgsWkbTypes.Type.Point)
|
||||||
|
self.assertEqual(res[0].geometryColumnName(), "")
|
||||||
|
self.assertEqual(res[0].driverName(), "ESRI Shapefile")
|
||||||
|
vl = res[0].toLayer(options)
|
||||||
|
self.assertTrue(vl.isValid())
|
||||||
|
self.assertEqual(vl.wkbType(), QgsWkbTypes.Type.Point)
|
||||||
|
|
||||||
|
# vsicurl with zip, explicit vsizip prefix
|
||||||
|
res = metadata.querySublayers(
|
||||||
|
f"/vsizip//vsicurl/http://localhost:{self.port}/zip/points2.zip"
|
||||||
|
)
|
||||||
|
self.assertEqual(len(res), 1)
|
||||||
|
self.assertEqual(res[0].layerNumber(), 0)
|
||||||
|
self.assertEqual(res[0].name(), "points")
|
||||||
|
self.assertEqual(res[0].description(), "")
|
||||||
|
self.assertEqual(
|
||||||
|
res[0].uri(),
|
||||||
|
f"/vsizip//vsicurl/http://localhost:{self.port}/zip/points2.zip|layername=points",
|
||||||
|
)
|
||||||
|
self.assertEqual(res[0].providerKey(), "ogr")
|
||||||
|
self.assertEqual(res[0].type(), QgsMapLayerType.VectorLayer)
|
||||||
|
self.assertEqual(res[0].featureCount(), Qgis.FeatureCountState.Uncounted)
|
||||||
|
self.assertEqual(res[0].wkbType(), QgsWkbTypes.Type.Point)
|
||||||
|
self.assertEqual(res[0].geometryColumnName(), "")
|
||||||
|
self.assertEqual(res[0].driverName(), "ESRI Shapefile")
|
||||||
|
vl = res[0].toLayer(options)
|
||||||
|
self.assertTrue(vl.isValid())
|
||||||
|
self.assertEqual(vl.wkbType(), QgsWkbTypes.Type.Point)
|
||||||
|
|
||||||
@unittest.skipIf(
|
@unittest.skipIf(
|
||||||
int(gdal.VersionInfo("VERSION_NUM")) < GDAL_COMPUTE_VERSION(3, 4, 0),
|
int(gdal.VersionInfo("VERSION_NUM")) < GDAL_COMPUTE_VERSION(3, 4, 0),
|
||||||
"GDAL 3.4 required",
|
"GDAL 3.4 required",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user