Skip to content

Commit

Permalink
Merge branch 'dev' into feat/explicit-override
Browse files Browse the repository at this point in the history
  • Loading branch information
sylvlecl authored Jan 2, 2025
2 parents 80e9f03 + c68cd50 commit e9c67fb
Show file tree
Hide file tree
Showing 23 changed files with 328 additions and 156 deletions.
4 changes: 2 additions & 2 deletions antarest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@

# Standard project metadata

__version__ = "2.18.2"
__version__ = "2.18.3"
__author__ = "RTE, Antares Web Team"
__date__ = "2024-12-11"
__date__ = "2024-12-17"
# noinspection SpellCheckingInspection
__credits__ = "(c) Réseau de Transport de l’Électricité (RTE)"

Expand Down
44 changes: 24 additions & 20 deletions antarest/study/business/xpansion_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def from_config(cls, config_obj: JSON) -> "GetXpansionSettings":
try:
return cls(**config_obj)
except ValidationError:
return cls.construct(**config_obj)
return cls.model_construct(**config_obj)


@all_optional_model
Expand Down Expand Up @@ -270,11 +270,6 @@ def __init__(self) -> None:
super().__init__(http.HTTPStatus.BAD_REQUEST)


class WrongTypeFormat(HTTPException):
def __init__(self, message: str) -> None:
super().__init__(http.HTTPStatus.BAD_REQUEST, message)


class WrongLinkFormatError(HTTPException):
def __init__(self, message: str) -> None:
super().__init__(http.HTTPStatus.BAD_REQUEST, message)
Expand All @@ -295,11 +290,6 @@ def __init__(self, message: str) -> None:
super().__init__(http.HTTPStatus.NOT_FOUND, message)


class ConstraintsNotFoundError(HTTPException):
def __init__(self, message: str) -> None:
super().__init__(http.HTTPStatus.NOT_FOUND, message)


