Skip to content

Commit

Permalink
[delimitedtext] Ensure that encodeUri and decodeUri are lossless
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] authored and nyalldawson committed Nov 15, 2020
1 parent c72dadf commit 872793e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 4 deletions.
44 changes: 42 additions & 2 deletions src/providers/delimitedtext/qgsdelimitedtextprovider.cpp
Expand Up @@ -1262,14 +1262,54 @@ QString QgsDelimitedTextProvider::description() const


QVariantMap QgsDelimitedTextProviderMetadata::decodeUri( const QString &uri ) QVariantMap QgsDelimitedTextProviderMetadata::decodeUri( const QString &uri )
{ {
const QUrl url( uri );
const QUrlQuery queryItems( url.query() );

QString subset;
QStringList openOptions;
for ( const auto &item : queryItems.queryItems() )
{
if ( item.first == QStringLiteral( "subset" ) )
{
subset = item.second;
}
else
{
openOptions << QStringLiteral( "%1=%2" ).arg( item.first, item.second );
}
}

QVariantMap components; QVariantMap components;
components.insert( QStringLiteral( "path" ), QUrl( uri ).toLocalFile() ); components.insert( QStringLiteral( "path" ), url.toLocalFile() );
if ( !subset.isEmpty() )
components.insert( QStringLiteral( "subset" ), subset );
components.insert( QStringLiteral( "openOptions" ), openOptions );
return components; return components;
} }


QString QgsDelimitedTextProviderMetadata::encodeUri( const QVariantMap &parts ) QString QgsDelimitedTextProviderMetadata::encodeUri( const QVariantMap &parts )
{ {
return QStringLiteral( "file://%1" ).arg( parts.value( QStringLiteral( "path" ) ).toString() ); QUrl url( QStringLiteral( "file://%1" ).arg( parts.value( QStringLiteral( "path" ) ).toString() ) );
const QStringList openOptions = parts.value( QStringLiteral( "openOptions" ) ).toStringList();

QUrlQuery queryItems;
for ( const auto &option : openOptions )
{
int separator = option.indexOf( '=' );
if ( separator >= 0 )
{
queryItems.addQueryItem( option.mid( 0, separator ), option.mid( separator + 1 ) );
}
else
{
queryItems.addQueryItem( option, QString() );
}
}
if ( parts.contains( QStringLiteral( "subset" ) ) )
queryItems.addQueryItem( QStringLiteral( "subset" ), parts.value( QStringLiteral( "subset" ) ).toString() );
url.setQuery( queryItems );

return url.toString();
} }


QgsDataProvider *QgsDelimitedTextProviderMetadata::createProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags ) QgsDataProvider *QgsDelimitedTextProviderMetadata::createProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
Expand Down
6 changes: 5 additions & 1 deletion tests/src/python/test_qgsdelimitedtextprovider.py
Expand Up @@ -47,7 +47,7 @@
QgsFeatureSource) QgsFeatureSource)


from qgis.testing import start_app, unittest from qgis.testing import start_app, unittest
from utilities import unitTestDataPath, compareWkt from utilities import unitTestDataPath, compareWkt, compareUrl


from providertestbase import ProviderTestCase from providertestbase import ProviderTestCase


Expand Down Expand Up @@ -292,6 +292,10 @@ def delimitedTextData(self, testname, filename, requests, verbose, **params):
if verbose: if verbose:
print(testname) print(testname)
layer = QgsVectorLayer(urlstr, 'test', 'delimitedtext') layer = QgsVectorLayer(urlstr, 'test', 'delimitedtext')

# decodeUri / encodeUri check
self.assertTrue(compareUrl(layer.source(), QgsProviderRegistry.instance().encodeUri('delimitedtext', QgsProviderRegistry.instance().decodeUri('delimitedtext', layer.source()))))

uri = layer.dataProvider().dataSourceUri() uri = layer.dataProvider().dataSourceUri()
if verbose: if verbose:
print(uri) print(uri)
Expand Down
16 changes: 15 additions & 1 deletion tests/src/python/utilities.py
Expand Up @@ -22,7 +22,7 @@
except ImportError: except ImportError:
from urllib.request import urlopen, HTTPError, URLError from urllib.request import urlopen, HTTPError, URLError


from qgis.PyQt.QtCore import QDir from qgis.PyQt.QtCore import QDir, QUrl, QUrlQuery


from qgis.core import ( from qgis.core import (
QgsCoordinateReferenceSystem, QgsCoordinateReferenceSystem,
Expand Down Expand Up @@ -130,6 +130,20 @@ def doubleNear(a, b, tol=0.0000000001):
return abs(float(a) - float(b)) < tol return abs(float(a) - float(b)) < tol




def compareUrl(a, b):
url_a = QUrl(a)
url_b = QUrl(b)
query_a = QUrlQuery(url_a.query()).queryItems()
query_b = QUrlQuery(url_b.query()).queryItems()

url_equal = url_a.path() == url_b.path()
for item in query_a:
if item not in query_b:
url_equal = False

return url_equal


def compareWkt(a, b, tol=0.000001): def compareWkt(a, b, tol=0.000001):
""" """
Compares two WKT strings, ignoring allowed differences between strings Compares two WKT strings, ignoring allowed differences between strings
Expand Down

0 comments on commit 872793e

Please sign in to comment.