From d3a417090fc665572c91a7b0814681767b53e13f Mon Sep 17 00:00:00 2001 From: wahadameh Date: Wed, 29 Jan 2025 15:24:00 +0100 Subject: [PATCH 1/9] feat(api): added import_study method to study_api.py --- src/antares/craft/exceptions/exceptions.py | 4 ++++ src/antares/craft/service/api_services/study_api.py | 13 +++++++++++++ src/antares/craft/service/base_services.py | 5 +++++ .../craft/service/local_services/study_local.py | 4 ++++ 4 files changed, 26 insertions(+) diff --git a/src/antares/craft/exceptions/exceptions.py b/src/antares/craft/exceptions/exceptions.py index 04648d99..4bda783d 100644 --- a/src/antares/craft/exceptions/exceptions.py +++ b/src/antares/craft/exceptions/exceptions.py @@ -255,6 +255,10 @@ def __init__(self, study_id: str, new_folder_name: str, message: str) -> None: self.message = f"Could not move the study {study_id} to folder {new_folder_name}: " + message super().__init__(self.message) +class StudyImportError(Exception): + def __init__(self, study_name: str, destination_folder_name: str, message: str): + self.message = f"Could not import the study {study_name} to folder {destination_folder_name}: " + message + super().__init__(self.message) class ThermalMatrixDownloadError(Exception): def __init__(self, area_name: str, cluster_name: str, matrix_name: str, message: str) -> None: diff --git a/src/antares/craft/service/api_services/study_api.py b/src/antares/craft/service/api_services/study_api.py index 2a29ef43..0f07b4c5 100644 --- a/src/antares/craft/service/api_services/study_api.py +++ b/src/antares/craft/service/api_services/study_api.py @@ -187,3 +187,16 @@ def generate_thermal_timeseries(self) -> None: wait_task_completion(self._base_url, self._wrapper, task_id) except (APIError, TaskFailedError, TaskTimeOutError) as e: raise ThermalTimeseriesGenerationError(self.study_id, e.message) + + def import_study(self, config: APIconf, study_path: Path, destination_path: Path) -> None: + def has_valid_extension(path: Path) -> bool: + valid_extensions = {".zip", ".7z"} + return path.suffix in valid_extensions + + try: + if has_valid_extension(study_path): + url = f"{self._base_url}/studies/_import?study={study_path}&encode=multipart" + self._wrapper.post(url) + self.move_study(destination_path) + except APIError: + raise NotImplementedError diff --git a/src/antares/craft/service/base_services.py b/src/antares/craft/service/base_services.py index d74ed61f..2e1a680a 100644 --- a/src/antares/craft/service/base_services.py +++ b/src/antares/craft/service/base_services.py @@ -16,6 +16,7 @@ import pandas as pd +from antares.craft.api_conf.api_conf import APIconf from antares.craft.config.base_configuration import BaseConfiguration from antares.craft.model.area import Area, AreaProperties, AreaUi from antares.craft.model.binding_constraint import ( @@ -640,6 +641,10 @@ def delete_output(self, output_name: str) -> None: def generate_thermal_timeseries(self) -> None: pass + @abstractmethod + def import_study(self, config: APIconf, study_path: Path, destination_path: Path) -> None: + pass + class BaseRenewableService(ABC): @abstractmethod diff --git a/src/antares/craft/service/local_services/study_local.py b/src/antares/craft/service/local_services/study_local.py index d4ae9a7a..4edff5f0 100644 --- a/src/antares/craft/service/local_services/study_local.py +++ b/src/antares/craft/service/local_services/study_local.py @@ -12,6 +12,7 @@ from pathlib import Path, PurePath from typing import TYPE_CHECKING, Any, Optional +from antares.craft.api_conf.api_conf import APIconf from antares.craft.config.local_configuration import LocalConfiguration from antares.craft.model.binding_constraint import BindingConstraint from antares.craft.model.output import Output @@ -70,3 +71,6 @@ def move_study(self, new_parent_path: Path) -> PurePath: def generate_thermal_timeseries(self) -> None: raise NotImplementedError + + def import_study(self, config: APIconf, study_path: Path, destination_path: Path) -> None: + raise NotImplementedError From a656287aaf607483dc89e2a3820d4f2d387b82c7 Mon Sep 17 00:00:00 2001 From: wahadameh Date: Wed, 29 Jan 2025 15:32:41 +0100 Subject: [PATCH 2/9] feat(api): added import_study method to study_api.py --- src/antares/craft/exceptions/exceptions.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/antares/craft/exceptions/exceptions.py b/src/antares/craft/exceptions/exceptions.py index 4bda783d..33e040ea 100644 --- a/src/antares/craft/exceptions/exceptions.py +++ b/src/antares/craft/exceptions/exceptions.py @@ -255,11 +255,13 @@ def __init__(self, study_id: str, new_folder_name: str, message: str) -> None: self.message = f"Could not move the study {study_id} to folder {new_folder_name}: " + message super().__init__(self.message) + class StudyImportError(Exception): def __init__(self, study_name: str, destination_folder_name: str, message: str): self.message = f"Could not import the study {study_name} to folder {destination_folder_name}: " + message super().__init__(self.message) + class ThermalMatrixDownloadError(Exception): def __init__(self, area_name: str, cluster_name: str, matrix_name: str, message: str) -> None: self.message = ( From aee8995a578fd7986b52be95529bd90229c3d3dc Mon Sep 17 00:00:00 2001 From: wahadameh Date: Fri, 31 Jan 2025 14:56:00 +0100 Subject: [PATCH 3/9] feat(api): added unit testing to import_study_api --- src/antares/craft/exceptions/exceptions.py | 4 +- src/antares/craft/model/study.py | 36 ++++++- .../craft/service/api_services/study_api.py | 13 --- src/antares/craft/service/base_services.py | 5 - .../service/local_services/study_local.py | 4 - .../services/api_services/test_study_api.py | 102 +++++++++++++++++- 6 files changed, 136 insertions(+), 28 deletions(-) diff --git a/src/antares/craft/exceptions/exceptions.py b/src/antares/craft/exceptions/exceptions.py index 33e040ea..ec14968a 100644 --- a/src/antares/craft/exceptions/exceptions.py +++ b/src/antares/craft/exceptions/exceptions.py @@ -257,8 +257,8 @@ def __init__(self, study_id: str, new_folder_name: str, message: str) -> None: class StudyImportError(Exception): - def __init__(self, study_name: str, destination_folder_name: str, message: str): - self.message = f"Could not import the study {study_name} to folder {destination_folder_name}: " + message + def __init__(self, study_id: str, message: str): + self.message = f"Could not import the study {study_id} : {message}" super().__init__(self.message) diff --git a/src/antares/craft/model/study.py b/src/antares/craft/model/study.py index 43ad1140..da08b0b5 100644 --- a/src/antares/craft/model/study.py +++ b/src/antares/craft/model/study.py @@ -9,7 +9,7 @@ # SPDX-License-Identifier: MPL-2.0 # # This file is part of the Antares project. - +import io import logging import os import time @@ -23,7 +23,13 @@ from antares.craft.api_conf.api_conf import APIconf from antares.craft.api_conf.request_wrapper import RequestWrapper from antares.craft.config.local_configuration import LocalConfiguration -from antares.craft.exceptions.exceptions import APIError, LinkCreationError, StudyCreationError, StudyMoveError +from antares.craft.exceptions.exceptions import ( + APIError, + LinkCreationError, + StudyCreationError, + StudyImportError, + StudyMoveError, +) from antares.craft.model.area import Area, AreaProperties, AreaUi from antares.craft.model.binding_constraint import ( BindingConstraint, @@ -89,6 +95,32 @@ def create_study_api( raise StudyCreationError(study_name, e.message) from e +def import_study_api(api_config: APIconf, study_path: Path, destination_path: Optional[Path]) -> "Study": + def has_valid_extension(path: Path) -> bool: + valid_extensions = {".zip", ".7z"} + return path.suffix in valid_extensions + + session = api_config.set_up_api_conf() + wrapper = RequestWrapper(session) + base_url = f"{api_config.get_host()}/api/v1" + + if has_valid_extension(study_path): + try: + files={"study":io.BytesIO(study_path.read_bytes())} + url = f"{base_url}/studies/_import" + study_id = wrapper.post(url, files=files).json() + + study = read_study_api(api_config, study_id) + if destination_path is not None: + study.move(destination_path) + + return study + except APIError as e: + raise StudyImportError(study_path.name, e.message) from e + else: + raise Exception(f"File doesn't have the right extensions (.zip/.7z): {study_path.suffix}" ) + + def create_study_local( study_name: str, version: str, diff --git a/src/antares/craft/service/api_services/study_api.py b/src/antares/craft/service/api_services/study_api.py index 0f07b4c5..2a29ef43 100644 --- a/src/antares/craft/service/api_services/study_api.py +++ b/src/antares/craft/service/api_services/study_api.py @@ -187,16 +187,3 @@ def generate_thermal_timeseries(self) -> None: wait_task_completion(self._base_url, self._wrapper, task_id) except (APIError, TaskFailedError, TaskTimeOutError) as e: raise ThermalTimeseriesGenerationError(self.study_id, e.message) - - def import_study(self, config: APIconf, study_path: Path, destination_path: Path) -> None: - def has_valid_extension(path: Path) -> bool: - valid_extensions = {".zip", ".7z"} - return path.suffix in valid_extensions - - try: - if has_valid_extension(study_path): - url = f"{self._base_url}/studies/_import?study={study_path}&encode=multipart" - self._wrapper.post(url) - self.move_study(destination_path) - except APIError: - raise NotImplementedError diff --git a/src/antares/craft/service/base_services.py b/src/antares/craft/service/base_services.py index 2e1a680a..d74ed61f 100644 --- a/src/antares/craft/service/base_services.py +++ b/src/antares/craft/service/base_services.py @@ -16,7 +16,6 @@ import pandas as pd -from antares.craft.api_conf.api_conf import APIconf from antares.craft.config.base_configuration import BaseConfiguration from antares.craft.model.area import Area, AreaProperties, AreaUi from antares.craft.model.binding_constraint import ( @@ -641,10 +640,6 @@ def delete_output(self, output_name: str) -> None: def generate_thermal_timeseries(self) -> None: pass - @abstractmethod - def import_study(self, config: APIconf, study_path: Path, destination_path: Path) -> None: - pass - class BaseRenewableService(ABC): @abstractmethod diff --git a/src/antares/craft/service/local_services/study_local.py b/src/antares/craft/service/local_services/study_local.py index 4edff5f0..d4ae9a7a 100644 --- a/src/antares/craft/service/local_services/study_local.py +++ b/src/antares/craft/service/local_services/study_local.py @@ -12,7 +12,6 @@ from pathlib import Path, PurePath from typing import TYPE_CHECKING, Any, Optional -from antares.craft.api_conf.api_conf import APIconf from antares.craft.config.local_configuration import LocalConfiguration from antares.craft.model.binding_constraint import BindingConstraint from antares.craft.model.output import Output @@ -71,6 +70,3 @@ def move_study(self, new_parent_path: Path) -> PurePath: def generate_thermal_timeseries(self) -> None: raise NotImplementedError - - def import_study(self, config: APIconf, study_path: Path, destination_path: Path) -> None: - raise NotImplementedError diff --git a/tests/antares/services/api_services/test_study_api.py b/tests/antares/services/api_services/test_study_api.py index cc8474b2..d5f09e0b 100644 --- a/tests/antares/services/api_services/test_study_api.py +++ b/tests/antares/services/api_services/test_study_api.py @@ -35,7 +35,7 @@ StudyMoveError, StudySettingsUpdateError, StudyVariantCreationError, - ThermalTimeseriesGenerationError, + ThermalTimeseriesGenerationError, APIError, StudyImportError, ) from antares.craft.model.area import Area, AreaProperties, AreaUi from antares.craft.model.binding_constraint import ( @@ -52,7 +52,7 @@ from antares.craft.model.settings.general import GeneralParameters from antares.craft.model.settings.study_settings import StudySettings from antares.craft.model.simulation import AntaresSimulationParameters, Job, JobStatus, Solver -from antares.craft.model.study import Study, create_study_api, create_variant_api, read_study_api +from antares.craft.model.study import Study, create_study_api, create_variant_api, read_study_api, import_study_api from antares.craft.service.api_services.output_api import OutputApiService from antares.craft.service.service_factory import ServiceFactory @@ -713,3 +713,101 @@ def test_generate_thermal_timeseries_failure(self): with pytest.raises(ThermalTimeseriesGenerationError, match=error_message): self.study.generate_thermal_timeseries() + + + def test_import_study_success(self, tmp_path): + json_study = { + "id": "22c52f44-4c2a-407b-862b-490887f93dd8", + "name": "test_read_areas", + "version": "880", + "folder": None, + } + + json_ui = { + "zone": { + "ui": {"x": 0, "y": 0, "color_r": 230, "color_g": 108, "color_b": 44, "layers": "0"}, + "layerX": {"0": 0}, + "layerY": {"0": 0}, + "layerColor": {"0": "230, 108, 44"}, + } + } + + study_path = tmp_path.joinpath("test.zip") + study_path.touch() + new_path = Path("/new/path/test") + base_url = "https://antares.com/api/v1" + + url = f"{base_url}/studies/{self.study_id}" + area_url = f"{url}/areas" + area_props_url = f"{area_url}/zone/properties/form" + thermal_url = f"{area_url}/zone/clusters/thermal" + renewable_url = f"{area_url}/zone/clusters/renewable" + storage_url = f"{area_url}/zone/storages" + output_url = f"{url}/outputs" + constraints_url = f"{base_url}/studies/{self.study_id}/bindingconstraints" + config_urls = re.compile(f"{base_url}/studies/{self.study_id}/config/.*") + + url_import = f"{base_url}/studies/_import" + url_move = f"{base_url}/studies/{self.study_id}/move?folder_dest={new_path}" + url_study = f"{base_url}/studies/{self.study_id}" + + with requests_mock.Mocker() as mocker: + mocker.post(url_import, status_code=200, json=self.study_id) + + mocker.get(url, json=json_study) + mocker.get(config_urls, json={}) + mocker.get(area_url, json=json_ui) + mocker.get(area_props_url, json={}) + mocker.get(renewable_url, json=[]) + mocker.get(thermal_url, json=[]) + mocker.get(storage_url, json=[]) + mocker.get( + output_url, + json=[], + ) + mocker.get(constraints_url, json=[]) + + #deux mockers + mocker.put(url_move) + mocker.get(url_study, json=json_study) + + actual_study = import_study_api(self.api, study_path, new_path) + + assert actual_study.name == json_study['name'] + assert actual_study.service.study_id == json_study['id'] + + def test_import_study_fail_wrong_extension(self, tmp_path): + + study_path = tmp_path.joinpath("test.rar") + study_path.touch() + new_path = Path("/new/path/test") + + base_url = "https://antares.com/api/v1" + url_import = f"{base_url}/studies/_import" + with requests_mock.Mocker() as mocker: + + mocker.get(url_import, status_code=404) + + with pytest.raises( + Exception, + match=re.escape("File doesn't have the right extensions (.zip/.7z): .rar") + ): + import_study_api(self.api, study_path, new_path) + + def test_import_study_fail_api_error(self, tmp_path): + study_path = tmp_path.joinpath("test.zip") + study_path.touch() + new_path = Path("/new/path/test") + + base_url = "https://antares.com/api/v1" + url_import = f"{base_url}/studies/_import" + url_read_study = f"{base_url}/studies/{self.study_id}" + + with requests_mock.Mocker() as mocker: + mocker.post(url_import, json=self.study_id) + mocker.get(url_read_study, json={"description": self.antares_web_description_msg}, status_code=404) + with pytest.raises( + StudyImportError, + match=f"Could not import the study test.zip : {self.antares_web_description_msg}" + ): + import_study_api(self.api, study_path, new_path) \ No newline at end of file From a8d9adda24fd7262474017b94b833d6dc645372f Mon Sep 17 00:00:00 2001 From: wahadameh Date: Fri, 31 Jan 2025 14:56:55 +0100 Subject: [PATCH 4/9] feat(api): added unit testing to import_study_api --- src/antares/craft/model/study.py | 4 ++-- .../services/api_services/test_study_api.py | 24 +++++++------------ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/antares/craft/model/study.py b/src/antares/craft/model/study.py index da08b0b5..fc7ee135 100644 --- a/src/antares/craft/model/study.py +++ b/src/antares/craft/model/study.py @@ -106,7 +106,7 @@ def has_valid_extension(path: Path) -> bool: if has_valid_extension(study_path): try: - files={"study":io.BytesIO(study_path.read_bytes())} + files = {"study": io.BytesIO(study_path.read_bytes())} url = f"{base_url}/studies/_import" study_id = wrapper.post(url, files=files).json() @@ -118,7 +118,7 @@ def has_valid_extension(path: Path) -> bool: except APIError as e: raise StudyImportError(study_path.name, e.message) from e else: - raise Exception(f"File doesn't have the right extensions (.zip/.7z): {study_path.suffix}" ) + raise Exception(f"File doesn't have the right extensions (.zip/.7z): {study_path.suffix}") def create_study_local( diff --git a/tests/antares/services/api_services/test_study_api.py b/tests/antares/services/api_services/test_study_api.py index d5f09e0b..a6b924b1 100644 --- a/tests/antares/services/api_services/test_study_api.py +++ b/tests/antares/services/api_services/test_study_api.py @@ -32,10 +32,11 @@ SimulationFailedError, SimulationTimeOutError, StudyCreationError, + StudyImportError, StudyMoveError, StudySettingsUpdateError, StudyVariantCreationError, - ThermalTimeseriesGenerationError, APIError, StudyImportError, + ThermalTimeseriesGenerationError, ) from antares.craft.model.area import Area, AreaProperties, AreaUi from antares.craft.model.binding_constraint import ( @@ -52,7 +53,7 @@ from antares.craft.model.settings.general import GeneralParameters from antares.craft.model.settings.study_settings import StudySettings from antares.craft.model.simulation import AntaresSimulationParameters, Job, JobStatus, Solver -from antares.craft.model.study import Study, create_study_api, create_variant_api, read_study_api, import_study_api +from antares.craft.model.study import Study, create_study_api, create_variant_api, import_study_api, read_study_api from antares.craft.service.api_services.output_api import OutputApiService from antares.craft.service.service_factory import ServiceFactory @@ -714,7 +715,6 @@ def test_generate_thermal_timeseries_failure(self): with pytest.raises(ThermalTimeseriesGenerationError, match=error_message): self.study.generate_thermal_timeseries() - def test_import_study_success(self, tmp_path): json_study = { "id": "22c52f44-4c2a-407b-862b-490887f93dd8", @@ -767,17 +767,16 @@ def test_import_study_success(self, tmp_path): ) mocker.get(constraints_url, json=[]) - #deux mockers + # deux mockers mocker.put(url_move) mocker.get(url_study, json=json_study) actual_study = import_study_api(self.api, study_path, new_path) - assert actual_study.name == json_study['name'] - assert actual_study.service.study_id == json_study['id'] + assert actual_study.name == json_study["name"] + assert actual_study.service.study_id == json_study["id"] def test_import_study_fail_wrong_extension(self, tmp_path): - study_path = tmp_path.joinpath("test.rar") study_path.touch() new_path = Path("/new/path/test") @@ -785,13 +784,9 @@ def test_import_study_fail_wrong_extension(self, tmp_path): base_url = "https://antares.com/api/v1" url_import = f"{base_url}/studies/_import" with requests_mock.Mocker() as mocker: - mocker.get(url_import, status_code=404) - with pytest.raises( - Exception, - match=re.escape("File doesn't have the right extensions (.zip/.7z): .rar") - ): + with pytest.raises(Exception, match=re.escape("File doesn't have the right extensions (.zip/.7z): .rar")): import_study_api(self.api, study_path, new_path) def test_import_study_fail_api_error(self, tmp_path): @@ -807,7 +802,6 @@ def test_import_study_fail_api_error(self, tmp_path): mocker.post(url_import, json=self.study_id) mocker.get(url_read_study, json={"description": self.antares_web_description_msg}, status_code=404) with pytest.raises( - StudyImportError, - match=f"Could not import the study test.zip : {self.antares_web_description_msg}" + StudyImportError, match=f"Could not import the study test.zip : {self.antares_web_description_msg}" ): - import_study_api(self.api, study_path, new_path) \ No newline at end of file + import_study_api(self.api, study_path, new_path) From 19126369868490e9c42489e9cd6b86259e53c33b Mon Sep 17 00:00:00 2001 From: wahadameh Date: Mon, 3 Feb 2025 17:02:52 +0100 Subject: [PATCH 5/9] feat(api): wip integration_tests --- tests/integration/test_web_client.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_web_client.py b/tests/integration/test_web_client.py index 2d6b3eba..b8d71db1 100644 --- a/tests/integration/test_web_client.py +++ b/tests/integration/test_web_client.py @@ -9,6 +9,9 @@ # SPDX-License-Identifier: MPL-2.0 # # This file is part of the Antares project. +import shutil +import zipfile + import pytest from pathlib import Path, PurePath @@ -40,7 +43,7 @@ from antares.craft.model.settings.study_settings import PlaylistParameters, StudySettings from antares.craft.model.simulation import AntaresSimulationParameters, Job, JobStatus from antares.craft.model.st_storage import STStorageGroup, STStorageMatrixName, STStorageProperties -from antares.craft.model.study import create_study_api, create_variant_api, read_study_api +from antares.craft.model.study import create_study_api, create_variant_api, read_study_api, import_study_api from antares.craft.model.thermal import ThermalClusterGroup, ThermalClusterProperties from tests.integration.antares_web_desktop import AntaresWebDesktop @@ -56,7 +59,7 @@ def antares_web() -> AntaresWebDesktop: # todo add integration tests for matrices class TestWebClient: - def test_creation_lifecycle(self, antares_web: AntaresWebDesktop): + def test_creation_lifecycle(self, antares_web: AntaresWebDesktop, tmp_path): api_config = APIconf(api_host=antares_web.url, token="", verify=False) study = create_study_api("antares-craft-test", "880", api_config) @@ -92,6 +95,17 @@ def test_creation_lifecycle(self, antares_web: AntaresWebDesktop): area_fr.create_wind(ts_matrix) assert area_fr.get_wind_matrix().equals(ts_matrix) + # testing import study + test_path = Path(antares_web.desktop_path.joinpath("internal_studies").joinpath(study.service.study_id)) + copy_dir = tmp_path / test_path.name + + tmp_path_zip = tmp_path / f"{copy_dir.name}" + shutil.copytree(test_path, copy_dir) + + zip_study = Path(shutil.make_archive(str(tmp_path_zip), "zip", copy_dir)) + + print(tmp_path_zip.exists()) + study = import_study_api(api_config, zip_study, None) # tests area creation with ui values area_ui = AreaUi(x=100, color_rgb=[255, 0, 0]) area_name = "BE?" From 49c45c3bd993702869160aeef3647f5ddb8e135f Mon Sep 17 00:00:00 2001 From: wahadameh Date: Tue, 4 Feb 2025 10:32:20 +0100 Subject: [PATCH 6/9] feat(api): working on import_study_api integration tests --- tests/integration/test_web_client.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/tests/integration/test_web_client.py b/tests/integration/test_web_client.py index b8d71db1..19dfdc24 100644 --- a/tests/integration/test_web_client.py +++ b/tests/integration/test_web_client.py @@ -9,11 +9,10 @@ # SPDX-License-Identifier: MPL-2.0 # # This file is part of the Antares project. -import shutil -import zipfile - import pytest +import shutil + from pathlib import Path, PurePath import numpy as np @@ -43,7 +42,7 @@ from antares.craft.model.settings.study_settings import PlaylistParameters, StudySettings from antares.craft.model.simulation import AntaresSimulationParameters, Job, JobStatus from antares.craft.model.st_storage import STStorageGroup, STStorageMatrixName, STStorageProperties -from antares.craft.model.study import create_study_api, create_variant_api, read_study_api, import_study_api +from antares.craft.model.study import create_study_api, create_variant_api, import_study_api, read_study_api from antares.craft.model.thermal import ThermalClusterGroup, ThermalClusterProperties from tests.integration.antares_web_desktop import AntaresWebDesktop @@ -104,8 +103,17 @@ def test_creation_lifecycle(self, antares_web: AntaresWebDesktop, tmp_path): zip_study = Path(shutil.make_archive(str(tmp_path_zip), "zip", copy_dir)) - print(tmp_path_zip.exists()) - study = import_study_api(api_config, zip_study, None) + # importing without moving the study + imported_study = import_study_api(api_config, zip_study, None) + + assert imported_study.path == study.path + + # importing with moving the study + path_test = Path("/new/test/studies") + imported_study = import_study_api(api_config, zip_study, path_test) + + assert imported_study.path == path_test / f"{imported_study.service.study_id}" + # tests area creation with ui values area_ui = AreaUi(x=100, color_rgb=[255, 0, 0]) area_name = "BE?" From 5f796414997f2c48547764380448aa787e422e96 Mon Sep 17 00:00:00 2001 From: wahadameh Date: Tue, 4 Feb 2025 11:44:17 +0100 Subject: [PATCH 7/9] feat(api): correcting minor issues --- src/antares/craft/model/study.py | 30 ++++++------- .../services/api_services/test_study_api.py | 9 +--- tests/integration/test_web_client.py | 42 ++++++++++--------- 3 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/antares/craft/model/study.py b/src/antares/craft/model/study.py index fc7ee135..e7ba41d3 100644 --- a/src/antares/craft/model/study.py +++ b/src/antares/craft/model/study.py @@ -104,21 +104,21 @@ def has_valid_extension(path: Path) -> bool: wrapper = RequestWrapper(session) base_url = f"{api_config.get_host()}/api/v1" - if has_valid_extension(study_path): - try: - files = {"study": io.BytesIO(study_path.read_bytes())} - url = f"{base_url}/studies/_import" - study_id = wrapper.post(url, files=files).json() - - study = read_study_api(api_config, study_id) - if destination_path is not None: - study.move(destination_path) - - return study - except APIError as e: - raise StudyImportError(study_path.name, e.message) from e - else: - raise Exception(f"File doesn't have the right extensions (.zip/.7z): {study_path.suffix}") + if not has_valid_extension(study_path): + raise StudyImportError(study_path.name, f"File doesn't have the right extensions (.zip/.7z): {study_path.suffix}") + + try: + files = {"study": io.BytesIO(study_path.read_bytes())} + url = f"{base_url}/studies/_import" + study_id = wrapper.post(url, files=files).json() + + study = read_study_api(api_config, study_id) + if destination_path is not None: + study.move(destination_path) + + return study + except APIError as e: + raise StudyImportError(study_path.name, e.message) from e def create_study_local( diff --git a/tests/antares/services/api_services/test_study_api.py b/tests/antares/services/api_services/test_study_api.py index a6b924b1..d8b0083a 100644 --- a/tests/antares/services/api_services/test_study_api.py +++ b/tests/antares/services/api_services/test_study_api.py @@ -781,13 +781,8 @@ def test_import_study_fail_wrong_extension(self, tmp_path): study_path.touch() new_path = Path("/new/path/test") - base_url = "https://antares.com/api/v1" - url_import = f"{base_url}/studies/_import" - with requests_mock.Mocker() as mocker: - mocker.get(url_import, status_code=404) - - with pytest.raises(Exception, match=re.escape("File doesn't have the right extensions (.zip/.7z): .rar")): - import_study_api(self.api, study_path, new_path) + with pytest.raises(Exception, match=re.escape("File doesn't have the right extensions (.zip/.7z): .rar")): + import_study_api(self.api, study_path, new_path) def test_import_study_fail_api_error(self, tmp_path): study_path = tmp_path.joinpath("test.zip") diff --git a/tests/integration/test_web_client.py b/tests/integration/test_web_client.py index 19dfdc24..48530b31 100644 --- a/tests/integration/test_web_client.py +++ b/tests/integration/test_web_client.py @@ -94,26 +94,6 @@ def test_creation_lifecycle(self, antares_web: AntaresWebDesktop, tmp_path): area_fr.create_wind(ts_matrix) assert area_fr.get_wind_matrix().equals(ts_matrix) - # testing import study - test_path = Path(antares_web.desktop_path.joinpath("internal_studies").joinpath(study.service.study_id)) - copy_dir = tmp_path / test_path.name - - tmp_path_zip = tmp_path / f"{copy_dir.name}" - shutil.copytree(test_path, copy_dir) - - zip_study = Path(shutil.make_archive(str(tmp_path_zip), "zip", copy_dir)) - - # importing without moving the study - imported_study = import_study_api(api_config, zip_study, None) - - assert imported_study.path == study.path - - # importing with moving the study - path_test = Path("/new/test/studies") - imported_study = import_study_api(api_config, zip_study, path_test) - - assert imported_study.path == path_test / f"{imported_study.service.study_id}" - # tests area creation with ui values area_ui = AreaUi(x=100, color_rgb=[255, 0, 0]) area_name = "BE?" @@ -680,3 +660,25 @@ def test_creation_lifecycle(self, antares_web: AntaresWebDesktop, tmp_path): moved_study = read_study_api(api_config, study.service.study_id) assert moved_study.path == study.path assert moved_study.name == study.name + + # testing import study + # creating a test path to not affect the internal studies created + test_path = Path(antares_web.desktop_path.joinpath("internal_studies").joinpath(study.service.study_id)) + copy_dir = tmp_path / test_path.name + + tmp_path_zip = tmp_path / copy_dir.name + shutil.copytree(test_path, copy_dir) + + zip_study = Path(shutil.make_archive(str(tmp_path_zip), "zip", copy_dir)) + + # importing without moving the study + imported_study = import_study_api(api_config, zip_study, None) + + assert imported_study.path == PurePath(".") + + # importing with moving the study + path_test = Path("/new/test/studies") + imported_study = import_study_api(api_config, zip_study, path_test) + + assert imported_study.path == path_test / f"{imported_study.service.study_id}" + assert list(imported_study.get_areas()) == list(study.get_areas()) From 6e68243bb4991e870b45651a2950023834742349 Mon Sep 17 00:00:00 2001 From: wahadameh Date: Tue, 4 Feb 2025 11:45:45 +0100 Subject: [PATCH 8/9] feat(api): correcting minor issues --- src/antares/craft/model/study.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/antares/craft/model/study.py b/src/antares/craft/model/study.py index e7ba41d3..3aadde8f 100644 --- a/src/antares/craft/model/study.py +++ b/src/antares/craft/model/study.py @@ -105,7 +105,9 @@ def has_valid_extension(path: Path) -> bool: base_url = f"{api_config.get_host()}/api/v1" if not has_valid_extension(study_path): - raise StudyImportError(study_path.name, f"File doesn't have the right extensions (.zip/.7z): {study_path.suffix}") + raise StudyImportError( + study_path.name, f"File doesn't have the right extensions (.zip/.7z): {study_path.suffix}" + ) try: files = {"study": io.BytesIO(study_path.read_bytes())} From ac04e93606566cfb4ac1c41e62e0842c7558a0ec Mon Sep 17 00:00:00 2001 From: wahadameh Date: Tue, 4 Feb 2025 12:55:53 +0100 Subject: [PATCH 9/9] feat(api): correcting minor issues --- tests/antares/services/api_services/test_study_api.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/tests/antares/services/api_services/test_study_api.py b/tests/antares/services/api_services/test_study_api.py index d8b0083a..8cf9fba1 100644 --- a/tests/antares/services/api_services/test_study_api.py +++ b/tests/antares/services/api_services/test_study_api.py @@ -723,15 +723,6 @@ def test_import_study_success(self, tmp_path): "folder": None, } - json_ui = { - "zone": { - "ui": {"x": 0, "y": 0, "color_r": 230, "color_g": 108, "color_b": 44, "layers": "0"}, - "layerX": {"0": 0}, - "layerY": {"0": 0}, - "layerColor": {"0": "230, 108, 44"}, - } - } - study_path = tmp_path.joinpath("test.zip") study_path.touch() new_path = Path("/new/path/test") @@ -756,7 +747,7 @@ def test_import_study_success(self, tmp_path): mocker.get(url, json=json_study) mocker.get(config_urls, json={}) - mocker.get(area_url, json=json_ui) + mocker.get(area_url, json={}) mocker.get(area_props_url, json={}) mocker.get(renewable_url, json=[]) mocker.get(thermal_url, json=[])