From e747d0e54039b813cf1b11c4ca6e15489fe73c27 Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 16 Jul 2025 17:09:33 +0200 Subject: [PATCH 1/7] update dependancies fastjsonschema and imports on utils_functions.py Need to work on new methods ? --- requirements.in | 2 +- requirements.txt | 48 ++++++++---------------- src/opengeodeweb_back/utils_functions.py | 11 +++--- 3 files changed, 23 insertions(+), 38 deletions(-) diff --git a/requirements.in b/requirements.in index cba0f877..a9f7d46d 100644 --- a/requirements.in +++ b/requirements.in @@ -9,7 +9,7 @@ geode-simplex geode-explicit geode-implicit geode-common -jsonschema +fastjsonschema Flask[async] Flask-Cors werkzeug \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index f60c72a2..89828cd9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,30 +2,28 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile requirements.in +# pip-compile # -asgiref==3.8.1 +asgiref==3.9.1 # via flask -attrs==25.3.0 - # via - # jsonschema - # referencing blinker==1.9.0 # via flask click==8.2.1 # via flask +fastjsonschema==2.21.1 + # via -r requirements.in flask[async]==3.1.1 # via # -r requirements.in # flask-cors flask-cors==6.0.1 # via -r requirements.in -geode-background==9.2.9 +geode-background==9.3.3 # via # geode-explicit # geode-implicit # geode-simplex -geode-common==33.8.8 +geode-common==33.8.12 # via # -r requirements.in # geode-background @@ -35,22 +33,22 @@ geode-common==33.8.8 # geode-numerics # geode-simplex # geode-viewables -geode-conversion==6.3.3 +geode-conversion==6.3.5 # via # geode-explicit # geode-implicit -geode-explicit==6.2.3 +geode-explicit==6.2.6 # via # -r requirements.in # geode-implicit -geode-implicit==3.9.4 +geode-implicit==4.0.1 # via -r requirements.in -geode-numerics==6.2.2 +geode-numerics==6.2.3 # via # -r requirements.in # geode-implicit # geode-simplex -geode-simplex==9.4.2 +geode-simplex==9.5.3 # via # -r requirements.in # geode-implicit @@ -60,16 +58,12 @@ itsdangerous==2.2.0 # via flask jinja2==3.1.6 # via flask -jsonschema==4.24.0 - # via -r requirements.in -jsonschema-specifications==2025.4.1 - # via jsonschema markupsafe==3.0.2 # via # flask # jinja2 # werkzeug -opengeode-core==15.21.2 +opengeode-core==15.21.7 # via # -r requirements.in # geode-background @@ -84,38 +78,28 @@ opengeode-core==15.21.2 # opengeode-geosciencesio # opengeode-inspector # opengeode-io -opengeode-geosciences==9.0.0 +opengeode-geosciences==9.1.2 # via # -r requirements.in # geode-implicit # geode-viewables # opengeode-geosciencesio -opengeode-geosciencesio==5.4.2 +opengeode-geosciencesio==5.4.3 # via # -r requirements.in # geode-implicit -opengeode-inspector==6.6.1 +opengeode-inspector==6.6.4 # via # -r requirements.in # geode-explicit # geode-implicit # geode-simplex -opengeode-io==7.2.1 +opengeode-io==7.2.3 # via # -r requirements.in # geode-implicit # geode-viewables # opengeode-geosciencesio -referencing==0.36.2 - # via - # jsonschema - # jsonschema-specifications -rpds-py==0.25.1 - # via - # jsonschema - # referencing -typing-extensions==4.14.0 - # via referencing werkzeug==3.1.3 # via # -r requirements.in diff --git a/src/opengeodeweb_back/utils_functions.py b/src/opengeodeweb_back/utils_functions.py index 183d40de..3fba6e3f 100644 --- a/src/opengeodeweb_back/utils_functions.py +++ b/src/opengeodeweb_back/utils_functions.py @@ -6,8 +6,8 @@ # Third party imports import flask -from jsonschema import validate -from jsonschema.exceptions import ValidationError +import fastjsonschema +from fastjsonschema.exceptions import JsonSchemaDefinitionException import importlib.metadata as metadata # Local application imports @@ -82,9 +82,10 @@ def validate_request(request, schema): json_data = {} try: - validate(instance=json_data, schema=schema) - except ValidationError as e: - flask.abort(400, f"Validation error: {e.message}") + validate = fastjsonschema.compile(schema) + validate(json_data) + except fastjsonschema.JsonSchemaException as e: + flask.abort(400, f"Validation error: {str(e)}") def set_interval(func, sec, args=None): From b9801890699f96673ef79191eb00871fa08a6344 Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 16 Jul 2025 22:19:00 +0200 Subject: [PATCH 2/7] =?UTF-8?q?=C3=A0=20faire=20valider.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test cases in test_routes.py expect a validation error format thats need to be match fastjsonschema provides {key} is a required property for missing required fields Additionnal properties are not allowed for extra properties Modifications : - Catch fastjsonjsonschema exceptions and extract the field name - transform the error message to match the format expected by tests - uses string manipulations to handle both mising required fields and additionnal properties cases pytest : 40/40 passed --- src/opengeodeweb_back/utils_functions.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/opengeodeweb_back/utils_functions.py b/src/opengeodeweb_back/utils_functions.py index 3fba6e3f..73837387 100644 --- a/src/opengeodeweb_back/utils_functions.py +++ b/src/opengeodeweb_back/utils_functions.py @@ -85,7 +85,19 @@ def validate_request(request, schema): validate = fastjsonschema.compile(schema) validate(json_data) except fastjsonschema.JsonSchemaException as e: - flask.abort(400, f"Validation error: {str(e)}") + error_msg = str(e) + + # Transforme les messages d'erreur pour les rendre plus lisibles + if "data must contain" in error_msg: + # Estraire le nom du champ depuis jsonschema erreurs + field = error_msg.split("data must contain ['")[1].split("']")[0] + error_msg = f"'{field}' is a required property" + elif "data must not contain" in error_msg: + # Extrait le nom en plus du champ + field = error_msg.split("data must not contain {'")[1].split("'")[0] + error_msg = f"Additional properties are not allowed ('{field}' was unexpected)" + + flask.abort(400, f"Validation error: {error_msg}") def set_interval(func, sec, args=None): From 8ace7d266f1db70d7baf08909492416756efb583 Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 16 Jul 2025 22:20:23 +0200 Subject: [PATCH 3/7] =?UTF-8?q?from=20fastjsonschema.exceptions=20import?= =?UTF-8?q?=20JsonSchemaDefinitionException=20=20enlev=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/opengeodeweb_back/utils_functions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opengeodeweb_back/utils_functions.py b/src/opengeodeweb_back/utils_functions.py index 73837387..29d1b29b 100644 --- a/src/opengeodeweb_back/utils_functions.py +++ b/src/opengeodeweb_back/utils_functions.py @@ -7,7 +7,6 @@ # Third party imports import flask import fastjsonschema -from fastjsonschema.exceptions import JsonSchemaDefinitionException import importlib.metadata as metadata # Local application imports From 366fa6f4d90d9c214f585e39dbed7f43391a1e47 Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Thu, 17 Jul 2025 09:30:20 +0200 Subject: [PATCH 4/7] fix(schema validation): replace jssonschema with fastjsonschema --- requirements.txt | 46 +++++++++++++++--------- src/opengeodeweb_back/utils_functions.py | 3 -- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/requirements.txt b/requirements.txt index 89828cd9..4260add6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,28 +2,32 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile +# pip-compile requirements.in # -asgiref==3.9.1 +asgiref==3.8.1 # via flask +attrs==25.3.0 + # via + # jsonschema + # referencing blinker==1.9.0 # via flask click==8.2.1 # via flask fastjsonschema==2.21.1 - # via -r requirements.in +# via -r requirements.in flask[async]==3.1.1 # via # -r requirements.in # flask-cors flask-cors==6.0.1 # via -r requirements.in -geode-background==9.3.3 +geode-background==9.2.9 # via # geode-explicit # geode-implicit # geode-simplex -geode-common==33.8.12 +geode-common==33.8.8 # via # -r requirements.in # geode-background @@ -33,22 +37,22 @@ geode-common==33.8.12 # geode-numerics # geode-simplex # geode-viewables -geode-conversion==6.3.5 +geode-conversion==6.3.3 # via # geode-explicit # geode-implicit -geode-explicit==6.2.6 +geode-explicit==6.2.3 # via # -r requirements.in # geode-implicit -geode-implicit==4.0.1 +geode-implicit==3.9.4 # via -r requirements.in -geode-numerics==6.2.3 +geode-numerics==6.2.2 # via # -r requirements.in # geode-implicit # geode-simplex -geode-simplex==9.5.3 +geode-simplex==9.4.2 # via # -r requirements.in # geode-implicit @@ -63,7 +67,7 @@ markupsafe==3.0.2 # flask # jinja2 # werkzeug -opengeode-core==15.21.7 +opengeode-core==15.21.2 # via # -r requirements.in # geode-background @@ -78,30 +82,40 @@ opengeode-core==15.21.7 # opengeode-geosciencesio # opengeode-inspector # opengeode-io -opengeode-geosciences==9.1.2 +opengeode-geosciences==9.0.0 # via # -r requirements.in # geode-implicit # geode-viewables # opengeode-geosciencesio -opengeode-geosciencesio==5.4.3 +opengeode-geosciencesio==5.4.2 # via # -r requirements.in # geode-implicit -opengeode-inspector==6.6.4 +opengeode-inspector==6.6.1 # via # -r requirements.in # geode-explicit # geode-implicit # geode-simplex -opengeode-io==7.2.3 +opengeode-io==7.2.1 # via # -r requirements.in # geode-implicit # geode-viewables # opengeode-geosciencesio +referencing==0.36.2 + # via + # jsonschema + # jsonschema-specifications +rpds-py==0.25.1 + # via + # jsonschema + # referencing +typing-extensions==4.14.0 + # via referencing werkzeug==3.1.3 # via # -r requirements.in # flask - # flask-cors + # flask-cors \ No newline at end of file diff --git a/src/opengeodeweb_back/utils_functions.py b/src/opengeodeweb_back/utils_functions.py index 29d1b29b..46a58056 100644 --- a/src/opengeodeweb_back/utils_functions.py +++ b/src/opengeodeweb_back/utils_functions.py @@ -86,13 +86,10 @@ def validate_request(request, schema): except fastjsonschema.JsonSchemaException as e: error_msg = str(e) - # Transforme les messages d'erreur pour les rendre plus lisibles if "data must contain" in error_msg: - # Estraire le nom du champ depuis jsonschema erreurs field = error_msg.split("data must contain ['")[1].split("']")[0] error_msg = f"'{field}' is a required property" elif "data must not contain" in error_msg: - # Extrait le nom en plus du champ field = error_msg.split("data must not contain {'")[1].split("'")[0] error_msg = f"Additional properties are not allowed ('{field}' was unexpected)" From 582687f582e9b01ef2546412f6f98230be8bc09a Mon Sep 17 00:00:00 2001 From: MaxNumerique <144453705+MaxNumerique@users.noreply.github.com> Date: Thu, 17 Jul 2025 07:30:59 +0000 Subject: [PATCH 5/7] Apply prepare changes --- src/opengeodeweb_back/utils_functions.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/opengeodeweb_back/utils_functions.py b/src/opengeodeweb_back/utils_functions.py index 46a58056..ec7a6970 100644 --- a/src/opengeodeweb_back/utils_functions.py +++ b/src/opengeodeweb_back/utils_functions.py @@ -85,14 +85,16 @@ def validate_request(request, schema): validate(json_data) except fastjsonschema.JsonSchemaException as e: error_msg = str(e) - + if "data must contain" in error_msg: field = error_msg.split("data must contain ['")[1].split("']")[0] error_msg = f"'{field}' is a required property" elif "data must not contain" in error_msg: field = error_msg.split("data must not contain {'")[1].split("'")[0] - error_msg = f"Additional properties are not allowed ('{field}' was unexpected)" - + error_msg = ( + f"Additional properties are not allowed ('{field}' was unexpected)" + ) + flask.abort(400, f"Validation error: {error_msg}") From 9ad7016c6c4485bdc160cff0cf01bd5f33bcfff8 Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Fri, 18 Jul 2025 11:16:44 +0200 Subject: [PATCH 6/7] fix(schema validation): match fastjsonschema test_utils error msg --- src/opengeodeweb_back/test_utils.py | 9 ++++----- src/opengeodeweb_back/utils_functions.py | 10 +--------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/opengeodeweb_back/test_utils.py b/src/opengeodeweb_back/test_utils.py index 0d4c6176..0888a4ad 100644 --- a/src/opengeodeweb_back/test_utils.py +++ b/src/opengeodeweb_back/test_utils.py @@ -12,14 +12,13 @@ def test_route_wrong_params(client, route, get_full_data): response = client.post(route, json=json) assert response.status_code == 400 error_description = response.json["description"] - assert error_description == f"Validation error: '{key}' is a required property" + assert "data must contain" in error_description + assert f"'{key}'" in error_description json = get_full_data() json["dumb_key"] = "dumb_value" response = client.post(route, json=json) assert response.status_code == 400 error_description = response.json["description"] - assert ( - error_description - == "Validation error: Additional properties are not allowed ('dumb_key' was unexpected)" - ) + assert "data must not contain" in error_description + assert "'dumb_key'" in error_description diff --git a/src/opengeodeweb_back/utils_functions.py b/src/opengeodeweb_back/utils_functions.py index 46a58056..1b12cebd 100644 --- a/src/opengeodeweb_back/utils_functions.py +++ b/src/opengeodeweb_back/utils_functions.py @@ -85,15 +85,7 @@ def validate_request(request, schema): validate(json_data) except fastjsonschema.JsonSchemaException as e: error_msg = str(e) - - if "data must contain" in error_msg: - field = error_msg.split("data must contain ['")[1].split("']")[0] - error_msg = f"'{field}' is a required property" - elif "data must not contain" in error_msg: - field = error_msg.split("data must not contain {'")[1].split("'")[0] - error_msg = f"Additional properties are not allowed ('{field}' was unexpected)" - - flask.abort(400, f"Validation error: {error_msg}") + flask.abort(400, error_msg) def set_interval(func, sec, args=None): From 4b95370535f0612e3d22b8aae1e341bdd66fcaab Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Fri, 18 Jul 2025 11:23:59 +0200 Subject: [PATCH 7/7] fix(fastjsonschema): add error msg logic into the test_utils.py dans refact --- src/opengeodeweb_back/utils_functions.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/opengeodeweb_back/utils_functions.py b/src/opengeodeweb_back/utils_functions.py index 46a58056..1b12cebd 100644 --- a/src/opengeodeweb_back/utils_functions.py +++ b/src/opengeodeweb_back/utils_functions.py @@ -85,15 +85,7 @@ def validate_request(request, schema): validate(json_data) except fastjsonschema.JsonSchemaException as e: error_msg = str(e) - - if "data must contain" in error_msg: - field = error_msg.split("data must contain ['")[1].split("']")[0] - error_msg = f"'{field}' is a required property" - elif "data must not contain" in error_msg: - field = error_msg.split("data must not contain {'")[1].split("'")[0] - error_msg = f"Additional properties are not allowed ('{field}' was unexpected)" - - flask.abort(400, f"Validation error: {error_msg}") + flask.abort(400, error_msg) def set_interval(func, sec, args=None):