Skip to content

Commit

Permalink
Merge branch 'dev' into feat/support-solver-v87
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinBelthle committed Mar 6, 2024
2 parents 2b4c313 + f7f082a commit 4feab25
Show file tree
Hide file tree
Showing 23 changed files with 281 additions and 122 deletions.
4 changes: 2 additions & 2 deletions antarest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

# Standard project metadata

__version__ = "2.16.5"
__version__ = "2.16.6"
__author__ = "RTE, Antares Web Team"
__date__ = "2024-02-29"
__date__ = "2024-03-04"
# noinspection SpellCheckingInspection
__credits__ = "(c) Réseau de Transport de l’Électricité (RTE)"

Expand Down
8 changes: 8 additions & 0 deletions antarest/core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,14 @@ def __init__(self, *area_ids: str) -> None:
super().__init__(HTTPStatus.NOT_FOUND, msg)


class DuplicateAreaName(HTTPException):
"""Exception raised when trying to create an area with an already existing name."""

def __init__(self, area_name: str) -> None:
msg = f"Area '{area_name}' already exists and could not be created"
super().__init__(HTTPStatus.CONFLICT, msg)


class DistrictNotFound(HTTPException):
def __init__(self, *district_ids: str) -> None:
count = len(district_ids)
Expand Down
12 changes: 10 additions & 2 deletions antarest/study/business/area_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from pydantic import BaseModel

from antarest.core.exceptions import LayerNotAllowedToBeDeleted, LayerNotFound
from antarest.core.exceptions import DuplicateAreaName, LayerNotAllowedToBeDeleted, LayerNotFound
from antarest.study.business.utils import execute_or_add_commands
from antarest.study.model import Patch, PatchArea, PatchCluster, RawStudy, Study
from antarest.study.repository import StudyMetadataRepository
Expand Down Expand Up @@ -318,12 +318,20 @@ def remove_layer(self, study: RawStudy, layer_id: str) -> None:

def create_area(self, study: Study, area_creation_info: AreaCreationDTO) -> AreaInfoDTO:
file_study = self.storage_service.get_storage(study).get_raw(study)

# check if area already exists
area_id = transform_name_to_id(area_creation_info.name)
if area_id in set(file_study.config.areas):
raise DuplicateAreaName(area_creation_info.name)

# Create area and apply changes in the study
command = CreateArea(
area_name=area_creation_info.name,
command_context=self.storage_service.variant_study_service.command_factory.command_context,
)
execute_or_add_commands(study, file_study, [command], self.storage_service)
area_id = transform_name_to_id(area_creation_info.name)

