Skip to content

Commit

Permalink
v2.17.1
Browse files Browse the repository at this point in the history
Merge pull request #2057 from AntaresSimulatorTeam/release/v2.17.1
  • Loading branch information
skamril authored Jun 10, 2024
2 parents d9bac0e + 248e1df commit 55a245b
Show file tree
Hide file tree
Showing 154 changed files with 14,578 additions and 12,986 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ jobs:
auto-changelog -l false --hide-empty-releases
mv CHANGELOG.md dist/package/CHANGELOG.md
- name: 📦 Archive Antares Desktop + Worker for Windows
- name: 📦 Archive Antares Desktop for Windows
if: matrix.os == 'windows-latest'
run: 7z a AntaresWeb.zip *
working-directory: dist/package

- name: 📦 Archive Antares Desktop + Worker for Ubuntu
- name: 📦 Archive Antares Desktop for Ubuntu
# this is the only way to preserve file permission and symlinks
if: matrix.os == 'ubuntu-20.04'
run: zip -r --symlinks AntaresWeb.zip *
Expand Down
5 changes: 4 additions & 1 deletion AntaresWebLinux.spec
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# -*- mode: python ; coding: utf-8 -*-
from pathlib import Path
from PyInstaller.utils.hooks import collect_dynamic_libs

block_cipher = None

# We need to analyze all alembic files to be sure the migration phase works fine
migrations_dir = Path('alembic/versions')
migration_files = [str(f) for f in migrations_dir.iterdir() if f.is_file() and f.suffix == '.py']

binaries = [('./alembic.ini', './alembic.ini')] + collect_dynamic_libs('tables')

