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 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 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 process_get_call(self, url, url_query_items, timeout=None, report_url=True): """ Run a GET request and return reply data :param url: url for request :param url_query_items: :param timeout: in ms :param report_url: True if URL should be reported to feedback :return: response or error message in json format """ url_query = QUrl(url) if report_url: self.report_info('GET ' + url_query.toString()) if url_query_items: url_query.setQuery(url_query_items) request = QNetworkRequest(url_query) if self.connection.auth_cfg != '': request.setRawHeader("Accept".encode("utf-8"), "*/*".encode("utf-8")) if timeout is not None and "setTransferTimeout" in dir(request): request.setTransferTimeout(timeout) reply = self.network_access_manager.blockingGet( request, self.connection.auth_cfg, True, self.feedback) return self.process_qgs_reply(reply)
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="{}"'.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) query_string.addQueryItem('info', 'QgisQuickOSMPlugin') url_query.setQuery(query_string) return url_query.toString()
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 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 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 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 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 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()
def process_post_call(self, url, url_query_items, data, is_read_only=True, report_url=True): """ Run a POST request and return reply data :param url: url for request :param url_query_items: :param data: :param is_read_only: True if the request does not update data :param report_url: True if URL should be reported to feedback :return: response or error message in json format """ if self.connection.read_only and not is_read_only: return { "error": { "msg": "Graphium connection is set to read-only!" } } url_query = QUrl(url) if report_url: self.report_info('POST ' + url_query.toString()) if url_query_items: url_query.setQuery(url_query_items) # data_byte_array = json.dumps(data).encode('utf8') # data = QtCore.QByteArray( json.dumps( json_request ) ) data_byte_array = QJsonDocument.fromVariant(data) request = QNetworkRequest(url_query) if self.connection.auth_cfg != '': request.setRawHeader("Accept".encode("utf-8"), "*/*".encode("utf-8")) request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") reply = self.network_access_manager.blockingPost( request, data_byte_array.toJson(), self.connection.auth_cfg, True, self.feedback) return self.process_qgs_reply(reply)
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 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 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 prepare_url(self): """Prepare a query to be as an URL. :return: The URL encoded with the query. :rtype: basestring """ if not self._query_prepared: return '' 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 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()))