Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(api): horizon to be accepted as str and read_renewables doesn't fail when settings are aggregated #74

Merged
merged 3 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/antares/craft/api_conf/request_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,29 @@
]


class EmptyResponse(requests.Response):
"""
Class to simulate an empty requests.Response.
"""

def json(self, **kwargs: Any) -> list:
return []


def _handle_exceptions(response: requests.Response) -> requests.Response:
"""
If an exception occurred, returns APIError exception containing the AntaresWeb error message.
"""
if response.status_code - 200 < 100:
return response
try:
msg = response.json()["description"]
error_data = response.json()
msg = error_data.get("description", response.reason)
if response.status_code == 404 and "renewables" in msg:
vargastat marked this conversation as resolved.
Show resolved Hide resolved
return EmptyResponse()
except (json.decoder.JSONDecodeError, KeyError):
msg = response.reason

raise APIError(msg)


Expand Down
9 changes: 8 additions & 1 deletion src/antares/craft/model/settings/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
#
# This file is part of the Antares project.

import typing as t

from antares.craft.tools.all_optional_meta import all_optional_model
from antares.craft.tools.contents_tool import EnumIgnoreCase
from pydantic import BaseModel, ConfigDict, Field
from pydantic import BaseModel, ConfigDict, Field, field_validator
from pydantic.alias_generators import to_camel


Expand Down Expand Up @@ -97,6 +99,11 @@ class DefaultGeneralParameters(BaseModel, extra="forbid", populate_by_name=True,
mc_scenario: bool = False # ? output/storenewset
result_format: OutputFormat = Field(default=OutputFormat.TXT, exclude=True)

@field_validator("horizon", mode="before")
def transform_horizon_to_str(cls, val: t.Union[str, int, None]) -> t.Optional[str]:
# horizon can be an int.
return str(val) if val else val # type: ignore


@all_optional_model
class GeneralParameters(DefaultGeneralParameters):
Expand Down
20 changes: 20 additions & 0 deletions tests/antares/services/api_services/test_renewable_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,23 @@ def test_read_renewables(self):

assert expected_renewable.id == actual_renewable.id
assert expected_renewable.name == actual_renewable.name

def test_read_renewables_with_404_response_then_return_empty_list(self):
vargastat marked this conversation as resolved.
Show resolved Hide resolved
study_id_test = "248bbb99-c909-47b7-b239-01f6f6ae7de7"
area_id = "zone"
url = f"https://antares.com/api/v1/studies/{study_id_test}/areas/{area_id}/"

with requests_mock.Mocker() as mocker:
mocker.get(
url + "clusters/renewable",
status_code=404,
json={"description": "'renewables' not a child of Input", "exception": "ChildNotFoundError"},
)

renewable_api = RenewableApiService(self.api, study_id_test)

actual_renewable_list = renewable_api.read_renewables(area_id)
vargastat marked this conversation as resolved.
Show resolved Hide resolved

assert actual_renewable_list == []

assert len(actual_renewable_list) == 0
vargastat marked this conversation as resolved.
Show resolved Hide resolved
16 changes: 16 additions & 0 deletions tests/integration/test_web_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from antares.craft.api_conf.api_conf import APIconf
from antares.craft.exceptions.exceptions import (
APIError,
AreaDeletionError,
BindingConstraintCreationError,
ConstraintMatrixUpdateError,
Expand Down Expand Up @@ -504,6 +505,8 @@ def test_creation_lifecycle(self, antares_web: AntaresWebDesktop):
# Really important note. To instance such object with value you must respect camel case.
# Another way to do so is to instance the object and then fill its values
new_settings.general_parameters = GeneralParameters(nbYears=4)
# To create a variant with horizon as string
new_settings.general_parameters.horizon = "2018"
new_settings.advanced_parameters = AdvancedParameters()
new_settings.advanced_parameters.unit_commitment_mode = UnitCommitmentMode.MILP
new_study.update_settings(new_settings)
Expand Down Expand Up @@ -658,3 +661,16 @@ def test_creation_lifecycle(self, antares_web: AntaresWebDesktop):
moved_study = read_study_api(api_config, study.service.study_id)
assert moved_study.path == study.path
assert moved_study.name == study.name

new_settings_aggregated = StudySettings()
new_settings_aggregated.general_parameters = GeneralParameters(nbYears=4)
new_settings_aggregated.advanced_parameters = AdvancedParameters()
new_settings_aggregated.advanced_parameters.unit_commitment_mode = UnitCommitmentMode.MILP
new_settings_aggregated.advanced_parameters.renewable_generation_modelling = "aggregated"
study_aggregated = create_study_api("test_aggregated", "880", api_config, new_settings_aggregated)
vargastat marked this conversation as resolved.
Show resolved Hide resolved
study_aggregated.create_area("area_without_renewables")
# read_study_api does not raise an error
try:
vargastat marked this conversation as resolved.
Show resolved Hide resolved
read_study_api(api_config, study_aggregated.service.study_id)
except APIError as e:
pytest.fail(f"read_study_api raised an unexpected APIError: {e}")