def getHttp(uri, params): nam = QgsNetworkAccessManager.instance() QgsApplication.setOverrideCursor(Qt.WaitCursor) try: rq = QUrl(uri) q = QUrlQuery() for (k, v) in params.items(): q.addQueryItem(k, v) rq.setQuery(q) req = QNetworkRequest(rq) try: reply = nam.blockingGet(req) resource = reply.content().data().decode("utf8") r = json.loads(resource) if isinstance(r, list): return r else: return [r] except Exception as e: for m in e.args: QgsMessageLog.logMessage(m, "Extensions") finally: QgsApplication.restoreOverrideCursor() return None
def prepare_url(self): """Prepare a query to be as an URL. if the query is not ready to be URL prepared, a None is returned. :return: The URL encoded with the query. :rtype: basestring """ if not self._query_is_ready: return None if self._output_format: query = re.sub( r'output="[a-z]*"', 'output="%s"' % self._output_format, self._query_prepared) query = re.sub( r'\[out:[a-z]*', '[out:%s' % self._output_format, query) else: query = self._query_prepared url_query = QUrl(self._overpass) query_string = QUrlQuery() query_string.addQueryItem('data', query) query_string.addQueryItem('info', 'QgisQuickOSMPlugin') url_query.setQuery(query_string) return url_query.toString()
def __init__(self, request, parent=None): super().__init__(parent) self.url = request.request().url() self.operation = self.operation2string(request.operation()) query = QUrlQuery(self.url) RequestDetailsItem('Operation', self.operation, self) RequestDetailsItem('Thread', request.originatingThreadId(), self) RequestDetailsItem( 'Initiator', request.initiatorClassName() if request.initiatorClassName() else 'unknown', self) if request.initiatorRequestId(): RequestDetailsItem('ID', str(request.initiatorRequestId()), self) RequestDetailsItem( 'Cache (control)', self.cache_control_to_string(request.request().attribute( QNetworkRequest.CacheLoadControlAttribute)), self) RequestDetailsItem( 'Cache (save)', 'Can store result in cache' if request.request().attribute( QNetworkRequest.CacheSaveControlAttribute) else 'Result cannot be stored in cache', self) query_items = query.queryItems() if query_items: RequestQueryItems(query_items, self) RequestHeadersItem(request, self) if self.operation in ('POST', 'PUT'): PostContentItem(request, self)
def prepare_url(self, output: QueryLanguage = None) -> str: """Prepare a query to be as an URL. if the query is not ready to be URL prepared, a None is returned. :return: The URL encoded with the query. :rtype: basestring """ if not self._query_is_ready: return None if self._output_format: query = re.sub(r'output="[a-z]*"', 'output="{}"'.format(self._output_format), self._query_prepared) query = re.sub(r'\[out:[a-z]*', '[out:{}'.format(self._output_format), query) else: query = self._query_prepared url_query = QUrl(self._overpass) query_string = QUrlQuery() query_string.addQueryItem('data', query) if output == QueryLanguage.XML: query_string.addQueryItem('target', "xml") elif output == QueryLanguage.OQL: query_string.addQueryItem('target', "mapql") query_string.addQueryItem('info', 'QgisQuickOSMPlugin') url_query.setQuery(query_string) return url_query.toString()
def url_with_param(url, params) -> str: url = QUrl(url) q = QUrlQuery(url) for key, value in params.items(): q.addQueryItem(key, value) url.setQuery(q) return url
def __init__(self, uri='', providerOptions=QgsDataProvider.ProviderOptions()): """ :param uri: <app>.<model>[?geofield=<name>] :param providerOptions: """ super().__init__(uri) self._is_valid = False self.setNativeTypes(( # TODO QgsVectorDataProvider.NativeType('Integer', 'integer', QVariant.Int, -1, -1, 0, 0), QgsVectorDataProvider.NativeType('Text', 'text', QVariant.String, -1, -1, -1, -1), )) self._uri = uri url = QUrl(uri) url_query = QUrlQuery(url) self._full_model_name = url.path() self._app_label, self._model_name = self._full_model_name.split('.') self._model = apps.get_model(self._app_label, self._model_name) # Django model self._meta = self._model._meta self._qgis_fields = QgsFields() self._django_fields = [] # Django fields represented by provider in the same order as QgsFields for django_field in self._meta.get_fields(): # TODO: more field types qgis_field = self._get_qgis_field_from_django_field(django_field) if qgis_field: self._qgis_fields.append(qgis_field) self._django_fields.append(django_field) self._geo_field_name = url_query.queryItemValue('geofield') self._geo_field = None # Django geometry field if self._geo_field_name: self._meta.get_field(self._geo_field_name) else: # If geometry field was not specified in uri, use the first one if any. for field in self._meta.get_fields(): if isinstance(field, models.GeometryField): self._geo_field = field self._geo_field_name = field.name break self._wkbType = QgsWkbTypes.NoGeometry if self._geo_field: for geo_field_class in wkb_types.keys(): if isinstance(self._geo_field, geo_field_class): self._wkbType = wkb_types[geo_field_class] break self._extent = QgsRectangle() self._crs = None if self._geo_field: self._crs = QgsCoordinateReferenceSystem.fromEpsgId(self._geo_field.srid) self._provider_options = providerOptions self._is_valid = True
def wfs(self): name = self.connectionCombo.currentText() conn = QgsOwsConnection("wfs", name) uri = conn.uri().param('url') req_version = conn.uri().param('version') s = QgsSettings() checked_version = s.value( "qgis/connections-wfs/{}/checked_version".format(name), False) if req_version == "auto" or not checked_version: # detect version u = QUrlQuery() u.addQueryItem("request", "GetCapabilities") u.addQueryItem("service", "WFS") if req_version == "auto": u.addQueryItem("acceptversions", "2.0.0,1.1.0,1.0.0") elif not checked_version: u.addQueryItem("version", req_version) final_url = QUrl(uri) final_url.setQuery(u) xml, ns_map = xml_parse(remote_open_from_qgis( final_url.toString())) root = xml.getroot() if 'ows' in ns_map: versions = [ v.text for v in root.findall( "./ows:ServiceIdentification/ows:ServiceTypeVersion", ns_map) ] else: versions = [ v.text for v in root.findall( "./ServiceIdentification/ServiceTypeVersion", ns_map) ] if not versions: if 'version' in root.attrib: versions = [root.attrib['version']] if not versions: raise RuntimeError("Cannot determine WFS version") # take the greatest version, if more than one version = sorted(versions)[-1] if version != req_version: QgsMessageLog.logMessage( "Requested WFS version {}, got {}".format( req_version, version)) else: s.setValue( "qgis/connections-wfs/{}/checked_version".format(name), True) else: version = req_version with qgis_proxy_settings(): return WebFeatureService(url=uri, version=version)
def get_segment(self, graph_name, graph_version, segment_id, is_hd_segments=False): if self.connection is None: return [] url = self.connection.get_connection_url() + '/' + ('hdwaysegments' if is_hd_segments else 'segments') +\ '/graphs/' + graph_name + '/versions/' + graph_version url_query_items = QUrlQuery() url_query_items.addQueryItem('ids', str(segment_id)) return self.process_get_call(url, url_query_items, report_url=False)
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 post(self, url, params: dict = None, data: bytes = b'', timeout: int = 20000, content_type: str = None, **kwargs) -> Reply: ''' posts data to given url (POST) asynchronous posts are not implemented yet Parameters ---------- url : str the url to post to params : dict, optional query parameters with the parameters as keys and the values as values, defaults to no query parameters data : bytes, optional the data to post as a byte-string, defaults to no data posted timeout : int, optional the timeout of synchronous requests in milliseconds, will be ignored when making asynchronous requests, defaults to 20000 ms content_type : str, optional the content type of the data, puts content type into header of request **kwargs : additional parameters matching the requests-interface will be ignored (e.g. verify is not supported) Returns ---------- Reply the response is returned in case of synchronous calls, if you are using asynchronous calls retrieve the response via the finished- signal instead ''' qurl = QUrl(url) if params: query = QUrlQuery() for param, value in params.items(): query.addQueryItem(param, str(value)) qurl.setQuery(query.query()) if self.synchronous: return self._post_sync(qurl, timeout=timeout, data=data, content_type=content_type) return self._post_async(qurl, content_type=content_type)
def query(self, query: str) -> dict: """Perform a nominatim query. :param query: Query to execute on the nominatim server. :type query: basestring :return: The result of the query as a dictionary. :rtype: dict :raise NetWorkErrorException: """ query_string = QUrlQuery() query_string.addQueryItem('q', query) query_string.addQueryItem('format', 'json') query_string.addQueryItem('info', 'QgisQuickOSMPlugin') self._url.setQuery(query_string) self.download() with open(self.result_path, encoding='utf8') as json_file: data = json.load(json_file) if not data: raise NominatimBadRequest(query) return data
def query(self, query): """Perform a nominatim query. :param query: Query to execute on the nominatim server. :type query: basestring :return: The result of the query as a dictionary. :rtype: dict :raise NetWorkErrorException """ url_query = QUrl(self.__url) query_string = QUrlQuery() query_string.addQueryItem('q', query) query_string.addQueryItem('format', 'json') query_string.addQueryItem('info', 'QgisQuickOSMPlugin') url_query.setQuery(query_string) loop = QEventLoop() downloader = QgsFileDownloader(url_query, self.result_path, delayStart=True) downloader.downloadExited.connect(loop.quit) downloader.downloadError.connect(self.error) downloader.downloadCanceled.connect(self.canceled) downloader.downloadCompleted.connect(self.completed) downloader.startDownload() loop.exec_() with open(self.result_path) as json_file: data = json.load(json_file) return data
def add_graph_version_new(self, new_graph_file, graph_name, graph_version, is_hd_segments, override_if_exists): if self.connection is None: return {"error": {"msg": "No connection selected"}} url = self.connection.get_connection_url() + '/' + ('hdwaysegments' if is_hd_segments else 'segments') + \ '/graphs/' + graph_name + '/versions/' + graph_version url_query_items = QUrlQuery() url_query_items.addQueryItem('overrideIfExists', str(override_if_exists)) return self.process_post_call(url, url_query_items, new_graph_file, False)
def query(self, query): """ Perform a nominatim query @param query: Query to execute @type query: str @raise NetWorkErrorException @return: the result of the query @rtype: str """ url_query = QUrl(self.__url) # query = QUrl.toPercentEncoding(query) query_string = QUrlQuery() query_string.addQueryItem('q', query) query_string.addQueryItem('format', 'json') query_string.addQueryItem('info', 'QgisQuickOSMPlugin') url_query.setQuery(query_string) request = QNetworkRequest(url_query) # request.setRawHeader("User-Agent", "QuickOSM") self.network_reply = self.network.get(request) self.loop = QEventLoop() self.network.finished.connect(self._end_of_request) self.loop.exec_() if self.network_reply.error() == QNetworkReply.NoError: return json.loads(self.data) else: raise NetWorkErrorException(suffix="Nominatim API")
def clean_ows_url(url): """clean an OWS URL of added basic service parameters""" url = QUrl(url) query_string = url.query() if query_string: query_string = QUrlQuery(query_string) query_string.removeQueryItem('service') query_string.removeQueryItem('SERVICE') query_string.removeQueryItem('request') query_string.removeQueryItem('REQUEST') url.setQuery(query_string) return url.toString()
class MyUrl: def __init__(self, url): self.url = url self.query = QUrlQuery() @classmethod def fromLocalFile(cls, filename): return cls(QUrl.fromLocalFile(filename)) def addQueryItem(self, k, v): self.query.addQueryItem(k, v) def toString(self): urlstr = self.url.toString() querystr = self.query.toString(QUrl.FullyDecoded) if querystr != '': urlstr += '?' urlstr += querystr return urlstr
class MyUrl: def __init__(self, url): self.url = url self.query = QUrlQuery() @classmethod def fromLocalFile(cls, filename): return cls(QUrl.fromLocalFile(filename)) def addQueryItem(self, k, v): self.query.addQueryItem(k, v) def toString(self): urlstr = self.url.toString() querystr = self.query.toString(QUrl.FullyDecoded) if querystr != "": urlstr += "?" urlstr += querystr return urlstr
def get(self, url: str, params: dict = None, timeout: int = 20000, **kwargs) -> Reply: ''' queries given url (GET) Parameters ---------- url : str the url to request params : dict, optional query parameters with the parameters as keys and the values as values, defaults to no query parameters timeout : int, optional the timeout of synchronous requests in milliseconds, will be ignored when making asynchronous requests, defaults to 20000 ms **kwargs : additional parameters matching the requests interface will be ignored (e.g. verify is not supported) Returns ---------- Reply the response is returned in case of synchronous calls, if you are using asynchronous calls retrieve the response via the finished- signal instead ''' qurl = QUrl(url) if params: query = QUrlQuery() for param, value in params.items(): query.addQueryItem(param, str(value)) qurl.setQuery(query.query()) if self.synchronous: return self._get_sync(qurl, timeout=timeout) return self._get_async(qurl)
def __parseTask(self, task): """ :type task: QUrl :return: dict """ taskMap = {u'action': task.path()} for key, value in QUrlQuery(task).queryItems(task.PrettyDecoded): taskMap[str(key)] = str(value) # QUrl.toPercentEncoding((value)) return taskMap
def test_real_wrong_request(self): """Test wrong request. This is test is using internet. """ url = QUrl(OVERPASS_SERVERS[0]) query_string = QUrlQuery() query_string.addQueryItem('data', 'fake_query') url.setQuery(query_string) overpass = ConnexionOAPI(url.toString()) self.assertListEqual(overpass.errors, []) # We don't want the FileNotFoundError try: overpass.run() except OverpassBadRequestException: self.assertTrue(True) except FileNotFoundError: self.assertFalse(True) else: self.assertFalse(True) self.assertEqual(len(overpass.errors), 1)
def _sendRequest(self, url, params, headers={}): if self.asynchonous: if self.reply is not None: self.reply.finished.disconnect(self.reply_finished) self.reply.abort() self.reply = None url = QUrl(url) urlQuery = QUrlQuery(url) for key, value in params.items(): urlQuery.addQueryItem(key, value) QgsLogger.debug('Request: {}'.format(url.toEncoded())) url.setQuery(urlQuery) request = QNetworkRequest(url) for key, value in headers.items(): request.setRawHeader(key, value) self.reply = QgsNetworkAccessManager.instance().get(request) else: url = url + '?' + urllib.parse.urlencode(params) response = urllib.request.urlopen(url) data = json.load(response) self.load_data(data)
def query(self, query): """ Make a query to the overpass @param query:Query to execute @type query:str @raise OverpassBadRequestException,NetWorkErrorException, OverpassTimeoutException @return: the result of the query @rtype: str """ url_query = QUrl(self.__url + 'interpreter') # The output format can be forced (JSON or XML) if self.__output: query = re.sub(r'output="[a-z]*"', 'output="' + self.__output + '"', query) query = re.sub(r'\[out:[a-z]*', '[out:' + self.__output, query) # noinspection PyCallByClass # encoded_query = QUrl.toPercentEncoding(query) query_string = QUrlQuery() query_string.addQueryItem('data', query) query_string.addQueryItem('info', 'QgisQuickOSMPlugin') url_query.setQuery(query_string) request = QNetworkRequest(url_query) # request.setRawHeader("User-Agent", "QuickOSM") self.network_reply = self.network.get(request) self.loop = QEventLoop() self.network.finished.connect(self._end_of_request) self.loop.exec_() if self.network_reply.error() == QNetworkReply.NoError: file_obj = codecs.open(self.result_path, 'r', 'utf-8') file_obj.seek(0, 2) fsize = file_obj.tell() file_obj.seek(max(fsize - 1024, 0), 0) lines = file_obj.readlines() lines = lines[-10:] # Get last 10 lines timeout = '<remark> runtime error: Query timed out in "[a-z]+" ' \ 'at line [\d]+ after ([\d]+) seconds. </remark>' if re.search(timeout, ''.join(lines)): raise OverpassTimeoutException else: return self.result_path elif self.network_reply.error() == QNetworkReply.UnknownContentError: raise OverpassBadRequestException else: raise NetWorkErrorException(suffix="Overpass OSM API")
def mock_doStartPrepare(self): PredictionManagerTest.request_urls.append(self.url()) query = QUrlQuery(QUrl(self.url())) query_date = query.queryItemValue('begin_date').replace(' ', 'T') query_vel_type = query.queryItemValue('vel_type') query_interval = query.queryItemValue('interval') query_station = query.queryItemValue('station') query_bin = query.queryItemValue('bin') filename = '{}_{}-{}-{}-{}.xml'.format(query_station, query_bin, query_date, query_vel_type, query_interval) self.fetcher = Mock(QgsNetworkContentFetcherTask) with open(os.path.join(os.path.dirname(__file__), 'data', filename), 'r') as dataFile: self.content = dataFile.read()
def wfs(self): conn = QgsOwsConnection("wfs", self.connectionCombo.currentText()) uri = conn.uri().param('url') version = conn.uri().param('version') if version == "auto": # detect version u = QUrlQuery(uri) u.addQueryItem("request", "GetCapabilities") u.addQueryItem("acceptversions", "2.0.0,1.1.0,1.0.0") xml, ns_map = xml_parse(remote_open_from_qgis(u.query())) root = xml.getroot() versions = [ v.text for v in root.findall( "./ows:ServiceIdentification/ows:ServiceTypeVersion", ns_map) ] # take the greatest version, if more than one version = sorted(versions)[-1] with qgis_proxy_settings(): return WebFeatureService(url=uri, version=version)
def do_request(self, point: QgsPointXY) -> None: query = QUrlQuery() query.addQueryItem("lat", str(point.y())) query.addQueryItem("lon", str(point.x())) query.addQueryItem("format", "json") url = QUrl(self.URL) url.setQuery(query) request = QNetworkRequest(url) request.setHeader(QNetworkRequest.UserAgentHeader, "*****@*****.**") response = self.nam.blockingGet(request) self._status_code = response.attribute( QNetworkRequest.HttpStatusCodeAttribute) self._content = json.loads(bytes(response.content())) if self._content.get("error"): self._error_string = self._content["error"] return
def __init__(self, url): self.url = url self.query = QUrlQuery()
def query(self, *args: object, max_retries: int = 2, **kwargs: object ) -> Reply: ''' query the service Parameters ---------- *args query parameters without keyword **kwargs query parameters with keyword and value max_retries: int, optional maximum number of retries after connection error, defaults to 2 retries Returns ---------- Reply the reply of the geocoding API, contains a list of geojson features with "geometry" attribute of the matched address "properties" containing "text" (description of found address in BKG database), "typ", "treffer" and "score" (the higher the better the match) Raises ---------- RuntimeError critical error (no parameters, no access to service/url), it is recommended to abort geocoding ValueError request got through but parameters were malformed, may still work for different features ''' self.params = {} retries = 0 if self.rs: self.params['filter'] = f'rs:{self.rs}' self.params['srsname'] = self.crs query = self._build_params(*args, **kwargs) if not query: raise ValueError('keine Suchparameter gefunden') self.params['query'] = query do_post = self.area_wkt is not None if self.area_wkt: self.params['geometry'] = self.area_wkt while True: try: if not do_post: self.reply = requests.get(self.url, params=self.params) else: content_type = 'application/x-www-form-urlencoded' data = QUrlQuery() for k, v in self.params.items(): data.addQueryItem(k, v) self.reply = requests.post( self.url, data=data.query().encode('utf-8'), content_type=content_type ) except ConnectionError: if retries >= max_retries: raise RuntimeError( f'Anfrage nach {retries + 1} gescheiterten ' 'Verbindungsversuchen abgebrochen.') retries += 1 continue break self.raise_on_error(self.reply) return self.reply
def url(self): query = QUrlQuery() query.addQueryItem('application', CoopsApplicationName) query.addQueryItem('begin_date', self.startTime.toString('yyyyMMdd hh:mm')) query.addQueryItem('end_date', self.endTime.addSecs(-1).toString('yyyyMMdd hh:mm')) query.addQueryItem('units', 'english') query.addQueryItem('time_zone', 'gmt') query.addQueryItem('product', self.productName) query.addQueryItem('format', 'xml') self.addQueryItems(query) return self.baseUrl + '?' + query.query()
def do_routing(self, graph_name, graph_version, start_x, start_y, end_x, end_y, date, cut_segments, routing_mode, criteria): if self.connection is None: return {"error": {"msg": "No connection selected"}} if not self.check_capability('routing'): return { "error": { "msg": "Server '" + self.connection.name + "' does not support routing!" } } url = self.connection.get_connection_url() + '/routing/graphs/' + graph_name + \ '/versions/' + graph_version + '/route.do' url_query_items = QUrlQuery() url_query_items.addQueryItem('time', date.strftime("%Y-%m-%dT%H:%M:%S")) url_query_items.addQueryItem( 'coords', str(start_x) + ',' + str(start_y) + ';' + str(end_x) + ',' + str(end_y)) url_query_items.addQueryItem('output', 'path') # url_query_items.addQueryItem('cutsegments', 'true' if cut_segments else 'false') url_query_items.addQueryItem('mode', routing_mode) url_query_items.addQueryItem('criteria', criteria) url_query_items.addQueryItem('algo', 'dijkstra') return self.process_get_call(url, url_query_items)
def result(self, result): # See if OK was pressed if result: project = QgsProject.instance() # First get all the values of the GUI items crs_input = self.dlg.crs_input.crs() crs_out = QgsCoordinateReferenceSystem( 'EPSG:4326') # we need this to be WGS84 for Nominatim lineedit_text = self.dlg.lineedit_xy.value() # Protect the free text field for coordinates from generic user failure try: lineedit_yx = [ float(coord.strip()) for coord in lineedit_text.split(',') ] except: QMessageBox.critical( self.iface.mainWindow(), 'QuickAPI error', "Did you really specify a coordinate in comma-separated Lat/Long?\nExiting..." ) return # Create a Point and transform if necessary point = QgsPointXY(*reversed(lineedit_yx)) if crs_input.authid() != 'EPSG:4326': xform = QgsCoordinateTransform(crs_input, crs_out, project) point_transform = xform.transform(point) point = point_transform # Set up the GET Request to Nominatim query = QUrlQuery() query.addQueryItem('lat', str(point.y())) query.addQueryItem('lon', str(point.x())) query.addQueryItem('format', 'json') url = QUrl('https://nominatim.openstreetmap.org/reverse') url.setQuery(query) request = QNetworkRequest(url) request.setHeader(QNetworkRequest.UserAgentHeader, '*****@*****.**') nam = QgsNetworkAccessManager() response: QgsNetworkReplyContent = nam.blockingGet(request) # Only process if HTTP status code is 200 status_code = response.attribute( QNetworkRequest.HttpStatusCodeAttribute) if status_code == 200: # Get the content of the response and process it response_json = json.loads(bytes(response.content())) if response_json.get('error'): QMessageBox.critical( self.iface.mainWindow(), "Quick API error", "The request was not processed succesfully!\n\n" "Message:\n" "{}".format(response_json['error'])) return x = float(response_json['lon']) y = float(response_json['lat']) address = response_json['display_name'] license = response_json['licence'] # Create the output memory layer layer_out = QgsVectorLayer( "Point?crs=EPSG:4326&field=address:string&field=license:string", "Nominatim Reverse Geocoding", "memory") # Create the output feature (only one here) point_out = QgsPointXY(x, y) feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPointXY(point_out)) feature.setAttributes([address, license]) # Add feature to layer and layer to map layer_out.dataProvider().addFeature(feature) layer_out.updateExtents() project.addMapLayer(layer_out) # build bbox for auto-zoom feature bbox = [float(coord) for coord in response_json['boundingbox']] min_y, max_y, min_x, max_x = bbox bbox_geom = QgsGeometry.fromRect( QgsRectangle(min_x, min_y, max_x, max_y)) # Transform bbox if map canvas has a different CRS if project.crs().authid() != 'EPSG:4326': xform = QgsCoordinateTransform(crs_out, project.crs(), project) bbox_geom.transform(xform) self.iface.mapCanvas().zoomToFeatureExtent( QgsRectangle.fromWkt(bbox_geom.asWkt()))
def import_layer_from_csv(parent, csv_path, layer_name, iface, longitude_field='lon', latitude_field='lat', delimiter=',', quote='"', lines_to_skip_count=0, wkt_field=None, save_format=None, save_dest=None, zoom_to_layer=True, has_geom=True, subset=None, add_to_legend=True, add_on_top=False): if not lines_to_skip_count: lines_to_skip_count = count_heading_commented_lines(csv_path) url = QUrl.fromLocalFile(csv_path) url_query = QUrlQuery() url_query.addQueryItem('type', 'csv') if has_geom: if wkt_field is not None: url_query.addQueryItem('wktField', wkt_field) else: url_query.addQueryItem('xField', longitude_field) url_query.addQueryItem('yField', latitude_field) url_query.addQueryItem('spatialIndex', 'no') url_query.addQueryItem('crs', 'epsg:4326') url_query.addQueryItem('subsetIndex', 'no') url_query.addQueryItem('watchFile', 'no') url_query.addQueryItem('delimiter', delimiter) url_query.addQueryItem('quote', quote) url_query.addQueryItem('skipLines', str(lines_to_skip_count)) url_query.addQueryItem('trimFields', 'yes') if subset is not None: # NOTE: it loads all features and applies a filter in visualization url_query.addQueryItem('subset', subset) # i.e. '"fieldname" != 0' url.setQuery(url_query) layer_uri = url.toString() layer = QgsVectorLayer(layer_uri, layer_name, "delimitedtext") if save_format: if save_format == 'ESRI Shapefile': fmt = '.shp' fmt_text = 'Shapefiles (*.shp)' elif save_format == 'GPKG': fmt = '.gpkg' fmt_text = 'Geopackages (*.gpkg)' else: raise NotImplementedError( 'Only shapefiles and geopackages are supported. Got %s' % save_format) dest_filename = save_dest if not dest_filename: dest_filename, file_filter = QFileDialog.getSaveFileName( parent, 'Save as...', os.path.expanduser("~"), fmt_text) if dest_filename: if os.path.splitext(dest_filename)[1] != fmt: dest_filename += fmt else: return writer_error, error_msg = save_layer_as( layer, dest_filename, save_format) if writer_error: raise RuntimeError( 'Could not save layer. %s: %s' % (writer_error, error_msg)) layer = QgsVectorLayer(dest_filename, layer_name, 'ogr') if layer.isValid(): if add_to_legend: if add_on_top: root = QgsProject.instance().layerTreeRoot() QgsProject.instance().addMapLayer(layer, False) root.insertLayer(0, layer) else: QgsProject.instance().addMapLayer(layer, True) iface.setActiveLayer(layer) if zoom_to_layer: iface.zoomToActiveLayer() else: raise RuntimeError('Unable to load layer') return layer