From a2a05a69fb2fa6aae9a96d49d543e72008d2888f Mon Sep 17 00:00:00 2001 From: Sebastiaan Huber Date: Fri, 12 May 2023 16:54:28 +0200 Subject: [PATCH] Dependencies: Update requirement `flask~=2.2` (#6011) In 508aeda0ad9c50b24d77f25234e63e67038eb8f2, an upper limit was placed on the `flask` dependency because `flask==2.2` removed the class `flask.json.JSONEncoder`. Here the upper limit is removed and the minimum requirement is updated. The `JSONEncoder` is replaced with `flask.json.provider.DefaultJSONProvider`. Co-authored-by: Marnik Bercx Co-authored-by: Kristjan Eimre --- aiida/restapi/common/utils.py | 32 +++++++++++++-------------- aiida/restapi/run_api.py | 4 ++-- docs/source/nitpick-exceptions | 2 +- pyproject.toml | 2 +- requirements/requirements-py-3.10.txt | 2 +- requirements/requirements-py-3.11.txt | 2 +- requirements/requirements-py-3.8.txt | 2 +- requirements/requirements-py-3.9.txt | 2 +- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/aiida/restapi/common/utils.py b/aiida/restapi/common/utils.py index f3a61a1892..b5966c1a46 100644 --- a/aiida/restapi/common/utils.py +++ b/aiida/restapi/common/utils.py @@ -12,7 +12,7 @@ import urllib.parse from flask import jsonify -from flask.json import JSONEncoder +from flask.json.provider import DefaultJSONProvider from wrapt import decorator from aiida.common.exceptions import InputValidationError, ValidationError @@ -27,43 +27,43 @@ ########################## Classes ##################### -class CustomJSONEncoder(JSONEncoder): +class CustomJSONProvider(DefaultJSONProvider): """ Custom json encoder for serialization. This has to be provided to the Flask app in order to replace the default encoder. """ - def default(self, o): - # pylint: disable=method-hidden + def default(self, obj, **kwargs): """ - Override default method from JSONEncoder to change serializer - :param o: Object e.g. dict, list that will be serialized - :return: serialized object + Override serialization of ``DefaultJSONProvider`` for ``datetime`` and ``bytes`` objects. + + :param obj: Object e.g. dict, list that will be serialized. + :return: Serialized object as a string. """ from aiida.restapi.common.config import SERIALIZER_CONFIG # Treat the datetime objects - if isinstance(o, datetime): + if isinstance(obj, datetime): if 'datetime_format' in SERIALIZER_CONFIG and SERIALIZER_CONFIG['datetime_format'] != 'default': if SERIALIZER_CONFIG['datetime_format'] == 'asinput': - if o.utcoffset() is not None: - o = o - o.utcoffset() - return '-'.join([str(o.year), str(o.month).zfill(2), - str(o.day).zfill(2)]) + 'T' + \ + if obj.utcoffset() is not None: + obj = obj - obj.utcoffset() + return '-'.join([str(obj.year), str(obj.month).zfill(2), + str(obj.day).zfill(2)]) + 'T' + \ ':'.join([str( - o.hour).zfill(2), str(o.minute).zfill(2), - str(o.second).zfill(2)]) + obj.hour).zfill(2), str(obj.minute).zfill(2), + str(obj.second).zfill(2)]) # To support bytes objects, try to decode to a string try: - return o.decode('utf-8') + return obj.decode('utf-8') except (UnicodeDecodeError, AttributeError): pass # If not returned yet, do it in the default way - return JSONEncoder.default(self, o) + return super().default(obj, **kwargs) class Utils: diff --git a/aiida/restapi/run_api.py b/aiida/restapi/run_api.py index bf884789ec..7544e2b49d 100755 --- a/aiida/restapi/run_api.py +++ b/aiida/restapi/run_api.py @@ -95,8 +95,8 @@ def configure_api(flask_app=api_classes.App, flask_api=api_classes.AiidaApi, **k # Configure the serializer if config_module.SERIALIZER_CONFIG: - from aiida.restapi.common.utils import CustomJSONEncoder - app.json_encoder = CustomJSONEncoder + from aiida.restapi.common.utils import CustomJSONProvider + app.json = CustomJSONProvider(app) # Set up WSGI profiler if requested if wsgi_profile: diff --git a/docs/source/nitpick-exceptions b/docs/source/nitpick-exceptions index 43690f342c..82081b1f1e 100644 --- a/docs/source/nitpick-exceptions +++ b/docs/source/nitpick-exceptions @@ -160,7 +160,7 @@ py:class html.parser.HTMLParser py:class disk_objectstore.container.Container py:class flask.app.Flask -py:class flask.json.JSONEncoder +py:class Flask py:class pytest.tmpdir.TempPathFactory diff --git a/pyproject.toml b/pyproject.toml index 119de1cd2b..c265d00df2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,7 +70,7 @@ ssh_kerberos = [ rest = [ "flask-cors~=3.0", "flask-restful~=0.3.7", - "flask~=2.0,<2.3", + "flask~=2.2", "pyparsing~=2.4", "python-memcached~=1.59", "seekpath~=1.9,>=1.9.3" diff --git a/requirements/requirements-py-3.10.txt b/requirements/requirements-py-3.10.txt index e3e6d10620..0c75e3dee5 100644 --- a/requirements/requirements-py-3.10.txt +++ b/requirements/requirements-py-3.10.txt @@ -33,7 +33,7 @@ disk-objectstore==0.6.0 docstring-parser==0.15.0 docutils==0.16 entrypoints==0.3 -Flask==2.0.3 +Flask==2.2.0 Flask-Cors==3.0.10 Flask-RESTful==0.3.9 fonttools==4.28.2 diff --git a/requirements/requirements-py-3.11.txt b/requirements/requirements-py-3.11.txt index aec787177c..52d59bde05 100644 --- a/requirements/requirements-py-3.11.txt +++ b/requirements/requirements-py-3.11.txt @@ -37,7 +37,7 @@ docstring-parser==0.15.0 docutils==0.16 emmet-core==0.39.0 fastjsonschema==2.16.2 -Flask==2.1.3 +Flask==2.2.0 Flask-Cors==3.0.10 Flask-RESTful==0.3.9 fonttools==4.38.0 diff --git a/requirements/requirements-py-3.8.txt b/requirements/requirements-py-3.8.txt index fc97e1e1af..9fbc5ef76f 100644 --- a/requirements/requirements-py-3.8.txt +++ b/requirements/requirements-py-3.8.txt @@ -33,7 +33,7 @@ disk-objectstore==0.6.0 docstring-parser==0.15.0 docutils==0.16 entrypoints==0.3 -Flask==2.0.3 +Flask==2.2.0 Flask-Cors==3.0.10 Flask-RESTful==0.3.9 fonttools==4.28.2 diff --git a/requirements/requirements-py-3.9.txt b/requirements/requirements-py-3.9.txt index 8d8d0cc48d..0ea829d74e 100644 --- a/requirements/requirements-py-3.9.txt +++ b/requirements/requirements-py-3.9.txt @@ -33,7 +33,7 @@ disk-objectstore==0.6.0 docstring-parser==0.15.0 docutils==0.16 entrypoints==0.3 -Flask==2.0.3 +Flask==2.2.0 Flask-Cors==3.0.10 Flask-RESTful==0.3.9 fonttools==4.28.2