diff --git a/CHANGELOG.md b/CHANGELOG.md index 18de461ca..d17c7b004 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [8.0.1] + +### Fixed +- Upgrade from `flask==2.2.5` to `Flask==3.0.3`. Fixes a bug in which Dependabot was not tracking Flask upgrades because we specified the dependency name as lowercase. +- Specify our custom JSON encoder by subclassing `flask.json.provider.JSONProvider`. See + ## [8.0.0] ### Added diff --git a/apps/api/src/hyp3_api/routes.py b/apps/api/src/hyp3_api/routes.py index e3c820d05..e0d69998f 100644 --- a/apps/api/src/hyp3_api/routes.py +++ b/apps/api/src/hyp3_api/routes.py @@ -6,6 +6,7 @@ import yaml from flask import abort, g, jsonify, make_response, redirect, render_template, request +from flask.json.provider import JSONProvider from flask_cors import CORS from openapi_core import OpenAPI from openapi_core.contrib.flask.decorators import FlaskOpenAPIViewDecorator @@ -87,13 +88,24 @@ def default(self, o): if isinstance(o, datetime.date): return o.isoformat() + if isinstance(o, Decimal): if o == int(o): return int(o) return float(o) + + # Raises a TypeError json.JSONEncoder.default(self, o) +class CustomJSONProvider(JSONProvider): + def dumps(self, o): + return json.dumps(o, cls=CustomEncoder) + + def loads(self, s): + return json.loads(s) + + class ErrorHandler(FlaskOpenAPIErrorsHandler): def __init__(self): super().__init__() @@ -104,7 +116,7 @@ def __call__(self, errors): return handlers.problem_format(error['status'], error['title']) -app.json_encoder = CustomEncoder +app.json = CustomJSONProvider(app) openapi = FlaskOpenAPIViewDecorator( api_spec, diff --git a/requirements-apps-api.txt b/requirements-apps-api.txt index ce688299c..469dde376 100644 --- a/requirements-apps-api.txt +++ b/requirements-apps-api.txt @@ -1,4 +1,5 @@ -flask==2.2.5 +# TODO: verify that dependabot bumps to Flask 3.0.3 on Monday +Flask==3.0.2 Flask-Cors==5.0.0 jsonschema==4.23.0 openapi-core==0.19.4 diff --git a/tests/test_api/test_patch_user.py b/tests/test_api/test_patch_user.py index a3086a63d..7185d77e8 100644 --- a/tests/test_api/test_patch_user.py +++ b/tests/test_api/test_patch_user.py @@ -18,7 +18,7 @@ def test_patch_new_user(client, tables): assert response.json == { 'user_id': 'foo', 'application_status': APPLICATION_PENDING, - 'remaining_credits': Decimal(0), + 'remaining_credits': 0, 'job_names': [], 'use_case': 'I want data.', } @@ -45,7 +45,7 @@ def test_patch_pending_user(client, tables): assert response.status_code == HTTPStatus.OK assert response.json == { 'user_id': 'foo', - 'remaining_credits': Decimal(0), + 'remaining_credits': 0, 'application_status': APPLICATION_PENDING, 'use_case': 'New use case.', 'job_names': [], @@ -92,7 +92,7 @@ def test_patch_user_access_code(client, tables): assert response.json == { 'user_id': 'foo', 'application_status': APPLICATION_APPROVED, - 'remaining_credits': Decimal(25), + 'remaining_credits': 25, 'job_names': [], 'use_case': 'I want data.', 'access_code': '123',