# Update metadata
patch = self.patch_service.get(study)
patch.areas = patch.areas or {}
patch.areas[area_id] = area_creation_info.metadata or PatchArea()
Expand Down
34 changes: 15 additions & 19 deletions antarest/study/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
MatrixIndex,
PatchArea,
PatchCluster,
PatchStudy,
RawStudy,
Study,
StudyAdditionalData,
Expand Down Expand Up @@ -121,6 +120,7 @@
upgrade_study,
)
from antarest.study.storage.utils import assert_permission, get_start_date, is_managed, remove_from_cache
from antarest.study.storage.variantstudy.business.utils import transform_command_to_dto
from antarest.study.storage.variantstudy.model.command.icommand import ICommand
from antarest.study.storage.variantstudy.model.command.replace_matrix import ReplaceMatrix
from antarest.study.storage.variantstudy.model.command.update_comments import UpdateComments
Expand Down Expand Up @@ -395,17 +395,7 @@ def get_comments(self, study_id: str, params: RequestParameters) -> t.Union[str,
study = self.get_study(study_id)
assert_permission(params.user, study, StudyPermissionType.READ)

output: t.Union[str, JSON]
raw_study_service = self.storage_service.raw_study_service
variant_study_service = self.storage_service.variant_study_service
if isinstance(study, RawStudy):
output = raw_study_service.get(metadata=study, url="/settings/comments")
elif isinstance(study, VariantStudy):
patch = raw_study_service.patch_service.get(study)
patch_study = PatchStudy() if patch.study is None else patch.study
output = patch_study.comments or variant_study_service.get(metadata=study, url="/settings/comments")
else:
raise StudyTypeUnsupported(study.id, study.type)
output = self.storage_service.get_storage(study).get(metadata=study, url="/settings/comments")

with contextlib.suppress(AttributeError, UnicodeDecodeError):
output = output.decode("utf-8") # type: ignore
Expand Down Expand Up @@ -440,14 +430,20 @@ def edit_comments(
new=bytes(data.comments, "utf-8"),
params=params,
)
elif isinstance(study, VariantStudy):
patch = self.storage_service.raw_study_service.patch_service.get(study)
patch_study = patch.study or PatchStudy()
patch_study.comments = data.comments
patch.study = patch_study
self.storage_service.raw_study_service.patch_service.save(study, patch)
else:
raise StudyTypeUnsupported(study.id, study.type)
variant_study_service = self.storage_service.variant_study_service
command = [
UpdateRawFile(
target="settings/comments",
b64Data=base64.b64encode(data.comments.encode("utf-8")).decode("utf-8"),
command_context=variant_study_service.command_factory.command_context,
)
]
variant_study_service.append_commands(
study.id,
transform_command_to_dto(command, force_aggregate=True),
RequestParameters(user=params.user),
)

def get_studies_information(
self,
Expand Down
11 changes: 1 addition & 10 deletions antarest/study/storage/storage_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

from typing import Union

from antarest.core.exceptions import StudyTypeUnsupported
from antarest.study.common.studystorage import IStudyStorageService
from antarest.study.model import RawStudy, Study
from antarest.study.storage.rawstudy.raw_study_service import RawStudyService
Expand Down Expand Up @@ -49,13 +48,5 @@ def get_storage(self, study: Study) -> IStudyStorageService[Union[RawStudy, Vari
Returns:
The study storage service associated with the study type.
Raises:
StudyTypeUnsupported: If the study type is not supported by the available storage services.
"""
if isinstance(study, RawStudy):
return self.raw_study_service
elif isinstance(study, VariantStudy):
return self.variant_study_service
else:
raise StudyTypeUnsupported(study.id, study.type)
return self.raw_study_service if isinstance(study, RawStudy) else self.variant_study_service
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ class UpdateRawFile(ICommand):
target: str
b64Data: str

def __repr__(self) -> str:
cls = self.__class__.__name__
target = self.target
try:
data = base64.decodebytes(self.b64Data.encode("utf-8")).decode("utf-8")
return f"{cls}(target={target!r}, data={data!r})"
except (ValueError, TypeError):
return f"{cls}(target={target!r}, b64Data={self.b64Data!r})"

def _apply_config(self, study_data: FileStudyTreeConfig) -> Tuple[CommandOutput, Dict[str, Any]]:
return CommandOutput(status=True, message="ok"), {}

Expand Down
18 changes: 17 additions & 1 deletion docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
Antares Web Changelog
=====================

v2.16.6 (2024-03-04)
--------------------

### Features

* **ui-tasks:** add launcher metrics [`#1960`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1960)
* **ui-tasks:** auto refresh launcher metrics [`#1963`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1963)


### Bug Fixes

* **ui-results:** adjust date times for accurate frequency display [`#1960`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1960)
* **ui-common:** matrices display issues [`#1960`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1960)
* **ui-common:** download latest value of matrices [`#1962`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1962)


v2.16.5 (2024-02-29)
--------------------

Expand All @@ -18,7 +34,7 @@ v2.16.5 (2024-02-29)
* **ui-hydro:** disable stretch to fix display issue on some matrices [`#1945`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1945)
* **variants:** correct the generation of variant when a snapshot is removed [`#1947`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1947)
* **tags:** resolve issue with `study.additional_data.patch` attribute reading [`#1944`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1944)
* **study:** correct access to study `additional_data` (#1949) [`#1949`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1949)
* **study:** correct access to study `additional_data` [`#1949`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1949)
* **ui-tablemode:** create modal is frozen when submitting without column [`#1946`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1946)
* **ui-tablemode:** 'co2' column not working [`#1952`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1952)
* **ui:** add missing i18n dependency [`#1954`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1954)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

setup(
name="AntaREST",
version="2.16.5",
version="2.16.6",
description="Antares Server",
long_description=Path("README.md").read_text(encoding="utf-8"),
long_description_content_type="text/markdown",
Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ sonar.exclusions=antarest/gui.py,antarest/main.py
sonar.python.coverage.reportPaths=coverage.xml
sonar.python.version=3.8
sonar.javascript.lcov.reportPaths=webapp/coverage/lcov.info
sonar.projectVersion=2.16.5
sonar.projectVersion=2.16.6
sonar.coverage.exclusions=antarest/gui.py,antarest/main.py,antarest/singleton_services.py,antarest/worker/archive_worker_service.py,webapp/**/*
19 changes: 11 additions & 8 deletions tests/integration/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from antarest.core.model import PublicMode
from antarest.launcher.model import LauncherLoadDTO
from antarest.study.business.adequacy_patch_management import PriceTakingOrder
from antarest.study.business.area_management import AreaType, LayerInfoDTO
from antarest.study.business.area_management import LayerInfoDTO
from antarest.study.business.areas.properties_management import AdequacyPatchMode
from antarest.study.business.areas.renewable_management import TimeSeriesInterpretation
from antarest.study.business.general_management import Mode
Expand Down Expand Up @@ -420,31 +420,34 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id:
headers=admin_headers,
json={
"name": "area 1",
"type": AreaType.AREA.value,
"type": "AREA",
"metadata": {"country": "FR", "tags": ["a"]},
},
)
assert res.status_code == 200, res.json()

# Test area creation with duplicate name
res = client.post(
f"/v1/studies/{study_id}/areas",
headers=admin_headers,
json={
"name": "area 1",
"type": AreaType.AREA.value,
"name": "Area 1", # Same name but with different case
"type": "AREA",
"metadata": {"country": "FR"},
},
)
assert res.status_code == 500
assert res.status_code == 409, res.json()
assert res.json() == {
"description": "Area 'area 1' already exists and could not be created",
"exception": "CommandApplicationError",
"description": "Area 'Area 1' already exists and could not be created",
"exception": "DuplicateAreaName",
}

client.post(
f"/v1/studies/{study_id}/areas",
headers=admin_headers,
json={
"name": "area 2",
"type": AreaType.AREA.value,
"type": "AREA",
"metadata": {"country": "DE"},
},
)
Expand Down
72 changes: 62 additions & 10 deletions tests/integration/variant_blueprint/test_variant_manager.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,45 @@
import logging
import typing as t

import pytest
from starlette.testclient import TestClient

from antarest.core.tasks.model import TaskDTO, TaskStatus


def test_variant_manager(client: TestClient, admin_access_token: str, study_id: str, caplog) -> None:
@pytest.fixture(name="base_study_id")
def base_study_id_fixture(client: TestClient, admin_access_token: str, caplog: t.Any) -> str:
"""Create a base study and return its ID."""
admin_headers = {"Authorization": f"Bearer {admin_access_token}"}
with caplog.at_level(level=logging.WARNING):
admin_headers = {"Authorization": f"Bearer {admin_access_token}"}

base_study_res = client.post("/v1/studies?name=foo", headers=admin_headers)
res = client.post("/v1/studies?name=Base1", headers=admin_headers)
return t.cast(str, res.json())


@pytest.fixture(name="variant_id")
def variant_id_fixture(
client: TestClient,
admin_access_token: str,
base_study_id: str,
caplog: t.Any,
) -> str:
"""Create a variant and return its ID."""
admin_headers = {"Authorization": f"Bearer {admin_access_token}"}
with caplog.at_level(level=logging.WARNING):
res = client.post(f"/v1/studies/{base_study_id}/variants?name=Variant1", headers=admin_headers)
return t.cast(str, res.json())

base_study_id = base_study_res.json()

res = client.post(f"/v1/studies/{base_study_id}/variants?name=foo", headers=admin_headers)
variant_id = res.json()
def test_variant_manager(
client: TestClient,
admin_access_token: str,
base_study_id: str,
variant_id: str,
caplog: t.Any,
) -> None:
admin_headers = {"Authorization": f"Bearer {admin_access_token}"}

with caplog.at_level(level=logging.WARNING):
client.post(f"/v1/launcher/run/{variant_id}", headers=admin_headers)

res = client.get(f"v1/studies/{variant_id}/synthesis", headers=admin_headers)
Expand All @@ -26,9 +50,9 @@ def test_variant_manager(client: TestClient, admin_access_token: str, study_id:
client.post(f"/v1/studies/{variant_id}/variants?name=baz", headers=admin_headers)
res = client.get(f"/v1/studies/{base_study_id}/variants", headers=admin_headers)
children = res.json()
assert children["node"]["name"] == "foo"
assert children["node"]["name"] == "Base1"
assert len(children["children"]) == 1
assert children["children"][0]["node"]["name"] == "foo"
assert children["children"][0]["node"]["name"] == "Variant1"
assert len(children["children"][0]["children"]) == 2
assert children["children"][0]["children"][0]["node"]["name"] == "bar"
assert children["children"][0]["children"][1]["node"]["name"] == "baz"
Expand Down Expand Up @@ -169,7 +193,7 @@ def test_variant_manager(client: TestClient, admin_access_token: str, study_id:
res = client.post(f"/v1/studies/{variant_id}/freeze?name=bar", headers=admin_headers)
assert res.status_code == 500

new_study_id = "newid"
new_study_id = "new_id"

res = client.get(f"/v1/studies/{new_study_id}", headers=admin_headers)
assert res.status_code == 404
Expand All @@ -186,3 +210,31 @@ def test_variant_manager(client: TestClient, admin_access_token: str, study_id:

res = client.get(f"/v1/studies/{variant_id}", headers=admin_headers)
assert res.status_code == 404


def test_comments(client: TestClient, admin_access_token: str, variant_id: str) -> None:
admin_headers = {"Authorization": f"Bearer {admin_access_token}"}

# Put comments
comment = "updated comment"
res = client.put(f"/v1/studies/{variant_id}/comments", json={"comments": comment}, headers=admin_headers)
assert res.status_code == 204

# Asserts comments are updated
res = client.get(f"/v1/studies/{variant_id}/comments", headers=admin_headers)
assert res.json() == comment

# Generates the study
res = client.put(f"/v1/studies/{variant_id}/generate?denormalize=false&from_scratch=true", headers=admin_headers)
task_id = res.json()
# Wait for task completion
res = client.get(f"/v1/tasks/{task_id}", headers=admin_headers, params={"wait_for_completion": True})
assert res.status_code == 200
task_result = TaskDTO.parse_obj(res.json())
assert task_result.status == TaskStatus.COMPLETED
assert task_result.result is not None
assert task_result.result.success

# Asserts comments did not disappear
res = client.get(f"/v1/studies/{variant_id}/comments", headers=admin_headers)
assert res.json() == comment
4 changes: 2 additions & 2 deletions webapp/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion webapp/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "antares-web",
"version": "2.16.5",
"version": "2.16.6",
"private": true,
"type": "module",
"scripts": {
Expand Down
4 changes: 3 additions & 1 deletion webapp/public/locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,9 @@
"study.postProcessing": "Post processing",
"study.timeLimit": "Time limit (h)",
"study.nbCpu": "Number of cores",
"study.clusterLoad": "Cluster load",
"study.allocatedCpuRate": "CPU usage",
"study.clusterLoadRate": "Cluster load",
"study.nbQueuedJobs": "Pending jobs",
"study.synthesis": "Synthesis",
"study.level": "Level",
"study.years": "Years",
Expand Down
Loading

0 comments on commit 4feab25

Please sign in to comment.