diff --git a/CHANGELOG.md b/CHANGELOG.md index 4575e168..d606bfad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ RELEASING: - pre-commit configuration with Ruff linter for code quality enforcement - Improve cursor behaviour during digitization - Improve isochrone color ramp with many ranges +- Enabled usage of custom endpoints in main application ### Fixed - Delete annotations when plugin is uninstalled ([#346](https://github.com/GIScience/orstools-qgis-plugin/issues/346)) diff --git a/ORStools/common/client.py b/ORStools/common/client.py index 81857392..da1e8e54 100644 --- a/ORStools/common/client.py +++ b/ORStools/common/client.py @@ -33,6 +33,7 @@ from typing import Union, Dict, List, Optional from urllib.parse import urlencode + from qgis.PyQt.QtCore import QObject, pyqtSignal, QUrl, QTimer, QEventLoop from qgis.PyQt.QtNetwork import QNetworkRequest, QNetworkReply from qgis.core import QgsSettings, QgsBlockingNetworkRequest diff --git a/ORStools/gui/ORStoolsDialog.py b/ORStools/gui/ORStoolsDialog.py index 0b3f761e..26816fd5 100644 --- a/ORStools/gui/ORStoolsDialog.py +++ b/ORStools/gui/ORStoolsDialog.py @@ -27,8 +27,8 @@ ***************************************************************************/ """ -import json import os +import json from datetime import datetime from typing import Optional @@ -58,7 +58,11 @@ QgsAnnotation, QgsCoordinateTransform, ) -from qgis.gui import QgsMapCanvasAnnotationItem, QgsCollapsibleGroupBox, QgisInterface +from qgis.gui import ( + QgsMapCanvasAnnotationItem, + QgsCollapsibleGroupBox, + QgisInterface, +) from qgis.PyQt.QtCore import QSizeF, QPointF, QCoreApplication from qgis.PyQt.QtGui import QTextDocument from qgis.PyQt.QtWidgets import QAction, QDialog, QApplication, QMenu, QMessageBox, QDialogButtonBox @@ -291,11 +295,23 @@ def run_gui_control(self) -> None: except exceptions.ApiError as e: # Error thrown by ORStools/common/client.py, line 243, in _check_status - parsed = json.loads(e.message) - error_code = int(parsed["error"]["code"]) + try: + parsed = json.loads(e.message) + error_code = int(parsed["error"]["code"]) + except KeyError: + error_code = e.status + if error_code == 2010: maptools.LineTool(self.dlg).radius_message_box(e) return + elif error_code == "404": + self.iface.messageBar().pushMessage( + "Error 404: Not Found", + "Are your endpoints set correctly in the Provider Settings?", + level=Qgis.MessageLevel.Warning, + ) + else: + raise e def tr(self, string: str) -> str: return QCoreApplication.translate(str(self.__class__.__name__), string) diff --git a/ORStools/utils/maptools.py b/ORStools/utils/maptools.py index 9af4459b..831fbf12 100644 --- a/ORStools/utils/maptools.py +++ b/ORStools/utils/maptools.py @@ -314,7 +314,8 @@ def get_error_code(self, e: QEvent) -> int: json_end_index = e.message.rfind("}") + 1 json_str = e.message[json_start_index:json_end_index] error_dict = json.loads(json_str) - return error_dict["error"]["code"] + + return error_dict["error"]["code"] if error_dict["error"]["code"] else e.status def radius_message_box(self, e) -> None: parsed = json.loads(e.message) @@ -341,8 +342,15 @@ def _toggle_preview(self) -> None: self.create_rubber_band() except ApiError as e: self.dlg.toggle_preview.setChecked(state) - if self.get_error_code(e) == 2010: + error_code = self.get_error_code(e) + if error_code == 2010: self.radius_message_box(e) + elif error_code == "404": + self.dlg._iface.messageBar().pushMessage( + "Error 404: Not Found", + "Are your endpoints set correctly in the Provider Settings?", + level=Qgis.MessageLevel.Warning, + ) else: raise e except Exception as e: diff --git a/ORStools/utils/router.py b/ORStools/utils/router.py index 67e76d42..40759803 100644 --- a/ORStools/utils/router.py +++ b/ORStools/utils/router.py @@ -85,8 +85,11 @@ def route_as_layer(dlg): logger.log(msg, 0) dlg.debug_text.setText(msg) return + + endpoint = provider["endpoints"]["directions"] + response = clnt.fetch_with_retry( - "/v2/directions/" + profile + "/geojson", {}, post_json=params + f"/v2/{endpoint}/" + profile + "/geojson", {}, post_json=params ) feat = directions_core.get_output_feature_directions( response, profile, params["preference"], directions.options diff --git a/tests/conftest.py b/tests/conftest.py index 69faa44d..4c8ead41 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,6 +5,7 @@ from ORStools.ORStoolsPlugin import ORStools from tests.utils.utilities import get_qgis_app + def pytest_sessionstart(session): """ Called after the Session object has been created and diff --git a/tests/test_gui.py b/tests/test_gui.py index fc5b47e7..374122fc 100644 --- a/tests/test_gui.py +++ b/tests/test_gui.py @@ -358,3 +358,45 @@ def test_ORStoolsDialogConfig_url(self): "POINT(8.67251100000000008 49.39887900000000087)", next(layer.getFeatures()).geometry().asPolyline()[0].asWkt(), ) + + def test_custom_endpoints(self): + from ORStools.gui.ORStoolsDialogConfig import ORStoolsDialogConfigMain + + # Set and reset config to test whether the reset works + dlg_config = ORStoolsDialogConfigMain() + provider = dlg_config.providers.findChildren(QgsCollapsibleGroupBox)[0] + + # set endpoint of directions to non-existent value + line_edit = provider.findChild(QLineEdit, "openrouteservice_directions_endpoint") + line_edit.setText("custom_directions_endpoint") + dlg_config.accept() + + settings_directions_endpoint = QgsSettings().value("ORStools/config")["providers"][0][ + "endpoints" + ]["directions"] + + proc = TestProc() + proc.setUpClass() + + self.assertEqual(settings_directions_endpoint, "custom_directions_endpoint") + + layer = proc.get_directions_points_layer() + self.assertEqual(layer.featureCount(), 0) + + # reset endpoints + dlg_config._reset_endpoints() + dlg_config.accept() + + settings_directions_endpoint = QgsSettings().value("ORStools/config")["providers"][0][ + "endpoints" + ]["directions"] + + self.assertEqual(settings_directions_endpoint, "directions") + + layer = proc.get_directions_points_layer() + self.assertEqual(layer.featureCount(), 93) + + self.assertEqual( + "POINT(8.67251100000000008 49.39887900000000087)", + next(layer.getFeatures()).geometry().asPolyline()[0].asWkt(), + )