Skip to content

Commit

Permalink
Merge branch 'main' into Add-support-for-extra-info-parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
koebi committed May 15, 2024
2 parents 9e7dbde + 85ebed2 commit 1137c80
Show file tree
Hide file tree
Showing 27 changed files with 5,165 additions and 4,890 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ RELEASING:
14. Create new release in GitHub with tag version and release title of `vX.X.X`
-->

## Unreleased

### Fixed
- QGis crashes when selecting more than two vertices for deletion ([#230](https://github.com/GIScience/orstools-qgis-plugin/issues/230))
- Vertices on canvas not depicted fully with n having more than one digit in length ([#235](https://github.com/GIScience/orstools-qgis-plugin/issues/235))
- Replace qt QSettings with QgsSettings for centralized configuration management ([#239](https://github.com/GIScience/orstools-qgis-plugin/issues/239))
- Fix: Point Annotations stay after saving project and not deleting them manually([#229](https://github.com/GIScience/orstools-qgis-plugin/issues/229))
- Improved type hints

### Added
- Add support for decimal ranges with isochrones([#237](https://github.com/GIScience/orstools-qgis-plugin/issues/237))
- Add hint for joining with `Layer ID Field` ([#143](https://github.com/GIScience/orstools-qgis-plugin/issues/143))
- Add option to export order of optimization route points ([#145](https://github.com/GIScience/orstools-qgis-plugin/issues/145))

### Changed
- Rename `Ok` button in configuration window to `Save` for clarification([#241](https://github.com/GIScience/orstools-qgis-plugin/issues/241))

## [1.7.1] - 2024-01-15

Expand Down
13 changes: 7 additions & 6 deletions ORStools/ORStoolsPlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
***************************************************************************/
"""

from qgis.core import QgsApplication
from PyQt5.QtCore import QTranslator, QSettings, qVersion, QCoreApplication
from qgis.gui import QgisInterface
from qgis.core import QgsApplication, QgsSettings
from PyQt5.QtCore import QTranslator, qVersion, QCoreApplication
import os.path

from .gui import ORStoolsDialog
Expand All @@ -40,7 +41,7 @@ class ORStools:

# noinspection PyTypeChecker,PyArgumentList,PyCallByClass

def __init__(self, iface):
def __init__(self, iface: QgisInterface) -> None:
"""Constructor.
:param iface: An interface instance that will be passed to this class
Expand All @@ -55,7 +56,7 @@ def __init__(self, iface):
self.plugin_dir = os.path.dirname(__file__)

# initialize locale
locale = QSettings().value("locale/userLocale")[0:2]
locale = QgsSettings().value("locale/userLocale")[0:2]
locale_path = os.path.join(self.plugin_dir, "i18n", "orstools_{}.qm".format(locale))

if os.path.exists(locale_path):
Expand All @@ -65,13 +66,13 @@ def __init__(self, iface):
if qVersion() > "4.3.3":
QCoreApplication.installTranslator(self.translator)

def initGui(self):
def initGui(self) -> None:
"""Create the menu entries and toolbar icons inside the QGIS GUI."""

QgsApplication.processingRegistry().addProvider(self.provider)
self.dialog.initGui()

def unload(self):
def unload(self) -> None:
"""remove menu entry and toolbar icons"""
QgsApplication.processingRegistry().removeProvider(self.provider)
self.dialog.unload()
16 changes: 12 additions & 4 deletions ORStools/common/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import random
import time
from datetime import datetime, timedelta
from typing import Union, Dict, List, Optional
from urllib.parse import urlencode

from PyQt5.QtCore import QObject, pyqtSignal
Expand All @@ -48,7 +49,7 @@
class Client(QObject):
"""Performs requests to the ORS API services."""

def __init__(self, provider=None, agent=None):
def __init__(self, provider: Optional[dict] = None, agent: Optional[str] = None) -> None:
"""
:param provider: A openrouteservice provider from config.yml
:type provider: dict
Expand Down Expand Up @@ -87,7 +88,14 @@ def __init__(self, provider=None, agent=None):

overQueryLimit = pyqtSignal()

def request(self, url, params, first_request_time=None, retry_counter=0, post_json=None):
def request(
self,
url: str,
params: dict,
first_request_time: Optional[datetime.time] = None,
retry_counter: int = 0,
post_json: Optional[dict] = None,
):
"""Performs HTTP GET/POST with credentials, returning the body as
JSON.
Expand Down Expand Up @@ -194,7 +202,7 @@ def request(self, url, params, first_request_time=None, retry_counter=0, post_js

return json.loads(content.decode("utf-8"))

def _check_status(self):
def _check_status(self) -> None:
"""
Casts JSON response to dict
Expand Down Expand Up @@ -231,7 +239,7 @@ def _check_status(self):
elif status_code != 200:
raise exceptions.GenericServerError(str(status_code), message)

def _generate_auth_url(self, path, params):
def _generate_auth_url(self, path: str, params: Union[Dict, List]) -> str:
"""Returns the path and query string portion of the request URL, first
adding any necessary parameters.
Expand Down
29 changes: 18 additions & 11 deletions ORStools/common/directions_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@

from itertools import product
from qgis.core import QgsPoint, QgsPointXY, QgsGeometry, QgsFeature, QgsFields, QgsField
from typing import List, Optional
from typing import List, Generator, Tuple, Any, Optional

from PyQt5.QtCore import QVariant

from ORStools.utils import convert, logger


def get_request_point_features(route_dict, row_by_row):
def get_request_point_features(route_dict: dict, row_by_row: str) -> Generator[List, Tuple, None]:
"""
Processes input point features depending on the layer to layer relation in directions settings
Expand Down Expand Up @@ -75,13 +75,13 @@ def get_request_point_features(route_dict, row_by_row):


def get_fields(
from_type=QVariant.String,
to_type=QVariant.String,
from_name="FROM_ID",
to_name="TO_ID",
line=False,
from_type: QVariant.Type = QVariant.String,
to_type: QVariant.Type = QVariant.String,
from_name: str = "FROM_ID",
to_name: str = "TO_ID",
line: bool = False,
extra_info: list = [],
):
) -> QgsFields:
"""
Builds output fields for directions response layer.
Expand Down Expand Up @@ -121,8 +121,13 @@ def get_fields(


def get_output_feature_directions(
response, profile, preference, options=None, from_value=None, to_value=None
):
response: dict,
profile: str,
preference: str,
options: Optional[str] = None,
from_value: Any = None,
to_value: Any = None,
) -> QgsFeature:
"""
Build output feature based on response attributes for directions endpoint.
Expand Down Expand Up @@ -169,7 +174,9 @@ def get_output_feature_directions(
return feat


def get_output_features_optimization(response, profile, from_value=None):
def get_output_features_optimization(
response: dict, profile: str, from_value: Any = None
) -> QgsFeature:
"""
Build output feature based on response attributes for optimization endpoint.
Expand Down
22 changes: 16 additions & 6 deletions ORStools/common/isochrones_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
***************************************************************************/
"""

from typing import Any, Generator

from qgis._core import QgsMapLayer
from qgis.core import (
QgsPointXY,
QgsFeature,
Expand All @@ -49,7 +52,7 @@
class Isochrones:
"""convenience class to build isochrones"""

def __init__(self):
def __init__(self) -> None:
# Will all be set in self.set_parameters(), bcs Processing Algo has to initialize this class before it
# knows about its own parameters
self.profile = None
Expand All @@ -60,8 +63,13 @@ def __init__(self):
self.field_dimension_name = None

def set_parameters(
self, profile, dimension, factor, id_field_type=QVariant.String, id_field_name="ID"
):
self,
profile: str,
dimension: str,
factor: int,
id_field_type: QVariant.String = QVariant.String,
id_field_name: str = "ID",
) -> None:
"""
Sets all parameters defined in __init__, because processing algorithm calls this class when it doesn't know
its parameters yet.
Expand Down Expand Up @@ -89,7 +97,7 @@ def set_parameters(

self.field_dimension_name = "AA_MINS" if self.dimension == "time" else "AA_METERS"

def get_fields(self):
def get_fields(self) -> QgsFields:
"""
Set all fields for output isochrone layer.
Expand All @@ -106,7 +114,9 @@ def get_fields(self):

return fields

def get_features(self, response, id_field_value):
def get_features(
self, response: dict, id_field_value: Any
) -> Generator[QgsFeature, None, None]:
"""
Generator to return output isochrone features from response.
Expand Down Expand Up @@ -158,7 +168,7 @@ def get_features(self, response, id_field_value):
#
# return dissolved

def stylePoly(self, layer):
def stylePoly(self, layer: QgsMapLayer) -> None:
"""
Style isochrone polygon layer.
Expand Down
22 changes: 12 additions & 10 deletions ORStools/common/networkaccessmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def __init__(
exception_class=None,
debug=True,
timeout=60,
):
) -> None:
self.disable_ssl_certificate_validation = disable_ssl_certificate_validation
self.authid = authid
self.reply = None
Expand All @@ -175,17 +175,19 @@ def __init__(
)
self.timeout = timeout

def msg_log(self, msg):
def msg_log(self, msg: str) -> None:
if self.debug:
QgsMessageLog.logMessage(msg, "NetworkAccessManager")

def httpResult(self):
def httpResult(self) -> None:
return self.http_call_result

def auth_manager(self):
def auth_manager(self) -> None:
return QgsApplication.authManager()

def request(self, url, method="GET", body=None, headers=None, blocking=True):
def request(
self, url: str, method: str = "GET", body=None, headers=None, blocking: bool = True
):
"""
Make a network request by calling QgsNetworkAccessManager.
redirections argument is ignored and is here only for httplib2 compatibility.
Expand Down Expand Up @@ -279,19 +281,19 @@ def request(self, url, method="GET", body=None, headers=None, blocking=True):

return self.http_call_result, self.http_call_result.content

def downloadProgress(self, bytesReceived, bytesTotal):
def downloadProgress(self, bytesReceived, bytesTotal) -> None:
"""Keep track of the download progress"""
# self.msg_log("downloadProgress %s of %s ..." % (bytesReceived, bytesTotal))
pass

# noinspection PyUnusedLocal
def requestTimedOut(self, reply):
def requestTimedOut(self, reply) -> None:
"""Trap the timeout. In Async mode requestTimedOut is called after replyFinished"""
# adapt http_call_result basing on receiving qgs timer timout signal
self.exception_class = RequestsExceptionTimeout
self.http_call_result.exception = RequestsExceptionTimeout("Timeout error")

def replyFinished(self):
def replyFinished(self) -> None:
err = self.reply.error()
httpStatus = self.reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
httpStatusMessage = self.reply.attribute(QNetworkRequest.HttpReasonPhraseAttribute)
Expand Down Expand Up @@ -401,7 +403,7 @@ def replyFinished(self):
else:
self.msg_log("Reply was already deleted ...")

def sslErrors(self, ssl_errors):
def sslErrors(self, ssl_errors) -> None:
"""
Handle SSL errors, logging them if debug is on and ignoring them
if disable_ssl_certificate_validation is set.
Expand All @@ -412,7 +414,7 @@ def sslErrors(self, ssl_errors):
if self.disable_ssl_certificate_validation:
self.reply.ignoreSslErrors()

def abort(self):
def abort(self) -> None:
"""
Handle request to cancel HTTP call
"""
Expand Down
Loading

0 comments on commit 1137c80

Please sign in to comment.