class FileCurrentlyUsedInSettings(HTTPException):
def __init__(self, message: str) -> None:
super().__init__(http.HTTPStatus.CONFLICT, message)
Expand Down Expand Up @@ -337,7 +327,10 @@ def create_xpansion_configuration(self, study: Study, zipped_config: t.Optional[

xpansion_settings = XpansionSettings()
settings_obj = xpansion_settings.model_dump(
mode="json", by_alias=True, exclude_none=True, exclude={"sensitivity_config"}
mode="json",
by_alias=True,
exclude_none=True,
exclude={"sensitivity_config", "yearly_weights", "additional_constraints"},
)
if xpansion_settings.sensitivity_config:
sensitivity_obj = xpansion_settings.sensitivity_config.model_dump(
Expand Down Expand Up @@ -389,22 +382,33 @@ def update_xpansion_settings(

file_study = self.study_storage_service.get_storage(study).get_raw(study)

# Specific handling of the additional constraints file:
# - If the file name is `None`, it means that the user does not want to select an additional constraints file.
# - If the file name is empty, it means that the user wants to deselect the additional constraints file,
# but he does not want to delete it from the expansion configuration folder.
# - If the file name is not empty, it means that the user wants to select an additional constraints file.
# Specific handling for yearly_weights and additional_constraints:
# - If the attributes are given, it means that the user wants to select a file.
# It is therefore necessary to check that the file exists.
constraints_file = new_xpansion_settings.additional_constraints
if constraints_file:
# - Else, it means the user want to deselect the additional constraints file,
# but he does not want to delete it from the expansion configuration folder.
excludes = {"sensitivity_config"}
if constraints_file := new_xpansion_settings.additional_constraints:
try:
constraints_url = ["user", "expansion", "constraints", constraints_file]
file_study.tree.get(constraints_url)
except ChildNotFoundError:
msg = f"Additional constraints file '{constraints_file}' does not exist"
raise XpansionFileNotFoundError(msg) from None
else:
excludes.add("additional_constraints")

if weights_file := new_xpansion_settings.yearly_weights:
try:
weights_url = ["user", "expansion", "weights", weights_file]
file_study.tree.get(weights_url)
except ChildNotFoundError:
msg = f"Additional weights file '{weights_file}' does not exist"
raise XpansionFileNotFoundError(msg) from None
else:
excludes.add("yearly_weights")

config_obj = updated_settings.model_dump(mode="json", by_alias=True, exclude={"sensitivity_config"})
config_obj = updated_settings.model_dump(mode="json", by_alias=True, exclude=excludes)
file_study.tree.save(config_obj, ["user", "expansion", "settings"])

if new_xpansion_settings.sensitivity_config:
Expand Down
12 changes: 12 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
Antares Web Changelog
=====================

v2.18.3 (2024-12-17)
--------------------

## What's Changed

### Bug Fixes

* **ui-results**: resolve data misalignment in matrix column filtering [`2269`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2269)

**Full Changelog**: https://github.com/AntaresSimulatorTeam/AntaREST/compare/v2.18.2...v2.18.3


v2.18.2 (2024-12-11)
--------------------

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["setuptools"]

[project]
name = "AntaREST"
version = "2.18.2"
version = "2.18.3"
authors = [{name="RTE, Antares Web Team", email="[email protected]" }]
description="Antares Server"
readme = {file = "README.md", 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.11
sonar.javascript.lcov.reportPaths=webapp/coverage/lcov.info
sonar.projectVersion=2.18.2
sonar.projectVersion=2.18.3
sonar.coverage.exclusions=antarest/gui.py,antarest/main.py,antarest/singleton_services.py,antarest/worker/archive_worker_service.py,webapp/**/*,,antarest/fastapi_jwt_auth/**
61 changes: 57 additions & 4 deletions tests/storage/business/test_xpansion_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ def set_up_xpansion_manager(tmp_path: Path) -> t.Tuple[FileStudy, RawStudy, Xpan
"log_level": 0,
"separation_parameter": 0.5,
"batch_size": 96,
"yearly-weights": "",
"additional-constraints": "",
"timelimit": int(1e12),
},
"weights": {},
Expand Down Expand Up @@ -228,8 +226,6 @@ def test_update_xpansion_settings(tmp_path: Path) -> None:
"max_iteration": 123,
"uc_type": UcType.EXPANSION_FAST,
"master": Master.INTEGER,
"yearly-weights": "",
"additional-constraints": "",
"relaxed_optimality_gap": "1.2%", # percentage
"relative_gap": 1e-12,
"batch_size": 4,
Expand Down Expand Up @@ -463,6 +459,63 @@ def test_update_constraints(tmp_path: Path) -> None:
assert actual_settings.additional_constraints == ""


@pytest.mark.unit_test
def test_update_constraints_via_the_front(tmp_path: Path) -> None:
empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path)
empty_study.tree.save({"user": {"expansion": {"constraints": {"constraints.txt": b"0"}}}})

# asserts we can update a field without writing the field additional constraint in the file
front_settings = UpdateXpansionSettings(master="relaxed")
xpansion_manager.update_xpansion_settings(study, front_settings)
json_content = empty_study.tree.get(["user", "expansion", "settings"])
assert "additional-constraints" not in json_content
assert json_content["master"] == "relaxed"

# asserts the front-end can fill additional constraints
new_constraint = {"additional-constraints": "constraints.txt"}
front_settings = UpdateXpansionSettings.model_validate(new_constraint)
actual_settings = xpansion_manager.update_xpansion_settings(study, front_settings)
assert actual_settings.additional_constraints == "constraints.txt"
json_content = empty_study.tree.get(["user", "expansion", "settings"])
assert json_content["additional-constraints"] == "constraints.txt"

# asserts the front-end can unselect this constraint by not filling it
front_settings = UpdateXpansionSettings()
actual_settings = xpansion_manager.update_xpansion_settings(study, front_settings)
assert actual_settings.additional_constraints == ""
json_content = empty_study.tree.get(["user", "expansion", "settings"])
assert "additional-constraints" not in json_content


@pytest.mark.unit_test
def test_update_weights_via_the_front(tmp_path: Path) -> None:
# Same test as the one for constraints
empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path)
empty_study.tree.save({"user": {"expansion": {"weights": {"weights.txt": b"0"}}}})

# asserts we can update a field without writing the field yearly-weights in the file
front_settings = UpdateXpansionSettings(master="relaxed")
xpansion_manager.update_xpansion_settings(study, front_settings)
json_content = empty_study.tree.get(["user", "expansion", "settings"])
assert "yearly-weights" not in json_content
assert json_content["master"] == "relaxed"

# asserts the front-end can fill yearly weights
new_constraint = {"yearly-weights": "weights.txt"}
front_settings = UpdateXpansionSettings.model_validate(new_constraint)
actual_settings = xpansion_manager.update_xpansion_settings(study, front_settings)
assert actual_settings.yearly_weights == "weights.txt"
json_content = empty_study.tree.get(["user", "expansion", "settings"])
assert json_content["yearly-weights"] == "weights.txt"

# asserts the front-end can unselect this weight by not filling it
front_settings = UpdateXpansionSettings()
actual_settings = xpansion_manager.update_xpansion_settings(study, front_settings)
assert actual_settings.yearly_weights == ""
json_content = empty_study.tree.get(["user", "expansion", "settings"])
assert "yearly-weights" not in json_content


@pytest.mark.unit_test
def test_add_resources(tmp_path: Path) -> None:
empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path)
Expand Down
1 change: 1 addition & 0 deletions webapp/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
18.16.1
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.18.2",
"version": "2.18.3",
"private": true,
"type": "module",
"scripts": {
Expand Down
1 change: 1 addition & 0 deletions webapp/public/locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"global.date": "Date",
"global.general": "General",
"global.files": "Files",
"global.rawFile": "Raw file",
"global.none": "None",
"global.upload": "Upload",
"global.key": "Key",
Expand Down
1 change: 1 addition & 0 deletions webapp/public/locales/fr/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"global.date": "Date",
"global.general": "Général",
"global.files": "Fichiers",
"global.rawFile": "Fichier brut",
"global.none": "Aucun",
"global.upload": "Charger",
"global.key": "Clé",
Expand Down
31 changes: 10 additions & 21 deletions webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,54 +21,43 @@ import UsePromiseCond from "../../../../../common/utils/UsePromiseCond";
import type { DataCompProps } from "../utils";
import DownloadButton from "../../../../../common/buttons/DownloadButton";
import { downloadFile } from "../../../../../../utils/fileUtils";
import { useEffect, useState } from "react";
import { Filename, Flex, Menubar } from "./styles";
import UploadFileButton from "../../../../../common/buttons/UploadFileButton";
import { getRawFile } from "@/services/api/studies/raw";

function Json({ filePath, filename, studyId, canEdit }: DataCompProps) {
const [t] = useTranslation();
const { enqueueSnackbar } = useSnackbar();
const [currentJson, setCurrentJson] = useState<JSONEditorProps["json"]>();

const res = usePromiseWithSnackbarError(
const jsonRes = usePromiseWithSnackbarError(
() => getStudyData(studyId, filePath, -1),
{
errorMessage: t("studies.error.retrieveData"),
deps: [studyId, filePath],
},
);

useEffect(() => {
setCurrentJson(res.data);
}, [res.data]);

////////////////////////////////////////////////////////////////
// Event Handlers
////////////////////////////////////////////////////////////////

const handleDownload = async () => {
const file = await getRawFile({ studyId, path: filePath });
downloadFile(file, file.name);
};

const handleSave: JSONEditorProps["onSave"] = (json) => {
return editStudy(json, studyId, filePath);
};

const handleSaveSuccessful: JSONEditorProps["onSaveSuccessful"] = (json) => {
setCurrentJson(json);

const handleSaveSuccessful: JSONEditorProps["onSaveSuccessful"] = () => {
enqueueSnackbar(t("studies.success.saveData"), {
variant: "success",
});
};

const handleDownload = () => {
if (currentJson !== undefined) {
downloadFile(
JSON.stringify(currentJson, null, 2),
filename.endsWith(".json") ? filename : `${filename}.json`,
);
}
};

const handleUploadSuccessful = () => {
res.reload();
jsonRes.reload();
};

////////////////////////////////////////////////////////////////
Expand All @@ -77,7 +66,7 @@ function Json({ filePath, filename, studyId, canEdit }: DataCompProps) {

return (
<UsePromiseCond
response={res}
response={jsonRes}
ifFulfilled={(json) => (
<Flex>
<Menubar>
Expand Down
17 changes: 7 additions & 10 deletions webapp/src/components/App/Singlestudy/explore/Debug/Data/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { Filename, Flex, Menubar } from "./styles";
import UploadFileButton from "../../../../../common/buttons/UploadFileButton";
import EmptyView from "@/components/common/page/SimpleContent";
import GridOffIcon from "@mui/icons-material/GridOff";
import { getRawFile } from "@/services/api/studies/raw";

SyntaxHighlighter.registerLanguage("xml", xml);
SyntaxHighlighter.registerLanguage("plaintext", plaintext);
Expand Down Expand Up @@ -75,7 +76,7 @@ function Text({
const { t } = useTranslation();
const theme = useTheme();

const res = usePromiseWithSnackbarError(
const textRes = usePromiseWithSnackbarError(
() =>
getStudyData<string>(studyId, filePath).then((text) =>
parseContent(text, { filePath, fileType }),
Expand All @@ -90,17 +91,13 @@ function Text({
// Event Handlers
////////////////////////////////////////////////////////////////

const handleDownload = () => {
if (res.data) {
downloadFile(
res.data,
filename.endsWith(".txt") ? filename : `${filename}.txt`,
);
}
const handleDownload = async () => {
const file = await getRawFile({ studyId, path: filePath });
downloadFile(file, file.name);
};

const handleUploadSuccessful = () => {
res.reload();
textRes.reload();
};

////////////////////////////////////////////////////////////////
Expand All @@ -109,7 +106,7 @@ function Text({

return (
<UsePromiseCond
response={res}
response={textRes}
ifFulfilled={(text) => (
<Flex>
<Menubar>
Expand Down
Loading

0 comments on commit e9c67fb

Please sign in to comment.