diff --git a/.gitignore b/.gitignore index 1a771f5b..01b64dd9 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ __pycache__ .vscode uploads node_modules -schemas.json \ No newline at end of file +schemas.json +.mypy_cache \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 3e99ede3..006e581e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,5 +3,11 @@ "." ], "python.testing.unittestEnabled": false, - "python.testing.pytestEnabled": true + "python.testing.pytestEnabled": true, + "mypy-type-checker.args": [ + "--config-file=mypy.ini" + ], + "mypy-type-checker.interpreter": [ + "${workspaceFolder}/venv/bin/python" + ] } \ No newline at end of file diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 00000000..3a29484e --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,16 @@ +export default { + extends: ["@commitlint/config-angular"], + rules: { + "scope-empty": [2, "never"], + "subject-empty": [2, "never"], + "subject-max-length": [0], + "body-leading-blank": [0], + "footer-leading-blank": [0], + "header-max-length": [0], + "scope-case": [0], + "subject-case": [0], + "subject-full-stop": [0], + "type-case": [0], + "type-empty": [0], + }, +} diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 00000000..82403124 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,3 @@ +[mypy] +strict = True +files = src/ \ No newline at end of file diff --git a/src/opengeodeweb_back/geode_functions.py b/src/opengeodeweb_back/geode_functions.py index 763a4a7e..2019a162 100644 --- a/src/opengeodeweb_back/geode_functions.py +++ b/src/opengeodeweb_back/geode_functions.py @@ -2,8 +2,8 @@ import os # Third party imports -import opengeode_geosciences as og_gs -import opengeode as og +import opengeode_geosciences as og_gs # type: ignore +import opengeode as og # type: ignore import werkzeug import flask diff --git a/src/opengeodeweb_back/geode_objects.py b/src/opengeodeweb_back/geode_objects.py index 7386f24e..d1f25614 100644 --- a/src/opengeodeweb_back/geode_objects.py +++ b/src/opengeodeweb_back/geode_objects.py @@ -1,12 +1,12 @@ # Standard library imports # Third party imports -import opengeode as og -import opengeode_io as og_io -import opengeode_inspector as og_inspector -import opengeode_geosciences as og_gs -import opengeode_geosciencesio as og_gs_io -import geode_viewables as g_v +import opengeode as og # type: ignore +import opengeode_io as og_io # type: ignore +import opengeode_inspector as og_inspector # type: ignore +import opengeode_geosciences as og_gs # type: ignore +import opengeode_geosciencesio as og_gs_io # type: ignore +import geode_viewables as g_v # type: ignore # Local application imports diff --git a/src/opengeodeweb_back/utils_functions.py b/src/opengeodeweb_back/utils_functions.py index fc1aa143..3efd0af9 100644 --- a/src/opengeodeweb_back/utils_functions.py +++ b/src/opengeodeweb_back/utils_functions.py @@ -4,52 +4,55 @@ import time import uuid import zipfile +from collections.abc import Callable +from typing import Any # Third party imports import flask -import fastjsonschema +import fastjsonschema # type: ignore import importlib.metadata as metadata import shutil +from werkzeug.exceptions import HTTPException import werkzeug # Local application imports from . import geode_functions -def increment_request_counter(current_app): +def increment_request_counter(current_app: flask.Flask) -> None: if "REQUEST_COUNTER" in current_app.config: - REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER")) + REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER", 0)) REQUEST_COUNTER += 1 current_app.config.update(REQUEST_COUNTER=REQUEST_COUNTER) -def decrement_request_counter(current_app): +def decrement_request_counter(current_app: flask.Flask) -> None: if "REQUEST_COUNTER" in current_app.config: - REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER")) + REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER", 0)) REQUEST_COUNTER -= 1 current_app.config.update(REQUEST_COUNTER=REQUEST_COUNTER) -def update_last_request_time(current_app): +def update_last_request_time(current_app: flask.Flask) -> None: if "LAST_REQUEST_TIME" in current_app.config: LAST_REQUEST_TIME = time.time() current_app.config.update(LAST_REQUEST_TIME=LAST_REQUEST_TIME) -def before_request(current_app): +def before_request(current_app: flask.Flask) -> None: increment_request_counter(current_app) -def teardown_request(current_app): +def teardown_request(current_app: flask.Flask) -> None: decrement_request_counter(current_app) update_last_request_time(current_app) -def kill_task(current_app): - REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER")) - LAST_PING_TIME = float(current_app.config.get("LAST_PING_TIME")) - LAST_REQUEST_TIME = float(current_app.config.get("LAST_REQUEST_TIME")) - MINUTES_BEFORE_TIMEOUT = float(current_app.config.get("MINUTES_BEFORE_TIMEOUT")) +def kill_task(current_app: flask.Flask) -> None: + REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER", 0)) + LAST_PING_TIME = float(current_app.config.get("LAST_PING_TIME", 0)) + LAST_REQUEST_TIME = float(current_app.config.get("LAST_REQUEST_TIME", 0)) + MINUTES_BEFORE_TIMEOUT = float(current_app.config.get("MINUTES_BEFORE_TIMEOUT", 0)) current_time = time.time() minutes_since_last_request = (current_time - LAST_REQUEST_TIME) / 60 minutes_since_last_ping = (current_time - LAST_PING_TIME) / 60 @@ -64,12 +67,12 @@ def kill_task(current_app): kill_server() -def kill_server(): +def kill_server() -> None: print("Server timed out due to inactivity, shutting down...", flush=True) os._exit(0) -def versions(list_packages: list): +def versions(list_packages: list[str]) -> list[dict[str, str]]: list_with_versions = [] for package in list_packages: list_with_versions.append( @@ -78,7 +81,7 @@ def versions(list_packages: list): return list_with_versions -def validate_request(request, schema): +def validate_request(request: flask.Request, schema: dict[str, str]) -> None: json_data = request.get_json(force=True, silent=True) if json_data is None: @@ -92,22 +95,26 @@ def validate_request(request, schema): flask.abort(400, error_msg) -def set_interval(func, sec, args=None): - def func_wrapper(): - set_interval(func, sec, args) - func(args) +def set_interval( + function: Callable[[Any], None], seconds: float, args: Any +) -> threading.Timer: + def function_wrapper() -> None: + set_interval(function, seconds, args) + function(args) - t = threading.Timer(sec, func_wrapper) - t.daemon = True - t.start() - return t + timer = threading.Timer(seconds, function_wrapper) + timer.daemon = True + timer.start() + return timer -def extension_from_filename(filename): +def extension_from_filename(filename: str) -> str: return os.path.splitext(filename)[1][1:] -def send_file(upload_folder, saved_files, new_file_name): +def send_file( + upload_folder: str, saved_files: str, new_file_name: str +) -> flask.Response: if len(saved_files) == 1: mimetype = "application/octet-binary" else: @@ -132,13 +139,13 @@ def send_file(upload_folder, saved_files, new_file_name): return response -def handle_exception(e): - response = e.get_response() +def handle_exception(exception: HTTPException) -> flask.Response: + response = exception.get_response() response.data = flask.json.dumps( { - "code": e.code, - "name": e.name, - "description": e.description, + "code": exception.code, + "name": exception.name, + "description": exception.description, } ) response.content_type = "application/json"