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 2 commits
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
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
8 changes: 7 additions & 1 deletion src/antares/craft/service/api_services/renewable_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,14 @@ def read_renewables(
area_id: str,
) -> List[RenewableCluster]:
url = f"{self._base_url}/studies/{self.study_id}/areas/{area_id}/clusters/renewable"
json_renewables = self._wrapper.get(url).json()

try:
json_renewables = self._wrapper.get(url).json()
except APIError as e:
if e.message == "'renewables' not a child of Input":
vargastat marked this conversation as resolved.
Show resolved Hide resolved
json_renewables = []
else:
raise
renewables = []

for renewable in json_renewables:
Expand Down
15 changes: 15 additions & 0 deletions tests/antares/services/api_services/test_area_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,18 @@ def test_read_hydro(self):
assert actual_hydro.area_id == expected_hydro.area_id
assert actual_hydro.properties == expected_hydro.properties
assert actual_hydro.matrices is None

def test_read_renewables_empty(self):
area = self.area
url_renewable = f"https://antares.com/api/v1/studies/{self.study_id}/areas/{area.id}/clusters/renewable"

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

actual_renewables = area.read_renewables()

assert actual_renewables == []
18 changes: 18 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,21 @@ 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 == []
14 changes: 14 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,14 @@ 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.advanced_parameters = AdvancedParameters()
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}")