diff --git a/src/antares/model/link.py b/src/antares/model/link.py index 13a5b04a..bee7833f 100644 --- a/src/antares/model/link.py +++ b/src/antares/model/link.py @@ -15,7 +15,6 @@ from pydantic import BaseModel -from antares.model.area import Area from antares.model.commons import FilterOption, sort_filter_values from antares.tools.alias_generators import to_kebab from antares.tools.all_optional_meta import all_optional_model @@ -132,8 +131,8 @@ def yield_link_ui(self) -> LinkUi: class Link: def __init__( # type: ignore # TODO: Find a way to avoid circular imports self, - area_from: Area, - area_to: Area, + area_from: str, + area_to: str, link_service, properties: Optional[LinkProperties] = None, ui: Optional[LinkUi] = None, @@ -146,14 +145,14 @@ def __init__( # type: ignore # TODO: Find a way to avoid circular imports @property def name(self) -> str: - return self._area_from.id + " / " + self._area_to.id + return self._area_from + " / " + self._area_to @property - def area_from(self) -> Area: + def area_from(self) -> str: return self._area_from @property - def area_to(self) -> Area: + def area_to(self) -> str: return self._area_to @property diff --git a/src/antares/model/study.py b/src/antares/model/study.py index 1b0bc163..1807ead0 100644 --- a/src/antares/model/study.py +++ b/src/antares/model/study.py @@ -246,8 +246,8 @@ def delete_area(self, area: Area) -> None: def create_link( self, *, - area_from: Area, - area_to: Area, + area_from: str, + area_to: str, properties: Optional[LinkProperties] = None, ui: Optional[LinkUi] = None, existing_areas: Optional[MappingProxyType[str, Area]] = None, diff --git a/src/antares/service/api_services/link_api.py b/src/antares/service/api_services/link_api.py index 2e5346ff..2f0cf52e 100644 --- a/src/antares/service/api_services/link_api.py +++ b/src/antares/service/api_services/link_api.py @@ -37,8 +37,8 @@ def __init__(self, config: APIconf, study_id: str): def create_link( self, - area_from: Area, - area_to: Area, + area_from: str, + area_to: str, properties: Optional[LinkProperties] = None, ui: Optional[LinkUi] = None, existing_areas: Optional[MappingProxyType[str, Area]] = None, @@ -60,7 +60,9 @@ def create_link( """ base_url = f"{self._base_url}/studies/{self.study_id}" # TODO: Currently, AntaresWeb does not have a specific endpoint for links. Once it will, we should change this logic. - area1_id, area2_id = sorted([area_from.id, area_to.id]) + + area1_id, area2_id = sorted([area_from, area_to]) + raw_url = f"{base_url}/raw?path=input/links/{area1_id}/properties/{area2_id}" try: @@ -94,13 +96,13 @@ def create_link( created_properties = LinkProperties.model_validate(json_properties) except APIError as e: - raise LinkCreationError(area_from.id, area_to.id, e.message) from e + raise LinkCreationError(area_from, area_to, e.message) from e return Link(area_from, area_to, self, created_properties, ui) def delete_link(self, link: Link) -> None: - area_from_id = link.area_from.id - area_to_id = link.area_to.id + area_from_id = link.area_from + area_to_id = link.area_to url = f"{self._base_url}/studies/{self.study_id}/links/{area_from_id}/{area_to_id}" try: self._wrapper.delete(url) @@ -109,7 +111,7 @@ def delete_link(self, link: Link) -> None: def update_link_properties(self, link: Link, properties: LinkProperties) -> LinkProperties: # todo: change this code when AntaresWeb will have a real endpoint - area1_id, area2_id = sorted([link.area_from.id, link.area_to.id]) + area1_id, area2_id = sorted([link.area_from, link.area_to]) raw_url = f"{self._base_url}/studies/{self.study_id}/raw?path=input/links/{area1_id}/properties/{area2_id}" try: new_properties = properties.model_dump(mode="json", by_alias=True, exclude_none=True) @@ -141,7 +143,7 @@ def update_link_properties(self, link: Link, properties: LinkProperties) -> Link def update_link_ui(self, link: Link, ui: LinkUi) -> LinkUi: # todo: change this code when AntaresWeb will have a real endpoint - area1_id, area2_id = sorted([link.area_from.id, link.area_to.id]) + area1_id, area2_id = sorted([link.area_from, link.area_to]) raw_url = f"{self._base_url}/studies/{self.study_id}/raw?path=input/links/{area1_id}/properties/{area2_id}" try: new_ui = ui.model_dump(mode="json", by_alias=True, exclude_none=True) diff --git a/src/antares/service/base_services.py b/src/antares/service/base_services.py index da89201c..a385746a 100644 --- a/src/antares/service/base_services.py +++ b/src/antares/service/base_services.py @@ -315,8 +315,8 @@ class BaseLinkService(ABC): @abstractmethod def create_link( self, - area_from: Area, - area_to: Area, + area_from: str, + area_to: str, properties: Optional[LinkProperties] = None, ui: Optional[LinkUi] = None, existing_areas: Optional[MappingProxyType[str, Area]] = None, diff --git a/src/antares/service/local_services/link_local.py b/src/antares/service/local_services/link_local.py index 4587a24a..5f7ae3f6 100644 --- a/src/antares/service/local_services/link_local.py +++ b/src/antares/service/local_services/link_local.py @@ -33,8 +33,8 @@ def __init__(self, config: LocalConfiguration, study_name: str, **kwargs: Any) - def create_link( self, - area_from: Area, - area_to: Area, + area_from: str, + area_to: str, properties: Optional[LinkProperties] = None, ui: Optional[LinkUi] = None, existing_areas: Optional[MappingProxyType[str, Area]] = None, @@ -53,18 +53,18 @@ def create_link( Raises: LinkCreationError if an area doesn't exist or existing areas have not been provided """ - areas = dict(sorted({area_from.name: area_from, area_to.name: area_to}.items())) + areas = dict(sorted({area_from: area_from, area_to: area_to}.items())) if existing_areas is not None: for area in areas.keys(): if area not in existing_areas: - raise LinkCreationError(area_from.name, area_to.name, f"{area} does not exist.") + raise LinkCreationError(area_from, area_to, f"{area} does not exist.") else: - raise LinkCreationError(area_from.name, area_to.name, "Cannot verify existing areas.") + raise LinkCreationError(area_from, area_to, "Cannot verify existing areas.") area_from, area_to = areas.values() - link_dir = self.config.study_path / "input/links" / area_from.name + link_dir = self.config.study_path / "input/links" / area_from os.makedirs(link_dir, exist_ok=True) local_properties = ( @@ -81,16 +81,16 @@ def create_link( with open(properties_ini_file, "r") as ini_file: properties_ini.read_file(ini_file) try: - properties_ini.add_section(area_to.name) + properties_ini.add_section(area_to) except DuplicateSectionError: raise LinkCreationError( - area_from=area_from.name, - area_to=area_to.name, - message=f"Link exists already between '{area_from.name}' and '{area_to.name}'.", + area_from=area_from, + area_to=area_to, + message=f"Link exists already between '{area_from}' and '{area_to}'.", ) ini_dict = dict(local_properties.ini_fields) ini_dict.update(local_ui.ini_fields) - properties_ini[area_to.name] = self.sort_link_properties_dict(ini_dict) + properties_ini[area_to] = self.sort_link_properties_dict(ini_dict) properties_ini = sort_ini_sections(properties_ini) diff --git a/tests/antares/delete/test_delete_api.py b/tests/antares/delete/test_delete_api.py index c19d64f9..8b493262 100644 --- a/tests/antares/delete/test_delete_api.py +++ b/tests/antares/delete/test_delete_api.py @@ -70,19 +70,19 @@ def test_delete_area_fails(self): def test_delete_link_success(self): with requests_mock.Mocker() as mocker: - link = Link(self.area_be, self.area_fr, self.link_service) + link = Link(self.area_be.id, self.area_fr.id, self.link_service) url = f"https://antares.com/api/v1/studies/{self.study_id}/links/{self.area_be.id}/{self.area_fr.id}" mocker.delete(url, status_code=200) self.link_service.delete_link(link) def test_delete_link_fails(self): with requests_mock.Mocker() as mocker: - link = Link(self.area_fr, self.area_be, self.link_service) + link = Link(self.area_fr.name, self.area_be.name, self.link_service) url = f"https://antares.com/api/v1/studies/{self.study_id}/links/{self.area_fr.id}/{self.area_be.id}" mocker.delete(url, json={"description": self.antares_web_description_msg}, status_code=404) with pytest.raises( LinkDeletionError, - match=f"Could not delete the link {self.area_fr.id} / {self.area_be.id}: {self.antares_web_description_msg}", + match=f"Could not delete the link {self.area_fr.name} / {self.area_be.name}: {self.antares_web_description_msg}", ): self.link_service.delete_link(link) diff --git a/tests/antares/services/api_services/test_link_api.py b/tests/antares/services/api_services/test_link_api.py index dbfd0f37..3054f535 100644 --- a/tests/antares/services/api_services/test_link_api.py +++ b/tests/antares/services/api_services/test_link_api.py @@ -32,7 +32,7 @@ class TestCreateAPI: ) area_to = Area(name="area_to", area_service=api, storage_service=api, thermal_service=api, renewable_service=api) antares_web_description_msg = "Mocked Server KO" - link = Link(area_from, area_to, ServiceFactory(api, study_id).create_link_service()) + link = Link(area_from.id, area_to.id, ServiceFactory(api, study_id).create_link_service()) def test_update_links_properties_success(self): with requests_mock.Mocker() as mocker: @@ -64,6 +64,7 @@ def test_update_links_properties_fails(self): ) antares_web_description_msg = "Server KO" mocker.get(raw_url, json={"description": antares_web_description_msg}, status_code=404) + with pytest.raises( LinkPropertiesUpdateError, match=f"Could not update properties for link {self.link.name}: {antares_web_description_msg}", diff --git a/tests/antares/services/api_services/test_study_api.py b/tests/antares/services/api_services/test_study_api.py index 98c7cc96..17912b60 100644 --- a/tests/antares/services/api_services/test_study_api.py +++ b/tests/antares/services/api_services/test_study_api.py @@ -133,22 +133,10 @@ def test_create_link_success(self): base_url = f"https://antares.com/api/v1/studies/{self.study_id}" url = f"{base_url}/links" mocker.post(url, status_code=200) - area = Area( - name="area", - area_service=self.api, - storage_service=self.api, - thermal_service=self.api, - renewable_service=self.api, - ) - area_to = Area( - name="area_to", - area_service=self.api, - storage_service=self.api, - thermal_service=self.api, - renewable_service=self.api, - ) + area = "area" + area_to = "area_to" - raw_url = f"{base_url}/raw?path=input/links/{area.id}/properties/{area_to.id}" + raw_url = f"{base_url}/raw?path=input/links/{area}/properties/{area_to}" json_response = {**LinkProperties().model_dump(by_alias=True), **LinkUi().model_dump(by_alias=True)} mocker.get(raw_url, json=json_response, status_code=200) link = self.study.create_link(area_from=area, area_to=area_to) @@ -158,24 +146,12 @@ def test_create_link_fails(self): with requests_mock.Mocker() as mocker: url = f"https://antares.com/api/v1/studies/{self.study_id}/links" mocker.post(url, json={"description": self.antares_web_description_msg}, status_code=404) - area_from = Area( - name="area_from", - area_service=self.api, - storage_service=self.api, - thermal_service=self.api, - renewable_service=self.api, - ) - area_to = Area( - name="area_to", - area_service=self.api, - storage_service=self.api, - thermal_service=self.api, - renewable_service=self.api, - ) + area_from = "area_from" + area_to = "area_to" with pytest.raises( LinkCreationError, - match=f"Could not create the link {area_from.id} / {area_to.id}: {self.antares_web_description_msg}", + match=f"Could not create the link {area_from} / {area_to}: {self.antares_web_description_msg}", ): self.study.create_link(area_from=area_from, area_to=area_to) diff --git a/tests/antares/services/local_services/conftest.py b/tests/antares/services/local_services/conftest.py index 8b039902..8b68216f 100644 --- a/tests/antares/services/local_services/conftest.py +++ b/tests/antares/services/local_services/conftest.py @@ -56,10 +56,9 @@ def local_study_w_links(tmp_path, local_study_w_areas): for link in links_to_create: area_from, area_to = link.split("_") local_study_w_areas.create_link( - area_from=local_study_w_areas.get_areas()[area_from], - area_to=local_study_w_areas.get_areas()[area_to], - existing_areas=local_study_w_areas.get_areas(), + area_from=area_from, area_to=area_to, existing_areas=local_study_w_areas.get_areas() ) + return local_study_w_areas diff --git a/tests/antares/services/local_services/test_study.py b/tests/antares/services/local_services/test_study.py index 8681a428..f03ec9a8 100644 --- a/tests/antares/services/local_services/test_study.py +++ b/tests/antares/services/local_services/test_study.py @@ -29,7 +29,7 @@ CustomError, LinkCreationError, ) -from antares.model.area import Area, AreaProperties, AreaPropertiesLocal, AreaUi, AreaUiLocal +from antares.model.area import AreaProperties, AreaPropertiesLocal, AreaUi, AreaUiLocal from antares.model.binding_constraint import ( BindingConstraint, BindingConstraintFrequency, @@ -83,11 +83,7 @@ from antares.model.settings.study_settings import DefaultStudySettings, StudySettingsLocal from antares.model.settings.thematic_trimming import DefaultThematicTrimmingParameters, ThematicTrimmingParametersLocal from antares.model.study import create_study_local -from antares.service.local_services.area_local import AreaLocalService from antares.service.local_services.link_local import LinkLocalService -from antares.service.local_services.renewable_local import RenewableLocalService -from antares.service.local_services.st_storage_local import ShortTermStorageLocalService -from antares.service.local_services.thermal_local import ThermalLocalService from antares.tools.ini_tool import IniFileTypes @@ -1624,8 +1620,8 @@ def test_create_link(self, tmp_path, local_study_w_areas): # When area_from, area_to = link_to_create.split("_") link_created = local_study_w_areas.create_link( - area_from=local_study_w_areas.get_areas()[area_from], - area_to=local_study_w_areas.get_areas()[area_to], + area_from=area_from, + area_to=area_to, existing_areas=local_study_w_areas.get_areas(), ) @@ -1634,23 +1630,15 @@ def test_create_link(self, tmp_path, local_study_w_areas): def test_unknown_area_errors(self, tmp_path, local_study_w_areas): # Given link_to_create = "es_fr" - fake_study_name = "nonExistantStudy" - fake_config = LocalConfiguration(Path("/fake/path"), fake_study_name) # When area_from, area_to = link_to_create.split("_") - area_from = Area( - name=area_from, - area_service=AreaLocalService(fake_config, fake_study_name), - storage_service=ShortTermStorageLocalService(fake_config, fake_study_name), - thermal_service=ThermalLocalService(fake_config, fake_study_name), - renewable_service=RenewableLocalService(fake_config, fake_study_name), - ) - area_to = local_study_w_areas.get_areas()[area_to] + area_from = area_from + area_to = area_to with pytest.raises( LinkCreationError, - match=f"Could not create the link {area_from.name} / {area_to.name}: {area_from.name} does not exist", + match=f"Could not create the link {area_from} / {area_to}: {area_from} does not exist", ): local_study_w_areas.create_link( area_from=area_from, area_to=area_to, existing_areas=local_study_w_areas.get_areas() @@ -1658,8 +1646,8 @@ def test_unknown_area_errors(self, tmp_path, local_study_w_areas): def test_study_areas_not_provided_errors(self, tmp_path, local_study_w_areas): # With - area_from = local_study_w_areas.get_areas()["fr"] - area_to = local_study_w_areas.get_areas()["it"] + area_from = "fr" + area_to = "it" test_service = LinkLocalService( local_study_w_areas.service.config, local_study_w_areas.name, @@ -1667,7 +1655,7 @@ def test_study_areas_not_provided_errors(self, tmp_path, local_study_w_areas): with pytest.raises( LinkCreationError, - match=f"Could not create the link {area_from.name} / {area_to.name}: Cannot verify existing areas.", + match=f"Could not create the link {area_from} / {area_to}: Cannot verify existing areas.", ): test_service.create_link( area_from=area_from, @@ -1685,13 +1673,13 @@ def test_create_link_alphabetically(self, tmp_path, local_study): # When area_from, area_to = link_to_create.split("_") link_created = local_study.create_link( - area_from=local_study.get_areas()[area_from], - area_to=local_study.get_areas()[area_to], + area_from=area_from, + area_to=area_to, existing_areas=local_study.get_areas(), ) - assert link_created.area_from.name == "at" - assert link_created.area_to.name == "fr" + assert link_created.area_from == "at" + assert link_created.area_to == "fr" def test_create_link_sets_ini_content(self, tmp_path, local_study_w_areas): # Given @@ -1717,8 +1705,8 @@ def test_create_link_sets_ini_content(self, tmp_path, local_study_w_areas): area_from, area_to = link_to_create.split("_") local_study_w_areas.create_link( - area_from=local_study_w_areas.get_areas()[area_from], - area_to=local_study_w_areas.get_areas()[area_to], + area_from="fr", + area_to="it", existing_areas=local_study_w_areas.get_areas(), ) @@ -1754,8 +1742,8 @@ def test_created_link_has_default_local_properties(self, tmp_path, local_study_w # When area_from, area_to = link_to_create.split("_") created_link = local_study_w_areas.create_link( - area_from=local_study_w_areas.get_areas()[area_from], - area_to=local_study_w_areas.get_areas()[area_to], + area_from="fr", + area_to="it", existing_areas=local_study_w_areas.get_areas(), ) ini_file = tmp_path / local_study_w_areas.name / "input/links" / area_from / "properties.ini" @@ -1802,8 +1790,8 @@ def test_created_link_has_custom_properties(self, tmp_path, local_study_w_areas) # When area_from, area_to = link_to_create.split("_") link_created = local_study_w_areas.create_link( - area_from=local_study_w_areas.get_areas()[area_from], - area_to=local_study_w_areas.get_areas()[area_to], + area_from="fr", + area_to="it", properties=link_properties, existing_areas=local_study_w_areas.get_areas(), ) @@ -1863,8 +1851,8 @@ def test_multiple_links_created_from_same_area(self, tmp_path, local_study_w_are for link in links_to_create: area_from, area_to = link.split("_") local_study_w_areas.create_link( - area_from=local_study_w_areas.get_areas()[area_from], - area_to=local_study_w_areas.get_areas()[area_to], + area_from=area_from, + area_to=area_to, existing_areas=local_study_w_areas.get_areas(), ) @@ -1924,8 +1912,8 @@ def test_multiple_links_created_from_same_area_are_alphabetical(self, tmp_path, for link in links_to_create: area_from, area_to = link.split("_") local_study_w_areas.create_link( - area_from=local_study_w_areas.get_areas()[area_from], - area_to=local_study_w_areas.get_areas()[area_to], + area_from=area_from, + area_to=area_to, existing_areas=local_study_w_areas.get_areas(), ) @@ -1952,8 +1940,8 @@ def test_duplicate_links_raises_error(self, tmp_path, local_study_w_links): match=f"Could not create the link {area_from} / {area_to}: Link exists already between '{area_from}' and '{area_to}'.", ): local_study_w_links.create_link( - area_from=local_study_w_links.get_areas()[area_from], - area_to=local_study_w_links.get_areas()[area_to], + area_from=area_from, + area_to=area_to, existing_areas=local_study_w_links.get_areas(), ) @@ -1984,8 +1972,8 @@ def test_created_link_has_default_ui_values(self, tmp_path, local_study_w_areas) # When area_from, area_to = link_to_create.split(" / ") local_study_w_areas.create_link( - area_from=local_study_w_areas.get_areas()[area_from], - area_to=local_study_w_areas.get_areas()[area_to], + area_from=area_from, + area_to=area_to, existing_areas=local_study_w_areas.get_areas(), ) with open(actual_ini_file, "r") as file: @@ -2032,8 +2020,8 @@ def test_created_link_with_custom_ui_values(self, tmp_path, local_study_w_areas) # When area_from, area_to = link_to_create.split(" / ") created_link = local_study_w_areas.create_link( - area_from=local_study_w_areas.get_areas()[area_from], - area_to=local_study_w_areas.get_areas()[area_to], + area_from=area_from, + area_to=area_to, properties=expected_properties, ui=expected_ui, existing_areas=local_study_w_areas.get_areas(), diff --git a/tests/integration/test_web_client.py b/tests/integration/test_web_client.py index 300f8301..63ac09a0 100644 --- a/tests/integration/test_web_client.py +++ b/tests/integration/test_web_client.py @@ -104,16 +104,16 @@ def test_creation_lifecycle(self, antares_web: AntaresWebDesktop): assert area_de.properties.filter_synthesis == {FilterOption.HOURLY, FilterOption.DAILY} # tests link creation with default values - link_de_fr = study.create_link(area_from=area_de, area_to=area_fr) - assert link_de_fr.area_from == area_de - assert link_de_fr.area_to == area_fr + link_de_fr = study.create_link(area_from=area_de.id, area_to=area_fr.id) + assert link_de_fr.area_from == area_de.id + assert link_de_fr.area_to == area_fr.id assert link_de_fr.name == f"{area_de.id} / {area_fr.id}" # tests link creation with ui and properties link_ui = LinkUi(colorr=44) link_properties = LinkProperties(hurdles_cost=True) link_properties.filter_year_by_year = [FilterOption.HOURLY] - link_be_fr = study.create_link(area_from=area_be, area_to=area_fr, ui=link_ui, properties=link_properties) + link_be_fr = study.create_link(area_from=area_be.id, area_to=area_fr.id, ui=link_ui, properties=link_properties) assert link_be_fr.ui.colorr == 44 assert link_be_fr.properties.hurdles_cost assert link_be_fr.properties.filter_year_by_year == {FilterOption.HOURLY}