antares_web_server_a = Analysis(['antarest/gui.py', 'alembic/env.py'] + migration_files,
pathex=[],
binaries=[('./alembic.ini', './alembic.ini')],
binaries=binaries,
datas=[('./resources', './resources'), ('./alembic', './alembic')],
hiddenimports=[
'cmath',
Expand Down
5 changes: 4 additions & 1 deletion AntaresWebWin.spec
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# -*- mode: python ; coding: utf-8 -*-
from pathlib import Path
from PyInstaller.utils.hooks import collect_dynamic_libs

block_cipher = None

# We need to analyze all alembic files to be sure the migration phase works fine
migrations_dir = Path('alembic/versions')
migration_files = [str(f) for f in migrations_dir.iterdir() if f.is_file() and f.suffix == '.py']

binaries = [('./alembic.ini', './alembic.ini')] + collect_dynamic_libs('tables')

antares_web_server_a = Analysis(['antarest/gui.py', 'alembic/env.py'] + migration_files,
pathex=[],
binaries=[('./alembic.ini', './alembic.ini')],
binaries=binaries,
datas=[('./resources', './resources'), ('./alembic', './alembic')],
hiddenimports=[
'cmath',
Expand Down
45 changes: 0 additions & 45 deletions AntaresWebWorker.spec

This file was deleted.

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.17"
__version__ = "2.17.1"
__author__ = "RTE, Antares Web Team"
__date__ = "2024-05-15"
__date__ = "2024-06-10"
# noinspection SpellCheckingInspection
__credits__ = "(c) Réseau de Transport de l’Électricité (RTE)"

Expand Down
66 changes: 63 additions & 3 deletions antarest/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,48 @@ def __post_init__(self) -> None:
raise ValueError(msg)


@dataclass(frozen=True)
class TimeLimitConfig:
"""
The TimeLimitConfig class is designed to manage the configuration of the time limit for a job.
Attributes:
min: int: minimum allowed value for the time limit (in hours).
default: int: default value for the time limit (in hours).
max: int: maximum allowed value for the time limit (in hours).
"""

min: int = 1
default: int = 48
max: int = 48

def to_json(self) -> Dict[str, int]:
"""
Retrieves the time limit parameters, returning a dictionary containing the values "min"
(minimum allowed value), "defaultValue" (default value), and "max" (maximum allowed value)
Returns:
A dictionary: `{"min": min, "defaultValue": default, "max": max}`.
Because ReactJs Material UI expects "min", "defaultValue" and "max" keys.
"""
return {"min": self.min, "defaultValue": self.default, "max": self.max}

def __post_init__(self) -> None:
"""validation of CPU configuration"""
if 1 <= self.min <= self.default <= self.max:
return
msg = f"Invalid configuration: 1 <= {self.min=} <= {self.default=} <= {self.max=}"
raise ValueError(msg)


@dataclass(frozen=True)
class LocalConfig:
"""Sub config object dedicated to launcher module (local)"""

binaries: Dict[str, Path] = field(default_factory=dict)
enable_nb_cores_detection: bool = True
nb_cores: NbCoresConfig = NbCoresConfig()
time_limit: TimeLimitConfig = TimeLimitConfig()

@classmethod
def from_dict(cls, data: JSON) -> "LocalConfig":
Expand Down Expand Up @@ -251,7 +286,7 @@ class SlurmConfig:
key_password: str = ""
password: str = ""
default_wait_time: int = 0
default_time_limit: int = 0
time_limit: TimeLimitConfig = TimeLimitConfig()
default_json_db_name: str = ""
slurm_script_path: str = ""
partition: str = ""
Expand Down Expand Up @@ -279,6 +314,9 @@ def from_dict(cls, data: JSON) -> "SlurmConfig":
nb_cores["max"] = max(nb_cores["max"], nb_cores["default"])
if enable_nb_cores_detection:
nb_cores.update(cls._autodetect_nb_cores())
# In the configuration file, the default time limit is in seconds, so we convert it to hours
max_time_limit = data.get("default_time_limit", defaults.time_limit.max * 3600) // 3600
time_limit = TimeLimitConfig(min=1, default=max_time_limit, max=max_time_limit)
return cls(
local_workspace=Path(data.get("local_workspace", defaults.local_workspace)),
username=data.get("username", defaults.username),
Expand All @@ -288,7 +326,7 @@ def from_dict(cls, data: JSON) -> "SlurmConfig":
key_password=data.get("key_password", defaults.key_password),
password=data.get("password", defaults.password),
default_wait_time=data.get("default_wait_time", defaults.default_wait_time),
default_time_limit=data.get("default_time_limit", defaults.default_time_limit),
time_limit=time_limit,
default_json_db_name=data.get("default_json_db_name", defaults.default_json_db_name),
slurm_script_path=data.get("slurm_script_path", defaults.slurm_script_path),
partition=data.get("partition", defaults.partition),
Expand All @@ -308,7 +346,7 @@ def _autodetect_nb_cores(cls) -> Dict[str, int]:

class InvalidConfigurationError(Exception):
"""
Exception raised when an attempt is made to retrieve the number of cores
Exception raised when an attempt is made to retrieve a property
of a launcher that doesn't exist in the configuration.
"""

Expand Down Expand Up @@ -371,6 +409,28 @@ def get_nb_cores(self, launcher: str) -> "NbCoresConfig":
raise InvalidConfigurationError(launcher)
return launcher_config.nb_cores

def get_time_limit(self, launcher: str) -> TimeLimitConfig:
"""
Retrieve the time limit for a job of the given launcher: "local" or "slurm".
If "default" is specified, retrieve the configuration of the default launcher.
Args:
launcher: type of launcher "local", "slurm" or "default".
Returns:
Time limit for a job of the given launcher (in seconds).
Raises:
InvalidConfigurationError: Exception raised when an attempt is made to retrieve
a property of a launcher that doesn't exist in the configuration.
"""
config_map = {"local": self.local, "slurm": self.slurm}
config_map["default"] = config_map[self.default]
launcher_config = config_map.get(launcher)
if launcher_config is None:
raise InvalidConfigurationError(launcher)
return launcher_config.time_limit


@dataclass(frozen=True)
class LoggingConfig:
Expand Down
45 changes: 34 additions & 11 deletions antarest/core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,6 @@ def __str__(self) -> str:
return self.detail


class DuplicateSTStorageId(HTTPException):
"""Exception raised when trying to create a short-term storage with an already existing id."""

def __init__(self, study_id: str, area_id: str, st_storage_id: str) -> None:
detail = f"Short term storage '{st_storage_id}' already exists in area '{area_id}'"
super().__init__(HTTPStatus.CONFLICT, detail)

def __str__(self) -> str:
return self.detail


class ThermalClusterMatrixNotFound(MatrixNotFound):
"""Matrix of the thermal cluster is not found (404 Not Found)"""

Expand Down Expand Up @@ -325,6 +314,17 @@ def __init__(self, uuid: str, message: t.Optional[str] = None) -> None:
)


class StudyVariantUpgradeError(HTTPException):
def __init__(self, is_variant: bool) -> None:
if is_variant:
super().__init__(
HTTPStatus.EXPECTATION_FAILED,
"Upgrade not supported for variant study",
)
else:
super().__init__(HTTPStatus.EXPECTATION_FAILED, "Upgrade not supported for parent of variants")


class UnsupportedStudyVersion(HTTPException):
def __init__(self, version: str) -> None:
super().__init__(
Expand All @@ -346,6 +346,20 @@ def __init__(self, message: str) -> None:
super().__init__(HTTPStatus.UNPROCESSABLE_ENTITY, message)


class OutputNotFound(HTTPException):
"""
Exception raised when an output is not found in the study results directory.
"""

def __init__(self, output_id: str) -> None:
message = f"Output '{output_id}' not found"
super().__init__(HTTPStatus.NOT_FOUND, message)

def __str__(self) -> str:
"""Return a string representation of the exception."""
return self.detail


class BadZipBinary(HTTPException):
def __init__(self, message: str) -> None:
super().__init__(HTTPStatus.UNSUPPORTED_MEDIA_TYPE, message)
Expand All @@ -356,6 +370,15 @@ def __init__(self, message: str) -> None:
super().__init__(HTTPStatus.NOT_FOUND, message)


class FileTooLargeError(HTTPException):
def __init__(self, estimated_size: int, maximum_size: int) -> None:
message = (
f"Cannot aggregate output data."
f" The expected size: {estimated_size}Mo exceeds the max supported size: {maximum_size}"
)
super().__init__(HTTPStatus.REQUEST_ENTITY_TOO_LARGE, message)


class UrlNotMatchJsonDataError(HTTPException):
def __init__(self, message: str) -> None:
super().__init__(HTTPStatus.NOT_FOUND, message)
Expand Down
12 changes: 0 additions & 12 deletions antarest/core/utils/dict.py

This file was deleted.

Loading

0 comments on commit 55a245b

Please sign in to comment.