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
nirvn committed Nov 14, 2020
1 parent 278ccb8 commit 53ec183
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 ) const
{
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;
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;
}

QString QgsDelimitedTextProviderMetadata::encodeUri( const QVariantMap &parts ) const
{
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 )
Expand Down
6 changes: 5 additions & 1 deletion tests/src/python/test_qgsdelimitedtextprovider.py
Expand Up @@ -47,7 +47,7 @@
QgsFeatureSource)

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

from providertestbase import ProviderTestCase

Expand Down Expand Up @@ -292,6 +292,10 @@ def delimitedTextData(self, testname, filename, requests, verbose, **params):
if verbose:
print(testname)
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()
if verbose:
print(uri)
Expand Down
16 changes: 15 additions & 1 deletion tests/src/python/utilities.py
Expand Up @@ -22,7 +22,7 @@
except ImportError:
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 (
QgsCoordinateReferenceSystem,
Expand Down Expand Up @@ -130,6 +130,20 @@ def doubleNear(a, b, tol=0.0000000001):
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):
"""
Compares two WKT strings, ignoring allowed differences between strings
Expand Down

0 comments on commit 53ec183

Please sign in to comment.