diff --git a/antarest/study/web/raw_studies_blueprint.py b/antarest/study/web/raw_studies_blueprint.py index a62a08b207..1105a5f74a 100644 --- a/antarest/study/web/raw_studies_blueprint.py +++ b/antarest/study/web/raw_studies_blueprint.py @@ -136,7 +136,18 @@ def get_study( # because it's better to avoid raising an exception. return Response(content=output, media_type="application/octet-stream") - return JSONResponse(content=output) + # We want to allow `NaN`, `+Infinity`, and `-Infinity` values in the JSON response + # even though they are not standard JSON values because they are supported in JavaScript. + # Additionally, we cannot use `orjson` because, despite its superior performance, it converts + # `NaN` and other values to `null`, even when using a custom encoder. + json_response = json.dumps( + output, + ensure_ascii=False, + allow_nan=True, + indent=None, + separators=(",", ":"), + ).encode("utf-8") + return Response(content=json_response, media_type="application/json") @bp.post( "/studies/{uuid}/raw", diff --git a/tests/integration/raw_studies_blueprint/test_fetch_raw_data.py b/tests/integration/raw_studies_blueprint/test_fetch_raw_data.py index 96366c6e44..7b5bc4e38e 100644 --- a/tests/integration/raw_studies_blueprint/test_fetch_raw_data.py +++ b/tests/integration/raw_studies_blueprint/test_fetch_raw_data.py @@ -4,6 +4,7 @@ import shutil from urllib.parse import urlencode +import numpy as np import pytest from starlette.testclient import TestClient @@ -41,6 +42,7 @@ def test_get_study( with db(): study: RawStudy = db.session.get(Study, study_id) study_dir = pathlib.Path(study.path) + headers = {"Authorization": f"Bearer {user_access_token}"} shutil.copytree( ASSETS_DIR.joinpath("user"), @@ -55,7 +57,7 @@ def test_get_study( query_string = urlencode({"path": f"/{rel_path}", "depth": 1}) res = client.get( f"/v1/studies/{study_id}/raw?{query_string}", - headers={"Authorization": f"Bearer {user_access_token}"}, + headers=headers, ) res.raise_for_status() if file_path.suffix == ".json": @@ -81,7 +83,7 @@ def test_get_study( query_string = urlencode({"path": f"/{rel_path.as_posix()}", "depth": 1}) res = client.get( f"/v1/studies/{study_id}/raw?{query_string}", - headers={"Authorization": f"Bearer {user_access_token}"}, + headers=headers, ) res.raise_for_status() actual = res.content @@ -95,7 +97,7 @@ def test_get_study( query_string = urlencode({"path": f"/{rel_path.as_posix()}", "depth": 1}) res = client.get( f"/v1/studies/{study_id}/raw?{query_string}", - headers={"Authorization": f"Bearer {user_access_token}"}, + headers=headers, ) assert res.status_code == http.HTTPStatus.UNPROCESSABLE_ENTITY @@ -104,7 +106,15 @@ def test_get_study( query_string = urlencode({"path": "/input/areas/list", "depth": 1}) res = client.get( f"/v1/studies/{study_id}/raw?{query_string}", - headers={"Authorization": f"Bearer {user_access_token}"}, + headers=headers, ) res.raise_for_status() assert res.json() == ["DE", "ES", "FR", "IT"] + + # asserts that the GET /raw endpoint is able to read matrix containing NaN values + res = client.get( + f"/v1/studies/{study_id}/raw?path=output/20201014-1427eco/economy/mc-all/areas/de/id-monthly", + headers=headers, + ) + assert res.status_code == 200 + assert np.isnan(res.json()["data"][0]).any() diff --git a/tests/integration/test_integration_xpansion.py b/tests/integration/test_integration_xpansion.py index f4f4648605..0aa0579734 100644 --- a/tests/integration/test_integration_xpansion.py +++ b/tests/integration/test_integration_xpansion.py @@ -1,18 +1,14 @@ import io from pathlib import Path -from fastapi import FastAPI from starlette.testclient import TestClient from antarest.study.business.area_management import AreaType from antarest.study.business.xpansion_management import XpansionCandidateDTO -def test_integration_xpansion(app: FastAPI, tmp_path: Path): - client = TestClient(app, raise_server_exceptions=False) - res = client.post("/v1/login", json={"username": "admin", "password": "admin"}) - admin_credentials = res.json() - headers = {"Authorization": f'Bearer {admin_credentials["access_token"]}'} +def test_integration_xpansion(client: TestClient, tmp_path: Path, admin_access_token: str): + headers = {"Authorization": f"Bearer {admin_access_token}"} created = client.post( "/v1/studies?name=foo",